C	T E S T     J A C O B I   A N D   G A U S S - S E I D E L
C
C	This program tests subroutines J_GS and Jacobi2, which
C	illustrate how the FMS subroutines may be used for a block
C	iterative solution.
C
C	The test matrix is of the form
C
C              [A]        {X}  =  {B}
C       +-            -+ +   +   +   +
C       | N -1 -1 -1 -1| | 1 |   | 1 |
C       |-1  1  0  0  0| | 1 |   | 0 |
C       |-1  0  1  0  0| | 1 | = | 0 |
C       |-1  0  0  1  0| | 1 |   | 0 |
C       |-1  0  0  0  1| | 1 |   | 0 |
C       +-            -+ +   +   +   +
C
C
C	Program name:
	CHARACTER*10 MYNAME
	PARAMETER (MYNAME='EXAMPLE_17')
C
C	FMS matrix and vector file attributes:
	INTEGER     LU_A11(25)
	INTEGER     LU_A12(25)
	INTEGER     LU_A21(25)
	INTEGER     LU_A22(25)
	INTEGER     LU_B1 (25), LU_X1(25)
	INTEGER     LU_B2 (25), LU_X2(25)
C
C	FMS memory management requires the following arrays:
	POINTER   (CMD_PTR, CMD)
	POINTER   (RMD_PTR, RMD)
	POINTER   (IMD_PTR, IMD)
	COMPLEX*16 CMD(0:1)
	REAL*8     RMD(0:1)
	INTEGER    IMD(0:1)
C
C	Data Type:
	INTEGER    IDTYPE
	PARAMETER (IDTYPE=2)
C
C	Input Data:
	LOGICAL ASK
	INTEGER ASK_I
	REAL*8  ASK_R
C
C	Solution methods:
	INTEGER    METHOD_JACOBI
	PARAMETER (METHOD_JACOBI           =1)
	INTEGER    METHOD_GAUSS_SEIDEL
	PARAMETER (METHOD_GAUSS_SEIDEL     =2)
	INTEGER    METHOD_JACOBI_INCREMENT
	PARAMETER (METHOD_JACOBI_INCREMENT =3)
C
C	LOCAL VARIABLES:
C	Number of equations in [A11]:
	   INTEGER N1
C	Number of equations in [A22]:
	   INTEGER N2
C	Maximum of N1 and N2:
	   INTEGER NMAX
C	Number of solution vectors:
	   INTEGER NRHS
C	Form a new [A11] matrix:
	   LOGICAL NEWA11
C	Form a new [A22] matrix:
	   LOGICAL NEWA22
C	Type of solution method:
	   INTEGER METHOD
C	Print FMS output during interation:
	   LOGICAL NOFMSP
C	Maximum number of iterations:
	   INTEGER MAXITR
C	Maximum iteration error:
	   REAL*8  ERRMAX
C	Error on current term:
	   REAL*8  EI
C	Maximum overall error:
	   REAL*8  ERROR
C	CMD Pointer to scratch vector:
	   INTEGER L_TEMP
C	Profile vector for a full matrix:
	INTEGER    LOWEQ(1)
	DATA       LOWEQ/-1/
C
C	CONSTANTS:
	   REAL*8     R_ZERO
	   DATA R_ZERO/0.0D0/
	   COMPLEX*16 C_ONE
	   DATA C_ONE/(1.0D0,0.0D0)/
C
C (1)	Initialize FMS:
	CALL FMSINI
	CALL FMSPSH (MYNAME)
C
C	Use full column partial pivoting (SLAB format):
	CALL FMSIST ('MFMAT', 3)
C
C	Read in problem size parameters:
   10	CONTINUE
	N1     = ASK_I('Enter the number of equations in A11.....')
	N2     = ASK_I('Enter the number of equations in A22.....')
	NRHS   = ASK_I('Enter the number of solution vectors.....')
	MAXITR = ASK_I('Enter the maximum number of iterations...')
	ERRMAX = ASK_R('Enter the maximum error..................')
	WRITE(6,*) 'The following solution methods are available:'
	WRITE(6,*) '   1 = Jacobi,'
	WRITE(6,*) '   2 = Gauss-Seidel,'
	WRITE(6,*) '   3 = Incremental Jacobi.'
	METHOD = ASK_I('Enter solution method (1 | 2 | 3 ).......')
	WRITE(6,*) 'The following vector norms are available:'
	WRITE(6,*) '   0 = Infinity norm (MAX(ABS(X(i)))'
	WRITE(6,*) '   1 =  SUM( ABS( X(i) ) )'
	WRITE(6,*) '   2 =( SUM( ABS( X(i) )**2) )**(1/2)'
	INORM  = ASK_I('Enter the norm number (0 | 1 | 2)........')
	NOFMSP = ASK  ('Print FMS output during iterations?')
	NOFMSP = (.NOT.NOFMSP)
	WRITE (6,*) 'You may now alter any FMS parameter.'
	WRITE (6,*) 'When you are finished, type the letters RETURN'
	CALL FMSSET
	CALL FMSIGT ('MEMPTR', IMD_PTR)
	CALL FMSIGT ('MEMPTR', RMD_PTR)
	CALL FMSIGT ('MEMPTR', CMD_PTR)
C
C	Get a temporary vector for generating columns and RHS's:
	NMAX = MAX0(N1,N2)
	CALL FMSCMG (CMD, L_TEMP, NMAX)
C
C (2)	Open FMS files:
	CALL CNDI  (LOWEQ, N1,           'LU_A11', LU_A11)
	CALL FMSOV (N1, IDTYPE, N2  , 'LU_A12', LU_A12)
	CALL FMSOV (N1, IDTYPE, N2  , 'LU_A21', LU_A21)
	CALL CNDI  (LOWEQ, N2,           'LU_A22', LU_A22)
	CALL FMSOV (N1, IDTYPE, NRHS, 'LU_B1' , LU_B1 )
	CALL FMSOV (N1, IDTYPE, NRHS, 'LU_X1' , LU_X1 )
	CALL FMSOV (N2, IDTYPE, NRHS, 'LU_B2' , LU_B2 )
	CALL FMSOV (N2, IDTYPE, NRHS, 'LU_X2' , LU_X2 )
C
C (3)	Write data to FMS files:
	NEWA11 = .TRUE.
	NEWA22 = .TRUE.
C
C	Branch back to here for refinement solutions:
   30	CONTINUE
C
C	Generate [A11]:
	IF(NEWA11) CALL A11GEN (CMD(L_TEMP), N1, N2,   LU_A11)
C
C	Generate [A12]:
	CALL A12GEN (CMD(L_TEMP), N1, N2,   LU_A12)
C
C	Generate [A21]:
	CALL A21GEN (CMD(L_TEMP), N1, N2,   LU_A21)
C
C	Generate [A22]:
	IF(NEWA22) CALL A22GEN (CMD(L_TEMP), N2,       LU_A22)
C
C	Generate {B1}:
	CALL B1GEN  (CMD(L_TEMP), N1, NRHS, LU_B1 )
C
C	Generate {B2}:
	CALL B2GEN  (CMD(L_TEMP), N2, NRHS, LU_B2 )
C
C (4)	Perform matrix algebra:
	IF( (METHOD .EQ. METHOD_JACOBI) .OR.
     1	    (METHOD .EQ. METHOD_GAUSS_SEIDEL) ) THEN
	   CALL J_GS
     1	   (LU_A11, LU_A11,
     2	    LU_A12,
     3	    LU_A21,
     4	    LU_A22, LU_A22,
     5	    LU_B1,  LU_X1,
     6	    LU_B2,  LU_X2,
     7	    NEWA11, NEWA22,
     8	    INORM, MAXITR, ERRMAX, METHOD, NOFMSP)
