00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 subroutine psmile_search_nn_3d_real ( &
00012 sin_search, cos_search, z_search, distance, &
00013 nfound, locations, n_send, &
00014 x_coords, y_coords, z_coords, coords_shape, &
00015 sin_values, cos_values, grid_valid_shape, &
00016 mask_array, mask_shape, mask_available, &
00017 tol, ierror)
00018
00019
00020
00021 use PRISM
00022
00023 use PSMILe, dummy_interface => PSMILe_Search_nn_3d_real
00024
00025 Implicit none
00026
00027
00028
00029
00030
00031
00032
00033
00034 Integer, Parameter :: lon = 1
00035 Integer, Parameter :: lat = 2
00036
00037 Real, Parameter :: real_earth = 6400000.0
00038 Real, Parameter :: acosp1 = 1.0
00039 Real, Parameter :: acosm1 = -1.0
00040 Real, Parameter :: eps = 1d-6
00041
00042
00043
00044 Integer, Intent (In) :: n_send
00045
00046
00047
00048 Real, Intent (In) :: sin_search (n_send, lat)
00049
00050
00051
00052
00053 Real, Intent (In) :: cos_search (n_send, lat)
00054
00055
00056
00057
00058 Real, Intent (In) :: z_search (n_send)
00059
00060
00061
00062
00063 Integer, Intent (In) :: coords_shape (2, ndim_3d)
00064
00065
00066
00067 Real, Intent (In) ::
00068 x_coords( coords_shape(1,1):coords_shape(2,1),
00069 coords_shape(1,2):coords_shape(2,2),
00070 coords_shape(1,3):coords_shape(2,3))
00071 Real, Intent (In) ::
00072 y_coords( coords_shape(1,1):coords_shape(2,1),
00073 coords_shape(1,2):coords_shape(2,2),
00074 coords_shape(1,3):coords_shape(2,3))
00075 Real, Intent (In) ::
00076 z_coords( coords_shape(1,1):coords_shape(2,1),
00077 coords_shape(1,2):coords_shape(2,2),
00078 coords_shape(1,3):coords_shape(2,3))
00079
00080
00081
00082 Integer, Intent (In) :: mask_shape (2, ndim_3d)
00083
00084
00085
00086 Logical, Intent (In) ::
00087 mask_array (mask_shape (1,1):mask_shape (2,1),
00088 mask_shape (1,2):mask_shape (2,2),
00089 mask_shape (1,3):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 Real, Intent (In) ::
00103 sin_values (grid_valid_shape(1,1):grid_valid_shape(2,1),
00104 grid_valid_shape(1,2):grid_valid_shape(2,2),
00105 grid_valid_shape(1,3):grid_valid_shape(2,3), lat)
00106
00107
00108
00109 Real, Intent (In) ::
00110 cos_values (grid_valid_shape(1,1):grid_valid_shape(2,1),
00111 grid_valid_shape(1,2):grid_valid_shape(2,2),
00112 grid_valid_shape(1,3):grid_valid_shape(2,3), lat)
00113
00114
00115
00116 Real, Intent (In) :: tol
00117
00118
00119
00120
00121
00122
00123
00124 Real, Intent (InOut) :: distance (n_send)
00125
00126
00127
00128 Integer, Intent (InOut) :: nfound (n_send)
00129
00130
00131
00132
00133
00134 Integer, Intent (Out) :: locations (ndim_3d, n_send)
00135
00136
00137
00138 Integer, Intent (Out) :: ierror
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 Integer :: n
00149
00150
00151
00152 Real :: real_huge, dist2, fac
00153 Integer :: kmin (ndim_3d)
00154
00155 Real, Allocatable :: vals (:, :, :)
00156
00157
00158
00159 Integer, Parameter :: nerrp = 2
00160 Integer :: ierrp (nerrp)
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 Character(len=len_cvs_string), save :: mycvs =
00183 '$Id: psmile_search_nn_3d_real.F90 2082 2009-10-21 13:31:19Z hanke $'
00184
00185
00186
00187
00188 #ifdef VERBOSE
00189 print 9990, trim(ch_id), n_send
00190
00191 call psmile_flushstd
00192 #endif /* VERBOSE */
00193
00194 ierror = 0
00195
00196
00197
00198 #if 0
00199 TODO: allocate only data for boundary of the 3d block
00200 and test on these points
00201 whether smaller distance is available in block
00202 Currently Brute force
00203 num = 2 * ( (grid_valid_shape(2,1)-grid_valid_shape(1,1)+1)*
00204 (grid_valid_shape(2,2)-grid_valid_shape(1,2)+1) +
00205 (grid_valid_shape(2,2)-grid_valid_shape(1,2)+1)*
00206 (grid_valid_shape(2,3)-grid_valid_shape(1,3)+1) +
00207 (grid_valid_shape(2,3)-grid_valid_shape(1,3)+1)*
00208 (grid_valid_shape(2,1)-grid_valid_shape(1,1)+1) )
00209 #endif
00210
00211 Allocate (vals (grid_valid_shape(1,1):grid_valid_shape(2,1), &
00212 grid_valid_shape(1,2):grid_valid_shape(2,2), &
00213 grid_valid_shape(1,3):grid_valid_shape(2,3)), &
00214 STAT = ierror)
00215
00216 if (ierror > 0) then
00217 ierrp (1) = ierror
00218 ierrp (2) = (grid_valid_shape(2,1)-grid_valid_shape(1,1)+1) * &
00219 (grid_valid_shape(2,2)-grid_valid_shape(1,2)+1)
00220
00221 ierror = PRISM_Error_Alloc
00222 call psmile_error ( ierror, 'vals', ierrp, 2, &
00223 __FILE__, __LINE__ )
00224 return
00225 endif
00226
00227
00228
00229
00230
00231 real_huge = huge (distance(1))
00232
00233 do n = 1, n_send
00234 if (distance (n) == real_huge) then
00235 dist2 = real_huge
00236 else
00237 dist2 = distance (n) * distance (n)
00238 endif
00239
00240 fac = real_earth + z_search (n)
00241
00242
00243
00244
00245 vals = ( sin_values(:,:,:, lat) * sin_search(n, lat) &
00246 + cos_values(:,:,:, lat) * cos_search(n, lat) &
00247 * (cos_values(:,:,:, lon) * cos_search(n, lon) &
00248 +sin_values(:,:,:, lon) * sin_search(n, lon)) )
00249
00250 #ifdef PRISM_ASSERTION
00251 if (minval (vals) < acosm1 - eps .or. &
00252 maxval (vals) > acosp1 + eps) then
00253 print *, 'min vals', minloc (vals), minval (vals)
00254 print *, 'max vals', maxloc (vals), maxval (vals)
00255 call psmile_assert (__FILE__, __LINE__, &
00256 'invalid value for acos')
00257 endif
00258 #endif
00259
00260 vals = min (acosp1, vals)
00261 vals = max (acosm1, vals)
00262
00263 vals = fac * acos (vals)
00264 vals = vals * vals
00265
00266
00267
00268 vals = vals + &
00269 (z_coords (grid_valid_shape(1,1):grid_valid_shape(2,1), &
00270 grid_valid_shape(1,2):grid_valid_shape(2,2), &
00271 grid_valid_shape(1,3):grid_valid_shape(2,3)) &
00272 - z_search (n)) ** 2
00273
00274 if (mask_available) then
00275 kmin = minloc (vals, &
00276 mask_array (grid_valid_shape(1,1):grid_valid_shape(2,1), &
00277 grid_valid_shape(1,2):grid_valid_shape(2,2), &
00278 grid_valid_shape(1,3):grid_valid_shape(2,3)) )
00279 else
00280 kmin = minloc (vals)
00281 endif
00282
00283 if (vals(kmin(1), kmin(2), kmin(3)) >= dist2) cycle
00284
00285
00286
00287 locations (:, n) = kmin (:)
00288
00289 nfound (n) = 1
00290
00291 #ifdef DEBUGX
00292 print *, 'psmile_search_nn_3d_real: n, old, dist2', &
00293 n, dist2, vals(kmin(1), kmin(2), kmin(3))
00294 print *, 'psmile_search_nn_3d_real: n, loc', &
00295 n, locations (:, n)
00296 #endif
00297
00298 distance (n) = sqrt ( vals(kmin(1), kmin(2), kmin(3)) )
00299
00300 enddo
00301
00302 Deallocate (vals)
00303
00304
00305
00306 #ifdef VERBOSE
00307 print 9980, trim(ch_id), ierror
00308
00309 call psmile_flushstd
00310 #endif /* VERBOSE */
00311
00312 return
00313
00314
00315
00316 #ifdef VERBOSE
00317 9990 format (1x, a, ': psmile_search_nn_3d_real: n_send', i7)
00318 9980 format (1x, a, ': psmile_search_nn_3d_real: eof ierror =', i4)
00319 #endif /* VERBOSE */
00320
00321 end subroutine PSMILe_Search_nn_3d_real