libsim Versione 8.0.0

◆ grid_transform_compute()

recursive subroutine grid_transform_compute ( type(grid_transform), intent(in), target this,
real, dimension(:,:,:), intent(in) field_in,
real, dimension(:,:,:), intent(out) field_out,
type(vol7d_var), intent(in), optional var,
real, dimension(:,:,:), intent(in), optional, target coord_3d_in,
logical, dimension(:), intent(in), optional zlist )

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.

Parametri
[in]thisgrid_transformation object
[in]field_ininput array
[out]field_outoutput array
[in]varphysical variable to be interpolated, if provided, some ad-hoc algorithms may be used where possible
[in]coord_3d_ininput vertical coordinate for vertical interpolation, if not provided by other means
[in]zlistlist of levels actually present in input volume, if provided, levels marked as .FALSE. will not be interpolated regardless of their content (optimisation to avoid interpolating missing data)

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

Generated with Doxygen.