28   subroutine axis_edges_(fileobj, name, edge_data, reproduce_null_char_bug_flag)
 
   30   class(fmsnetcdffile_t), 
intent(in)            :: fileobj
 
   31   character(len=*), 
intent(in)                  :: name
 
   32   real(FMS_AU_KIND_), 
dimension(:), 
intent(out) :: edge_data
 
   33   logical, 
intent(in), 
optional                 :: reproduce_null_char_bug_flag
 
   38   character(len=128)                                   :: buffer
 
   39   integer,                 
dimension(:),   
allocatable :: dim_sizes
 
   40   real(kind=fms_au_kind_), 
dimension(:),   
allocatable :: r_var
 
   41   real(kind=fms_au_kind_), 
dimension(:,:), 
allocatable :: r2d
 
   44   logical                                              :: reproduce_null_char_bug
 
   47   integer, 
parameter                                   :: lkind = fms_au_kind_
 
   48   integer :: edge_index(2)
 
   52   ndims = get_variable_num_dimensions(fileobj, name)
 
   53   allocate(dim_sizes(ndims))
 
   55   call get_variable_size(fileobj, name, dim_sizes)
 
   58   if (
size(edge_data) .ne. n+1) 
then 
   59     call mpp_error(fatal, 
"axis_edge: incorrect size of edge_data array.")
 
   63   reproduce_null_char_bug = .false.
 
   64   if (
present(reproduce_null_char_bug_flag)) reproduce_null_char_bug = reproduce_null_char_bug_flag
 
   67   if (variable_att_exists(fileobj, name, 
"edges")) 
then 
   69     call get_variable_attribute(fileobj, name, 
"edges", buffer(1:128), &
 
   70         reproduce_null_char_bug_flag=reproduce_null_char_bug)
 
   73     if (reproduce_null_char_bug) 
then 
   75         i = index(buffer, char(0))
 
   76         if (i > 0) buffer = 
"" 
   78   elseif (variable_att_exists(fileobj, name, 
"bounds")) 
then 
   80     call get_variable_attribute(fileobj, name, 
"bounds", buffer(1:128), &
 
   81         reproduce_null_char_bug_flag=reproduce_null_char_bug)
 
   84     if (reproduce_null_char_bug) 
then 
   86         i = index(buffer, char(0))
 
   87         if (i > 0) buffer = 
"" 
   90   if (trim(buffer) .ne. 
"") 
then 
   91     ndims = get_variable_num_dimensions(fileobj, buffer)
 
   92     allocate(dim_sizes(ndims))
 
   94     call get_variable_size(fileobj, buffer, dim_sizes)
 
   96     if (
size(dim_sizes) .eq. 1) 
then 
   97       if (dim_sizes(1) .ne. n+1) 
then 
   98         call mpp_error(fatal, 
"axis_edges: incorrect size of edge data.")
 
  101       call read_data(fileobj, buffer, edge_data)
 
  103     elseif (
size(dim_sizes) .eq. 2) 
then 
  104       if (dim_sizes(1) .ne. 2) 
then 
  105         call mpp_error(fatal, 
"axis_edges: first dimension of edge must be of size 2")
 
  107       if (dim_sizes(2) .ne. n) 
then 
  108         call mpp_error(fatal, 
"axis_edges: incorrect size of edge data.")
 
  111       allocate(r2d(dim_sizes(1), dim_sizes(2)))
 
  112       call read_data(fileobj, buffer, r2d)
 
  113       edge_index = (/1, 2/)
 
  114       if (r2d(1,1) .gt. r2d(1,2)) edge_index = (/2, 1 /)
 
  115       edge_data(1:dim_sizes(2)) = r2d(edge_index(1),:)
 
  116       edge_data(dim_sizes(2)+1) = r2d(edge_index(2),dim_sizes(2))
 
  119     deallocate(dim_sizes)
 
  123       call read_data(fileobj, name, r_var)
 
  126          edge_data(i) = r_var(i-1) + 0.5_lkind*(r_var(i) - r_var(i-1))
 
  128       edge_data(1)    = r_var(1) - 0.5_lkind*(r_var(2) - r_var(1))
 
  129       if (abs(edge_data(1)) .lt. 1.e-10_lkind) 
then 
  130          edge_data(1) = 0.0_lkind
 
  132       edge_data(n+1)  = r_var(n) + 0.5_lkind*(r_var(n) - r_var(n-1))
 
  141     real(kind=fms_au_kind_), 
