libsim  Versione8.0.0

◆ grid_transform_compute()

recursive subroutine grid_transform_class::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 
)
private

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 3157 del file grid_transform_class.F90.

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 
3269 ELSE 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
3354 ELSE 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 
3436 ELSE 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 
3586 ELSE 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 
3766 ELSE 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 
3774 ELSE 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 
3877 ELSE 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 
4131 ELSE IF (this%trans%trans_type == '' .OR. this%trans%trans_type == 'none') THEN
4132 
4133  field_out(:,:,:) = field_in(:,:,:)
4134 
4135 ENDIF
4136 
4137 
4138 CONTAINS
4139 
4140 
4141 ! internal function for interpolating directions from 0 to 360 degree
4142 ! hope it is inlined by the compiler
4143 FUNCTION interp_var_360(v1, v2, w1, w2)
4144 REAL,INTENT(in) :: v1, v2, w1, w2
4145 REAL :: interp_var_360
4146 
4147 REAL :: lv1, lv2
4148 
4149 IF (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.)
4158 ELSE
4159  interp_var_360 = v1*w2 + v2*w1
4160 ENDIF
4161 
4162 END FUNCTION interp_var_360
4163 
4164 
4165 RECURSIVE FUNCTION find_prevailing_direction(v1, l, h, res, mask) RESULT(prev)
4166 REAL,INTENT(in) :: v1(:,:)
4167 REAL,INTENT(in) :: l, h, res
4168 LOGICAL,INTENT(in),OPTIONAL :: mask(:,:)
4169 REAL :: prev
4170 
4171 REAL :: m
4172 INTEGER :: nh, nl
4173 !REAL,PARAMETER :: res = 1.0
4174 
4175 m = (l + h)/2.
4176 IF ((h - l) <= res) THEN
4177  prev = m
4178  RETURN
4179 ENDIF
4180 
4181 IF (PRESENT(mask)) THEN
4182  nl = count(v1 >= l .AND. v1 < m .AND. mask)
4183  nh = count(v1 >= m .AND. v1 < h .AND. mask)
4184 ELSE
4185  nl = count(v1 >= l .AND. v1 < m)
4186  nh = count(v1 >= m .AND. v1 < h)
4187 ENDIF
4188 IF (nh > nl) THEN
4189  prev = find_prevailing_direction(v1, m, h, res)
4190 ELSE IF (nl > nh) THEN
4191  prev = find_prevailing_direction(v1, l, m, res)
4192 ELSE IF (nl == 0 .AND. nh == 0) THEN
4193  prev = rmiss
4194 ELSE
4195  prev = m
4196 ENDIF
4197 
4198 END FUNCTION find_prevailing_direction
4199 
4200 
4201 END SUBROUTINE grid_transform_compute
4202 
4203 
4209 SUBROUTINE grid_transform_v7d_grid_compute(this, field_in, field_out, var, &
4210  coord_3d_in)
4211 TYPE(grid_transform),INTENT(in) :: this
4212 REAL, INTENT(in) :: field_in(:,:)
4213 REAL, INTENT(out):: field_out(:,:,:)
4214 TYPE(vol7d_var),INTENT(in),OPTIONAL :: var
4215 REAL,INTENT(in),OPTIONAL,TARGET :: coord_3d_in(:,:,:)
4216 
4217 real,allocatable :: field_in_p(:),x_in_p(:),y_in_p(:)
4218 INTEGER :: inn_p, ier, k
4219 INTEGER :: innx, inny, innz, outnx, outny, outnz
4220 
4221 #ifdef DEBUG
4222 call l4f_category_log(this%category,l4f_debug,"start v7d_grid_transform_compute")
4223 #endif
4224 
4225 field_out(:,:,:) = rmiss
4226 
4227 IF (.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
4232 ENDIF
4233 
4234 innx = SIZE(field_in,1); inny = 1; innz = SIZE(field_in,2)
4235 outnx = SIZE(field_out,1); outny = SIZE(field_out,2); outnz = SIZE(field_out,3)
4236 
4237 ! check size of field_in, field_out
4238 IF (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 
4265 ELSE ! 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 
4293 ENDIF
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 
4301 IF (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 ELSE IF (this%trans%trans_type == 'boxinter' .OR. &
4354  this%trans%trans_type == 'polyinter' .OR. &
4355  this%trans%trans_type == 'vertint' .OR. &
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 
4362 ENDIF
4363 
4364 END 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 ! _____________________________________________________________
4379 ELEMENTAL FUNCTION hbilin (z1,z2,z3,z4,x1,y1,x3,y3,xp,yp) RESULT(zp)
4380 REAL,INTENT(in) :: z1,z2,z3,z4 ! Z values on the four points
4381 DOUBLE PRECISION,INTENT(in):: x1,y1 ! coordinate of the lower left point
4382 DOUBLE PRECISION,INTENT(in):: x3,y3 ! coordinate of the upper right point
4383 DOUBLE PRECISION,INTENT(in):: xp,yp ! coordinate of point where interpolate
4384 REAL :: zp
4385 
4386 REAL :: p1,p2
4387 REAL :: z5,z6
4388 
4389 
4390 p2 = REAL((yp-y1)/(y3-y1))
4391 p1 = REAL((xp-x1)/(x3-x1))

Generated with Doxygen.