21 #include <fms_platform.h> 82 #include<file_version.h> 140 REAL, _allocatable,
DIMENSION(:,:) :: glo_lat, glo_lon
141 REAL, _allocatable,
DIMENSION(:,:) :: aglo_lat, aglo_lon
142 INTEGER :: myxbegin, myybegin
143 INTEGER :: dimi, dimj
144 INTEGER :: adimi, adimj
145 INTEGER :: tile_number
147 INTEGER :: pestart, peend
148 CHARACTER(len=128) :: grid_type
228 SUBROUTINE diag_grid_init(domain, glo_lat, glo_lon, aglo_lat, aglo_lon)
230 REAL,
INTENT(in),
DIMENSION(:,:) :: glo_lat, glo_lon
231 REAL,
INTENT(in),
DIMENSION(:,:) :: aglo_lat, aglo_lon
233 INTEGER,
DIMENSION(1) :: tile
236 INTEGER :: i_dim, j_dim
237 INTEGER :: ai_dim, aj_dim
238 INTEGER,
DIMENSION(2) :: latdim, londim
239 INTEGER,
DIMENSION(2) :: alatdim, alondim
240 INTEGER :: mype, npes, npespertile
241 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: xbegin, xend, ybegin, yend
244 CALL write_version_number(
"DIAG_GRID_MOD", version)
248 IF (
ALLOCATED(xbegin) )
DEALLOCATE(xbegin)
249 IF (
ALLOCATED(ybegin) )
DEALLOCATE(ybegin)
250 IF (
ALLOCATED(xend) )
DEALLOCATE(xend)
251 IF (
ALLOCATED(yend) )
DEALLOCATE(yend)
254 mype = mpp_pe() -mpp_root_pe() + 1
258 ALLOCATE(xbegin(npes), &
261 & yend(npes), stat=stat)
262 IF ( stat .NE. 0 )
THEN 263 CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
264 &
'Could not allocate memory for the compute grid indices& 269 ntiles = mpp_get_ntile_count(domain)
270 tile = mpp_get_tile_id(domain)
273 npespertile = npes / ntiles
279 & xbegin=xbegin, xend=xend,&
280 & ybegin=ybegin, yend=yend)
286 latdim = shape(glo_lat)
287 londim = shape(glo_lon)
288 IF ( (latdim(1) == londim(1)) .AND.&
289 &(latdim(2) == londim(2)) )
THEN 293 CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
294 &
'glo_lat and glo_lon must be the same shape.', fatal)
298 alatdim = shape(aglo_lat)
299 alondim = shape(aglo_lon)
300 IF ( (alatdim(1) == alondim(1)) .AND. &
301 &(alatdim(2) == alondim(2)) )
THEN 302 IF ( tile(1) == 4 .OR. tile(1) == 5 )
THEN 311 CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
312 &
"a-grid's glo_lat and glo_lon must be the same shape.", fatal)
318 IF ( mpp_pe() == mpp_root_pe() ) &
319 &
CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
320 &
'The global grid has already been initialized', warning)
324 IF ( stat .NE. 0 )
THEN 325 CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
326 &
'Could not allocate memory for the global grid.', fatal)
333 IF ( mpp_pe() == mpp_root_pe() ) &
334 &
CALL error_mesg(
'diag_grid_mod::diag_grid_init',&
335 &
'The global a-grid has already been initialized', warning)
339 IF ( stat .NE. 0 )
THEN 340 CALL error_mesg(
'diag_global_mod::diag_grid_init',&
341 &
'Could not allocate memory for the global a-grid', fatal)
349 IF ( tile(1) == 4 .OR. tile(1) == 5 )
THEN 405 ELSE IF ( mpp_pe() == mpp_root_pe() )
THEN 406 CALL error_mesg(
'diag_grid_mod::diag_grid_end',&
407 &
'diag_global_grid%glo_lat was not allocated.', warning)
412 ELSE IF ( mpp_pe() == mpp_root_pe() )
THEN 413 CALL error_mesg(
'diag_grid_mod::diag_grid_end',&
414 &
'diag_global_grid%glo_lon was not allocated.', warning)
419 ELSE IF ( mpp_pe() == mpp_root_pe() )
THEN 420 CALL error_mesg(
'diag_grid_mod::diag_grid_end',&
421 &
'diag_global_grid%aglo_lat was not allocated.', warning)
426 ELSE IF ( mpp_pe() == mpp_root_pe() )
THEN 427 CALL error_mesg(
'diag_grid_mod::diag_grid_end',&
428 &
'diag_global_grid%aglo_lon was not allocated.', warning)
478 & istart, iend, jstart, jend)
479 REAL,
INTENT(in) :: latstart, lonstart
480 REAL,
INTENT(in) :: latend, lonend
481 INTEGER,
INTENT(out) :: istart, jstart
482 INTEGER,
INTENT(out) :: iend, jend
484 REAL,
ALLOCATABLE,
DIMENSION(:,:) :: delta_lat, delta_lon, grid_lon
486 REAL,
DIMENSION(4) :: dists_lon, dists_lat
487 REAL :: lonendadj, my_lonstart, my_lonend
489 INTEGER,
ALLOCATABLE,
DIMENSION(:,:) :: ijmin, ijmax
490 INTEGER :: mytile, ntiles, i, j, k, dimi, dimj, istat
498 REAL :: minimum_distance
499 REAL :: global_min_distance
503 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
504 &
'Module not initialized, first initialze module with a call & 505 &to diag_grid_init', fatal)
508 if ( lonstart < 0. )
then 509 my_lonstart = lonstart + 360.
511 my_lonstart = lonstart
513 if ( lonend < 0. )
then 514 my_lonend = lonend + 360.
519 IF (latstart .EQ. latend .AND. my_lonstart .EQ. my_lonend)
THEN 527 allocate(ijmin(ntiles,2))
539 global_min_distance = minimum_distance
540 CALL mpp_min(global_min_distance)
544 IF (global_min_distance .EQ. minimum_distance)
THEN 552 IF (rank_buf .EQ. -1)
THEN 554 "No rank has minimum distance.", &
558 IF (rank_buf .EQ. mpp_pe())
THEN 568 istart = ijmin(mytile,1)
569 jstart = ijmin(mytile,2)
580 ALLOCATE(ijmin(ntiles,2), stat=istat)
582 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
583 &
'Cannot allocate ijMin index array', fatal)
584 ALLOCATE(ijmax(ntiles,2), stat=istat)
586 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
587 &
'Cannot allocate ijMax index array', fatal)
598 ALLOCATE(delta_lat(dimi,dimj), stat=istat)
600 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
601 &
'Cannot allocate latitude delta array', fatal)
602 ALLOCATE(delta_lon(dimi,dimj), stat=istat)
604 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
605 &
'Cannot allocate longitude delta array', fatal)
634 IF ( dists_lon(k) > 180.0 )
THEN 635 dists_lon(k) = 360.0 - dists_lon(k)
638 delta_lon(i,j) = sum(dists_lon)/
real(count)
639 delta_lat(i,j) = sum(dists_lat)/
real(count)
647 ALLOCATE(grid_lon(dimi,dimj), stat=istat)
649 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes',&
650 &
'Cannot allocate temporary longitude array', fatal)
654 IF ( my_lonstart > my_lonend )
THEN 655 WHERE ( grid_lon < my_lonstart )
656 grid_lon = grid_lon + 360.0
658 lonendadj = my_lonend + 360.0
660 lonendadj = my_lonend
669 IF ( (abs(latstart)-delta_lat(i,j) <= 90.0 .AND.&
670 & 90.0 <= abs(latend)+delta_lat(i,j)) .AND.&
673 ELSE IF ( (my_lonstart-delta_lon(i,j) <= grid_lon(i,j) .AND.&
674 & grid_lon(i,j) < lonendadj+delta_lon(i,j)) )
THEN 688 DEALLOCATE(delta_lon)
689 DEALLOCATE(delta_lat)
700 IF ( ijmin(mytile,1) == huge(1) .OR. ijmax(mytile,1) == -huge(1) )
THEN 704 IF ( ijmin(mytile,2) == huge(1) .OR. ijmax(mytile,2) == -huge(1) )
THEN 709 istart = ijmin(mytile,1)
710 jstart = ijmin(mytile,2)
711 iend = ijmax(mytile,1)
712 jend = ijmax(mytile,2)
748 REAL,
INTENT(in) :: lat, lon
749 INTEGER,
INTENT(out) :: iindex, jindex
751 INTEGER :: indexes(2)
754 &
CALL error_mesg(
'diag_grid_mod::get_local_indexes2',&
755 &
'Module not initialized, first initialze module with a call & 756 &to diag_grid_init', fatal)
801 PURE ELEMENTAL REAL FUNCTION rad2deg(angle)
802 REAL,
INTENT(in) :: angle
825 PURE ELEMENTAL REAL FUNCTION deg2rad(angle)
826 REAL,
INTENT(in) :: angle
858 REAL,
INTENT(in) :: lat, lon
860 INTEGER :: indxi, indxj
861 INTEGER :: dimi, dimj
863 INTEGER :: nearestcorner
864 INTEGER,
DIMENSION(4,2) :: ijarray
867 REAL,
DIMENSION(4) :: pntdistances
868 TYPE(
point) :: origpt
869 REAL,
DIMENSION(4,2) :: cornerpts
870 TYPE(
point),
DIMENSION(9) :: points
871 REAL,
DIMENSION(9) :: distsqrd
881 IF ( lat == 90.0 )
THEN 883 ELSE IF ( lat == -90.0 )
THEN 892 iloop:
DO i=0, dimi-2
893 jloop:
DO j = 0, dimj-2
898 & (/ 4, 2 /), order=(/2,1/) )
900 maxctrdist =
max(
gcirdistance(cornerpts(1,1),cornerpts(1,2), cornerpts(2,1),cornerpts(2,2)),&
901 &
gcirdistance(cornerpts(3,1),cornerpts(3,2), cornerpts(4,1),cornerpts(4,2)))
904 pntdistances =
gcirdistance(cornerpts(:,1),cornerpts(:,2), llat,llon)
906 IF ( (minval(pntdistances) <= maxctrdist) .AND. (i*j.NE.0) )
THEN 908 ijarray = reshape( (/ i, j, i+1, j+1, i+1, j, i, j+1 /), (/ 4, 2 /), order=(/2,1/) )
911 nearestcorner = minloc(pntdistances,1)
913 indxi = ijarray(nearestcorner,1)
914 indxj = ijarray(nearestcorner,2)
923 valid:
IF ( (indxi <= 0 .OR. dimi-1 <= indxi) .OR. &
924 & (indxj <= 0 .OR. dimj-1 <= indxj) )
THEN 970 SELECT CASE (minloc(distsqrd,1))
1035 REAL,
INTENT(in) :: lat, lon
1037 INTEGER :: indxi, indxj
1038 INTEGER :: indxi_tmp
1039 INTEGER :: dimi, dimj
1041 INTEGER :: jstart, jend, nextj
1042 TYPE(
point) :: origpt
1043 TYPE(
point),
DIMENSION(4) :: points
1044 REAL,
DIMENSION(4) :: distsqrd
1067 iloop:
DO i=0, dimi-2
1084 IF ( indxi > 0 )
THEN 1085 jloop:
DO j=jstart, jend, nextj
1095 valid:
IF ( (indxi <= 0 .OR. dimi-1 < indxi) .OR. &
1096 & (indxj <= 0 .OR. dimj-1 < indxj) )
THEN 1114 points(i)%x = 1.0e20
1115 points(i)%y = 1.0e20
1116 points(i)%z = 1.0e20
1135 SELECT CASE (minloc(distsqrd,1))
1141 indxj = indxj+nextj;
1144 indxj = indxj+nextj;
1196 REAL,
INTENT(in) :: lat, lon
1238 & (pt1%y-pt2%y)**2 +&
1259 PURE ELEMENTAL REAL FUNCTION gcirdistance(lat1, lon1, lat2, lon2)
1260 REAL,
INTENT(in) :: lat1, lat2, lon1, lon2
1262 REAL :: theta1, theta2
1268 deltalambda =
deg2rad(lon2-lon1)
1269 deltatheta =
deg2rad(lat2-lat1)
1271 gcirdistance = radius * 2. * asin(sqrt((sin(deltatheta/2.))**2 + cos(theta1)*cos(theta2)*(sin(deltalambda/2.))**2))
1284 REAL,
INTENT(IN) :: lat
1285 REAL,
INTENT(IN) :: lon
1286 INTEGER,
INTENT(OUT) :: minI
1287 INTEGER,
INTENT(OUT) :: minJ
1288 REAL,
INTENT(OUT) :: minimum_distance
1299 IF (lat .EQ. 90.0)
THEN 1301 ELSEIF (lat .EQ. -90.0)
THEN 1314 minimum_distance = 2.0*radius*3.141592653
1321 IF (dist .LT. minimum_distance)
THEN 1336 minimum_distance = dist
1342 IF (mini .EQ. 0 .OR. minj .EQ. 0)
THEN 1343 call error_mesg(
"find_nearest_agrid_index", &
1344 "A minimum distance was not found.", &
real, parameter, public radius
Radius of the Earth [m].
real, parameter, public rad_to_deg
Degrees per radian [deg/rad].
type(diag_global_grid_type) diag_global_grid
pure integer function, dimension(2) find_equator_index_agrid(lat, lon)
subroutine, public diag_grid_init(domain, glo_lat, glo_lon, aglo_lat, aglo_lon)
subroutine, public get_local_indexes(latStart, latEnd, lonStart, lonEnd, istart, iend, jstart, jend)
pure elemental real function rad2deg(angle)
subroutine, public diag_grid_end()
pure elemental type(point) function latlon2xyz(lat, lon)
logical diag_grid_initialized
real, parameter, public deg_to_rad
Radians per degree [rad/deg].
subroutine find_nearest_agrid_index(lat, lon, minI, minJ, minimum_distance)
pure elemental real function distancesqrd(pt1, pt2)
pure elemental real function deg2rad(angle)
subroutine, public error_mesg(routine, message, level)
pure elemental real function gcirdistance(lat1, lon1, lat2, lon2)
pure integer function, dimension(2) find_pole_index_agrid(lat, lon)
subroutine, public get_local_indexes2(lat, lon, iindex, jindex)