intent(in) :: lon, l_strt
 
  143     real(kind=fms_au_kind_)             :: l_end
 
  144     integer, 
parameter                  :: lkind = fms_au_kind_
 
  147     l_end = l_strt + 360.0_lkind
 
  185     real(kind=fms_au_kind_), 
intent(inout), 
dimension(:) :: lon
 
  186     real(kind=fms_au_kind_), 
intent(in)                  :: lon_start
 
  187     integer, 
intent(out)                                 :: istrt
 
  189     real(kind=fms_au_kind_) :: lon_strt, tmp(
size(lon(:))-1)
 
  194        lon(i) = lon_in_range(lon(i),lon_start)
 
  199        if (lon(i+1) < lon(i)) 
then 
  206        if (abs(lon(len)-lon(1)) < real(epsln, fms_au_kind_)) 
then 
  207           tmp = cshift(lon(1:len-1),istrt-1)
 
  211           lon = cshift(lon,istrt-1)
 
  216           lon(i)   = lon_in_range(lon(i),lon_strt)
 
  227     integer                               :: ia, i, ii, iunit
 
  228     real(kind=fms_au_kind_)               :: rval 
 
  230     real(kind=fms_au_kind_), 
dimension(:) :: array 
 
  231     logical                               :: keep_going
 
  232     integer, 
parameter                    :: lkind = fms_au_kind_
 
  236        if (array(i) < array(i-1)) 
then 
  238           write (iunit,*) 
'=> Error: "frac_index" array must be monotonically' &
 
  239           & // 
'increasing when searching for nearest value to ', rval
 
  240           write (iunit,*) 
'          array(i) < array(i-1) for i=',i
 
  241           write (iunit,*) 
'          array(i) for i=1..ia follows:' 
  243              write (iunit,*) 
'i=',ii, 
' array(i)=',array(ii)
 
  245           call mpp_error(fatal,
' "frac_index" array must be monotonically increasing.')
 
  249     if (rval < array(1) .or. rval > array(ia)) 
then 
  254        do while (i <= ia .and. keep_going)
 
  256           if (rval <= array(i)) 
then 
  257              frac_index_ = real((i-1), lkind) + (rval-array(i-1)) / (array(i) - array(i-1))
 
  301     real(kind=fms_au_kind_), 
intent(in)               :: rval 
 
  302     real(kind=fms_au_kind_), 
intent(in), 
dimension(:) :: array 
 
  308     logical :: increasing
 
  315        IF( array(i) .lt. array(i-1)) 
then 
  321     if (.not. increasing) 
then 
  324          IF( array(i) .gt. array(i-1)) &
 
  325             call mpp_error(fatal, 
'axis_utils2::nearest_index array is NOT monotonously ordered')
 
  329     array_is_increasing: 
if (increasing) 
then 
  331       if (rval .le. array(1)) 
then 
  334       elseif (rval .ge. array(ia)) 
then 
  340         if (rval .le. array(i)) 
then 
  348       if (rval .le. array(ia)) 
then 
  351       elseif (rval .gt. array(1)) 
then 
  357         if (rval .ge. array(i)) 
then 
  359           if (rval - array(i) .gt. array(i-1) -rval ) 
nearest_index_ = i - 1
 
  363     endif array_is_increasing
 
  368   subroutine interp_1d_linear_(grid1,grid2,data1,data2)
 
  370     real(kind=fms_au_kind_), 
dimension(:),    
intent(in) :: grid1, data1, grid2
 
  371     real(kind=fms_au_kind_), 
dimension(:), 
intent(inout) :: data2
 
  373     integer                 :: n1, n2, i, n
 
  374     real(kind=fms_au_kind_) :: w
 
  375     integer, 
parameter      :: lkind = fms_au_kind_
 
  382        if (grid1(i) <= grid1(i-1)) 
call mpp_error(fatal, 
'grid1 not monotonic')
 
  386        if (grid2(i) <= grid2(i-1)) 
call mpp_error(fatal, 
'grid2 not monotonic')
 
  389     if (grid1(1) > grid2(1) ) 
call mpp_error(fatal, 
'grid2 lies outside grid1')
 
  390     if (grid1(n1) < grid2(n2) ) 
call mpp_error(fatal, 
'grid2 lies outside grid1')
 
  393        n = nearest_index(grid2(i),grid1)
 
  395        if (grid1(n) < grid2(i)) 
