root / src / Ginvse.f90 @ 2
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 |