Add files via upload
This commit is contained in:
152
code/obs_operators/gaussj.f
Normal file
152
code/obs_operators/gaussj.f
Normal file
@ -0,0 +1,152 @@
|
||||
SUBROUTINE gaussj( IA, NA, NB, A, B, SINGLR, FAIL, ERRMSG )
|
||||
C
|
||||
C VERSION
|
||||
C 10-JAN-94 RJW Remove non-ANSI common block WORKER
|
||||
C 18-JAN-90 RJW Increased IAMAX to 200
|
||||
C 08-JUN-89 AD
|
||||
C
|
||||
C DESCRIPTION
|
||||
C General Purpose Matrix routine.
|
||||
C Invert Matrix A: B = A**-1
|
||||
C Using A as the output matrix is also possible: A = A**-1
|
||||
C This routine uses Gauss-Jordan Elimination with full pivoting, based on
|
||||
C the routine GAUSSJ given on pp 28-29 of Numerical Recipes.
|
||||
C This routine is no quicker than using MTXLEQ but saves having to construct
|
||||
C an Identity matrix.
|
||||
C There is probably scope for some more optmisation in this routine.
|
||||
C
|
||||
C Ref: Numerical Recipes (Press et al.)
|
||||
IMPLICIT NONE
|
||||
C
|
||||
C ARGUMENTS
|
||||
INTEGER IA ! I order of matrix A
|
||||
INTEGER NA ! I 1st index of A as declared externally
|
||||
INTEGER NB ! I 1st index of B as declared externally
|
||||
REAL*8 A(NA,IA) ! I
|
||||
REAL*8 B(NB,IA) ! I Note: NA,NB >= IA is required
|
||||
LOGICAL SINGLR ! O Set TRUE if A is singular
|
||||
LOGICAL FAIL ! O Set TRUE if a Fatal Error is detected
|
||||
CHARACTER*80 ERRMSG ! O Error message written if FAIL is TRUE
|
||||
C
|
||||
C LOCAL CONSTANTS
|
||||
INTEGER IAMAX ! Largest expected value of IA
|
||||
PARAMETER ( IAMAX = 3000 )
|
||||
C
|
||||
C LOCAL VARIABLES
|
||||
INTEGER IPIV(IAMAX) ! Workspace
|
||||
INTEGER INDXR(IAMAX)
|
||||
INTEGER INDXC(IAMAX)
|
||||
INTEGER I, J, K ! counters
|
||||
INTEGER IROW, ICOL ! store pivot row/column
|
||||
REAL*4 BIG, DUM, PIVINV
|
||||
C
|
||||
1000 FORMAT ( A, I11, A, I11 )
|
||||
C
|
||||
C- EXECUTABLE CODE ------------------------------------------------------------
|
||||
C
|
||||
|
||||
C Initialise B
|
||||
DO I = 1, NB
|
||||
DO J = 1, IA
|
||||
B(I,J) = 0.0
|
||||
ENDDO
|
||||
ENDDO
|
||||
|
||||
C Check parameters
|
||||
IF ( IA .GT. IAMAX ) THEN ! Matrix A too large
|
||||
WRITE ( ERRMSG, 1000 )
|
||||
& 'F-MTXINV: IA =', IA, ' exceeds IAMAX =', IAMAX
|
||||
FAIL = .TRUE.
|
||||
RETURN ! Exit with Fatal Error
|
||||
END IF
|
||||
C
|
||||
IF ( IA .GT. NA ) THEN ! Inconsistent parameters
|
||||
WRITE ( ERRMSG, 1000 )
|
||||
& 'F-MTXINV: IA =', IA, ' exceeds NA =', NA
|
||||
FAIL = .TRUE.
|
||||
RETURN ! Exit with Fatal Error
|
||||
END IF
|
||||
C
|
||||
FAIL = .FALSE. ! no further Fatal errors, only singular matrices
|
||||
SINGLR = .FALSE. ! set TRUE if a Singular Matrix is detected
|
||||
C
|
||||
DO I = 1, IA
|
||||
DO J = 1, IA
|
||||
B(J,I) = A(J,I) ! copy matrix A to B (may not be necessary here?)
|
||||
END DO
|
||||
IPIV (I) = 0
|
||||
IF (B(I,I) .EQ. 0.0) THEN
|
||||
PRINT *, 'B EQ TO ZERO IN INPUT!!',I,B(I,I)
|
||||
! STOP 'B ZERO'
|
||||
ENDIF
|
||||
END DO
|
||||
|
||||
C
|
||||
DO I = 1, IA ! Main loop over columns to be reduced
|
||||
BIG = 0.0
|
||||
DO J = 1, IA ! Outer loop of search for a pivot element
|
||||
IF ( IPIV(J) .NE. 1 ) THEN
|
||||
DO K = 1, IA
|
||||
IF ( IPIV(K) .EQ. 0 ) THEN
|
||||
IF ( ABS(B(J,K)) .GE. BIG ) THEN
|
||||
BIG = ABS(B(J,K))
|
||||
IROW = J
|
||||
ICOL = K
|
||||
END IF
|
||||
ELSE IF ( IPIV(K) .GT. 1 ) THEN
|
||||
print*,'SING 1!'
|
||||
SINGLR = .TRUE.
|
||||
RETURN ! Exit for Singular Matrix
|
||||
END IF
|
||||
END DO
|
||||
END IF
|
||||
END DO
|
||||
IPIV(ICOL) = IPIV(ICOL) + 1
|
||||
C
|
||||
IF ( IROW .NE. ICOL ) THEN
|
||||
C got pivot element so interchange rows if reqd to put pivot on diagonal
|
||||
DO J = 1, IA
|
||||
DUM = B(IROW,J)
|
||||
B(IROW,J) = B(ICOL,J)
|
||||
B(ICOL,J) = DUM
|
||||
c print *, 'irow,icol, j, b(irow,j),b(icol,j)',irow,icol, j,
|
||||
c & b(irow,j),b(icol,j)
|
||||
END DO
|
||||
END IF
|
||||
INDXR(I) = IROW
|
||||
INDXC(I) = ICOL
|
||||
IF ( B(ICOL,ICOL) .EQ. 0.0 ) THEN
|
||||
print*,'SING 2!'
|
||||
SINGLR = .TRUE.
|
||||
RETURN ! Exit for Singular Matrix
|
||||
END IF
|
||||
|
||||
|
||||
PIVINV = 1.0/B(ICOL,ICOL) ! Now divide pivot row by pivot element
|
||||
B(ICOL,ICOL) = 1.0
|
||||
DO J = 1, IA
|
||||
B(ICOL,J) = B(ICOL,J)*PIVINV
|
||||
END DO
|
||||
DO J = 1, IA ! Reduce Rows except for pivot row
|
||||
IF ( J .NE. ICOL ) THEN
|
||||
DUM = B(J,ICOL)
|
||||
B(J,ICOL) = 0.0
|
||||
DO K = 1, IA
|
||||
B(J,K) = B(J,K)-B(ICOL,K)*DUM
|
||||
END DO
|
||||
END IF
|
||||
END DO
|
||||
END DO ! end of loop over column reduction
|
||||
C
|
||||
DO J = IA, 1, -1 ! unscramble column changes
|
||||
IF ( INDXR(J) .NE. INDXC(J) ) THEN
|
||||
DO K = 1, IA
|
||||
DUM = B(K,INDXR(J))
|
||||
B(K,INDXR(J)) = B(K,INDXC(J))
|
||||
B(K,INDXC(J)) = DUM
|
||||
END DO
|
||||
END IF
|
||||
END DO
|
||||
C
|
||||
END
|
||||
|
Reference in New Issue
Block a user