then 
  396           w        = (grid2(i)-grid1(n))/(grid1(n+1)-grid1(n))
 
  397           data2(i) = (1.0_lkind-w)*data1(n) + w*data1(n+1)
 
  402              w        = (grid2(i)-grid1(n-1))/(grid1(n)-grid1(n-1))
 
  403              data2(i) = (1.0_lkind-w)*data1(n-1) + w*data1(n)
 
  411   end subroutine interp_1d_linear_
 
  414   subroutine interp_1d_cubic_spline_(grid1, grid2, data1, data2, yp1, ypn)
 
  416     real(kind=fms_au_kind_), 
dimension(:),    
intent(in)    :: grid1, grid2, data1
 
  417     real(kind=fms_au_kind_), 
dimension(:),    
intent(inout) :: data2
 
  418     real(kind=fms_au_kind_),                  
intent(in)    :: yp1, ypn
 
  420     real(kind=fms_au_kind_), 
dimension(size(grid1))         :: y2, u
 
  421     real(kind=fms_au_kind_)                                 :: sig, p, qn, un, h, a ,b
 
  422     integer                                                 :: n, m, i, k, klo, khi
 
  423     integer, 
parameter                                      :: lkind = fms_au_kind_
 
  429        if (grid1(i) <= grid1(i-1)) 
call mpp_error(fatal, 
'grid1 not monotonic')
 
  433        if (grid2(i) <= grid2(i-1)) 
call mpp_error(fatal, 
'grid2 not monotonic')
 
  436     if (grid1(1) > grid2(1) ) 
call mpp_error(fatal, 
'grid2 lies outside grid1')
 
  437     if (grid1(n) < grid2(m) ) 
call mpp_error(fatal, 
'grid2 lies outside grid1')
 
  439 if (yp1>0.99e30_lkind) 
then 
  444        u(1)  = (3.0_lkind)/(grid1(2)-grid1(1))*((data1(2)-data1(1))/(grid1(2)-grid1(1))-yp1)
 
  448        sig   = (grid1(i)-grid1(i-1))/(grid1(i+1)-grid1(i-1))
 
  449        p     = sig*y2(i-1) + 2.0_lkind
 
  450        y2(i) = (sig-1.0_lkind)/p
 
  451        u(i)  = (6.0_lkind*((data1(i+1)-data1(i))/(grid1(i+1)-grid1(i))-(data1(i)-data1(i-1)) &
 
  452                /(grid1(i)-grid1(i-1)))/(grid1(i+1)-grid1(i-1))-sig*u(i-1))/p
 
  455     if (ypn>0.99e30_lkind) 
then 
  460        un = (3.0_lkind)/(grid1(n)-grid1(n-1))*(ypn-(data1(n)-data1(n-1))/ &
 
  461             (grid1(n)-grid1(n-1)))
 
  464     y2(n) = (un-qn*u(n-1))/(qn*y2(n-1)+1.0_lkind)
 
  467        y2(k) = y2(k)*y2(k+1)+u(k)
 
  471        n = nearest_index(grid2(k),grid1)
 
  472        if (grid1(n) < grid2(k)) 
then 
  483        h        = grid1(khi)-grid1(klo)
 
  484        a        = (grid1(khi) - grid2(k))/h
 
  485        b        = (grid2(k) - grid1(klo))/h
 
  486        data2(k) = a*data1(klo) + b*data1(khi)+ ((a**3-a)*y2(klo) + (b**3-b)*y2(khi))*(h**2) &
 
  490   end subroutine interp_1d_cubic_spline_
 
  494   subroutine interp_1d_1d_(grid1,grid2,data1,data2, method, yp1, yp2)
 
  496     real(kind=fms_au_kind_), 
dimension(:),         
intent(in)    :: grid1, data1, grid2
 
  497     real(kind=fms_au_kind_), 
dimension(:),         
intent(inout) :: data2
 
  498     character(len=*),                    
optional, 
intent(in)    :: method
 
  499     real(kind=fms_au_kind_),             
optional, 
intent(in)    :: yp1, yp2
 
  501     real(kind=fms_au_kind_)                                      :: y1, y2
 
  502     character(len=32)                                            :: interp_method
 
  503     integer                                                      :: k2, ks, ke
 
  504     integer, 
parameter                                           :: lkind = fms_au_kind_
 
  508     interp_method = 
