00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 subroutine prismtrs_intersection(location,intrsct_lat,intrsct_lon,lcoinc, &
00011 beglat, beglon, endlat, endlon, begseg, &
00012 lbegin, lrevers, &
00013 num_srch_cells, id_nbcorners, &
00014 srch_corner_lat, srch_corner_lon, srch_add)
00015
00016
00017
00018
00019
00020
00021
00022 USE PRISMDrv, dummy_INTERFACE => PRISMTrs_intersection
00023 IMPLICIT NONE
00024
00025 INTEGER, INTENT(in) :: num_srch_cells, id_nbcorners
00026 DOUBLE PRECISION, DIMENSION(id_nbcorners, num_srch_cells), INTENT(in) ::
00027 srch_corner_lat, srch_corner_lon
00028 INTEGER, DIMENSION(num_srch_cells), INTENT(in) :: srch_add
00029
00030 logical, intent(in) ::
00031 lbegin,
00032 lrevers
00033
00034 DOUBLE PRECISION, intent(in) ::
00035 beglat, beglon,
00036 endlat, endlon
00037
00038 DOUBLE PRECISION, dimension(2), intent(inout) ::
00039 begseg
00040
00041
00042
00043
00044
00045
00046
00047 integer, intent(out) ::
00048 location
00049
00050
00051 logical, intent(out) ::
00052 lcoinc
00053
00054
00055 DOUBLE PRECISION, intent(out) ::
00056 intrsct_lat, intrsct_lon
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 CHARACTER(LEN=len_cvs_string), SAVE :: mycvs =
00087 '$Id: prismtrs_intersection.F90 2082 2009-10-21 13:31:19Z hanke $'
00088 integer :: n, next_n, cell, srch_corners
00089
00090 INTEGER :: next2_n, neg, pos
00091
00092 integer, save ::
00093 last_loc
00094
00095 logical ::
00096 loutside
00097
00098 logical, save ::
00099 lthresh = .false.
00100
00101 DOUBLE PRECISION ::
00102 lon1, lon2,
00103 lat1, lat2,
00104 grdlon1, grdlon2,
00105 grdlat1, grdlat2,
00106 vec1_lat, vec1_lon,
00107 vec2_lat, vec2_lon,
00108 cross_product,
00109 eps, offset,
00110 s1, s2, determ,
00111 mat1, mat2, mat3, mat4, rhs1, rhs2,
00112 rl_halfpi, rl_v2lonmpi2, rl_v2lonppi2
00113
00114 DOUBLE PRECISION, save ::
00115 intrsct_lat_off, intrsct_lon_off
00116
00117
00118 #ifdef DEBUGX
00119 INTEGER, PARAMETER :: nbr_tgt_cells = 13
00120 INTEGER, DIMENSION(nbr_tgt_cells) :: grid_tgt
00121 INTEGER :: ii
00122 DOUBLE PRECISION, PARAMETER :: dbl_rad2deg = 360.0/6.2831853
00123 #endif
00124
00125 #ifdef DEBUGX
00126 PRINT *, '| | | | | | | Enter PRISMTrs_intersection'
00127 call psmile_flushstd
00128 #endif
00129
00130
00131
00132
00133
00134 #ifdef DEBUGX
00135 grid_tgt(1)= 7215
00136 grid_tgt(2)= 7216
00137 grid_tgt(3)= 7251
00138 grid_tgt(4)= 7252
00139 grid_tgt(5)= 7253
00140 grid_tgt(6)= 7254
00141 grid_tgt(7)= 7279
00142 grid_tgt(8)= 7280
00143 grid_tgt(9)= 7281
00144 grid_tgt(10)= 7282
00145 grid_tgt(11)= 7290
00146 grid_tgt(12)= 7291
00147 grid_tgt(13)= 7292
00148 #endif
00149
00150 location = 0
00151 lcoinc = .false.
00152 intrsct_lat = endlat
00153 intrsct_lon = endlon
00154
00155 if (num_srch_cells == 0) return
00156
00157 if (beglat > north_thresh .or. beglat < south_thresh) then
00158
00159 if (lthresh) location = last_loc
00160 call prismtrs_pole_intersection(location, &
00161 intrsct_lat,intrsct_lon,lcoinc,lthresh, &
00162 beglat, beglon, endlat, endlon, begseg, lrevers, &
00163 num_srch_cells, id_nbcorners, &
00164 srch_corner_lat, srch_corner_lon, srch_add)
00165 if (lthresh) then
00166 last_loc = location
00167 intrsct_lat_off = intrsct_lat
00168 intrsct_lon_off = intrsct_lon
00169 endif
00170 return
00171
00172 endif
00173
00174 loutside = .false.
00175 if (lbegin) then
00176 lat1 = beglat
00177 lon1 = beglon
00178 else
00179 lat1 = intrsct_lat_off
00180 lon1 = intrsct_lon_off
00181 endif
00182 lat2 = endlat
00183 lon2 = endlon
00184 if ((lon2-lon1) > three*dble_pih) then
00185 lon2 = lon2 - dble_pi2
00186 else if ((lon2-lon1) < -three*dble_pih) then
00187 lon2 = lon2 + dble_pi2
00188 endif
00189 s1 = zero
00190
00191
00192
00193
00194
00195
00196
00197
00198 srch_corners = size(srch_corner_lat,DIM=1)
00199 srch_loop: do
00200
00201
00202
00203
00204
00205 if (lthresh) then
00206 do cell=1,num_srch_cells
00207 if (srch_add(cell) == last_loc) then
00208 location = last_loc
00209 eps = tiny
00210 exit srch_loop
00211 endif
00212 end do
00213 endif
00214
00215
00216
00217
00218
00219 cell_loop: DO cell=1,num_srch_cells
00220 corner_loop: do n=1,srch_corners
00221 next_n = MOD(n,srch_corners) + 1
00222
00223
00224
00225
00226
00227
00228
00229
00230 vec1_lat = srch_corner_lat(next_n,cell) - &
00231 srch_corner_lat(n ,cell)
00232 vec1_lon = srch_corner_lon(next_n,cell) - &
00233 srch_corner_lon(n ,cell)
00234 vec2_lat = lat1 - srch_corner_lat(n,cell)
00235 vec2_lon = lon1 - srch_corner_lon(n,cell)
00236
00237
00238
00239
00240
00241
00242 if (vec2_lat == 0 .and. vec2_lon == 0) then
00243 lat1 = lat1 + 1.d-10*(lat2-lat1)
00244 lon1 = lon1 + 1.d-10*(lon2-lon1)
00245 vec2_lat = lat1 - srch_corner_lat(n,cell)
00246 vec2_lon = lon1 - srch_corner_lon(n,cell)
00247 ENDIF
00248
00249
00250
00251
00252
00253 if (vec1_lon > dble_pi) then
00254 vec1_lon = vec1_lon - dble_pi2
00255 else if (vec1_lon < -dble_pi) then
00256 vec1_lon = vec1_lon + dble_pi2
00257 endif
00258 if (vec2_lon > dble_pi) then
00259 vec2_lon = vec2_lon - dble_pi2
00260 else if (vec2_lon < -dble_pi) then
00261 vec2_lon = vec2_lon + dble_pi2
00262 endif
00263
00264 cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 if (cross_product == zero) then
00280 if (vec1_lat /= zero .or. vec1_lon /= zero) then
00281 vec2_lat = lat2 - lat1
00282 vec2_lon = lon2 - lon1
00283
00284 if (vec2_lon > dble_pi) then
00285 vec2_lon = vec2_lon - dble_pi2
00286 else if (vec2_lon < -dble_pi) then
00287 vec2_lon = vec2_lon + dble_pi2
00288 endif
00289
00290 cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat
00291 else
00292 cross_product = one
00293 endif
00294
00295 if (cross_product == zero) then
00296 lcoinc = .true.
00297 cross_product = vec1_lon*vec2_lon + vec1_lat*vec2_lat
00298 if (lrevers) cross_product = -cross_product
00299 endif
00300 endif
00301
00302 #ifdef DEBUGX
00303 DO ii = 1,nbr_tgt_cells
00304 IF (srch_add(cell) == grid_tgt(ii) ) THEN
00305 WRITE(88,*) 'lrevers :',lrevers
00306 WRITE(88,1110) srch_add(cell),n,next_n
00307 WRITE(88,1111) dbl_rad2deg*lon1,dbl_rad2deg*lat1
00308 WRITE(88,1112) dbl_rad2deg*lon2,dbl_rad2deg*lat2
00309 WRITE(88,1113) cross_product
00310 ENDIF
00311 ENDDO
00312
00313 1110 FORMAT (' grid2 cell, corners = ', 2X, I6, 2X, I2, 2X, I2)
00314 1111 format (' lon1, lat1 = ', 2X, F12.4, 2X, F12.4)
00315 1112 format (' lon2, lat2 = ', 2X, F12.4, 2X, F12.4)
00316 1113 format (' cross_product = ', 2X, F12.6)
00317 #endif
00318
00319
00320
00321
00322
00323 if (cross_product < zero) exit corner_loop
00324 end do corner_loop
00325
00326
00327
00328
00329
00330 if (n > srch_corners) then
00331 location = srch_add(cell)
00332
00333
00334
00335
00336
00337
00338 if (loutside) then
00339
00340
00341 neg=0
00342 pos=0
00343 do n=1,srch_corners
00344 next_n = MOD(n,srch_corners) + 1
00345 next2_n = MOD(next_n,srch_corners) + 1
00346
00347 vec1_lat = srch_corner_lat(next_n,cell) - &
00348 srch_corner_lat(n,cell)
00349 vec1_lon = srch_corner_lon(next_n,cell) - &
00350 srch_corner_lon(n,cell)
00351 vec2_lat = srch_corner_lat(next2_n,cell) - &
00352 srch_corner_lat(next_n,cell)
00353 vec2_lon = srch_corner_lon(next2_n,cell) - &
00354 srch_corner_lon(next_n,cell)
00355
00356 if (vec1_lon > three*dble_pih) then
00357 vec1_lon = vec1_lon - dble_pi2
00358 else if (vec1_lon < -three*dble_pih) then
00359 vec1_lon = vec1_lon + dble_pi2
00360 endif
00361
00362 if (vec2_lon > three*dble_pih) then
00363 vec2_lon = vec2_lon - dble_pi2
00364 else if (vec2_lon < -three*dble_pih) then
00365 vec2_lon = vec2_lon + dble_pi2
00366 endif
00367
00368 cross_product= &
00369 vec1_lat*vec2_lon - vec2_lat*vec1_lon
00370
00371 if (cross_product < zero) then
00372 neg=neg+1
00373 else if (cross_product > zero) then
00374 pos=pos+1
00375 endif
00376 enddo
00377
00378
00379 if (neg/=0 .and. pos/=0) then
00380 loutside=.false.
00381 print*, 'The mesh ',srch_add(cell),' is non-convex'
00382 print*, 'srch_corner_lat=',srch_corner_lat(:,cell)
00383 print*, 'srch_corner_lon=',srch_corner_lon(:,cell)
00384 endif
00385 endif
00386 if (loutside) then
00387 lat2 = beglat
00388 lon2 = beglon
00389 location = 0
00390 eps = -tiny
00391 else
00392 eps = tiny
00393 endif
00394 exit srch_loop
00395 endif
00396
00397
00398
00399
00400 end do cell_loop
00401
00402
00403
00404
00405
00406
00407
00408 loutside = .true.
00409 s1 = s1 + baby
00410 lat1 = beglat + s1*(endlat - beglat)
00411 lon1 = beglon + s1*(lon2 - beglon)
00412
00413
00414
00415
00416
00417 if (s1 >= one) return
00418
00419 end do srch_loop
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 intrsct_loop: do n=1,srch_corners
00432 next_n = mod(n,srch_corners) + 1
00433
00434 grdlon1 = srch_corner_lon(n ,cell)
00435 grdlon2 = srch_corner_lon(next_n,cell)
00436 grdlat1 = srch_corner_lat(n ,cell)
00437 grdlat2 = srch_corner_lat(next_n,cell)
00438
00439
00440
00441
00442
00443 mat1 = lat2 - lat1
00444 mat2 = grdlat1 - grdlat2
00445 mat3 = lon2 - lon1
00446 mat4 = grdlon1 - grdlon2
00447 rhs1 = grdlat1 - lat1
00448 rhs2 = grdlon1 - lon1
00449
00450 if (mat3 > dble_pi) then
00451 mat3 = mat3 - dble_pi2
00452 else if (mat3 < -dble_pi) then
00453 mat3 = mat3 + dble_pi2
00454 endif
00455 if (mat4 > dble_pi) then
00456 mat4 = mat4 - dble_pi2
00457 else if (mat4 < -dble_pi) then
00458 mat4 = mat4 + dble_pi2
00459 endif
00460 if (rhs2 > dble_pi) then
00461 rhs2 = rhs2 - dble_pi2
00462 else if (rhs2 < -dble_pi) then
00463 rhs2 = rhs2 + dble_pi2
00464 endif
00465
00466 determ = mat1*mat4 - mat2*mat3
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 if (abs(determ) > 1.e-30) then
00481
00482 s1 = (rhs1*mat4 - mat2*rhs2)/determ
00483 s2 = (mat1*rhs2 - rhs1*mat3)/determ
00484
00485 if (s2 >= zero .and. s2 <= one .and. &
00486 s1 > zero .and. s1 <= one) then
00487
00488
00489
00490
00491
00492
00493 if (.not. loutside) then
00494 mat1 = lat2 - begseg(1)
00495 mat3 = lon2 - begseg(2)
00496 rhs1 = grdlat1 - begseg(1)
00497 rhs2 = grdlon1 - begseg(2)
00498 else
00499 mat1 = begseg(1) - endlat
00500 mat3 = begseg(2) - endlon
00501 rhs1 = grdlat1 - endlat
00502 rhs2 = grdlon1 - endlon
00503 endif
00504
00505 if (mat3 > dble_pi) then
00506 mat3 = mat3 - dble_pi2
00507 else if (mat3 < -dble_pi) then
00508 mat3 = mat3 + dble_pi2
00509 endif
00510 if (rhs2 > dble_pi) then
00511 rhs2 = rhs2 - dble_pi2
00512 else if (rhs2 < -dble_pi) then
00513 rhs2 = rhs2 + dble_pi2
00514 endif
00515
00516 determ = mat1*mat4 - mat2*mat3
00517
00518
00519
00520
00521
00522
00523
00524
00525 if (determ /= zero) then
00526 s1 = (rhs1*mat4 - mat2*rhs2)/determ
00527 s2 = (mat1*rhs2 - rhs1*mat3)/determ
00528
00529 offset = s1 + eps/determ
00530 if (offset > one) offset = one
00531
00532 if (.not. loutside) then
00533 intrsct_lat = begseg(1) + mat1*s1
00534 intrsct_lon = begseg(2) + mat3*s1
00535 intrsct_lat_off = begseg(1) + mat1*offset
00536 intrsct_lon_off = begseg(2) + mat3*offset
00537 else
00538 intrsct_lat = endlat + mat1*s1
00539 intrsct_lon = endlon + mat3*s1
00540 intrsct_lat_off = endlat + mat1*offset
00541 intrsct_lon_off = endlon + mat3*offset
00542 endif
00543 exit intrsct_loop
00544 endif
00545
00546 endif
00547 endif
00548
00549
00550
00551
00552
00553 end do intrsct_loop
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 if (lthresh) then
00566 if (intrsct_lat < north_thresh .or. intrsct_lat > south_thresh) &
00567 lthresh = .false.
00568 else if (lat1 > zero .and. intrsct_lat > north_thresh) then
00569 intrsct_lat = north_thresh + tiny
00570 intrsct_lat_off = north_thresh + eps*mat1
00571 s1 = (intrsct_lat - begseg(1))/mat1
00572 intrsct_lon = begseg(2) + s1*mat3
00573 intrsct_lon_off = begseg(2) + (s1+eps)*mat3
00574 last_loc = location
00575 lthresh = .true.
00576 else if (lat1 < zero .and. intrsct_lat < south_thresh) then
00577 intrsct_lat = south_thresh - tiny
00578 intrsct_lat_off = south_thresh + eps*mat1
00579 s1 = (intrsct_lat - begseg(1))/mat1
00580 intrsct_lon = begseg(2) + s1*mat3
00581 intrsct_lon_off = begseg(2) + (s1+eps)*mat3
00582 last_loc = location
00583 lthresh = .true.
00584 endif
00585
00586 #ifdef DEBUGX
00587 PRINT *, '| | | | | | | Quit PRISMTrs_intersection'
00588 call psmile_flushstd
00589 #endif
00590
00591
00592
00593 end subroutine prismtrs_intersection
00594
00595