00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 subroutine psmile_neigh_near_3d_reg_dble ( &
00012 grid_id, &
00013 coords1, coords2, coords3, &
00014 x_coords, y_coords, z_coords, &
00015 coords_shape, &
00016 mask_array, mask_shape, mask_available, &
00017 sin_values_lon, cos_values_lon, &
00018 sin_values_lat, cos_values_lat, &
00019 grid_valid_shape, search_mode, &
00020 srclocs, nlocs, nloc, nprev, &
00021 neighbors_3d, num_neigh, &
00022 extra_search, ierror)
00023
00024
00025
00026 use PRISM_constants
00027
00028 use PSMILe, dummy_interface => PSMILe_Neigh_near_3d_reg_dble
00029
00030 implicit none
00031
00032
00033
00034 Integer, Intent (In) :: grid_id
00035
00036
00037
00038
00039 Integer, Intent (In) :: nloc
00040
00041
00042
00043 Integer, Intent (In) :: nlocs (ndim_3d)
00044
00045
00046
00047
00048
00049
00050 Integer, Intent (In) :: nprev
00051
00052
00053
00054 Type (integer_vector), Intent (In) :: srclocs (ndim_3d)
00055
00056
00057
00058 Double Precision, Intent (In) :: coords1 (nlocs(1),nlocs(2),nlocs(3))
00059 Double Precision, Intent (In) :: coords2 (nlocs(1),nlocs(2),nlocs(3))
00060 Double Precision, Intent (In) :: coords3 (nlocs(1),nlocs(2),nlocs(3))
00061
00062
00063
00064
00065
00066 Integer, Intent (In) :: coords_shape (2, ndim_3d)
00067
00068
00069
00070 Double Precision, Intent (In) :: x_coords(coords_shape(1,1):
00071 coords_shape(2,1))
00072 Double Precision, Intent (In) :: y_coords(coords_shape(1,2):
00073 coords_shape(2,2))
00074 Double Precision, Intent (In) :: z_coords(coords_shape(1,3):
00075 coords_shape(2,3))
00076
00077
00078
00079 Integer, Intent (In) :: mask_shape (2, ndim_3d)
00080
00081
00082
00083 Logical, Intent (In) :: mask_array (mask_shape (1,1):
00084 mask_shape (2,1),
00085 mask_shape (1,2):
00086 mask_shape (2,2),
00087 mask_shape (1,3):
00088 mask_shape (2,3))
00089
00090
00091 Logical, Intent (In) :: mask_available
00092
00093
00094
00095
00096
00097 Integer, Intent (In) :: grid_valid_shape (2, ndim_3d)
00098
00099
00100
00101 Double Precision, Intent (In) :: sin_values_lon (grid_valid_shape(1,1):
00102 grid_valid_shape(2,1))
00103 Double Precision, Intent (In) :: sin_values_lat (grid_valid_shape(1,2):
00104 grid_valid_shape(2,2))
00105
00106
00107
00108 Double Precision, Intent (In) :: cos_values_lon (grid_valid_shape(1,1):
00109 grid_valid_shape(2,1))
00110 Double Precision, Intent (In) :: cos_values_lat (grid_valid_shape(1,2):
00111 grid_valid_shape(2,2))
00112
00113
00114
00115 Integer, Intent (In) :: search_mode
00116
00117
00118
00119
00120
00121
00122 Integer, Intent (In) :: num_neigh
00123
00124
00125
00126
00127
00128
00129 Type (Extra_search_info) :: extra_search
00130
00131
00132
00133
00134
00135
00136 Integer, Intent (Out) :: neighbors_3d (ndim_3d, nloc, num_neigh)
00137
00138
00139
00140 integer, Intent (Out) :: ierror
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 Integer, Parameter :: nref_3d = 4 * 4 * 4
00160 Integer, Parameter :: nref_2d = 4 * 4
00161 Integer, Parameter :: nref_1d = 4
00162 Integer, Parameter :: lon = 1
00163 Integer, Parameter :: lat = 2
00164
00165 Double Precision, Parameter :: dble_earth = 6400.0
00166
00167 Double Precision, Parameter :: tol = 1d-6
00168 Double Precision, Parameter :: eps = 1d-6
00169 Double Precision, Parameter :: acosp1 = 1.0d0
00170 Double Precision, Parameter :: acosm1 = -1.0d0
00171
00172
00173
00174
00175
00176 Double Precision :: sin_search_lon (nlocs(1))
00177 Double Precision :: cos_search_lon (nlocs(1))
00178 Double Precision :: sin_search_lat (nlocs(2))
00179 Double Precision :: cos_search_lat (nlocs(2))
00180
00181 Integer :: nrefv (1:ndim_3d)
00182
00183
00184
00185 Integer :: leni, lenij
00186 Integer :: np
00187
00188
00189
00190 Integer :: i, j, k
00191 Integer :: ii, jj, kk
00192 Integer :: n, nref, nrefd
00193
00194 Integer :: ijk (ndim_3d)
00195 Integer :: ijk0 (ndim_3d)
00196 Integer :: ijkdst (ndim_3d, nref_3d)
00197 Integer :: ijkctl (ndim_3d, nref_3d)
00198 Integer :: irange (2, ndim_3d)
00199
00200
00201
00202 Integer :: itemp (ndim_3d)
00203
00204
00205
00206 Logical :: mask_dist (nref_3d)
00207
00208
00209
00210 Integer :: nfound
00211 Integer :: nmin (1)
00212
00213 Double Precision :: dble_huge
00214 Double Precision :: dist, fac, val, z
00215 Double Precision :: distance (nref_3d)
00216 #ifdef TODO
00217 Double Precision :: dist_control
00218 #endif
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 Character(len=len_cvs_string), save :: mycvs =
00256 '$Id: psmile_neigh_near_3d_reg_dble.F90 2325 2010-04-21 15:00:07Z valcke $'
00257
00258
00259
00260
00261
00262 #ifdef OLD
00263 Integer, Parameter :: nrefd = 3 * 3 * 3
00264
00265 data ((ijkctl (i, n), i=1,ndim_3d), n = 1,nref_3d) &
00266 / 0, 0, 0, &
00267 1, 0, 0, 0, 1, 0, 0, 0, 1, &
00268 -1, 0, 0, 0,-1, 0, 0, 0,-1, &
00269 -1,-1, 0, 1,-1, 0, &
00270 -1, 1, 0, 1, 1, 0, &
00271 -1, 0,-1, 1, 0,-1, &
00272 -1, 0, 1, 1, 0, 1, &
00273 0,-1,-1, 0, 1,-1, &
00274 0,-1, 1, 0, 1, 1, &
00275 -1,-1,-1, 1,-1,-1, &
00276 -1, 1,-1, 1, 1,-1, &
00277 -1,-1, 1, 1,-1, 1, &
00278 -1, 1, 1, 1, 1, 1/
00279 #endif
00280
00281
00282
00283 data ((ijkctl (i, n), i=1,ndim_3d), n = 1,nref_3d) &
00284 / 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, &
00285 0, 1, 0, 1, 1, 0, 2, 1, 0, 3, 1, 0, &
00286 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0, &
00287 0, 3, 0, 1, 3, 0, 2, 3, 0, 3, 3, 0, &
00288 0, 0, 1, 1, 0, 1, 2, 0, 1, 3, 0, 1, &
00289 0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, &
00290 0, 2, 1, 1, 2, 1, 2, 2, 1, 3, 2, 1, &
00291 0, 3, 1, 1, 3, 1, 2, 3, 1, 3, 3, 1, &
00292 0, 0, 2, 1, 0, 2, 2, 0, 2, 3, 0, 2, &
00293 0, 1, 2, 1, 1, 2, 2, 1, 2, 3, 1, 2, &
00294 0, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 2, &
00295 0, 3, 2, 1, 3, 2, 2, 3, 2, 3, 3, 2, &
00296 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3, &
00297 0, 1, 3, 1, 1, 3, 2, 1, 3, 3, 1, 3, &
00298 0, 2, 3, 1, 2, 3, 2, 2, 3, 3, 2, 3, &
00299 0, 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, 3/
00300
00301 data nrefv /nref_1d, nref_2d, nref_3d/
00302
00303
00304
00305
00306
00307 #ifdef VERBOSE
00308 print 9990, trim(ch_id)
00309
00310 call psmile_flushstd
00311 #endif /* VERBOSE */
00312
00313 ierror = 0
00314
00315 #ifdef PRISM_ASSERTION
00316
00317
00318
00319 if (search_mode < 1 .or. search_mode > ndim_3d) then
00320 print *, trim(ch_id), " search_mode ", search_mode
00321 call psmile_assert (__FILE__, __LINE__, &
00322 'search_mode is out of range ')
00323 endif
00324
00325 if (nloc < nprev + nlocs (1) * nlocs (2) * nlocs (3)) then
00326 print *, trim(ch_id), " nloc, nprev, nlocs ", nloc, nprev, nlocs
00327 call psmile_assert (__FILE__, __LINE__, &
00328 'nloc < nprev + PRODUCT (nlocs) ')
00329 endif
00330
00331
00332
00333 do j = 1, ndim_3d
00334
00335 do i = 1, nlocs (j)
00336
00337 if (srclocs(j)%vector(i) < grid_valid_shape(1,j) - 1 .or. &
00338 srclocs(j)%vector(i) > grid_valid_shape(2,j)) exit
00339 end do
00340
00341 if (i <= nlocs(j)) then
00342 print *, "Incorrect index in j, i", j, i, srclocs(j)%vector(i)
00343 call psmile_assert (__FILE__, __LINE__, &
00344 'wrong index')
00345 endif
00346 end do
00347 #endif
00348
00349 dble_huge = huge (distance(1))
00350
00351
00352
00353 nrefd = nrefv (search_mode)
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 do i = 1, nlocs (1)
00373 sin_search_lon (i) = coords1 (i, 1, 1) * dble_deg2rad
00374 end do
00375
00376
00377 do j = 1, nlocs (2)
00378 sin_search_lat (j) = coords2 (1, j, 1) * dble_deg2rad
00379 end do
00380
00381 cos_search_lon = cos (sin_search_lon)
00382 cos_search_lat = cos (sin_search_lat)
00383
00384 sin_search_lon = sin (sin_search_lon)
00385 sin_search_lat = sin (sin_search_lat)
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 ijk0 = Grids(grid_id)%ijk0
00407 np = nprev
00408
00409 do k = 1, nlocs (3)
00410
00411
00412
00413
00414
00415 if (search_mode < 3) then
00416 ijk(3) = srclocs(3)%vector(k)
00417 irange (:, 3) = ijk (3)
00418 else
00419 ijk(3) = ijk0(3) + ((srclocs(3)%vector(k) - ijk0(3)) / 4) * 4
00420 irange (1, 3) = max (ijk (3), grid_valid_shape (1, 3))
00421 irange (2, 3) = min (ijk (3)+3, grid_valid_shape (2, 3))
00422 endif
00423
00424 z = coords3 (1, 1, k)
00425 fac = dble_earth + z
00426
00427 do j = 1, nlocs (2)
00428
00429
00430
00431
00432 if (search_mode < 2) then
00433 ijk(2) = srclocs(2)%vector(j)
00434 irange (:, 2) = ijk (2)
00435 else
00436 ijk(2) = ijk0(2) + ((srclocs(2)%vector(j) - ijk0(2)) / 4) * 4
00437 irange (1, 2) = max (ijk (2), grid_valid_shape (1, 2))
00438 irange (2, 2) = min (ijk (2)+3, grid_valid_shape (2, 2))
00439 endif
00440
00441 do i = 1, nlocs (1)
00442
00443
00444
00445
00446 ijk(1) = ijk0(1) + ((srclocs(1)%vector(i) - ijk0(1)) / 4) * 4
00447
00448 irange (1, 1) = max (ijk(1), grid_valid_shape (1, 1))
00449 irange (2, 1) = min (ijk(1)+3, grid_valid_shape (2, 1))
00450
00451 nref = (irange (2,1) - irange (1,1) + 1) * &
00452 (irange (2,2) - irange (1,2) + 1) * &
00453 (irange (2,3) - irange (1,3) + 1)
00454
00455 if (nref == nrefd) then
00456 do n = 1, nrefd
00457 ijkdst (:, n) = ijk + ijkctl (:, n)
00458 end do
00459 else
00460
00461 leni = irange (2, 1) - irange (1, 1) + 1
00462 lenij = (irange (2, 2) - irange (1, 2) + 1) * leni
00463
00464 do kk = 1, irange (2,3)-irange(1,3) + 1
00465 n = (kk-1)*lenij
00466 do jj = 1, irange (2,2)-irange(1,2) + 1
00467
00468 do ii = 1, leni
00469 ijkdst (1, n+ii) = irange(1,1) + ii - 1
00470 end do
00471
00472 ijkdst (2, n+1:n+leni) = irange (1,2) + jj - 1
00473 n = n + leni
00474 end do
00475
00476 ijkdst (3, (kk-1)*lenij+1:kk*lenij) = irange (1,3) + kk - 1
00477 end do
00478 endif
00479
00480
00481
00482 if (mask_available) then
00483
00484 do n = 1, nref
00485 mask_dist (n) = mask_array (ijkdst (1,n), ijkdst (2,n), &
00486 ijkdst (3,n))
00487 end do
00488
00489 n = count (mask_dist(1:nref))
00490
00491 if (n == 0) then
00492
00493
00494 nref = 0
00495 go to 10
00496 endif
00497
00498 if (n < nref) then
00499 n = 0
00500 do ii = 1, nref
00501 if (mask_dist (ii)) then
00502 n = n + 1
00503 if (n /= ii) ijkdst (:, n) = ijkdst (:, ii)
00504 endif
00505 end do
00506 nref = n
00507 endif
00508 endif
00509
00510
00511
00512
00513 do n = 1, nref
00514 val = ( sin_values_lat(ijkdst (2,n)) * sin_search_lat(j) &
00515 + cos_values_lat(ijkdst (2,n)) * cos_search_lat(j) &
00516 * (cos_values_lon(ijkdst (1,n)) * cos_search_lon(i) &
00517 +sin_values_lon(ijkdst (1,n)) * sin_search_lon(i)) )
00518
00519 #ifdef PRISM_ASSERTION
00520 if (val < acosm1 - eps .or. val > acosp1 + eps) then
00521 print *, i, j, k, val
00522 call psmile_assert (__FILE__, __LINE__, &
00523 'invalid value for acos')
00524 endif
00525 #endif
00526 val = min (acosp1, val)
00527 val = max (acosm1, val)
00528
00529 dist = fac * acos (val)
00530
00531 distance (n) = dist*dist + (z-z_coords(ijkdst (3,n)))**2
00532 #ifdef DEBUG2
00533 if (i == 1 .and. j == 1 .and. k == 1) then
00534 print *, 'dist, diff', dist, &
00535 z-z_coords(ijkdst (3,n))
00536 endif
00537 #endif
00538 end do
00539
00540 nmin = minloc (distance(1:nref))
00541 #ifdef MINLOCFIX
00542 if (nmin(1).eq.0) nmin=1
00543 #endif /* MINLOCFIX */
00544
00545 #ifdef DEBUG2
00546 if (i == 1 .and. j == 1 .and. k == 1) then
00547 print *, 'psmile_neigh_near_3d_reg_dble: ictl =', i, j, k, np
00548 print *, 'ijkdst and distance:'
00549 do n = 1, nref
00550 print *, ijkdst (:, n), distance (n)
00551 end do
00552 endif
00553 #endif
00554
00555
00556
00557 if (distance(nmin(1)) <= tol) then
00558 neighbors_3d (:, np+i, 1) = ijkdst (:, nmin(1))
00559
00560 do n = 2, num_neigh
00561 neighbors_3d (:, np+i, n) = grid_valid_shape (1, :) - 1
00562 end do
00563
00564 cycle
00565 endif
00566
00567
00568
00569
00570 10 continue
00571
00572 nfound = min (num_neigh, nref)
00573 if (nfound < num_neigh) then
00574 distance(nfound+1:num_neigh) = dble_huge
00575
00576 do n = nfound+1, num_neigh
00577 ijkdst (:, n) = grid_valid_shape (1, :) - 1
00578 end do
00579 endif
00580
00581 do n = 1, nfound
00582
00583 nmin = minloc (distance(n:nref))
00584 #ifdef MINLOCFIX
00585 if (nmin(1).eq.0) nmin=1
00586 #endif /* MINLOCFIX */
00587
00588 if (nmin(1) /= 1) then
00589 jj = n + nmin (1) - 1
00590
00591 itemp (:) = ijkdst (:, n)
00592 ijkdst (:, n) = ijkdst (:, jj)
00593 ijkdst (:, jj) = itemp (:)
00594
00595 dist = distance (n)
00596 distance (n) = distance (jj)
00597 distance (jj) = dist
00598 endif
00599 end do
00600
00601 #ifdef PRISM_ASSERTION
00602 do n = 1, nfound-1
00603 if (distance(n) > distance (n+1)) exit
00604 end do
00605
00606 if (n <= nfound-1) then
00607 print *, 'n =' , n
00608 print *, 'distance (n) ', distance (n)
00609 print *, 'distance (n+1)', distance (n+1)
00610 print *, 'distance', distance (1:nfound)
00611 call psmile_assert (__FILE__, __LINE__, &
00612 'incorrect sort')
00613 endif
00614 #endif
00615
00616
00617
00618 #ifdef TODO
00619 dist_control = distance (num_neigh)
00620
00621 call psmile_mg_search_nneigh_3d_reg_dble (distance, ijkdst, num_neigh, &
00622 grid_id, ierror)
00623 #endif /* TODO */
00624
00625
00626
00627 do n = 1, num_neigh
00628 neighbors_3d (:, np+i, n) = ijkdst (:, n)
00629 end do
00630
00631 end do
00632
00633 np = np + nlocs (1)
00634 end do
00635 end do
00636
00637
00638
00639 #ifdef VERBOSE
00640 print 9980, trim(ch_id), ierror
00641
00642 call psmile_flushstd
00643 #endif /* VERBOSE */
00644
00645
00646
00647 9990 format (1x, a, ': psmile_neigh_near_3d_reg_dble')
00648 9980 format (1x, a, ': psmile_neigh_near_3d_reg_dble: eof, ierror =', i3)
00649
00650 end subroutine PSMILe_Neigh_near_3d_reg_dble