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)