Statistiques
| Révision :

root / src / Ginvse.f90 @ 5

Historique | Voir | Annoter | Télécharger (8,53 ko)

1 1 pfleura2
2 1 pfleura2
SUBROUTINE GINVSE(A, MA, NA, AIN, NAIN, M, N, TOL, V, NV, FAIL, NOUT)
3 1 pfleura2
4 1 pfleura2
  Use Io_module
5 1 pfleura2
  ! INVERSE.OF.A = V * INVERSE.OF.S * TRANSPOSE.OF.U
6 1 pfleura2
  ! VIA SINGULAR VALUE DECOMPOSITION USING ALGORITHMS 1 AND 2 OF
7 1 pfleura2
  ! NASH J C, COMPACT NUMERICAL METHODS FOR COMPUTERS, 1979,
8 1 pfleura2
  !    ADAM HILGER, BRISTOL OR HALSTED PRESS, N.Y.
9 1 pfleura2
  !
10 1 pfleura2
  !
11 1 pfleura2
  ! CALLING SEQUENCE
12 1 pfleura2
  !
13 1 pfleura2
  !    CALL GINVSE (A,MA,NA,AIN,NAIN,M,N,TOL,V,NV,FAIL,NOUT)
14 1 pfleura2
  !
15 1 pfleura2
  ! A      = MATRIX OF SIZE M BY N TO BE 'INVERTED'
16 1 pfleura2
  !          A IS DESTROYED BY THIS ROUTINE AND BECOMES THE
17 1 pfleura2
  !          U MATRIX OF THE SINGULAR VALUE DECOMPOSITION
18 1 pfleura2
  ! MA     = ROW DIMENSION OF ARRAY A
19 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
20 1 pfleura2
  ! NA     = COLUMN DIMENSION OF ARRAY A
21 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
22 1 pfleura2
  ! AIN    = COMPUTED 'INVERSE' (N ROWS BY M COLS.)
23 1 pfleura2
  ! NAIN   = ROW DIMENSION OF ARRAY AIN
24 1 pfleura2
  !          ( COLUMN DIMENSION ASSUMED TO BE AT LEAST M )
25 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
26 1 pfleura2
  ! M      = NUMBER OF ROWS IN MATRIX A AND
27 1 pfleura2
  !          THE NUMBER OF COLUMNS IN MATRIX AIN
28 1 pfleura2
  ! N      = NUMBER OF COLUMNS IN MATRIX A AND
29 1 pfleura2
  !          THE NUMBER OF ROWS IN MATRIX AIN
30 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
31 1 pfleura2
  ! TOL    = MACHINE PRECISION FOR COMPUTING ENVIRONMENT
32 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
33 1 pfleura2
  ! V      = WORK MATRIX WHICH BECOMES THE V MATRIX (N BY N)
34 1 pfleura2
  !          OF THE SINGULAR VALUE DECOMPOSITION
35 1 pfleura2
  ! NV     = DIMENSIONS OF V  (BOTH ROWS AND COLUMNS)
36 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
37 1 pfleura2
  ! FAIL   = ERROR FLAG - .TRUE. IMPLIES FAILURE OF GINVSE
38 1 pfleura2
  ! NOUT   = OUTPUT CHANNEL NUMBER
39 1 pfleura2
  !          UNCHANGED BY THIS SUB-PROGRAM
40 1 pfleura2
  !
41 1 pfleura2
  ! NOTE.  THIS ROUTINE IS NOT DESIGNED TO PRODUCE A 'GOOD'
42 1 pfleura2
  !     GENERALIZED INVERSE. IT IS MEANT ONLY TO FURNISH TEST
43 1 pfleura2
  !     DATA FOR THE ROUTINES  GMATX, ZIELKE, AND PTST
44 1 pfleura2
  !
45 1 pfleura2
  INTEGER(KINT), INTENT(IN) :: MA, NA, NAIN,N, M,NV, NOUT
46 1 pfleura2
  INTEGER(KINT) :: ICOUNT, NM1, I, J, JP1, K,SWEEP, LIMIT
47 1 pfleura2
  LOGICAL, INTENT(INOUT) :: FAIL
48 1 pfleura2
  REAL(KREAL), INTENT(IN) :: TOL
49 1 pfleura2
  REAL(KREAL) :: P, Q, R, VV, C, S, TEMP
50 1 pfleura2
  REAL(KREAL), INTENT(INOUT) :: V(NV,NV)
51 1 pfleura2
  REAL(KREAL), INTENT(INOUT) :: AIN(NAIN,M)
52 1 pfleura2
  REAL(KREAL), INTENT(INOUT) :: A(MA,NA)
