|
libsim Versione 8.0.0
|
◆ grid_transform_compute()
Compute the output data array from input data array according to the defined transformation. The grid_transform object this must have been properly initialised, so that it contains all the information needed for computing the transformation. This is the grid-to-grid and grid-to-sparse points version. In the case of grid-to-sparse points transformation, the output argument is still a 2-d array with shape (np,1), which may have to be reshaped and assigned to the target 1-d array after the subroutine call by means of the RESHAPE() intrinsic function.
Definizione alla linea 3145 del file grid_transform_class.F90. 3147 ii = ii+1
3148 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3149 IF (navg > 0) THEN
3150 field_out(ii,jj,k) = sum(field_in(i:ie,j:je,k), &
3151 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3152 ENDIF
3153 ENDDO
3154 ENDDO
3155 ENDDO
3156
3157 ENDIF
3158
3159 ELSE IF (this%trans%sub_type == 'stddev' .OR. &
3160 this%trans%sub_type == 'stddevnm1') THEN
3161
3162 IF (this%trans%sub_type == 'stddev') THEN
3163 nm1 = .false.
3164 ELSE
3165 nm1 = .true.
3166 ENDIF
3167
3168 navg = this%trans%box_info%npx*this%trans%box_info%npy
3169 DO k = 1, innz
3170 IF (.NOT.lzlist(k)) cycle
3171 jj = 0
3172 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3173 je = j+this%trans%box_info%npy-1
3174 jj = jj+1
3175 ii = 0
3176 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3177 ie = i+this%trans%box_info%npx-1
3178 ii = ii+1
3179 field_out(ii,jj,k) = stat_stddev( &
3180 reshape(field_in(i:ie,j:je,k),(/navg/)), nm1=nm1)
3181 ENDDO
3182 ENDDO
3183 ENDDO
3184
3185 ELSE IF (this%trans%sub_type == 'max') THEN
3186 DO k = 1, innz
3187 IF (.NOT.lzlist(k)) cycle
3188 jj = 0
3189 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3190 je = j+this%trans%box_info%npy-1
3191 jj = jj+1
3192 ii = 0
3193 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3194 ie = i+this%trans%box_info%npx-1
3195 ii = ii+1
3196 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3197 IF (navg > 0) THEN
3198 field_out(ii,jj,k) = maxval(field_in(i:ie,j:je,k), &
3199 mask=(field_in(i:ie,j:je,k) /= rmiss))
3200 ENDIF
3201 ENDDO
3202 ENDDO
3203 ENDDO
3204
3205 ELSE IF (this%trans%sub_type == 'min') THEN
3206 DO k = 1, innz
3207 IF (.NOT.lzlist(k)) cycle
3208 jj = 0
3209 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3210 je = j+this%trans%box_info%npy-1
3211 jj = jj+1
3212 ii = 0
3213 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3214 ie = i+this%trans%box_info%npx-1
3215 ii = ii+1
3216 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3217 IF (navg > 0) THEN
3218 field_out(ii,jj,k) = minval(field_in(i:ie,j:je,k), &
3219 mask=(field_in(i:ie,j:je,k) /= rmiss))
3220 ENDIF
3221 ENDDO
3222 ENDDO
3223 ENDDO
3224
3225 ELSE IF (this%trans%sub_type == 'percentile') THEN
3226
3227 navg = this%trans%box_info%npx*this%trans%box_info%npy
3228 DO k = 1, innz
3229 IF (.NOT.lzlist(k)) cycle
3230 jj = 0
3231 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3232 je = j+this%trans%box_info%npy-1
3233 jj = jj+1
3234 ii = 0
3235 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3236 ie = i+this%trans%box_info%npx-1
3237 ii = ii+1
3238 field_out(ii:ii,jj,k) = stat_percentile( &
3239 reshape(field_in(i:ie,j:je,k),(/navg/)), &
3240 (/real(this%trans%stat_info%percentile)/))
3241 ENDDO
3242 ENDDO
3243 ENDDO
3244
3245 ELSE IF (this%trans%sub_type == 'frequency') THEN
3246
3247 DO k = 1, innz
3248 IF (.NOT.lzlist(k)) cycle
3249 jj = 0
3250 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3251 je = j+this%trans%box_info%npy-1
3252 jj = jj+1
3253 ii = 0
3254 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3255 ie = i+this%trans%box_info%npx-1
3256 ii = ii+1
3257 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3258 IF (navg > 0) THEN
3259 field_out(ii,jj,k) = sum(interval_info_valid( &
3260 this%trans%interval_info, field_in(i:ie,j:je,k)), &
3261 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3262 ENDIF
3263 ENDDO
3264 ENDDO
3265 ENDDO
3266
3267 ENDIF
3268
3269ELSE IF (this%trans%trans_type == 'inter') THEN
3270
3271 IF (this%trans%sub_type == 'near') THEN
3272
3273 DO k = 1, innz
3274 IF (.NOT.lzlist(k)) cycle
3275 DO j = 1, this%outny
3276 DO i = 1, this%outnx
3277
3278 IF (c_e(this%inter_index_x(i,j))) field_out(i,j,k) = &
3279 field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3280
3281 ENDDO
3282 ENDDO
3283 ENDDO
3284
3285 ELSE IF (this%trans%sub_type == 'bilin') THEN
3286
3287 DO k = 1, innz
3288 IF (.NOT.lzlist(k)) cycle
3289 DO j = 1, this%outny
3290 DO i = 1, this%outnx
3291
3292 IF (c_e(this%inter_index_x(i,j))) THEN
3293
3294 z1=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3295 z2=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j),k)
3296 z3=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1,k)
3297 z4=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j)+1,k)
3298
3299 IF (c_e(z1) .AND. c_e(z2) .AND. c_e(z3) .AND. c_e(z4)) THEN
3300
3301 x1=this%inter_x(this%inter_index_x(i,j),this%inter_index_y(i,j))
3302 y1=this%inter_y(this%inter_index_x(i,j),this%inter_index_y(i,j))
3303 x3=this%inter_x(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3304 y3=this%inter_y(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3305
3306 xp=this%inter_xp(i,j)
3307 yp=this%inter_yp(i,j)
3308
3309 field_out(i,j,k) = hbilin(z1,z2,z3,z4,x1,y1,x3,y3,xp,yp)
3310
3311 ENDIF
3312 ENDIF
3313
3314 ENDDO
3315 ENDDO
3316 ENDDO
3317 ELSE IF (this%trans%sub_type == 'shapiro_near') THEN
3318 DO k = 1, innz
3319 IF (.NOT.lzlist(k)) cycle
3320 DO j = 1, this%outny
3321 DO i = 1, this%outnx
3322
3323 IF (c_e(this%inter_index_x(i,j))) THEN
3324
3325 IF(this%inter_index_x(i,j)-1>0)THEN
3326 z(1) = field_in(this%inter_index_x(i,j)-1,this%inter_index_y(i,j) ,k)
3327 ELSE
3328 z(1) = rmiss
3329 END IF
3330 IF(this%inter_index_x(i,j)+1<=this%outnx)THEN
3331 z(3)=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j) ,k)
3332 ELSE
3333 z(3) = rmiss
3334 END IF
3335 IF(this%inter_index_y(i,j)+1<=this%outny)THEN
3336 z(2)=field_in(this%inter_index_x(i,j) ,this%inter_index_y(i,j)+1,k)
3337 ELSE
3338 z(2) = rmiss
3339 END IF
3340 IF(this%inter_index_y(i,j)-1>0)THEN
3341 z(4)=field_in(this%inter_index_x(i,j), this%inter_index_y(i,j)-1,k)
3342 ELSE
3343 z(4) = rmiss
3344 END IF
3345 field_out(i,j,k) = shapiro(z,field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k))
3346
3347 ENDIF
3348
3349 ENDDO
3350 ENDDO
3351 ENDDO
3352
3353 ENDIF
3354ELSE IF (this%trans%trans_type == 'intersearch') THEN
3355
3356 likethis = this
3357 likethis%trans%trans_type = 'inter' ! fake type and make a recursive call to compute base field
3358 CALL grid_transform_compute(likethis, field_in, field_out, var, coord_3d_in, zlist)
3359 CALL getenv('LIBSIM_DISABLEOPTSEARCH', env_var)
3360 optsearch = len_trim(env_var) == 0
3361
3362 DO k = 1, innz
3363 IF (.NOT.lzlist(k)) cycle
3364 IF ((.NOT.all(c_e(field_out(:,:,k)))) .AND. (any(c_e(field_in(:,:,k))))) THEN ! must fill some values
3365 DO j = 1, this%outny
3366 DO i = 1, this%outnx
3367 IF (.NOT.c_e(field_out(i,j,k))) THEN
3368 dist = huge(dist)
3369 nearcount = 0
3370 IF (optsearch) THEN ! optimized, error-prone algorithm
3371 ix = this%inter_index_x(i,j)
3372 iy = this%inter_index_y(i,j)
3373 DO s = 0, max(this%innx, this%inny)
3374 farenough = .true.
3375 DO m = iy-s, iy+s, max(2*s, 1) ! y loop on upper and lower frames
3376 IF (m < 1 .OR. m > this%inny) cycle
3377 DO l = max(1, ix-s), min(this%innx, ix+s) ! x loop on upper and lower frames
3378 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3379 IF (c_e(field_in(l,m,k))) THEN
3380 IF (disttmp < dist) THEN
3381 dist = disttmp
3382 field_out(i,j,k) = field_in(l,m,k)
3383 nearcount = 1
3384 ELSE IF (disttmp == dist) THEN
3385 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3386 nearcount = nearcount + 1
3387 ENDIF
3388 ENDIF
3389 IF (disttmp < dist) farenough = .false.
3390 ENDDO
3391 ENDDO
3392 DO m = max(1, iy-s+1), min(this%inny, iy+s-1) ! y loop on left and right frames (avoid corners)
3393 DO l = ix-s, ix+s, 2*s ! x loop on left and right frames (exchange loops?)
3394 IF (l < 1 .OR. l > this%innx) cycle
3395 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3396 IF (c_e(field_in(l,m,k))) THEN
3397 IF (disttmp < dist) THEN
3398 dist = disttmp
3399 field_out(i,j,k) = field_in(l,m,k)
3400 nearcount = 1
3401 ELSE IF (disttmp == dist) THEN
3402 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3403 nearcount = nearcount + 1
3404 ENDIF
3405 ENDIF
3406 IF (disttmp < dist) farenough = .false.
3407 ENDDO
3408 ENDDO
3409 IF (s > 0 .AND. farenough) EXIT ! nearest point found, do not trust the same point, in case of bilin it could be not the nearest
3410 ENDDO
3411 ELSE ! linear, simple, slow algorithm
3412 DO m = 1, this%inny
3413 DO l = 1, this%innx
3414 IF (c_e(field_in(l,m,k))) THEN
3415 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3416 IF (disttmp < dist) THEN
3417 dist = disttmp
3418 field_out(i,j,k) = field_in(l,m,k)
3419 nearcount = 1
3420 ELSE IF (disttmp == dist) THEN
3421 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3422 nearcount = nearcount + 1
3423 ENDIF
3424 ENDIF
3425 ENDDO
3426 ENDDO
3427 ENDIF
3428! average points with same minimum distance
3429 IF (nearcount > 1) field_out(i,j,k) = field_out(i,j,k)/nearcount
3430 ENDIF
3431 ENDDO
3432 ENDDO
3433 ENDIF
3434 ENDDO
3435
3436ELSE IF (this%trans%trans_type == 'boxinter' &
3437 .OR. this%trans%trans_type == 'polyinter' &
3438 .OR. this%trans%trans_type == 'maskinter') THEN
3439
3440 IF (this%trans%sub_type == 'average') THEN
3441
3442 IF (vartype == var_dir360) THEN
3443 DO k = 1, innz
3444 IF (.NOT.lzlist(k)) cycle
3445 DO j = 1, this%outny
3446 DO i = 1, this%outnx
3447 field_out(i,j,k) = find_prevailing_direction(field_in(:,:,k), &
3448 0.0, 360.0, 5.0, &
3449 mask=this%inter_index_x(:,:) == i .AND. this%inter_index_y(:,:) == j)
3450 ENDDO
3451 ENDDO
3452 ENDDO
3453
3454 ELSE
3455 ALLOCATE(nval(this%outnx, this%outny))
3456 field_out(:,:,:) = 0.0
3457 DO k = 1, innz
3458 IF (.NOT.lzlist(k)) cycle
3459 nval(:,:) = 0
3460 DO j = 1, this%inny
3461 DO i = 1, this%innx
3462 IF (c_e(this%inter_index_x(i,j)) .AND. c_e(field_in(i,j,k))) THEN
3463 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3464 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3465 field_in(i,j,k)
3466 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3467 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3468 ENDIF
3469 ENDDO
3470 ENDDO
3471 WHERE (nval(:,:) /= 0)
3472 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3473 ELSEWHERE
3474 field_out(:,:,k) = rmiss
3475 END WHERE
3476 ENDDO
3477 DEALLOCATE(nval)
3478 ENDIF
3479
3480 ELSE IF (this%trans%sub_type == 'stddev' .OR. &
3481 this%trans%sub_type == 'stddevnm1') THEN
3482
3483 IF (this%trans%sub_type == 'stddev') THEN
3484 nm1 = .false.
3485 ELSE
3486 nm1 = .true.
3487 ENDIF
3488 DO k = 1, innz
3489 IF (.NOT.lzlist(k)) cycle
3490 DO j = 1, this%outny
3491 DO i = 1, this%outnx
3492! da paura
3493 field_out(i:i,j,k) = stat_stddev( &
3494 reshape(field_in(:,:,k), (/SIZE(field_in(:,:,k))/)), &
3495 mask=reshape((this%inter_index_x == i .AND. &
3496 this%inter_index_y == j), (/SIZE(field_in(:,:,k))/)), nm1=nm1)
3497 ENDDO
3498 ENDDO
3499 ENDDO
3500
3501 ELSE IF (this%trans%sub_type == 'max') THEN
3502
3503 DO k = 1, innz
3504 IF (.NOT.lzlist(k)) cycle
3505 DO j = 1, this%inny
3506 DO i = 1, this%innx
3507 IF (c_e(this%inter_index_x(i,j)) .AND. c_e(field_in(i,j,k))) THEN
3508 IF (c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k))) THEN
3509 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3510 max(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3511 field_in(i,j,k))
3512 ELSE
3513 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3514 field_in(i,j,k)
3515 ENDIF
3516 ENDIF
3517 ENDDO
3518 ENDDO
3519 ENDDO
3520
3521
3522 ELSE IF (this%trans%sub_type == 'min') THEN
3523
3524 DO k = 1, innz
3525 IF (.NOT.lzlist(k)) cycle
3526 DO j = 1, this%inny
3527 DO i = 1, this%innx
3528 IF (c_e(this%inter_index_x(i,j)) .AND. c_e(field_in(i,j,k))) THEN
3529 IF (c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k))) THEN
3530 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3531 min(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3532 field_in(i,j,k))
3533 ELSE
3534 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3535 field_in(i,j,k)
3536 ENDIF
3537 ENDIF
3538 ENDDO
3539 ENDDO
3540 ENDDO
3541
3542 ELSE IF (this%trans%sub_type == 'percentile') THEN
3543
3544 DO k = 1, innz
3545 IF (.NOT.lzlist(k)) cycle
3546 DO j = 1, this%outny
3547 DO i = 1, this%outnx
3548! da paura
3549 field_out(i:i,j,k) = stat_percentile( &
3550 reshape(field_in(:,:,k), (/SIZE(field_in(:,:,k))/)), &
3551 (/real(this%trans%stat_info%percentile)/), &
3552 mask=reshape((this%inter_index_x == i .AND. &
3553 this%inter_index_y == j), (/SIZE(field_in(:,:,k))/)))
3554 ENDDO
3555 ENDDO
3556 ENDDO
3557
3558 ELSE IF (this%trans%sub_type == 'frequency') THEN
3559
3560 ALLOCATE(nval(this%outnx, this%outny))
3561 DO k = 1, innz
3562 IF (.NOT.lzlist(k)) cycle
3563 field_out(:,:,k) = 0.0
3564 nval(:,:) = 0
3565 DO j = 1, this%inny
3566 DO i = 1, this%innx
3567 IF (c_e(this%inter_index_x(i,j)) .AND. c_e(field_in(i,j,k))) THEN
3568 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3569 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3570 interval_info_valid(this%trans%interval_info, field_in(i,j,k))
3571 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3572 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3573 ENDIF
3574 ENDDO
3575 ENDDO
3576 WHERE (nval(:,:) /= 0)
3577 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3578 ELSEWHERE
3579 field_out(:,:,k) = rmiss
3580 END WHERE
3581 ENDDO
3582 DEALLOCATE(nval)
3583
3584 ENDIF
3585
3586ELSE IF (this%trans%trans_type == 'stencilinter') THEN
3587 np = SIZE(this%stencil,1)/2
3588 ns = SIZE(this%stencil)
3589
3590 IF (this%trans%sub_type == 'average') THEN
3591
3592 IF (vartype == var_dir360) THEN
3593 DO k = 1, innz
3594 IF (.NOT.lzlist(k)) cycle
3595 DO j = 1, this%outny
3596 DO i = 1, this%outnx
3597 IF (c_e(this%inter_index_x(i,j))) THEN
3598 i1 = this%inter_index_x(i,j) - np
3599 i2 = this%inter_index_x(i,j) + np
3600 j1 = this%inter_index_y(i,j) - np
3601 j2 = this%inter_index_y(i,j) + np
3602 field_out(i,j,k) = find_prevailing_direction(field_in(i1:i2,j1:j2,k), &
3603 0.0, 360.0, 5.0, &
3604 mask=this%stencil(:,:)) ! simpler and equivalent form
3605! mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3606 ENDIF
3607 ENDDO
3608 ENDDO
3609 ENDDO
3610
3611 ELSE
3612!$OMP PARALLEL DEFAULT(SHARED)
3613!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2, n)
3614 DO k = 1, innz
3615 IF (.NOT.lzlist(k)) cycle
3616 DO j = 1, this%outny
3617 DO i = 1, this%outnx
3618 IF (c_e(this%inter_index_x(i,j))) THEN
3619 i1 = this%inter_index_x(i,j) - np
3620 i2 = this%inter_index_x(i,j) + np
3621 j1 = this%inter_index_y(i,j) - np
3622 j2 = this%inter_index_y(i,j) + np
3623 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3624 IF (n > 0) THEN
3625 field_out(i,j,k) = sum(field_in(i1:i2,j1:j2,k), &
3626 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3627 ENDIF
3628 ENDIF
3629 ENDDO
3630 ENDDO
3631 ENDDO
3632!$OMP END PARALLEL
3633 ENDIF
3634
3635 ELSE IF (this%trans%sub_type == 'stddev' .OR. &
3636 this%trans%sub_type == 'stddevnm1') THEN
3637
3638 IF (this%trans%sub_type == 'stddev') THEN
3639 nm1 = .false.
3640 ELSE
3641 nm1 = .true.
3642 ENDIF
3643
3644!$OMP PARALLEL DEFAULT(SHARED)
3645!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2)
3646 DO k = 1, innz
3647 IF (.NOT.lzlist(k)) cycle
3648 DO j = 1, this%outny
3649 DO i = 1, this%outnx
3650 IF (c_e(this%inter_index_x(i,j))) THEN
3651 i1 = this%inter_index_x(i,j) - np
3652 i2 = this%inter_index_x(i,j) + np
3653 j1 = this%inter_index_y(i,j) - np
3654 j2 = this%inter_index_y(i,j) + np
3655! da paura
3656 field_out(i:i,j,k) = stat_stddev( &
3657 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3658 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3659 this%stencil(:,:), (/ns/)), nm1=nm1)
3660 ENDIF
3661 ENDDO
3662 ENDDO
3663 ENDDO
3664!$OMP END PARALLEL
3665
3666 ELSE IF (this%trans%sub_type == 'max') THEN
3667
3668!$OMP PARALLEL DEFAULT(SHARED)
3669!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2, n)
3670 DO k = 1, innz
3671 IF (.NOT.lzlist(k)) cycle
3672 DO j = 1, this%outny
3673 DO i = 1, this%outnx
3674 IF (c_e(this%inter_index_x(i,j))) THEN
3675 i1 = this%inter_index_x(i,j) - np
3676 i2 = this%inter_index_x(i,j) + np
3677 j1 = this%inter_index_y(i,j) - np
3678 j2 = this%inter_index_y(i,j) + np
3679 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3680 IF (n > 0) THEN
3681 field_out(i,j,k) = maxval(field_in(i1:i2,j1:j2,k), &
3682 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3683 ENDIF
3684 ENDIF
3685 ENDDO
3686 ENDDO
3687 ENDDO
3688!$OMP END PARALLEL
3689
3690 ELSE IF (this%trans%sub_type == 'min') THEN
3691
3692!$OMP PARALLEL DEFAULT(SHARED)
3693!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2, n)
3694 DO k = 1, innz
3695 IF (.NOT.lzlist(k)) cycle
3696 DO j = 1, this%outny
3697 DO i = 1, this%outnx
3698 IF (c_e(this%inter_index_x(i,j))) THEN
3699 i1 = this%inter_index_x(i,j) - np
3700 i2 = this%inter_index_x(i,j) + np
3701 j1 = this%inter_index_y(i,j) - np
3702 j2 = this%inter_index_y(i,j) + np
3703 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3704 IF (n > 0) THEN
3705 field_out(i,j,k) = minval(field_in(i1:i2,j1:j2,k), &
3706 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3707 ENDIF
3708 ENDIF
3709 ENDDO
3710 ENDDO
3711 ENDDO
3712!$OMP END PARALLEL
3713
3714 ELSE IF (this%trans%sub_type == 'percentile') THEN
3715
3716!$OMP PARALLEL DEFAULT(SHARED)
3717!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2)
3718 DO k = 1, innz
3719 IF (.NOT.lzlist(k)) cycle
3720 DO j = 1, this%outny
3721 DO i = 1, this%outnx
3722 IF (c_e(this%inter_index_x(i,j))) THEN
3723 i1 = this%inter_index_x(i,j) - np
3724 i2 = this%inter_index_x(i,j) + np
3725 j1 = this%inter_index_y(i,j) - np
3726 j2 = this%inter_index_y(i,j) + np
3727! da paura
3728 field_out(i:i,j,k) = stat_percentile( &
3729 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3730 (/real(this%trans%stat_info%percentile)/), &
3731 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3732 this%stencil(:,:), (/ns/)))
3733 ENDIF
3734 ENDDO
3735 ENDDO
3736 ENDDO
3737!$OMP END PARALLEL
3738
3739 ELSE IF (this%trans%sub_type == 'frequency') THEN
3740
3741!$OMP PARALLEL DEFAULT(SHARED)
3742!$OMP DO PRIVATE(i, j, k, i1, i2, j1, j2, n)
3743 DO k = 1, innz
3744 IF (.NOT.lzlist(k)) cycle
3745 DO j = 1, this%outny
3746 DO i = 1, this%outnx
3747 IF (c_e(this%inter_index_x(i,j))) THEN
3748 i1 = this%inter_index_x(i,j) - np
3749 i2 = this%inter_index_x(i,j) + np
3750 j1 = this%inter_index_y(i,j) - np
3751 j2 = this%inter_index_y(i,j) + np
3752 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3753 IF (n > 0) THEN
3754 field_out(i,j,k) = sum(interval_info_valid( &
3755 this%trans%interval_info, field_in(i1:i2,j1:j2,k)), &
3756 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3757 ENDIF
3758 ENDIF
3759 ENDDO
3760 ENDDO
3761 ENDDO
3762!$OMP END PARALLEL
3763
3764 ENDIF
3765
3766ELSE IF (this%trans%trans_type == 'maskgen') THEN
3767
3768 DO k = 1, innz
3769 WHERE(c_e(this%inter_index_x(:,:)))
3770 field_out(:,:,k) = real(this%inter_index_x(:,:))
3771 END WHERE
3772 ENDDO
3773
3774ELSE IF (this%trans%trans_type == 'metamorphosis') THEN
3775
3776 IF (this%trans%sub_type == 'all') THEN
3777
3778 field_out(:,:,:) = reshape(field_in(:,:,:), (/this%outnx,this%outny,innz/))
3779
3780 ELSE IF (this%trans%sub_type == 'coordbb' .OR. this%trans%sub_type == 'poly' &
3781 .OR. this%trans%sub_type == 'mask' .OR. this%trans%sub_type == 'index') THEN
3782
3783 DO k = 1, innz
3784 IF (.NOT.lzlist(k)) cycle
3785! this is to sparse-points only, so field_out(:,1,k) is acceptable
3786 field_out(:,1,k) = pack(field_in(:,:,k), c_e(this%point_index(:,:)))
3787 ENDDO
3788
3789 ELSE IF (this%trans%sub_type == 'maskvalid' .OR. &
3790 this%trans%sub_type == 'maskinvalid') THEN
3791
3792 DO k = 1, innz
3793 IF (.NOT.lzlist(k)) cycle
3794 WHERE (this%point_mask(:,:)) ! this is almost the same as the previous syntax
3795 field_out(:,:,k) = field_in(:,:,k) ! check which is more efficient
3796 END WHERE
3797 ENDDO
3798
3799 ELSE IF (this%trans%sub_type == 'lemaskinvalid') THEN
3800
3801 DO k = 1, innz
3802 IF (.NOT.lzlist(k)) cycle
3803 WHERE (c_e(field_in(:,:,k)) .AND. field_in(:,:,k) > this%val_mask(:,:))
3804 field_out(:,:,k) = field_in(:,:,k)
3805 ELSEWHERE
3806 field_out(:,:,k) = rmiss
3807 END WHERE
3808 ENDDO
3809
3810 ELSE IF (this%trans%sub_type == 'ltmaskinvalid') THEN
3811
3812 DO k = 1, innz
3813 IF (.NOT.lzlist(k)) cycle
3814 WHERE (c_e(field_in(:,:,k)) .AND. field_in(:,:,k) >= this%val_mask(:,:))
3815 field_out(:,:,k) = field_in(:,:,k)
3816 ELSEWHERE
3817 field_out(:,:,k) = rmiss
3818 END WHERE
3819 ENDDO
3820
3821 ELSE IF (this%trans%sub_type == 'gemaskinvalid') THEN
3822
3823 DO k = 1, innz
3824 IF (.NOT.lzlist(k)) cycle
3825 WHERE (c_e(field_in(:,:,k)) .AND. field_in(:,:,k) < this%val_mask(:,:))
3826 field_out(:,:,k) = field_in(:,:,k)
3827 ELSEWHERE
3828 field_out(:,:,k) = rmiss
3829 END WHERE
3830 ENDDO
3831
3832 ELSE IF (this%trans%sub_type == 'gtmaskinvalid') THEN
3833
3834 DO k = 1, innz
3835 IF (.NOT.lzlist(k)) cycle
3836 WHERE (c_e(field_in(:,:,k)) .AND. field_in(:,:,k) <= this%val_mask(:,:))
3837 field_out(:,:,k) = field_in(:,:,k)
3838 ELSEWHERE
3839 field_out(:,:,k) = rmiss
3840 END WHERE
3841 ENDDO
3842
3843 ELSE IF (this%trans%sub_type == 'setinvalidto') THEN
3844
3845 DO k = 1, innz
3846 IF (.NOT.lzlist(k)) cycle ! should i skip levels here?
3847 WHERE (c_e(field_in(:,:,k)))
3848 field_out(:,:,k) = field_in(:,:,k)
3849 ELSE WHERE
3850 field_out(:,:,k) = this%val1
3851 END WHERE
3852 ENDDO
3853
3854 ELSE IF (this%trans%sub_type == 'settoinvalid') THEN
3855 IF (c_e(this%val1) .AND. c_e(this%val2)) THEN
3856 WHERE (c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1 &
3857 .AND. field_in(:,:,:) <= this%val2)
3858 field_out(:,:,:) = rmiss
3859 ELSE WHERE
3860 field_out(:,:,:) = field_in(:,:,:)
3861 END WHERE
3862 ELSE IF (c_e(this%val1)) THEN
3863 WHERE (c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1)
3864 field_out(:,:,:) = rmiss
3865 ELSE WHERE
3866 field_out(:,:,:) = field_in(:,:,:)
3867 END WHERE
3868 ELSE IF (c_e(this%val2)) THEN
3869 WHERE (c_e(field_in(:,:,:)) .AND. field_in(:,:,:) <= this%val2)
3870 field_out(:,:,:) = rmiss
3871 ELSE WHERE
3872 field_out(:,:,:) = field_in(:,:,:)
3873 END WHERE
3874 ENDIF
3875 ENDIF
3876
3877ELSE IF (this%trans%trans_type == 'vertint') THEN
3878
3879 IF (this%trans%sub_type == 'linear') THEN
3880
3881 alloc_coord_3d_in_act = .false.
3882 IF (ASSOCIATED(this%inter_index_z)) THEN
3883
3884 DO k = 1, outnz
3885 IF (c_e(this%inter_index_z(k))) THEN
3886 z1 = real(this%inter_zp(k)) ! weight for k+1
3887 z2 = real(1.0d0 - this%inter_zp(k)) ! weight for k
3888 SELECT CASE(vartype)
3889
3890 CASE(var_dir360)
3891 DO j = 1, inny
3892 DO i = 1, innx
3893 IF (c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3894 c_e(field_in(i,j,this%inter_index_z(k)+1))) THEN
3895 field_out(i,j,k) = &
3896 interp_var_360(field_in(i,j,this%inter_index_z(k)), &
3897 field_in(i,j,this%inter_index_z(k)+1), z1, z2)
3898 ENDIF
3899 ENDDO
3900 ENDDO
3901
3902 CASE(var_press)
3903 DO j = 1, inny
3904 DO i = 1, innx
3905 IF (c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3906 c_e(field_in(i,j,this%inter_index_z(k)+1)) .AND. &
3907 field_in(i,j,this%inter_index_z(k)) > 0. .AND. &
3908 field_in(i,j,this%inter_index_z(k)+1) > 0.) THEN
3909 field_out(i,j,k) = exp( &
3910 log(field_in(i,j,this%inter_index_z(k)))*z2 + &
3911 log(field_in(i,j,this%inter_index_z(k)+1))*z1)
3912 ENDIF
3913 ENDDO
3914 ENDDO
3915
3916 CASE default
3917 DO j = 1, inny
3918 DO i = 1, innx
3919 IF (c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3920 c_e(field_in(i,j,this%inter_index_z(k)+1))) THEN
3921 field_out(i,j,k) = &
3922 field_in(i,j,this%inter_index_z(k))*z2 + &
3923 field_in(i,j,this%inter_index_z(k)+1)*z1
3924 ENDIF
3925 ENDDO
3926 ENDDO
3927
3928 END SELECT
3929
3930 ENDIF
3931 ENDDO
3932
3933 ELSE ! use coord_3d_in
3934
3935 IF (ALLOCATED(this%coord_3d_in)) THEN
3936 coord_3d_in_act => this%coord_3d_in
3937#ifdef DEBUG
3938 CALL l4f_category_log(this%category,l4f_debug, &
3939 "Using external vertical coordinate for vertint")
3940#endif
3941 ELSE
3942 IF (PRESENT(coord_3d_in)) THEN
3943#ifdef DEBUG
3944 CALL l4f_category_log(this%category,l4f_debug, &
3945 "Using internal vertical coordinate for vertint")
3946#endif
3947 IF (this%dolog) THEN
3948 ALLOCATE(coord_3d_in_act(SIZE(coord_3d_in,1), &
3949 SIZE(coord_3d_in,2), SIZE(coord_3d_in,3)))
3950 alloc_coord_3d_in_act = .true.
3951 WHERE (c_e(coord_3d_in) .AND. coord_3d_in > 0.0)
3952 coord_3d_in_act = log(coord_3d_in)
3953 ELSEWHERE
3954 coord_3d_in_act = rmiss
3955 END WHERE
3956 ELSE
3957 coord_3d_in_act => coord_3d_in
3958 ENDIF
3959 ELSE
3960 CALL l4f_category_log(this%category,l4f_error, &
3961 "Missing internal and external vertical coordinate for vertint")
3962 CALL raise_error()
3963 RETURN
3964 ENDIF
3965 ENDIF
3966
3967 inused = SIZE(coord_3d_in_act,3)
3968 IF (inused < 2) RETURN ! to avoid algorithm failure
3969 kkcache = 1
3970
3971 DO k = 1, outnz
3972 IF (.NOT.c_e(this%vcoord_out(k))) cycle
3973 DO j = 1, inny
3974 DO i = 1, innx
3975 kfound = imiss
3976 DO kk = 1, max(inused-kkcache-1, kkcache) ! +-1
3977 kkup = kkcache + kk
3978 kkdown = kkcache - kk + 1
3979
3980 IF (kkdown >= 1) THEN ! search down
3981 IF (this%vcoord_out(k) >= &
3982 min(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1)) .AND. &
3983 this%vcoord_out(k) < &
3984 max(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1))) THEN
3985 kkcache = kkdown
3986 kfoundin = kkcache
3987 kfound = kkcache + this%levshift
3988 EXIT ! kk
3989 ENDIF
3990 ENDIF
3991 IF (kkup < inused) THEN ! search up
3992 IF (this%vcoord_out(k) >= &
3993 min(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1)) .AND. &
3994 this%vcoord_out(k) < &
3995 max(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1))) THEN
3996 kkcache = kkup
3997 kfoundin = kkcache
3998 kfound = kkcache + this%levshift
3999 EXIT ! kk
4000 ENDIF
4001 ENDIF
4002
4003 ENDDO
4004
4005 IF (c_e(kfound)) THEN
4006 IF (c_e(field_in(i,j,kfound)) .AND. c_e(field_in(i,j,kfound+1))) THEN
4007 z1 = real((this%vcoord_out(k) - coord_3d_in_act(i,j,kfoundin))/ &
4008 (coord_3d_in_act(i,j,kfoundin+1) - coord_3d_in_act(i,j,kfoundin)))
4009 z2 = 1.0 - z1
4010 SELECT CASE(vartype)
4011
4012 CASE(var_dir360)
4013 field_out(i,j,k) = &
4014 interp_var_360(field_in(i,j,kfound), field_in(i,j,kfound+1), z1, z2)
4015 CASE(var_press)
4016 field_out(i,j,k) = exp(log(field_in(i,j,kfound))*z2 + &
4017 log(field_in(i,j,kfound+1))*z1)
4018
4019 CASE default
4020 field_out(i,j,k) = field_in(i,j,kfound)*z2 + field_in(i,j,kfound+1)*z1
4021 END SELECT
4022
4023 ENDIF
4024 ELSE
4025 ENDIF
4026 ENDDO ! i
4027 ENDDO ! j
4028 ENDDO ! k
4029 IF (alloc_coord_3d_in_act) DEALLOCATE(coord_3d_in_act)
4030 ENDIF
4031
4032 ELSE IF (this%trans%sub_type == 'linearsparse') THEN
4033
4034
4035 IF (.NOT.ASSOCIATED(this%vcoord_in) .AND. .NOT.PRESENT(coord_3d_in)) THEN
4036 CALL l4f_category_log(this%category,l4f_error, &
4037 "linearsparse interpolation, no input vert coord available")
4038 RETURN
4039 ENDIF
4040
4041 ALLOCATE(coord_in(innz),val_in(innz),mask_in(innz))
4042 DO j = 1, inny
4043 DO i = 1, innx
4044
4045 IF (ASSOCIATED(this%vcoord_in)) THEN
4046 mask_in = c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4047 .AND. c_e(this%vcoord_in(:))
4048 ELSE
4049 mask_in = c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4050 .AND. c_e(coord_3d_in(i,j,:))
4051 ENDIF
4052
4053 IF (vartype == var_press) THEN
4054 mask_in(:) = mask_in(:) .AND. &
4055 (field_in(i,j,this%levshift+1:this%levshift+this%levused) > 0.0d0)
4056 ENDIF
4057 inused = count(mask_in)
4058 IF (inused > 1) THEN
4059 IF (ASSOCIATED(this%vcoord_in)) THEN
4060 coord_in(1:inused) = pack(this%vcoord_in(:), mask=mask_in)
4061 ELSE
4062 coord_in(1:inused) = pack(coord_3d_in(i,j,:), mask=mask_in)
4063 ENDIF
4064 IF (vartype == var_press) THEN
4065 val_in(1:inused) = log(pack( &
4066 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4067 mask=mask_in))
4068 ELSE
4069 val_in(1:inused) = pack( &
4070 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4071 mask=mask_in)
4072 ENDIF
4073 kkcache = 1
4074 DO k = 1, outnz
4075
4076 kfound = imiss
4077 DO kk = 1, max(inused-kkcache-1, kkcache) ! +-1
4078 kkup = kkcache + kk
4079 kkdown = kkcache - kk + 1
4080
4081 IF (kkdown >= 1) THEN ! search down
4082 IF (this%vcoord_out(k) >= &
4083 min(coord_in(kkdown), coord_in(kkdown+1)) .AND. &
4084 this%vcoord_out(k) < &
4085 max(coord_in(kkdown), coord_in(kkdown+1))) THEN
4086 kkcache = kkdown
4087 kfoundin = kkcache
4088 kfound = kkcache
4089 EXIT ! kk
4090 ENDIF
4091 ENDIF
4092 IF (kkup < inused) THEN ! search up
4093 IF (this%vcoord_out(k) >= &
4094 min(coord_in(kkup), coord_in(kkup+1)) .AND. &
4095 this%vcoord_out(k) < &
4096 max(coord_in(kkup), coord_in(kkup+1))) THEN
4097 kkcache = kkup
4098 kfoundin = kkcache
4099 kfound = kkcache
4100 EXIT ! kk
4101 ENDIF
4102 ENDIF
4103
4104 ENDDO
4105
4106 IF (c_e(kfound)) THEN
4107 z1 = real((this%vcoord_out(k) - coord_in(kfound-1))/ &
4108 (coord_in(kfound) - coord_in(kfound-1)))
4109 z2 = 1.0 - z1
4110 IF (vartype == var_dir360) THEN
4111 field_out(i,j,k) = &
4112 interp_var_360(val_in(kfound-1), val_in(kfound), z1, z2)
4113 ELSE IF (vartype == var_press) THEN
4114 field_out(i,j,k) = exp(val_in(kfound-1)*z2 + val_in(kfound)*z1)
4115 ELSE
4116 field_out(i,j,k) = val_in(kfound-1)*z2 + val_in(kfound)*z1
4117 ENDIF
4118 ENDIF
4119
4120 ENDDO
4121
4122 ENDIF
4123
4124 ENDDO
4125 ENDDO
4126 DEALLOCATE(coord_in,val_in)
4127
4128
4129 ENDIF
4130
4131ELSE IF (this%trans%trans_type == '' .OR. this%trans%trans_type == 'none') THEN
4132
4133 field_out(:,:,:) = field_in(:,:,:)
4134
4135ENDIF
4136
4137
4138CONTAINS
4139
4140
4141! internal function for interpolating directions from 0 to 360 degree
4142! hope it is inlined by the compiler
4143FUNCTION interp_var_360(v1, v2, w1, w2)
4144REAL,INTENT(in) :: v1, v2, w1, w2
4145REAL :: interp_var_360
4146
4147REAL :: lv1, lv2
4148
4149IF (abs(v1 - v2) > 180.) THEN
4150 IF (v1 > v2) THEN
4151 lv1 = v1 - 360.
4152 lv2 = v2
4153 ELSE
4154 lv1 = v1
4155 lv2 = v2 - 360.
4156 ENDIF
4157 interp_var_360 = modulo(lv1*w2 + lv2*w1, 360.)
4158ELSE
4159 interp_var_360 = v1*w2 + v2*w1
4160ENDIF
4161
4162END FUNCTION interp_var_360
4163
4164
4165RECURSIVE FUNCTION find_prevailing_direction(v1, l, h, res, mask) RESULT(prev)
4166REAL,INTENT(in) :: v1(:,:)
4167REAL,INTENT(in) :: l, h, res
4168LOGICAL,INTENT(in),OPTIONAL :: mask(:,:)
4169REAL :: prev
4170
4171REAL :: m
4172INTEGER :: nh, nl
4173!REAL,PARAMETER :: res = 1.0
4174
4175m = (l + h)/2.
4176IF ((h - l) <= res) THEN
4177 prev = m
4178 RETURN
4179ENDIF
4180
4181IF (PRESENT(mask)) THEN
4182 nl = count(v1 >= l .AND. v1 < m .AND. mask)
4183 nh = count(v1 >= m .AND. v1 < h .AND. mask)
4184ELSE
4185 nl = count(v1 >= l .AND. v1 < m)
4186 nh = count(v1 >= m .AND. v1 < h)
4187ENDIF
4188IF (nh > nl) THEN
4189 prev = find_prevailing_direction(v1, m, h, res)
4190ELSE IF (nl > nh) THEN
4191 prev = find_prevailing_direction(v1, l, m, res)
4192ELSE IF (nl == 0 .AND. nh == 0) THEN
4193 prev = rmiss
4194ELSE
4195 prev = m
4196ENDIF
4197
4198END FUNCTION find_prevailing_direction
4199
4200
4201END SUBROUTINE grid_transform_compute
4202
4203
4204!> Compute the output data array from input data array according to
4205!! the defined transformation. The \a grid_transform object \a this
4206!! must have been properly initialised, so that it contains all the
4207!! information needed for computing the transformation. This is the
4208!! sparse points-to-grid and sparse points-to-sparse points version.
4209SUBROUTINE grid_transform_v7d_grid_compute(this, field_in, field_out, var, &
4210 coord_3d_in)
4211TYPE(grid_transform),INTENT(in) :: this !< grid_tranform object
4212REAL, INTENT(in) :: field_in(:,:) !< input array
4213REAL, INTENT(out):: field_out(:,:,:) !< output array
4214TYPE(vol7d_var),INTENT(in),OPTIONAL :: var !< physical variable to be interpolated, if provided, some ad-hoc algorithms may be used where possible
4215REAL,INTENT(in),OPTIONAL,TARGET :: coord_3d_in(:,:,:) !< input vertical coordinate for vertical interpolation, if not provided by other means
4216
4217real,allocatable :: field_in_p(:),x_in_p(:),y_in_p(:)
4218INTEGER :: inn_p, ier, k
4219INTEGER :: innx, inny, innz, outnx, outny, outnz
4220
4221#ifdef DEBUG
4222call l4f_category_log(this%category,L4F_DEBUG,"start v7d_grid_transform_compute")
4223#endif
4224
4225field_out(:,:,:) = rmiss
4226
4227IF (.NOT.this%valid) THEN
4228 call l4f_category_log(this%category,l4f_error, &
4229 "refusing to perform a non valid transformation")
4230 call raise_error()
4231 RETURN
4232ENDIF
4233
4234innx = SIZE(field_in,1); inny = 1; innz = SIZE(field_in,2)
4235outnx = SIZE(field_out,1); outny = SIZE(field_out,2); outnz = SIZE(field_out,3)
4236
4237! check size of field_in, field_out
4238IF (this%trans%trans_type == 'vertint') THEN ! vertical interpolation
4239
4240 IF (innz /= this%innz) THEN
4241 CALL l4f_category_log(this%category,l4f_error,"vertical interpolation")
4242 CALL l4f_category_log(this%category,l4f_error,"inconsistent input shape: "//&
4243 t2c(this%innz)//" /= "//t2c(innz))
4244 CALL raise_error()
4245 RETURN
4246 ENDIF
4247
4248 IF (outnz /= this%outnz) THEN
4249 CALL l4f_category_log(this%category,l4f_error,"vertical interpolation")
4250 CALL l4f_category_log(this%category,l4f_error,"inconsistent output shape: "//&
4251 t2c(this%outnz)//" /= "//t2c(outnz))
4252 CALL raise_error()
4253 RETURN
4254 ENDIF
4255
4256 IF (innx /= outnx .OR. inny /= outny) THEN
4257 CALL l4f_category_log(this%category,l4f_error,"vertical interpolation")
4258 CALL l4f_category_log(this%category,l4f_error,"inconsistent hor. sizes: "//&
4259 t2c(innx)//","//t2c(inny)//" /= "//&
4260 t2c(outnx)//","//t2c(outny))
4261 CALL raise_error()
4262 RETURN
4263 ENDIF
4264
4265ELSE ! horizontal interpolation
4266
4267 IF (innx /= this%innx .OR. inny /= this%inny) THEN
4268 CALL l4f_category_log(this%category,l4f_error,"horizontal interpolation")
4269 CALL l4f_category_log(this%category,l4f_error,"inconsistent input shape: "//&
4270 t2c(this%innx)//","//t2c(this%inny)//" /= "//&
4271 t2c(innx)//","//t2c(inny))
4272 CALL raise_error()
4273 RETURN
4274 ENDIF
4275
4276 IF (outnx /= this%outnx .OR. outny /= this%outny) THEN
4277 CALL l4f_category_log(this%category,l4f_error,"horizontal interpolation")
4278 CALL l4f_category_log(this%category,l4f_error,"inconsistent output shape: "//&
4279 t2c(this%outnx)//","//t2c(this%outny)//" /= "//&
4280 t2c(outnx)//","//t2c(outny))
4281 CALL raise_error()
4282 RETURN
4283 ENDIF
4284
4285 IF (innz /= outnz) THEN
4286 CALL l4f_category_log(this%category,l4f_error,"horizontal interpolation")
4287 CALL l4f_category_log(this%category,l4f_error,"inconsistent vert. sizes: "//&
4288 t2c(innz)//" /= "//t2c(outnz))
4289 CALL raise_error()
4290 RETURN
4291 ENDIF
4292
4293ENDIF
4294
4295#ifdef DEBUG
4296 call l4f_category_log(this%category,l4f_debug, &
4297 "start grid_transform_v7d_grid_compute "//trim(this%trans%trans_type)//':'// &
4298 trim(this%trans%sub_type))
4299#endif
4300
4301IF (this%trans%trans_type == 'inter') THEN
4302
4303 IF (this%trans%sub_type == 'linear') THEN
4304
4305#ifdef HAVE_LIBNGMATH
4306! optimization, allocate only once with a safe size
4307 ALLOCATE(field_in_p(innx*inny), x_in_p(innx*inny), y_in_p(innx*inny))
4308 DO k = 1, innz
4309 inn_p = count(c_e(field_in(:,k)))
4310
4311 CALL l4f_category_log(this%category,l4f_info, &
4312 "Number of sparse data points: "//t2c(inn_p)//','//t2c(SIZE(field_in(:,k))))
4313
4314 IF (inn_p > 2) THEN
4315
4316 field_in_p(1:inn_p) = pack(field_in(:,k), c_e(field_in(:,k)))
4317 x_in_p(1:inn_p) = pack(this%inter_xp(:,1), c_e(field_in(:,k)))
4318 y_in_p(1:inn_p) = pack(this%inter_yp(:,1), c_e(field_in(:,k)))
4319
4320 IF (.NOT.this%trans%extrap) THEN
4321 CALL nnseti('ext', 0) ! 0 = no extrapolation
4322 CALL nnsetr('nul', rmiss)
4323 ENDIF
4324
4325 CALL natgrids(inn_p, x_in_p, y_in_p, field_in_p, & ! (1:inn_p) omitted
4326 this%outnx, this%outny, real(this%inter_x(:,1)), & ! no f90 interface
4327 REAL(this%inter_y(1,:)), field_out(1,1,k), ier)
4328
4329 IF (ier /= 0) THEN
4330 CALL l4f_category_log(this%category,l4f_error, &
4331 "Error code from NCAR natgrids: "//t2c(ier))
4332 CALL raise_error()
4333 EXIT
4334 ENDIF ! exit loop to deallocate
4335 ELSE
4336
4337 CALL l4f_category_log(this%category,l4f_info, &
4338 "insufficient data in gridded region to triangulate")
4339
4340 ENDIF
4341 ENDDO
4342 DEALLOCATE(field_in_p, x_in_p, y_in_p)
4343
4344#else
4345 CALL l4f_category_log(this%category,l4f_error, &
4346 "libsim compiled without natgridd(ngmath ncarg library)")
4347 CALL raise_error()
4348 RETURN
4349#endif
4350
4351 ENDIF
4352
4353.OR.ELSE IF (this%trans%trans_type == 'boxinter' &
4354.OR. this%trans%trans_type == 'polyinter' &
4355.OR. this%trans%trans_type == 'vertint' &
4356 this%trans%trans_type == 'metamorphosis') THEN ! use the grid-to-grid method
4357
4358 CALL compute(this, &
4359 RESHAPE(field_in, (/SIZE(field_in,1), 1, SIZE(field_in,2)/)), field_out, var, &
4360 coord_3d_in)
4361
4362ENDIF
4363
4364END SUBROUTINE grid_transform_v7d_grid_compute
4365
4366
4367! Bilinear interpolation
4368! Effettua interpolazione bilineare dati i valori nei punti 1,2,3,4 e
4369! le coordinate dei punti 1 e 3 oltre a quelle del punto p dove viene
4370! valutato il campo.
4371!_____________________________________________________________
4372! disposizione punti
4373! 4 3
4374!
4375! p
4376!
4377! 1 2
4378! _____________________________________________________________
4379ELEMENTAL FUNCTION hbilin (z1,z2,z3,z4,x1,y1,x3,y3,xp,yp) RESULT(zp)
4380REAL,INTENT(in) :: z1,z2,z3,z4 ! Z values on the four points
4381DOUBLE PRECISION,INTENT(in):: x1,y1 ! coordinate of the lower left point
|