2025-09-05 09:42:21 +02:00

843 lines
30 KiB
Fortran

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
! This module reads in and initializes two grids for remapping.
! NOTE: grid1 must be the master grid -- the grid that determines
! which cells participate (e.g. land mask) and the fractional
! area of grid2 cells that participate in the remapping.
!
!-----------------------------------------------------------------------
!
! CVS:$Id: grids.f,v 1.6 2001/08/21 21:06:41 pwjones Exp $
!
! Copyright (c) 1997, 1998 the Regents of the University of
! California.
!
! This software and ancillary information (herein called software)
! called SCRIP is made available under the terms described here.
! The software has been approved for release with associated
! LA-CC Number 98-45.
!
! Unless otherwise indicated, this software has been authored
! by an employee or employees of the University of California,
! operator of the Los Alamos National Laboratory under Contract
! No. W-7405-ENG-36 with the U.S. Department of Energy. The U.S.
! Government has rights to use, reproduce, and distribute this
! software. The public may copy and use this software without
! charge, provided that this Notice and any statement of authorship
! are reproduced on all copies. Neither the Government nor the
! University makes any warranty, express or implied, or assumes
! any liability or responsibility for the use of this software.
!
! If software is modified to produce derivative works, such modified
! software should be clearly marked, so as not to confuse it with
! the version available from Los Alamos National Laboratory.
!
!***********************************************************************
module grids
!-----------------------------------------------------------------------
use kinds_mod ! defines data types
use constants ! common constants
use iounits ! I/O unit manager
use netcdf_mod ! netCDF stuff
implicit none
!-----------------------------------------------------------------------
!
! variables that describe each grid
!
!-----------------------------------------------------------------------
integer (kind=int_kind), save :: &
grid1_size, grid2_size, & ! total points on each grid
grid1_rank, grid2_rank, & ! rank of each grid
grid1_corners, grid2_corners ! number of corners
! for each grid cell
integer (kind=int_kind), dimension(:), allocatable, save :: &
grid1_dims, grid2_dims ! size of each grid dimension
character(char_len), save :: &
grid1_name, grid2_name ! name for each grid
character (char_len), save :: &
grid1_units, & ! units for grid coords (degs/radians)
grid2_units ! units for grid coords
real (kind=dbl_kind), parameter :: &
deg2rad = pi/180. ! conversion for deg to rads
!-----------------------------------------------------------------------
!
! grid coordinates and masks
!
!-----------------------------------------------------------------------
logical (kind=log_kind), dimension(:), allocatable, save :: &
grid1_mask, & ! flag which cells participate
grid2_mask ! flag which cells participate
real (kind=dbl_kind), dimension(:), allocatable, save :: &
grid1_center_lat, & ! lat/lon coordinates for
grid1_center_lon, & ! each grid center in radians
grid2_center_lat, &
grid2_center_lon, &
grid1_area, & ! tot area of each grid1 cell
grid2_area, & ! tot area of each grid2 cell
grid1_area_in, & ! area of grid1 cell from file
grid2_area_in, & ! area of grid2 cell from file
grid1_frac, & ! fractional area of grid cells
grid2_frac ! participating in remapping
real (kind=dbl_kind), dimension(:,:), allocatable, save :: &
grid1_corner_lat, & ! lat/lon coordinates for
grid1_corner_lon, & ! each grid corner in radians
grid2_corner_lat, &
grid2_corner_lon
logical (kind=log_kind), save :: &
luse_grid_centers & ! use centers for bounding boxes
, luse_grid1_area & ! use area from grid file
, luse_grid2_area ! use area from grid file
real (kind=dbl_kind), dimension(:,:), allocatable, save :: &
grid1_bound_box, & ! lat/lon bounding box for use
grid2_bound_box ! in restricting grid searches
!-----------------------------------------------------------------------
!
! bins for restricting searches
!
!-----------------------------------------------------------------------
character (char_len), save :: &
restrict_type ! type of bins to use
integer (kind=int_kind), save :: &
num_srch_bins ! num of bins for restricted srch
integer (kind=int_kind), dimension(:,:), allocatable, save :: &
bin_addr1, & ! min,max adds for grid1 cells in this lat bin
bin_addr2 ! min,max adds for grid2 cells in this lat bin
real(kind=dbl_kind), dimension(:,:), allocatable, save :: &
bin_lats & ! min,max latitude for each search bin
, bin_lons ! min,max longitude for each search bin
!***********************************************************************
contains
!***********************************************************************
subroutine grid_init(grid1_file, grid2_file)
!-----------------------------------------------------------------------
!
! this routine reads grid info from grid files and makes any
! necessary changes (e.g. for 0,2pi longitude range)
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
!
! input variables
!
!-----------------------------------------------------------------------
character(char_len), intent(in) :: &
grid1_file, grid2_file ! grid data files
!-----------------------------------------------------------------------
!
! local variables
!
!-----------------------------------------------------------------------
integer (kind=int_kind) :: &
n & ! loop counter
, nele & ! element loop counter
, iunit & ! unit number for opening files
, i,j & ! logical 2d addresses
, ip1,jp1 &
, n_add, e_add, ne_add &
, nx, ny
integer (kind=int_kind) :: &
ncstat, & ! netCDF status variable
nc_grid1_id, & ! netCDF grid file id
nc_grid2_id, & ! netCDF grid file id
nc_grid1size_id, & ! netCDF grid size dim id
nc_grid2size_id, & ! netCDF grid size dim id
nc_grid1corn_id, & ! netCDF grid corner dim id
nc_grid2corn_id, & ! netCDF grid corner dim id
nc_grid1rank_id, & ! netCDF grid rank dim id
nc_grid2rank_id, & ! netCDF grid rank dim id
nc_grid1area_id, & ! netCDF grid rank dim id
nc_grid2area_id, & ! netCDF grid rank dim id
nc_grid1dims_id, & ! netCDF grid dimension size id
nc_grid2dims_id, & ! netCDF grid dimension size id
nc_grd1imask_id, & ! netCDF grid imask var id
nc_grd2imask_id, & ! netCDF grid imask var id
nc_grd1crnrlat_id, & ! netCDF grid corner lat var id
nc_grd2crnrlat_id, & ! netCDF grid corner lat var id
nc_grd1crnrlon_id, & ! netCDF grid corner lon var id
nc_grd2crnrlon_id, & ! netCDF grid corner lon var id
nc_grd1cntrlat_id, & ! netCDF grid center lat var id
nc_grd2cntrlat_id, & ! netCDF grid center lat var id
nc_grd1cntrlon_id, & ! netCDF grid center lon var id
nc_grd2cntrlon_id ! netCDF grid center lon var id
integer (kind=int_kind), dimension(:), allocatable :: &
imask ! integer mask read from file
real (kind=dbl_kind) :: &
dlat,dlon ! lat/lon intervals for search bins
real (kind=dbl_kind), dimension(4) :: &
tmp_lats, tmp_lons ! temps for computing bounding boxes
!-----------------------------------------------------------------------
!
! open grid files and read grid size/name data
!
!-----------------------------------------------------------------------
ncstat = nf_open(grid1_file, NF_NOWRITE, nc_grid1_id)
call netcdf_error_handler(ncstat)
ncstat = nf_open(grid2_file, NF_NOWRITE, nc_grid2_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid1_id, 'grid_size', nc_grid1size_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid1_id, nc_grid1size_id, grid1_size)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid2_id, 'grid_size', nc_grid2size_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid2_id, nc_grid2size_id, grid2_size)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid1_id, 'grid_rank', nc_grid1rank_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid1_id, nc_grid1rank_id, grid1_rank)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid2_id, 'grid_rank', nc_grid2rank_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid2_id, nc_grid2rank_id, grid2_rank)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid1_id,'grid_corners',nc_grid1corn_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid1_id,nc_grid1corn_id,grid1_corners)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimid(nc_grid2_id,'grid_corners',nc_grid2corn_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_dimlen(nc_grid2_id,nc_grid2corn_id,grid2_corners)
call netcdf_error_handler(ncstat)
allocate( grid1_dims(grid1_rank), &
grid2_dims(grid2_rank))
ncstat = nf_get_att_text(nc_grid1_id, nf_global, 'title', &
grid1_name)
call netcdf_error_handler(ncstat)
ncstat = nf_get_att_text(nc_grid2_id, nf_global, 'title', &
grid2_name)
call netcdf_error_handler(ncstat)
!-----------------------------------------------------------------------
!
! allocate grid coordinates/masks and read data
!
!-----------------------------------------------------------------------
allocate( grid1_mask (grid1_size), &
grid2_mask (grid2_size), &
grid1_center_lat(grid1_size), &
grid1_center_lon(grid1_size), &
grid2_center_lat(grid2_size), &
grid2_center_lon(grid2_size), &
grid1_area (grid1_size), &
grid2_area (grid2_size), &
grid1_frac (grid1_size), &
grid2_frac (grid2_size), &
grid1_corner_lat(grid1_corners, grid1_size), &
grid1_corner_lon(grid1_corners, grid1_size), &
grid2_corner_lat(grid2_corners, grid2_size), &
grid2_corner_lon(grid2_corners, grid2_size), &
grid1_bound_box (4 , grid1_size), &
grid2_bound_box (4 , grid2_size))
allocate(imask(grid1_size))
ncstat = nf_inq_varid(nc_grid1_id, 'grid_dims', nc_grid1dims_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid1_id, 'grid_imask', nc_grd1imask_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid1_id, 'grid_center_lat', &
nc_grd1cntrlat_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid1_id, 'grid_center_lon', &
nc_grd1cntrlon_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid1_id, 'grid_corner_lat', &
nc_grd1crnrlat_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid1_id, 'grid_corner_lon', &
nc_grd1crnrlon_id)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_int(nc_grid1_id, nc_grid1dims_id, grid1_dims)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_int(nc_grid1_id, nc_grd1imask_id, imask)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid1_id, nc_grd1cntrlat_id, &
grid1_center_lat)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid1_id, nc_grd1cntrlon_id, &
grid1_center_lon)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid1_id, nc_grd1crnrlat_id, &
grid1_corner_lat)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid1_id, nc_grd1crnrlon_id, &
grid1_corner_lon)
call netcdf_error_handler(ncstat)
if (luse_grid1_area) then
allocate (grid1_area_in(grid1_size))
ncstat = nf_inq_varid(nc_grid1_id, 'grid_area', nc_grid1area_id)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid1_id, nc_grid1area_id, &
grid1_area_in)
call netcdf_error_handler(ncstat)
endif
grid1_area = zero
grid1_frac = zero
!-----------------------------------------------------------------------
!
! initialize logical mask and convert lat/lon units if required
!
!-----------------------------------------------------------------------
where (imask == 1)
grid1_mask = .true.
elsewhere
grid1_mask = .false.
endwhere
deallocate(imask)
grid1_units = ' '
ncstat = nf_get_att_text(nc_grid1_id, nc_grd1cntrlat_id, 'units', &
grid1_units)
call netcdf_error_handler(ncstat)
select case (grid1_units(1:7))
case ('degrees')
grid1_center_lat = grid1_center_lat*deg2rad
grid1_center_lon = grid1_center_lon*deg2rad
case ('radians')
!*** no conversion necessary
case default
print *,'unknown units supplied for grid1 center lat/lon: '
print *,'proceeding assuming radians'
end select
grid1_units = ' '
ncstat = nf_get_att_text(nc_grid1_id, nc_grd1crnrlat_id, 'units', &
grid1_units)
call netcdf_error_handler(ncstat)
select case (grid1_units(1:7))
case ('degrees')
grid1_corner_lat = grid1_corner_lat*deg2rad
grid1_corner_lon = grid1_corner_lon*deg2rad
case ('radians')
!*** no conversion necessary
case default
print *,'unknown units supplied for grid1 corner lat/lon: '
print *,'proceeding assuming radians'
end select
ncstat = nf_close(nc_grid1_id)
call netcdf_error_handler(ncstat)
!-----------------------------------------------------------------------
!
! read data for grid 2
!
!-----------------------------------------------------------------------
allocate(imask(grid2_size))
ncstat = nf_inq_varid(nc_grid2_id, 'grid_dims', nc_grid2dims_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid2_id, 'grid_imask', nc_grd2imask_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid2_id, 'grid_center_lat', &
nc_grd2cntrlat_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid2_id, 'grid_center_lon', &
nc_grd2cntrlon_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid2_id, 'grid_corner_lat', &
nc_grd2crnrlat_id)
call netcdf_error_handler(ncstat)
ncstat = nf_inq_varid(nc_grid2_id, 'grid_corner_lon', &
nc_grd2crnrlon_id)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_int(nc_grid2_id, nc_grid2dims_id, grid2_dims)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_int(nc_grid2_id, nc_grd2imask_id, imask)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid2_id, nc_grd2cntrlat_id, &
grid2_center_lat)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid2_id, nc_grd2cntrlon_id, &
grid2_center_lon)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid2_id, nc_grd2crnrlat_id, &
grid2_corner_lat)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid2_id, nc_grd2crnrlon_id, &
grid2_corner_lon)
call netcdf_error_handler(ncstat)
if (luse_grid2_area) then
allocate (grid2_area_in(grid2_size))
ncstat = nf_inq_varid(nc_grid2_id, 'grid_area', nc_grid2area_id)
call netcdf_error_handler(ncstat)
ncstat = nf_get_var_double(nc_grid2_id, nc_grid2area_id, &
grid2_area_in)
call netcdf_error_handler(ncstat)
endif
grid2_area = zero
grid2_frac = zero
!-----------------------------------------------------------------------
!
! initialize logical mask and convert lat/lon units if required
!
!-----------------------------------------------------------------------
where (imask == 1)
grid2_mask = .true.
elsewhere
grid2_mask = .false.
endwhere
deallocate(imask)
grid2_units = ' '
ncstat = nf_get_att_text(nc_grid2_id, nc_grd2cntrlat_id, 'units', &
grid2_units)
call netcdf_error_handler(ncstat)
select case (grid2_units(1:7))
case ('degrees')
grid2_center_lat = grid2_center_lat*deg2rad
grid2_center_lon = grid2_center_lon*deg2rad
case ('radians')
!*** no conversion necessary
case default
print *,'unknown units supplied for grid2 center lat/lon: '
print *,'proceeding assuming radians'
end select
grid2_units = ' '
ncstat = nf_get_att_text(nc_grid2_id, nc_grd2crnrlat_id, 'units', &
grid2_units)
call netcdf_error_handler(ncstat)
select case (grid2_units(1:7))
case ('degrees')
grid2_corner_lat = grid2_corner_lat*deg2rad
grid2_corner_lon = grid2_corner_lon*deg2rad
case ('radians')
!*** no conversion necessary
case default
print *,'no units supplied for grid2 corner lat/lon: '
print *,'proceeding assuming radians'
end select
ncstat = nf_close(nc_grid2_id)
call netcdf_error_handler(ncstat)
!-----------------------------------------------------------------------
!
! convert longitudes to 0,2pi interval
!
!-----------------------------------------------------------------------
where (grid1_center_lon .gt. pi2) grid1_center_lon = &
grid1_center_lon - pi2
where (grid1_center_lon .lt. zero) grid1_center_lon = &
grid1_center_lon + pi2
where (grid2_center_lon .gt. pi2) grid2_center_lon = &
grid2_center_lon - pi2
where (grid2_center_lon .lt. zero) grid2_center_lon = &
grid2_center_lon + pi2
where (grid1_corner_lon .gt. pi2) grid1_corner_lon = &
grid1_corner_lon - pi2
where (grid1_corner_lon .lt. zero) grid1_corner_lon = &
grid1_corner_lon + pi2
where (grid2_corner_lon .gt. pi2) grid2_corner_lon = &
grid2_corner_lon - pi2
where (grid2_corner_lon .lt. zero) grid2_corner_lon = &
grid2_corner_lon + pi2
!-----------------------------------------------------------------------
!
! make sure input latitude range is within the machine values
! for +/- pi/2
!
!-----------------------------------------------------------------------
where (grid1_center_lat > pih) grid1_center_lat = pih
where (grid1_corner_lat > pih) grid1_corner_lat = pih
where (grid1_center_lat < -pih) grid1_center_lat = -pih
where (grid1_corner_lat < -pih) grid1_corner_lat = -pih
where (grid2_center_lat > pih) grid2_center_lat = pih
where (grid2_corner_lat > pih) grid2_corner_lat = pih
where (grid2_center_lat < -pih) grid2_center_lat = -pih
where (grid2_corner_lat < -pih) grid2_corner_lat = -pih
!-----------------------------------------------------------------------
!
! compute bounding boxes for restricting future grid searches
!
!-----------------------------------------------------------------------
if (.not. luse_grid_centers) then
grid1_bound_box(1,:) = minval(grid1_corner_lat, DIM=1)
grid1_bound_box(2,:) = maxval(grid1_corner_lat, DIM=1)
grid1_bound_box(3,:) = minval(grid1_corner_lon, DIM=1)
grid1_bound_box(4,:) = maxval(grid1_corner_lon, DIM=1)
grid2_bound_box(1,:) = minval(grid2_corner_lat, DIM=1)
grid2_bound_box(2,:) = maxval(grid2_corner_lat, DIM=1)
grid2_bound_box(3,:) = minval(grid2_corner_lon, DIM=1)
grid2_bound_box(4,:) = maxval(grid2_corner_lon, DIM=1)
else
nx = grid1_dims(1)
ny = grid1_dims(2)
do n=1,grid1_size
!*** find N,S and NE points to this grid point
j = (n - 1)/nx +1
i = n - (j-1)*nx
if (i < nx) then
ip1 = i + 1
else
!*** assume cyclic
ip1 = 1
!*** but if it is not, correct
e_add = (j - 1)*nx + ip1
if (abs(grid1_center_lat(e_add) - &
grid1_center_lat(n )) > pih) then
ip1 = i
endif
endif
if (j < ny) then
jp1 = j+1
else
!*** assume cyclic
jp1 = 1
!*** but if it is not, correct
n_add = (jp1 - 1)*nx + i
if (abs(grid1_center_lat(n_add) - &
grid1_center_lat(n )) > pih) then
jp1 = j
endif
endif
n_add = (jp1 - 1)*nx + i
e_add = (j - 1)*nx + ip1
ne_add = (jp1 - 1)*nx + ip1
!*** find N,S and NE lat/lon coords and check bounding box
tmp_lats(1) = grid1_center_lat(n)
tmp_lats(2) = grid1_center_lat(e_add)
tmp_lats(3) = grid1_center_lat(ne_add)
tmp_lats(4) = grid1_center_lat(n_add)
tmp_lons(1) = grid1_center_lon(n)
tmp_lons(2) = grid1_center_lon(e_add)
tmp_lons(3) = grid1_center_lon(ne_add)
tmp_lons(4) = grid1_center_lon(n_add)
grid1_bound_box(1,n) = minval(tmp_lats)
grid1_bound_box(2,n) = maxval(tmp_lats)
grid1_bound_box(3,n) = minval(tmp_lons)
grid1_bound_box(4,n) = maxval(tmp_lons)
end do
nx = grid2_dims(1)
ny = grid2_dims(2)
do n=1,grid2_size
!*** find N,S and NE points to this grid point
j = (n - 1)/nx +1
i = n - (j-1)*nx
if (i < nx) then
ip1 = i + 1
else
!*** assume cyclic
ip1 = 1
!*** but if it is not, correct
e_add = (j - 1)*nx + ip1
if (abs(grid2_center_lat(e_add) - &
grid2_center_lat(n )) > pih) then
ip1 = i
endif
endif
if (j < ny) then
jp1 = j+1
else
!*** assume cyclic
jp1 = 1
!*** but if it is not, correct
n_add = (jp1 - 1)*nx + i
if (abs(grid2_center_lat(n_add) - &
grid2_center_lat(n )) > pih) then
jp1 = j
endif
endif
n_add = (jp1 - 1)*nx + i
e_add = (j - 1)*nx + ip1
ne_add = (jp1 - 1)*nx + ip1
!*** find N,S and NE lat/lon coords and check bounding box
tmp_lats(1) = grid2_center_lat(n)
tmp_lats(2) = grid2_center_lat(e_add)
tmp_lats(3) = grid2_center_lat(ne_add)
tmp_lats(4) = grid2_center_lat(n_add)
tmp_lons(1) = grid2_center_lon(n)
tmp_lons(2) = grid2_center_lon(e_add)
tmp_lons(3) = grid2_center_lon(ne_add)
tmp_lons(4) = grid2_center_lon(n_add)
grid2_bound_box(1,n) = minval(tmp_lats)
grid2_bound_box(2,n) = maxval(tmp_lats)
grid2_bound_box(3,n) = minval(tmp_lons)
grid2_bound_box(4,n) = maxval(tmp_lons)
end do
endif
where (abs(grid1_bound_box(4,:) - grid1_bound_box(3,:)) > pi)
grid1_bound_box(3,:) = zero
grid1_bound_box(4,:) = pi2
end where
where (abs(grid2_bound_box(4,:) - grid2_bound_box(3,:)) > pi)
grid2_bound_box(3,:) = zero
grid2_bound_box(4,:) = pi2
end where
!***
!*** try to check for cells that overlap poles
!***
where (grid1_center_lat > grid1_bound_box(2,:)) &
grid1_bound_box(2,:) = pih
where (grid1_center_lat < grid1_bound_box(1,:)) &
grid1_bound_box(1,:) = -pih
where (grid2_center_lat > grid2_bound_box(2,:)) &
grid2_bound_box(2,:) = pih
where (grid2_center_lat < grid2_bound_box(1,:)) &
grid2_bound_box(1,:) = -pih
!-----------------------------------------------------------------------
!
! set up and assign address ranges to search bins in order to
! further restrict later searches
!
!-----------------------------------------------------------------------
select case (restrict_type)
case ('latitude')
write(stdout,*) 'Using latitude bins to restrict search.'
allocate(bin_addr1(2,num_srch_bins))
allocate(bin_addr2(2,num_srch_bins))
allocate(bin_lats (2,num_srch_bins))
allocate(bin_lons (2,num_srch_bins))
dlat = pi/num_srch_bins
do n=1,num_srch_bins
bin_lats(1,n) = (n-1)*dlat - pih
bin_lats(2,n) = n*dlat - pih
bin_lons(1,n) = zero
bin_lons(2,n) = pi2
bin_addr1(1,n) = grid1_size + 1
bin_addr1(2,n) = 0
bin_addr2(1,n) = grid2_size + 1
bin_addr2(2,n) = 0
end do
do nele=1,grid1_size
do n=1,num_srch_bins
if (grid1_bound_box(1,nele) <= bin_lats(2,n) .and. &
grid1_bound_box(2,nele) >= bin_lats(1,n)) then
bin_addr1(1,n) = min(nele,bin_addr1(1,n))
bin_addr1(2,n) = max(nele,bin_addr1(2,n))
endif
end do
end do
do nele=1,grid2_size
do n=1,num_srch_bins
if (grid2_bound_box(1,nele) <= bin_lats(2,n) .and. &
grid2_bound_box(2,nele) >= bin_lats(1,n)) then
bin_addr2(1,n) = min(nele,bin_addr2(1,n))
bin_addr2(2,n) = max(nele,bin_addr2(2,n))
endif
end do
end do
case ('latlon')
write(stdout,*) 'Using lat/lon boxes to restrict search.'
dlat = pi /num_srch_bins
dlon = pi2/num_srch_bins
allocate(bin_addr1(2,num_srch_bins*num_srch_bins))
allocate(bin_addr2(2,num_srch_bins*num_srch_bins))
allocate(bin_lats (2,num_srch_bins*num_srch_bins))
allocate(bin_lons (2,num_srch_bins*num_srch_bins))
n = 0
do j=1,num_srch_bins
do i=1,num_srch_bins
n = n + 1
bin_lats(1,n) = (j-1)*dlat - pih
bin_lats(2,n) = j*dlat - pih
bin_lons(1,n) = (i-1)*dlon
bin_lons(2,n) = i*dlon
bin_addr1(1,n) = grid1_size + 1
bin_addr1(2,n) = 0
bin_addr2(1,n) = grid2_size + 1
bin_addr2(2,n) = 0
end do
end do
num_srch_bins = num_srch_bins**2
do nele=1,grid1_size
do n=1,num_srch_bins
if (grid1_bound_box(1,nele) <= bin_lats(2,n) .and. &
grid1_bound_box(2,nele) >= bin_lats(1,n) .and. &
grid1_bound_box(3,nele) <= bin_lons(2,n) .and. &
grid1_bound_box(4,nele) >= bin_lons(1,n)) then
bin_addr1(1,n) = min(nele,bin_addr1(1,n))
bin_addr1(2,n) = max(nele,bin_addr1(2,n))
endif
end do
end do
do nele=1,grid2_size
do n=1,num_srch_bins
if (grid2_bound_box(1,nele) <= bin_lats(2,n) .and. &
grid2_bound_box(2,nele) >= bin_lats(1,n) .and. &
grid2_bound_box(3,nele) <= bin_lons(2,n) .and. &
grid2_bound_box(4,nele) >= bin_lons(1,n)) then
bin_addr2(1,n) = min(nele,bin_addr2(1,n))
bin_addr2(2,n) = max(nele,bin_addr2(2,n))
endif
end do
end do
case default
stop 'unknown search restriction method'
end select
!-----------------------------------------------------------------------
end subroutine grid_init
!***********************************************************************
end module grids
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!