53 1 pfleura2
54 1 pfleura2
  LOGICAL :: debug
55 1 pfleura2
  INTERFACE
56 1 pfleura2
     function valid(string) result (isValid)
57 1 pfleura2
       CHARACTER(*), intent(in) :: string
58 1 pfleura2
       logical                  :: isValid
59 1 pfleura2
     END function VALID
60 1 pfleura2
61 1 pfleura2
  END INTERFACE
62 1 pfleura2
63 1 pfleura2
  debug=valid('Ginvse')
64 1 pfleura2
  if (debug) WRITE(*,*) '=======Entering Ginvse======='
65 1 pfleura2
66 1 pfleura2
  !Print *, 'A='
67 1 pfleura2
  DO J=1,MA
68 1 pfleura2
     !WRITE(*,'(50(1X,F10.2))') AIN(:,J)
69 1 pfleura2
     !Print *, A(:,J)
70 1 pfleura2
  END DO
71 1 pfleura2
  !Print *, 'End of A'
72 1 pfleura2
  !
73 1 pfleura2
  ! INITIALLY SET FAIL=.FALSE. TO IMPLY CORRECT EXECUTION
74 1 pfleura2
  !
75 1 pfleura2
  FAIL = .FALSE.
76 1 pfleura2
  !
77 1 pfleura2
  ! TESTS ON VALIDITY OF DIMENSIONS
78 1 pfleura2
  !
79 1 pfleura2
  IF (M.LT.2 .OR. MA.LT.2 .OR. N.LT.2 .OR. NA.LT.2) GO TO 230
80 1 pfleura2
  IF (N.GT.NA) GO TO 210
81 1 pfleura2
  IF (M.GT.MA) GO TO 220
82 1 pfleura2
  !
83 1 pfleura2
  ! N MUST NOT EXCEED M, OTHERWISE GINVSE WILL FAIL
84 1 pfleura2
  !
85 1 pfleura2
  IF (N.GT.M) GO TO 200
86 1 pfleura2
  !
87 1 pfleura2
  ! SWEEP COUNTER  INITIALIZED TO ZERO
88 1 pfleura2
  !
89 1 pfleura2
  SWEEP = 0
90 1 pfleura2
  !
91 1 pfleura2
  ! SET SWEEP LIMIT
92 1 pfleura2
  !
93 1 pfleura2
  LIMIT = MAX0(N,6)
94 1 pfleura2
  !
95 1 pfleura2
  ! MAX0(N,6) WAS  CHOSEN FROM EXPERIENCE
96 1 pfleura2
  !
97 1 pfleura2
  !
98 1 pfleura2
  ! V(I,J) INITIALLY N BY N IDENTITY
99 1 pfleura2
  !
100 1 pfleura2
  DO 20 I=1,N
101 1 pfleura2
     DO 10 J=1,N
102 1 pfleura2
        V(I,J) = 0.0
103 1 pfleura2
10      CONTINUE
104 1 pfleura2
        V(I,I) = 1.0
105 1 pfleura2
20      CONTINUE
106 1 pfleura2
        !
107 1 pfleura2
        ! INITIALIZE ROTATION COUNTER (COUNTS DOWN TO 0)
108 1 pfleura2
        !
109 1 pfleura2
30      ICOUNT = N*(N-1)/2
110 1 pfleura2
        !
111 1 pfleura2
        ! COUNT SWEEP
112 1 pfleura2
        !
113 1 pfleura2
        SWEEP = SWEEP + 1
114 1 pfleura2
        NM1 = N - 1
115 1 pfleura2
        DO 110 J=1,NM1
116 1 pfleura2
           JP1 = J + 1
117 1 pfleura2
           DO 100 K=JP1,N
118 1 pfleura2
              P = 0.
119 1 pfleura2
              Q = 0.
120 1 pfleura2
              R = 0.
121 1 pfleura2
              DO 40 I=1,M
122 1 pfleura2
                 !
123 1 pfleura2
           ! TEST FOR AND AVOID UNDERFLOW
124 1 pfleura2
           ! NOT NEEDED FOR MACHINES WHICH UNDERFLOW TO ZERO WITHOUT
125 1 pfleura2
           ! ERROR MESSAGE
126 1 pfleura2
           !
127 1 pfleura2
           IF (ABS(A(I,J)).GE.TOL) Q = Q + A(I,J)*A(I,J)
128 1 pfleura2
           !Print *, '1 Q=',Q
129 1 pfleura2
           !Print *, 'A(',I,J,')=',A(I,J)
130 1 pfleura2
           IF (ABS(A(I,K)).GE.TOL) R = R + A(I,K)*A(I,K)
