WAVEWATCH III  beta 0.0.1
w3profsmd.F90
Go to the documentation of this file.
1 #include "w3macros.h"
2 !/ ------------------------------------------------------------------- /
3 MODULE w3profsmd
4  !/
5  !/ +-----------------------------------+
6  !/ | WAVEWATCH III NOAA/NCEP |
7  !/ | Aron Roland |
8  !/ | Fabrice Ardhuin |
9  !/ | FORTRAN 90 |
10  !/ | Last update : 15-Apr-2020 |
11  !/ +-----------------------------------+
12  !/
13  !/ XX-Nov-2007 : Origination. ( version 3.10 )
14  !/ 03-Nov-2011 : Adding shoreline reflection ( version 4.04 )
15  !/ 03-Jun-2013 : Removed assign statements ( version 4.10 )
16  !/ 20-Jun-2013 : Update test output for time steps ( version 4.10 )
17  !/ 17-Oct-2013 : Removes boundary nodes from CFL ( version 4.12 )
18  !/ 15-Dec-2013 : Bug fix for implicit scheme ( version 4.16 )
19  !/ 18-Aug-2016 : Corrected boundary treatment ( version 4.16 )
20  !/ 15-Apr-2020 : Adds optional opt-out for CFL on BC ( version 7.08 )
21  !
22  ! 1. Purpose :
23  !
24  ! Propagation schemes for unstructured grids using fluctuation splitting
25  !
26  ! 2. Variables and types :
27  !
28  ! Name Type Scope Description
29  ! ----------------------------------------------------------------
30  ! ----------------------------------------------------------------
31  !
32  ! 3. Subroutines and functions :
33  !
34  ! Name Type Scope Description
35  ! ----------------------------------------------------------------
36  ! W3XYPUG Subr. Public Generic fluctuation splitting operations
37  ! W3XYPFSN2 Subr. Public advection with N scheme (Csik et al. 2002)
38  ! W3XYPFSPSI Subr. Public advection with FCT scheme
39  ! W3XYPFSFCT2 Subr. Public advection with FCT scheme
40  ! ----------------------------------------------------------------
41  !
42  ! 4. Subroutines and functions used :
43  !
44  ! Name Type Module Description
45  ! ----------------------------------------------------------------
46  ! ----------------------------------------------------------------
47  !
48  ! 5. Remarks :
49  ! For a detailed description of the schemes and their properties, see
50  ! Roland (2008), Ph.D. Thesis, T. U. Darmstadt.
51  !
52  ! 6. Switches :
53  !
54  ! 7. Source code :
55  !/
56  !/ ------------------------------------------------------------------- /
57  !/
58  PUBLIC
59  !/
60 CONTAINS
61  !/ ------------------------------------------------------------------- /
62  SUBROUTINE w3xypug ( ISP, FACX, FACY, DTG, VQ, VGX, VGY, LCALC )
63  !/
64  !/ +-----------------------------------+
65  !/ | WAVEWATCH III NOAA/NCEP |
66  !/ | Aron Roland |
67  !/ | FORTRAN 90 |
68  !/ | Last update : 10-Jan-2011 |
69  !/ +-----------------------------------+
70  !/
71  !/ 10-Jan-2008 : Origination. ( version 3.13 )
72  !/ 10-Jan-2011 : Addition of implicit scheme ( version 3.14.4 )
73  !/
74  ! 1. Purpose :
75  !
76  ! Propagation in physical space for a given spectral component.
77  ! Gives the choice of scheme on unstructured grid
78  !
79  ! 2. Method :
80  !
81  !
82  !
83  ! 3. Parameters :
84  !
85  ! Parameter list
86  ! ----------------------------------------------------------------
87  ! ISP Int. I Number of spectral bin (IK-1)*NTH+ITH
88  ! FACX/Y Real I Factor in propagation velocity.
89  ! ( 1 or 0 * DT / DX )
90  ! DTG Real I Total time step.
91  ! VQ R.A. I/O Field to propagate.
92  ! VGX/Y Real I Speed of grid.
93  ! ----------------------------------------------------------------
94  !
95  ! Local variables.
96  ! ----------------------------------------------------------------
97  ! VCFL0X R.A. Local courant numbers for absolute group vel.
98  ! using local X-grid step.
99  ! VCFL0Y R.A. Id. in Y.
100  ! ----------------------------------------------------------------
101  !
102  ! 4. Subroutines used :
103  !
104 
105  ! 5. Called by :
106  !
107  ! W3WAVE Wave model routine.
108  !
109  ! 6. Error messages :
110  !
111  ! None.
112  !
113  ! 7. Remarks :
114  ! make the interface between the WAVEWATCH and the WWM code.
115  !
116  ! 8. Structure :
117  !
118  !
119  ! 9. Switches :
120  !
121  ! !/S Enable subroutine tracing.
122  !
123  !
124  ! 10. Source code :
125  !/ ------------------------------------------------------------------- /
126  !/
127  !
128  USE constants
129  !
130  USE w3timemd, ONLY: dsec21
131  !
132  USE w3gdatmd, ONLY: nx, ny, nsea, mapsf, mapfs, dtcfl, clats, &
133  flcx, flcy, nk, nth, dth, xfr, &
134  ecos, esin, sig, pfmove,ien, &
135  ntri, trigp, ccon , &
138 
139  USE w3wdatmd, ONLY: time
140  USE w3odatmd, ONLY: tbpi0, tbpin, flbpi
141  USE w3adatmd, ONLY: cg, cx, cy, atrnx, atrny, itime, cflxymax, dw
142  USE w3idatmd, ONLY: flcur
143  ! USE W3ODATMD, ONLY: NDSE, NDST, FLBPI, NBI, TBPI0, TBPIN, &
144  ! ISBPI, BBPI0, BBPIN
145 #ifdef W3_S
146  USE w3servmd, ONLY: strace
147 #endif
148 
149  IMPLICIT NONE
150  !/ ------------------------------------------------------------------- /
151  !/ Parameter list
152  !/
153  INTEGER, INTENT(IN) :: ISP
154  REAL, INTENT(IN) :: FACX, FACY, DTG, VGX, VGY
155  REAL, INTENT(INOUT) :: VQ(1-NY:NY*(NX+2))
156  LOGICAL, INTENT(IN) :: LCALC
157  !/
158  !/ ------------------------------------------------------------------- /
159  !/ Local parameters
160  !/
161  INTEGER :: ITH, IK, ISEA, IXY
162  INTEGER :: IX
163 #ifdef W3_S
164  INTEGER, SAVE :: IENT = 0
165 #endif
166  REAL :: CCOS, CSIN, CCURX, CCURY
167  REAL :: C(NX,2)
168  REAL :: RD1, RD2
169  !/
170  !/ Automatic work arrays
171  !/
172  REAL :: VLCFLX((NX+1)*NY), VLCFLY(NX*NY)
173  DOUBLE PRECISION :: AC(NX)
174  !/ ------------------------------------------------------------------- /
175  !
176  ! 1. Preparations --------------------------------------------------- *
177  ! 1.a Set constants
178  !
179 
180 #ifdef W3_S
181  CALL strace (ient, 'W3XYPUG')
182 #endif
183  ith = 1 + mod(isp-1,nth)
184  ik = 1 + (isp-1)/nth
185 
186  ccos = facx * ecos(ith)
187  csin = facy * esin(ith)
188  ccurx = facx
189  ccury = facy
190  !
191  ! 1.b Initialize arrays
192  !
193  vlcflx = 0.
194  vlcfly = 0.
195  !
196  ! 1.c Set depth
197  !
198  CALL setdepth
199  !
200  !
201  ! 2. Calculate velocities ---------------- *
202  !
203  DO isea = 1, nsea
204  ixy = mapsf(isea,3)
205  vq(ixy) = vq(ixy) / cg(ik,isea) * clats(isea)
206  vlcflx(ixy) = ccos * cg(ik,isea) / clats(isea)
207  vlcfly(ixy) = csin * cg(ik,isea)
208 #ifdef W3_MGP
209  vlcflx(ixy) = vlcflx(ixy) - ccurx*vgx/clats(isea)
210  vlcfly(ixy) = vlcfly(ixy) - ccury*vgy
211 #endif
212  END DO
213 
214  IF ( flcur ) THEN
215  DO isea=1, nsea
216  ixy = mapsf(isea,3)
217  !
218  ! Currents are not included on coastal boundaries (IOBP(IXY).EQ.0)
219  !
220  IF (iobp(ixy) .EQ. 1) THEN
221  vlcflx(ixy) = vlcflx(ixy) + ccurx*cx(isea)/clats(isea)
222  vlcfly(ixy) = vlcfly(ixy) + ccury*cy(isea)
223  END IF
224  END DO
225  END IF
226 
227  !
228  ! 3. initialize fluctuation splitting arrays ( to fit with WWM notations)
229  !
230  ac(1:nx) = dble(vq(1:nx)) * iobdp(1:nx)
231  c(1:nx,1) = vlcflx(1:nx) * iobdp(1:nx)
232  c(1:nx,2) = vlcfly(1:nx) * iobdp(1:nx)
233 
234  !
235  ! 4. Prepares boundary update
236  !
237  IF ( flbpi ) THEN
238  rd1 = dsec21( tbpi0, time )
239  rd2 = dsec21( tbpi0, tbpin )
240  ELSE
241  rd1=1.
242  rd2=0.
243  END IF
244  !
245  ! 4. propagate using the selected scheme
246  !
247  IF (fsn) THEN
248  CALL w3xypfsn2 (isp, c, lcalc, rd1, rd2, dtg, ac)
249  ELSE IF (fspsi) THEN
250  CALL w3xypfspsi2 (isp, c, lcalc, rd1, rd2, dtg, ac)
251  ELSE IF (fsfct) THEN
252  CALL w3xypfsfct2 (isp, c, lcalc, rd1, rd2, dtg, ac)
253  ELSE IF (fsnimp) THEN
254  CALL w3xypfsnimp(isp, c, lcalc, rd1, rd2, dtg, ac)
255  ENDIF
256  !
257  DO ix=1,nx
258  isea=mapfs(1,ix)
259  vq(ix)=real(ac(ix))
260  ENDDO
261 
262  ! 6. Store results in VQ in proper format --------------------------- *
263  !
264  DO isea=1, nsea
265  ixy = mapsf(isea,3)
266  vq(ixy) = max( 0. , cg(ik,isea)/clats(isea)*vq(ixy) )
267  END DO
268  END SUBROUTINE w3xypug
269  !/ ------------------------------------------------------------------- /
270  SUBROUTINE w3cflug ( ISEA, NKCFL, FACX, FACY, DT, MAPFS, CFLXYMAX, &
271  VGX, VGY )
272  !/
273  !/ +-----------------------------------+
274  !/ | WAVEWATCH III NOAA/NCEP |
275  !/ | Fabrice Ardhuin |
276  !/ | FORTRAN 90 |
277  !/ | Last update : 20-Jun-2013 |
278  !/ +-----------------------------------+
279  !/
280  !/ 01-Mar-2011 : Origination. ( version 3.14 )
281  !/ 20-Jun-2013 : Computes only up to NKCFL for tests ( version 4.10 )
282  !/ 1-Jun-2017 : Rewrite routine for performance ( version 5.xx )
283  !/
284  ! 1. Purpose :
285  !
286  ! Computes the max CFL number for output purposes
287  !
288  ! 2. Method :
289  !
290  !
291  !
292  ! 3. Parameters :
293  !
294  ! Parameter list
295  ! ----------------------------------------------------------------
296  ! ISEA Int. I Index of sea point
297  ! NKCFL Int. I Maximum frequency index
298  ! FACX/Y Real I Factor in propagation velocity.
299  ! ( 1 or 0 * DT / DX )
300  ! DT Real I Time step.
301  ! MAPFS I.A. I Storage map.
302  ! CFLXYMAX Real Maxmimum CFL for spatial advection
303  ! VGX/Y Real I Speed of grid.
304  ! ----------------------------------------------------------------
305  !
306  ! Local variables.
307  ! ----------------------------------------------------------------
308  ! VCFL0X R.A. Local courant numbers for absolute group vel.
309  ! using local X-grid step.
310  ! VCFL0Y R.A. Id. in Y.
311  ! ----------------------------------------------------------------
312  !
313  ! 4. Subroutines used :
314  !
315 
316  ! 5. Called by :
317  !
318  ! W3WAVE Wave model routine.
319  !
320  ! 6. Error messages :
321  !
322  ! None.
323  !
324  ! 7. Remarks :
325  ! make the interface between the WAVEWATCH and the WWM code.
326  !
327  ! 8. Structure :
328  !
329  !
330  ! 9. Switches :
331  !
332  ! !/S Enable subroutine tracing.
333  !
334  !
335  ! 10. Source code :
336  !/ ------------------------------------------------------------------- /
337  !/
338  !
339  USE constants
340  !
341  USE w3timemd, ONLY: dsec21
342  !
343  USE w3gdatmd, ONLY: nx, ny, nsea, mapsf, dtcfl, clats, &
344  flcx, flcy, nk, nth, dth, xfr, &
346  ntri, trigp, ccon , &
348 
349  USE w3adatmd, ONLY: cg, cx, cy, atrnx, atrny, itime, dw
350  USE w3idatmd, ONLY: flcur
351 #ifdef W3_T
352  USE w3odatmd, ONLY: ndse, ndst, flbpi, nbi, tbpi0, tbpin, &
353  isbpi, bbpi0, bbpin
354 #endif
355 #ifdef W3_S
356  USE w3servmd, ONLY: strace
357 #endif
358 
359  IMPLICIT NONE
360  !/ ------------------------------------------------------------------- /
361  !/ Parameter list
362  !/
363  INTEGER, INTENT(IN) :: ISEA, NKCFL, MAPFS(NY*NX)
364  REAL, INTENT(IN) :: FACX, FACY, DT, VGX, VGY
365  REAL, INTENT(INOUT) :: CFLXYMAX
366  !/
367  !/ ------------------------------------------------------------------- /
368  !/ Local parameters
369  !/
370  INTEGER :: ITH, IK
371  INTEGER :: IP, IP2, ISEA2, I, J, IE, IV, I1, I2, I3
372 #ifdef W3_S
373  INTEGER, SAVE :: IENT = 0
374 #endif
375  REAL :: CCOS, CSIN, CCURX, CCURY
376  REAL :: C(NX,2)
377  real*8 :: kelem(3), ktmp(3), lambda(2)
378  real*8 :: kksum, dtmaxexp
379  !/
380  !/ Velocities
381  !/
382  real*8, PARAMETER :: onesixth = 1.0d0/6.0d0
383  real*8, PARAMETER :: thr8 = tiny(1.0d0)
384  REAL, PARAMETER :: THR = tiny(1.0)
385 
386  !/ ------------------------------------------------------------------- /
387  !
388  ! 1. Preparations --------------------------------------------------- *
389  ! 1.a Set constants
390  !
391 
392 #ifdef W3_S
393  CALL strace (ient, 'W3CFLUG')
394 #endif
395  cflxymax=1e-10
396  ip = mapsf(isea,3)
397  !
398  ! CFL no important on boundary
399  !
400  IF (iobp(ip).EQ.1) THEN
401  ccurx = facx
402  ccury = facy
403  !
404  ! Loop over spectral components
405  !
406  DO ik=1,nkcfl
407  DO ith=1,nth
408  ccos = facx * ecos(ith)
409  csin = facy * esin(ith)
410  c(:,:)=0.
411 
412  !
413  ! 2. Calculate advection velocities: group speed ---------------- *
414  !
415  !AR: needs to be rewritten for speed ... single node computation is costly ...
416  !MA: you are right but now it is only called if CFX and UNST for CFL profiling
417 
418  DO i = index_cell(ip), index_cell(ip+1)-1
419  ie=ie_cell(i) ! TRIGP(IV,IE)=IP with IV=POS_CELL(I)
420  DO j=1,3
421  ip2=trigp(j,ie)
422  isea2=mapfs(ip2)
423  c(ip2,1) = ccos * cg(ik,isea2) / clats(isea2)
424  c(ip2,2) = csin * cg(ik,isea2)
425 #ifdef W3_MGP
426  c(ip2,1) = c(ip2,1) - ccurx*vgx/clats(isea2)
427  c(ip2,2) = c(ip2,2) - ccury*vgy
428 #endif
429  IF ( flcur ) THEN
430  IF (iobp(ip2) .EQ. 1) THEN
431  c(ip2,1) = c(ip2,1) + ccurx*cx(isea2)/clats(isea2)
432  c(ip2,2) = c(ip2,2) + ccury*cy(isea2)
433  END IF
434  END IF ! end of ( FLCUR )
435  END DO
436  END DO
437  !
438  !3. Calculate K-Values and contour based quantities ...
439  !
440  kksum = 0.d0
441  DO i = index_cell(ip), index_cell(ip+1)-1
442  ie=ie_cell(i) ! TRIGP(IV,IE)=IP
443  iv=pos_cell(i)
444  i1 = trigp(1,ie)
445  i2 = trigp(2,ie)
446  i3 = trigp(3,ie)
447  lambda(1) = onesixth *(c(i1,1)+c(i2,1)+c(i3,1)) ! Advection speed in X direction
448  lambda(2) = onesixth *(c(i1,2)+c(i2,2)+c(i3,2)) ! Advection speed in Y direction
449  kelem(1) = lambda(1) * ien(ie,1) + lambda(2) * ien(ie,2) ! K-Values - so called Flux Jacobians
450  kelem(2) = lambda(1) * ien(ie,3) + lambda(2) * ien(ie,4) ! K-Values - so called Flux Jacobians
451  kelem(3) = lambda(1) * ien(ie,5) + lambda(2) * ien(ie,6) ! K-Values - so called Flux Jacobians
452 
453  ktmp = kelem ! Copy
454  kelem = max(0.d0,ktmp)
455 
456  kksum = kksum + kelem(iv)
457  END DO ! COUNTRI
458  !
459  dtmaxexp = si(ip)/max(dble(10.e-10),kksum)
460  cflxymax = max(dble(dt)/dtmaxexp,dble(cflxymax))
461  END DO
462  END DO
463  END IF
464  !
465  RETURN
466  END SUBROUTINE w3cflug
467  !/ ------------------------------------------------------------------- /
468 
469  SUBROUTINE w3xypfsn2 ( ISP, C, LCALC, RD10, RD20, DT, AC)
470 
471  !/
472  !/
473  !/ +-----------------------------------+
474  !/ | WWIII Version of the WWM FS Code |
475  !/ | by Aron Roland |
476  !/ | and Fabrice Ardhuin |
477  !/ | for use in WWIII |
478  !/ | GPL License |
479  !/ | Last update : 15-Apr-2020 |
480  !/ +-----------------------------------+
481  !/
482  !/ 19-Dec-2007 : Origination. ( version 3.13 )
483  !/ 25-Aug-2011 : Change of method for IOBPD ( version 4.04 )
484  !/ 03-Nov-2011 : Addition of shoreline reflection ( version 4.04 )
485  !/ 15-Apr-2020 : Adds optional opt-out for CFL on BC ( version 7.08 )
486  !/
487  !/
488  ! 1. Purpose :
489  ! Advection of a scalar in a arbitary velocity field on unstructured meshes
490  ! for the conservative hyperbolic equation N,t + (c*N),xy = 0 in spatial space
491  ! This is the standard explicit N-Scheme from Roe as formulated in Abgrall
492  !
493  ! 2. Method :
494  !
495  ! 3. Parameters :
496  !
497  ! Parameter list
498  ! ----------------------------------------------------------------
499  ! ----------------------------------------------------------------
500  !
501  ! 4. Subroutines used :
502  !
503  ! STRACE Subroutine tracing (!/S switch)
504  !
505  ! 5. Called by :
506  !
507  ! W3XYPUG Routine for advection on unstructured grid
508  !
509  ! 6. Error messages :
510  !
511  ! None.
512  !
513  ! 7. Remarks :
514  !
515  ! 8. Structure :
516  !
517  ! See source code.
518  !
519  ! 9. Switches :
520  !
521  ! !/S Enable subroutine tracing.
522  !
523  ! 10. Source code :
524  !
525  !/ ------------------------------------------------------------------- /
526  !/
527  USE w3gdatmd, ONLY : nk, nth, ntri, nx, ccon, ie_cell,pos_cell, si, &
528  ien, trigp, clats, mapsf, iobpd, iobp, iobdp, &
529  iobpa, fsbccfl
530 #ifdef W3_REF1
531  USE w3gdatmd, ONLY : refpars
532 #endif
533  USE w3wdatmd, ONLY: time
534  USE w3adatmd, ONLY: cg, iter, dw
535  USE w3odatmd, ONLY: ndse, ndst, flbpi, nbi, tbpi0, tbpin, isbpi, bbpi0, bbpin
536  USE w3timemd, ONLY: dsec21
537 #ifdef W3_S
538  USE w3servmd, ONLY: strace
539 #endif
540  IMPLICIT NONE
541 
542  INTEGER, INTENT(IN) :: ISP ! Actual Frequency/Wavenumber, actual Wave Direction
543  REAL, INTENT(IN) :: DT ! Time intervall for which the advection should be computed for the given velocity field
544  REAL, INTENT(IN) :: C(:,:) ! Velocity field in it's X- and Y- Components,
545  DOUBLE PRECISION, INTENT(INOUT):: AC(:) ! Wave Action before and after advection
546  REAL, INTENT(IN) :: RD10, RD20 ! Time interpolation coefficients for boundary conditions
547  LOGICAL, INTENT(IN) :: LCALC ! Switch for the calculation of the max. Global Time step
548  !/
549  !/ ------------------------------------------------------------------- /
550  !/ Parameter list
551  !/
552  !/
553  !/ ------------------------------------------------------------------- /
554  !/ Local parameters
555  !/
556 #ifdef W3_S
557  INTEGER, SAVE :: IENT = 0
558 #endif
559 
560  real*8, PARAMETER :: onesixth = 1.0d0/6.0d0
561  real*8, PARAMETER :: thr8 = tiny(1.0d0)
562  REAL, PARAMETER :: THR = tiny(1.0)
563  !/
564  !/ ------------------------------------------------------------------- /
565  !/
566  !
567  ! local integer
568  !
569  INTEGER :: IP, IE, IT, I1, I2, I3, ITH, IK
570  INTEGER :: IBI, NI(3)
571  !
572  ! local real
573  !
574  REAL :: RD1, RD2
575  !
576  ! local double
577  !
578  real*8 :: utilde, boundary_forcing
579  real*8 :: cflxy
580  real*8 :: fl11, fl12, fl21, fl22, fl31, fl32
581  real*8 :: fl111, fl112, fl211, fl212, fl311, fl312
582  real*8 :: dtsi(nx), u(nx)
583  real*8 :: dtmaxgl, dtmaxexp, rest
584  real*8 :: lambda(2), ktmp(3), cloc(2,3)
585  real*8 :: kelem(3,ntri), flall(3,ntri)
586  real*8 :: kksum(nx), st(nx)
587  real*8 :: nm(ntri)
588 
589 #ifdef W3_S
590  CALL strace (ient, 'W3XYPFSN')
591 #endif
592 
593  ! 1. initialisation
594 
595  ith = 1 + mod(isp-1,nth)
596  ik = 1 + (isp-1)/nth
597  dtmaxgl = dble(10.e10)
598  !
599  !2 Propagation
600  !2.a Calculate K-Values and contour based quantities ...
601  !
602  DO ie = 1, ntri ! I precacalculate this arrays below as I assume that current velocity changes continusly ...
603 
604  i1 = trigp(1,ie) ! Index of the Element Nodes (TRIGP)
605  i2 = trigp(2,ie)
606  i3 = trigp(3,ie)
607  ni = trigp(:,ie)
608  lambda(1) = onesixth *(c(i1,1)+c(i2,1)+c(i3,1)) ! Linearized advection speed in X and Y direction
609  lambda(2) = onesixth *(c(i1,2)+c(i2,2)+c(i3,2))
610  kelem(1,ie) = lambda(1) * ien(ie,1) + lambda(2) * ien(ie,2) ! K-Values - so called Flux Jacobians
611  kelem(2,ie) = lambda(1) * ien(ie,3) + lambda(2) * ien(ie,4)
612  kelem(3,ie) = lambda(1) * ien(ie,5) + lambda(2) * ien(ie,6)
613  !
614  ktmp = kelem(:,ie) ! Copy
615  nm(ie) = - 1.d0/min(-thr8,sum(min(0.d0,ktmp))) ! N-Values
616  kelem(:,ie) = max(0.d0,ktmp)
617  fl11 = c(i2,1) * ien(ie,1) + c(i2,2) * ien(ie,2) ! Weights for Simpson Integration
618  fl12 = c(i3,1) * ien(ie,1) + c(i3,2) * ien(ie,2)
619  fl21 = c(i3,1) * ien(ie,3) + c(i3,2) * ien(ie,4)
620  fl22 = c(i1,1) * ien(ie,3) + c(i1,2) * ien(ie,4)
621  fl31 = c(i1,1) * ien(ie,5) + c(i1,2) * ien(ie,6)
622  fl32 = c(i2,1) * ien(ie,5) + c(i2,2) * ien(ie,6)
623  fl111 = 2.d0*fl11+fl12
624  fl112 = 2.d0*fl12+fl11
625  fl211 = 2.d0*fl21+fl22
626  fl212 = 2.d0*fl22+fl21
627  fl311 = 2.d0*fl31+fl32
628  fl312 = 2.d0*fl32+fl31
629  flall(1,ie) = (fl311 + fl212) * onesixth + kelem(1,ie)
630  flall(2,ie) = (fl111 + fl312) * onesixth + kelem(2,ie)
631  flall(3,ie) = (fl211 + fl112) * onesixth + kelem(3,ie)
632  ! IF (I1.EQ.1.OR.I2.EQ.1.OR.I3.EQ.1) WRITE(6,*) 'TEST N1 :',IK,ITH,IP,IE,KELEM(:,IE),'##',LAMBDA
633  END DO ! NTRI
634 
635  IF (lcalc) THEN ! If the current field or water level changes estimate the iteration number based on the new flow field and the CFL number of the scheme
636  kksum = 0.d0
637  DO ie = 1, ntri
638  ni = trigp(:,ie)
639  kksum(ni) = kksum(ni) + kelem(:,ie)
640  END DO ! IE
641  dtmaxexp = 1e10 ! initialize to large number
642  DO ip = 1, nx
643  IF (iobp(ip) .EQ. 1 .OR. fsbccfl) THEN
644  dtmaxexp = si(ip)/max(dble(10.e-10),kksum(ip)*iobdp(ip))
645  dtmaxgl = min( dtmaxgl, dtmaxexp)
646  END IF
647  END DO ! IP
648  cflxy = dble(dt)/dtmaxgl
649  rest = abs(mod(cflxy,1.0d0))
650  IF (rest .LT. thr8) THEN
651  iter(ik,ith) = abs(nint(cflxy))
652  ELSE IF (rest .GT. thr8 .AND. rest .LT. 0.5d0) THEN
653  iter(ik,ith) = abs(nint(cflxy)) + 1
654  ELSE
655  iter(ik,ith) = abs(nint(cflxy))
656  END IF
657  END IF ! LCALC
658 
659  DO ip = 1, nx
660  dtsi(ip) = dble(dt)/dble(iter(ik,ith))/si(ip) ! Some precalculations for the time integration.
661  END DO
662 
663  DO it = 1, iter(ik,ith)
664  u = ac
665  st = 0.d0
666  DO ie = 1, ntri
667  ni = trigp(:,ie)
668  utilde = nm(ie) * (dot_product(flall(:,ie),u(ni)))
669  st(ni) = st(ni) + kelem(:,ie) * (u(ni) - utilde) ! the 2nd term are the theta values of each node ...
670  END DO ! IE
671 
672  DO ip = 1, nx
673  !
674  ! IOBPD=0 : waves coming from land (or outside grid)
675  ! Possibly set flux to zero by multiplying ST by IOBPD but also in UTILDE multiply U(NI) by IOBPD ...
676  !
677  u(ip) = max(0.d0,u(ip)-dtsi(ip)*st(ip)*(1-iobpa(ip)))*dble(iobpd(ith,ip))
678 
679 #ifdef W3_REF1
680  WRITE(10111,*) refpars(3), iobpd(ith,ip), iobpa(ip), u(ip), ac(ip)
681  IF (refpars(3).LT.0.5.AND.iobpd(ith,ip).EQ.0.AND.iobpa(ip).EQ.0) THEN
682  u(ip) = ac(ip) ! restores reflected boundary values
683  ENDIF
684 #endif
685  END DO
686  ! update spectrum
687  ac = u
688  !
689  ! 4 Update boundaries: performs interpolation in time as done in rect grids (e.g. w3pro1md.ftn)
690  !
691  IF ( flbpi ) THEN
692  !
693  ! 4.1 In this case the boundary is read from the nest.ww3 file
694  !
695  rd1=rd10 - dt * real(iter(ik,ith)-it)/real(iter(ik,ith))
696  rd2=rd20
697  IF ( rd2 .GT. 0.001 ) THEN
698  rd2 = min(1.,max(0.,rd1/rd2))
699  rd1 = 1. - rd2
700  ELSE
701  rd1 = 0.
702  rd2 = 1.
703  END IF
704  !
705  ! Overwrites only the incoming energy ( IOBPD(ITH,IP) = 0)
706  !
707  DO ibi=1, nbi
708  ip = mapsf(isbpi(ibi),1)
709  ac(ip) = ( rd1*bbpi0(isp,ibi) + rd2*bbpin(isp,ibi) ) &
710  / cg(ik,isbpi(ibi)) * clats(isbpi(ibi))
711  END DO
712 
713  ENDIF
714  !
715  END DO ! End of loop on time steps
716  ! CALL EXTCDE ( 99 )
717  !/
718  !/ End of W3XYPFSN ----------------------------------------------------- /
719  !/
720  END SUBROUTINE w3xypfsn2
721 
722  !/ ------------------------------------------------------------------- /
723  SUBROUTINE w3xypfspsi2 ( ISP, C, LCALC, RD10, RD20, DT, AC)
724 
725  !/
726  !/
727  !/ +-----------------------------------+
728  !/ | WWIII Version of the WWM FS Code |
729  !/ | by Aron Roland |
730  !/ | for use in WWIII |
731  !/ | GPL License |
732  !/ | Last update : 19-Dec-2007 |
733  !/ +-----------------------------------+
734  !/
735  ! 1. Purpose :
736  ! Advection of a scalar in a arbitary velocity field on unstructured meshes
737  ! for the conservative hyperbolic equation N,t + (c*N),xy = 0 in spatial space
738  ! This is the standard explicit N-Scheme from Roe as formulated in Abgrall
739  !
740  ! 2. Method :
741  !
742  ! 3. Parameters :
743  !
744  ! Parameter list
745  ! ----------------------------------------------------------------
746  ! ----------------------------------------------------------------
747  !
748  ! 4. Subroutines used :
749  !
750  ! STRACE Subroutine tracing (!/S switch)
751  !
752  ! 5. Called by :
753  !
754  ! W3XYPUG Routine for advection on unstructured grid
755  !
756  ! 6. Error messages :
757  !
758  ! None.
759  !
760  ! 7. Remarks :
761  !
762  ! 8. Structure :
763  !
764  ! See source code.
765  !
766  ! 9. Switches :
767  !
768  ! !/S Enable subroutine tracing.
769  !
770  ! 10. Source code :
771  !
772  !/ ------------------------------------------------------------------- /
773  !/
774  USE w3gdatmd, ONLY : nk, nth, ntri, nx, ccon, ie_cell,pos_cell, si, &
776 #ifdef W3_REF1
777  USE w3gdatmd, ONLY : refpars
778 #endif
779  USE w3wdatmd, ONLY: time
780  USE w3adatmd, ONLY: cg, iter
781  USE w3odatmd, ONLY: ndse, ndst, flbpi, nbi, tbpi0, tbpin, isbpi, bbpi0, bbpin
782  USE w3timemd, ONLY: dsec21
783 #ifdef W3_S
784  USE w3servmd, ONLY: strace
785 #endif
786  IMPLICIT NONE
787 
788  INTEGER, INTENT(IN) :: ISP ! Actual Frequency/Wavenumber, actual Wave Direction
789  REAL, INTENT(IN) :: DT ! Time intervall for which the advection should be computed for the given velocity field
790  REAL, INTENT(IN) :: C(:,:) ! Velocity field in it's X- and Y- Components,
791  DOUBLE PRECISION,INTENT(INOUT) :: AC(:) ! Wave Action before and after advection
792  REAL, INTENT(IN) :: RD10, RD20 ! Time interpolation coefficients for boundary conditions
793  LOGICAL, INTENT(IN) :: LCALC ! Switch for the calculation of the max. Global Time step
794  !/
795  !/ ------------------------------------------------------------------- /
796  !/ Parameter list
797  !/
798  !/
799  !/ ------------------------------------------------------------------- /
800  !/ Local parameters
801  !/
802 #ifdef W3_S
803  INTEGER, SAVE :: IENT = 0
804 #endif
805 
806  real*8, PARAMETER :: onesixth = 1.0d0/6.0d0
807  real*8, PARAMETER :: thr8 = tiny(1.0d0)
808  REAL, PARAMETER :: THR = tiny(1.0)
809  !/
810  !/ ------------------------------------------------------------------- /
811  !/
812  !
813  ! local integer
814  !
815  INTEGER :: IP, IE, IT, I1, I2, I3, ITH, IK
816  INTEGER :: IBI, NI(3)
817  !
818  ! local real
819  !
820  REAL :: RD1, RD2
821  !:
822  ! local double
823  !
824  real*8 :: utilde, boundary_forcing
825  real*8 :: ft, cflxy
826  real*8 :: fl11, fl12, fl21, fl22, fl31, fl32
827  real*8 :: fl111, fl112, fl211, fl212, fl311, fl312
828  real*8 :: dtsi(nx), u(nx)
829  real*8 :: dtmaxgl, dtmaxexp, rest
830  real*8 :: lambda(2), ktmp(3), tmp(3)
831  real*8 :: theta_l(3), bet1(3), betahat(3)
832  real*8 :: kelem(3,ntri), flall(3,ntri)
833  real*8 :: kksum(nx), st(nx)
834  real*8 :: nm(ntri)
835 
836 #ifdef W3_S
837  CALL strace (ient, 'W3XYPFSN')
838 #endif
839 
840  ! 1. initialisation
841 
842  ith = 1 + mod(isp-1,nth)
843  ik = 1 + (isp-1)/nth
844  dtmaxgl = dble(10.e10)
845  !
846  !2 Propagation
847  !2.a Calculate K-Values and contour based quantities ...
848  !
849  DO ie = 1, ntri ! I precacalculate this arrays below as I assume that current velocity changes continusly ...
850  i1 = trigp(1,ie) ! Index of the Element Nodes (TRIGP)
851  i2 = trigp(2,ie)
852  i3 = trigp(3,ie)
853  lambda(1) = onesixth *(c(i1,1)+c(i2,1)+c(i3,1)) ! Linearized advection speed in X and Y direction
854  lambda(2) = onesixth *(c(i1,2)+c(i2,2)+c(i3,2))
855  kelem(1,ie) = lambda(1) * ien(ie,1) + lambda(2) * ien(ie,2) ! K-Values - so called Flux Jacobians
856  kelem(2,ie) = lambda(1) * ien(ie,3) + lambda(2) * ien(ie,4)
857  kelem(3,ie) = lambda(1) * ien(ie,5) + lambda(2) * ien(ie,6)
858  ktmp = kelem(:,ie) ! Copy
859  nm(ie) = - 1.d0/min(-thr8,sum(min(0.d0,ktmp))) ! N-Values
860  kelem(:,ie) = max(0.d0,ktmp)
861  fl11 = c(i2,1) * ien(ie,1) + c(i2,2) * ien(ie,2) ! Weights for Simpson Integration
862  fl12 = c(i3,1) * ien(ie,1) + c(i3,2) * ien(ie,2)
863  fl21 = c(i3,1) * ien(ie,3) + c(i3,2) * ien(ie,4)
864  fl22 = c(i1,1) * ien(ie,3) + c(i1,2) * ien(ie,4)
865  fl31 = c(i1,1) * ien(ie,5) + c(i1,2) * ien(ie,6)
866  fl32 = c(i2,1) * ien(ie,5) + c(i2,2) * ien(ie,6)
867  fl111 = 2.d0*fl11+fl12
868  fl112 = 2.d0*fl12+fl11
869  fl211 = 2.d0*fl21+fl22
870  fl212 = 2.d0*fl22+fl21
871  fl311 = 2.d0*fl31+fl32
872  fl312 = 2.d0*fl32+fl31
873  flall(1,ie) = (fl311 + fl212)! * ONESIXTH + KELEM(1,IE)
874  flall(2,ie) = (fl111 + fl312)! * ONESIXTH + KELEM(2,IE)
875  flall(3,ie) = (fl211 + fl112)! * ONESIXTH + KELEM(3,IE)
876  END DO ! NTRI
877 
878  IF (lcalc) THEN ! If the current field or water level changes estimate the iteration number based on the new flow field and the CFL number of the scheme
879  kksum = 0.d0
880  DO ie = 1, ntri
881  ni = trigp(:,ie)
882  kksum(ni) = kksum(ni) + kelem(:,ie)
883  END DO ! IE
884  dtmaxexp = 1e10 ! initialize to large number
885  DO ip = 1, nx
886  dtmaxexp = si(ip)/max(dble(10.e-10),kksum(ip)*iobdp(ip))
887  dtmaxgl = min( dtmaxgl, dtmaxexp)
888  END DO ! IP
889  cflxy = dble(dt)/dtmaxgl
890  rest = abs(mod(cflxy,1.0d0))
891  IF (rest .LT. thr8) THEN
892  iter(ik,ith) = abs(nint(cflxy))
893  ELSE IF (rest .GT. thr8 .AND. rest .LT. 0.5d0) THEN
894  iter(ik,ith) = abs(nint(cflxy)) + 1
895  ELSE
896  iter(ik,ith) = abs(nint(cflxy))
897  END IF
898  END IF ! LCALC
899 
900  DO ip = 1, nx
901  dtsi(ip) = dble(dt)/dble(iter(ik,ith))/si(ip) ! Some precalculations for the time integration.
902  END DO
903 
904  DO it = 1, iter(ik,ith)
905  u = ac
906 
907  st = 0.d0
908 
909  DO ie = 1, ntri
910  ni = trigp(:,ie)
911  ft =-onesixth*dot_product(u(ni),flall(:,ie))
912  utilde = nm(ie) * ( dot_product(kelem(:,ie),u(ni)) - ft )
913  theta_l(:) = kelem(:,ie) * (u(ni) - utilde)
914  IF (abs(ft) .GT. 0.0d0) THEN
915  bet1(:) = theta_l(:)/ft
916  IF (any( bet1 .LT. 0.0d0) ) THEN
917  betahat(1) = bet1(1) + 0.5d0 * bet1(2)
918  betahat(2) = bet1(2) + 0.5d0 * bet1(3)
919  betahat(3) = bet1(3) + 0.5d0 * bet1(1)
920  bet1(1) = max(0.d0,min(betahat(1),1.d0-betahat(2),1.d0))
921  bet1(2) = max(0.d0,min(betahat(2),1.d0-betahat(3),1.d0))
922  bet1(3) = max(0.d0,min(betahat(3),1.d0-betahat(1),1.d0))
923  theta_l(:) = ft * bet1
924  END IF
925  ELSE
926  theta_l(:) = 0.d0
927  END IF
928  st(ni) = st(ni) + theta_l ! the 2nd term are the theta values of each node ...
929  END DO
930 
931  DO ip = 1, nx
932  u(ip) = max(0.d0,u(ip)-dtsi(ip)*st(ip)*(1-iobpa(ip)))*dble(iobpd(ith,ip))
933 #ifdef W3_REF1
934  IF (refpars(3).LT.0.5.AND.iobpd(ith,ip).EQ.0.AND.iobpa(ip).EQ.0) u(ip)= ac(ip) ! restores reflected boundary values
935 #endif
936  END DO
937 
938  ! update spectrum
939  ac = u
940  !
941  ! 4 Update boundaries: performs interpolation in time as done in rect grids (e.g. w3pro1md.ftn)
942  !
943  IF ( flbpi ) THEN
944  !
945  ! 4.1 In this case the boundary is read from the nest.ww3 file
946  !
947  rd1=rd10 - dt * real(iter(ik,ith)-it)/real(iter(ik,ith))
948  rd2=rd20
949  IF ( rd2 .GT. 0.001 ) THEN
950  rd2 = min(1.,max(0.,rd1/rd2))
951  rd1 = 1. - rd2
952  ELSE
953  rd1 = 0.
954  rd2 = 1.
955  END IF
956  !
957  ! Overwrites only the incoming energy ( IOBPD(ITH,IP) = 0)
958  !
959  DO ibi=1, nbi
960  ip = mapsf(isbpi(ibi),1)
961  ac(ip) = ( rd1*bbpi0(isp,ibi) + rd2*bbpin(isp,ibi) ) &
962  / cg(ik,isbpi(ibi)) * clats(isbpi(ibi))
963  END DO
964 
965  ENDIF
966  !
967  END DO ! End of loop on time steps
968  ! CALL EXTCDE ( 99 )
969  !/
970  !/ End of W3XYPFSN ----------------------------------------------------- /
971  !/
972  END SUBROUTINE w3xypfspsi2
973 
974  !/ ------------------------------------------------------------------- /
975  SUBROUTINE w3xypfsnimp ( ISP, C, LCALC, RD10, RD20, DT, AC)
976 
977  !/
978  !/
979  !/ +-----------------------------------+
980  !/ | WWIII Version of the WWM FS Code |
981  !/ | by Aron Roland |
982  !/ | for use in WWIII |
983  !/ | GPL License |
984  !/ | Last update : 15-Dec-2013 |
985  !/ +-----------------------------------+
986  !/
987  !/ 15-Dec-2013 : Bug fix for implicit scheme ( version 4.16 )
988  !/
989  ! 1. Purpose :
990  ! Advection of a scalar in a arbitary velocity field on unstructured meshes
991  ! for the conservative hyperbolic equation N,t + (c*N),xy = 0 in spatial space
992  ! This is the standard explicit N-Scheme from Roe as formulated in Abgrall
993  !
994  ! 2. Method :
995  !
996  ! 3. Parameters :
997  !
998  ! Parameter list
999  ! ----------------------------------------------------------------
1000  ! ----------------------------------------------------------------
1001  !
1002  ! 4. Subroutines used :
1003  !
1004  ! STRACE Subroutine tracing (!/S switch)
1005  !
1006  ! 5. Called by :
1007  !
1008  ! W3XYPUG Routine for advection on unstructured grid
1009  !
1010  ! 6. Error messages :
1011  !
1012  ! None.
1013  !
1014  ! 7. Remarks :
1015  !
1016  ! 8. Structure :
1017  !
1018  ! See source code.
1019  !
1020  ! 9. Switches :
1021  !
1022  ! !/S Enable subroutine tracing.
1023  !
1024  ! 10. Source code :
1025  !
1026  !/ ------------------------------------------------------------------- /
1027  !/
1028  USE w3gdatmd, ONLY : nk, nth, ntri, nx, ccon, ie_cell,pos_cell, si, &
1029  ien, trigp, clats, mapsf, iobpd, iobpa, iobp, iaa, jaa, posi, &
1030  tria, nnz
1031 #ifdef W3_REF1
1032  USE w3gdatmd, ONLY : refpars
1033 #endif
1034  USE w3wdatmd, ONLY: time
1035  USE w3adatmd, ONLY: cg, iter
1036  USE w3odatmd, ONLY: ndse, ndst, flbpi, nbi, tbpi0, tbpin, isbpi, bbpi0, bbpin
1037  USE w3timemd, ONLY: dsec21
1038 #ifdef W3_S
1039  USE w3servmd, ONLY: strace
1040 #endif
1041  IMPLICIT NONE
1042 
1043  INTEGER, INTENT(IN) :: ISP ! Actual Frequency/Wavenumber, actual Wave Direction
1044  REAL, INTENT(IN) :: DT ! Time intervall for which the advection should be computed for the given velocity field
1045  REAL, INTENT(IN) :: C(:,:) ! Velocity field in it's X- and Y- Components,
1046  DOUBLE PRECISION,INTENT(INOUT) :: AC(:) ! Wave Action before and after advection
1047  REAL, INTENT(IN) :: RD10, RD20 ! Time interpolation coefficients for boundary conditions
1048  LOGICAL, INTENT(IN) :: LCALC ! Switch for the calculation of the max. Global Time step
1049  !/
1050  !/ ------------------------------------------------------------------- /
1051  !/ Parameter list
1052  !/
1053  !/
1054  !/ ------------------------------------------------------------------- /
1055  !/ Local parameters
1056  !/
1057 #ifdef W3_S
1058  INTEGER, SAVE :: IENT = 0
1059 #endif
1060 
1061  real*8, PARAMETER :: onesixth = 1.0d0/6.0d0
1062  real*8, PARAMETER :: onethird = 1.0d0/3.0d0
1063  real*8, PARAMETER :: thr8 = tiny(1.0d0)
1064  REAL, PARAMETER :: THR = tiny(1.0)
1065  !/
1066  !/ ------------------------------------------------------------------- /
1067  !/
1068  !
1069  ! local integer
1070  !
1071  INTEGER :: IP, IE, POS, I1, I2, I3, I, J, ITH, IK
1072  INTEGER :: IBI
1073  !
1074  ! local real
1075  !
1076  REAL :: RD1, RD2
1077  !:
1078  ! local double
1079  !
1080  real*8 :: boundary_forcing
1081  real*8 :: fl11, fl12, fl21, fl22, fl31, fl32
1082  real*8 :: u(nx)
1083  real*8 :: dtmaxgl
1084  real*8 :: lambda(2)
1085  real*8 :: kp(3,ntri)
1086  real*8 :: k1, dtk, tmp3, km(3), k(3)
1087  real*8 :: nm(ntri), crfs(3), deltal(3,ntri)
1088  real*8 :: b(nx), x(nx)
1089  real*8 :: aspar(nnz)
1090 
1091  INTEGER :: IWKSP( 20*NX )
1092  INTEGER :: FLJU(NX)
1093  INTEGER :: FLJAU(NNZ+1)
1094 
1095 
1096  INTEGER :: POS_TRICK(3,2)
1097 
1098  INTEGER :: IPAR(16)
1099  INTEGER :: IERROR ! IWK ! ERROR Indicator and Work Array Size,
1100  INTEGER :: JAU(NNZ+1), JU(NX)
1101 
1102  real*8 :: fpar(16) ! DROPTOL
1103  real*8 :: wksp( 8 * nx ) ! REAL WORKSPACES
1104  real*8 :: au(nnz+1)
1105  real*8 :: iniu(nx)
1106 
1107  external bcgstab
1108 
1109  pos_trick(1,1) = 2
1110  pos_trick(1,2) = 3
1111  pos_trick(2,1) = 3
1112  pos_trick(2,2) = 1
1113  pos_trick(3,1) = 1
1114  pos_trick(3,2) = 2
1115 
1116 #ifdef W3_S
1117  CALL strace (ient, 'W3XYPFSN')
1118 #endif
1119 
1120  ! 1. initialisation
1121 
1122  ith = 1 + mod(isp-1,nth)
1123  ik = 1 + (isp-1)/nth
1124  dtmaxgl = dble(10.e10)
1125 
1126  IF (.false.) THEN
1127  WRITE(*,*) 'NNZ', nnz
1128  WRITE(*,*) 'MINVAL IAA,JAA', minval(iaa), minval(jaa)
1129  WRITE(*,*) 'MINVAL IAA,JAA', maxval(iaa), maxval(jaa)
1130  WRITE(*,*) 'MAX/MIN POSI', maxval(posi), minval(posi)
1131  WRITE(*,*) 'AC, AQ', sum(ac)
1132  END IF
1133  !
1134  !2 Propagation
1135  !2.a Calculate K-Values and contour based quantities ...
1136  !
1137  DO ie = 1, ntri ! I precacalculate this arrays below as I assume that current velocity changes continusly ...
1138  i1 = trigp(1,ie) ! Index of the Element Nodes (TRIGP)
1139  i2 = trigp(2,ie)
1140  i3 = trigp(3,ie)
1141  lambda(1) = onesixth * (c(i1,1)+c(i2,1)+c(i3,1))
1142  lambda(2) = onesixth * (c(i1,2)+c(i2,2)+c(i3,2))
1143  k(1) = lambda(1) * ien(ie,1) + lambda(2) * ien(ie,2)
1144  k(2) = lambda(1) * ien(ie,3) + lambda(2) * ien(ie,4)
1145  k(3) = lambda(1) * ien(ie,5) + lambda(2) * ien(ie,6)
1146  kp(1,ie) = max(0.d0,k(1))
1147  kp(2,ie) = max(0.d0,k(2))
1148  kp(3,ie) = max(0.d0,k(3))
1149  km(1) = min(0.d0,k(1))
1150  km(2) = min(0.d0,k(2))
1151  km(3) = min(0.d0,k(3))
1152  fl11 = c(i2,1)*ien(ie,1)+c(i2,2)*ien(ie,2)
1153  fl12 = c(i3,1)*ien(ie,1)+c(i3,2)*ien(ie,2)
1154  fl21 = c(i3,1)*ien(ie,3)+c(i3,2)*ien(ie,4)
1155  fl22 = c(i1,1)*ien(ie,3)+c(i1,2)*ien(ie,4)
1156  fl31 = c(i1,1)*ien(ie,5)+c(i1,2)*ien(ie,6)
1157  fl32 = c(i2,1)*ien(ie,5)+c(i2,2)*ien(ie,6)
1158  crfs(1) = - onesixth * (2.0d0 *fl31 + fl32 + fl21 + 2.0d0 * fl22 )
1159  crfs(2) = - onesixth * (2.0d0 *fl32 + 2.0d0 * fl11 + fl12 + fl31 )
1160  crfs(3) = - onesixth * (2.0d0 *fl12 + 2.0d0 * fl21 + fl22 + fl11 )
1161  deltal(:,ie) = crfs(:)- kp(:,ie)
1162  nm(ie) = 1.d0/min(dble(thr),sum(km(:)))
1163  END DO ! NTRI
1164 
1165  u = dble(ac)
1166  j = 0
1167  aspar = 0.d0
1168  b = 0.d0
1169  DO ip = 1, nx
1170  DO i = 1, ccon(ip)
1171  j = j + 1
1172  ie = ie_cell(j)
1173  pos = pos_cell(j)
1174  k1 = kp(pos,ie) * iobpd(ith,ip)
1175  IF (k1 > 0.) THEN
1176  dtk = k1 * dt
1177  tmp3 = dtk * nm(ie)
1178  i1 = posi(1,j)
1179  i2 = posi(2,j)
1180  i3 = posi(3,j)
1181  aspar(i1) = onethird * tria(ie) + dtk - tmp3 * deltal(pos,ie) + aspar(i1)
1182  aspar(i2) = - tmp3 * deltal(pos_trick(pos,1),ie) + aspar(i2)
1183  aspar(i3) = - tmp3 * deltal(pos_trick(pos,2),ie) + aspar(i3)
1184  b(ip) = b(ip) + onethird * tria(ie) * u(ip)
1185  ELSE
1186  i1 = posi(1,j)
1187  aspar(i1) = onethird * tria(ie) + aspar(i1)
1188  b(ip) = b(ip) + onethird * tria(ie) * u(ip)
1189  END IF
1190  END DO ! End loop over connected elements ...
1191  END DO
1192  !
1193  !2DO setup a semi-implicit integration scheme for source terms only ...
1194  !
1195  ipar(1) = 0 ! always 0 to start an iterative solver
1196  ipar(2) = 1 ! right preconditioning
1197  ipar(3) = 1 ! use convergence test scheme 1
1198  ipar(4) = 8*nx !
1199  ipar(5) = 15
1200  ipar(6) = 1000 ! use at most 1000 matvec's
1201  fpar(1) = dble(1.0e-8) ! relative tolerance 1.0E-6
1202  fpar(2) = dble(1.0e-10) ! absolute tolerance 1.0E-10
1203  fpar(11) = 0.d0 ! clearing the FLOPS counter
1204 
1205  au = 0.
1206  fljau = 0
1207  flju = 0
1208  jau = 0
1209  ju = 0
1210 
1211  CALL ilu0 (nx, aspar, jaa, iaa, au, fljau, flju, iwksp, ierror)
1212 
1213  ! WRITE(*,*) 'PRECONDITIONER', IERROR
1214 
1215  ! IF (SUM(AC) .GT. 0.) THEN
1216  IF (.false.) THEN
1217  WRITE(*,*) sum(ac)
1218  WRITE(*,*) 'CALL SOLVER'
1219  WRITE(*,*) 'WRITE CG', sum(cg)
1220  WRITE(*,*) 'B, X, AC, U', sum(b), sum(x), sum(ac), sum(u)
1221  WRITE(*,*) 'IPAR, FPAR', sum(ipar), sum(fpar)
1222  WRITE(*,*) 'WKSP, INIU', sum(wksp), sum(iniu)
1223  WRITE(*,*) 'ASPAR, JAA, IAA',sum(aspar), sum(iaa), sum(jaa)
1224  WRITE(*,*) 'AU, FLJAU, FLJU',sum(au), sum(fljau), sum(flju)
1225  END IF
1226 
1227  iniu = u
1228  x = 0.d0
1229 
1230  CALL runrc (nx, b, x, ipar, fpar, wksp, iniu, aspar, jaa, iaa, au, fljau, flju, bcgstab)
1231 
1232  IF (.false.) THEN
1233  WRITE(*,*) 'SOLUTION'
1234  WRITE(*,*) 'B, X, AC, U', sum(b), sum(x), sum(ac), sum(u)
1235  WRITE(*,*) 'IPAR, FPAR', sum(ipar), sum(fpar)
1236  WRITE(*,*) 'WKSP, INIU', sum(wksp), sum(iniu)
1237  WRITE(*,*) 'ASPAR, JAA, IAA', sum(aspar), sum(jaa), sum(iaa)
1238  WRITE(*,*) 'AU, FLJAU, FLJU', sum(au), sum(fljau), sum(flju)
1239  END IF
1240 
1241  DO ip = 1,nx
1242  u(ip) = max(0.d0,x(ip)*dble(iobpd(ith,ip)))
1243 #ifdef W3_REF1
1244  IF (refpars(3).LT.0.5.AND.iobpd(ith,ip).EQ.0.AND.iobpa(ip).EQ.0) u(ip)= ac(ip) ! restores reflected boundary values
1245 #endif
1246  END DO
1247  !
1248  ! update spectrum
1249  ac = real(u)
1250  !
1251  ! 4 Update boundaries: performs interpolation in time as done in rect grids (e.g. w3pro1md.ftn)
1252  !
1253  IF ( flbpi ) THEN
1254  rd1=rd10
1255  rd2=rd20
1256  IF ( rd2 .GT. 0.001 ) THEN
1257  rd2 = min(1.,max(0.,rd1/rd2))
1258  rd1 = 1. - rd2
1259  ELSE
1260  rd1 = 0.
1261  rd2 = 1.
1262  END IF
1263  !
1264  ! Time interpolation as done in rect grids
1265  !
1266  DO ibi=1, nbi
1267  ip = mapsf(isbpi(ibi),1)
1268  ac(ip) = ( rd1*bbpi0(isp,ibi) + rd2*bbpin(isp,ibi) ) &
1269  *iobpa(ip)*iobpd(ith,ip) / cg(ik,isbpi(ibi)) * clats(isbpi(ibi))
1270  END DO
1271  END IF
1272 
1273  ! CALL EXTCDE ( 99 )
1274  !/
1275  !/ End of W3XYPFSNIMP------------------------------------------------- /
1276  !/
1277  END SUBROUTINE w3xypfsnimp
1278 
1279  !/ ------------------------------------------------------------------- /
1280 
1281  SUBROUTINE w3xypfsfct2 ( ISP, C, LCALC, RD10, RD20, DT, AC)
1282  !/
1283  !/
1284  !/ +-----------------------------------+
1285  !/ | WWIII Version of the WWM FS Code |
1286  !/ | by Aron Roland |
1287  !/ | for use in WWIII |
1288  !/ | GPL License |
1289  !/ | Last update : 19-Dec-2007 |
1290  !/ +-----------------------------------+
1291  !/
1292  ! 1. Purpose :
1293  ! Advection of a scalar in a arbitary velocity field on unstructured meshes
1294  ! for the conservative hyperbolic equation N,t + (c*N),xy = 0 in spatial space
1295  !
1296  ! 2. Method :
1297  !
1298  ! 3. Parameters :
1299  !
1300  ! Parameter list
1301  ! ----------------------------------------------------------------
1302  ! ----------------------------------------------------------------
1303  !
1304  ! 4. Subroutines used :
1305  !
1306  ! STRACE Subroutine tracing (!/S switch)
1307  !
1308  ! 5. Called by :
1309  !
1310  ! W3XYPUG Routine for advection on unstructured grid
1311  !
1312  ! 6. Error messages :
1313  !
1314  ! None.
1315  !
1316  ! 7. Remarks :
1317  !
1318  ! 8. Structure :
1319  !
1320  ! See source code.
1321  !
1322  ! 9. Switches :
1323  !
1324  ! !/S Enable subroutine tracing.
1325  !
1326  ! 10. Source code :
1327  !
1328  !/ ------------------------------------------------------------------- /
1329  !/
1330  USE w3gdatmd, ONLY : nk, nth, ntri, nx, ccon, ie_cell,pos_cell, si, &
1332 #ifdef W3_REF1
1333  USE w3gdatmd, ONLY : refpars
1334 #endif
1335  USE w3wdatmd, ONLY: time
1336  USE w3adatmd, ONLY: cg, iter
1337  USE w3odatmd, ONLY: ndse, ndst, flbpi, nbi, tbpi0, tbpin, isbpi, bbpi0, bbpin
1338  USE w3timemd, ONLY: dsec21
1339 #ifdef W3_S
1340  USE w3servmd, ONLY: strace
1341 #endif
1342  IMPLICIT NONE
1343 
1344  INTEGER, INTENT(IN) :: ISP ! Actual Frequency/Wavenumber, actual Wave Direction
1345  REAL, INTENT(IN) :: DT ! Time intervall for which the advection should be computed for the given velocity field
1346  REAL, INTENT(IN) :: C(:,:) ! Velocity field in it's X- and Y- Components,
1347  DOUBLE PRECISION, INTENT(INOUT) :: AC(:) ! Wave Action before and after advection
1348  REAL, INTENT(IN) :: RD10, RD20 ! Time interpolation coefficients for boundary condition
1349  LOGICAL, INTENT(IN) :: LCALC ! Switch for the calculation of the max. Global Time step
1350  !/
1351  !/ ------------------------------------------------------------------- /
1352  !/ Parameter list
1353  !/
1354  !/
1355  !/ ------------------------------------------------------------------- /
1356  !/ Local parameters
1357  !/
1358 #ifdef W3_S
1359  INTEGER, SAVE :: IENT = 0
1360 #endif
1361 
1362  real*8, PARAMETER :: onesixth = 1.0d0/6.0d0
1363  real*8, PARAMETER :: onethird = 1.0d0/3.0d0
1364  real*8, PARAMETER :: thr8 = tiny(1.0d0)
1365  REAL, PARAMETER :: THR = tiny(1.0)
1366  !/
1367  !/ ------------------------------------------------------------------- /
1368  !/
1369  !
1370  ! local integer
1371  !
1372  INTEGER :: IP, IE, IT, I1, I2, I3, I, ITH, IK
1373  INTEGER :: IBI, NI(3)
1374  !
1375  ! local real
1376  !
1377  REAL :: RD1, RD2
1378  !:
1379  ! local double
1380  !
1381  real*8 :: utilde, boundary_forcing
1382  real*8 :: ft, cflxy
1383  real*8 :: fl11, fl12, fl21, fl22, fl31, fl32
1384  real*8 :: fl111, fl112, fl211, fl212, fl311, fl312
1385  real*8 :: dtsi(nx), u(nx), dt4ai
1386  real*8 :: dtmaxgl, dtmaxexp, rest
1387  real*8 :: lambda(2), ktmp(3), tmp(3)
1388  real*8 :: bet1(3), betahat(3)
1389  real*8 :: theta_l(3,ntri), theta_h(3,ntri), theta_ace(3,ntri), utmp(3)
1390  real*8 :: wii(2,nx), ul(nx), ustari(2,nx)
1391 
1392  real*8 :: pm(nx), pp(nx), uim(nx), uip(nx)
1393 
1394  real*8 :: kelem(3,ntri), flall(3,ntri)
1395  real*8 :: kksum(nx), st(nx), beta
1396  real*8 :: nm(ntri)
1397 
1398 #ifdef W3_S
1399  CALL strace (ient, 'W3XYPFSFCT2')
1400 #endif
1401 
1402  ! 1. initialisation
1403 
1404  ith = 1 + mod(isp-1,nth)
1405  ik = 1 + (isp-1)/nth
1406  dtmaxgl = dble(10.e10)
1407  !
1408  !2 Propagation
1409  !2.a Calculate K-Values and contour based quantities ...
1410  !
1411  DO ie = 1, ntri ! I precacalculate this arrays below as I assume that current velocity changes continusly ...
1412  i1 = trigp(1,ie) ! Index of the Element Nodes (TRIGP)
1413  i2 = trigp(2,ie)
1414  i3 = trigp(3,ie)
1415  lambda(1) = onesixth *(c(i1,1)+c(i2,1)+c(i3,1)) ! Linearized advection speed in X and Y direction
1416  lambda(2) = onesixth *(c(i1,2)+c(i2,2)+c(i3,2))
1417  kelem(1,ie) = lambda(1) * ien(ie,1) + lambda(2) * ien(ie,2) ! K-Values - so called Flux Jacobians
1418  kelem(2,ie) = lambda(1) * ien(ie,3) + lambda(2) * ien(ie,4)
1419  kelem(3,ie) = lambda(1) * ien(ie,5) + lambda(2) * ien(ie,6)
1420  ktmp = kelem(:,ie) ! Copy
1421  nm(ie) = - 1.d0/min(-thr8,sum(min(0.d0,ktmp))) ! N-Values
1422  fl11 = c(i2,1) * ien(ie,1) + c(i2,2) * ien(ie,2) ! Weights for Simpson Integration
1423  fl12 = c(i3,1) * ien(ie,1) + c(i3,2) * ien(ie,2)
1424  fl21 = c(i3,1) * ien(ie,3) + c(i3,2) * ien(ie,4)
1425  fl22 = c(i1,1) * ien(ie,3) + c(i1,2) * ien(ie,4)
1426  fl31 = c(i1,1) * ien(ie,5) + c(i1,2) * ien(ie,6)
1427  fl32 = c(i2,1) * ien(ie,5) + c(i2,2) * ien(ie,6)
1428  fl111 = 2.d0*fl11+fl12
1429  fl112 = 2.d0*fl12+fl11
1430  fl211 = 2.d0*fl21+fl22
1431  fl212 = 2.d0*fl22+fl21
1432  fl311 = 2.d0*fl31+fl32
1433  fl312 = 2.d0*fl32+fl31
1434  flall(1,ie) = (fl311 + fl212)! * ONESIXTH + KELEM(1,IE)
1435  flall(2,ie) = (fl111 + fl312)! * ONESIXTH + KELEM(2,IE)
1436  flall(3,ie) = (fl211 + fl112)! * ONESIXTH + KELEM(3,IE)
1437  END DO ! NTRI
1438 
1439  IF (lcalc) THEN ! If the current field or water level changes estimate the iteration number based on the new flow field and the CFL number of the scheme
1440  kksum = 0.d0
1441  DO ie = 1, ntri
1442  ni = trigp(:,ie)
1443  kksum(ni) = kksum(ni) + kelem(:,ie)
1444  END DO ! IE
1445  dtmaxexp = 1e10 ! initialize to large number
1446  DO ip = 1, nx
1447  dtmaxexp = si(ip)/max(dble(10.e-10),kksum(ip)*iobdp(ip))
1448  dtmaxgl = min( dtmaxgl, dtmaxexp)
1449  END DO ! IP
1450  cflxy = dble(dt)/dtmaxgl
1451  rest = abs(mod(cflxy,1.0d0))
1452  IF (rest .LT. thr8) THEN
1453  iter(ik,ith) = abs(nint(cflxy))
1454  ELSE IF (rest .GT. thr8 .AND. rest .LT. 0.5d0) THEN
1455  iter(ik,ith) = abs(nint(cflxy)) + 1
1456  ELSE
1457  iter(ik,ith) = abs(nint(cflxy))
1458  END IF
1459  END IF ! LCALC
1460 
1461  dt4ai = dble(dt)/dble(iter(ik,ith))
1462  dtsi(:) = dt4ai/si(:) ! Some precalculations for the time integration.
1463 
1464  u = ac
1465  ul = u
1466  !
1467  ! Now loop on sub-timesteps
1468  !
1469  DO it = 1, iter(ik,ith)
1470 
1471  st = 0.d0
1472 
1473  DO ie = 1, ntri
1474  ni = trigp(:,ie)
1475  utmp = u(ni)
1476  ft = - onesixth*dot_product(utmp,flall(:,ie))
1477  tmp = max(0.d0,kelem(:,ie))
1478  utilde = nm(ie) * ( dot_product(tmp,utmp) - ft )
1479  theta_l(:,ie) = tmp * ( utmp - utilde )
1480  IF (abs(ft) .GT. dble(thr)) THEN
1481  bet1(:) = theta_l(:,ie)/ft
1482  IF (any( bet1 .LT. 0.0d0) ) THEN
1483  betahat(1) = bet1(1) + 0.5d0 * bet1(2)
1484  betahat(2) = bet1(2) + 0.5d0 * bet1(3)
1485  betahat(3) = bet1(3) + 0.5d0 * bet1(1)
1486  bet1(1) = max(0.d0,min(betahat(1),1.d0-betahat(2),1.d0))
1487  bet1(2) = max(0.d0,min(betahat(2),1.d0-betahat(3),1.d0))
1488  bet1(3) = max(0.d0,min(betahat(3),1.d0-betahat(1),1.d0))
1489  theta_l(:,ie) = ft * bet1
1490  END IF
1491  ELSE
1492  theta_l(:,ie) = 0.d0
1493  END IF
1494  ! THETA_H(:,IE) = (ONETHIRD+DT4AI/(2.d0*TRIA(IE)) * KELEM(:,IE))*FT ! LAX-WENDROFF
1495  theta_h(:,ie) = (1./3.+2./3.* kelem(:,ie)/sum(abs(kelem(:,ie))) )*ft ! CENTRAL SCHEME
1496  ! Antidiffusive residual according to the higher order nonmonotone scheme
1497  theta_ace(:,ie) = ((theta_h(:,ie) - theta_l(:,ie))) * dt4ai/si(ni)
1498  st(ni) = st(ni) + theta_l(:,ie)*dt4ai/si(ni)
1499  END DO
1500 
1501  ! UL = MAX(0.d0,U-ST)*DBLE(IOBPD(ITH,:))!*DBLE(IOBDP(:)) ... add for IOBDP dry/wet flag.
1502 
1503  DO ip = 1,nx
1504  ul(ip) = max(0.d0,u(ip)-st(ip))*dble(iobpd(ith,ip))
1505  END DO
1506 
1507  ustari(1,:) = max(ul,u)
1508  ustari(2,:) = min(ul,u)
1509 
1510  uip = -thr8
1511  uim = thr8
1512  pp = 0.d0
1513  pm = 0.d0
1514  DO ie = 1, ntri
1515  ni = trigp(:,ie)
1516  pp(ni) = pp(ni) + max( thr8, -theta_ace(:,ie))
1517  pm(ni) = pm(ni) + min( -thr8, -theta_ace(:,ie))
1518  uip(ni) = max(uip(ni), maxval( ustari(1,ni) ))
1519  uim(ni) = min(uim(ni), minval( ustari(2,ni) ))
1520  END DO
1521 
1522  wii(1,:) = min(1.0d0,(uip-ul)/max( thr8,pp))
1523  wii(2,:) = min(1.0d0,(uim-ul)/min(-thr8,pm))
1524 
1525  st = 0.d0
1526  DO ie = 1, ntri
1527  DO i = 1, 3
1528  ip = trigp(i,ie)
1529  IF (-theta_ace(i,ie) .GE. 0.) THEN
1530  tmp(i) = wii(1,ip)
1531  ELSE
1532  tmp(i) = wii(2,ip)
1533  END IF
1534  END DO
1535  beta = minval(tmp)
1536  ni = trigp(:,ie)
1537  st(ni) = st(ni) + beta * theta_ace(:,ie)
1538  END DO
1539 
1540  DO ip = 1,nx
1541  !
1542  ! IOBPD is the switch for removing energy coming from the shoreline
1543  !
1544  u(ip) = max(0.d0,ul(ip)-st(ip))*dble(iobpd(ith,ip))
1545 #ifdef W3_REF1
1546  IF (refpars(3).LT.0.5.AND.iobpd(ith,ip).EQ.0.AND.iobpa(ip).EQ.0) u(ip)= ac(ip) ! restores reflected boundary values
1547 #endif
1548  END DO
1549  !
1550  ! update spectrum
1551  ac = u
1552  !
1553  ! 4 Update boundaries: performs interpolation in time as done in rect grids (e.g. w3pro1md.ftn)
1554  !
1555  IF ( flbpi ) THEN
1556  !
1557  ! 4.1 In this case the boundary is read from the nest.ww3 file
1558  !
1559  rd1=rd10 - dt * real(iter(ik,ith)-it)/real(iter(ik,ith))
1560  rd2=rd20
1561  IF ( rd2 .GT. 0.001 ) THEN
1562  rd2 = min(1.,max(0.,rd1/rd2))
1563  rd1 = 1. - rd2
1564  ELSE
1565  rd1 = 0.
1566  rd2 = 1.
1567  END IF
1568  !
1569  ! Overwrites only the incoming energy ( IOBPD(ITH,IP) = 0)
1570  !
1571  DO ibi=1, nbi
1572  ip = mapsf(isbpi(ibi),1)
1573  ac(ip) = ( rd1*bbpi0(isp,ibi) + rd2*bbpin(isp,ibi) ) &
1574  / cg(ik,isbpi(ibi)) * clats(isbpi(ibi))
1575  END DO
1576 
1577  ENDIF
1578  !
1579  END DO ! End of loop on time steps
1580  ! CALL EXTCDE ( 99 )
1581  !/
1582  !/ End of W3XYPFSN ----------------------------------------------------- /
1583  !/
1584  END SUBROUTINE w3xypfsfct2
1585  !/ ------------------------------------------------------------------- /
1586  SUBROUTINE setdepth
1587  !/
1588  !/ +-----------------------------------+
1589  !/ | WAVEWATCH III NOAA/NCEP |
1590  !/ | |
1591  !/ | Aron Roland (BGS IT&E GmbH) |
1592  !/ | Mathieu Dutour-Sikiric (IRB) |
1593  !/ | |
1594  !/ | FORTRAN 90 |
1595  !/ | Last update : 01-June-2018 |
1596  !/ +-----------------------------------+
1597  !/
1598  !/ 01-June-2018 : Origination. ( version 6.04 )
1599  !/
1600  ! 1. Purpose : Init pdlib part
1601  ! 2. Method :
1602  ! 3. Parameters :
1603  !
1604  ! Parameter list
1605  ! ----------------------------------------------------------------
1606  ! ----------------------------------------------------------------
1607  !
1608  ! 4. Subroutines used :
1609  !
1610  ! Name Type Module Description
1611  ! ----------------------------------------------------------------
1612  ! STRACE Subr. W3SERVMD Subroutine tracing.
1613  ! ----------------------------------------------------------------
1614  !
1615  ! 5. Called by :
1616  !
1617  ! Name Type Module Description
1618  ! ----------------------------------------------------------------
1619  ! ----------------------------------------------------------------
1620  !
1621  ! 6. Error messages :
1622  ! 7. Remarks
1623  ! 8. Structure :
1624  ! 9. Switches :
1625  !
1626  ! !/S Enable subroutine tracing.
1627  !
1628  ! 10. Source code :
1629  !
1630  !/ ------------------------------------------------------------------- /
1631 #ifdef W3_S
1632  USE w3servmd, ONLY: strace
1633 #endif
1634  !
1635  USE constants, ONLY : lpdlib
1636  USE w3gdatmd, ONLY: mapsf, nseal, dmin, iobdp, mapsta, iobp, mapfs, nx
1637  USE w3adatmd, ONLY: dw
1638 
1639  IMPLICIT NONE
1640  !/
1641  !/ ------------------------------------------------------------------- /
1642  !/ Parameter list
1643  !/
1644  !/ ------------------------------------------------------------------- /
1645  !/ Local PARAMETERs
1646  !/
1647 #ifdef W3_S
1648  INTEGER, SAVE :: IENT = 0
1649 #endif
1650  !/
1651  !/ ------------------------------------------------------------------- /
1652  !
1653  INTEGER :: JSEA, ISEA, IX, IP
1654  real*8, PARAMETER :: dthr = 10e-6
1655 #ifdef W3_S
1656  CALL strace (ient, 'SETDEPTH')
1657 #endif
1658  iobdp = 1
1659  DO ip=1,nx
1660  IF (dw(ip) .LT. dmin + dthr) iobdp(ip) = 0
1661  !WRITE(*,*) ip, ip_glob, MAPSTA(1,IP_glob), IOBP(IP_glob), DW(ISEA), DMIN
1662  END DO
1663 
1664  END SUBROUTINE setdepth
1665 
1666  !/ ------------------------------------------------------------------- /
1667 
1668 END MODULE w3profsmd
1669 
1670 
1671 !--------------------------------------------------------------------------
1672 !--------------------------------------------------------------------------
1673 !--------------------------------------------------------------------------
1674 !------------------iterative solver ---------------------------------------
1675 !----------------------------------------------------------------------c
1676 ! S P A R S K I T c
1677 !----------------------------------------------------------------------c
1678 ! Basic Iterative Solvers with Reverse Communication c
1679 !----------------------------------------------------------------------c
1680 ! This file currently has several basic iterative linear system c
1681 ! solvers. They are: c
1682 ! CG -- Conjugate Gradient Method c
1683 ! CGNR -- Conjugate Gradient Method (Normal Residual equation) c
1684 ! BCG -- Bi-Conjugate Gradient Method c
1685 ! DBCG -- BCG with partial pivoting c
1686 ! BCGSTAB -- BCG stabilized c
1687 ! TFQMR -- Transpose-Free Quasi-Minimum Residual method c
1688 ! FOM -- Full Orthogonalization Method c
1689 ! GMRES -- Generalized Minimum RESidual method (no longer available) c
1690 ! FGMRES -- Flexible version of Generalized Minimum c
1691 ! RESidual method c
1692 ! DQGMRES -- Direct versions of Quasi Generalize Minimum c
1693 ! Residual method c
1694 !----------------------------------------------------------------------c
1695 ! They all have the following calling sequence:
1696 ! subroutine solver(n, rhs, sol, ipar, fpar, w)
1697 ! integer n, ipar(16)
1698 ! real*8 rhs(n), sol(n), fpar(16), w(*)
1699 ! Where
1700 ! (1) 'n' is the size of the linear system,
1701 ! (2) 'rhs' is the right-hand side of the linear system,
1702 ! (3) 'sol' is the solution to the linear system,
1703 ! (4) 'ipar' is an integer parameter array for the reverse
1704 ! communication protocol,
1705 ! (5) 'fpar' is an floating-point parameter array storing
1706 ! information to and from the iterative solvers.
1707 ! (6) 'w' is the work space (size is specified in ipar)
1708 !
1709 ! They are preconditioned iterative solvers with reverse
1710 ! communication. The preconditioners can be applied from either
1711 ! from left or right or both (specified by ipar(2), see below).
1712 !
1713 ! Author: Kesheng John Wu (kewu@mail.cs.umn.edu) 1993
1714 !
1715 ! NOTES:
1716 !
1717 ! (1) Work space required by each of the iterative solver
1718 ! routines is as follows:
1719 ! CG == 5 * n
1720 ! CGNR == 5 * n
1721 ! BCG == 7 * n
1722 ! DBCG == 11 * n
1723 ! BCGSTAB == 8 * n
1724 ! TFQMR == 11 * n
1725 ! FOM == (n+3)*(m+2) + (m+1)*m/2 (m = ipar(5), default m=15)
1726 ! GMRES == (n+3)*(m+2) + (m+1)*m/2 (m = ipar(5), default m=15)
1727 ! GMRES is no longer available
1728 ! FGMRES == 2*n*(m+1) + (m+1)*m/2 + 3*m + 2 (m = ipar(5),
1729 ! default m=15)
1730 ! DQGMRES == n + lb * (2*n+4) (lb=ipar(5)+1, default lb = 16)
1731 !
1732 ! (2) ALL iterative solvers require a user-supplied DOT-product
1733 ! routine named ddot. The prototype of ddot is
1734 !
1735 ! real*8 function ddot(n,x,y)
1736 ! integer n, ix, iy
1737 ! real*8 x(1+(n-1)*ix), y(1+(n-1)*iy)
1738 !
1739 ! This interface of ddot is exactly the same as that of
1740 ! DDOT (or SDOT if real == real*8) from BLAS-1. It should have
1741 ! same functionality as DDOT on a single processor machine. On a
1742 ! parallel/distributed environment, each processor can perform
1743 ! DDOT on the data it has, then perform a summation on all the
1744 ! partial results.
1745 !
1746 ! (3) To use this set of routines under SPMD/MIMD program paradigm,
1747 ! several things are to be noted: (a) 'n' should be the number of
1748 ! vector elements of 'rhs' that is present on the local processor.
1749 ! (b) if RHS(i) is on processor j, it is expected that SOL(i)
1750 ! will be on the same processor, i.e. the vectors are distributed
1751 ! to each processor in the same way. (c) the preconditioning and
1752 ! stopping criteria specifications have to be the same on all
1753 ! processor involved, ipar and fpar have to be the same on each
1754 ! processor. (d) ddot should be replaced by a distributed
1755 ! dot-product function.
1756 !
1757 ! ..................................................................
1758 ! Reverse Communication Protocols
1759 !
1760 ! When a reverse-communication routine returns, it could be either
1761 ! that the routine has terminated or it simply requires the caller
1762 ! to perform one matrix-vector multiplication. The possible matrices
1763 ! that involve in the matrix-vector multiplications are:
1764 ! A (the matrix of the linear system),
1765 ! A^T (A transposed),
1766 ! Ml^{-1} (inverse of the left preconditioner),
1767 ! Ml^{-T} (inverse of the left preconditioner transposed),
1768 ! Mr^{-1} (inverse of the right preconditioner),
1769 ! Mr^{-T} (inverse of the right preconditioner transposed).
1770 ! For all the matrix vector multiplication, v = A u. The input and
1771 ! output vectors are supposed to be part of the work space 'w', and
1772 ! the starting positions of them are stored in ipar(8:9), see below.
1773 !
1774 ! The array 'ipar' is used to store the information about the solver.
1775 ! Here is the list of what each element represents:
1776 !
1777 ! ipar(1) -- status of the call/return.
1778 ! A call to the solver with ipar(1) == 0 will initialize the
1779 ! iterative solver. On return from the iterative solver, ipar(1)
1780 ! carries the status flag which indicates the condition of the
1781 ! return. The status information is divided into two categories,
1782 ! (1) a positive value indicates the solver requires a matrix-vector
1783 ! multiplication,
1784 ! (2) a non-positive value indicates termination of the solver.
1785 ! Here is the current definition:
1786 ! 1 == request a matvec with A,
1787 ! 2 == request a matvec with A^T,
1788 ! 3 == request a left preconditioner solve (Ml^{-1}),
1789 ! 4 == request a left preconditioner transposed solve (Ml^{-T}),
1790 ! 5 == request a right preconditioner solve (Mr^{-1}),
1791 ! 6 == request a right preconditioner transposed solve (Mr^{-T}),
1792 ! 10 == request the caller to perform stopping test,
1793 ! 0 == normal termination of the solver, satisfied the stopping
1794 ! criteria,
1795 ! -1 == termination because iteration number is greater than the
1796 ! preset limit,
1797 ! -2 == return due to insufficient work space,
1798 ! -3 == return due to anticipated break-down / divide by zero,
1799 ! in the case where Arnoldi procedure is used, additional
1800 ! error code can be found in ipar(12), where ipar(12) is
1801 ! the error code of orthogonalization procedure MGSRO:
1802 ! -1: zero input vector
1803 ! -2: input vector contains abnormal numbers
1804 ! -3: input vector is a linear combination of others
1805 ! -4: trianguler system in GMRES/FOM/etc. has nul rank
1806 ! -4 == the values of fpar(1) and fpar(2) are both <= 0, the valid
1807 ! ranges are 0 <= fpar(1) < 1, 0 <= fpar(2), and they can
1808 ! not be zero at the same time
1809 ! -9 == while trying to detect a break-down, an abnormal number is
1810 ! detected.
1811 ! -10 == return due to some non-numerical reasons, e.g. invalid
1812 ! floating-point numbers etc.
1813 !
1814 ! ipar(2) -- status of the preconditioning:
1815 ! 0 == no preconditioning
1816 ! 1 == left preconditioning only
1817 ! 2 == right preconditioning only
1818 ! 3 == both left and right preconditioning
1819 !
1820 ! ipar(3) -- stopping criteria (details of this will be
1821 ! discussed later).
1822 !
1823 ! ipar(4) -- number of elements in the array 'w'. if this is less
1824 ! than the desired size, it will be over-written with the minimum
1825 ! requirement. In which case the status flag ipar(1) = -2.
1826 !
1827 ! ipar(5) -- size of the Krylov subspace (used by GMRES and its
1828 ! variants), e.g. GMRES(ipar(5)), FGMRES(ipar(5)),
1829 ! DQGMRES(ipar(5)).
1830 !
1831 ! ipar(6) -- maximum number of matrix-vector multiplies, if not a
1832 ! positive number the iterative solver will run till convergence
1833 ! test is satisfied.
1834 !
1835 ! ipar(7) -- current number of matrix-vector multiplies. It is
1836 ! incremented after each matrix-vector multiplication. If there
1837 ! is preconditioning, the counter is incremented after the
1838 ! preconditioning associated with each matrix-vector multiplication.
1839 !
1840 ! ipar(8) -- pointer to the input vector to the requested matrix-
1841 ! vector multiplication.
1842 !
1843 ! ipar(9) -- pointer to the output vector of the requested matrix-
1844 ! vector multiplication.
1845 !
1846 ! To perform v = A * u, it is assumed that u is w(ipar(8):ipar(8)+n-1)
1847 ! and v is stored as w(ipar(9):ipar(9)+n-1).
1848 !
1849 ! ipar(10) -- the return address (used to determine where to go to
1850 ! inside the iterative solvers after the caller has performed the
1851 ! requested services).
1852 !
1853 ! ipar(11) -- the result of the external convergence test
1854 ! On final return from the iterative solvers, this value
1855 ! will be reflected by ipar(1) = 0 (details discussed later)
1856 !
1857 ! ipar(12) -- error code of MGSRO, it is
1858 ! 1 if the input vector to MGSRO is linear combination
1859 ! of others,
1860 ! 0 if MGSRO was successful,
1861 ! -1 if the input vector to MGSRO is zero,
1862 ! -2 if the input vector contains invalid number.
1863 !
1864 ! ipar(13) -- number of initializations. During each initilization
1865 ! residual norm is computed directly from M_l(b - A x).
1866 !
1867 ! ipar(14) to ipar(16) are NOT defined, they are NOT USED by
1868 ! any iterative solver at this time.
1869 !
1870 ! Information about the error and tolerance are stored in the array
1871 ! FPAR. So are some internal variables that need to be saved from
1872 ! one iteration to the next one. Since the internal variables are
1873 ! not the same for each routine, we only define the common ones.
1874 !
1875 ! The first two are input parameters:
1876 ! fpar(1) -- the relative tolerance,
1877 ! fpar(2) -- the absolute tolerance (details discussed later),
1878 !
1879 ! When the iterative solver terminates,
1880 ! fpar(3) -- initial residual/error norm,
1881 ! fpar(4) -- target residual/error norm,
1882 ! fpar(5) -- current residual norm (if available),
1883 ! fpar(6) -- current residual/error norm,
1884 ! fpar(7) -- convergence rate,
1885 !
1886 ! fpar(8:10) are used by some of the iterative solvers to save some
1887 ! internal information.
1888 !
1889 ! fpar(11) -- number of floating-point operations. The iterative
1890 ! solvers will add the number of FLOPS they used to this variable,
1891 ! but they do NOT initialize it, nor add the number of FLOPS due to
1892 ! matrix-vector multiplications (since matvec is outside of the
1893 ! iterative solvers). To insure the correct FLOPS count, the
1894 ! caller should set fpar(11) = 0 before invoking the iterative
1895 ! solvers and account for the number of FLOPS from matrix-vector
1896 ! multiplications and preconditioners.
1897 !
1898 ! fpar(12:16) are not used in current implementation.
1899 !
1900 ! Whether the content of fpar(3), fpar(4) and fpar(6) are residual
1901 ! norms or error norms depends on ipar(3). If the requested
1902 ! convergence test is based on the residual norm, they will be
1903 ! residual norms. If the caller want to test convergence based the
1904 ! error norms (estimated by the norm of the modifications applied
1905 ! to the approximate solution), they will be error norms.
1906 ! Convergence rate is defined by (Fortran 77 statement)
1907 ! fpar(7) = log10(fpar(3) / fpar(6)) / (ipar(7)-ipar(13))
1908 ! If fpar(7) = 0.5, it means that approximately every 2 (= 1/0.5)
1909 ! steps the residual/error norm decrease by a factor of 10.
1910 !
1911 ! ..................................................................
1912 ! Stopping criteria,
1913 !
1914 ! An iterative solver may be terminated due to (1) satisfying
1915 ! convergence test; (2) exceeding iteration limit; (3) insufficient
1916 ! work space; (4) break-down. Checking of the work space is
1917 ! only done in the initialization stage, i.e. when it is called with
1918 ! ipar(1) == 0. A complete convergence test is done after each
1919 ! update of the solutions. Other conditions are monitored
1920 ! continuously.
1921 !
1922 ! With regard to the number of iteration, when ipar(6) is positive,
1923 ! the current iteration number will be checked against it. If
1924 ! current iteration number is greater the ipar(6) than the solver
1925 ! will return with status -1. If ipar(6) is not positive, the
1926 ! iteration will continue until convergence test is satisfied.
1927 !
1928 ! Two things may be used in the convergence tests, one is the
1929 ! residual 2-norm, the other one is 2-norm of the change in the
1930 ! approximate solution. The residual and the change in approximate
1931 ! solution are from the preconditioned system (if preconditioning
1932 ! is applied). The DQGMRES and TFQMR use two estimates for the
1933 ! residual norms. The estimates are not accurate, but they are
1934 ! acceptable in most of the cases. Generally speaking, the error
1935 ! of the TFQMR's estimate is less accurate.
1936 !
1937 ! The convergence test type is indicated by ipar(3). There are four
1938 ! type convergence tests: (1) tests based on the residual norm;
1939 ! (2) tests based on change in approximate solution; (3) caller
1940 ! does not care, the solver choose one from above two on its own;
1941 ! (4) caller will perform the test, the solver should simply continue.
1942 ! Here is the complete definition:
1943 ! -2 == || dx(i) || <= rtol * || rhs || + atol
1944 ! -1 == || dx(i) || <= rtol * || dx(1) || + atol
1945 ! 0 == solver will choose test 1 (next)
1946 ! 1 == || residual || <= rtol * || initial residual || + atol
1947 ! 2 == || residual || <= rtol * || rhs || + atol
1948 ! 999 == caller will perform the test
1949 ! where dx(i) denote the change in the solution at the ith update.
1950 ! ||.|| denotes 2-norm. rtol = fpar(1) and atol = fpar(2).
1951 !
1952 ! If the caller is to perform the convergence test, the outcome
1953 ! should be stored in ipar(11).
1954 ! ipar(11) = 0 -- failed the convergence test, iterative solver
1955 ! should continue
1956 ! ipar(11) = 1 -- satisfied convergence test, iterative solver
1957 ! should perform the clean up job and stop.
1958 !
1959 ! Upon return with ipar(1) = 10,
1960 ! ipar(8) points to the starting position of the change in
1961 ! solution Sx, where the actual solution of the step is
1962 ! x_j = x_0 + M_r^{-1} Sx.
1963 ! Exception: ipar(8) < 0, Sx = 0. It is mostly used by
1964 ! GMRES and variants to indicate (1) Sx was not necessary,
1965 ! (2) intermediate result of Sx is not computed.
1966 ! ipar(9) points to the starting position of a work vector that
1967 ! can be used by the caller.
1968 !
1969 ! NOTE: the caller should allow the iterative solver to perform
1970 ! clean up job after the external convergence test is satisfied,
1971 ! since some of the iterative solvers do not directly
1972 ! update the 'sol' array. A typical clean-up stage includes
1973 ! performing the final update of the approximate solution and
1974 ! computing the convergence information (e.g. values of fpar(3:7)).
1975 !
1976 ! NOTE: fpar(4) and fpar(6) are not set by the accelerators (the
1977 ! routines implemented here) if ipar(3) = 999.
1978 !
1979 ! ..................................................................
1980 ! Usage:
1981 !
1982 ! To start solving a linear system, the user needs to specify
1983 ! first 6 elements of the ipar, and first 2 elements of fpar.
1984 ! The user may optionally set fpar(11) = 0 if one wants to count
1985 ! the number of floating-point operations. (Note: the iterative
1986 ! solvers will only add the floating-point operations inside
1987 ! themselves, the caller will have to add the FLOPS from the
1988 ! matrix-vector multiplication routines and the preconditioning
1989 ! routines in order to account for all the arithmetic operations.)
1990 !
1991 ! Here is an example:
1992 ! ipar(1) = 0 ! always 0 to start an iterative solver
1993 ! ipar(2) = 2 ! right preconditioning
1994 ! ipar(3) = 1 ! use convergence test scheme 1
1995 ! ipar(4) = 10000 ! the 'w' has 10,000 elements
1996 ! ipar(5) = 10 ! use *GMRES(10) (e.g. FGMRES(10))
1997 ! ipar(6) = 100 ! use at most 100 matvec's
1998 ! fpar(1) = 1.0E-6 ! relative tolerance 1.0E-6
1999 ! fpar(2) = 1.0E-10 ! absolute tolerance 1.0E-10
2000 ! fpar(11) = 0.0 ! clearing the FLOPS counter
2001 !
2002 ! After the above specifications, one can start to call an iterative
2003 ! solver, say BCG. Here is a piece of pseudo-code showing how it can
2004 ! be done,
2005 !
2006 ! 10 call bcg(n,rhs,sol,ipar,fpar,w)
2007 ! if (ipar(1).eq.1) then
2008 ! call amux(n,w(ipar(8)),w(ipar(9)),a,ja,ia)
2009 ! goto 10
2010 ! else if (ipar(1).eq.2) then
2011 ! call atmux(n,w(ipar(8)),w(ipar(9)),a,ja,ia)
2012 ! goto 10
2013 ! else if (ipar(1).eq.3) then
2014 ! left preconditioner solver
2015 ! goto 10
2016 ! else if (ipar(1).eq.4) then
2017 ! left preconditioner transposed solve
2018 ! goto 10
2019 ! else if (ipar(1).eq.5) then
2020 ! right preconditioner solve
2021 ! goto 10
2022 ! else if (ipar(1).eq.6) then
2023 ! right preconditioner transposed solve
2024 ! goto 10
2025 ! else if (ipar(1).eq.10) then
2026 ! call my own stopping test routine
2027 ! goto 10
2028 ! else if (ipar(1).gt.0) then
2029 ! ipar(1) is an unspecified code
2030 ! else
2031 ! the iterative solver terminated with code = ipar(1)
2032 ! endif
2033 !
2034 ! This segment of pseudo-code assumes the matrix is in CSR format,
2035 ! AMUX and ATMUX are two routines from the SPARSKIT MATVEC module.
2036 ! They perform matrix-vector multiplications for CSR matrices,
2037 ! where w(ipar(8)) is the first element of the input vectors to the
2038 ! two routines, and w(ipar(9)) is the first element of the output
2039 ! vectors from them. For simplicity, we did not show the name of
2040 ! the routine that performs the preconditioning operations or the
2041 ! convergence tests.
2042 !-----------------------------------------------------------------------
2043 subroutine bcgstab(n, rhs, sol, ipar, fpar, w)
2044  implicit none
2045  integer n, ipar(16)
2046  real*8 rhs(n), sol(n), fpar(16), w(n,8)
2047  !-----------------------------------------------------------------------
2048  ! BCGSTAB --- Bi Conjugate Gradient stabilized (BCGSTAB)
2049  ! This is an improved BCG routine. (1) no matrix transpose is
2050  ! involved. (2) the convergence is smoother.
2051  !
2052  !
2053  ! Algorithm:
2054  ! Initialization - r = b - A x, r0 = r, p = r, rho = (r0, r),
2055  ! Iterate -
2056  ! (1) v = A p
2057  ! (2) alpha = rho / (r0, v)
2058  ! (3) s = r - alpha v
2059  ! (4) t = A s
2060  ! (5) omega = (t, s) / (t, t)
2061  ! (6) x = x + alpha * p + omega * s
2062  ! (7) r = s - omega * t
2063  ! convergence test goes here
2064  ! (8) beta = rho, rho = (r0, r), beta = rho * alpha / (beta * omega)
2065  ! p = r + beta * (p - omega * v)
2066  !
2067  ! in this routine, before successful return, the fpar's are
2068  ! fpar(3) == initial (preconditionied-)residual norm
2069  ! fpar(4) == target (preconditionied-)residual norm
2070  ! fpar(5) == current (preconditionied-)residual norm
2071  ! fpar(6) == current residual norm or error
2072  ! fpar(7) == current rho (rhok = <r, r0>)
2073  ! fpar(8) == alpha
2074  ! fpar(9) == omega
2075  !
2076  ! Usage of the work space W
2077  ! w(:, 1) = r0, the initial residual vector
2078  ! w(:, 2) = r, current residual vector
2079  ! w(:, 3) = s
2080  ! w(:, 4) = t
2081  ! w(:, 5) = v
2082  ! w(:, 6) = p
2083  ! w(:, 7) = tmp, used in preconditioning, etc.
2084  ! w(:, 8) = delta x, the correction to the answer is accumulated
2085  ! here, so that the right-preconditioning may be applied
2086  ! at the end
2087  !-----------------------------------------------------------------------
2088  ! external routines used
2089  !
2090  real*8 ddot
2091  logical stopbis, brkdn
2092  external ddot, stopbis, brkdn
2093  !
2094  real*8 one
2095  parameter(one=1.0d0)
2096  !
2097  ! local variables
2098  !
2099  integer i
2100  real*8 alpha,beta,rho,omega
2101  logical lp, rp
2102  save lp, rp
2103  !
2104  ! where to go
2105  !
2106  if (ipar(1).gt.0) then
2107  !!goto (10, 20, 40, 50, 60, 70, 80, 90, 100, 110) ipar(10)
2108  SELECT CASE (ipar(10))
2109  CASE (1)
2110  GOTO 10
2111  CASE (2)
2112  GOTO 20
2113  CASE (3)
2114  GOTO 40
2115  CASE (4)
2116  GOTO 50
2117  CASE (5)
2118  GOTO 60
2119  CASE (6)
2120  GOTO 70
2121  CASE (7)
2122  GOTO 80
2123  CASE (8)
2124  GOTO 90
2125  CASE (9)
2126  GOTO 100
2127  CASE (10)
2128  GOTO 110
2129  END SELECT
2130  else if (ipar(1).lt.0) then
2131  goto 900
2132  endif
2133  !
2134  ! call the initialization routine
2135  !
2136  call bisinit(ipar,fpar,8*n,1,lp,rp,w)
2137  if (ipar(1).lt.0) return
2138  !
2139  ! perform a matvec to compute the initial residual
2140  !
2141  ipar(1) = 1
2142  ipar(8) = 1
2143  ipar(9) = 1 + n
2144  do i = 1, n
2145  w(i,1) = sol(i)
2146  enddo
2147  ipar(10) = 1
2148  return
2149 10 ipar(7) = ipar(7) + 1
2150  ipar(13) = ipar(13) + 1
2151  do i = 1, n
2152  w(i,1) = rhs(i) - w(i,2)
2153  enddo
2154  fpar(11) = fpar(11) + n
2155  if (lp) then
2156  ipar(1) = 3
2157  ipar(10) = 2
2158  return
2159  endif
2160  !
2161 20 if (lp) then
2162  do i = 1, n
2163  w(i,1) = w(i,2)
2164  w(i,6) = w(i,2)
2165  enddo
2166  else
2167  do i = 1, n
2168  w(i,2) = w(i,1)
2169  w(i,6) = w(i,1)
2170  enddo
2171  endif
2172  !
2173  fpar(7) = ddot(n,w,w)
2174  fpar(11) = fpar(11) + 2 * n
2175  fpar(5) = sqrt(fpar(7))
2176  fpar(3) = fpar(5)
2177  if (abs(ipar(3)).eq.2) then
2178  fpar(4) = fpar(1) * sqrt(ddot(n,rhs,rhs)) + fpar(2)
2179  fpar(11) = fpar(11) + 2 * n
2180  else if (ipar(3).ne.999) then
2181  fpar(4) = fpar(1) * fpar(3) + fpar(2)
2182  endif
2183  if (ipar(3).ge.0) fpar(6) = fpar(5)
2184  if (ipar(3).ge.0 .and. fpar(5).le.fpar(4) .and. ipar(3).ne.999) then
2185  goto 900
2186  endif
2187  !
2188  ! beginning of the iterations
2189  !
2190  ! Step (1), v = A p
2191 30 if (rp) then
2192  ipar(1) = 5
2193  ipar(8) = 5*n+1
2194  if (lp) then
2195  ipar(9) = 4*n + 1
2196  else
2197  ipar(9) = 6*n + 1
2198  endif
2199  ipar(10) = 3
2200  return
2201  endif
2202  !
2203 40 ipar(1) = 1
2204  if (rp) then
2205  ipar(8) = ipar(9)
2206  else
2207  ipar(8) = 5*n+1
2208  endif
2209  if (lp) then
2210  ipar(9) = 6*n + 1
2211  else
2212  ipar(9) = 4*n + 1
2213  endif
2214  ipar(10) = 4
2215  return
2216 50 if (lp) then
2217  ipar(1) = 3
2218  ipar(8) = ipar(9)
2219  ipar(9) = 4*n + 1
2220  ipar(10) = 5
2221  return
2222  endif
2223  !
2224 60 ipar(7) = ipar(7) + 1
2225  !
2226  ! step (2)
2227  alpha = ddot(n,w(1,1),w(1,5))
2228  fpar(11) = fpar(11) + 2 * n
2229  if (brkdn(alpha, ipar)) goto 900
2230  alpha = fpar(7) / alpha
2231  fpar(8) = alpha
2232  !
2233  ! step (3)
2234  do i = 1, n
2235  w(i,3) = w(i,2) - alpha * w(i,5)
2236  enddo
2237  fpar(11) = fpar(11) + 2 * n
2238  !
2239  ! Step (4): the second matvec -- t = A s
2240  !
2241  if (rp) then
2242  ipar(1) = 5
2243  ipar(8) = n+n+1
2244  if (lp) then
2245  ipar(9) = ipar(8)+n
2246  else
2247  ipar(9) = 6*n + 1
2248  endif
2249  ipar(10) = 6
2250  return
2251  endif
2252  !
2253 70 ipar(1) = 1
2254  if (rp) then
2255  ipar(8) = ipar(9)
2256  else
2257  ipar(8) = n+n+1
2258  endif
2259  if (lp) then
2260  ipar(9) = 6*n + 1
2261  else
2262  ipar(9) = 3*n + 1
2263  endif
2264  ipar(10) = 7
2265  return
2266 80 if (lp) then
2267  ipar(1) = 3
2268  ipar(8) = ipar(9)
2269  ipar(9) = 3*n + 1
2270  ipar(10) = 8
2271  return
2272  endif
2273 90 ipar(7) = ipar(7) + 1
2274  !
2275  ! step (5)
2276  omega = ddot(n,w(1,4),w(1,4))
2277  fpar(11) = fpar(11) + n + n
2278  if (brkdn(omega,ipar)) goto 900
2279  omega = ddot(n,w(1,4),w(1,3)) / omega
2280  fpar(11) = fpar(11) + n + n
2281  if (brkdn(omega,ipar)) goto 900
2282  fpar(9) = omega
2283  alpha = fpar(8)
2284  !
2285  ! step (6) and (7)
2286  do i = 1, n
2287  w(i,7) = alpha * w(i,6) + omega * w(i,3)
2288  w(i,8) = w(i,8) + w(i,7)
2289  w(i,2) = w(i,3) - omega * w(i,4)
2290  enddo
2291  fpar(11) = fpar(11) + 6 * n + 1
2292  !
2293  ! convergence test
2294  if (ipar(3).eq.999) then
2295  ipar(1) = 10
2296  ipar(8) = 7*n + 1
2297  ipar(9) = 6*n + 1
2298  ipar(10) = 9
2299  return
2300  endif
2301  if (stopbis(n,ipar,2,fpar,w(1,2),w(1,7),one)) goto 900
2302 100 if (ipar(3).eq.999.and.ipar(11).eq.1) goto 900
2303  !
2304  ! step (8): computing new p and rho
2305  !
2306  rho = fpar(7)
2307  fpar(7) = ddot(n,w(1,2),w(1,1))
2308  omega = fpar(9)
2309  beta = fpar(7) * fpar(8) / (fpar(9) * rho)
2310  do i = 1, n
2311  w(i,6) = w(i,2) + beta * (w(i,6) - omega * w(i,5))
2312  enddo
2313  fpar(11) = fpar(11) + 6 * n + 3
2314  if (brkdn(fpar(7),ipar)) goto 900
2315  !
2316  ! end of an iteration
2317  !
2318  goto 30
2319  !
2320  ! some clean up job to do
2321  !
2322 900 if (rp) then
2323  if (ipar(1).lt.0) ipar(12) = ipar(1)
2324  ipar(1) = 5
2325  ipar(8) = 7*n + 1
2326  ipar(9) = ipar(8) - n
2327  ipar(10) = 10
2328  return
2329  endif
2330 
2331 110 if (rp) then
2332  call tidycg(n,ipar,fpar,sol,w(1,7))
2333  else
2334  call tidycg(n,ipar,fpar,sol,w(1,8))
2335  endif
2336  !
2337  return
2338  !-----end-of-bcgstab
2339 end subroutine bcgstab
2340 !-----------------------------------------------------------------------
2341 subroutine implu(np,umm,beta,ypiv,u,permut,full)
2342  real*8 umm,beta,ypiv(*),u(*),x, xpiv
2343  logical full, perm, permut(*)
2344  integer np,k,npm1
2345  !-----------------------------------------------------------------------
2346  ! performs implicitly one step of the lu factorization of a
2347  ! banded hessenberg matrix.
2348  !-----------------------------------------------------------------------
2349  if (np .le. 1) goto 12
2350  npm1 = np - 1
2351  !
2352  ! -- perform previous step of the factorization-
2353  !
2354  do k=1,npm1
2355  if (.not. permut(k)) goto 5
2356  x=u(k)
2357  u(k) = u(k+1)
2358  u(k+1) = x
2359 5 u(k+1) = u(k+1) - ypiv(k)*u(k)
2360  end do
2361  !-----------------------------------------------------------------------
2362  ! now determine pivotal information to be used in the next call
2363  !-----------------------------------------------------------------------
2364 12 umm = u(np)
2365  perm = (beta .gt. abs(umm))
2366  if (.not. perm) goto 4
2367  xpiv = umm / beta
2368  u(np) = beta
2369  goto 8
2370 4 xpiv = beta/umm
2371 8 permut(np) = perm
2372  ypiv(np) = xpiv
2373  if (.not. full) return
2374  ! shift everything up if full...
2375  do k=1,npm1
2376  ypiv(k) = ypiv(k+1)
2377  permut(k) = permut(k+1)
2378  end do
2379  return
2380  !-----end-of-implu
2381 end subroutine implu
2382 !-----------------------------------------------------------------------
2383 subroutine uppdir(n,p,np,lbp,indp,y,u,usav,flops)
2384  implicit none
2385 
2386  integer :: k,np,n,npm1,j,ju,indp,lbp
2387  real*8 :: p(n,lbp), y(*), u(*), usav(*), x, flops
2388 
2389  !-----------------------------------------------------------------------
2390  ! updates the conjugate directions p given the upper part of the
2391  ! banded upper triangular matrix u. u contains the non zero
2392  ! elements of the column of the triangular matrix..
2393  !-----------------------------------------------------------------------
2394  real*8 zero
2395  parameter(zero=0.0d0)
2396  !
2397  npm1=np-1
2398  if (np .le. 1) goto 12
2399  j=indp
2400  ju = npm1
2401 10 if (j .le. 0) j=lbp
2402  x = u(ju) /usav(j)
2403  if (x .eq. zero) goto 115
2404  do k=1,n
2405  y(k) = y(k) - x*p(k,j)
2406  end do
2407  flops = flops + 2*n
2408 115 j = j-1
2409  ju = ju -1
2410  if (ju .ge. 1) goto 10
2411 12 indp = indp + 1
2412  if (indp .gt. lbp) indp = 1
2413  usav(indp) = u(np)
2414  do k=1,n
2415  p(k,indp) = y(k)
2416  end do
2417  return
2418  !-----------------------------------------------------------------------
2419  !-------end-of-uppdir---------------------------------------------------
2420 end subroutine uppdir
2421 
2422 subroutine givens(x,y,c,s)
2423  implicit none
2424 
2425  real*8 :: x,y,c,s
2426  !-----------------------------------------------------------------------
2427  ! Given x and y, this subroutine generates a Givens' rotation c, s.
2428  ! And apply the rotation on (x,y) ==> (sqrt(x**2 + y**2), 0).
2429  ! (See P 202 of "matrix computation" by Golub and van Loan.)
2430  !-----------------------------------------------------------------------
2431  real*8 :: t,one,zero
2432  parameter(zero=0.0d0,one=1.0d0)
2433  !
2434  if (x.eq.zero .and. y.eq.zero) then
2435  c = one
2436  s = zero
2437  else if (abs(y).gt.abs(x)) then
2438  t = x / y
2439  x = sqrt(one+t*t)
2440  s = sign(one / x, y)
2441  c = t*s
2442  else if (abs(y).le.abs(x)) then
2443  t = y / x
2444  y = sqrt(one+t*t)
2445  c = sign(one / y, x)
2446  s = t*c
2447  else
2448  !
2449  ! X or Y must be an invalid floating-point number, set both to zero
2450  !
2451  x = zero
2452  y = zero
2453  c = one
2454  s = zero
2455  endif
2456  x = abs(x*y)
2457  !
2458  ! end of givens
2459  !
2460  return
2461 end subroutine givens
2462 !-----end-of-givens
2463 !-----------------------------------------------------------------------
2464 logical function stopbis(n,ipar,mvpi,fpar,r,delx,sx)
2465  implicit none
2466  integer n,mvpi,ipar(16)
2467  real*8 fpar(16), r(n), delx(n), sx, ddot
2468  external ddot
2469  !-----------------------------------------------------------------------
2470  ! function for determining the stopping criteria. return value of
2471  ! true if the stopbis criteria is satisfied.
2472  !-----------------------------------------------------------------------
2473  if (ipar(11) .eq. 1) then
2474  stopbis = .true.
2475  else
2476  stopbis = .false.
2477  endif
2478  if (ipar(6).gt.0 .and. ipar(7).ge.ipar(6)) then
2479  ipar(1) = -1
2480  stopbis = .true.
2481  endif
2482  if (stopbis) return
2483  !
2484  ! computes errors
2485  !
2486  fpar(5) = sqrt(ddot(n,r,r))
2487  fpar(11) = fpar(11) + 2 * n
2488  if (ipar(3).lt.0) then
2489  !
2490  ! compute the change in the solution vector
2491  !
2492  fpar(6) = sx * sqrt(ddot(n,delx,delx))
2493  fpar(11) = fpar(11) + 2 * n
2494  if (ipar(7).lt.mvpi+mvpi+1) then
2495  !
2496  ! if this is the end of the first iteration, set fpar(3:4)
2497  !
2498  fpar(3) = fpar(6)
2499  if (ipar(3).eq.-1) then
2500  fpar(4) = fpar(1) * fpar(3) + fpar(2)
2501  endif
2502  endif
2503  else
2504  fpar(6) = fpar(5)
2505  endif
2506  !
2507  ! .. the test is struct this way so that when the value in fpar(6)
2508  ! is not a valid number, STOPBIS is set to .true.
2509  !
2510  if (fpar(6).gt.fpar(4)) then
2511  stopbis = .false.
2512  ipar(11) = 0
2513  else
2514  stopbis = .true.
2515  ipar(11) = 1
2516  endif
2517  !
2518  return
2519 end function stopbis
2520 !-----end-of-stopbis
2521 !-----------------------------------------------------------------------
2522 subroutine tidycg(n,ipar,fpar,sol,delx)
2523  implicit none
2524  integer i,n,ipar(16)
2525  real*8 fpar(16),sol(n),delx(n)
2526  !-----------------------------------------------------------------------
2527  ! Some common operations required before terminating the CG routines
2528  !-----------------------------------------------------------------------
2529  real*8 zero
2530  parameter(zero=0.0d0)
2531  !
2532  if (ipar(12).ne.0) then
2533  ipar(1) = ipar(12)
2534  else if (ipar(1).gt.0) then
2535  if ((ipar(3).eq.999 .and. ipar(11).eq.1) .or. &
2536  & fpar(6).le.fpar(4)) then
2537  ipar(1) = 0
2538  else if (ipar(7).ge.ipar(6) .and. ipar(6).gt.0) then
2539  ipar(1) = -1
2540  else
2541  ipar(1) = -10
2542  endif
2543  endif
2544  if (fpar(3).gt.zero .and. fpar(6).gt.zero .and. ipar(7).gt.ipar(13)) then
2545  fpar(7) = log10(fpar(3) / fpar(6)) / dble(ipar(7)-ipar(13))
2546  else
2547  fpar(7) = zero
2548  endif
2549  do i = 1, n
2550  sol(i) = sol(i) + delx(i)
2551  enddo
2552  return
2553 end subroutine tidycg
2554 !-----end-of-tidycg
2555 !-----------------------------------------------------------------------
2556 logical function brkdn(alpha, ipar)
2557  implicit none
2558  integer ipar(16)
2559  real*8 alpha, beta, zero, one
2560  parameter(zero=0.0d0, one=1.0d0)
2561  !-----------------------------------------------------------------------
2562  ! test whether alpha is zero or an abnormal number, if yes,
2563  ! this routine will return .true.
2564  !
2565  ! If alpha == 0, ipar(1) = -3,
2566  ! if alpha is an abnormal number, ipar(1) = -9.
2567  !-----------------------------------------------------------------------
2568  brkdn = .false.
2569  if (alpha.gt.zero) then
2570  beta = one / alpha
2571  if (.not. beta.gt.zero) then
2572  brkdn = .true.
2573  ipar(1) = -9
2574  endif
2575  else if (alpha.lt.zero) then
2576  beta = one / alpha
2577  if (.not. beta.lt.zero) then
2578  brkdn = .true.
2579  ipar(1) = -9
2580  endif
2581  else if (alpha.eq.zero) then
2582  brkdn = .true.
2583  ipar(1) = -3
2584  else
2585  brkdn = .true.
2586  ipar(1) = -9
2587  endif
2588  return
2589 end function brkdn
2590 !-----end-of-brkdn
2591 !-----------------------------------------------------------------------
2592 subroutine bisinit(ipar,fpar,wksize,dsc,lp,rp,wk)
2593  implicit none
2594  integer i,ipar(16),wksize,dsc
2595  logical lp,rp
2596  real*8 fpar(16),wk(*)
2597  !-----------------------------------------------------------------------
2598  ! some common initializations for the iterative solvers
2599  !-----------------------------------------------------------------------
2600  real*8 zero, one
2601  parameter(zero=0.0d0, one=1.0d0)
2602  !
2603  ! ipar(1) = -2 inidcate that there are not enough space in the work
2604  ! array
2605  !
2606  if (ipar(4).lt.wksize) then
2607  ipar(1) = -2
2608  ipar(4) = wksize
2609  return
2610  endif
2611  !
2612  if (ipar(2).gt.2) then
2613  lp = .true.
2614  rp = .true.
2615  else if (ipar(2).eq.2) then
2616  lp = .false.
2617  rp = .true.
2618  else if (ipar(2).eq.1) then
2619  lp = .true.
2620  rp = .false.
2621  else
2622  lp = .false.
2623  rp = .false.
2624  endif
2625  if (ipar(3).eq.0) ipar(3) = dsc
2626  ! .. clear the ipar elements used
2627  ipar(7) = 0
2628  ipar(8) = 0
2629  ipar(9) = 0
2630  ipar(10) = 0
2631  ipar(11) = 0
2632  ipar(12) = 0
2633  ipar(13) = 0
2634  !
2635  ! fpar(1) must be between (0, 1), fpar(2) must be positive,
2636  ! fpar(1) and fpar(2) can NOT both be zero
2637  ! Normally return ipar(1) = -4 to indicate any of above error
2638  !
2639  if (fpar(1).lt.zero .or. fpar(1).ge.one .or. fpar(2).lt.zero .or. &
2640  & (fpar(1).eq.zero .and. fpar(2).eq.zero)) then
2641  if (ipar(1).eq.0) then
2642  ipar(1) = -4
2643  return
2644  else
2645  fpar(1) = 1.0d-6
2646  fpar(2) = 1.0d-16
2647  endif
2648  endif
2649  ! .. clear the fpar elements
2650  do i = 3, 10
2651  fpar(i) = zero
2652  enddo
2653  if (fpar(11).lt.zero) fpar(11) = zero
2654  ! .. clear the used portion of the work array to zero
2655  do i = 1, wksize
2656  wk(i) = zero
2657  enddo
2658  !
2659  return
2660  !-----end-of-bisinit
2661 end subroutine bisinit
2662 !-----------------------------------------------------------------------
2663 subroutine mgsro(full,lda,n,m,ind,ops,vec,hh,ierr)
2664  implicit none
2665  logical full
2666  integer lda,m,n,ind,ierr
2667  real*8 ops,hh(m),vec(lda,m)
2668  !-----------------------------------------------------------------------
2669  ! MGSRO -- Modified Gram-Schmidt procedure with Selective Re-
2670  ! Orthogonalization
2671  ! The ind'th vector of VEC is orthogonalized against the rest of
2672  ! the vectors.
2673  !
2674  ! The test for performing re-orthogonalization is performed for
2675  ! each indivadual vectors. If the cosine between the two vectors
2676  ! is greater than 0.99 (REORTH = 0.99**2), re-orthogonalization is
2677  ! performed. The norm of the 'new' vector is kept in variable NRM0,
2678  ! and updated after operating with each vector.
2679  !
2680  ! full -- .ture. if it is necessary to orthogonalize the ind'th
2681  ! against all the vectors vec(:,1:ind-1), vec(:,ind+2:m)
2682  ! .false. only orthogonalize againt vec(:,1:ind-1)
2683  ! lda -- the leading dimension of VEC
2684  ! n -- length of the vector in VEC
2685  ! m -- number of vectors can be stored in VEC
2686  ! ind -- index to the vector to be changed
2687  ! ops -- operation counts
2688  ! vec -- vector of LDA X M storing the vectors
2689  ! hh -- coefficient of the orthogonalization
2690  ! ierr -- error code
2691  ! 0 : successful return
2692  ! -1: zero input vector
2693  ! -2: input vector contains abnormal numbers
2694  ! -3: input vector is a linear combination of others
2695  !
2696  ! External routines used: real*8 ddot
2697  !-----------------------------------------------------------------------
2698  integer i,k
2699  real*8 nrm0, nrm1, fct, thr, ddot, zero, one, reorth
2700  parameter(zero=0.0d0, one=1.0d0, reorth=0.98d0)
2701  external ddot
2702  !
2703  ! compute the norm of the input vector
2704  !
2705  nrm0 = ddot(n,vec(1,ind),vec(1,ind))
2706  ops = ops + n + n
2707  thr = nrm0 * reorth
2708  if (nrm0.le.zero) then
2709  ierr = - 1
2710  return
2711  else if (nrm0.gt.zero .and. one/nrm0.gt.zero) then
2712  ierr = 0
2713  else
2714  ierr = -2
2715  return
2716  endif
2717  !
2718  ! Modified Gram-Schmidt loop
2719  !
2720  if (full) then
2721  do i = ind+1, m
2722  fct = ddot(n,vec(1,ind),vec(1,i))
2723  hh(i) = fct
2724  do k = 1, n
2725  vec(k,ind) = vec(k,ind) - fct * vec(k,i)
2726  end do
2727  ops = ops + 4 * n + 2
2728  if (fct*fct.gt.thr) then
2729  fct = ddot(n,vec(1,ind),vec(1,i))
2730  hh(i) = hh(i) + fct
2731  do k = 1, n
2732  vec(k,ind) = vec(k,ind) - fct * vec(k,i)
2733  end do
2734  ops = ops + 4*n + 1
2735  endif
2736  nrm0 = nrm0 - hh(i) * hh(i)
2737  if (nrm0.lt.zero) nrm0 = zero
2738  thr = nrm0 * reorth
2739  end do
2740  endif
2741  !
2742  do i = 1, ind-1
2743  fct = ddot(n,vec(1,ind),vec(1,i))
2744  hh(i) = fct
2745  do k = 1, n
2746  vec(k,ind) = vec(k,ind) - fct * vec(k,i)
2747  end do
2748  ops = ops + 4 * n + 2
2749  if (fct*fct.gt.thr) then
2750  fct = ddot(n,vec(1,ind),vec(1,i))
2751  hh(i) = hh(i) + fct
2752  do k = 1, n
2753  vec(k,ind) = vec(k,ind) - fct * vec(k,i)
2754  end do
2755  ops = ops + 4*n + 1
2756  endif
2757  nrm0 = nrm0 - hh(i) * hh(i)
2758  if (nrm0.lt.zero) nrm0 = zero
2759  thr = nrm0 * reorth
2760  end do
2761  !
2762  ! test the resulting vector
2763  !
2764  nrm1 = sqrt(ddot(n,vec(1,ind),vec(1,ind)))
2765  ops = ops + n + n
2766  hh(ind) = nrm1 ! statement label 75
2767  if (nrm1.le.zero) then
2768  ierr = -3
2769  return
2770  endif
2771  !
2772  ! scale the resulting vector
2773  !
2774  fct = one / nrm1
2775  do k = 1, n
2776  vec(k,ind) = vec(k,ind) * fct
2777  end do
2778  ops = ops + n + 1
2779  !
2780  ! normal return
2781  !
2782  ierr = 0
2783  return
2784  ! end subroutine mgsro
2785 end subroutine mgsro
2786 !----------------------------------------------------------------------c
2787 ! S P A R S K I T c
2788 !----------------------------------------------------------------------c
2789 ! BASIC MATRIX-VECTOR OPERATIONS - MATVEC MODULE c
2790 ! Matrix-vector Mulitiplications and Triang. Solves c
2791 !----------------------------------------------------------------------c
2792 ! contents: (as of Nov 18, 1991) c
2793 !---------- c
2794 ! 1) Matrix-vector products: c
2795 !--------------------------- c
2796 ! amux : A times a vector. Compressed Sparse Row (CSR) format. c
2797 ! amuxms: A times a vector. Modified Compress Sparse Row format. c
2798 ! atmux : Transp(A) times a vector. CSR format. c
2799 ! atmuxr: Transp(A) times a vector. CSR format. A rectangular. c
2800 ! amuxe : A times a vector. Ellpack/Itpack (ELL) format. c
2801 ! amuxd : A times a vector. Diagonal (DIA) format. c
2802 ! amuxj : A times a vector. Jagged Diagonal (JAD) format. c
2803 ! vbrmv : Sparse matrix-full vector product, in VBR format c
2804 ! c
2805 ! 2) Triangular system solutions: c
2806 !------------------------------- c
2807 ! lsol : Unit Lower Triang. solve. Compressed Sparse Row (CSR) format.c
2808 ! ldsol : Lower Triang. solve. Modified Sparse Row (MSR) format. c
2809 ! lsolc : Unit Lower Triang. solve. Comp. Sparse Column (CSC) format. c
2810 ! ldsolc: Lower Triang. solve. Modified Sparse Column (MSC) format. c
2811 ! ldsoll: Lower Triang. solve with level scheduling. MSR format. c
2812 ! usol : Unit Upper Triang. solve. Compressed Sparse Row (CSR) format.c
2813 ! udsol : Upper Triang. solve. Modified Sparse Row (MSR) format. c
2814 ! usolc : Unit Upper Triang. solve. Comp. Sparse Column (CSC) format. c
2815 ! udsolc: Upper Triang. solve. Modified Sparse Column (MSC) format. c
2816 !----------------------------------------------------------------------c
2817 ! 1) M A T R I X B Y V E C T O R P R O D U C T S c
2818 !----------------------------------------------------------------------c
2819 subroutine amux (n, x, y, a,ja,ia)
2820  real*8 x(*), y(*), a(*)
2821  integer n, ja(*), ia(*)
2822  !-----------------------------------------------------------------------
2823  ! A times a vector
2824  !-----------------------------------------------------------------------
2825  ! multiplies a matrix by a vector using the dot product form
2826  ! Matrix A is stored in compressed sparse row storage.
2827  !
2828  ! on entry:
2829  !----------
2830  ! n = row dimension of A
2831  ! x = real array of length equal to the column dimension of
2832  ! the A matrix.
2833  ! a, ja,
2834  ! ia = input matrix in compressed sparse row format.
2835  !
2836  ! on return:
2837  !-----------
2838  ! y = real array of length n, containing the product y=Ax
2839  !
2840  !-----------------------------------------------------------------------
2841  ! local variables
2842  !
2843  real*8 t
2844  integer i, k
2845  !-----------------------------------------------------------------------
2846  do i = 1,n
2847  !
2848  ! compute the inner product of row i with vector x
2849  !
2850  t = 0.0d0
2851  do k=ia(i), ia(i+1)-1
2852  t = t + a(k)*x(ja(k))
2853  end do
2854  !
2855  ! store result in y(i)
2856  !
2857  y(i) = t
2858  end do
2859  !
2860  return
2861  !---------end-of-amux---------------------------------------------------
2862  !-----------------------------------------------------------------------
2863 end subroutine amux
2864 !-----------------------------------------------------------------------
2865 subroutine amuxms (n, x, y, a,ja)
2866  real*8 x(*), y(*), a(*)
2867  integer n, ja(*)
2868  !-----------------------------------------------------------------------
2869  ! A times a vector in MSR format
2870  !-----------------------------------------------------------------------
2871  ! multiplies a matrix by a vector using the dot product form
2872  ! Matrix A is stored in Modified Sparse Row storage.
2873  !
2874  ! on entry:
2875  !----------
2876  ! n = row dimension of A
2877  ! x = real array of length equal to the column dimension of
2878  ! the A matrix.
2879  ! a, ja,= input matrix in modified compressed sparse row format.
2880  !
2881  ! on return:
2882  !-----------
2883  ! y = real array of length n, containing the product y=Ax
2884  !
2885  !-----------------------------------------------------------------------
2886  ! local variables
2887  !
2888  integer i, k
2889  !-----------------------------------------------------------------------
2890  do i=1, n
2891  y(i) = a(i)*x(i)
2892  end do
2893  do i = 1,n
2894  !
2895  ! compute the inner product of row i with vector x
2896  !
2897  do k=ja(i), ja(i+1)-1
2898  y(i) = y(i) + a(k) *x(ja(k))
2899  end do
2900  end do
2901  !
2902  return
2903  !---------end-of-amuxm--------------------------------------------------
2904  !-----------------------------------------------------------------------
2905 end subroutine amuxms
2906 !-----------------------------------------------------------------------
2907 subroutine atmux (n, x, y, a, ja, ia)
2908  real*8 x(*), y(*), a(*)
2909  integer n, ia(*), ja(*)
2910  !-----------------------------------------------------------------------
2911  ! transp( A ) times a vector
2912  !-----------------------------------------------------------------------
2913  ! multiplies the transpose of a matrix by a vector when the original
2914  ! matrix is stored in compressed sparse row storage. Can also be
2915  ! viewed as the product of a matrix by a vector when the original
2916  ! matrix is stored in the compressed sparse column format.
2917  !-----------------------------------------------------------------------
2918  !
2919  ! on entry:
2920  !----------
2921  ! n = row dimension of A
2922  ! x = real array of length equal to the column dimension of
2923  ! the A matrix.
2924  ! a, ja,
2925  ! ia = input matrix in compressed sparse row format.
2926  !
2927  ! on return:
2928  !-----------
2929  ! y = real array of length n, containing the product y=transp(A)*x
2930  !
2931  !-----------------------------------------------------------------------
2932  ! local variables
2933  !
2934  integer i, k
2935  !-----------------------------------------------------------------------
2936  !
2937  ! zero out output vector
2938  !
2939  do i=1,n
2940  y(i) = 0.0
2941  end do
2942  !
2943  ! loop over the rows
2944  !
2945  do i = 1,n
2946  do k=ia(i), ia(i+1)-1
2947  y(ja(k)) = y(ja(k)) + x(i)*a(k)
2948  end do
2949  end do
2950  !
2951  return
2952  !-------------end-of-atmux----------------------------------------------
2953  !-----------------------------------------------------------------------
2954 end subroutine atmux
2955 !-----------------------------------------------------------------------
2956 subroutine atmuxr (m, n, x, y, a, ja, ia)
2957  real*8 x(*), y(*), a(*)
2958  integer m, n, ia(*), ja(*)
2959  !-----------------------------------------------------------------------
2960  ! transp( A ) times a vector, A can be rectangular
2961  !-----------------------------------------------------------------------
2962  ! See also atmux. The essential difference is how the solution vector
2963  ! is initially zeroed. If using this to multiply rectangular CSC
2964  ! matrices by a vector, m number of rows, n is number of columns.
2965  !-----------------------------------------------------------------------
2966  !
2967  ! on entry:
2968  !----------
2969  ! m = column dimension of A
2970  ! n = row dimension of A
2971  ! x = real array of length equal to the column dimension of
2972  ! the A matrix.
2973  ! a, ja,
2974  ! ia = input matrix in compressed sparse row format.
2975  !
2976  ! on return:
2977  !-----------
2978  ! y = real array of length n, containing the product y=transp(A)*x
2979  !
2980  !-----------------------------------------------------------------------
2981  ! local variables
2982  !
2983  integer i, k
2984  !-----------------------------------------------------------------------
2985  !
2986  ! zero out output vector
2987  !
2988  do i=1,m
2989  y(i) = 0.0
2990  end do
2991  !
2992  ! loop over the rows
2993  !
2994  do i = 1,n
2995  do k=ia(i), ia(i+1)-1
2996  y(ja(k)) = y(ja(k)) + x(i)*a(k)
2997  end do
2998  end do
2999  !
3000  return
3001  !-------------end-of-atmuxr---------------------------------------------
3002  !-----------------------------------------------------------------------
3003 end subroutine atmuxr
3004 !-----------------------------------------------------------------------
3005 subroutine amuxe (n,x,y,na,ncol,a,ja)
3006  implicit none
3007 
3008  integer :: n, na, ncol, ja(na,*)
3009  real*8 :: x(n), y(n), a(na,*)
3010 
3011  !-----------------------------------------------------------------------
3012  ! A times a vector in Ellpack Itpack format (ELL)
3013  !-----------------------------------------------------------------------
3014  ! multiplies a matrix by a vector when the original matrix is stored
3015  ! in the ellpack-itpack sparse format.
3016  !-----------------------------------------------------------------------
3017  !
3018  ! on entry:
3019  !----------
3020  ! n = row dimension of A
3021  ! x = real array of length equal to the column dimension of
3022  ! the A matrix.
3023  ! na = integer. The first dimension of arrays a and ja
3024  ! as declared by the calling program.
3025  ! ncol = integer. The number of active columns in array a.
3026  ! (i.e., the number of generalized diagonals in matrix.)
3027  ! a, ja = the real and integer arrays of the itpack format
3028  ! (a(i,k),k=1,ncol contains the elements of row i in matrix
3029  ! ja(i,k),k=1,ncol contains their column numbers)
3030  !
3031  ! on return:
3032  !-----------
3033  ! y = real array of length n, containing the product y=y=A*x
3034  !
3035  !-----------------------------------------------------------------------
3036  ! local variables
3037  !
3038  integer i, j
3039  !-----------------------------------------------------------------------
3040  do i=1, n
3041  y(i) = 0.0
3042  end do
3043  do j=1,ncol
3044  do i = 1,n
3045  y(i) = y(i)+a(i,j)*x(ja(i,j))
3046  end do
3047  end do
3048  !
3049  return
3050  !--------end-of-amuxe---------------------------------------------------
3051  !-----------------------------------------------------------------------
3052 end subroutine amuxe
3053 !-----------------------------------------------------------------------
3054 subroutine amuxd (n,x,y,diag,ndiag,idiag,ioff)
3055  integer n, ndiag, idiag, ioff(idiag)
3056  real*8 x(n), y(n), diag(ndiag,idiag)
3057  !-----------------------------------------------------------------------
3058  ! A times a vector in Diagonal storage format (DIA)
3059  !-----------------------------------------------------------------------
3060  ! multiplies a matrix by a vector when the original matrix is stored
3061  ! in the diagonal storage format.
3062  !-----------------------------------------------------------------------
3063  !
3064  ! on entry:
3065  !----------
3066  ! n = row dimension of A
3067  ! x = real array of length equal to the column dimension of
3068  ! the A matrix.
3069  ! ndiag = integer. The first dimension of array adiag as declared in
3070  ! the calling program.
3071  ! idiag = integer. The number of diagonals in the matrix.
3072  ! diag = real array containing the diagonals stored of A.
3073  ! idiag = number of diagonals in matrix.
3074  ! diag = real array of size (ndiag x idiag) containing the diagonals
3075  !
3076  ! ioff = integer array of length idiag, containing the offsets of the
3077  ! diagonals of the matrix:
3078  ! diag(i,k) contains the element a(i,i+ioff(k)) of the matrix.
3079  !
3080  ! on return:
3081  !-----------
3082  ! y = real array of length n, containing the product y=A*x
3083  !
3084  !-----------------------------------------------------------------------
3085  ! local variables
3086  !
3087  integer j, k, io, i1, i2
3088  !-----------------------------------------------------------------------
3089  do j=1, n
3090  y(j) = 0.0d0
3091  end do
3092  do j=1, idiag
3093  io = ioff(j)
3094  i1 = max0(1,1-io)
3095  i2 = min0(n,n-io)
3096  do k=i1, i2
3097  y(k) = y(k)+diag(k,j)*x(k+io)
3098  end do
3099  end do
3100  !
3101  return
3102  !----------end-of-amuxd-------------------------------------------------
3103  !-----------------------------------------------------------------------
3104 end subroutine amuxd
3105 !-----------------------------------------------------------------------
3106 subroutine amuxj (n, x, y, jdiag, a, ja, ia)
3107  integer n, jdiag, ja(*), ia(*)
3108  real*8 x(n), y(n), a(*)
3109  !-----------------------------------------------------------------------
3110  ! A times a vector in Jagged-Diagonal storage format (JAD)
3111  !-----------------------------------------------------------------------
3112  ! multiplies a matrix by a vector when the original matrix is stored
3113  ! in the jagged diagonal storage format.
3114  !-----------------------------------------------------------------------
3115  !
3116  ! on entry:
3117  !----------
3118  ! n = row dimension of A
3119  ! x = real array of length equal to the column dimension of
3120  ! the A matrix.
3121  ! jdiag = integer. The number of jadded-diagonals in the data-structure.
3122  ! a = real array containing the jadded diagonals of A stored
3123  ! in succession (in decreasing lengths)
3124  ! j = integer array containing the colum indices of the
3125  ! corresponding elements in a.
3126  ! ia = integer array containing the lengths of the jagged diagonals
3127  !
3128  ! on return:
3129  !-----------
3130  ! y = real array of length n, containing the product y=A*x
3131  !
3132  ! Note:
3133  !-------
3134  ! Permutation related to the JAD format is not performed.
3135  ! this can be done by:
3136  ! call permvec (n,y,y,iperm)
3137  ! after the call to amuxj, where iperm is the permutation produced
3138  ! by csrjad.
3139  !-----------------------------------------------------------------------
3140  ! local variables
3141  !
3142  integer i, ii, k1, ilen, j
3143  !-----------------------------------------------------------------------
3144  do i=1, n
3145  y(i) = 0.0d0
3146  end do
3147  do ii=1, jdiag
3148  k1 = ia(ii)-1
3149  ilen = ia(ii+1)-k1-1
3150  do j=1,ilen
3151  y(j)= y(j)+a(k1+j)*x(ja(k1+j))
3152  end do
3153  end do
3154  !
3155  return
3156  !----------end-of-amuxj-------------------------------------------------
3157  !-----------------------------------------------------------------------
3158 end subroutine amuxj
3159 !-----------------------------------------------------------------------
3160 subroutine vbrmv(nr, nc, ia, ja, ka, a, kvstr, kvstc, x, b)
3161  !-----------------------------------------------------------------------
3162  integer nr, nc, ia(nr+1), ja(*), ka(*), kvstr(nr+1), kvstc(*)
3163  real*8 a(*), x(*), b(*)
3164  !-----------------------------------------------------------------------
3165  ! Sparse matrix-full vector product, in VBR format.
3166  !-----------------------------------------------------------------------
3167  ! On entry:
3168  !--------------
3169  ! nr, nc = number of block rows and columns in matrix A
3170  ! ia,ja,ka,a,kvstr,kvstc = matrix A in variable block row format
3171  ! x = multiplier vector in full format
3172  !
3173  ! On return:
3174  !---------------
3175  ! b = product of matrix A times vector x in full format
3176  !
3177  ! Algorithm:
3178  !---------------
3179  ! Perform multiplication by traversing a in order.
3180  !
3181  !-----------------------------------------------------------------------
3182  !-----local variables
3183  integer n, i, j, ii, jj, k, istart, istop
3184  real*8 xjj
3185  !---------------------------------
3186  n = kvstc(nc+1)-1
3187  do i = 1, n
3188  b(i) = 0.d0
3189  enddo
3190  !---------------------------------
3191  k = 1
3192  do i = 1, nr
3193  istart = kvstr(i)
3194  istop = kvstr(i+1)-1
3195  do j = ia(i), ia(i+1)-1
3196  do jj = kvstc(ja(j)), kvstc(ja(j)+1)-1
3197  xjj = x(jj)
3198  do ii = istart, istop
3199  b(ii) = b(ii) + xjj*a(k)
3200  k = k + 1
3201  enddo
3202  enddo
3203  enddo
3204  enddo
3205  !---------------------------------
3206  return
3207 end subroutine vbrmv
3208 !-----------------------------------------------------------------------
3209 !----------------------end-of-vbrmv-------------------------------------
3210 !-----------------------------------------------------------------------
3211 !----------------------------------------------------------------------c
3212 ! 2) T R I A N G U L A R S Y S T E M S O L U T I O N S c
3213 !----------------------------------------------------------------------c
3214 subroutine lsol (n,x,y,al,jal,ial)
3215  integer n, jal(*),ial(n+1)
3216  real*8 x(n), y(n), al(*)
3217  !-----------------------------------------------------------------------
3218  ! solves L x = y ; L = lower unit triang. / CSR format
3219  !-----------------------------------------------------------------------
3220  ! solves a unit lower triangular system by standard (sequential )
3221  ! forward elimination - matrix stored in CSR format.
3222  !-----------------------------------------------------------------------
3223  !
3224  ! On entry:
3225  !----------
3226  ! n = integer. dimension of problem.
3227  ! y = real array containg the right side.
3228  !
3229  ! al,
3230  ! jal,
3231  ! ial, = Lower triangular matrix stored in compressed sparse row
3232  ! format.
3233  !
3234  ! On return:
3235  !-----------
3236  ! x = The solution of L x = y.
3237  !--------------------------------------------------------------------
3238  ! local variables
3239  !
3240  integer k, j
3241  real*8 t
3242  !-----------------------------------------------------------------------
3243  x(1) = y(1)
3244  do k = 2, n
3245  t = y(k)
3246  do j = ial(k), ial(k+1)-1
3247  t = t-al(j)*x(jal(j))
3248  end do
3249  x(k) = t
3250  end do
3251  !
3252  return
3253  !----------end-of-lsol--------------------------------------------------
3254  !-----------------------------------------------------------------------
3255 end subroutine lsol
3256 !-----------------------------------------------------------------------
3257 subroutine ldsol (n,x,y,al,jal)
3258  integer n, jal(*)
3259  real*8 x(n), y(n), al(*)
3260  !-----------------------------------------------------------------------
3261  ! Solves L x = y L = triangular. MSR format
3262  !-----------------------------------------------------------------------
3263  ! solves a (non-unit) lower triangular system by standard (sequential)
3264  ! forward elimination - matrix stored in MSR format
3265  ! with diagonal elements already inverted (otherwise do inversion,
3266  ! al(1:n) = 1.0/al(1:n), before calling ldsol).
3267  !-----------------------------------------------------------------------
3268  !
3269  ! On entry:
3270  !----------
3271  ! n = integer. dimension of problem.
3272  ! y = real array containg the right hand side.
3273  !
3274  ! al,
3275  ! jal, = Lower triangular matrix stored in Modified Sparse Row
3276  ! format.
3277  !
3278  ! On return:
3279  !-----------
3280  ! x = The solution of L x = y .
3281  !--------------------------------------------------------------------
3282  ! local variables
3283  !
3284  integer k, j
3285  real*8 t
3286  !-----------------------------------------------------------------------
3287  x(1) = y(1)*al(1)
3288  do k = 2, n
3289  t = y(k)
3290  do j = jal(k), jal(k+1)-1
3291  t = t - al(j)*x(jal(j))
3292  end do
3293  x(k) = al(k)*t
3294  end do
3295  return
3296  !----------end-of-ldsol-------------------------------------------------
3297  !-----------------------------------------------------------------------
3298 end subroutine ldsol
3299 !-----------------------------------------------------------------------
3300 subroutine lsolc (n,x,y,al,jal,ial)
3301  integer n, jal(*),ial(*)
3302  real*8 x(n), y(n), al(*)
3303  !-----------------------------------------------------------------------
3304  ! SOLVES L x = y ; where L = unit lower trang. CSC format
3305  !-----------------------------------------------------------------------
3306  ! solves a unit lower triangular system by standard (sequential )
3307  ! forward elimination - matrix stored in CSC format.
3308  !-----------------------------------------------------------------------
3309  !
3310  ! On entry:
3311  !----------
3312  ! n = integer. dimension of problem.
3313  ! y = real*8 array containg the right side.
3314  !
3315  ! al,
3316  ! jal,
3317  ! ial, = Lower triangular matrix stored in compressed sparse column
3318  ! format.
3319  !
3320  ! On return:
3321  !-----------
3322  ! x = The solution of L x = y.
3323  !-----------------------------------------------------------------------
3324  ! local variables
3325  !
3326  integer k, j
3327  real*8 t
3328  !-----------------------------------------------------------------------
3329  do k=1,n
3330  x(k) = y(k)
3331  end do
3332  do k = 1, n-1
3333  t = x(k)
3334  do j = ial(k), ial(k+1)-1
3335  x(jal(j)) = x(jal(j)) - t*al(j)
3336  end do
3337  end do
3338  !
3339  return
3340  !----------end-of-lsolc-------------------------------------------------
3341  !-----------------------------------------------------------------------
3342 end subroutine lsolc
3343 !-----------------------------------------------------------------------
3344 subroutine ldsolc (n,x,y,al,jal)
3345  integer n, jal(*)
3346  real*8 x(n), y(n), al(*)
3347  !-----------------------------------------------------------------------
3348  ! Solves L x = y ; L = nonunit Low. Triang. MSC format
3349  !-----------------------------------------------------------------------
3350  ! solves a (non-unit) lower triangular system by standard (sequential)
3351  ! forward elimination - matrix stored in Modified Sparse Column format
3352  ! with diagonal elements already inverted (otherwise do inversion,
3353  ! al(1:n) = 1.0/al(1:n), before calling ldsol).
3354  !-----------------------------------------------------------------------
3355  !
3356  ! On entry:
3357  !----------
3358  ! n = integer. dimension of problem.
3359  ! y = real array containg the right hand side.
3360  !
3361  ! al,
3362  ! jal,
3363  ! ial, = Lower triangular matrix stored in Modified Sparse Column
3364  ! format.
3365  !
3366  ! On return:
3367  !-----------
3368  ! x = The solution of L x = y .
3369  !--------------------------------------------------------------------
3370  ! local variables
3371  !
3372  integer k, j
3373  real*8 t
3374  !-----------------------------------------------------------------------
3375  do k=1,n
3376  x(k) = y(k)
3377  end do
3378  do k = 1, n
3379  x(k) = x(k)*al(k)
3380  t = x(k)
3381  do j = jal(k), jal(k+1)-1
3382  x(jal(j)) = x(jal(j)) - t*al(j)
3383  end do
3384  end do
3385  !
3386  return
3387  !----------end-of-lsolc------------------------------------------------
3388  !-----------------------------------------------------------------------
3389 end subroutine ldsolc
3390 !-----------------------------------------------------------------------
3391 subroutine ldsoll (n,x,y,al,jal,nlev,lev,ilev)
3392  integer n, nlev, jal(*), ilev(nlev+1), lev(n)
3393  real*8 x(n), y(n), al(*)
3394  !-----------------------------------------------------------------------
3395  ! Solves L x = y L = triangular. Uses LEVEL SCHEDULING/MSR format
3396  !-----------------------------------------------------------------------
3397  !
3398  ! On entry:
3399  !----------
3400  ! n = integer. dimension of problem.
3401  ! y = real array containg the right hand side.
3402  !
3403  ! al,
3404  ! jal, = Lower triangular matrix stored in Modified Sparse Row
3405  ! format.
3406  ! nlev = number of levels in matrix
3407  ! lev = integer array of length n, containing the permutation
3408  ! that defines the levels in the level scheduling ordering.
3409  ! ilev = pointer to beginning of levels in lev.
3410  ! the numbers lev(i) to lev(i+1)-1 contain the row numbers
3411  ! that belong to level number i, in the level shcheduling
3412  ! ordering.
3413  !
3414  ! On return:
3415  !-----------
3416  ! x = The solution of L x = y .
3417  !--------------------------------------------------------------------
3418  integer ii, jrow, i, k
3419  real*8 t
3420  !
3421  ! outer loop goes through the levels. (SEQUENTIAL loop)
3422  !
3423  do ii=1, nlev
3424  !
3425  ! next loop executes within the same level. PARALLEL loop
3426  !
3427  do i=ilev(ii), ilev(ii+1)-1
3428  jrow = lev(i)
3429  !
3430  ! compute inner product of row jrow with x
3431  !
3432  t = y(jrow)
3433  do k=jal(jrow), jal(jrow+1)-1
3434  t = t - al(k)*x(jal(k))
3435  end do
3436  x(jrow) = t*al(jrow)
3437  end do
3438  end do
3439  return
3440  !-----------------------------------------------------------------------
3441 end subroutine ldsoll
3442 !-----------------------------------------------------------------------
3443 subroutine usol (n,x,y,au,jau,iau)
3444  integer n, jau(*),iau(n+1)
3445  real*8 x(n), y(n), au(*)
3446  !-----------------------------------------------------------------------
3447  ! Solves U x = y U = unit upper triangular.
3448  !-----------------------------------------------------------------------
3449  ! solves a unit upper triangular system by standard (sequential )
3450  ! backward elimination - matrix stored in CSR format.
3451  !-----------------------------------------------------------------------
3452  !
3453  ! On entry:
3454  !----------
3455  ! n = integer. dimension of problem.
3456  ! y = real array containg the right side.
3457  !
3458  ! au,
3459  ! jau,
3460  ! iau, = Lower triangular matrix stored in compressed sparse row
3461  ! format.
3462  !
3463  ! On return:
3464  !-----------
3465  ! x = The solution of U x = y .
3466  !--------------------------------------------------------------------
3467  ! local variables
3468  !
3469  integer k, j
3470  real*8 t
3471  !-----------------------------------------------------------------------
3472  x(n) = y(n)
3473  do k = n-1,1,-1
3474  t = y(k)
3475  do j = iau(k), iau(k+1)-1
3476  t = t - au(j)*x(jau(j))
3477  end do
3478  x(k) = t
3479  end do
3480  !
3481  return
3482  !----------end-of-usol--------------------------------------------------
3483  !-----------------------------------------------------------------------
3484 end subroutine usol
3485 !-----------------------------------------------------------------------
3486 subroutine udsol (n,x,y,au,jau)
3487  integer n, jau(*)
3488  real*8 x(n), y(n),au(*)
3489  !-----------------------------------------------------------------------
3490  ! Solves U x = y ; U = upper triangular in MSR format
3491  !-----------------------------------------------------------------------
3492  ! solves a non-unit upper triangular matrix by standard (sequential )
3493  ! backward elimination - matrix stored in MSR format.
3494  ! with diagonal elements already inverted (otherwise do inversion,
3495  ! au(1:n) = 1.0/au(1:n), before calling).
3496  !-----------------------------------------------------------------------
3497  !
3498  ! On entry:
3499  !----------
3500  ! n = integer. dimension of problem.
3501  ! y = real array containg the right side.
3502  !
3503  ! au,
3504  ! jau, = Lower triangular matrix stored in modified sparse row
3505  ! format.
3506  !
3507  ! On return:
3508  !-----------
3509  ! x = The solution of U x = y .
3510  !--------------------------------------------------------------------
3511  ! local variables
3512  !
3513  integer k, j
3514  real*8 t
3515  !-----------------------------------------------------------------------
3516  x(n) = y(n)*au(n)
3517  do k = n-1,1,-1
3518  t = y(k)
3519  do j = jau(k), jau(k+1)-1
3520  t = t - au(j)*x(jau(j))
3521  end do
3522  x(k) = au(k)*t
3523  end do
3524  !
3525  return
3526  !----------end-of-udsol-------------------------------------------------
3527  !-----------------------------------------------------------------------
3528 end subroutine udsol
3529 !-----------------------------------------------------------------------
3530 subroutine usolc (n,x,y,au,jau,iau)
3531  real*8 x(*), y(*), au(*)
3532  integer n, jau(*),iau(*)
3533  !-----------------------------------------------------------------------
3534  ! SOUVES U x = y ; where U = unit upper trang. CSC format
3535  !-----------------------------------------------------------------------
3536  ! solves a unit upper triangular system by standard (sequential )
3537  ! forward elimination - matrix stored in CSC format.
3538  !-----------------------------------------------------------------------
3539  !
3540  ! On entry:
3541  !----------
3542  ! n = integer. dimension of problem.
3543  ! y = real*8 array containg the right side.
3544  !
3545  ! au,
3546  ! jau,
3547  ! iau, = Uower triangular matrix stored in compressed sparse column
3548  ! format.
3549  !
3550  ! On return:
3551  !-----------
3552  ! x = The solution of U x = y.
3553  !-----------------------------------------------------------------------
3554  ! local variables
3555  !
3556  integer k, j
3557  real*8 t
3558  !-----------------------------------------------------------------------
3559  do k=1,n
3560  x(k) = y(k)
3561  end do
3562  do k = n,1,-1
3563  t = x(k)
3564  do j = iau(k), iau(k+1)-1
3565  x(jau(j)) = x(jau(j)) - t*au(j)
3566  end do
3567  end do
3568  !
3569  return
3570  !----------end-of-usolc-------------------------------------------------
3571  !-----------------------------------------------------------------------
3572 end subroutine usolc
3573 !-----------------------------------------------------------------------
3574 subroutine udsolc (n,x,y,au,jau)
3575  integer n, jau(*)
3576  real*8 x(n), y(n), au(*)
3577  !-----------------------------------------------------------------------
3578  ! Solves U x = y ; U = nonunit Up. Triang. MSC format
3579  !-----------------------------------------------------------------------
3580  ! solves a (non-unit) upper triangular system by standard (sequential)
3581  ! forward elimination - matrix stored in Modified Sparse Column format
3582  ! with diagonal elements already inverted (otherwise do inversion,
3583  ! auuuul(1:n) = 1.0/au(1:n), before calling ldsol).
3584  !-----------------------------------------------------------------------
3585  !
3586  ! On entry:
3587  !----------
3588  ! n = integer. dimension of problem.
3589  ! y = real*8 array containg the right hand side.
3590  !
3591  ! au,
3592  ! jau, = Upper triangular matrix stored in Modified Sparse Column
3593  ! format.
3594  !
3595  ! On return:
3596  !-----------
3597  ! x = The solution of U x = y .
3598  !--------------------------------------------------------------------
3599  ! local variables
3600  !
3601  integer k, j
3602  real*8 t
3603  !-----------------------------------------------------------------------
3604  do k=1,n
3605  x(k) = y(k)
3606  end do
3607  do k = n,1,-1
3608  x(k) = x(k)*au(k)
3609  t = x(k)
3610  do j = jau(k), jau(k+1)-1
3611  x(jau(j)) = x(jau(j)) - t*au(j)
3612  end do
3613  end do
3614  !
3615  return
3616  !----------end-of-udsolc------------------------------------------------
3617  !-----------------------------------------------------------------------
3618 end subroutine udsolc
3619 !-----------------------------------------------------------------------
3620 subroutine lusol(n, y, x, alu, jlu, ju)
3621  implicit none
3622 
3623  integer :: n, jlu(*), ju(*)
3624  real*8 :: x(n), y(n), alu(*)
3625 
3626  !-----------------------------------------------------------------------
3627  integer :: i,k
3628  !
3629  ! forward solve
3630  !
3631  do i = 1, n
3632  x(i) = y(i)
3633  do k=jlu(i),ju(i)-1
3634  x(i) = x(i) - alu(k)* x(jlu(k))
3635  end do
3636  end do
3637  do i = n, 1, -1
3638  do k=ju(i),jlu(i+1)-1
3639  x(i) = x(i) - alu(k)*x(jlu(k))
3640  end do
3641  x(i) = alu(i)*x(i)
3642  end do
3643  !
3644  return
3645  !----------------end of lusol ------------------------------------------
3646 end subroutine lusol
3647 !-----------------------------------------------------------------------
3648 subroutine lutsol(n, y, x, alu, jlu, ju)
3649  implicit none
3650 
3651  integer :: n, jlu(*), ju(*)
3652  real*8 :: x(n), y(n), alu(*)
3653 
3654  !-----------------------------------------------------------------------
3655  ! local variables
3656  !
3657  integer :: i,k
3658  !
3659  do i = 1, n
3660  x(i) = y(i)
3661  end do
3662  !
3663  ! forward solve (with U^T)
3664  !
3665  do i = 1, n
3666  x(i) = x(i) * alu(i)
3667  do k=ju(i),jlu(i+1)-1
3668  x(jlu(k)) = x(jlu(k)) - alu(k)* x(i)
3669  end do
3670  end do
3671  !
3672  ! backward solve (with L^T)
3673  !
3674  do i = n, 1, -1
3675  do k=jlu(i),ju(i)-1
3676  x(jlu(k)) = x(jlu(k)) - alu(k)*x(i)
3677  end do
3678  end do
3679  !
3680  return
3681  !----------------end of lutsol -----------------------------------------
3682  !-----------------------------------------------------------------------
3683 end subroutine lutsol
3684 !-----------------------------------------------------------------------
3685 subroutine qsplit(a,ind,n,ncut)
3686  implicit none
3687 
3688  integer :: n, ind(n), ncut
3689  real*8 :: a(n)
3690 
3691  !-----------------------------------------------------------------------
3692  ! does a quick-sort split of a real array.
3693  ! on input a(1:n). is a real array
3694  ! on output a(1:n) is permuted such that its elements satisfy:
3695  !
3696  ! abs(a(i)) .ge. abs(a(ncut)) for i .lt. ncut and
3697  ! abs(a(i)) .le. abs(a(ncut)) for i .gt. ncut
3698  !
3699  ! ind(1:n) is an integer array which permuted in the same way as a(*).
3700  !-----------------------------------------------------------------------
3701  real*8 :: tmp, abskey
3702  integer :: itmp, first, last, j, mid
3703  !-----
3704  first = 1
3705  last = n
3706  if (ncut .lt. first .or. ncut .gt. last) return
3707  !
3708  ! outer loop -- while mid .ne. ncut do
3709  !
3710 1 mid = first
3711  abskey = abs(a(mid))
3712  do j=first+1, last
3713  if (abs(a(j)) .gt. abskey) then
3714  mid = mid+1
3715  ! interchange
3716  tmp = a(mid)
3717  itmp = ind(mid)
3718  a(mid) = a(j)
3719  ind(mid) = ind(j)
3720  a(j) = tmp
3721  ind(j) = itmp
3722  endif
3723  end do
3724  !
3725  ! interchange
3726  !
3727  tmp = a(mid)
3728  a(mid) = a(first)
3729  a(first) = tmp
3730  !
3731  itmp = ind(mid)
3732  ind(mid) = ind(first)
3733  ind(first) = itmp
3734  !
3735  ! test for while loop
3736  !
3737  if (mid .eq. ncut) return
3738  if (mid .gt. ncut) then
3739  last = mid-1
3740  else
3741  first = mid+1
3742  endif
3743  goto 1
3744  !----------------end-of-qsplit------------------------------------------
3745  !-----------------------------------------------------------------------
3746 end subroutine qsplit
3747 subroutine runrc(n,rhs,sol,ipar,fpar,wk,guess,a,ja,ia,au,jau,ju,solver)
3748  implicit none
3749  integer n,ipar(16),ia(n+1),ja(*),ju(*),jau(*)
3750  real*8 fpar(16),rhs(n),sol(n),guess(n),wk(*),a(*),au(*)
3751  external solver
3752  !-----------------------------------------------------------------------
3753  ! the actual tester. It starts the iterative linear system solvers
3754  ! with a initial guess suppied by the user.
3755  !
3756  ! The structure {au, jau, ju} is assumed to have the output from
3757  ! the ILU* routines in ilut.f.
3758  !
3759  !-----------------------------------------------------------------------
3760  ! local variables
3761  !
3762  integer :: i, its
3763  ! real :: dtime, dt(2), time
3764  ! external dtime
3765  save its
3766  !
3767  ! ipar(2) can be 0, 1, 2, please don't use 3
3768  !
3769  if (ipar(2).gt.2) then
3770  WRITE(*,*) 'I can not do both left and right preconditioning.'
3771  return
3772  endif
3773 
3774  its = 0
3775  !
3776  do i = 1, n
3777  sol(i) = guess(i)
3778  enddo
3779  !
3780  ipar(1) = 0
3781  ! time = dtime(dt)
3782 
3783 10 call solver(n,rhs,sol,ipar,fpar,wk)
3784 
3785  if (ipar(7).ne.its) then
3786  its = ipar(7)
3787  endif
3788  if (ipar(1).eq.1) then
3789  call amux(n, wk(ipar(8)), wk(ipar(9)), a, ja, ia)
3790  goto 10
3791  else if (ipar(1).eq.2) then
3792  call atmux(n, wk(ipar(8)), wk(ipar(9)), a, ja, ia)
3793  goto 10
3794  else if (ipar(1).eq.3 .or. ipar(1).eq.5) then
3795  call lusol(n,wk(ipar(8)),wk(ipar(9)),au,jau,ju)
3796  goto 10
3797  else if (ipar(1).eq.4 .or. ipar(1).eq.6) then
3798  call lutsol(n,wk(ipar(8)),wk(ipar(9)),au,jau,ju)
3799  goto 10
3800  else if (ipar(1).le.0) then
3801  if (ipar(1).eq.0) then
3802  ! WRITE(*,*) 'Iterative sovler has satisfied convergence test.'
3803  else if (ipar(1).eq.-1) then
3804  WRITE(*,*) 'Iterative solver has iterated too many times.'
3805  else if (ipar(1).eq.-2) then
3806  WRITE(*,*) 'Iterative solver was not given enough work space.'
3807  WRITE(*,*) 'The work space should at least have ', ipar(4), &
3808  & ' elements.'
3809  else if (ipar(1).eq.-3) then
3810  WRITE(*,*) 'Iterative sovler is facing a break-down.'
3811  else
3812  WRITE(*,*) 'Iterative solver terminated. code =', ipar(1)
3813  endif
3814  endif
3815 end subroutine runrc
3816 !-----end-of-runrc
3817 !----------------------------------------------------------------------c
3818 ! S P A R S K I T c
3819 !----------------------------------------------------------------------c
3820 ! ITERATIVE SOLVERS MODULE c
3821 !----------------------------------------------------------------------c
3822 ! This Version Dated: August 13, 1996. Warning: meaning of some c
3823 ! ============ arguments have changed w.r.t. earlier versions. Some c
3824 ! Calling sequences may also have changed c
3825 !
3826 subroutine ilut(n,a,ja,ia,lfil,droptol,alu,jlu,ju,iwk,w,jw,ierr)
3827  !-----------------------------------------------------------------------
3828  implicit none
3829  integer n
3830  real*8 a(*),alu(*),w(n+1),droptol
3831  integer ja(*),ia(n+1),jlu(*),ju(n),jw(2*n),lfil,iwk,ierr
3832  !----------------------------------------------------------------------*
3833  ! *** ILUT preconditioner *** *
3834  ! incomplete LU factorization with dual truncation mechanism *
3835  !----------------------------------------------------------------------*
3836  ! Author: Yousef Saad *May, 5, 1990, Latest revision, August 1996 *
3837  !----------------------------------------------------------------------*
3838  ! PARAMETERS
3839  !-----------
3840  !
3841  ! on entry:
3842  !==========
3843  ! n = integer. The row dimension of the matrix A. The matrix
3844  !
3845  ! a,ja,ia = matrix stored in Compressed Sparse Row format.
3846  !
3847  ! lfil = integer. The fill-in parameter. Each row of L and each row
3848  ! of U will have a maximum of lfil elements (excluding the
3849  ! diagonal element). lfil must be .ge. 0.
3850  ! ** WARNING: THE MEANING OF LFIL HAS CHANGED WITH RESPECT TO
3851  ! EARLIER VERSIONS.
3852  !
3853  ! droptol = real*8. Sets the threshold for dropping small terms in the
3854  ! factorization. See below for details on dropping strategy.
3855  !
3856  !
3857  ! iwk = integer. The lengths of arrays alu and jlu. If the arrays
3858  ! are not big enough to store the ILU factorizations, ilut
3859  ! will stop with an error message.
3860  !
3861  ! On return:
3862  !===========
3863  !
3864  ! alu,jlu = matrix stored in Modified Sparse Row (MSR) format containing
3865  ! the L and U factors together. The diagonal (stored in
3866  ! alu(1:n) ) is inverted. Each i-th row of the alu,jlu matrix
3867  ! contains the i-th row of L (excluding the diagonal entry=1)
3868  ! followed by the i-th row of U.
3869  !
3870  ! ju = integer array of length n containing the pointers to
3871  ! the beginning of each row of U in the matrix alu,jlu.
3872  !
3873  ! ierr = integer. Error message with the following meaning.
3874  ! ierr = 0 --> successful return.
3875  ! ierr .gt. 0 --> zero pivot encountered at step number ierr.
3876  ! ierr = -1 --> Error. input matrix may be wrong.
3877  ! (The elimination process has generated a
3878  ! row in L or U whose length is .gt. n.)
3879  ! ierr = -2 --> The matrix L overflows the array al.
3880  ! ierr = -3 --> The matrix U overflows the array alu.
3881  ! ierr = -4 --> Illegal value for lfil.
3882  ! ierr = -5 --> zero row encountered.
3883  !
3884  ! work arrays:
3885  !=============
3886  ! jw = integer work array of length 2*n.
3887  ! w = real work array of length n+1.
3888  !
3889  !----------------------------------------------------------------------
3890  ! w, ju (1:n) store the working array [1:ii-1 = L-part, ii:n = u]
3891  ! jw(n+1:2n) stores nonzero indicators
3892  !
3893  ! Notes:
3894  ! ------
3895  ! The diagonal elements of the input matrix must be nonzero (at least
3896  ! 'structurally').
3897  !
3898  !----------------------------------------------------------------------*
3899  !---- Dual drop strategy works as follows. *
3900  ! *
3901  ! 1) Theresholding in L and U as set by droptol. Any element whose *
3902  ! magnitude is less than some tolerance (relative to the abs *
3903  ! value of diagonal element in u) is dropped. *
3904  ! *
3905  ! 2) Keeping only the largest lfil elements in the i-th row of L *
3906  ! and the largest lfil elements in the i-th row of U (excluding *
3907  ! diagonal elements). *
3908  ! *
3909  ! Flexibility: one can use droptol=0 to get a strategy based on *
3910  ! keeping the largest elements in each row of L and U. Taking *
3911  ! droptol .ne. 0 but lfil=n will give the usual threshold strategy *
3912  ! (however, fill-in is then mpredictible). *
3913  !----------------------------------------------------------------------*
3914  ! locals
3915  integer ju0,k,j1,j2,j,ii,i,lenl,lenu,jj,jrow,jpos,lenn
3916  real*8 tnorm, t, abs, s, fact
3917  if (lfil .lt. 0) goto 998
3918  !-----------------------------------------------------------------------
3919  ! initialize ju0 (points to next element to be added to alu,jlu)
3920  ! and pointer array.
3921  !-----------------------------------------------------------------------
3922  ju0 = n+2
3923  jlu(1) = ju0
3924  !
3925  ! initialize nonzero indicator array.
3926  !
3927  do j=1,n
3928  jw(n+j) = 0
3929  end do
3930  !-----------------------------------------------------------------------
3931  ! beginning of main loop.
3932  !-----------------------------------------------------------------------
3933  do ii = 1, n
3934 
3935  j1 = ia(ii)
3936  j2 = ia(ii+1) - 1
3937 
3938  tnorm = 0.0d0
3939  do k=j1,j2
3940  tnorm = tnorm+abs(a(k))
3941  end do
3942  if (abs(tnorm) .lt. tiny(1.)) goto 999
3943 
3944  tnorm = tnorm/real(j2-j1+1)
3945  !
3946  ! unpack L-part and U-part of row of A in arrays w
3947  !
3948  lenu = 1
3949  lenl = 0
3950  jw(ii) = ii
3951  w(ii) = 0.0
3952  jw(n+ii) = ii
3953  !
3954  do j = j1, j2
3955  k = ja(j)
3956  t = a(j)
3957  if (k .lt. ii) then
3958  lenl = lenl+1
3959  jw(lenl) = k
3960  w(lenl) = t
3961  jw(n+k) = lenl
3962  else if (k .eq. ii) then
3963  w(ii) = t
3964  else
3965  lenu = lenu+1
3966  jpos = ii+lenu-1
3967  jw(jpos) = k
3968  w(jpos) = t
3969  jw(n+k) = jpos
3970  endif
3971  end do
3972  jj = 0
3973  lenn = 0
3974  !
3975  ! eliminate previous rows
3976  !
3977 150 jj = jj+1
3978  if (jj .gt. lenl) goto 160
3979  !-----------------------------------------------------------------------
3980  ! in order to do the elimination in the correct order we must select
3981  ! the smallest column index among jw(k), k=jj+1, ..., lenl.
3982  !-----------------------------------------------------------------------
3983  jrow = jw(jj)
3984  k = jj
3985  !
3986  ! determine smallest column index
3987  !
3988  do j=jj+1,lenl
3989  if (jw(j) .lt. jrow) then
3990  jrow = jw(j)
3991  k = j
3992  endif
3993  end do
3994  !
3995  if (k .ne. jj) then
3996  ! exchange in jw
3997  j = jw(jj)
3998  jw(jj) = jw(k)
3999  jw(k) = j
4000  ! exchange in jr
4001  jw(n+jrow) = jj
4002  jw(n+j) = k
4003  ! exchange in w
4004  s = w(jj)
4005  w(jj) = w(k)
4006  w(k) = s
4007  endif
4008  !
4009  ! zero out element in row by setting jw(n+jrow) to zero.
4010  !
4011  jw(n+jrow) = 0
4012  !
4013  ! get the multiplier for row to be eliminated (jrow).
4014  !
4015  fact = w(jj)*alu(jrow)
4016  if (abs(fact) .le. droptol) goto 150
4017  !
4018  ! combine current row and row jrow
4019  !
4020  do k = ju(jrow), jlu(jrow+1)-1
4021  s = fact*alu(k)
4022  j = jlu(k)
4023  jpos = jw(n+j)
4024  if (j .ge. ii) then
4025  !
4026  ! dealing with upper part.
4027  !
4028  if (jpos .eq. 0) then
4029  !
4030  ! this is a fill-in element
4031  !
4032  lenu = lenu+1
4033  if (lenu .gt. n) goto 995
4034  i = ii+lenu-1
4035  jw(i) = j
4036  jw(n+j) = i
4037  w(i) = - s
4038  else
4039  !
4040  ! this is not a fill-in element
4041  !
4042  w(jpos) = w(jpos) - s
4043 
4044  endif
4045  else
4046  !
4047  ! dealing with lower part.
4048  !
4049  if (jpos .eq. 0) then
4050  !
4051  ! this is a fill-in element
4052  !
4053  lenl = lenl+1
4054  if (lenl .gt. n) goto 995
4055  jw(lenl) = j
4056  jw(n+j) = lenl
4057  w(lenl) = - s
4058  else
4059  !
4060  ! this is not a fill-in element
4061  !
4062  w(jpos) = w(jpos) - s
4063  endif
4064  endif
4065  end do
4066  !
4067  ! store this pivot element -- (from left to right -- no danger of
4068  ! overlap with the working elements in L (pivots).
4069  !
4070  lenn = lenn+1
4071  w(lenn) = fact
4072  jw(lenn) = jrow
4073  goto 150
4074 160 continue
4075  !
4076  ! reset double-pointer to zero (U-part)
4077  !
4078  do k=1, lenu
4079  jw(n+jw(ii+k-1)) = 0
4080  end do
4081  !
4082  ! update L-matrix
4083  !
4084  lenl = lenn
4085  lenn = min0(lenl,lfil)
4086  !
4087  ! sort by quick-split
4088  !
4089  call qsplit (w,jw,lenl,lenn)
4090  !
4091  ! store L-part
4092  !
4093  do k=1, lenn
4094  if (ju0 .gt. iwk) goto 996
4095  alu(ju0) = w(k)
4096  jlu(ju0) = jw(k)
4097  ju0 = ju0+1
4098  end do
4099  !
4100  ! save pointer to beginning of row ii of U
4101  !
4102  ju(ii) = ju0
4103  !
4104  ! update U-matrix -- first apply dropping strategy
4105  !
4106  lenn = 0
4107  do k=1, lenu-1
4108  if (abs(w(ii+k)) .gt. droptol*tnorm) then
4109  lenn = lenn+1
4110  w(ii+lenn) = w(ii+k)
4111  jw(ii+lenn) = jw(ii+k)
4112  endif
4113  enddo
4114  lenu = lenn+1
4115  lenn = min0(lenu,lfil)
4116  !
4117  call qsplit (w(ii+1), jw(ii+1), lenu-1,lenn)
4118  !
4119  ! copy
4120  !
4121  t = abs(w(ii))
4122  if (lenn + ju0 .gt. iwk) goto 997
4123  do k=ii+1,ii+lenn-1
4124  jlu(ju0) = jw(k)
4125  alu(ju0) = w(k)
4126  t = t + abs(w(k) )
4127  ju0 = ju0+1
4128  end do
4129  !
4130  ! store inverse of diagonal element of u
4131  !
4132  !2do check if it works ... after correction ...
4133  if (abs(w(ii)) .lt. tiny(1.d0)) w(ii) = (0.0001d0 + droptol)*tnorm
4134  !
4135  alu(ii) = 1.0d0/ w(ii)
4136  !
4137  ! update pointer to beginning of next row of U.
4138  !
4139  jlu(ii+1) = ju0
4140  !-----------------------------------------------------------------------
4141  ! end main loop
4142  !-----------------------------------------------------------------------
4143  end do
4144  ierr = 0
4145  return
4146  !
4147  ! incomprehensible error. Matrix must be wrong.
4148  !
4149 995 ierr = -1
4150  return
4151  !
4152  ! insufficient storage in L.
4153  !
4154 996 ierr = -2
4155  return
4156  !
4157  ! insufficient storage in U.
4158  !
4159 997 ierr = -3
4160  return
4161  !
4162  ! illegal lfil entered.
4163  !
4164 998 ierr = -4
4165  return
4166  !
4167  ! zero row encountered
4168  !
4169 999 ierr = -5
4170  return
4171  !----------------end-of-ilut--------------------------------------------
4172  !-----------------------------------------------------------------------
4173 end subroutine ilut
4174 !----------------------------------------------------------------------
4175 ! subroutine ilu0(n, a, ja, ia, alu, jlu, ju, iw, ipoint1, ipoint2, ierr)
4176 subroutine ilu0(n, a, ja, ia, alu, jlu, ju, iw, ierr)
4178  !implicit real*8 (a-h,o-z)
4179  real*8 a(*), alu(*), tl
4180  integer n, ju0, ii, jj, i, j, jcol, js, jf, jm, jrow, jw, ierr
4181  integer ja(*), ia(*), ju(*), jlu(*), iw(n)
4182  !
4183  !-----------------------------------------------------------------------
4184  ju0 = n+2
4185  jlu(1) = ju0 !!!
4186  iw = 0
4187  do ii = 1, n
4188  js = ju0
4189  do j=ia(ii),ia(ii+1)-1
4190  jcol = ja(j)
4191  if (jcol .eq. ii) then
4192  alu(ii) = a(j)
4193  iw(jcol) = ii
4194  ju(ii) = ju0 !!!
4195  else
4196  alu(ju0) = a(j)
4197  jlu(ju0) = ja(j)
4198  iw(jcol) = ju0
4199  ju0 = ju0+1
4200  endif
4201  end do
4202  jlu(ii+1) = ju0 !!!
4203  jf = ju0-1
4204  jm = ju(ii)-1
4205  ! exit if diagonal element is reached.
4206  do j=js, jm
4207  jrow = jlu(j)
4208  tl = alu(j)*alu(jrow)
4209  alu(j) = tl
4210  ! perform linear combination
4211  do jj = ju(jrow), jlu(jrow+1)-1
4212  jw = iw(jlu(jj))
4213  if (jw .ne. 0) then
4214  alu(jw) = alu(jw) - tl*alu(jj)
4215  ! write(*,*) ii, jw, jj
4216  end if
4217  end do
4218  end do
4219  ! invert and store diagonal element.
4220  if (abs(alu(ii)) .lt. tiny(1.)) goto 600
4221  alu(ii) = 1.0d0/alu(ii)
4222  ! reset pointer iw to zero
4223  iw(ii) = 0
4224  do i = js, jf
4225  iw(jlu(i)) = 0
4226  end do
4227  end do
4228 
4229  ierr = 0
4230  return
4231 
4232  ! zero pivot :
4233 600 ierr = ii
4234  return
4235 end subroutine ilu0
4236 !-----------------------------------------------------------------------
4237 ! subroutine pgmres(n, im, rhs, sol, eps, maxits, ierr)
4238 ! subroutine pgmres(n, im, rhs, sol, eps, maxits, aspar, ierr)
4239 subroutine pgmres(n, im, rhs, sol, eps, maxits, aspar, nnz, ia, ja, alu, jlu, ju, vv, ierr)
4240  !-----------------------------------------------------------------------
4241  ! use datapool, only : nnz, ia, ja, alu, jlu, ju, vv, aspar!, rhs, sol
4242  implicit none
4243 
4244  integer :: n, im, maxits, ierr, nnz
4245 
4246  integer :: ja(nnz), ia(n+1)
4247  integer :: jlu(nnz+1), ju(n)
4248  real*8 :: vv(n,im+1), alu(nnz+1)
4249  real*8 :: aspar(nnz)
4250 
4251  real*8 :: rhs(*), sol(*)
4252 
4253  real*8 :: eps
4254  real*8 :: eps1, epsmac, gam, t, ddot, dnrm2, ro, tl
4255 
4256  integer :: i,i1,j,jj,k,k1,iii,ii,ju0
4257  integer :: its,jrow,jcol,jf,jm,js,jw
4258 
4259  real*8 :: hh(im+1,im), c(im), s(im), rs(im+1)
4260  real*8 :: iw(n)
4261 
4262  logical :: lblas = .false. ! use sparskit matvec and external blas libs (true), don't use them (false)
4263  logical :: lilu = .true. ! use simple ilu preconditioner
4264 
4265  data epsmac/1.d-16/
4266 
4267  ! ilu0 preconditioner
4268 
4269  if (lilu) then
4270  ju0 = n+2
4271  jlu(1) = ju0 !!!
4272  iw = 0
4273  do ii = 1, n
4274  js = ju0
4275  do j=ia(ii),ia(ii+1)-1
4276  jcol = ja(j)
4277  if (jcol .eq. ii) then
4278  alu(ii) = aspar(j)
4279  iw(jcol) = ii
4280  ju(ii) = ju0 !!!
4281  else
4282  alu(ju0) = aspar(j)
4283  jlu(ju0) = ja(j)
4284  iw(jcol) = ju0
4285  ju0 = ju0+1
4286  endif
4287  end do
4288  jlu(ii+1) = ju0 !!!
4289  jf = ju0-1
4290  jm = ju(ii)-1
4291  ! exit if diagonal element is reached.
4292  do j=js, jm
4293  jrow = jlu(j)
4294  tl = alu(j)*alu(jrow)
4295  alu(j) = tl
4296  ! perform linear combination
4297  do jj = ju(jrow), jlu(jrow+1)-1
4298  jw = int(iw(jlu(jj)))
4299  if (jw .ne. 0) then
4300  alu(jw) = alu(jw) - tl*alu(jj)
4301  ! write(*,*) ii, jw, jj
4302  end if
4303  end do
4304  end do
4305  ! invert and store diagonal element.
4306  if (abs(alu(ii)) .lt. epsmac) then
4307  write (*,*) 'zero pivot'
4308  stop
4309  end if
4310  alu(ii) = 1.0d0/alu(ii)
4311  ! reset pointer iw to zero
4312  iw(ii) = 0
4313  do i = js, jf
4314  iw(jlu(i)) = 0
4315  end do
4316  end do
4317  ! end preconditioner
4318  end if
4319  !-------------------------------------------------------------
4320  its = 0
4321  ! outer loop starts here..
4322  if (lblas) then
4323  call amux (n, sol, vv, aspar, ja, ia)
4324  else
4325  do iii = 1, n
4326  t = 0.0d0
4327  do k = ia(iii), ia(iii+1)-1
4328  t = t + aspar(k) * sol(ja(k))
4329  end do
4330  vv(iii,1) = t
4331  end do
4332  end if
4333  do j=1,n
4334  vv(j,1) = rhs(j) - vv(j,1)
4335  end do
4336 20 if (lblas) then
4337  ro = dnrm2(n, vv)
4338  else
4339  ro = sqrt(sum(vv(:,1)*vv(:,1)))
4340  end if
4341  if (abs(ro) .lt. epsmac) goto 999
4342  t = 1.0d0 / ro
4343  do j=1, n
4344  vv(j,1) = vv(j,1)*t
4345  end do
4346  if (its .eq. 0) eps1=eps*ro
4347  ! initialize 1-st term of rhs of hessenberg system..
4348  rs(1) = ro
4349  i = 0
4350 4 i=i+1
4351  its = its + 1
4352  i1 = i + 1
4353  if (lblas) then
4354  call lusol (n, vv(1,i), rhs, alu, jlu, ju)
4355  call amux (n, rhs, vv(1,i1), aspar, ja, ia)
4356  else
4357  do iii = 1, n !- lusol
4358  rhs(iii) = vv(iii,i)
4359  do k=jlu(iii),ju(iii)-1
4360  rhs(iii) = rhs(iii) - alu(k)* rhs(jlu(k))
4361  end do
4362  end do
4363  do iii = n, 1, -1
4364  do k=ju(iii),jlu(iii+1)-1
4365  rhs(iii) = rhs(iii) - alu(k)*rhs(jlu(k))
4366  end do
4367  rhs(iii) = alu(iii)*rhs(iii)
4368  end do
4369  do iii = 1, n !- amux
4370  t = 0.0d0
4371  do k = ia(iii), ia(iii+1)-1
4372  t = t + aspar(k) * rhs(ja(k))
4373  end do
4374  vv(iii,i1) = t
4375  end do
4376  end if
4377  ! modified gram - schmidt...
4378  if (lblas) then
4379  do j=1, i
4380  t = ddot(n, vv(1,j),vv(1,i1))
4381  hh(j,i) = t
4382  call daxpy(n, -t, vv(1,j), 1, vv(1,i1), 1)
4383  t = dnrm2(n, vv(1,i1))
4384  end do
4385  else
4386  do j=1, i
4387  t = 0.d0
4388  do iii = 1,n
4389  t = t + vv(iii,j)*vv(iii,i1)
4390  end do
4391  hh(j,i) = t
4392  vv(:,i1) = vv(:,i1) - t * vv(:,j)
4393  t = sqrt(sum(vv(:,i1)*vv(:,i1)))
4394  end do
4395  end if
4396  hh(i1,i) = t
4397  if ( abs(t) .lt. epsmac) goto 58
4398  t = 1.0d0/t
4399  do k=1,n
4400  vv(k,i1) = vv(k,i1)*t
4401  end do
4402  ! done with modified gram schimd and arnoldi step.. now update factorization of hh
4403 58 if (i .eq. 1) goto 121
4404  do k=2,i
4405  k1 = k-1
4406  t = hh(k1,i)
4407  hh(k1,i) = c(k1)*t + s(k1)*hh(k,i)
4408  hh(k,i) = -s(k1)*t + c(k1)*hh(k,i)
4409  end do
4410 121 gam = sqrt(hh(i,i)**2 + hh(i1,i)**2)
4411  if (abs(gam) .lt. epsmac) gam = epsmac
4412  ! get next plane rotation
4413  c(i) = hh(i,i)/gam
4414  s(i) = hh(i1,i)/gam
4415  rs(i1) = -s(i)*rs(i)
4416  rs(i) = c(i)*rs(i)
4417  ! detrermine residual norm and test for convergence-
4418  hh(i,i) = c(i)*hh(i,i) + s(i)*hh(i1,i)
4419  ro = abs(rs(i1))
4420  if (i .lt. im .and. (ro .gt. eps1)) goto 4
4421  ! now compute solution. first solve upper triangular system.
4422  rs(i) = rs(i)/hh(i,i)
4423  do ii=2,i
4424  k=i-ii+1
4425  k1 = k+1
4426  t=rs(k)
4427  do j=k1,i
4428  t = t-hh(k,j)*rs(j)
4429  end do
4430  rs(k) = t/hh(k,k)
4431  end do
4432  ! form linear combination of v(*,i)'s to get solution
4433  t = rs(1)
4434  do k=1, n
4435  rhs(k) = vv(k,1)*t
4436  end do
4437  do j = 2, i
4438  t = rs(j)
4439  do k=1, n
4440  rhs(k) = rhs(k)+t*vv(k,j)
4441  end do
4442  end do
4443  ! call preconditioner.
4444  if (lblas) then
4445  call lusol (n, rhs, rhs, alu, jlu, ju)
4446  else
4447  do iii = 1, n
4448  do k=jlu(iii),ju(iii)-1
4449  rhs(iii) = rhs(iii) - alu(k)* rhs(jlu(k))
4450  end do
4451  end do
4452  do iii = n, 1, -1
4453  do k=ju(iii),jlu(iii+1)-1
4454  rhs(iii) = rhs(iii) - alu(k)*rhs(jlu(k))
4455  end do
4456  rhs(iii) = alu(iii)*rhs(iii)
4457  end do
4458  end if
4459  do k=1, n
4460  sol(k) = sol(k) + rhs(k)
4461  end do
4462  ! restart outer loop when necessary
4463  if (ro .le. eps1) goto 990
4464  if (its .ge. maxits) goto 991
4465  ! else compute residual vector and continue..
4466  do j=1,i
4467  jj = i1-j+1
4468  rs(jj-1) = -s(jj-1)*rs(jj)
4469  rs(jj) = c(jj-1)*rs(jj)
4470  end do
4471  do j=1,i1
4472  t = rs(j)
4473  if (j .eq. 1) t = t-1.0d0
4474  if (lblas) then
4475  call daxpy (n, t, vv(1,j), 1, vv, 1)
4476  else
4477  vv(:,j) = vv(:,j) + t * vv(:,1)
4478  end if
4479  end do
4480  ! 199 format(' its =', i4, ' res. norm =', d20.6)
4481  ! restart outer loop.
4482  goto 20
4483 990 ierr = 0
4484  return
4485 991 ierr = 1
4486  return
4487 999 continue
4488  ierr = -1
4489  return
4490  !---------------------------------------------------------------------
4491 end subroutine pgmres
4492 !-----------------------------------------------------------------------
4493 
4494 !-----------------------------------------------------------------------
4495 !-----------------------------------------------------------------------
4496 ! subroutine from blas1.f90
4497 !-----------------------------------------------------------------------
4498 DOUBLE PRECISION FUNCTION dnrm2(N,X)
4499  ! .. Scalar Arguments ..
4500  INTEGER n
4501  ! ..
4502  ! .. Array Arguments ..
4503  DOUBLE PRECISION x(*)
4504  ! ..
4505  !
4506  ! Purpose
4507  ! =======
4508  !
4509  ! DNRM2 returns the euclidean norm of a vector via the function
4510  ! name, so that
4511  !
4512  ! DNRM2 := sqrt( x'*x )
4513  !
4514  ! Further Details
4515  ! ===============
4516  !
4517  ! -- This version written on 25-October-1982.
4518  ! Modified on 14-October-1993 to inline the call to DLASSQ.
4519  ! Sven Hammarling, Nag Ltd.
4520  !
4521  ! =====================================================================
4522  !
4523  ! .. Parameters ..
4524  DOUBLE PRECISION one,zero
4525  parameter(one=1.0d+0,zero=0.0d+0)
4526  ! ..
4527  ! .. Local Scalars ..
4528  DOUBLE PRECISION absxi,norm,scale,ssq
4529  INTEGER ix
4530  ! ..
4531  ! .. Intrinsic Functions ..
4532  INTRINSIC abs,sqrt
4533  ! ..
4534  IF (n.LT.1 ) THEN
4535  norm = zero
4536  ELSE IF (n.EQ.1) THEN
4537  norm = abs(x(1))
4538  ELSE
4539  scale = zero
4540  ssq = one
4541  ! The following loop is equivalent to this call to the LAPACK
4542  ! auxiliary routine:
4543  ! CALL DLASSQ( N, X, SCALE, SSQ )
4544  !
4545  DO ix = 1,1 + (n-1)
4546  IF (x(ix).NE.zero) THEN
4547  absxi = abs(x(ix))
4548  IF (scale.LT.absxi) THEN
4549  ssq = one + ssq* (scale/absxi)**2
4550  scale = absxi
4551  ELSE
4552  ssq = ssq + (absxi/scale)**2
4553  END IF
4554  END IF
4555  end do
4556  norm = scale*sqrt(ssq)
4557  END IF
4558  !
4559  dnrm2 = norm
4560  RETURN
4561  !
4562  ! End of DNRM2.
4563  !
4564 END function dnrm2
4565 
4566 !-----------------------------------------------------------------------
4567 SUBROUTINE dlassq( N, X, SCALE, SUMSQ )
4568  !
4569  ! -- LAPACK auxiliary routine (version 3.1) --
4570  ! Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
4571  ! November 2006
4572  INTEGER N
4573  DOUBLE PRECISION SCALE, SUMSQ
4574  DOUBLE PRECISION X( * )
4575  !
4576  ! DLASSQ returns the values scl and smsq such that
4577  !
4578  ! ( scl**2 )*smsq = x( 1 )**2 +...+ x( n )**2 + ( scale**2 )*sumsq,
4579  !
4580  ! where x( i ) = X( 1 + ( i - 1 )*INCX ). The value of sumsq is
4581  ! assumed to be non-negative and scl returns the value
4582  !
4583  ! scl = max( scale, abs( x( i ) ) ).
4584  !
4585  ! SCALE (input/output) DOUBLE PRECISION
4586  ! On entry, the value scale in the equation above.
4587  ! On exit, SCALE is overwritten with scl , the scaling factor
4588  ! for the sum of squares.
4589  DOUBLE PRECISION ZERO
4590  parameter( zero = 0.0d+0 )
4591  INTEGER IX
4592  DOUBLE PRECISION ABSXI
4593  INTRINSIC abs
4594  !
4595  IF( n.GT.0 ) THEN
4596  DO ix = 1, 1 + ( n-1 )
4597  IF( x( ix ).NE.zero ) THEN
4598  absxi = abs( x( ix ) )
4599  IF( scale.LT.absxi ) THEN
4600  sumsq = 1 + sumsq*( scale / absxi )**2
4601  scale = absxi
4602  ELSE
4603  sumsq = sumsq + ( absxi / scale )**2
4604  END IF
4605  END IF
4606  END DO
4607  END IF
4608  RETURN
4609 END SUBROUTINE dlassq
4610 
4611 !-------------------------------------------------------------------------
4612 double precision function ddot(n,dx,dy)
4613  !
4614  ! forms the dot product of two vectors.
4615  ! uses unrolled loops for increments equal to one.
4616  ! jack dongarra, linpack, 3/11/78.
4617  !
4618  double precision dx(*),dy(*),dtemp
4619  integer i,m,mp1,n
4620  !
4621  ddot = 0.0d0
4622  dtemp = 0.0d0
4623  if(n.le.0)return
4624 
4625 20 m = mod(n,5)
4626  if( m .eq. 0 ) go to 40
4627  do i = 1,m
4628  dtemp = dtemp + dx(i)*dy(i)
4629  end do
4630  if( n .lt. 5 ) go to 60
4631 40 mp1 = m + 1
4632  do i = mp1,n,5
4633  dtemp = dtemp + dx(i)*dy(i) + dx(i + 1)*dy(i + 1) + &
4634  & dx(i + 2)*dy(i + 2) + dx(i + 3)*dy(i + 3) + dx(i + 4)*dy(i + 4)
4635  end do
4636 60 ddot = dtemp
4637  return
4638 end function ddot
4639 !----------------------------------------------------------------------
4640 subroutine daxpy(n,da,dx,incx,dy,incy)
4641  !
4642  ! constant times a vector plus a vector.
4643  ! uses unrolled loops for increments equal to one.
4644  ! jack dongarra, linpack, 3/11/78.
4645  !
4646  double precision dx(1),dy(1),da
4647  integer i,incx,incy,ix,iy,m,mp1,n
4648  !
4649  if(n.le.0)return
4650  if (abs(da) .lt. tiny(1.d0)) return
4651  if(incx.eq.1.and.incy.eq.1)go to 20
4652  !
4653  ! code for unequal increments or equal increments
4654  ! not equal to 1
4655  !
4656  ix = 1
4657  iy = 1
4658  if(incx.lt.0)ix = (-n+1)*incx + 1
4659  if(incy.lt.0)iy = (-n+1)*incy + 1
4660  do i = 1,n
4661  dy(iy) = dy(iy) + da*dx(ix)
4662  ix = ix + incx
4663  iy = iy + incy
4664  end do
4665  return
4666  !
4667  ! code for both increments equal to 1
4668  !
4669  !
4670  ! clean-up loop
4671  !
4672 20 m = mod(n,4)
4673  if( m .eq. 0 ) go to 40
4674  do i = 1,m
4675  dy(i) = dy(i) + da*dx(i)
4676  end do
4677  if( n .lt. 4 ) return
4678 40 mp1 = m + 1
4679  do i = mp1,n,4
4680  dy(i) = dy(i) + da*dx(i)
4681  dy(i + 1) = dy(i + 1) + da*dx(i + 1)
4682  dy(i + 2) = dy(i + 2) + da*dx(i + 2)
4683  dy(i + 3) = dy(i + 3) + da*dx(i + 3)
4684  end do
4685  return
4686 end subroutine daxpy
ddot
double precision function ddot(n, dx, dy)
Definition: w3profsmd.F90:4613
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
amux
subroutine amux(n, x, y, a, ja, ia)
Definition: w3profsmd.F90:2820
lusol
subroutine lusol(n, y, x, alu, jlu, ju)
Definition: w3profsmd.F90:3621
w3gdatmd::trigp
integer, dimension(:,:), pointer trigp
Definition: w3gdatmd.F90:1111
w3gdatmd::nseal
integer, pointer nseal
Definition: w3gdatmd.F90:1097
w3odatmd::tbpi0
integer, dimension(:), pointer tbpi0
Definition: w3odatmd.F90:464
w3timemd::dsec21
real function dsec21(TIME1, TIME2)
Definition: w3timemd.F90:333
w3gdatmd::iaa
integer, dimension(:), pointer iaa
Definition: w3gdatmd.F90:1124
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3gdatmd::fspsi
logical, pointer fspsi
Definition: w3gdatmd.F90:1405
w3adatmd
Define data structures to set up wave model auxiliary data for several models simultaneously.
Definition: w3adatmd.F90:26
qsplit
subroutine qsplit(a, ind, n, ncut)
Definition: w3profsmd.F90:3686
stopbis
logical function stopbis(n, ipar, mvpi, fpar, r, delx, sx)
Definition: w3profsmd.F90:2465
w3profsmd::w3xypfsfct2
subroutine w3xypfsfct2(ISP, C, LCALC, RD10, RD20, DT, AC)
Definition: w3profsmd.F90:1282
udsol
subroutine udsol(n, x, y, au, jau)
Definition: w3profsmd.F90:3487
w3gdatmd::ungtype
integer, parameter ungtype
Definition: w3gdatmd.F90:626
w3gdatmd::dmin
real, pointer dmin
Definition: w3gdatmd.F90:1183
w3gdatmd::ntri
integer, pointer ntri
Definition: w3gdatmd.F90:1109
w3wdatmd
Define data structures to set up wave model dynamic data for several models simultaneously.
Definition: w3wdatmd.F90:18
w3adatmd::atrnx
real, dimension(:,:), pointer atrnx
Definition: w3adatmd.F90:578
w3profsmd::w3xypfsn2
subroutine w3xypfsn2(ISP, C, LCALC, RD10, RD20, DT, AC)
Definition: w3profsmd.F90:470
w3adatmd::cflxymax
real, dimension(:), pointer cflxymax
Definition: w3adatmd.F90:620
w3adatmd::cg
real, dimension(:,:), pointer cg
Definition: w3adatmd.F90:575
ldsol
subroutine ldsol(n, x, y, al, jal)
Definition: w3profsmd.F90:3258
w3gdatmd::ie_cell
integer, dimension(:), pointer ie_cell
Definition: w3gdatmd.F90:1124
w3gdatmd::fsn
logical, pointer fsn
Definition: w3gdatmd.F90:1405
w3adatmd::dw
real, dimension(:), pointer dw
Definition: w3adatmd.F90:584
w3adatmd::atrny
real, dimension(:,:), pointer atrny
Definition: w3adatmd.F90:578
amuxe
subroutine amuxe(n, x, y, na, ncol, a, ja)
Definition: w3profsmd.F90:3006
givens
subroutine givens(x, y, c, s)
Definition: w3profsmd.F90:2423
w3gdatmd::sig
real, dimension(:), pointer sig
Definition: w3gdatmd.F90:1234
w3profsmd
Definition: w3profsmd.F90:3
usol
subroutine usol(n, x, y, au, jau, iau)
Definition: w3profsmd.F90:3444
w3wdatmd::time
integer, dimension(:), pointer time
Definition: w3wdatmd.F90:172
w3gdatmd::ecos
real, dimension(:), pointer ecos
Definition: w3gdatmd.F90:1234
w3odatmd::bbpi0
real, dimension(:,:), pointer bbpi0
Definition: w3odatmd.F90:541
w3profsmd::setdepth
subroutine setdepth
Definition: w3profsmd.F90:1587
w3gdatmd::ny
integer, pointer ny
Definition: w3gdatmd.F90:1097
w3odatmd::tbpin
integer, dimension(:), pointer tbpin
Definition: w3odatmd.F90:464
lsol
subroutine lsol(n, x, y, al, jal, ial)
Definition: w3profsmd.F90:3215
ldsolc
subroutine ldsolc(n, x, y, al, jal)
Definition: w3profsmd.F90:3345
lutsol
subroutine lutsol(n, y, x, alu, jlu, ju)
Definition: w3profsmd.F90:3649
w3odatmd::nbi
integer, pointer nbi
Definition: w3odatmd.F90:530
w3gdatmd::iobpa
integer *1, dimension(:), pointer iobpa
Definition: w3gdatmd.F90:1130
w3odatmd::flbpi
logical, pointer flbpi
Definition: w3odatmd.F90:546
tidycg
subroutine tidycg(n, ipar, fpar, sol, delx)
Definition: w3profsmd.F90:2523
w3idatmd::flcur
logical, pointer flcur
Definition: w3idatmd.F90:261
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
pgmres
subroutine pgmres(n, im, rhs, sol, eps, maxits, aspar, nnz, ia, ja, alu, jlu, ju, vv, ierr)
Definition: w3profsmd.F90:4240
dlassq
subroutine dlassq(N, X, SCALE, SUMSQ)
Definition: w3profsmd.F90:4568
uppdir
subroutine uppdir(n, p, np, lbp, indp, y, u, usav, flops)
Definition: w3profsmd.F90:2384
w3gdatmd::mapfs
integer, dimension(:,:), pointer mapfs
Definition: w3gdatmd.F90:1163
atmuxr
subroutine atmuxr(m, n, x, y, a, ja, ia)
Definition: w3profsmd.F90:2957
w3gdatmd::esin
real, dimension(:), pointer esin
Definition: w3gdatmd.F90:1234
amuxms
subroutine amuxms(n, x, y, a, ja)
Definition: w3profsmd.F90:2866
constants::lpdlib
logical lpdlib
LPDLIB Logical for using the PDLIB library.
Definition: constants.F90:101
w3gdatmd::nsea
integer, pointer nsea
Definition: w3gdatmd.F90:1097
w3servmd
Definition: w3servmd.F90:3
atmux
subroutine atmux(n, x, y, a, ja, ia)
Definition: w3profsmd.F90:2908
dnrm2
double precision function dnrm2(N, X)
Definition: w3profsmd.F90:4499
mgsro
subroutine mgsro(full, lda, n, m, ind, ops, vec, hh, ierr)
Definition: w3profsmd.F90:2664
w3gdatmd::tria
real(8), dimension(:), pointer tria
Definition: w3gdatmd.F90:1131
w3gdatmd::fsfct
logical, pointer fsfct
Definition: w3gdatmd.F90:1405
bcgstab
subroutine bcgstab(n, rhs, sol, ipar, fpar, w)
Definition: w3profsmd.F90:2044
w3profsmd::w3xypug
subroutine w3xypug(ISP, FACX, FACY, DTG, VQ, VGX, VGY, LCALC)
Definition: w3profsmd.F90:63
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3odatmd
Definition: w3odatmd.F90:3
ilut
subroutine ilut(n, a, ja, ia, lfil, droptol, alu, jlu, ju, iwk, w, jw, ierr)
Definition: w3profsmd.F90:3827
w3gdatmd::clats
real, dimension(:), pointer clats
Definition: w3gdatmd.F90:1196
w3gdatmd::ien
real(8), dimension(:,:), pointer ien
Definition: w3gdatmd.F90:1122
w3profsmd::w3xypfspsi2
subroutine w3xypfspsi2(ISP, C, LCALC, RD10, RD20, DT, AC)
Definition: w3profsmd.F90:724
w3adatmd::cy
real, dimension(:), pointer cy
Definition: w3adatmd.F90:584
amuxd
subroutine amuxd(n, x, y, diag, ndiag, idiag, ioff)
Definition: w3profsmd.F90:3055
brkdn
logical function brkdn(alpha, ipar)
Definition: w3profsmd.F90:2557
vbrmv
subroutine vbrmv(nr, nc, ia, ja, ka, a, kvstr, kvstc, x, b)
Definition: w3profsmd.F90:3161
w3gdatmd::mapsf
integer, dimension(:,:), pointer mapsf
Definition: w3gdatmd.F90:1163
w3gdatmd::fsnimp
logical, pointer fsnimp
Definition: w3gdatmd.F90:1405
w3gdatmd::fsbccfl
logical, pointer fsbccfl
Definition: w3gdatmd.F90:1406
w3gdatmd::countri
integer, pointer countri
Definition: w3gdatmd.F90:1109
w3gdatmd::iobpd
integer *1, dimension(:,:), pointer iobpd
Definition: w3gdatmd.F90:1130
w3gdatmd::nnz
integer, pointer nnz
Definition: w3gdatmd.F90:1109
w3profsmd::w3xypfsnimp
subroutine w3xypfsnimp(ISP, C, LCALC, RD10, RD20, DT, AC)
Definition: w3profsmd.F90:976
ldsoll
subroutine ldsoll(n, x, y, al, jal, nlev, lev, ilev)
Definition: w3profsmd.F90:3392
bisinit
subroutine bisinit(ipar, fpar, wksize, dsc, lp, rp, wk)
Definition: w3profsmd.F90:2593
w3gdatmd::jaa
integer, dimension(:), pointer jaa
Definition: w3gdatmd.F90:1124
amuxj
subroutine amuxj(n, x, y, jdiag, a, ja, ia)
Definition: w3profsmd.F90:3107
ilu0
subroutine ilu0(n, a, ja, ia, alu, jlu, ju, iw, ierr)
Definition: w3profsmd.F90:4177
udsolc
subroutine udsolc(n, x, y, au, jau)
Definition: w3profsmd.F90:3575
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3gdatmd::gtype
integer, pointer gtype
Definition: w3gdatmd.F90:1094
w3idatmd
Define data structures to set up wave model input data for several models simultaneously.
Definition: w3idatmd.F90:16
w3gdatmd::iobdp
integer *1, dimension(:), pointer iobdp
Definition: w3gdatmd.F90:1130
w3gdatmd::xfr
real, pointer xfr
Definition: w3gdatmd.F90:1232
w3gdatmd::flcy
logical, pointer flcy
Definition: w3gdatmd.F90:1217
implu
subroutine implu(np, umm, beta, ypiv, u, permut, full)
Definition: w3profsmd.F90:2342
w3gdatmd::ccon
integer, dimension(:), pointer ccon
Definition: w3gdatmd.F90:1124
w3gdatmd::iobp
integer *2, dimension(:), pointer iobp
Definition: w3gdatmd.F90:1129
w3gdatmd::si
real(8), dimension(:), pointer si
Definition: w3gdatmd.F90:1122
w3odatmd::ndst
integer, pointer ndst
Definition: w3odatmd.F90:456
w3gdatmd::flcx
logical, pointer flcx
Definition: w3gdatmd.F90:1217
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
daxpy
subroutine daxpy(n, da, dx, incx, dy, incy)
Definition: w3profsmd.F90:4641
w3profsmd::w3cflug
subroutine w3cflug(ISEA, NKCFL, FACX, FACY, DT, MAPFS, CFLXYMAX, VGX, VGY)
Definition: w3profsmd.F90:272
w3adatmd::iter
integer, dimension(:,:), pointer iter
Definition: w3adatmd.F90:654
w3gdatmd
Definition: w3gdatmd.F90:16
w3gdatmd::refpars
real, dimension(:), pointer refpars
Definition: w3gdatmd.F90:1139
w3gdatmd::pfmove
real, pointer pfmove
Definition: w3gdatmd.F90:1183
w3adatmd::itime
integer, pointer itime
Definition: w3adatmd.F90:686
w3gdatmd::index_cell
integer, dimension(:), pointer index_cell
Definition: w3gdatmd.F90:1124
usolc
subroutine usolc(n, x, y, au, jau, iau)
Definition: w3profsmd.F90:3531
runrc
subroutine runrc(n, rhs, sol, ipar, fpar, wk, guess, a, ja, ia, au, jau, ju, solver)
Definition: w3profsmd.F90:3748
w3odatmd::isbpi
integer, dimension(:), pointer isbpi
Definition: w3odatmd.F90:535
w3adatmd::cx
real, dimension(:), pointer cx
Definition: w3adatmd.F90:584
w3gdatmd::nx
integer, pointer nx
Definition: w3gdatmd.F90:1097
w3timemd
Definition: w3timemd.F90:3
w3gdatmd::dtcfl
real, pointer dtcfl
Definition: w3gdatmd.F90:1183
lsolc
subroutine lsolc(n, x, y, al, jal, ial)
Definition: w3profsmd.F90:3301
w3gdatmd::pos_cell
integer, dimension(:), pointer pos_cell
Definition: w3gdatmd.F90:1124
w3gdatmd::mapsta
integer, dimension(:,:), pointer mapsta
Definition: w3gdatmd.F90:1163
w3gdatmd::posi
integer, dimension(:,:), pointer posi
Definition: w3gdatmd.F90:1124
w3odatmd::bbpin
real, dimension(:,:), pointer bbpin
Definition: w3odatmd.F90:541