00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 subroutine prismtrs_bilinear_weight_2d(id_src_size, &
00011 dda_src_lat, &
00012 dda_src_lon, &
00013 id_tgt_size, &
00014 dda_tgt_lat, &
00015 dda_tgt_lon, &
00016 ida_tgt_mask, &
00017 ida_neighbor_index, &
00018 dda_weights, &
00019 id_err)
00020
00021
00022
00023
00024 USE PRISMDrv, dummy_INTERFACE => PRISMTrs_Bilinear_weight_2d
00025
00026 IMPLICIT NONE
00027
00028
00029
00030
00031
00032 INTEGER, INTENT (IN) :: id_src_size
00033 INTEGER, INTENT (IN) :: id_tgt_size
00034
00035
00036 DOUBLE PRECISION, DIMENSION(id_src_size) :: dda_src_lat
00037 DOUBLE PRECISION, DIMENSION(id_src_size) :: dda_src_lon
00038
00039
00040 DOUBLE PRECISION, DIMENSION(id_tgt_size) :: dda_tgt_lat
00041 DOUBLE PRECISION, DIMENSION(id_tgt_size) :: dda_tgt_lon
00042
00043 INTEGER, DIMENSION(id_tgt_size), INTENT (IN) :: ida_tgt_mask
00044
00045
00046 INTEGER, DIMENSION(id_tgt_size,4), INTENT (IN) :: ida_neighbor_index
00047
00048
00049
00050
00051
00052 DOUBLE PRECISION, DIMENSION(id_tgt_size,4), INTENT (Out) :: dda_weights
00053
00054 INTEGER, INTENT (Out) :: id_err
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 CHARACTER(LEN=len_cvs_string), SAVE :: mycvs =
00077 '$Id: prismtrs_bilinear_weight_2d.F90 3241 2011-06-23 09:55:11Z coquart $'
00078
00079
00080 INTEGER :: ib, ib_bis, iter
00081 DOUBLE PRECISION, PARAMETER :: converge = 1.0D-2
00082 DOUBLE PRECISION, PARAMETER :: tolerance = 1.0D-12
00083
00084
00085 DOUBLE PRECISION, DIMENSION(4) :: src_lats
00086 DOUBLE PRECISION, DIMENSION(4) :: src_lons
00087 DOUBLE PRECISION, DIMENSION(4) :: vec_lon
00088 DOUBLE PRECISION :: common_grid_range(2)
00089 DOUBLE PRECISION :: shiftSize
00090
00091
00092 #ifndef SX
00093 DOUBLE PRECISION :: plat, plon
00094 #else
00095 DOUBLE PRECISION, DIMENSION(id_tgt_size) :: plat, plon
00096 #endif
00097
00098 DOUBLE PRECISION :: iguess, jguess
00099
00100 DOUBLE PRECISION :: deli, delj
00101
00102 DOUBLE PRECISION :: dth1, dth2, dth3
00103
00104 DOUBLE PRECISION :: dph1, dph2, dph3
00105
00106 DOUBLE PRECISION :: dthp, dphp
00107
00108 DOUBLE PRECISION :: mat1, mat2, mat3, mat4
00109
00110 DOUBLE PRECISION :: determinant
00111
00112
00113 DOUBLE PRECISION :: dist2v(4)
00114 DOUBLE PRECISION :: rdistance, arg
00115
00116 INTEGER :: nb
00117 INTEGER :: srch_add
00118 #ifndef SX
00119 LOGICAL :: nearest_neighbor
00120 #else
00121 INTEGER :: ib_part
00122 LOGICAL, DIMENSION(id_tgt_size) :: nearest_neighbor
00123 #endif
00124
00125 #ifdef DEBUGX
00126 DOUBLE PRECISION :: dbl_rad2deg
00127 #endif
00128
00129
00130
00131 #ifdef VERBOSE
00132 PRINT *, '| | | | | | | Enter PRISMTrs_Bilinear_weight_2d'
00133 PRINT*, 'Size of target epio :',id_tgt_size
00134 call psmile_flushstd
00135 #endif
00136 id_err = 0
00137 dda_weights = 0.0
00138 common_grid_range(1) = 0.
00139 common_grid_range(2) = dble_pi2
00140 shiftSize = common_grid_range(2) - common_grid_range(1)
00141
00142
00143
00144
00145
00146 DO ib = 1, id_src_size
00147 DO WHILE (dda_src_lon(ib) < common_grid_range(1))
00148 dda_src_lon(ib) = dda_src_lon(ib) + shiftSize
00149 ENDDO
00150 DO WHILE (dda_src_lon(ib) >= common_grid_range(2))
00151 dda_src_lon(ib) = dda_src_lon(ib) - shiftSize
00152 ENDDO
00153 ENDDO
00154 DO ib = 1, id_tgt_size
00155 DO WHILE (dda_tgt_lon(ib) < common_grid_range(1))
00156 dda_tgt_lon(ib) = dda_tgt_lon(ib) + shiftSize
00157 ENDDO
00158 DO WHILE (dda_tgt_lon(ib) >= common_grid_range(2))
00159 dda_tgt_lon(ib) = dda_tgt_lon(ib) - shiftSize
00160 ENDDO
00161 ENDDO
00162
00163
00164
00165
00166 DO ib = 1, id_src_size
00167 IF ( (dda_src_lat(ib) > dble_pih) .OR. (dda_src_lat(ib) < -dble_pih)) THEN
00168 WRITE(*,*) 'Problem :Latitudes of source are greater than +/-90 degrees'
00169 CALL psmile_abort
00170 ENDIF
00171 ENDDO
00172 DO ib = 1, id_tgt_size
00173 IF ( (dda_tgt_lat(ib) > dble_pih) .OR. (dda_tgt_lat(ib) < -dble_pih) ) THEN
00174 WRITE(*,*) 'Problem :Latitudes of target are greater than +/-90 degrees'
00175 CALL psmile_abort
00176 ENDIF
00177 ENDDO
00178
00179 nearest_neighbor = .false.
00180
00181 #ifndef SX
00182
00183
00184
00185 DO ib = 1, id_tgt_size
00186
00187
00188 plat = dda_tgt_lat(ib)
00189 plon = dda_tgt_lon(ib)
00190
00191 IF ( ida_neighbor_index(ib, 1) > 0 ) THEN
00192
00193 iter = 0
00194
00195
00196
00197 IF ( ida_neighbor_index(ib, 4) <= 0 ) nearest_neighbor = .true.
00198
00199 IF ( .not. nearest_neighbor ) THEN
00200
00201
00202
00203 DO ib_bis = 1, 4
00204 src_lats (ib_bis) = dda_src_lat (ida_neighbor_index(ib, ib_bis))
00205 src_lons (ib_bis) = dda_src_lon (ida_neighbor_index(ib, ib_bis))
00206 END DO
00207
00208 DO ib_bis = 1, 4
00209 vec_lon(ib_bis) = src_lons (ib_bis) - plon
00210 IF (vec_lon(ib_bis) > dble_pi) THEN
00211 src_lons (ib_bis)= src_lons (ib_bis) - dble_pi2
00212 ELSE IF (vec_lon(ib_bis) < -dble_pi) THEN
00213 src_lons (ib_bis) = src_lons (ib_bis) + dble_pi2
00214 ENDIF
00215 ENDDO
00216
00217 #ifdef DEBUGX
00218 dbl_rad2deg = 360.0/dble_pi2
00219 IF ( (ib == 4388) .OR. (ib == 4389) ) THEN
00220 PRINT*
00221 PRINT*, '+++++++++++++++++++++++++++++++'
00222 PRINT*, 'EPIOT number :',ib
00223 PRINT*, '+++++++++++++++++++++++++++++++'
00224 PRINT*
00225 PRINT*, 'lat and lon of TARGET point :',dbl_rad2deg*dda_tgt_lat(ib),dbl_rad2deg*dda_tgt_lon(ib)
00226 DO ib_bis=1,4
00227 PRINT*, 'EPIOS number, lat and lon of neighbours:',ida_neighbor_index(ib, ib_bis),&
00228 dbl_rad2deg*dda_src_lat (ida_neighbor_index(ib, ib_bis)), &
00229 dbl_rad2deg*dda_src_lon (ida_neighbor_index(ib, ib_bis))
00230 ENDDO
00231 PRINT*
00232 ENDIF
00233 #endif
00234
00235
00236
00237 dth1 = src_lats(2) - src_lats(1)
00238 dth2 = src_lats(4) - src_lats(1)
00239 dth3 = src_lats(3) - src_lats(2) - dth2
00240
00241 dph1 = src_lons(2) - src_lons(1)
00242 dph2 = src_lons(4) - src_lons(1)
00243 dph3 = src_lons(3) - src_lons(2)
00244
00245 IF (dph1 > three*dble_pih) dph1 = dph1 - dble_pi2
00246 IF (dph2 > three*dble_pih) dph2 = dph2 - dble_pi2
00247 IF (dph3 > three*dble_pih) dph3 = dph3 - dble_pi2
00248 IF (dph1 < -three*dble_pih) dph1 = dph1 + dble_pi2
00249 IF (dph2 < -three*dble_pih) dph2 = dph2 + dble_pi2
00250 IF (dph3 < -three*dble_pih) dph3 = dph3 + dble_pi2
00251
00252 dph3 = dph3 - dph2
00253
00254 iguess = half
00255 jguess = half
00256
00257
00258
00259 DO iter= 1, PSMILe_trans_Max_iter
00260
00261 dthp = plat - src_lats(1) &
00262 - dth1*iguess &
00263 - dth2*jguess &
00264 - dth3*iguess*jguess
00265
00266 dphp = plon - src_lons(1)
00267
00268 IF (dphp > three*dble_pih) dphp = dphp - dble_pi2
00269 IF (dphp < -three*dble_pih) dphp = dphp + dble_pi2
00270
00271 dphp = dphp - dph1*iguess &
00272 - dph2*jguess &
00273 - dph3*iguess*jguess
00274
00275 mat1 = dth1 + dth3*jguess
00276 mat2 = dth2 + dth3*iguess
00277 mat3 = dph1 + dph3*jguess
00278 mat4 = dph2 + dph3*iguess
00279
00280 determinant = mat1*mat4 - mat2*mat3
00281
00282 IF ( determinant == 0.0 ) EXIT
00283
00284 deli = (dthp*mat4 - mat2*dphp)/determinant
00285 delj = (mat1*dphp - dthp*mat3)/determinant
00286
00287 IF ( ABS(deli) < converge .AND. &
00288 ABS(delj) < converge) EXIT
00289
00290 iguess = iguess + deli
00291 jguess = jguess + delj
00292
00293 END DO
00294
00295 IF (iter <= PSMILe_trans_Max_iter) THEN
00296
00297
00298
00299
00300
00301 dda_weights(ib,1) = ABS((one-iguess)*(one-jguess))
00302 dda_weights(ib,2) = ABS(iguess*(one-jguess))
00303 dda_weights(ib,3) = ABS(iguess*jguess)
00304 dda_weights(ib,4) = ABS((one-iguess)*jguess)
00305
00306 IF ( ABS(SUM(dda_weights(ib,1:4))-1.0D0) > tolerance ) THEN
00307
00308
00309 #ifdef VERBOSE
00310 PRINT *, '| | | | | | | | We switch to nearest neighbor.',ABS(SUM(dda_weights(ib,1:4)))
00311 #endif
00312 dda_weights(ib,:) = 0.0
00313 nearest_neighbor = .true.
00314 ENDIF
00315
00316 ELSE
00317
00318 #ifdef VERBOSE
00319 PRINT *, '| | | | | | | | Point coords : ',plat,plon
00320 PRINT *, '| | | | | | | | Dest grid lats: ',src_lats
00321 PRINT *, '| | | | | | | | Dest grid lons: ',src_lons
00322 PRINT *, '| | | | | | | | Current i,j : ',iguess, jguess
00323 PRINT *, '| | | | | | | | | Iteration for i,j exceed max iteration count'
00324 PRINT *, '| | | | | | | | | We switch to nearest neighbor.'
00325 #endif
00326 nearest_neighbor = .true.
00327
00328 ENDIF
00329
00330 ENDIF
00331
00332
00333
00334
00335
00336 IF ( nearest_neighbor ) THEN
00337
00338 dist2v = 0.0d0
00339
00340 DO ib_bis = 1, 4
00341 IF ( ida_neighbor_index(ib,ib_bis) <= 0 ) EXIT
00342 ENDDO
00343
00344 nb = ib_bis - 1
00345
00346 DO ib_bis = 1, nb
00347
00348 srch_add = ida_neighbor_index(ib, ib_bis)
00349
00350 arg = SIN(plat)*SIN(dda_src_lat(srch_add)) + &
00351 COS(plat)*COS(dda_src_lat(srch_add)) * &
00352 (COS(plon)*COS(dda_src_lon(srch_add)) + &
00353 SIN(plon)*SIN(dda_src_lon(srch_add)))
00354
00355 IF (arg < -1.0d0) THEN
00356 arg = -1.0d0
00357 ELSE IF (arg > 1.0d0) THEN
00358 arg = 1.0d0
00359 END IF
00360
00361 dist2v(ib_bis) = ACOS(arg)
00362 dist2v(ib_bis) = dist2v(ib_bis)*dist2v(ib_bis)
00363
00364 END DO
00365
00366 DO ib_bis = 1, nb
00367 IF (dist2v(ib_bis) == 0.0d0 ) EXIT
00368 END DO
00369
00370 IF (ib_bis <= nb) THEN
00371
00372 dda_weights(ib,ib_bis) = 1.0d0
00373
00374 ELSE IF ( nb == 1 ) THEN
00375 dda_weights(ib,nb) = 1.0d0
00376
00377 ELSE IF ( nb > 1 ) THEN
00378 dda_weights(ib,1:nb) = 1.0d0 / dist2v(1:nb)
00379 rdistance = 1.0d0 / SUM (dda_weights(ib,1:nb))
00380 dda_weights(ib,1:nb) = dda_weights(ib,1:nb) * rdistance
00381 ENDIF
00382
00383 END IF
00384
00385 nearest_neighbor = .false.
00386
00387 END IF
00388
00389 #ifdef DEBUGX
00390 IF ( (ib == 4388) .OR. (ib == 4389) ) THEN
00391 PRINT*
00392 PRINT*, 'EPIOT number, EPIOS numbers of neighbours:',ib,ida_neighbor_index(ib,:)
00393 PRINT*, 'dda_weights(ib,:) :',dda_weights(ib,:)
00394 PRINT*
00395 ENDIF
00396 #endif
00397
00398 END DO
00399
00400 #else
00401
00402
00403
00404
00405
00406
00407 plat = dda_tgt_lat
00408 plon = dda_tgt_lon
00409
00410
00411
00412 DO ib = 1, id_tgt_size
00413 if ( ida_neighbor_index(ib, 4) <= 0 .AND. &
00414 ida_neighbor_index(ib, 1) > 0 .AND. &
00415 ida_tgt_mask(ib) == 1 ) nearest_neighbor(ib) = .TRUE.
00416 END DO
00417
00418 DO ib_part = 1, id_tgt_size, 5000
00419 DO ib = ib_part, min(id_tgt_size,ib_part+5000-1)
00420
00421
00422
00423 IF ( .not. nearest_neighbor(ib) .AND. &
00424 ida_tgt_mask(ib) == 1 .AND. &
00425 ida_neighbor_index(ib, 1) > 0 ) THEN
00426
00427
00428
00429 DO ib_bis = 1, 4
00430 src_lats (ib_bis) = dda_src_lat (ida_neighbor_index(ib, ib_bis))
00431 src_lons (ib_bis) = dda_src_lon (ida_neighbor_index(ib, ib_bis))
00432 END DO
00433
00434 DO ib_bis = 1, 4
00435 vec_lon(ib_bis) = src_lons (ib_bis) - plon(ib)
00436 IF (vec_lon(ib_bis) > dble_pi) THEN
00437 src_lons (ib_bis)= src_lons (ib_bis) - dble_pi2
00438 ELSE IF (vec_lon(ib_bis) < -dble_pi) THEN
00439 src_lons (ib_bis) = src_lons (ib_bis) + dble_pi2
00440 ENDIF
00441 ENDDO
00442
00443
00444
00445 dth1 = src_lats(2) - src_lats(1)
00446 dth2 = src_lats(4) - src_lats(1)
00447 dth3 = src_lats(3) - src_lats(2) - dth2
00448
00449 dph1 = src_lons(2) - src_lons(1)
00450 dph2 = src_lons(4) - src_lons(1)
00451 dph3 = src_lons(3) - src_lons(2)
00452
00453 IF (dph1 > three*dble_pih) dph1 = dph1 - dble_pi2
00454 IF (dph2 > three*dble_pih) dph2 = dph2 - dble_pi2
00455 IF (dph3 > three*dble_pih) dph3 = dph3 - dble_pi2
00456 IF (dph1 < -three*dble_pih) dph1 = dph1 + dble_pi2
00457 IF (dph2 < -three*dble_pih) dph2 = dph2 + dble_pi2
00458 IF (dph3 < -three*dble_pih) dph3 = dph3 + dble_pi2
00459
00460 dph3 = dph3 - dph2
00461
00462 iguess = half
00463 jguess = half
00464
00465
00466
00467 DO iter= 1, PSMILe_trans_Max_iter
00468
00469 dthp = plat(ib) - src_lats(1) &
00470 - dth1*iguess &
00471 - dth2*jguess &
00472 - dth3*iguess*jguess
00473
00474 dphp = plon(ib) - src_lons(1)
00475
00476 IF (dphp > three*dble_pih) dphp = dphp - dble_pi2
00477 IF (dphp < -three*dble_pih) dphp = dphp + dble_pi2
00478
00479 dphp = dphp - dph1*iguess &
00480 - dph2*jguess &
00481 - dph3*iguess*jguess
00482
00483 mat1 = dth1 + dth3*jguess
00484 mat2 = dth2 + dth3*iguess
00485 mat3 = dph1 + dph3*jguess
00486 mat4 = dph2 + dph3*iguess
00487
00488 determinant = mat1*mat4 - mat2*mat3
00489
00490 IF ( determinant == 0.0 ) EXIT
00491
00492 deli = (dthp*mat4 - mat2*dphp)/determinant
00493 delj = (mat1*dphp - dthp*mat3)/determinant
00494
00495 IF ( ABS(deli) < converge .AND. &
00496 ABS(delj) < converge) EXIT
00497
00498 iguess = iguess + deli
00499 jguess = jguess + delj
00500
00501 END DO
00502
00503 IF (iter <= PSMILe_trans_Max_iter) THEN
00504
00505
00506
00507
00508
00509 dda_weights(ib,1) = ABS((one-iguess)*(one-jguess))
00510 dda_weights(ib,2) = ABS(iguess*(one-jguess))
00511 dda_weights(ib,3) = ABS(iguess*jguess)
00512 dda_weights(ib,4) = ABS((one-iguess)*jguess)
00513
00514 IF ( ABS(SUM(dda_weights(ib,1:4))-1.0D0) > tolerance ) THEN
00515
00516
00517 #ifdef VERBOSE
00518 PRINT *, '| | | | | | | | We switch to nearest neighbor.',ABS(SUM(dda_weights(ib,1:4)))
00519 #endif
00520 dda_weights(ib,:) = 0.0
00521 nearest_neighbor(ib) = .true.
00522 ENDIF
00523
00524 ELSE
00525
00526 #ifdef VERBOSE
00527 PRINT *, '| | | | | | | | Point coords : ',plat(ib),plon(ib)
00528 PRINT *, '| | | | | | | | Dest grid lats: ',src_lats
00529 PRINT *, '| | | | | | | | Dest grid lons: ',src_lons
00530 PRINT *, '| | | | | | | | Current i,j : ',iguess, jguess
00531 PRINT *, '| | | | | | | | | Iteration for i,j exceed max iteration count'
00532 PRINT *, '| | | | | | | | | We switch to nearest neighbor.'
00533 #endif
00534 nearest_neighbor(ib) = .true.
00535
00536 ENDIF
00537
00538 ENDIF
00539
00540 END DO
00541 END DO
00542
00543
00544
00545
00546
00547 DO ib = 1, id_tgt_size
00548
00549 IF ( nearest_neighbor(ib) ) THEN
00550
00551 dist2v = 0.0d0
00552
00553 DO ib_bis = 1, 4
00554 IF ( ida_neighbor_index(ib,ib_bis) <= 0 ) EXIT
00555 ENDDO
00556
00557 nb = ib_bis - 1
00558
00559 DO ib_bis = 1, nb
00560
00561 srch_add = ida_neighbor_index(ib, ib_bis)
00562
00563 arg = SIN(plat(ib))*SIN(dda_src_lat(srch_add)) + &
00564 COS(plat(ib))*COS(dda_src_lat(srch_add)) * &
00565 (COS(plon(ib))*COS(dda_src_lon(srch_add)) + &
00566 SIN(plon(ib))*SIN(dda_src_lon(srch_add)))
00567
00568 IF (arg < -1.0d0) THEN
00569 arg = -1.0d0
00570 ELSE IF (arg > 1.0d0) THEN
00571 arg = 1.0d0
00572 END IF
00573
00574 dist2v(ib_bis) = ACOS(arg)
00575 dist2v(ib_bis) = dist2v(ib_bis)*dist2v(ib_bis)
00576
00577 END DO
00578
00579 DO ib_bis = 1, nb
00580 IF (dist2v(ib_bis) == 0.0d0 ) EXIT
00581 END DO
00582
00583 IF (ib_bis <= nb) THEN
00584
00585 dda_weights(ib,ib_bis) = 1.0d0
00586
00587 ELSE IF ( nb == 1 ) THEN
00588 dda_weights(ib,nb) = 1.0d0
00589
00590 ELSE IF ( nb > 0 ) THEN
00591 dda_weights(ib,1:nb) = 1.0d0 / dist2v(1:nb)
00592 rdistance = 1.0d0 / SUM (dda_weights(ib,1:nb))
00593 dda_weights(ib,1:nb) = dda_weights(ib,1:nb) * rdistance
00594 ENDIF
00595
00596 END IF
00597
00598
00599
00600
00601 END DO
00602
00603 #endif
00604
00605 #ifdef VERBOSE
00606 PRINT *, '| | | | | | | Quit PRISMTrs_Bilinear_weight_2d'
00607 call psmile_flushstd
00608 #endif
00609
00610 END SUBROUTINE PRISMTrs_Bilinear_weight_2d
00611
00612
00613
00614
00615