131 1 pfleura2
           IF (ABS(A(I,J)/TOL)*ABS(A(I,K)/TOL).GE.1.0) P = P + A(I,J)*A(I,K)
132 1 pfleura2
40         CONTINUE
133 1 pfleura2
           !Print *, '2 Q=',Q
134 1 pfleura2
           IF (Q.GE.R) GO TO 50
135 1 pfleura2
           C = 0.
136 1 pfleura2
           S = 1.
137 1 pfleura2
           GO TO 60
138 1 pfleura2
50         IF (ABS(Q).LT.TOL .AND. ABS(R).LT.TOL) GO TO 90
139 1 pfleura2
           IF (R.EQ.0.0) GO TO 90
140 1 pfleura2
           IF ((P/Q)*(P/R).LT.TOL) GO TO 90
141 1 pfleura2
           !
142 1 pfleura2
           ! CALCULATE THE SINE AND COSINE OF THE ANGLE OF ROTATION
143 1 pfleura2
           !
144 1 pfleura2
           !Print *, '3 Q=',Q
145 1 pfleura2
           !Print *, 'R=',R
146 1 pfleura2
           Q = Q - R
147 1 pfleura2
           VV = SQRT(4.*P*P+Q*Q)
148 1 pfleura2
           !Print *, 'VV=',VV
149 1 pfleura2
           !Print *, 'P=',P
150 1 pfleura2
           !Print *, 'Q=',Q
151 1 pfleura2
           C = SQRT((VV+Q)/(2.*VV))
152 1 pfleura2
           !Print *, 'C=', C
153 1 pfleura2
           S = P/(VV*C)
154 1 pfleura2
           !Print *, 'S=', S
155 1 pfleura2
           !
156 1 pfleura2
           ! APPLY THE ROTATION TO A
157 1 pfleura2
           !
158 1 pfleura2
60         DO 70 I=1,M
159 1 pfleura2
              R = A(I,J)
160 1 pfleura2
              A(I,J) = R*C + A(I,K)*S
161 1 pfleura2
              A(I,K) = -R*S + A(I,K)*C
162 1 pfleura2
70            CONTINUE
163 1 pfleura2
              !if (debug) WRITE(*,*) '=======After rotation of A======='
164 1 pfleura2
              !
165 1 pfleura2
              ! APPLY THE ROTATION TO V
166 1 pfleura2
              !
167 1 pfleura2
              DO 80 I=1,N
168 1 pfleura2
                 R = V(I,J)
169 1 pfleura2
                 V(I,J) = R*C + V(I,K)*S
170 1 pfleura2
                 !Print *, 'V(I,J)=', V(I,J)
171 1 pfleura2
                 !Print *, 'R=', R
172 1 pfleura2
                 V(I,K) = -R*S + V(I,K)*C
173 1 pfleura2
                 !Print *, 'V(I,K)=', V(I,K)
174 1 pfleura2
80               CONTINUE
175 1 pfleura2
                 GO TO 100
176 1 pfleura2
90               ICOUNT = ICOUNT - 1
177 1 pfleura2
100              CONTINUE
178 1 pfleura2
110              CONTINUE
179 1 pfleura2
                 !if (debug) WRITE(*,*) '=======After rotation of V======='
180 1 pfleura2
                 !
181 1 pfleura2
                 ! PRINT THE NUMBER OF SWEEPS AND ROTATIONS
182 1 pfleura2
                 !
183 1 pfleura2
                 IF (NOUT.GT.0) WRITE (NOUT,9997) SWEEP, ICOUNT
184 1 pfleura2
                 !
185 1 pfleura2
                 ! CHECK NUMBER OF SWEEPS AND ROTATIONS (TERMINATION TEST)
186 1 pfleura2
                 !
187 1 pfleura2
                 IF (ICOUNT.GT.0 .AND. SWEEP.LT.LIMIT) GO TO 30
188 1 pfleura2
                 IF (SWEEP.GE.LIMIT .AND. NOUT.GT.0) WRITE (NOUT,9996)
189 1 pfleura2
                 DO 160 J=1,N
190 1 pfleura2
                    Q = 0.
191 1 pfleura2
                    DO 120 I=1,M
192 1 pfleura2
                       Q = Q + A(I,J)*A(I,J)
193 1 pfleura2
120                    CONTINUE
194 1 pfleura2
                       !
195 1 pfleura2
                       ! ARBITRARY RANK DECISION
196 1 pfleura2
                       !
197 1 pfleura2
                       IF (J.EQ.1) VV = 1.0E-3*SQRT(Q)
198 1 pfleura2
                       IF (SQRT(Q).LE.VV) GO TO 140
