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