C
	ELSE IF(METHOD .EQ. METHOD_JACOBI_INCREMENT) THEN
	   CALL JACOBI2
     1	   (LU_A11, LU_A11,
     2	    LU_A12,
     3	    LU_A21,
     4	    LU_A22, LU_A22,
     5	    LU_B1,  LU_X1,
     6	    LU_B2,  LU_X2,
     7	    NEWA11, NEWA22,
     8	    INORM, MAXITR, ERRMAX, NOFMSP)
	END IF
C
C (5)	Read data from FMS files:
C       Check the answer:
	ERROR  = R_ZERO
C
C	Check {X1}:
	CALL FMSGET (LU_X1, 0, 0, 0, 0, CMD, 0)
	DO IRHS = 1,NRHS
	   CALL FMSGET (LU_X1, N1, 1, 1, IRHS, CMD(L_TEMP), N1)
	   DO I = 0,(N1-1)
	      EI = ABS(CMD(L_TEMP+I) - C_ONE)
	      IF(EI .GT. ERROR) ERROR = EI
	   END DO
	END DO
	CALL FMSGET (LU_X1, 0, 0, N1+1, 1, CMD, 0)
C
C	Check {X2}:
	CALL FMSGET (LU_X2, 0, 0, 0, 0, CMD, 0)
	DO IRHS = 1,NRHS
	   CALL FMSGET (LU_X2, N2, 1, 1, IRHS, CMD(L_TEMP), N2)
	   DO I = 0,(N2-1)
	      EI = ABS(CMD(L_TEMP+I) - C_ONE)
	      IF(EI .GT. ERROR) ERROR = EI
	   END DO
	END DO
	CALL FMSGET (LU_X2, 0, 0, N2+1, 1, CMD, 0)
	WRITE(6,*) 'MAXIMUM ERROR =', ERROR
C
C	Modify the matrix and solve it again:
	IF(.NOT. ASK('Do you want another solution with this matrix?'))
     1	         GO TO 100
	NEWA11 = ASK('Do you want a new A11?')
	NEWA22 = ASK('Do you want a new A22?')
C
	IF( NEWA11 .OR.
     1	    NEWA22) GO TO 30
C
C (6)	Close FMS files:
  100	CONTINUE
	CALL FMSCM (LU_A11)
	CALL FMSCV (LU_A12)
	CALL FMSCV (LU_A21)
	CALL FMSCM (LU_A22)
	CALL FMSCV (LU_B1 )
	CALL FMSCV (LU_X1 )
	CALL FMSCV (LU_B2 )
	CALL FMSCV (LU_X2 )
	CALL FMSCMR (CMD, L_TEMP, NMAX)
	IF(ASK('Do you want to solve another problem?')) GO TO 10
	CALL FMSPOP (MYNAME)
	CALL FMSEND
	END
C=======================================================================
	LOGICAL FUNCTION ASK(QUESTION)
C=======================================================================
	CHARACTER* (*) QUESTION
	CHARACTER*1 IYN
	WRITE(6,2000) QUESTION
	READ (5,1000) IYN
	IF( (IYN .EQ. 'Y') .OR. (IYN .EQ. 'y') ) THEN
	   ASK = .TRUE.
	ELSE
	   ASK = .FALSE.
	END IF
	RETURN
 1000	FORMAT (A)
 2000	FORMAT (1X,A,' (y,n)>')
	END
C=======================================================================
	INTEGER FUNCTION ASK_I(STRING)
C=======================================================================
	CHARACTER* (*) STRING
	WRITE(6,2000) STRING
	READ (5,*) ASK_I
	RETURN
 2000	FORMAT (1X,A,'>')
	END
C=======================================================================
	REAL*8 FUNCTION ASK_R(STRING)
C=======================================================================
	CHARACTER* (*) STRING
	WRITE(6,2000) STRING
	READ (5,*) ASK_R
	RETURN
 2000	FORMAT (1X,A,'>')
	END
C=======================================================================
	SUBROUTINE A11GEN (ACOL, N1, N2, LU_A11)