199 1 pfleura2
                       DO 130 I=1,M
200 1 pfleura2
                          A(I,J) = A(I,J)/Q
201 1 pfleura2
130                       CONTINUE
202 1 pfleura2
                          GO TO 160
203 1 pfleura2
140                       DO 150 I=1,M
204 1 pfleura2
                             A(I,J) = 0.0
205 1 pfleura2
150                          CONTINUE
206 1 pfleura2
160                          CONTINUE
207 1 pfleura2
208 1 pfleura2
                                   !if (debug) WRITE(*,*) '=======After termination test======='
209 1 pfleura2
210 1 pfleura2
                                   DO 190 I=1,N
211 1 pfleura2
                                      DO 180 J=1,M
212 1 pfleura2
                                         TEMP = 0.0
213 1 pfleura2
                                         DO 170 K=1,N
214 1 pfleura2
                                            TEMP = TEMP + V(I,K)*A(J,K)
215 1 pfleura2
                                            !Print *, 'V(I,K)*A(J,K)=', V(I,K)*A(J,K)
216 1 pfleura2
                                            !Print *, 'V(I,K)=', V(I,K)
217 1 pfleura2
                                            !Print *, 'A(J,K)=', A(J,K)
218 1 pfleura2
170    CONTINUE
219 1 pfleura2
       AIN(I,J) = TEMP
220 1 pfleura2
       !Print *, 'AIN(I,J)=', AIN(I,J)
221 1 pfleura2
180    CONTINUE
222 1 pfleura2
190    CONTINUE
223 1 pfleura2
       RETURN
224 1 pfleura2
225 1 pfleura2
       !Print *, 'AIN='
226 1 pfleura2
       !DO J=1,NAIN
227 1 pfleura2
       !WRITE(*,'(50(1X,F10.2))') AIN(:,J)
228 1 pfleura2
       !Print *, AIN(:,J)
229 1 pfleura2
       !END DO
230 1 pfleura2
       !Print *, 'End of AIN'
231 1 pfleura2
232 1 pfleura2
       !
233 1 pfleura2
       ! IF AN ERROR OCCURED THE APPROPRIATE MESSAGE IS PRINTED
234 1 pfleura2
       !    AND FAIL IS SET TO  .TRUE.
235 1 pfleura2
       !
236 1 pfleura2
200    IF (NOUT.GT.0) WRITE (NOUT,9995)
237 1 pfleura2
       FAIL = .TRUE.
238 1 pfleura2
       RETURN
239 1 pfleura2
210    IF (NOUT.GT.0) WRITE (NOUT,9999) N, NA
240 1 pfleura2
       FAIL = .TRUE.
241 1 pfleura2
       RETURN
242 1 pfleura2
220    IF (NOUT.GT.0) WRITE (NOUT,9998) M, MA
243 1 pfleura2
       FAIL = .TRUE.
244 1 pfleura2
       RETURN
245 1 pfleura2
230    IF (NOUT.GT.0) WRITE (NOUT,9994) M, MA, N, NA
246 1 pfleura2
       FAIL = .TRUE.
247 1 pfleura2
       RETURN
248 1 pfleura2
       !
249 1 pfleura2
       ! * * * * * * * * * * * * * * * * * * *
250 1 pfleura2
                                            !
251 1 pfleura2
9999    FORMAT (11H0**ERROR** , I5, 24H EXCEEDS ALLOWABLE VALUE,23H FOR N IN GINVSE   NA= , I5, 5(/))
252 1 pfleura2
9998        FORMAT (11H0**ERROR** , I5, 24H EXCEEDS ALLOWABLE VALUE,23H FOR M IN GINVSE   MA= , I5, 5(/))
253 1 pfleura2
9997        FORMAT (8H SWEEP =, I4, 2H  , I4, 19H JACOBI ROTATIONS P,8HERFORMED)
254 1 pfleura2
9996        FORMAT (21H SWEEP LIMIT REACHED )
255 1 pfleura2
9995        FORMAT (38H0**ERROR** N GREATER THAN M IS INVALID,21H AND GINVSE WILL FAIL, 5(/))
256 1 pfleura2
9994        FORMAT (46H0**ERROR** SOME DIMENSIONS ARE LESS THAN TWO I,8HN GINVSE &
257 1 pfleura2
                 /10X, 3HM =, I5, 5H MA =,I5, 4H N =, I5,5H NA =, I5, 5(/))
258 1 pfleura2
            !
259 1 pfleura2
            ! * * * END OF SUBROUTINE GINVSE * * *
260 1 pfleura2
            !
261 1 pfleura2
          END SUBROUTINE GINVSE