"linear" 
  509     if(
present(method)) interp_method = method
 
  512     if(
present(yp1)) y1 = yp1
 
  515     if(
present(yp2)) y2 = yp2
 
  516     call find_index(grid1, grid2(1), grid2(k2), ks, ke)
 
  517     select case(trim(interp_method))
 
  519        call interp_1d_linear(grid1(ks:ke),grid2,data1(ks:ke),data2)
 
  521        call interp_1d_cubic_spline(grid1(ks:ke),grid2,data1(ks:ke),data2, y1, y2)
 
  523        call mpp_error(fatal,
"axis_utils: interp_method should be linear or cubic_spline")
 
  528   end subroutine interp_1d_1d_
 
  533   subroutine interp_1d_2d_(grid1,grid2,data1,data2)
 
  535     real(kind=fms_au_kind_), 
dimension(:,:),    
intent(in) :: grid1, data1, grid2
 
  536     real(kind=fms_au_kind_), 
dimension(:,:), 
intent(inout) :: data2
 
  538     integer :: n1, n2, n, k2, ks, ke
 
  544     if (n1 /= n2) 
call mpp_error(fatal,
'grid size mismatch')
 
  547        call find_index(grid1(n,:), grid2(n,1), grid2(n,k2), ks, ke)
 
  548        call interp_1d_linear(grid1(n,ks:ke),grid2(n,:),data1(n,ks:ke),data2(n,:))
 
  553   end subroutine interp_1d_2d_
 
  557   subroutine interp_1d_3d_(grid1,grid2,data1,data2, method, yp1, yp2)
 
  559     real(fms_au_kind_), 
dimension(:,:,:), 
intent(in)    :: grid1, data1, grid2
 
  560     real(fms_au_kind_), 
dimension(:,:,:), 
intent(inout) :: data2
 
  561     character(len=*),           
optional, 
intent(in)    :: method
 
  562     real(kind=fms_au_kind_),    
optional, 
intent(in)    :: yp1, yp2
 
  564     integer                                             :: n1, n2, m1, m2, k2, n, m
 
  565     real(kind=fms_au_kind_)                             :: y1, y2
 
  566     character(len=32)                                   :: interp_method
 
  568     integer, 
parameter                                  :: lkind = fms_au_kind_
 
  576     interp_method = 
"linear" 
  577     if(
present(method)) interp_method = method
 
  580     if(
present(yp1)) y1 = yp1
 
  582     if(
present(yp2)) y2 = yp2
 
  584     if (n1 /= n2 .or. m1 /= m2) 
call mpp_error(fatal,
'grid size mismatch')
 
  586     select case(trim(interp_method))
 
  590             call find_index(grid1(n,m,:), grid2(n,m,1), grid2(n,m,k2), ks, ke)
 
  591             call interp_1d_linear(grid1(n,m,ks:ke),grid2(n,m,:),data1(n,m,ks:ke),data2(n,m,:))
 
  598             call find_index(grid1(n,m,:), grid2(n,m,1), grid2(n,m,k2), ks, ke)
 
  599             call interp_1d_cubic_spline(grid1(n,m,ks:ke),grid2(n,m,:), data1(n,m,ks:ke),data2(n,m,:), y1, y2)
 
  604        call mpp_error(fatal,
"axis_utils: interp_method should be linear or cubic_spline")
 
  609   end subroutine interp_1d_3d_
 
  613   subroutine find_index_(grid1, xs, xe, ks, ke)
 
  614     real(kind=fms_au_kind_), 
dimension(:), 
intent(in)  :: grid1
 
  615     real(kind=fms_au_kind_),               
intent(in)  :: xs, xe
 
  616     integer,                               
intent(out) :: ks, ke
 
  624        if(grid1(k) <= xs .and. grid1(k+1) > xs ) 
then 
  631        if(grid1(k) >= xe .and. grid1(k-1) < xe ) 
then 
  637     if(ks == 0 ) 
call mpp_error(fatal,
' xs locate outside of grid1')
 
  638     if(ke == 0 ) 
call mpp_error(fatal,
' xe locate outside of grid1')
 
  640   end subroutine find_index_
 
subroutine axis_edges_(fileobj, name, edge_data, reproduce_null_char_bug_flag)
get axis edge data from a given file
 
real(kind=fms_au_kind_) function frac_index_(rval, array)
 
integer function nearest_index_(rval, array)
Return index of nearest point along axis.
 
subroutine tranlon_(lon, lon_start, istrt)
Returns monotonic array of longitudes s.t., lon_strt <= lon(:) < lon_strt+360.
 
real(kind=fms_au_kind_) function lon_in_range_(lon, l_strt)
Returns lon_strt <= longitude <= lon_strt+360.
 
integer function stdout()
This function returns the current standard fortran unit numbers for output.