C T E S T R E S O L V C C This program tests subroutine RESOLV. 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_14') C C FMS matrix and vector file attributes: INTEGER LU_A11(25) INTEGER LU_A12(25) INTEGER LU_A21(25) INTEGER LU_A22(25), LU_F22(25) INTEGER LU_B1 (25), LU_X1(25) INTEGER LU_B2 (25), LU_S2(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 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 [A12] matrix: LOGICAL NEWA12 C Form a new [A21] matrix: LOGICAL NEWA21 C Form a new [A22] matrix: LOGICAL NEWA22 C Form a new {B1} matrix: LOGICAL NEWB1 C Form a new {B2} matrix: LOGICAL NEWB2 C Check the values of {X2}: LOGICAL ICK_X2 C Error on current term: REAL*8 EI C Maximum overall error: REAL*8 E2MAX, ERROR C CMD Pointer to scratch vector: INTEGER L_TEMP C C Profile vector for a full matrix: INTEGER LOWEQ(1) DATA LOWEQ/-1/ C C CONSTANTS: 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: 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') 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 FMSOM (LU_A22, 'LU_F22', LU_F22) 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_S2' , LU_S2 ) CALL FMSOV (N2, IDTYPE, NRHS, 'LU_X2' , LU_X2 ) C C (3) Write data to FMS files: NEWA11 = .TRUE. NEWA12 = .TRUE. NEWA21 = .TRUE. NEWA22 = .TRUE. NEWB1 = .TRUE. NEWB2 = .TRUE. ICK_X2 = .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]: IF(NEWA12) CALL A12GEN (CMD(L_TEMP), N1, N2, LU_A12) C C Generate [A21]: IF(NEWA21) 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}: IF(NEWB1 ) CALL B1GEN (CMD(L_TEMP), N1, NRHS, LU_B1 ) C C Generate {B2}: IF(NEWB2 ) CALL B2GEN (CMD(L_TEMP), N2, NRHS, LU_B2 ) C C (4) Perform matrix algebra: CALL RESOLV 1 (LU_A11, LU_A11, 2 LU_A12, LU_A12, 3 LU_A21, 4 LU_A22, LU_F22, 5 LU_B1, LU_B1, LU_X1, 6 LU_B2, LU_S2, LU_X2, 7 NEWA11, NEWA12, 8 NEWA21, NEWA22, 9 NEWB1, NEWB2, 1 ICK_X2, E2MAX) C C (5) Read data from FMS files: C Check the answer: ERROR = E2MAX C C Initialize FMSGET: CALL FMSGET (LU_X1, 0, 0, 0, 0, CMD, 0) DO 60 IRHS = 1,NRHS C C Check {X1}: CALL FMSGET (LU_X1, N1, 1, 1, IRHS, CMD(L_TEMP), N1) DO 51 I = 0,(N1-1) EI = ABS(CMD(L_TEMP+I) - C_ONE) IF(EI .GT. ERROR) ERROR = EI 51 CONTINUE 60 CONTINUE C C End FMSGET: CALL FMSGET (LU_X1, 0, 0, N1+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?')) GO TO 100 NEWA11 = ASK('Do you want a new A11?') NEWA12 = ASK('Do you want a new A12?') NEWA21 = ASK('Do you want a new A21?') NEWA22 = ASK('Do you want a new A22?') NEWB1 = ASK('Do you want a new B1?' ) NEWB2 = ASK('Do you want a new B2?' ) C C We have chosen to overlay factored data on input matrices. C Therefore if new factors must be recomputed, the arrays must C be reset to the unfactored values. C Based on the options selected above, these conditions become: IF( NEWA11 ) THEN NEWA12 = .TRUE. NEWA22 = .TRUE. NEWB1 = .TRUE. NEWB2 = .TRUE. END IF IF( NEWA12 ) NEWA22 = .TRUE. IF( NEWB1 ) NEWB2 = .TRUE. IF( NEWA11 .OR. 1 NEWA12 .OR. 2 NEWA21 .OR. 3 NEWA22 .OR. 4 NEWB1 .OR. 5 NEWB2) 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 FMSCM (LU_F22) CALL FMSCV (LU_B1 ) CALL FMSCV (LU_X1 ) CALL FMSCV (LU_B2 ) CALL FMSCV (LU_S2 ) CALL FMSCV (LU_X2 ) CALL FMSCMR (CMD, L_TEMP, NMAX) 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======================================================================= 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 R_ZERO, A11_Re DATA R_ZERO/0.0D0/ COMPLEX*16 C_MONE, C_ZERO, C_ONE DATA C_MONE/(-1.0D0,0.0D0)/ 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_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_MONE, C_ZERO DATA C_MONE/(-1.0D0,0.0D0)/ DATA C_ZERO/( 0.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_MONE, C_ZERO DATA C_MONE/(-1.0D0,0.0D0)/ DATA C_ZERO/( 0.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 RESOLV 1 (LU_A11, LU_F11, 2 LU_A12, LU_F12, 2 LU_A21, 4 LU_A22, LU_F22, 3 LU_B1, LU_S1, LU_X1, 4 LU_B2, LU_S2, LU_X2, 5 NEWA11, NEWA12, 6 NEWA21, NEWA22, 7 NEWB1, NEWB2, 6 ICK_X2, E2MAX) 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 when all or only part of the matrix terms change. 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 | | | | S1 | | | C +-----+-----+ +----+ = +----+ C | | | | S2 | | | C +- + -+ +- -+ +- -+ C C C On output, the following terms are returned: C C +- + -+ +- -+ +- -+ C | F11 | F12 | | X1 | | | C +-----+-----+ +----+ = +----+ C | | F22 | | X2 | | | C +- + -+ +- -+ +- -+ C C You may overlay any of the corresponding input, intermediate C or output terms to save storage by specifying the same actual C parameter on the subroutine call. C C Arrays containing input data may share storage with C intermediate and output arrays if these conditions are met: C 1) If any value changes in the input array, all values in that C input array are redefined. C 2) In defining the new values for an array, the previous C values are not required. (They are no longer available C because they have been overwritten) C If these conditions are true, then the following arrays can C share the same storage: C [A11] & [F11], C [A12] & [F12], C [A22] & [F22], C {B1} & {S1}, C {B2} & {S2}. C C Ths storage for {S1} and {S2} can be shared with {X1} and {X2}. C No additional computation is required if the following C conditions are met: C {S1} & {X1} : if [A11] or {B1} change, C {S2} & {X2} : if [A11], [A12], {B1} or {B2} change. C If these conditions are not met and the storage is shared, then C additional computation will be performed. C C You may also overlay {B1},{S1},{X1} or {B2},{S2},{X2} if C all the above conditions are met. 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_F12(25) = INTEGER ARRAY C FMS vector file attributes for [F12] C May be the same as LU_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 mtarix 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_S1(25) = INTEGER ARRAY C FMS vector file attributes for {S1}. C This is an intermediate work array. C May be the same value as LU_B1. C C (R ) LU_X1(25) = INTEGER ARRAY C FMS vector file attributes for {X1}. C May be the same as LU_S1. C C (R ) LU_B2(25) = INTEGER ARRAY C FMS vector file attributes for {B2} C C (R ) LU_S2(25) = INTEGER ARRAY C FMS vector file attributes for {S2}. C This is an intermediate work array. C May be the same value as LU_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 ) NEWA12 = LOGICAL C Indicated that [A12] has changed. C C (R ) NEWA21 = LOGICAL C Indicated that [A21] has changed. C C (R ) NEWA22 = LOGICAL C Indicated that [A22] has changed. C C (R ) NEWB1 = Logical C Indicates that {B1} has changed. C C (R ) NEWB2 = Logical C Indicates that {B2} has changed. C C (R ) ICK_X2 = Logical C Check the values in {X2}. C This requires access to [A22] and {B2}. C Requires the following: C LU_S2 or LU_X2 do not overlay LU_B2 C C (R ) E2MAX = REAL*8 C Maximum error in {X2}. C C FMSCOM PARAMETERS: C (RW) IACCOM = Multiply accumulate flag C (R ) LUPR = FORTRAN unit for printing C C CALLED FROM: C EXAMPLE_14 C C SUBPROGRAMS USED: C CNDF C CNDS C FMSMM C C ERROR CONDITIONS: C None. C C HISTORY: C C NOTES: C C Expanding the partitioned system gives: C C [A11]{X1} + [A12]{X2} = {B1} (1) C [A21]{X1} + [A22]{X2} = {B2} (2) C C Premultiplying (1) by inv[A11] gives C C {X1} = {S1} - [F12]{X2} (3) C C where C {S1} = inv[A11]{B1} (4) C [F12] = inv[A11][A12] (5) C C Substituting (3) into (2) gives: C C [F22]{X2} = {S2} (6) C C where C [F22] = [A22] - [A21][F12] (7) C {S2} = {B2} - [A21]{S1} (8) C C C The error in {X2} may be computed from: C C E2MAX = | {B2} - [A21]{X1} - [A22]{X2} | C C The algorithm consists of the following 8 steps: C C Solve large system: C 1. Factor [A11] into [F11]=[L11][U11] C 2. Solve [F11][F12] = [A12] (eq. 5) C 3. Solve [F11]{S1} = {B1} (eq. 4) C C Project to small system: C 4. Multiply [F22'] = [A22] - [A21][F12] (eq. 7) C 5. Factor [F22'] into [F22]=[L22][U22] C 6. Multiply {S2} = {B2} - [A21]{S1} (eq. 8) C C Solve small system: C 7. Solve [F22]{X2} = {S2} (eq. 6) C C Project back to large system: C 8. Multiply {X1} = {S1} - [F12]*{X2} (eq. 3) C C Check {X2}: (optional) C 9. Multiply {ERR} = {B2} - [A21]{X1} - [A22]{X2} C Then compute the maximum absolute value in {ERR}. C C Summary of arrays used: C C STEP A11 F11 A12 F12 A21 A22 F22 B1 S1 X1 B2 S2 X2 C ==== ======= ======= === ======= =========== =========== C 1 R-->W C 2 R R-->W C 3 R R-->W C 4 R R R-->W C 5 RW C 6 R R R-->W C 7 R R-->W C 8 R R-->W R C C Steps required: C C STEP1 = (NEWA11 ) C STEP2 = (NEWA12 | STEP1 ) C STEP3 = (NEWB1 | STEP1 ) C STEP4 = (NEWA22 | NEWA21 | STEP2 ) C STEP5 = (STEP4 ) C STEP6 = (NEWB2 | NEWA21 | STEP3 ) C STEP7 = (STEP5 | STEP6 ) C STEP8 = (STEP3 | STEP2 | STEP7 ) C C or, substituting, C C STEP1 = (NEWA11 ) C STEP2 = (NEWA11 | NEWA12 ) C STEP3 = (NEWA11 | NEWB1 ) C STEP4 = (NEWA11 | NEWA12 | NEWA21 | NEWA22 ) C STEP5 = (NEWA11 | NEWA12 | NEWA21 | NEWA22 ) C STEP6 = (NEWA11 | NEWA21 | NEWB1 | NEWB2 ) C STEP7 = (NEWA11 | NEWA12 | NEWA21 | NEWA22 | NEWB1 | NEWB2 ) C STEP8 = (NEWA11 | NEWA12 | NEWA21 | NEWA22 | NEWB1 | NEWB2 ) C C Also if the intermediate vector storage is overlaid on the C storage for the solution vectors, it is assumed that it no C longer contains the intermediate arrays. Therefore, C STEP3 = (STEP3 | (LU_S1 = LU_X1) ) C STEP6 = (STEP6 | (LU_S2 = LU_X2) ) C----------------------------------------------------------------------- C FORMAL PARAMETERS C----------------------------------------------------------------------- INTEGER LU_A11(25) INTEGER LU_F11(25) C INTEGER LU_A12(25) INTEGER LU_F12(25) C INTEGER LU_A21(25) C INTEGER LU_A22(25) C INTEGER LU_F22(25) C INTEGER LU_B1 (25) INTEGER LU_S1 (25) INTEGER LU_X1 (25) C INTEGER LU_B2 (25) INTEGER LU_S2 (25) INTEGER LU_X2 (25) C LOGICAL NEWA11 LOGICAL NEWA12 LOGICAL NEWA21 LOGICAL NEWA22 LOGICAL NEWB1 LOGICAL NEWB2 LOGICAL ICK_X2 REAL*8 E2MAX C----------------------------------------------------------------------- C LOCAL VARIABLES C----------------------------------------------------------------------- C CHARACTER*6 MYNAME PARAMETER (MYNAME='RESOLV') 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 COMMON /MYFMS/ L_A22, LDA22 C C Data type = complex: INTEGER IDTYPE PARAMETER (IDTYPE = 2) C C Skip operations during solving (no): INTEGER ISKIP PARAMETER (ISKIP=0) C C Constants: COMPLEX*16 C_ONE(1) DATA C_ONE /(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_THREE DATA R_THREE/ 3.0D0/ REAL*8 R_EIGHT DATA R_EIGHT/ 8.0D0/ C C FMS Parameters: INTEGER LUPR C C Matrix dimensions: INTEGER N1 INTEGER N2 INTEGER NRHS REAL*8 RN1 REAL*8 RN2 REAL*8 RNRHS C C Temporary file: INTEGER LU_ERR(25) INTEGER LUA0 (25) DATA LUA0(1)/0/ INTEGER LUX0 (25) INTEGER LUS0 (25) C C CPU, Wall and I/O time: REAL*8 TCPU(10) REAL*8 TWALL(10) REAL*8 TIO(10) REAL*8 T1, T2, T3 C C Steps to perform: LOGICAL STEP1 LOGICAL STEP2 LOGICAL STEP3 LOGICAL STEP4 LOGICAL STEP5 LOGICAL STEP6 LOGICAL STEP7 LOGICAL STEP8 LOGICAL STEP9 C C Floating point operations: REAL*8 OPS(9), TOPS 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 C C Determine which steps to do: STEP1 = (NEWA11 ) STEP2 = (NEWA12 .OR. STEP1 ) STEP3 = (NEWB1 .OR. STEP1 ) STEP4 = (NEWA22 .OR. NEWA21 .OR. STEP2 ) STEP5 = (STEP4 ) STEP6 = (NEWB2 .OR. NEWA21 .OR. STEP3 ) STEP7 = (STEP5 .OR. STEP6 ) STEP8 = (STEP2 .OR. STEP3 .OR. STEP7 ) STEP9 = (ICK_X2 ) C C Check overlaid storage: STEP3 = (STEP3 .OR. (LU_S1(1) .EQ. LU_X1(1)) ) STEP6 = (STEP6 .OR. (LU_S2(2) .EQ. LU_X2(2)) ) IF( (LU_B2(1) .EQ. LU_S2(1) ) .OR. 1 (LU_B2(1) .EQ. LU_X2(1) ) ) STEP9 = .FALSE. C C Initialize operation counts for each step: OPS(1) = R_ZERO OPS(2) = R_ZERO OPS(3) = R_ZERO OPS(4) = R_ZERO OPS(5) = R_ZERO OPS(6) = R_ZERO OPS(7) = R_ZERO OPS(8) = R_ZERO OPS(9) = R_ZERO C C (1) Factor [A11] into [L11][U11]: CALL FMSTIM (TCPU(1), TWALL(1), TIO(1)) IF(STEP1) THEN WRITE(LUPR,2001) OPS(1) = R_EIGHT*RN1*RN1*RN1/R_THREE CALL CNDAF (LU_A11, C_ONE, 1, LUS0, 0, LUA0, LU_F11, 1 LUX0, LUX0, 0) END IF C C (2) Solve [F11][F12] = [A12]: CALL FMSTIM (TCPU(2), TWALL(2), TIO(2)) IF(STEP2) THEN WRITE(LUPR,2002) OPS(2) = R_EIGHT*RN1*RN1*RN2 CALL CNDS (LU_F11, LU_A12, LU_F12, N2, 0) END IF C C (3) Solve [F11]{S1} = {B1}: CALL FMSTIM (TCPU(3), TWALL(3), TIO(3)) IF(STEP3) THEN WRITE(LUPR,2003) OPS(3) = R_EIGHT*RN1*RN1*RNRHS CALL CNDS (LU_F11, LU_B1, LU_S1, NRHS, 0) END IF C C (4) Multiply [F22'] = [A22] - [A21][F12] CALL FMSTIM (TCPU(4), TWALL(4), TIO(4)) IF(STEP4) THEN WRITE(LUPR,2004) OPS(4) = R_EIGHT*RN1*RN2*RN2 CALL FMSMM (LU_F22, LU_A22, -1, 'T', LU_A21, LU_F12) END IF C C (5) Factor [F22'] into [F22]: CALL FMSTIM (TCPU(5), TWALL(5), TIO(5)) IF(STEP5) THEN WRITE(LUPR,2005) OPS(5) = R_EIGHT*RN2*RN2*RN2/R_THREE CALL CNDAF (LU_F22, C_ONE, 1, LUS0, 0, LUA0, LU_F22, 1 LUX0, LUX0, 0) END IF C C (6) Multiply {S2} = {B2} - [A21]{S1} CALL FMSTIM (TCPU(6), TWALL(6), TIO(6)) IF(STEP6) THEN WRITE(LUPR,2006) OPS(6) = R_EIGHT*RN2*RN1*RNRHS CALL FMSMM (LU_S2, LU_B2, -1, 'T', LU_A21, LU_S1) END IF C C (7) Solve [F22]{X2} = {S2}: CALL FMSTIM (TCPU(7), TWALL(7), TIO(7)) IF(STEP7) THEN WRITE(LUPR,2007) OPS(7) = R_EIGHT*RN2*RN2*RNRHS CALL CNDS (LU_F22, LU_S2, LU_X2, NRHS, 0) END IF C C (8) Multiply {X1} = {S1} - [F12]{X2} CALL FMSTIM (TCPU(8), TWALL(8), TIO(8)) IF(STEP8) THEN WRITE(LUPR,2008) OPS(8) = R_EIGHT*RN1*RN2*RNRHS CALL FMSMM (LU_X1, LU_S1, -1, 'N', LU_F12, LU_X2) END IF C C (9) Check {X2}: {ERR} = {B2} - [A21]{X1} - [A22]{X2} CALL FMSTIM (TCPU(9), TWALL(9), TIO(9)) IF(STEP9) THEN WRITE(LUPR,2009) OPS(9) = R_EIGHT*(RN1+RN2)*RN2*RNRHS C C Open a vector file to store the error array ERR(N2,NRHS): CALL FMSOV (N2, IDTYPE, NRHS, 'LU_ERR' , LU_ERR) C C Multiply {ERR} = {B2} - [A21]{X1} CALL FMSMM (LU_ERR, LU_B2, -1, 'T', LU_A21, LU_X1) C C Multiply {ERR} = {ERR} - [A22]{X2}: CALL FMSMM (LU_ERR, LU_ERR, -1, 'N', LU_A22, LU_X2) C C Read LU_ERR and check the error: C C Allocate storage for one vector: CALL FMSCMG (CMD, L_ERR, N2) C C Initialize FMSGET: CALL FMSGET (LU_ERR, 0, 0, 0, 0, CMD, 0) C C Compute the maximum error: E2MAX = R_ZERO DO 95 N = 1,NRHS C Read in next vector: CALL FMSGET (LU_ERR, N2, 1, 1, N, CMD(L_ERR), N2) L = L_ERR DO 90 I = 1,N2 T1 = ABS(CMD(L)) IF(T1 .GT. E2MAX) E2MAX = T1 L = L + 1 90 CONTINUE 95 CONTINUE C C End FMSGET: CALL FMSGET (LU_ERR, 0, 0, N2+1, 1, CMD, 0) C C Close the vector file LU_ERR: CALL FMSCV(LU_ERR) C C Delete the storage for {ERR}: CALL FMSCMR (CMD, L_ERR, N2) END IF C C Print timings: WRITE(LUPR,2010) CALL FMSTIM (TCPU(10), TWALL(10), TIO(10)) TOPS = R_ZERO DO 100 ISTEP = 1,9 IF(OPS(ISTEP) .EQ. R_ZERO) THEN C C Operation skipped: WRITE(LUPR,2012) ISTEP ELSE TOPS = TOPS + OPS(ISTEP) C C CPU time and Mflops: T1 = TCPU(ISTEP+1) - 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+1) - TWALL(ISTEP) T3 = TIO(ISTEP+1) - 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,2011) ISTEP, T1, T2, T3, MF1, MF2, RATIO END IF 100 CONTINUE T1 = TCPU(10) - TCPU(1) T2 = TWALL(10) - TWALL(1) T3 = TIO(10) - TIO(1) 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 WRITE(LUPR,2013) T1, T2, T3, MF1, MF2, RATIO CALL FMSPOP (MYNAME) RETURN 2000 FORMAT (/ 1 ' Start of Subroutine RESOLV',/ 2 ' Rank of full matrix.....=',I6/ 3 ' Rank of submatrix #1....=',I6/ 4 ' Rank of submatrix #2....=',I6/ 5 ' # of right-hand-sides...=',I6/) 2001 FORMAT (/ 1 ' STEP 1. Factor [A11] into [F11]'/ 2 ' =================================') 2002 FORMAT (/ 1 ' STEP 2. Solve [F11][F12] = [A12]'/ 2 ' ===================================') 2003 FORMAT (/ 1 ' STEP 3. Solve [F11]{S1} = {B1}'/ 2 ' ==================================') 2004 FORMAT (/ 1 ' STEP 4. Multiply [F22] = [A22] - [A21][F12]'/ 2 ' ===========================================') 2005 FORMAT (/ 1 ' STEP 5. Factor [F22]'/ 2 ' ======================') 2006 FORMAT (/ 1 ' STEP 6. Multiply {S2} = {B2} - [A21]{S1}'/ 2 ' ==========================================') 2007 FORMAT (/ 1 ' STEP 7. Solve [F22]{X2} = {S2}'/ 2 ' =================================') 2008 FORMAT (/ 1 ' STEP 8. Multiply {X1} = {S1} - [A12]*{X2}'/ 2 ' =========================================') 2009 FORMAT (/ 1 ' STEP 9. Checking values in {X2}'/ 2 ' =========================================') 2010 FORMAT (/ 1 ' Summary of Subroutine RESOLV:'// 2 ' <----------TIMES (Sec.)----------->' 2 ' <--MFLOPS-->'/ 2 ' STEP CPU WALL I/O CPU WALL', 2 ' RATIO'/ 3 ' ===== ========= ========= ========= ==== ====', 3 ' =====') 2011 FORMAT (I6,3F13.3,2I8,F9.3) 2012 FORMAT (I6,6X,'Skipped') 2013 FORMAT (' TOTAL',3F13.3,2I8,F9.3) END