| 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
|
|---|