C=======================================================================
	COMPLEX*16 ACOL(N1)
	INTEGER    N1, N2
	INTEGER    LU_A11(25)
	CHARACTER*6 MYNAME
	PARAMETER (MYNAME='A11GEN')
	REAL*8     A11_Re, R_ZERO
	COMPLEX*16 C_ZERO, C_ONE, C_MONE
	DATA R_ZERO/0.0D0/
	DATA C_ZERO/( 0.0D0,0.0D0)/
	DATA C_MONE/(-1.0D0,0.0D0)/
	DATA C_ONE /( 1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
C	Initialize FMSCOL
	CALL FMSCOL (0, ACOL, LU_A11)
C
C	Write first column
	DO 10 I = 2,N1
	   ACOL(I) = C_MONE
   10	CONTINUE
	A11_Re  = DFLOAT(N1+N2)
	ACOL(1) = DCMPLX(A11_Re,R_ZERO)
	CALL FMSCOL (1, ACOL, LU_A11)
C
C	Write remaining columns:
	DO 20 I = 2,N1
	   ACOL(I) = C_ZERO
   20	CONTINUE
	ACOL(1) = C_MONE
	DO 30 I = 2,N1
	   ACOL(I) = C_ONE
	   CALL FMSCOL (I, ACOL, LU_A11)
	   ACOL(I) = C_ZERO
   30	CONTINUE
C
C	End FMSCOL
	CALL FMSCOL (N1+1, ACOL, LU_A11)
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating [A11]:')
	END
C=======================================================================
	SUBROUTINE A12GEN (ACOL, N1, N2, LU_A12)
C=======================================================================
	COMPLEX*16 ACOL(N1)
	INTEGER    N1, N2
	INTEGER    LU_A12(25)
	CHARACTER*6 MYNAME
	PARAMETER (MYNAME='A12GEN')
	COMPLEX*16 C_ZERO, C_MONE
	DATA C_ZERO/( 0.0D0,0.0D0)/
	DATA C_MONE/(-1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
	DO 10 I=2,N1
	   ACOL(I) = C_ZERO
   10	CONTINUE
	ACOL(1) = C_MONE
C
C	Initialize FMSPUT:
	CALL FMSPUT (LU_A12, 0, 0, 0, 0, ACOL, 0)
C
C	Write out columns of [A12]:
	DO 20 I = 1,N2
	   CALL FMSPUT (LU_A12, N1, 1, 1, I, ACOL, N1)
   20	CONTINUE
C
C	End FMSPUT:
	CALL FMSPUT (LU_A12, 0, 0, N1+1, 0, ACOL, 0)
C
C	Set status:
	LU_A12(7) = 0
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating [A12]:')
	END
C=======================================================================
	SUBROUTINE A21GEN (AROW, N1, N2, LU_A21)
C=======================================================================
	COMPLEX*16 AROW(N1)
	INTEGER    N1, N2
	INTEGER    LU_A21(25)
	CHARACTER*6 MYNAME
	PARAMETER (MYNAME='A21GEN')
	COMPLEX*16 C_ZERO, C_MONE
	DATA C_ZERO/( 0.0D0,0.0D0)/
	DATA C_MONE/(-1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
	DO 10 I=2,N1
	   AROW(I) = C_ZERO
   10	CONTINUE
	AROW(1) = C_MONE
C
C	Initialize FMSPUT:
	CALL FMSPUT (LU_A21, 0, 0, 0, 0, AROW, 0)
C
C	Write out rows of [A21], which is stored transposed:
	DO 20 I = 1,N2
	   CALL FMSPUT (LU_A21, N1, 1, 1, I, AROW, N1)
   20	CONTINUE
C
C	End FMSPUT:
	CALL FMSPUT (LU_A21, 0, 0, N1+1, 0, AROW, 0)
C
C	Set status:
	LU_A21(7) = 0
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating [A21]:')
	END
C=======================================================================
	SUBROUTINE A22GEN (ACOL, N2, LU_A22)
C=======================================================================
	COMPLEX*16 ACOL(N2)
	INTEGER    N2
	INTEGER    LU_A22(25)
	CHARACTER*6 MYNAME
	PARAMETER (MYNAME='A22GEN')
	COMPLEX*16 C_ZERO, C_ONE
	DATA C_ZERO/( 0.0D0,0.0D0)/
	DATA C_ONE /( 1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
C	Initialize FMSCOL
	CALL FMSCOL (0, ACOL, LU_A22)
C
	DO 10 I = 1,N2
	   ACOL(I) = C_ZERO
   10	CONTINUE
C
	DO 20 I = 1,N2
	   ACOL(I) = C_ONE
	   CALL FMSCOL (I, ACOL, LU_A22)
	   ACOL(I) = C_ZERO
   20	CONTINUE
C
C	End FMSCOL
	CALL FMSCOL (N2+1, ACOL, LU_A22)
C
C	Set status:
	LU_A22(7) = 0
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating [A22]:')
	END
C=======================================================================
	SUBROUTINE B1GEN (RHS, N1, NRHS, LU_B1)
C=======================================================================
	COMPLEX*16 RHS(N1)
	INTEGER    N1, NRHS
	INTEGER    LU_B1(25)
	CHARACTER*5 MYNAME
	PARAMETER (MYNAME='B1GEN')
	COMPLEX*16 C_ZERO, C_ONE
	DATA C_ZERO/(0.0D0,0.0D0)/
	DATA C_ONE /(1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
	DO 10 I=2,N1
	  RHS(I) = C_ZERO
   10	CONTINUE
	RHS(1) = C_ONE
C
C	Initialize FMSPUT:
	CALL FMSPUT (LU_B1, 0, 0, 0, 0, RHS, 0)
C
C	Write out columns of {B1}:
	DO 20 I = 1,NRHS
	   CALL FMSPUT (LU_B1, N1, 1, 1, I, RHS, N1)
   20	CONTINUE
C
C	End FMSPUT:
	CALL FMSPUT (LU_B1, 0, 0, N1+1, 0, RHS, 0)
C
C	Set status:
	LU_B1(7) = 0
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating {B1}:')
	END
C=======================================================================
	SUBROUTINE B2GEN (RHS, N2, NRHS, LU_B2)
C=======================================================================
	COMPLEX*16 RHS(N2)
	INTEGER    N2, NRHS
	INTEGER    LU_B2(25)
	CHARACTER*5 MYNAME
	PARAMETER (MYNAME='B2GEN')
	COMPLEX*16 C_ZERO, C_ONE
	DATA C_ZERO/(0.0D0,0.0D0)/
	DATA C_ONE /(1.0D0,0.0D0)/
C
	CALL FMSPSH (MYNAME)
	WRITE(6,2000)
C
	DO 10 I=1,N2
	  RHS(I) = C_ZERO
   10	CONTINUE
C
C	Initialize FMSPUT:
	CALL FMSPUT (LU_B2, 0, 0, 0, 0, RHS, 0)
C
C	Write out columns of {B2}:
	DO 20 I = 1,NRHS
	   CALL FMSPUT (LU_B2, N2, 1, 1, I, RHS, N2)
   20	CONTINUE
C
C	End FMSPUT:
	CALL FMSPUT (LU_B2, 0, 0, N2+1, 0, RHS, 0)
C
C	Set status:
	LU_B2(7) = 0
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (' Populating {B2}:')
	END
C=======================================================================
	SUBROUTINE J_GS
     1	(LU_A11, LU_F11,
     2	 LU_A12,
     2	 LU_A21,
     4	 LU_A22, LU_F22,
     3	 LU_B1,  LU_X1,
     4	 LU_B2,  LU_X2,
     5	 NEWA11, NEWA22,
     6	 INORM, MAXITR, ERRMAX, METHOD, NOFMSP)
C=======================================================================
C
C	DESCRIPTION:
C	   This subroutine solves the linear system
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | A11 | A12 | | X1 |   | B1 |
C	   +-----+-----+ +----+ = +----+
C	   | A21 | A22 | | X2 |   | B2 |
C	   +-    +    -+ +-  -+   +-  -+
C
C	   using block Jacobi or Gauss_Seidel iteration.
C
C	   On input, the following matrix terms are specified:
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | A11 | A12 | |    |   | B1 |
C	   +-----+-----+ +----+ = +----+
C	   | A21 | A22 | |    |   | B2 |
C	   +-    +    -+ +-  -+   +-  -+
C
C
C	   The following intermediate work arrays are used:
C
C	   +-    +    -+ +-      -+   +-  -+
C	   |     |     | | X1_OLD |   |    |
C	   +-----+-----+ +--------+ = +----+
C	   |     |     | | X2_OLD |   |    |
C	   +-    +    -+ +-      -+   +-  -+
C
C
C	   On output, the following terms are returned:
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | F11 |     | | X1 |   |    |
C	   +-----+-----+ +----+ = +----+
C	   |     | F22 | | X2 |   |    |
C	   +-    +    -+ +-  -+   +-  -+
C
C	You may overlay any of the corresponding input or output terms
C	to save storage by specifying the same actual parameter on the
C	subroutine call.
C
C	FORMAL PARAMETERS:
C	   (R ) LU_A11(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [A11]
C
C	   (R ) LU_F11(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [F11]
C	                      May be the same as LU_A11.
C
C	   (R ) LU_A12(25)  = INTEGER ARRAY
C	                      FMS vector file attributes for [A12]
C	                      Data on this file is not changed.
C
C	   (R ) LU_A21(25)  = INTEGER ARRAY
C	                      FMS vector file attributes for [A21]
C	                      Data on this file is not changed.
C
C	   (R ) LU_A22(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [A22]
C
C	   (R ) LU_F22(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [F22]
C
C	   (R ) LU_B1(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {B1}
C
C	   (R ) LU_X1(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {X1}.
C	                      May be the same as LU_B1.
C
C	   (R ) LU_B2(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {B2}
C
C	   (R ) LU_X2(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {X2}.
C	                      May be the same as LU_B2.
C
C	   (R ) NEWA11      = LOGICAL
C	                      Indicates that [A11] has changed.
C
C	   (R ) NEWA22      = LOGICAL
C	                      Indicates that [A22] has changed.
C
C	   (R ) INORM       = Integer
C	                      Norm for computing convergence:
C	                    = 0, Infinity norm (max. abs. value)
C	                    = 1, First norm
C	                    = 2, Second norm
C
C	   (R ) MAXITR      = Integer
C	                      The maximum number of iterations to
C	                      perform.
C
C	   (R ) ERRMAX      = REAL*8
C	                    = Maximum error for convergence
C
C	   (R ) METHOD      = Integer
C	                    = 1, Jacobi
C	                    = 2, Gauss-Seidel
C
C	   (R ) NOFMSP      = Logical
C	                      Print FMS output in iteration loop.
C
C	FMSCOM PARAMETERS:
C	   (RW) IACCOM      = Multiply accumulate flag
C	   (R ) LUPR        = FORTRAN unit for printing
C
C	CALLED FROM:
C	   EXAMPLE_17
C
C	SUBPROGRAMS USED:
C	   CNDF
C	   CNDS
C	   FMSMM
C
C	ERROR CONDITIONS:
C	   None.
C
C	HISTORY:
C
C	NOTES:
C
C-----------------------------------------------------------------------
C	FORMAL PARAMETERS
C-----------------------------------------------------------------------
	INTEGER    LU_A11(25)
	INTEGER    LU_F11(25)
C
	INTEGER    LU_A12(25)
C
	INTEGER    LU_A21(25)
C
	INTEGER    LU_A22(25)
	INTEGER    LU_F22(25)
C
	INTEGER    LU_B1 (25)
	INTEGER    LU_X1 (25)
C
	INTEGER    LU_B2 (25)
	INTEGER    LU_X2 (25)
C
	LOGICAL    NEWA11
	LOGICAL    NEWA22
	INTEGER    INORM
	INTEGER    MAXITR
	REAL*8     ERRMAX
	INTEGER    METHOD
	LOGICAL    NOFMSP
C-----------------------------------------------------------------------
C	LOCAL VARIABLES
C-----------------------------------------------------------------------
C
	CHARACTER*4 MYNAME
	PARAMETER (MYNAME='J_GS')
C
C	FMS Memory management:
	POINTER   (CMD_PTR, CMD)
	POINTER   (RMD_PTR, RMD)
	POINTER   (IMD_PTR, IMD)
	COMPLEX*16 CMD(0:1)
	REAL*8     RMD(0:1)
	INTEGER    IMD(0:1)
C
C	Data type = complex:
	INTEGER    IDTYPE
	PARAMETER (IDTYPE = 2)
C
C	Skip operations during solving (no):
	INTEGER    ISKIP
	PARAMETER (ISKIP=0)
C
C	Number of solution steps:
	INTEGER    NSTEPS
	PARAMETER (NSTEPS=11)
C
C	Method of solution:
	INTEGER    METHOD_JACOBI
	PARAMETER (METHOD_JACOBI=1)
	INTEGER    METHOD_GAUSS_SEIDEL
	PARAMETER (METHOD_GAUSS_SEIDEL=2)
C
C	Constants:
	COMPLEX*16 C_ONE(1)
	DATA       C_ONE  /( 1.0D0,0.0D0)/
	COMPLEX*16 C_MONE
	DATA       C_MONE /(-1.0D0,0.0D0)/
	REAL*8     R_ZERO
	DATA       R_ZERO /0.0D0/
	REAL*8     R_ONE
	DATA       R_ONE  /1.0D0/
	REAL*8     R_TWO
	DATA       R_TWO  /2.0D0/
	REAL*8     R_THREE
	DATA       R_THREE/3.0D0/
	REAL*8     R_EIGHT
	DATA       R_EIGHT/8.0D0/
C
C	FMS Parameters:
	INTEGER    LUPR
	INTEGER    IPRF
	INTEGER    IPRS
	INTEGER    IPRVV
C
C	Matrix dimensions:
	INTEGER    N1
	INTEGER    N2
	INTEGER    NRHS
	REAL*8     RN1
	REAL*8     RN2
	REAL*8     RNRHS
C
C	Convergence norms:
	REAL*8     R1
	REAL*8     R2
C
C	Temporary files:
	INTEGER    LU_X1_OLD(25)
	INTEGER    LU_X2_OLD(25)
	INTEGER     LUA0  (25)
	DATA        LUA0(1)/0/
	INTEGER     LUS0  (25)
	INTEGER     LUX0  (25)
C
C	CPU, Wall and I/O time:
	REAL*8     TCPU(NSTEPS)
	REAL*8     T1, TCPU_T1  ,TCPU_T2
	REAL*8     TWALL(NSTEPS)
	REAL*8     T2, TWALL_T1 ,TWALL_T2
	REAL*8     TIO(NSTEPS)
	REAL*8     T3, TIO_T1   ,TIO_T2
C
C	Floating point operations:
	REAL*8     OPS(NSTEPS), TOPS
	INTEGER    NCALLS(NSTEPS)
C-----------------------------------------------------------------------
C	FORTRAN PROCEDURE
C-----------------------------------------------------------------------
	CALL FMSPSH (MYNAME)
C
C	Get the FORTRAN unit for printng:
	CALL FMSIGT ('LUPR', LUPR)
C
C	Get the memory pointer for arrays IMD, RMD and CMD:
	CALL FMSIGT ('MEMPTR', IMD_PTR)
	CALL FMSIGT ('MEMPTR', RMD_PTR)
	CALL FMSIGT ('MEMPTR', CMD_PTR)
C
C	Determine the size of the matrices:
	N1    = LU_A11(8)
	N2    = LU_A22(8)
	NRHS  = LU_B1 (6)
	NUMEQ = N1 + N2
	RN1   = DFLOAT(N1)
	RN2   = DFLOAT(N2)
	RNRHS = DFLOAT(NRHS)
	WRITE(LUPR,2000) NUMEQ, N1, N2, NRHS, MAXITR, ERRMAX
C
C	Initialize operation counts and timers for each step:
	DO I=1,NSTEPS
	   OPS   (I) = R_ZERO
	   TCPU  (I) = R_ZERO
	   TWALL (I) = R_ZERO
	   TIO   (I) = R_ZERO
	   NCALLS(I) = 0
	END DO
C
C	Open temporary files for previous solution:
	CALL FMSOV (N1, IDTYPE, NRHS, 'LU_X1_OLD' , LU_X1_OLD )
	CALL FMSOV (N2, IDTYPE, NRHS, 'LU_X2_OLD' , LU_X2_OLD )
C
	CALL FMSTIM (TCPU_T1, TWALL_T1, TIO_T1)
	CALL  TIMER (0, R_ZERO, NCALLS, OPS, TCPU, TWALL, TIO)
C
C	Initialize {X1_OLD} and {X2_OLD}:
C
C  (1)	Factor [A11] into [F11]=[L11][U11]:
	ISTEP =  1
	IF(NEWA11) THEN
	   WRITE(LUPR,2001)
	   CALL CNDAF (LU_A11, C_ONE, 1, LUS0, 0, LUA0, LU_F11,
     1	               LUX0, LUX0, 0)
	   CALL TIMER (1, R_EIGHT*RN1*RN1*RN1/R_THREE,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
	END IF
C
C  (2)	Solve [F11]{X1_OLD} = {B1}:
	WRITE(LUPR,2002)
	CALL CNDS  (LU_F11, LU_B1, LU_X1_OLD, NRHS, 0)
	CALL TIMER (2, R_EIGHT*RN1*RN1*RNRHS,
     1	            NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (3)	Factor [A22] into [F22]=[L22][U22]:
	IF(NEWA22) THEN
	   WRITE(LUPR,2003)
	   CALL CNDAF (LU_A22, C_ONE, 1, LUS0, 0, LUA0, LU_F22,
     1	               LUX0, LUX0, 0)
	   CALL TIMER (3, R_EIGHT*RN2*RN2*RN2/R_THREE,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
	END IF
C
	IF(METHOD .EQ. METHOD_JACOBI) THEN
C
C  (4)	   Not performed:
C
C  (5)	   Solve [F22]{X2_OLD}  = {B2}:
	   WRITE(LUPR,2105)
	   CALL CNDS  (LU_F22, LU_B2,  LU_X2_OLD,  NRHS, 0)
	   CALL TIMER (5, R_EIGHT*RN2*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
	ELSE IF(METHOD .EQ. METHOD_GAUSS_SEIDEL) THEN
C
C  (4)	   Multiply {X2_OLD} = {B2} - [A21]{X1_OLD}:
	   WRITE(LUPR,2204)
	   CALL FMSMM (LU_X2_OLD, LU_B2, -1, 'T', LU_A21, LU_X1_OLD)
	   LU_X1_OLD(7) = 0
	   CALL TIMER (4, R_EIGHT*RN2*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (5)	   Solve [F22]{X2_OLD}  = {X2_OLD}:
	   WRITE(LUPR,2205)
	   CALL CNDS  (LU_F22, LU_X2_OLD,  LU_X2_OLD,  NRHS, 0)
	   CALL TIMER (5, R_EIGHT*RN2*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
	END IF
C
C	Turn off FMS printing in loop, if required:
	IF(NOFMSP) THEN
	   CALL FMSIGT ('IPRF' ,  IPRF)
	   CALL FMSIST ('IPRF' ,     0)
	   CALL FMSIGT ('IPRS' ,  IPRS)
	   CALL FMSIST ('IPRS' ,     0)
	   CALL FMSIGT ('IPRVV', IPRVV)
	   CALL FMSIST ('IPRVV',     0)
	END IF
C
C	Loop over iterations:
	DO 100 NITER = 1,MAXITR
C
C  (6)	   Multiply {X1} = {B1} - [A12]{X2_OLD}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2006)
	   CALL FMSMM (LU_X1, LU_B1, -1, 'N', LU_A12, LU_X2_OLD)
	   LU_X1(7) = 0
	   CALL TIMER (6, R_EIGHT*RN1*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (7)	   Solve [F11]{X1} = {X1}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2007)
	   CALL CNDS  (LU_F11, LU_X1, LU_X1, NRHS, 0)
	   CALL TIMER (7, R_EIGHT*RN1*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
	   IF(METHOD .EQ. METHOD_JACOBI) THEN
C
C  (8)	      Multiply {X2} = {B2} - [A21]{X1_OLD}:
	      IF(.NOT.NOFMSP) WRITE(LUPR,2108)
	      CALL FMSMM (LU_X2, LU_B2, -1, 'T', LU_A21, LU_X1_OLD)
C
	   ELSE IF(METHOD .EQ. METHOD_GAUSS_SEIDEL) THEN
C
C  (8)	      Multiply {X2} = {B2} - [A21]{X1}:
	      IF(.NOT.NOFMSP) WRITE(LUPR,2208)
	      CALL FMSMM (LU_X2, LU_B2, -1, 'T', LU_A21, LU_X1)
C
	   END IF
	   LU_X2(7) = 0
	   CALL TIMER (8, R_EIGHT*RN2*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (9)	   Solve [F22]{X2} = {X2}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2009)
	   CALL CNDS  (LU_F22, LU_X2, LU_X2, NRHS, 0)
	   CALL TIMER (9, R_EIGHT*RN2*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C (10)	   R1=|| ( {X1} - {X1_OLD} )/ {X1} ||; {X1}->{X1_OLD}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2010)
	   CALL FMSVAN (LU_X1_OLD, -1, LU_X1, INORM, R1, 3)
	   IF(INORM .GT. 1) THEN
	      R1 = R1/RN1
	   ELSE IF(INORM .EQ. 2) THEN
	      R1 = R1/SQRT(RN1)
	   END IF
	   CALL TIMER (10, R_TWO*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C (11)	   R2=|| ( {X2} - {X2_OLD} )/ {X2} ||; {X2}->{X2_OLD}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2011)
	   CALL FMSVAN (LU_X2_OLD, -1, LU_X2, INORM, R2, 3)
	   IF(INORM .GT. 1) THEN
	      R2 = R2/RN2
	   ELSE IF(INORM .EQ. 2) THEN
	      R2 = R2/SQRT(RN2)
	   END IF
	   CALL TIMER (11, R_TWO*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
	   WRITE(LUPR,2050) NITER, R1, R2
C
	   IF( ( R1 .LE. ERRMAX) .AND.
     1	       ( R2 .LE. ERRMAX) ) GO TO 101
  100	CONTINUE
  101	CONTINUE
C
C	Close temporary files:
	CALL FMSCV (LU_X1_OLD)
	CALL FMSCV (LU_X2_OLD)
C
C	Print timings:
	WRITE(LUPR,2020)
	CALL FMSTIM (TCPU_T2, TWALL_T2, TIO_T2)
	TOPS = R_ZERO
	DO 200 ISTEP = 1,NSTEPS
	   NCALL = NCALLS(ISTEP)
	   IF(NCALL .EQ. 0) THEN
C
C	      Operation skipped:
	      WRITE(LUPR,2022) ISTEP
	   ELSE
	      TOPS = TOPS + OPS(ISTEP)
C
C	      CPU time and Mflops:
	      T1 = TCPU(ISTEP)
	      IF(T1 .GT. R_ZERO) THEN
	         MF1   = ((1.0D-6)*OPS(ISTEP)/T1)
	      ELSE
	         MF1   = 0
	      END IF
C
C	      Wall time, Mflops and ratio:
	      T2 = TWALL(ISTEP)
	      T3 = TIO(ISTEP)
	      IF((T2 .GT. R_ZERO) .AND.
     1	         (T2 .GT.  T3   ) ) THEN
	         MF2   = ((1.0D-6)*OPS(ISTEP)/T2)
	         RATIO = T1/(T2-T3)
	      ELSE
	         MF2   = 0
	         RATIO = R_ONE
	      END IF
	      WRITE(LUPR,2021) ISTEP, NCALL, T1, T2, T3, MF1, MF2, RATIO
	   END IF
  200	CONTINUE
	T1 = TCPU_T2  - TCPU_T1
	T2 = TWALL_T2 - TWALL_T1
	T3 = TIO_T2   - TIO_T1
	IF(T1 .GT. R_ZERO) THEN
	   MF1   = ((1.0D-6)*TOPS/T1)
	ELSE
	   MF1   = 0
	END IF
	IF(T2 .GT. R_ZERO) THEN
	   MF2   = ((1.0D-6)*TOPS/T2)
	   RATIO = T1/(T2-T3)
	ELSE
	   MF2   = 0
	   RATIO = R_ONE
	END IF
	IF(NOFMSP) THEN
C	   Restore print settings:
	   CALL FMSIST ('IPRF' ,  IPRF)
	   CALL FMSIST ('IPRS' ,  IPRS)
	   CALL FMSIST ('IPRVV', IPRVV)
	END IF
	WRITE(LUPR,2023) T1, T2, T3, MF1, MF2, RATIO
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (/
     1	' Start of Subroutine J_GS',/
     2	' Rank of full matrix............=',I8/
     3	' Rank of submatrix #1...........=',I8/
     4	' Rank of submatrix #2...........=',I8/
     5	' # of right-hand-sides..........=',I8/
     6	' Maximum number of iterations...=',I8/
     7	' Maximum error norm.............=',E8.1/)
 2001	FORMAT (/
     1	' STEP  1. Factor   [A11] into [F11]'/
     2	' ==================================')
 2002	FORMAT (/
     1	' STEP  2. Solve    [F11]{X1_OLD}  = {B1}'/
     2	' =======================================')
 2003	FORMAT (/
     1	' STEP  3. Factor   [A22] into [F22]'/
     2	' ==================================')
 2204	FORMAT (/
     1	' STEP  4. Multiply {X2_OLD} = {B2} - [A21]{X1_OLD}'/
     2	' =================================================')
 2105	FORMAT (/
     1	' STEP  5. Solve    [F22]{X2_OLD}  = {B2}'/
     2	' ======================================')
 2205	FORMAT (/
     1	' STEP  5. Solve    [F22]{X2_OLD}  = {X2_OLD}'/
     2	' ===========================================')
 2006	FORMAT (/
     1	' STEP  6. Multiply {X1} = {B1} - [A12]{X2_OLD}'/
     2	' =============================================')
 2007	FORMAT (/
     1	' STEP  7. Solve    [F11]{X1} = {X1}'/
     2	' ==================================')
 2108	FORMAT (/
     1	' STEP  8. Multiply {X2} = {B2} - [A21]{X1_OLD}'/
     2	' =============================================')
 2208	FORMAT (/
     1	' STEP  8. Multiply {X2} = {B2} - [A21]{X1}'/
     2	' =========================================')
 2009	FORMAT (/
     1	' STEP  9. Solve    [F22]{X2} = {X2}'/
     2	' ==================================')
 2010	FORMAT (/
     1	' STEP 10. |( {X1} - {X1_OLD} )/{X1}; {X1}->{X1_OLD}'/,
     2	' ==================================================')
 2011	FORMAT (/
     1	' STEP 11. |( {X2} - {X2_OLD} )/{X2}; {X2}->{X2_OLD}'/,
     2	' ===================================================')
 2020	FORMAT (/
     1	' Summary of Subroutine J_GS:'//
     2	'                <----------TIMES (Sec.)----------->',
     2	'    <--MFLOPS-->'/
     2	'  STEP   RUN          CPU         WALL          I/O',
     2	'     CPU    WALL',
     2	'    RATIO'/
     3	' =====   ===    =========    =========    =========',
     3	'    ====    ====',
     3	'    =====')
 2021	FORMAT (2I6,3F13.3,2I8,F9.3)
 2022	FORMAT (I6,12X,'Skipped')
 2023	FORMAT (' TOTAL',6X,3F13.3,2I8,F9.3)
 2050	FORMAT (
     1	' ITERATION=',I3,
     2	', {DX1}NORM=',E12.3,
     3	', {DX2}NORM=',E12.3)
	END
C=======================================================================
	SUBROUTINE JACOBI2
     1	(LU_A11, LU_F11,
     2	 LU_A12,
     2	 LU_A21,
     4	 LU_A22, LU_F22,
     3	 LU_B1,  LU_X1,
     4	 LU_B2,  LU_X2,
     5	 NEWA11, NEWA22,
     6	 INORM, MAXITR, ERRMAX, NOFMSP)
C=======================================================================
C
C	DESCRIPTION:
C	   This subroutine solves the linear system
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | A11 | A12 | | X1 |   | B1 |
C	   +-----+-----+ +----+ = +----+
C	   | A21 | A22 | | X2 |   | B2 |
C	   +-    +    -+ +-  -+   +-  -+
C
C	   using an incremental form of block Jacobi iteration.
C
C
C	   On input, the following matrix terms are specified:
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | A11 | A12 | |    |   | B1 |
C	   +-----+-----+ +----+ = +----+
C	   | A21 | A22 | |    |   | B2 |
C	   +-    +    -+ +-  -+   +-  -+
C
C
C	   The following intermediate work arrays are used:
C
C	   +-    +    -+ +-      -+   +-  -+
C	   |     |     | | DX1(2) |   |    |
C	   +-----+-----+ +--------+ = +----+
C	   |     |     | | DX2(2) |   |    |
C	   +-    +    -+ +-      -+   +-  -+
C
C
C	   On output, the following terms are returned:
C
C	   +-    +    -+ +-  -+   +-  -+
C	   | F11 |     | | X1 |   |    |
C	   +-----+-----+ +----+ = +----+
C	   |     | F22 | | X2 |   |    |
C	   +-    +    -+ +-  -+   +-  -+
C
C	You may overlay any of the corresponding input or output terms
C	to save storage by specifying the same actual parameter on the
C	subroutine call.
C
C	FORMAL PARAMETERS:
C	   (R ) LU_A11(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [A11]
C
C	   (R ) LU_F11(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [F11]
C	                      May be the same as LU_A11.
C
C	   (R ) LU_A12(25)  = INTEGER ARRAY
C	                      FMS vector file attributes for [A12]
C
C	   (R ) LU_A21(25)  = INTEGER ARRAY
C	                      FMS vector file attributes for [A21]
C	                      Data on this file is not changed.
C
C	   (R ) LU_A22(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [A22]
C
C	   (R ) LU_F22(25)  = INTEGER ARRAY
C	                      FMS matrix file attributes for [F22]
C
C	   (R ) LU_B1(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {B1}
C
C	   (R ) LU_X1(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {X1}.
C	                      May be the same as LU_B1.
C
C	   (R ) LU_B2(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {B2}
C
C	   (R ) LU_X2(25)   = INTEGER ARRAY
C	                      FMS vector file attributes for {X2}.
C	                      May be the same as LU_B2.
C
C	   (R ) NEWA11      = LOGICAL
C	                      Indicates that [A11] has changed.
C
C	   (R ) NEWA22      = LOGICAL
C	                      Indicated that [A22] has changed.
C
C	   (R ) INORM       = Integer
C	                      Norm for computing convergence:
C	                    = 0, Infinity norm (max. abs. value)
C	                    = 1, First norm
C	                    = 2, Second norm
C
C	   (R ) MAXITR      = Integer
C	                      The maximum number of iterations to
C	                      perform.
C
C	   (R ) ERRMAX      = REAL*8
C	                    = Maximum error for convergence
C
C	   (R ) NOFMSP      = Logical
C	                      Print FMS output in iteration loop.
C
C	FMSCOM PARAMETERS:
C	   (RW) IACCOM      = Multiply accumulate flag
C	   (R ) LUPR        = FORTRAN unit for printing
C
C	CALLED FROM:
C	   EXAMPLE_17
C
C	SUBPROGRAMS USED:
C	   CNDF
C	   CNDS
C	   FMSMM
C
C	ERROR CONDITIONS:
C	   None.
C
C	HISTORY:
C
C	NOTES:
C
C	In this iterative approach, let {X1} and {X2} represent the
C	exact solution and {DX1} and {DX2} the error.
C
C	Expanding the partitioned system gives:
C
C	[A11]({X1}+{DX1}) + [A12]({X2}+{DX2}) = {B1}      (1)
C	[A21]({X1}+{DX1}) + [A22]({X2}+{DX2}) = {B2}      (2)
C
C	or
C
C	[A11]{X1} + [A11]{DX1} + [A12]{X2} + [A12]{DX2} = {B1}  (3)
C	[A21]{X1} + [A21]{DX1} + [A22]{X2} + [A22]{DX2} = {B2}  (4)
C
C	or
C
C	([A11]{X1}+[A12]{X2}-{B1}) + [A11]{DX1} = -[A12]{DX2}   (5)
C	([A21]{X1}+[A22]{X2}-{B2}) + [A22]{DX2} = -[A21]{DX1}   (6)
C
C	Noting that the first term in (5) and (6) is zero gives
C
C	[A11]{DX1} = -[A12]{DX2}     (7)
C	[A22]{DX2} = -[A21]{DX1}     (8)
C
C	which may be used to compute improved values of the error
C	{DX1} and {DX2}.
C-----------------------------------------------------------------------
C	FORMAL PARAMETERS
C-----------------------------------------------------------------------
	INTEGER    LU_A11(25)
	INTEGER    LU_F11(25)
C
	INTEGER    LU_A12(25)
C
	INTEGER    LU_A21(25)
C
	INTEGER    LU_A22(25)
	INTEGER    LU_F22(25)
C
	INTEGER    LU_B1 (25)
	INTEGER    LU_X1 (25)
C
	INTEGER    LU_B2 (25)
	INTEGER    LU_X2 (25)
C
	LOGICAL    NEWA11
	LOGICAL    NEWA22
	INTEGER    INORM
	INTEGER    MAXITR
	REAL*8     ERRMAX
	LOGICAL    NOFMSP
C-----------------------------------------------------------------------
C	LOCAL VARIABLES
C-----------------------------------------------------------------------
C
	CHARACTER*7 MYNAME
	PARAMETER (MYNAME='JACOBI2')
C
C	FMS Memory management:
	POINTER   (CMD_PTR, CMD)
	POINTER   (RMD_PTR, RMD)
	POINTER   (IMD_PTR, IMD)
	COMPLEX*16 CMD(0:1)
	REAL*8     RMD(0:1)
	INTEGER    IMD(0:1)
C
C	Data type = complex:
	INTEGER    IDTYPE
	PARAMETER (IDTYPE = 2)
C
C	Skip operations during solving (no):
	INTEGER    ISKIP
	PARAMETER (ISKIP=0)
C
C	Number of solution steps:
	INTEGER    NSTEPS
	PARAMETER (NSTEPS=10)
C
C	Constants:
	COMPLEX*16 C_ONE(1)
	DATA       C_ONE  /( 1.0D0,0.0D0)/
	COMPLEX*16 C_MONE
	DATA       C_MONE /(-1.0D0,0.0D0)/
	REAL*8     R_ZERO
	DATA       R_ZERO / 0.0D0/
	REAL*8     R_ONE
	DATA       R_ONE  / 1.0D0/
	REAL*8     R_TWO
	DATA       R_TWO  / 2.0D0/
	REAL*8     R_THREE
	DATA       R_THREE/ 3.0D0/
	REAL*8     R_EIGHT
	DATA       R_EIGHT/ 8.0D0/
C
C	FMS Parameters:
	INTEGER    LUPR
	INTEGER    IPRF
	INTEGER    IPRS
	INTEGER    IPRVV
C
C	Matrix dimensions:
	INTEGER    N1
	INTEGER    N2
	INTEGER    NRHS
	REAL*8     RN1
	REAL*8     RN2
	REAL*8     RNRHS
C
C	Convergence ratios:
	REAL*8     R1
	REAL*8     R2
C
C	Temporary files:
	INTEGER    LU_DX1(25,2), LU_DX1_SAVE(25)
	INTEGER    LU_DX2(25,2), LU_DX2_SAVE(25)
	INTEGER     LUA0  (25)
	DATA        LUA0(1)/0/
	INTEGER     LUS0  (25)
	INTEGER     LUX0  (25)
	INTEGER     LUD   (25)
C
C	CPU, Wall and I/O time:
	REAL*8     TCPU(NSTEPS)
	REAL*8     T1, TCPU_T1  ,TCPU_T2
	REAL*8     TWALL(NSTEPS)
	REAL*8     T2, TWALL_T1 ,TWALL_T2
	REAL*8     TIO(NSTEPS)
	REAL*8     T3, TIO_T1   ,TIO_T2
C
C	Floating point operations:
	REAL*8     OPS(NSTEPS), TOPS
	INTEGER    NCALLS(NSTEPS)
C
C	Sign for adding solution:
	INTEGER    ISIGN
C-----------------------------------------------------------------------
C	FORTRAN PROCEDURE
C-----------------------------------------------------------------------
	CALL FMSPSH (MYNAME)
C
C	Get the FORTRAN unit for printng:
	CALL FMSIGT ('LUPR', LUPR)
C
C	Get the memory pointer for arrays IMD, RMD and CMD:
	CALL FMSIGT ('MEMPTR', IMD_PTR)
	CALL FMSIGT ('MEMPTR', RMD_PTR)
	CALL FMSIGT ('MEMPTR', CMD_PTR)
C
C	Determine the size of the matrices:
	N1    = LU_A11(8)
	N2    = LU_A22(8)
	NRHS  = LU_B1 (6)
	NUMEQ = N1 + N2
	RN1   = DFLOAT(N1)
	RN2   = DFLOAT(N2)
	RNRHS = DFLOAT(NRHS)
	WRITE(LUPR,2000) NUMEQ, N1, N2, NRHS, MAXITR, ERRMAX
C
C	Initialize operation counts and timers for each step:
	DO I=1,NSTEPS
	   OPS   (I) = R_ZERO
	   TCPU  (I) = R_ZERO
	   TWALL (I) = R_ZERO
	   TIO   (I) = R_ZERO
	   NCALLS(I) = 0
	END DO
C
C	Open temporary files for residual vectors:
	CALL FMSOV (N1, IDTYPE, NRHS, 'LU_DX1_1' , LU_DX1(1,1))
	CALL FMSOV (N1, IDTYPE, NRHS, 'LU_DX1_2' , LU_DX1(1,2))
	CALL FMSOV (N2, IDTYPE, NRHS, 'LU_DX2_1' , LU_DX2(1,1))
	CALL FMSOV (N2, IDTYPE, NRHS, 'LU_DX2_2' , LU_DX2(1,2))
	LUD(1) = 0
C
	CALL FMSTIM (TCPU_T1, TWALL_T1, TIO_T1)
	CALL TIMER  (0, R_ZERO, NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (1)	Factor [A11] into [F11]=[L11][U11]:
	IF(NEWA11) THEN
	   WRITE(LUPR,2001)
	   CALL CNDAF (LU_A11, C_ONE, 1, LUS0, 0, LUA0, LU_F11,
     1	               LUX0, LUX0, 0)
	   CALL TIMER (1, R_EIGHT*RN1*RN1*RN1/R_THREE,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
	END IF
C
C  (2)	Solve [F11][X1] = [B1]:
	WRITE(LUPR,2002)
	CALL CNDS  (LU_F11, LU_B1, LU_X1, NRHS,   0)
	CALL TIMER (2, R_EIGHT*RN1*RN1*RNRHS,
     1	            NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (3)	Factor [A22] into [F22]=[L22][U22]:
	IF(NEWA22) THEN
	   WRITE(LUPR,2003)
	   CALL CNDAF (LU_A22, C_ONE, 1, LUS0, 0, LUA0, LU_F22,
     1	               LUX0, LUX0, 0)
	   CALL TIMER (3, R_EIGHT*RN2*RN2*RN2/R_THREE,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
	END IF
C
C  (4)	Solve [F22]{X2}  = {B2}:
	WRITE(LUPR,2004)
	CALL CNDS  (LU_F22, LU_B2,  LU_X2,  NRHS, 0)
	CALL TIMER (4, R_EIGHT*RN2*RN2*RNRHS,
     1	            NCALLS, OPS, TCPU, TWALL, TIO)
C
C	On the first pass, use {X1} and {X2} for {DX1}(KOLD) and
C	{DX2}(KOLD):
	K     = 2
	DO I=1,25
	   LU_DX1_SAVE(I) = LU_DX1(I,K)
	   LU_DX2_SAVE(I) = LU_DX2(I,K)
	   LU_DX1(I,K)    = LU_X1(I)
	   LU_DX2(I,K)    = LU_X2(I)
	END DO
C
C	Turn off FMS printing in loop, if required:
	IF(NOFMSP) THEN
	   CALL FMSIGT ('IPRF' ,  IPRF)
	   CALL FMSIST ('IPRF' ,     0)
	   CALL FMSIGT ('IPRS' ,  IPRS)
	   CALL FMSIST ('IPRS' ,     0)
	   CALL FMSIGT ('IPRVV', IPRVV)
	   CALL FMSIST ('IPRVV',     0)
	END IF
C
C	Loop over iterations:
	ISIGN = 1
	DO 100 NITER = 1, MAXITR
	   KOLD  = K
	   K     = 3 - K
	   ISIGN = -ISIGN
C
C  (5)	   Multiply {DX1}(K) = [A12]{DX2}(KOLD}:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2005) K, KOLD
	   CALL FMSMM (LU_DX1(1,K), LUD, 0, 'N', LU_A12,
     1	               LU_DX2(1,KOLD))
	   LU_DX1(7,K) = 0
	   CALL TIMER (5, R_EIGHT*RN1*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (6)	   Solve [F11]{DX1}(K) = {DX1}(K):
	   IF(.NOT.NOFMSP) WRITE(LUPR,2006) K, K
	   CALL CNDS  (LU_F11, LU_DX1(1,K), LU_DX1(1,K), NRHS, 0)
	   CALL TIMER (6, R_EIGHT*RN1*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (7)	   Compute {X1} = {X1} + (ISIGN)*{DX1} and compute norm R1:
	   IF(.NOT.NOFMSP) WRITE(LUPR,2007) K
	   CALL FMSVAN (LU_X1, ISIGN, LU_DX1(1,K), INORM, R1, 1)
	   IF(INORM .GT. 1) THEN
	      R1 = R1/RN1
	   ELSE IF(INORM .EQ. 2) THEN
	      R1 = R1/SQRT(RN1)
	   END IF
	   CALL TIMER (7, R_TWO*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (8)	   Multiply {DX2}(K) = [A21]{DX1}(KOLD):
	   IF(.NOT.NOFMSP) WRITE(LUPR,2008) K, KOLD
	   CALL FMSMM (LU_DX2(1,K), LUD, 0, 'T', LU_A21,
     1	               LU_DX1(1,KOLD))
	   LU_DX2(7,K) = 0
	   CALL TIMER (8, R_EIGHT*RN2*RN1*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C  (9)	   Solve [F22]{DX2}(K) = {DX2}(K):
	   IF(.NOT.NOFMSP) WRITE(LUPR,2009) K, K
	   CALL CNDS  (LU_F22, LU_DX2(1,K), LU_DX2(1,K), NRHS, 0)
	   CALL TIMER (9, R_EIGHT*RN2*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
C (10)	   Compute {X2} = {X2} + (ISIGN)*{DX2}(K):
	   IF(.NOT. NOFMSP) WRITE(LUPR,2010) K
	   CALL FMSVAN (LU_X2, ISIGN, LU_DX2(1,K), INORM, R2, 1)
	   IF(INORM .GT. 1) THEN
	      R2 = R2/RN2
	   ELSE IF(INORM .EQ. 2) THEN
	      R2 = R2/SQRT(RN2)
	   END IF
	   CALL TIMER (10, R_TWO*RN2*RNRHS,
     1	               NCALLS, OPS, TCPU, TWALL, TIO)
C
	   WRITE(LUPR,2050) NITER, R1, R2
	   IF(NITER .EQ. 1) THEN
C	      Redefine LU_DX1 and LU_DX2:
	      DO I=1,25
	         LU_DX1(I,KOLD) = LU_DX1_SAVE(I)
	         LU_DX2(I,KOLD) = LU_DX2_SAVE(I)
	      END DO
	   END IF
C
C	   Test for convergence:
	   IF( (R1 .LT. ERRMAX) .AND.
     1	       (R2 .LT. ERRMAX) ) GO TO 101
  100	CONTINUE
  101	CONTINUE
C
C	Close temporary files:
	CALL FMSCV  (LU_DX1(1,1))
	CALL FMSCV  (LU_DX1(1,2))
	CALL FMSCV  (LU_DX2(1,1))
	CALL FMSCV  (LU_DX2(1,2))
C
C	Print timings:
	WRITE(LUPR,2020)
	CALL FMSTIM (TCPU_T2, TWALL_T2, TIO_T2)
	TOPS = R_ZERO
	DO 200 ISTEP = 1,NSTEPS
	   NCALL = NCALLS(ISTEP)
	   IF(NCALL .EQ. 0) THEN
C
C	      Operation skipped:
	      WRITE(LUPR,2022) ISTEP
	   ELSE
	      TOPS = TOPS + OPS(ISTEP)
C
C	      CPU time and Mflops:
	      T1 = TCPU(ISTEP)
	      IF(T1 .GT. R_ZERO) THEN
	         MF1   = ((1.0D-6)*OPS(ISTEP)/T1)
	      ELSE
	         MF1   = 0
	      END IF
C
C	      Wall time, Mflops and ratio:
	      T2 = TWALL(ISTEP)
	      T3 = TIO(ISTEP)
	      IF((T2 .GT. R_ZERO) .AND.
     1	         (T2 .GT.  T3   ) ) THEN
	         MF2   = ((1.0D-6)*OPS(ISTEP)/T2)
	         RATIO = T1/(T2-T3)
	      ELSE
	         MF2   = 0
	         RATIO = R_ONE
	      END IF
	      WRITE(LUPR,2021) ISTEP, NCALL, T1, T2, T3, MF1, MF2, RATIO
	   END IF
  200	CONTINUE
	T1 = TCPU_T2  - TCPU_T1
	T2 = TWALL_T2 - TWALL_T1
	T3 = TIO_T2   - TIO_T1
	IF(T1 .GT. R_ZERO) THEN
	   MF1   = ((1.0D-6)*TOPS/T1)
	ELSE
	   MF1   = 0
	END IF
	IF(T2 .GT. R_ZERO) THEN
	   MF2   = ((1.0D-6)*TOPS/T2)
	   RATIO = T1/(T2-T3)
	ELSE
	   MF2   = 0
	   RATIO = R_ONE
	END IF
	IF(NOFMSP) THEN
C	   Restore print settings:
	   CALL FMSIST ('IPRF' ,  IPRF)
	   CALL FMSIST ('IPRS' ,  IPRS)
	   CALL FMSIST ('IPRVV', IPRVV)
	END IF
	WRITE(LUPR,2023) T1, T2, T3, MF1, MF2, RATIO
	CALL FMSPOP (MYNAME)
	RETURN
 2000	FORMAT (/
     1	' Start of Subroutine JACOBI2',/
     2	' Rank of full matrix............=',I8/
     3	' Rank of submatrix #1...........=',I8/
     4	' Rank of submatrix #2...........=',I8/
     5	' # of right-hand-sides..........=',I8/
     6	' Maximum number of iterations...=',I8/
     7	' Maximum error norm.............=',E8.1/)
 2001	FORMAT (/
     1	' STEP  1. Factor   [A11] into [F11]'/
     2	' ==================================')
 2002	FORMAT (/
     1	' STEP  2. Solve    [F11]{X1}  = {B1}'/
     2	' ===================================')
 2003	FORMAT (/
     1	' STEP  3. Factor   [A22] into [F22]'/
     2	' ==================================')
 2004	FORMAT (/
     1	' STEP  4. Solve    [F22]{X2}  = {B2}'/
     2	' ===================================')
 2005	FORMAT (/
     1	' STEP  5. Multiply {DX1}(',i1,') = [A12]{DX2}(',i1,')'/
     2	' ==========================================')
 2006	FORMAT (/
     1	' STEP  6. Solve    [F11]{DX1}(',I1,') = {DX1}(',I1,')'/
     2	' ==========================================')
 2007	FORMAT (/
     1	' STEP  7. Add      {X1} = {X1} + (ISIGN)*{DX1}(',I1,')'/
     2	' ================================================')
 2008	FORMAT (/
     1	' STEP  8. Multiply {DX2}(',I1,') = [A21]{DX1}(',I1,')'/
     2	' ==========================================')
 2009	FORMAT (/
     1	' STEP  9. Solve    [F22]{DX2}(',I1,') = {DX2}(',I1,')'/
     2	' ==========================================')
 2010	FORMAT (/
     1	' STEP 10. Add      {X2} = {X2} + (ISIGN)*{DX2}(',I1,')'/
     2	' ================================================')
 2020	FORMAT (/
     1	' Summary of Subroutine JACOBI2:'//
     2	'                <----------TIMES (Sec.)----------->',
     2	'    <--MFLOPS-->'/
     2	'  STEP   RUN          CPU         WALL          I/O',
     2	'     CPU    WALL',
     2	'    RATIO'/
     3	' =====   ===    =========    =========    =========',
     3	'    ====    ====',
     3	'    =====')
 2021	FORMAT (2I6,3F13.3,2I8,F9.3)
 2022	FORMAT (I6,12X,'Skipped')
 2023	FORMAT (' TOTAL',6X,3F13.3,2I8,F9.3)
 2050	FORMAT (
     1	' ITERATION=',I3,
     2	', {DX1}NORM=',E12.3,
     3	', {DX2}NORM=',E12.3)
	END
C=======================================================================
	SUBROUTINE TIMER (ICALL, OPSINC,
     1	 NCALLS, OPS, TCPU, TWALL, TIO)
C=======================================================================
	INTEGER ICALL
	REAL*8  OPSINC
	INTEGER NCALLS(*)
	REAL*8  OPS(*)
	REAL*8  TCPU(*)
	REAL*8  TWALL(*)
	REAL*8  TIO(*)
	COMMON /FMSTIMES/TCPU1, TWALL1, TIO1
	REAL*8  TCPU1, TWALL1, TIO1
	REAL*8  TCPU2, TWALL2, TIO2
	IF(ICALL .EQ. 0) THEN
	   CALL FMSTIM (TCPU1, TWALL1, TIO1)
	ELSE
	   CALL FMSTIM (TCPU2, TWALL2, TIO2)
	   NCALLS(ICALL) = NCALLS(ICALL) + 1
	   OPS   (ICALL) = OPS   (ICALL) + OPSINC
	   TCPU  (ICALL) = TCPU  (ICALL) + (TCPU2  - TCPU1 )
	   TWALL (ICALL) = TWALL (ICALL) + (TWALL2 - TWALL1)
	   TIO   (ICALL) = TIO   (ICALL) + (TIO2   - TIO1  )
	   TCPU1  = TCPU2
	   TWALL1 = TWALL2
	   TIO1   = TIO2
	END IF
	RETURN
	END
Copyright © Multipath Corporation