Statistiques
| Révision :

root / src / Ginvse.f90 @ 4

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

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