1 | ! $Id: ropp_pp_utils.f90 3491 2013-02-06 12:43:43Z idculv $
|
---|
2 |
|
---|
3 | MODULE ropp_pp_utils
|
---|
4 |
|
---|
5 | !****m* Modules/ropp_pp_utils *
|
---|
6 | !
|
---|
7 | ! NAME
|
---|
8 | ! ropp_pp_utils - Utility routines for ionospheric correction
|
---|
9 | !
|
---|
10 | ! SYNOPSIS
|
---|
11 | ! use ropp_pp_utils
|
---|
12 | !
|
---|
13 | ! DESCRIPTION
|
---|
14 | ! This module provides signal and matrix processing routines used by
|
---|
15 | ! the ROPP pre-processor ionospheric correction package.
|
---|
16 | !
|
---|
17 | ! AUTHOR
|
---|
18 | ! M Gorbunov, Russian Academy of Sciences, Russia.
|
---|
19 | ! Any comments on this software should be given via the ROM SAF
|
---|
20 | ! Helpdesk at http://www.romsaf.org
|
---|
21 | !
|
---|
22 | ! COPYRIGHT
|
---|
23 | ! Copyright (c) 1998-2010 Michael Gorbunov <michael.gorbunov@zmaw.de>
|
---|
24 | ! For further details please refer to the file COPYRIGHT
|
---|
25 | ! which you should have received as part of this distribution.
|
---|
26 | !
|
---|
27 | !****
|
---|
28 |
|
---|
29 | USE typesizes, ONLY: wp => EightByteReal
|
---|
30 |
|
---|
31 | INTERFACE ropp_pp_matmul
|
---|
32 | MODULE PROCEDURE ropp_pp_matmul_arr
|
---|
33 | MODULE PROCEDURE ropp_pp_matmul_vecl
|
---|
34 | MODULE PROCEDURE ropp_pp_matmul_vecr
|
---|
35 | END INTERFACE
|
---|
36 |
|
---|
37 | CONTAINS
|
---|
38 |
|
---|
39 | !****s* PPUtils/ropp_pp_matmul *
|
---|
40 | !
|
---|
41 | ! NAME
|
---|
42 | ! ropp_pp_matmul - Matrix multiplication
|
---|
43 | !
|
---|
44 | ! SYNOPSIS
|
---|
45 | ! C = ropp_pp_matmul(A, B)
|
---|
46 | !
|
---|
47 | ! DESCRIPTION
|
---|
48 | ! Replicates intrinsic 'MATMUL' function
|
---|
49 | !
|
---|
50 | !****
|
---|
51 | !
|
---|
52 | SUBROUTINE ropp_pp_matmul_sub(A, B, C)
|
---|
53 |
|
---|
54 | IMPLICIT NONE
|
---|
55 |
|
---|
56 | REAL(wp), DIMENSION(:,:), INTENT(in) :: A
|
---|
57 | REAL(wp), DIMENSION(:,:), INTENT(in) :: B
|
---|
58 | REAL(wp), DIMENSION(:,:), INTENT(out) :: C
|
---|
59 | INTEGER :: i, j, k
|
---|
60 |
|
---|
61 | DO i=1,SIZE(A,1)
|
---|
62 | DO j=1, SIZE(B,2)
|
---|
63 | C(i,j) = 0.0_wp
|
---|
64 | DO k=1, SIZE(B,1)
|
---|
65 | C(i,j) = C(i,j) + A(i,k)*B(k,j)
|
---|
66 | ENDDO
|
---|
67 | ENDDO
|
---|
68 | ENDDO
|
---|
69 |
|
---|
70 | END SUBROUTINE ropp_pp_matmul_sub
|
---|
71 |
|
---|
72 | FUNCTION ropp_pp_matmul_arr(A, B) RESULT (C)
|
---|
73 |
|
---|
74 | IMPLICIT NONE
|
---|
75 |
|
---|
76 | REAL(wp), DIMENSION(:,:), INTENT(in) :: A
|
---|
77 | REAL(wp), DIMENSION(:,:), INTENT(in) :: B
|
---|
78 | REAL(wp), DIMENSION(SIZE(A,1),SIZE(B,2)) :: C
|
---|
79 | INTEGER :: i, j, k
|
---|
80 |
|
---|
81 | DO i=1,SIZE(A,1)
|
---|
82 | DO j=1, SIZE(B,2)
|
---|
83 | C(i,j) = 0.0_wp
|
---|
84 | DO k=1, SIZE(B,1)
|
---|
85 | C(i,j) = C(i,j) + A(i,k)*B(k,j)
|
---|
86 | ENDDO
|
---|
87 | ENDDO
|
---|
88 | ENDDO
|
---|
89 |
|
---|
90 | END FUNCTION ropp_pp_matmul_arr
|
---|
91 |
|
---|
92 | FUNCTION ropp_pp_matmul_vecr(A, B) RESULT (C)
|
---|
93 |
|
---|
94 | IMPLICIT NONE
|
---|
95 |
|
---|
96 | REAL(wp), DIMENSION(:,:), INTENT(in) :: A
|
---|
97 | REAL(wp), DIMENSION(:), INTENT(in) :: B
|
---|
98 | REAL(wp), DIMENSION(SIZE(A,1)) :: C
|
---|
99 | INTEGER :: j, k
|
---|
100 |
|
---|
101 | DO j=1, SIZE(A,1)
|
---|
102 | C(j) = 0.0_wp
|
---|
103 | DO k=1, SIZE(B)
|
---|
104 | C(j) = C(j) + A(j,k)*B(k)
|
---|
105 | ENDDO
|
---|
106 | ENDDO
|
---|
107 |
|
---|
108 | END FUNCTION ropp_pp_matmul_vecr
|
---|
109 |
|
---|
110 | FUNCTION ropp_pp_matmul_vecl(A, B) RESULT (C)
|
---|
111 |
|
---|
112 | IMPLICIT NONE
|
---|
113 |
|
---|
114 | REAL(wp), DIMENSION(:), INTENT(in) :: A
|
---|
115 | REAL(wp), DIMENSION(:,:), INTENT(in) :: B
|
---|
116 | REAL(wp), DIMENSION(SIZE(B,2)) :: C
|
---|
117 | INTEGER :: j, k
|
---|
118 |
|
---|
119 | DO j=1, SIZE(B,2)
|
---|
120 | C(j) = 0.0_wp
|
---|
121 | DO k=1, SIZE(B,1)
|
---|
122 | C(j) = C(j) + A(k)*B(k,j)
|
---|
123 | ENDDO
|
---|
124 | ENDDO
|
---|
125 |
|
---|
126 | END FUNCTION ropp_pp_matmul_vecl
|
---|
127 |
|
---|
128 |
|
---|
129 | !****s* PPUtils/ropp_pp_invert_matrix *
|
---|
130 | !
|
---|
131 | ! NAME
|
---|
132 | ! ropp_pp_invert_matrix - Invert a matrix A(dimY, dimX)
|
---|
133 | !
|
---|
134 | ! SYNOPSIS
|
---|
135 | ! call ropp_pp_invert_matrix(A, B)
|
---|
136 | !
|
---|
137 | ! DESCRIPTION
|
---|
138 | ! Gauss elimination
|
---|
139 | !
|
---|
140 | !****
|
---|
141 | !
|
---|
142 | SUBROUTINE ropp_pp_invert_matrix(A, B)
|
---|
143 |
|
---|
144 | IMPLICIT NONE
|
---|
145 |
|
---|
146 | ! 2.1 Declarations
|
---|
147 |
|
---|
148 | REAL(wp), DIMENSION(:,:), INTENT(inout) :: A ! Matrix to invert
|
---|
149 | REAL(wp), DIMENSION(:,:), INTENT(out) :: B ! Inverted matrix
|
---|
150 |
|
---|
151 | INTEGER :: N ! Matrix dimension
|
---|
152 | INTEGER :: i, k ! Matrix indeces
|
---|
153 | INTEGER :: m(1) ! Search index
|
---|
154 | REAL(wp) :: Alpha ! Row combination coefficien
|
---|
155 | REAL(wp) :: Det ! Matrix determinant
|
---|
156 | REAL(wp) :: Amin, Amax ! Max and min diagonal elements
|
---|
157 | REAL(wp), DIMENSION(:), ALLOCATABLE :: F ! Exchange work space
|
---|
158 |
|
---|
159 | ! 2.2 Check array shape
|
---|
160 |
|
---|
161 | IF (SIZE(A,1) /= SIZE(A,2)) THEN
|
---|
162 | RETURN
|
---|
163 | ENDIF
|
---|
164 | IF (ANY(SHAPE(B) /= SHAPE(B))) THEN
|
---|
165 | RETURN
|
---|
166 | ENDIF
|
---|
167 |
|
---|
168 | ALLOCATE(F(SIZE(A,1)))
|
---|
169 |
|
---|
170 | ! 2.3 Initialization
|
---|
171 |
|
---|
172 | N = SIZE(A,1)
|
---|
173 | B(:,:) = 0.0_wp
|
---|
174 |
|
---|
175 | DO i=1,N
|
---|
176 | B(i,i) = 1.0_wp
|
---|
177 | ENDDO
|
---|
178 |
|
---|
179 | ! 2.4 Elimination of sub-diagonal elements
|
---|
180 |
|
---|
181 | Lower: DO k=1,N-1
|
---|
182 |
|
---|
183 | IF (A(k,k) == 0.0_wp) THEN
|
---|
184 | m(:) = MAXLOC(A(k+1:N,k), A(k+1:N,k) /= 0.0_wp)
|
---|
185 | IF (m(1) == 0) THEN
|
---|
186 | EXIT Lower
|
---|
187 | END IF
|
---|
188 | i = k + m(1)
|
---|
189 | F(:) = A(k,:)
|
---|
190 | A(k,:) = A(i,:)
|
---|
191 | A(i,:) = F(:)
|
---|
192 | F(:) = B(k,:)
|
---|
193 | B(k,:) = B(i,:)
|
---|
194 | B(i,:) = F(:)
|
---|
195 | END IF
|
---|
196 |
|
---|
197 | DO i=k+1,N
|
---|
198 | Alpha = A(i,k)/A(k,k)
|
---|
199 | A(i,:) = A(i,:) - Alpha*A(k,:)
|
---|
200 | B(i,:) = B(i,:) - Alpha*B(k,:)
|
---|
201 | END DO
|
---|
202 |
|
---|
203 | END DO Lower
|
---|
204 |
|
---|
205 | ! 2.5 Checking for degenerated matrix
|
---|
206 |
|
---|
207 | Det = 1.0_wp
|
---|
208 | Amin = ABS (A(1,1))
|
---|
209 | Amax = ABS (A(1,1))
|
---|
210 | Diagonal: DO i=1,N
|
---|
211 | Amin = MIN(ABS (A(i,i)), Amin)
|
---|
212 | Amax = MAX(ABS (A(i,i)), Amax)
|
---|
213 | Det = Det*A(i,i)
|
---|
214 | END DO Diagonal
|
---|
215 |
|
---|
216 | IF (Det == 0.0_wp) THEN
|
---|
217 | RETURN
|
---|
218 | END IF
|
---|
219 |
|
---|
220 | ! 2.6 Elimination of super-diagonal elements
|
---|
221 |
|
---|
222 | Upper: DO k=N,2,-1
|
---|
223 | DO i=k-1,1,-1
|
---|
224 | Alpha = A(i,k)/A(k,k)
|
---|
225 | A(i,:) = A(i,:) - Alpha*A(k,:)
|
---|
226 | B(i,:) = B(i,:) - Alpha*B(k,:)
|
---|
227 | END DO
|
---|
228 | END DO Upper
|
---|
229 |
|
---|
230 | DO i=1,N
|
---|
231 | B(i,:) = B(i,:)/A(i,i)
|
---|
232 | END DO
|
---|
233 |
|
---|
234 | DEALLOCATE(F)
|
---|
235 |
|
---|
236 | END SUBROUTINE ropp_pp_invert_matrix
|
---|
237 |
|
---|
238 | !****s* PPUtils/ropp_pp_quasi_invert *
|
---|
239 | !
|
---|
240 | ! NAME
|
---|
241 | ! ropp_pp_quasi_invert - Quasi-inverse of a matrix K(dimY, dimX)
|
---|
242 | !
|
---|
243 | ! SYNOPSIS
|
---|
244 | ! call ropp_pp_quasi_invert(K, Q)
|
---|
245 | !
|
---|
246 | ! DESCRIPTION
|
---|
247 | ! 1. dimY >= dimX:
|
---|
248 | ! x = Qy - vector minimizing ||Kx - y||
|
---|
249 | ! QK = E; Q is left inverse operator.
|
---|
250 | ! Q = (K^T K)^-1 K^T
|
---|
251 | ! 2. dimY <= dimX:
|
---|
252 | ! x = Qy - solution minimizing ||x||
|
---|
253 | ! KQ = E; Q is right inverse operator.
|
---|
254 | ! Q = K^T (KK^T)^-1
|
---|
255 | !
|
---|
256 | !****
|
---|
257 | !
|
---|
258 | SUBROUTINE ropp_pp_quasi_invert(K, Q)
|
---|
259 |
|
---|
260 | IMPLICIT NONE
|
---|
261 |
|
---|
262 | ! 3.1 Declarations
|
---|
263 |
|
---|
264 | REAL(wp), DIMENSION(:,:), INTENT(in) :: K ! Matrix to quasi-invert
|
---|
265 | REAL(wp), DIMENSION(:,:), INTENT(out) :: Q ! Quasi-inverse
|
---|
266 |
|
---|
267 | INTEGER :: DimX, DimY ! Dimension of x and y spaces
|
---|
268 | INTEGER :: N ! Work matrix dimension
|
---|
269 | REAL(wp), DIMENSION(:,:), ALLOCATABLE :: W ! Work arrays for inversion
|
---|
270 | REAL(wp), DIMENSION(:,:), ALLOCATABLE :: WI ! Work arrays for inversion
|
---|
271 | REAL(wp), DIMENSION(:,:), ALLOCATABLE :: KT
|
---|
272 |
|
---|
273 | ! 3.2 Initialization
|
---|
274 |
|
---|
275 | DimX = SIZE(K,2)
|
---|
276 | DimY = SIZE(K,1)
|
---|
277 |
|
---|
278 | IF (ANY(SHAPE(Q) /= (/ DimX, DimY /))) THEN
|
---|
279 | RETURN
|
---|
280 | END IF
|
---|
281 |
|
---|
282 | N = MIN(DimX, DimY)
|
---|
283 | ALLOCATE (W(N,N))
|
---|
284 | ALLOCATE (WI(N,N))
|
---|
285 | ALLOCATE (KT(DimX,DimY))
|
---|
286 |
|
---|
287 | KT = TRANSPOSE(K)
|
---|
288 |
|
---|
289 | ! 3.3 Quasi-Inversion
|
---|
290 |
|
---|
291 | IF (DimY >= DimX) THEN
|
---|
292 |
|
---|
293 | ! 3.3.1 Left inversion W=K^TK, WI=(K^TK)^-1, Q=(K^TK)^-1 K^T
|
---|
294 |
|
---|
295 | W = ropp_pp_matmul(KT, K)
|
---|
296 | CALL ropp_pp_invert_matrix(W, WI)
|
---|
297 | ! Q = ropp_pp_matmul(WI, KT)
|
---|
298 | CALL ropp_pp_matmul_sub(WI, KT, Q)
|
---|
299 |
|
---|
300 | ELSE
|
---|
301 |
|
---|
302 | ! 3.3.2. Right inversion W=KK^T, WI=(KK^T)^-1, Q=K^T(KK^T)^-1
|
---|
303 |
|
---|
304 | W = ropp_pp_matmul(K, KT)
|
---|
305 | CALL ropp_pp_invert_matrix(W, WI)
|
---|
306 | ! Q = ropp_pp_matmul(KT, WI)
|
---|
307 | CALL ropp_pp_matmul_sub(KT, WI, Q)
|
---|
308 |
|
---|
309 | END IF
|
---|
310 |
|
---|
311 | ! 3.4 Clean up
|
---|
312 |
|
---|
313 | DEALLOCATE (W)
|
---|
314 | DEALLOCATE (WI)
|
---|
315 | DEALLOCATE (KT)
|
---|
316 |
|
---|
317 | END SUBROUTINE ropp_pp_quasi_invert
|
---|
318 |
|
---|
319 | !****s* PPUtils/ropp_pp_polynomial *
|
---|
320 | !
|
---|
321 | ! NAME
|
---|
322 | ! ropp_pp_polynomial - Calculation of a polynomial and its derivative
|
---|
323 | !
|
---|
324 | ! SYNOPSIS
|
---|
325 | ! call ropp_pp_polynomial(c, x, P, DP)
|
---|
326 | !
|
---|
327 | ! DESCRIPTION
|
---|
328 | ! Horner scheme
|
---|
329 | !
|
---|
330 | !****
|
---|
331 | !
|
---|
332 | SUBROUTINE ropp_pp_polynomial(c, x, P, DP)
|
---|
333 |
|
---|
334 | USE typesizes, ONLY: wp => EightByteReal
|
---|
335 |
|
---|
336 | ! 4.1 Declarations
|
---|
337 |
|
---|
338 | IMPLICIT NONE
|
---|
339 |
|
---|
340 | REAL(wp), DIMENSION(0:), INTENT(in) :: c ! polynomial coefficients
|
---|
341 | REAL(wp), INTENT(in) :: x ! polynomial argument
|
---|
342 | REAL(wp), INTENT(out) :: P ! polynomial value
|
---|
343 | REAL(wp), OPTIONAL, INTENT(out) :: DP ! polynomial derivative
|
---|
344 |
|
---|
345 | INTEGER :: n, i
|
---|
346 |
|
---|
347 | ! 4.2 Calculate polynomial value
|
---|
348 |
|
---|
349 | n = UBOUND(c,1)
|
---|
350 |
|
---|
351 | P = c(n)
|
---|
352 | DO i = n-1, 0, -1
|
---|
353 | P = c(i) + x*P
|
---|
354 | ENDDO
|
---|
355 |
|
---|
356 | ! 4.3 Calculate polynomial derivative
|
---|
357 |
|
---|
358 | IF ( PRESENT(DP) ) THEN
|
---|
359 | DP = c(n)*REAL(n,wp)
|
---|
360 | DO i = n-1, 1, -1
|
---|
361 | DP = c(i)*REAL(i,wp) + x*DP
|
---|
362 | ENDDO
|
---|
363 | ENDIF
|
---|
364 |
|
---|
365 | END SUBROUTINE ropp_pp_polynomial
|
---|
366 |
|
---|
367 | !****s* PPUtils/ropp_pp_init_polynomial *
|
---|
368 | !
|
---|
369 | ! NAME
|
---|
370 | ! ropp_pp_init_polynomial - Generate matrix of basic polynomials
|
---|
371 | ! for regression
|
---|
372 | !
|
---|
373 | ! SYNOPSIS
|
---|
374 | ! call ropp_pp_init_polynomial(x, K)
|
---|
375 | !
|
---|
376 | ! DESCRIPTION
|
---|
377 | ! Compute basic polynomials as
|
---|
378 | ! K_ij = f_j(x_i) = (x_i)^j for j=0..UBound(K,2)
|
---|
379 | !
|
---|
380 | !****
|
---|
381 | !
|
---|
382 | SUBROUTINE ropp_pp_init_polynomial(x, K)
|
---|
383 |
|
---|
384 | USE typesizes, ONLY: wp => EightByteReal
|
---|
385 |
|
---|
386 | ! 5.1 Declarations
|
---|
387 |
|
---|
388 | IMPLICIT NONE
|
---|
389 |
|
---|
390 | REAL(wp), DIMENSION(1:), INTENT(in) :: x ! grid of argument x
|
---|
391 | REAL(wp), DIMENSION(1:,0:), INTENT(out) :: K ! matrix of polynomials
|
---|
392 | INTEGER :: i,j
|
---|
393 |
|
---|
394 | ! 5.2 Generate polynomials
|
---|
395 |
|
---|
396 | K(:,0) = 1.0_wp
|
---|
397 | DO j=1,UBOUND(K,2)
|
---|
398 | DO i=1,SIZE(x)
|
---|
399 | IF (x(i) > 0) THEN
|
---|
400 | K(i, j) = x(i)**REAL(j,wp)
|
---|
401 | ELSE
|
---|
402 | K(i, j) = x(i)**INT(REAL(j,wp))
|
---|
403 | ENDIF
|
---|
404 | ENDDO
|
---|
405 | ENDDO
|
---|
406 |
|
---|
407 | END SUBROUTINE ropp_pp_init_polynomial
|
---|
408 |
|
---|
409 | !****s* PPUtils/ropp_pp_regression *
|
---|
410 | !
|
---|
411 | ! NAME
|
---|
412 | ! ropp_pp_regression - Linear regression
|
---|
413 | !
|
---|
414 | ! SYNOPSIS
|
---|
415 | ! call ropp_pp_regression(K, y, a)
|
---|
416 | !
|
---|
417 | ! DESCRIPTION
|
---|
418 | ! Quasi-inversion of matrix of basic functions:
|
---|
419 | ! || Sum_j a_j f_j(x_i) - y_i || = min
|
---|
420 | ! Solution is a = Q y where Q is left inverse of K_ij = f_j(x_i)
|
---|
421 | !
|
---|
422 | !****
|
---|
423 | !
|
---|
424 | SUBROUTINE ropp_pp_regression(K, y, a)
|
---|
425 |
|
---|
426 | USE typesizes, ONLY: wp => EightByteReal
|
---|
427 |
|
---|
428 | ! 6.1 Declarations
|
---|
429 |
|
---|
430 | IMPLICIT NONE
|
---|
431 |
|
---|
432 | REAL(wp), DIMENSION(:,:), INTENT(in) :: K ! matrix of functions
|
---|
433 | REAL(wp), DIMENSION(:), INTENT(in) :: y ! regression data
|
---|
434 | REAL(wp), DIMENSION(:), INTENT(out) :: a ! regression coefficients
|
---|
435 |
|
---|
436 | REAL(wp), DIMENSION(:,:), ALLOCATABLE :: Q ! quasi-inverse matrix
|
---|
437 |
|
---|
438 | ALLOCATE(Q(SIZE(K,2), SIZE(K,1)))
|
---|
439 |
|
---|
440 | ! 6.2 Invert matrix of functions
|
---|
441 |
|
---|
442 | CALL ropp_pp_quasi_invert(K, Q)
|
---|
443 |
|
---|
444 | ! 6.3 Solve to find coefficients
|
---|
445 |
|
---|
446 |
|
---|
447 | a(:) = ropp_pp_matmul(Q, y(:))
|
---|
448 |
|
---|
449 | DEALLOCATE(Q)
|
---|
450 |
|
---|
451 | END SUBROUTINE ropp_pp_regression
|
---|
452 |
|
---|
453 | !****s* PPUtils/ropp_pp_residual_regression *
|
---|
454 | !
|
---|
455 | ! NAME
|
---|
456 | ! ropp_pp_residual_regression - linear regression on residual
|
---|
457 | !
|
---|
458 | ! SYNOPSIS
|
---|
459 | ! call ropp_pp_residual_regression(K, x, y, a)
|
---|
460 | !
|
---|
461 | ! DESCRIPTION
|
---|
462 | ! Updates the regression coefficients using
|
---|
463 | ! the residual from a previous regression estimate
|
---|
464 | !
|
---|
465 | !****
|
---|
466 | !
|
---|
467 |
|
---|
468 | SUBROUTINE ropp_pp_residual_regression(K, x, y, a)
|
---|
469 |
|
---|
470 | USE typesizes, ONLY: wp => EightByteReal
|
---|
471 |
|
---|
472 | ! 7.1 Declarations
|
---|
473 |
|
---|
474 | IMPLICIT NONE
|
---|
475 |
|
---|
476 | REAL(wp), DIMENSION(:,:),INTENT(in) :: K ! matrix of functions
|
---|
477 | REAL(wp), DIMENSION(:), INTENT(in) :: x ! independent variable
|
---|
478 | REAL(wp), DIMENSION(:), INTENT(in) :: y ! regression data
|
---|
479 | REAL(wp), DIMENSION(:), INTENT(inout):: a ! regression coefficients
|
---|
480 |
|
---|
481 | REAL(wp), DIMENSION(:), ALLOCATABLE :: y_a ! polynomial data
|
---|
482 | REAL(wp), DIMENSION(:), ALLOCATABLE :: y_res ! residual data
|
---|
483 | REAL(wp), DIMENSION(:), ALLOCATABLE :: a_res ! residual coefficients
|
---|
484 | INTEGER :: i
|
---|
485 |
|
---|
486 | ALLOCATE(y_a(SIZE(y)))
|
---|
487 | ALLOCATE(y_res(SIZE(y)))
|
---|
488 | ALLOCATE(a_res(SIZE(a)))
|
---|
489 |
|
---|
490 | ! 7.2 Calculate polynomial data from input regression coefficients
|
---|
491 |
|
---|
492 | DO i=1,SIZE(y)
|
---|
493 | CALL ropp_pp_polynomial(a, x(i), y_a(i))
|
---|
494 | END DO
|
---|
495 |
|
---|
496 | ! 7.3 Perform regression on the residuals
|
---|
497 |
|
---|
498 | y_res(:) = y(:) - y_a(:)
|
---|
499 |
|
---|
500 | CALL ropp_pp_regression(K, y_res, a_res)
|
---|
501 |
|
---|
502 | ! 7.4 Update the regression coefficients
|
---|
503 |
|
---|
504 | a(:) = a(:) + a_res(:)
|
---|
505 |
|
---|
506 | DEALLOCATE(y_a)
|
---|
507 | DEALLOCATE(y_res)
|
---|
508 | DEALLOCATE(a_res)
|
---|
509 |
|
---|
510 | END SUBROUTINE ropp_pp_residual_regression
|
---|
511 |
|
---|
512 | !****s* PPUtils/ropp_pp_nearest_power2 *
|
---|
513 | !
|
---|
514 | ! NAME
|
---|
515 | ! ropp_pp_nearest_power2 - Find power of 2 nearest input integer
|
---|
516 | !
|
---|
517 | ! SYNOPSIS
|
---|
518 | ! n2 = ropp_pp_nearest_power2(n)
|
---|
519 | !
|
---|
520 | !****
|
---|
521 |
|
---|
522 | FUNCTION ropp_pp_nearest_power2(N) RESULT(nearest_power2)
|
---|
523 |
|
---|
524 | IMPLICIT NONE
|
---|
525 | INTEGER, INTENT(in) :: N ! given integer number
|
---|
526 | INTEGER :: nearest_power2 ! power of 2 right-nearest to N
|
---|
527 | INTEGER :: i
|
---|
528 |
|
---|
529 | i = 1
|
---|
530 |
|
---|
531 | DO
|
---|
532 | IF (i >= N) THEN
|
---|
533 | Nearest_Power2 = i
|
---|
534 | RETURN
|
---|
535 | ENDIF
|
---|
536 | i = 2*i
|
---|
537 | ENDDO
|
---|
538 |
|
---|
539 | END FUNCTION ropp_pp_nearest_power2
|
---|
540 |
|
---|
541 |
|
---|
542 | !****s* PPUtils/ropp_pp_isnan *
|
---|
543 | !
|
---|
544 | ! NAME
|
---|
545 | ! ropp_pp_isnan - Test if variable value is NaN
|
---|
546 | !
|
---|
547 | ! SYNOPSIS
|
---|
548 | ! true_or_false = ropp_pp_isnan(x)
|
---|
549 | !
|
---|
550 | !****
|
---|
551 |
|
---|
552 | FUNCTION ropp_pp_isnan(x) RESULT(it_is)
|
---|
553 |
|
---|
554 | USE typesizes, ONLY: wp => EightByteReal
|
---|
555 | IMPLICIT NONE
|
---|
556 |
|
---|
557 | REAL(wp), INTENT(in) :: x
|
---|
558 | LOGICAL :: it_is
|
---|
559 |
|
---|
560 | it_is = .FALSE.
|
---|
561 |
|
---|
562 | IF ( x /= x ) it_is = .TRUE.
|
---|
563 | IF ( x + 1.0_wp == x ) it_is = .TRUE.
|
---|
564 | IF ((x > 0) .EQV. (x <= 0)) it_is=.true.
|
---|
565 |
|
---|
566 | END FUNCTION ropp_pp_isnan
|
---|
567 |
|
---|
568 | END MODULE ropp_pp_utils
|
---|