00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 subroutine psmile_mg_srch_nneigh_reg_dble (grid_id, nn_srch, &
00011 arrays, search_mode, nref_3d, grid_valid_shape, &
00012 neighbors_3d, nloc, num_neigh, &
00013 sin_search, cos_search, z_search, &
00014 dist_dble, dim1, indices, jbeg, jend, &
00015 mask_array, mask_shape, mask_available, &
00016 tol, ierror)
00017
00018
00019
00020 use PRISM_constants
00021
00022 use PSMILe, dummy_interface => PSMILe_MG_srch_nneigh_reg_dble
00023
00024 implicit none
00025
00026
00027
00028 Integer, Intent (In) :: grid_id
00029
00030
00031
00032
00033 Type (Extra_search_nn), Intent (In) :: nn_srch
00034
00035
00036
00037 Type (Extra_search_dble) :: arrays
00038
00039
00040
00041 Integer, Intent (In) :: nref_3d
00042
00043
00044
00045 Integer, Intent (In) :: search_mode
00046
00047
00048
00049
00050
00051
00052 Integer, Intent (In) :: grid_valid_shape (2, ndim_3d)
00053
00054
00055
00056 Integer, Intent (In) :: nloc
00057
00058
00059
00060
00061 Integer, Intent (In) :: num_neigh
00062
00063
00064
00065
00066
00067 Integer, Intent (In) :: jbeg, jend
00068
00069
00070
00071 Integer, Parameter :: lat = 2
00072 Double Precision, Intent (In) :: sin_search (jbeg:jend, lat)
00073
00074
00075
00076
00077 Double Precision, Intent (In) :: cos_search (jbeg:jend, lat)
00078
00079
00080
00081
00082 Double Precision, Intent (In) :: z_search (jbeg:jend)
00083
00084
00085
00086
00087 Integer, Intent (In) :: dim1 (2)
00088
00089
00090
00091 Integer, Intent (In) :: indices (:)
00092
00093
00094
00095
00096 Integer, Intent (In) :: mask_shape (2, ndim_3d)
00097
00098
00099
00100 Logical, Intent (In) ::
00101 mask_array (mask_shape (1,1):mask_shape (2,1),
00102 mask_shape (1,2):mask_shape (2,2),
00103 mask_shape (1,3):mask_shape (2,3))
00104
00105
00106
00107 Logical, Intent (In) :: mask_available
00108
00109
00110
00111
00112
00113 Double Precision, Intent (In) :: tol
00114
00115
00116
00117
00118
00119 Double Precision, Intent (InOut) :: dist_dble (dim1(1):dim1(2), num_neigh)
00120
00121
00122
00123 Integer, Intent (Out) :: neighbors_3d (ndim_3d, nloc, num_neigh)
00124
00125
00126
00127
00128
00129
00130 Integer, Intent (Out) :: ierror
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 Double Precision, Parameter :: dble_earth = 6400000.0
00141
00142 Double Precision, Parameter :: acosp1 = 1.0
00143 Double Precision, Parameter :: acosm1 = -1.0
00144
00145 Integer, Parameter :: lon = 1
00146 Integer, Parameter :: maxlen = 64
00147
00148
00149
00150 Double Precision :: dist, maxdist, val, fac, fac2
00151
00152 Double Precision :: sin_corner_lat(8,3)
00153 Double Precision :: cos_corner_lat(8,3)
00154 Double Precision :: sin_corner_lon(8,3)
00155 Double Precision :: cos_corner_lon(8,3)
00156
00157 Double Precision :: sin_midp_lat(3)
00158 Double Precision :: cos_midp_lat(3)
00159 Double Precision :: sin_midp_lon(3)
00160 Double Precision :: cos_midp_lon(3)
00161
00162 Double Precision :: distrad(maxlen), radius (maxlen)
00163
00164 Logical :: maskrad(maxlen)
00165
00166 Integer :: ijk0 (ndim_3d)
00167 Integer :: ijk (2,ndim_3d)
00168 Integer :: ii, jj, kk
00169 Integer :: inext, jnext, knext
00170 Integer :: i, j, k, n
00171 Integer :: ncount
00172 Integer :: iloc(1)
00173
00174 Type (Grid), Pointer :: grid_info
00175 Type (Enddef_mg_double), Pointer :: my_arrays
00176
00177
00178
00179 Integer :: lev, nlev
00180 Integer, Allocatable :: icoarse (:, :)
00181
00182
00183
00184 Integer :: leni, lenij, lenijk, lenj, lenk
00185
00186
00187
00188 Integer :: ind, jind
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 #ifdef VERBOSE
00213 print 9990, trim(ch_id)
00214
00215 call psmile_flushstd
00216 #endif /* VERBOSE */
00217
00218 ierror = 0
00219
00220 grid_info => Grids(grid_id)
00221 ijk0 = grid_info%ijk0
00222
00223 nlev = grid_info%nlev - 3
00224
00225 #ifdef PRISM_ASSERTION
00226
00227
00228
00229 if ( nn_srch%leni*nn_srch%lenj*nn_srch%lenk > maxlen ) then
00230 print *, "lenijk, maxlen", nn_srch%leni*nn_srch%lenj*nn_srch%lenk, maxlen
00231 call psmile_assert ( __FILE__, __LINE__, "lenijk > maxlen")
00232 endif
00233 #endif
00234
00235
00236
00237
00238
00239
00240 if (mask_available) then
00241 allocate (icoarse (ndim_3d, nlev), stat = ierror)
00242
00243 icoarse (1:ndim_3d, 1) = 1
00244
00245 do lev = 2, nlev
00246 do i = 1, ndim_3d
00247 if ( grid_info%mg_infos(lev )%levdim(i) /= &
00248 grid_info%mg_infos(lev-1)%levdim(i) ) then
00249 icoarse(i, lev) = icoarse(i, lev-1) * 2
00250 else
00251 icoarse(i, lev) = icoarse(i, lev-1)
00252 end if
00253 end do
00254 end do
00255 endif
00256
00257
00258
00259
00260
00261
00262 do jind = jbeg, jend
00263
00264
00265
00266 inext = 0
00267 jnext = 0
00268 knext = 0
00269
00270
00271
00272 my_arrays => grid_info%mg_infos(nlev)%double_arrays
00273
00274 leni = nn_srch%leni
00275 lenj = nn_srch%lenj
00276 lenk = nn_srch%lenk
00277
00278 lenij = leni*lenj
00279 lenijk = lenij*lenk
00280
00281 ind = indices (jind)
00282
00283 maxdist = maxval (dist_dble (jind, 1:num_neigh) )
00284
00285
00286
00287
00288 fac = dble_earth + z_search (jind)
00289
00290 n = 0
00291 do j = 1, lenj
00292
00293
00294 do i = 1, leni
00295 n = n+1
00296
00297 val = ( arrays%sin_cmidp_lat%vector(j) * sin_search(jind,lat) &
00298 + arrays%cos_cmidp_lat%vector(j) * cos_search(jind,lat) &
00299 * (arrays%cos_cmidp_lon%vector(i) * cos_search(jind,lon) &
00300 + arrays%sin_cmidp_lon%vector(i) * sin_search(jind,lon)) )
00301
00302 val = min (acosp1, val)
00303 val = max (acosm1, val)
00304
00305 dist = fac * acos (val)
00306 distrad (n) = dist * dist
00307 enddo
00308 enddo
00309
00310
00311
00312 do k = 2, lenk
00313 distrad ((k-1)*lenij+1:k*lenij) = distrad (1:lenij)
00314 enddo
00315
00316 if ( search_mode == 3 ) then
00317 n = 0
00318 do k = 1, lenk
00319 distrad (n+1:n+lenij) = distrad (n+1:n+lenij) + &
00320 (my_arrays%midp(3)%vector(k)-z_search(jind))**2
00321
00322 n = n + lenij
00323 enddo
00324 endif
00325
00326 distrad (1:lenijk) = sqrt (distrad (1:lenijk))
00327
00328
00329
00330
00331 distrad(1:lenijk) = distrad(1:lenijk) - arrays%radius(1:lenijk)
00332
00333
00334
00335 maskrad (1:lenijk) = distrad (1:lenijk) < maxdist
00336
00337 iloc(:) = minloc (distrad(1:lenijk), maskrad(1:lenijk))
00338 #ifdef MINLOCFIX
00339 if (iloc(1).eq.0) iloc(1)=1
00340 #endif /* MINLOCFIX */
00341
00342 if ( iloc(1) > lenijk ) iloc(1) = 0
00343
00344 do lev = nlev, 3, -1
00345
00346
00347
00348 if ( lev < nlev ) then
00349
00350 n = 0
00351
00352 do k = 1, lenk
00353 fac2 = dble_earth + my_arrays%midp(3)%vector(k)
00354 do j = 1, lenj
00355
00356 do i = 1, leni
00357 n = n+1
00358
00359 val = ( sin_corner_lat(1,j) * sin_midp_lat(j) &
00360 + cos_corner_lat(1,j) * cos_midp_lat(j) &
00361 * (cos_corner_lon(1,i) * cos_midp_lon(i) &
00362 + sin_corner_lon(1,i) * sin_midp_lon(i)) )
00363
00364 val = min (acosp1, val)
00365 val = max (acosm1, val)
00366
00367 dist = fac2 * acos (val)
00368 radius (n) = dist * dist
00369
00370 enddo
00371 enddo
00372 enddo
00373
00374 if ( search_mode == 3 ) then
00375 n = 0
00376
00377 do k = 1, lenk
00378 radius(n+1:n+lenij) = radius(n+1:n+lenij) + &
00379 (my_arrays%midp(3)%vector(k) - my_arrays%chmin(3)%vector(k))**2
00380 n = n + lenij
00381 enddo
00382 endif
00383
00384 radius (1:lenijk) = sqrt (radius (1:lenijk))
00385
00386
00387
00388
00389 n = 0
00390
00391 do j = 1, lenj
00392 do i = 1, leni
00393 n = n+1
00394
00395 val = ( sin_midp_lat(j) * sin_search(jind,lat) &
00396 + cos_midp_lat(j) * cos_search(jind,lat) &
00397 * (cos_midp_lon(i) * cos_search(jind,lon) &
00398 + sin_midp_lon(i) * sin_search(jind,lon)) )
00399
00400 val = min (acosp1, val)
00401 val = max (acosm1, val)
00402
00403 dist = fac * acos (val)
00404 distrad (n) = dist * dist
00405 enddo
00406 enddo
00407
00408 do k = 2, lenk
00409 distrad ((k-1)*lenij+1:k*lenij) = distrad (1:lenij)
00410 enddo
00411
00412 if ( search_mode == 3 ) then
00413 n = 0
00414 do k = 1, lenk
00415 distrad (n+1:n+lenij) = distrad (n+1:n+lenij) + &
00416 (my_arrays%midp(3)%vector(k)-z_search(jind))**2
00417 n = n + lenij
00418 end do
00419 endif
00420
00421 distrad (1:lenijk) = sqrt (distrad (1:lenijk))
00422
00423
00424
00425 distrad (1:lenijk) = distrad (1:lenijk) - radius(1:lenijk)
00426
00427
00428
00429 maskrad (1:lenijk) = distrad (1:lenijk) < maxdist
00430
00431 iloc(:) = minloc(distrad(1:lenijk),maskrad(1:lenijk))
00432 #ifdef MINLOCFIX
00433 if (iloc(1).eq.0) iloc(1)=1
00434 #endif /* MINLOCFIX */
00435
00436 if ( iloc(1) > lenijk ) iloc(1) = 0
00437
00438 endif
00439
00440
00441
00442
00443
00444 if ( mask_available .and. iloc(1) > 0 ) then
00445
00446
00447
00448 do i = 1, lenijk
00449
00450 kk = (iloc(1) - 1) / lenij + 1
00451 jj = (iloc(1) - (kk-1)*lenij - 1) / leni + 1
00452 ii = iloc(1) - (kk-1)*lenij - (jj-1)*leni
00453
00454 ii = ii - 1 + inext
00455 jj = jj - 1 + jnext
00456 kk = kk - 1 + knext
00457
00458 ijk(1,1) = ijk0(1) + ii*icoarse(1,lev)
00459 ijk(1,2) = ijk0(2) + jj*icoarse(2,lev)
00460 ijk(1,3) = ijk0(3) + kk*icoarse(3,lev)
00461
00462 ijk(2,1) = min (grid_valid_shape(2,1), ijk(1,1)+icoarse(1,lev)-1)
00463 ijk(2,2) = min (grid_valid_shape(2,2), ijk(1,2)+icoarse(2,lev)-1)
00464 ijk(2,3) = min (grid_valid_shape(2,3), ijk(1,3)+icoarse(3,lev)-1)
00465
00466 ncount = count( mask_array(ijk(1,1):ijk(2,1), &
00467 ijk(1,2):ijk(2,2), &
00468 ijk(1,3):ijk(2,3)) )
00469 #ifdef DEBUGX
00470 print *, ' masks: ', maskrad(1:lenijk)
00471 print *, ' ii, jj, kk: ', ii, jj, kk
00472 print *, ' lev, i, iloc(1), ncount : ', lev, i, iloc(1), ncount
00473 print *, ' => ijk ', ijk
00474 #endif
00475
00476 if ( ncount > 0 ) exit
00477
00478
00479
00480 maskrad (iloc(1)) = .false.
00481
00482 iloc(:) = minloc (distrad(1:lenijk), maskrad(1:lenijk))
00483 #ifdef MINLOCFIX
00484 if (iloc(1).eq.0) iloc(1)=1
00485 #endif /* MINLOCFIX */
00486
00487 if ( iloc(1) > lenijk ) then
00488 iloc(1) = 0
00489 exit
00490 endif
00491
00492
00493
00494 enddo
00495
00496 if ( ncount == 1 ) then
00497 do k = ijk(1,3),ijk(2,3)
00498 do j = ijk(1,2),ijk(2,2)
00499 do i = ijk(1,1),ijk(2,1)
00500 if ( mask_array(i,j,k) ) then
00501 neighbors_3d (1, ind, 1) = i
00502 neighbors_3d (2, ind, 1) = j
00503 neighbors_3d (3, ind, 1) = k
00504 endif
00505 enddo
00506 enddo
00507 enddo
00508
00509
00510 if ( lev < nlev ) then
00511 dist_dble (jind, 1) = distrad (iloc(1)) + radius(iloc(1))
00512 else
00513 dist_dble (jind, 1) = distrad (iloc(1)) + arrays%radius(iloc(1))
00514 endif
00515
00516 iloc(1) = 0
00517
00518 exit
00519
00520 endif
00521
00522 endif
00523
00524 if ( iloc(1) == 0 ) exit
00525
00526
00527
00528
00529
00530 if ( lev > 3 ) then
00531
00532
00533
00534 inext = ii * (icoarse(1,lev)/icoarse(1,lev-1))
00535 jnext = jj * (icoarse(2,lev)/icoarse(2,lev-1))
00536 knext = kk * (icoarse(3,lev)/icoarse(3,lev-1))
00537
00538 my_arrays => grid_info%mg_infos(lev-1)%double_arrays
00539
00540 leni = min(inext+2,grid_info%mg_infos(lev-1)%levdim(1)) - inext + 1
00541 lenj = min(jnext+2,grid_info%mg_infos(lev-1)%levdim(2)) - jnext + 1
00542 lenk = min(knext+2,grid_info%mg_infos(lev-1)%levdim(3)) - knext + 1
00543 lenij = leni*lenj
00544 lenijk = lenij*lenk
00545
00546 #ifdef PRISM_ASSERTION
00547
00548 if ( lenijk > maxlen ) then
00549 print *, "lenijk, maxlen", lenijk, maxlen
00550 call psmile_assert ( __FILE__, __LINE__, "lenijk > maxlen")
00551 endif
00552 #endif
00553 sin_corner_lon(1,1:leni) = sin(my_arrays%chmin(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00554 cos_corner_lon(1,1:leni) = cos(my_arrays%chmin(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00555 sin_corner_lat(1,1:lenj) = sin(my_arrays%chmin(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00556 cos_corner_lat(1,1:lenj) = cos(my_arrays%chmin(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00557
00558 sin_midp_lon(1:leni) = sin(my_arrays%midp(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00559 cos_midp_lon(1:leni) = cos(my_arrays%midp(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00560 sin_midp_lat(1:lenj) = sin(my_arrays%midp(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00561 cos_midp_lat(1:lenj) = cos(my_arrays%midp(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00562
00563 endif
00564
00565 enddo
00566
00567
00568
00569
00570
00571
00572 if ( iloc(1) > 0 ) then
00573
00574 my_arrays => grid_info%mg_infos(1)%double_arrays
00575
00576 inext = ijk(1,1) - ijk0(1)
00577 jnext = ijk(1,2) - ijk0(2)
00578 knext = ijk(1,3) - ijk0(3)
00579
00580 leni = ijk(2,1) - ijk(1,1) + 1
00581 lenj = ijk(2,2) - ijk(1,2) + 1
00582 lenk = ijk(2,3) - ijk(1,3) + 1
00583
00584 lenij = leni*lenj
00585 lenijk = lenij*lenk
00586
00587 #ifdef PRISM_ASSERTION
00588
00589 if ( lenijk > maxlen ) then
00590 print *, "lenijk, maxlen", lenijk, maxlen
00591 call psmile_assert ( __FILE__, __LINE__, "lenijk > maxlen")
00592 endif
00593 #endif
00594
00595 arrays%sin_fmidp_lon%vector(1:leni) = sin(my_arrays%midp(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00596 arrays%cos_fmidp_lon%vector(1:leni) = cos(my_arrays%midp(1)%vector(inext+1:inext+leni)*dble_deg2rad)
00597 arrays%sin_fmidp_lat%vector(1:lenj) = sin(my_arrays%midp(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00598 arrays%cos_fmidp_lat%vector(1:lenj) = cos(my_arrays%midp(2)%vector(jnext+1:jnext+lenj)*dble_deg2rad)
00599
00600 n = 0
00601
00602 do j = 1, lenj
00603
00604 do i = 1, leni
00605
00606 n = n+1
00607
00608
00609
00610 val = ( arrays%sin_fmidp_lat%vector(j) * sin_search(jind,lat) &
00611 + arrays%cos_fmidp_lat%vector(j) * cos_search(jind,lat) &
00612 * (arrays%cos_fmidp_lon%vector(i) * cos_search(jind,lon) &
00613 + arrays%sin_fmidp_lon%vector(i) * sin_search(jind,lon)) )
00614
00615 val = min (acosp1, val)
00616 val = max (acosm1, val)
00617
00618 dist = fac * acos (val)
00619
00620 distrad(n) = dist*dist
00621 end do
00622 enddo
00623
00624 do k = 2, lenk
00625 distrad ((k-1)*lenij+1:k*lenij) = distrad (1:lenij)
00626 enddo
00627
00628 if ( search_mode == 3 ) then
00629 n = 0
00630 do k = 1, lenk
00631 distrad (n+1:n+lenij) = distrad (n+1:n+lenij) + &
00632 (my_arrays%midp(3)%vector(k)-z_search(jind))**2
00633 n = n + lenij
00634 end do
00635 endif
00636
00637
00638 if ( mask_available ) then
00639 n = 0
00640 do k = 1, lenk
00641 do j = 1, lenj
00642
00643 do i = 1, leni
00644 n = n + 1
00645
00646 maskrad (n) = mask_array(ijk(1,1)+i-1, &
00647 ijk(1,2)+j-1, &
00648 ijk(1,3)+k-1)
00649 end do
00650 end do
00651 end do
00652
00653 i = min(num_neigh, count(maskrad(1:lenijk)))
00654 else
00655 maskrad (1:lenijk) = .true.
00656
00657 i = min(num_neigh, lenijk)
00658 endif
00659
00660 do n = 1, i
00661
00662 iloc(:) = minloc (distrad(1:lenijk), maskrad(1:lenijk))
00663 #ifdef MINLOCFIX
00664 if (iloc(1).eq.0) iloc(1)=1
00665 #endif /* MINLOCFIX */
00666
00667 kk = (iloc(1) - 1) / lenij + 1
00668 jj = (iloc(1) - (kk-1)*lenij - 1) / leni + 1
00669 ii = iloc(1) - (kk-1)*lenij - (jj-1) * leni
00670
00671 neighbors_3d (1, ind, n) = ijk(1,1)+ii-1
00672 neighbors_3d (2, ind, n) = ijk(1,2)+jj-1
00673 neighbors_3d (3, ind, n) = ijk(1,3)+kk-1
00674
00675
00676 dist_dble (jind, n) = sqrt ( distrad(iloc(1)) )
00677
00678 maskrad (iloc(1)) = .false.
00679
00680 end do
00681
00682 endif
00683 end do
00684
00685
00686
00687
00688 if (mask_available) then
00689 Deallocate (icoarse)
00690 endif
00691
00692 #ifdef VERBOSE
00693 print 9980, trim(ch_id), ierror
00694
00695 call psmile_flushstd
00696 #endif /* VERBOSE */
00697
00698
00699
00700 9990 format (1x, a, ': psmile_mg_srch_nneigh_reg_dble')
00701 9980 format (1x, a, ': psmile_mg_srch_nneigh_reg_dble: eof, ierror =', i3)
00702
00703 end subroutine PSMILe_MG_srch_nneigh_reg_dble