29 subroutine axis_edges_(fileobj, name, edge_data, reproduce_null_char_bug_flag)
31 class(fmsnetcdffile_t),
intent(in) :: fileobj
32 character(len=*),
intent(in) :: name
33 real(FMS_AU_KIND_),
dimension(:),
intent(out) :: edge_data
34 logical,
intent(in),
optional :: reproduce_null_char_bug_flag
39 character(len=128) :: buffer
40 integer,
dimension(:),
allocatable :: dim_sizes
41 real(kind=fms_au_kind_),
dimension(:),
allocatable :: r_var
42 real(kind=fms_au_kind_),
dimension(:,:),
allocatable :: r2d
45 logical :: reproduce_null_char_bug
48 integer,
parameter :: lkind = fms_au_kind_
49 integer :: edge_index(2)
53 ndims = get_variable_num_dimensions(fileobj, name)
54 allocate(dim_sizes(ndims))
56 call get_variable_size(fileobj, name, dim_sizes)
59 if (
size(edge_data) .ne. n+1)
then
60 call mpp_error(fatal,
"axis_edge: incorrect size of edge_data array.")
64 reproduce_null_char_bug = .false.
65 if (
present(reproduce_null_char_bug_flag)) reproduce_null_char_bug = reproduce_null_char_bug_flag
68 if (variable_att_exists(fileobj, name,
"edges"))
then
70 call get_variable_attribute(fileobj, name,
"edges", buffer(1:128), &
71 reproduce_null_char_bug_flag=reproduce_null_char_bug)
74 if (reproduce_null_char_bug)
then
76 i = index(buffer, char(0))
77 if (i > 0) buffer =
""
79 elseif (variable_att_exists(fileobj, name,
"bounds"))
then
81 call get_variable_attribute(fileobj, name,
"bounds", buffer(1:128), &
82 reproduce_null_char_bug_flag=reproduce_null_char_bug)
85 if (reproduce_null_char_bug)
then
87 i = index(buffer, char(0))
88 if (i > 0) buffer =
""
91 if (trim(buffer) .ne.
"")
then
92 ndims = get_variable_num_dimensions(fileobj, buffer)
93 allocate(dim_sizes(ndims))
95 call get_variable_size(fileobj, buffer, dim_sizes)
97 if (
size(dim_sizes) .eq. 1)
then
98 if (dim_sizes(1) .ne. n+1)
then
99 call mpp_error(fatal,
"axis_edges: incorrect size of edge data.")
102 call read_data(fileobj, buffer, edge_data)
104 elseif (
size(dim_sizes) .eq. 2)
then
105 if (dim_sizes(1) .ne. 2)
then
106 call mpp_error(fatal,
"axis_edges: first dimension of edge must be of size 2")
108 if (dim_sizes(2) .ne. n)
then
109 call mpp_error(fatal,
"axis_edges: incorrect size of edge data.")
112 allocate(r2d(dim_sizes(1), dim_sizes(2)))
113 call read_data(fileobj, buffer, r2d)
114 edge_index = (/1, 2/)
115 if (r2d(1,1) .gt. r2d(1,2)) edge_index = (/2, 1 /)
116 edge_data(1:dim_sizes(2)) = r2d(edge_index(1),:)
117 edge_data(dim_sizes(2)+1) = r2d(edge_index(2),dim_sizes(2))
120 deallocate(dim_sizes)
124 call read_data(fileobj, name, r_var)
127 edge_data(i) = r_var(i-1) + 0.5_lkind*(r_var(i) - r_var(i-1))
129 edge_data(1) = r_var(1) - 0.5_lkind*(r_var(2) - r_var(1))
130 if (abs(edge_data(1)) .lt. 1.e-10_lkind)
then
131 edge_data(1) = 0.0_lkind
133 edge_data(n+1) = r_var(n) + 0.5_lkind*(r_var(n) - r_var(n-1))
142 real(kind=fms_au_kind_),
intent(in) :: lon, l_strt
144 real(kind=fms_au_kind_) :: l_end
145 integer,
parameter :: lkind = fms_au_kind_
148 l_end = l_strt + 360.0_lkind
186 real(kind=fms_au_kind_),
intent(inout),
dimension(:) :: lon
187 real(kind=fms_au_kind_),
intent(in) :: lon_start
188 integer,
intent(out) :: istrt
190 real(kind=fms_au_kind_) :: lon_strt, tmp(
size(lon(:))-1)
195 lon(i) = lon_in_range(lon(i),lon_start)
200 if (lon(i+1) < lon(i))
then
207 if (abs(lon(len)-lon(1)) < real(epsln, fms_au_kind_))
then
208 tmp = cshift(lon(1:len-1),istrt-1)
212 lon = cshift(lon,istrt-1)
217 lon(i) = lon_in_range(lon(i),lon_strt)
228 integer :: ia, i, ii, iunit
229 real(kind=fms_au_kind_) :: rval
231 real(kind=fms_au_kind_),
dimension(:) :: array
232 logical :: keep_going
233 integer,
parameter :: lkind = fms_au_kind_
237 if (array(i) < array(i-1))
then
239 write (iunit,*)
'=> Error: "frac_index" array must be monotonically' &
240 & //
'increasing when searching for nearest value to ', rval
241 write (iunit,*)
' array(i) < array(i-1) for i=',i
242 write (iunit,*)
' array(i) for i=1..ia follows:'
244 write (iunit,*)
'i=',ii,
' array(i)=',array(ii)
246 call mpp_error(fatal,
' "frac_index" array must be monotonically increasing.')
250 if (rval < array(1) .or. rval > array(ia))
then
255 do while (i <= ia .and. keep_going)
257 if (rval <= array(i))
then
258 frac_index_ = real((i-1), lkind) + (rval-array(i-1)) / (array(i) - array(i-1))
302 real(kind=fms_au_kind_),
intent(in) :: rval
303 real(kind=fms_au_kind_),
intent(in),
dimension(:) :: array
309 logical :: increasing
316 IF( array(i) .lt. array(i-1))
then
322 if (.not. increasing)
then
325 IF( array(i) .gt. array(i-1)) &
326 call mpp_error(fatal,
'axis_utils2::nearest_index array is NOT monotonously ordered')
330 array_is_increasing:
if (increasing)
then
332 if (rval .le. array(1))
then
335 elseif (rval .ge. array(ia))
then
341 if (rval .le. array(i))
then
349 if (rval .le. array(ia))
then
352 elseif (rval .gt. array(1))
then
358 if (rval .ge. array(i))
then
360 if (rval - array(i) .gt. array(i-1) -rval )
nearest_index_ = i - 1
364 endif array_is_increasing
369 subroutine interp_1d_linear_(grid1,grid2,data1,data2)
371 real(kind=fms_au_kind_),
dimension(:),
intent(in) :: grid1, data1, grid2
372 real(kind=fms_au_kind_),
dimension(:),
intent(inout) :: data2
374 integer :: n1, n2, i, n
375 real(kind=fms_au_kind_) :: w
376 integer,
parameter :: lkind = fms_au_kind_
383 if (grid1(i) <= grid1(i-1))
call mpp_error(fatal,
'grid1 not monotonic')
387 if (grid2(i) <= grid2(i-1))
call mpp_error(fatal,
'grid2 not monotonic')
390 if (grid1(1) > grid2(1) )
call mpp_error(fatal,
'grid2 lies outside grid1')
391 if (grid1(n1) < grid2(n2) )
call mpp_error(fatal,
'grid2 lies outside grid1')
394 n = nearest_index(grid2(i),grid1)
396 if (grid1(n) < grid2(i))
then
397 w = (grid2(i)-grid1(n))/(grid1(n+1)-grid1(n))
398 data2(i) = (1.0_lkind-w)*data1(n) + w*data1(n+1)
403 w = (grid2(i)-grid1(n-1))/(grid1(n)-grid1(n-1))
404 data2(i) = (1.0_lkind-w)*data1(n-1) + w*data1(n)
412 end subroutine interp_1d_linear_
415 subroutine interp_1d_cubic_spline_(grid1, grid2, data1, data2, yp1, ypn)
417 real(kind=fms_au_kind_),
dimension(:),
intent(in) :: grid1, grid2, data1
418 real(kind=fms_au_kind_),
dimension(:),
intent(inout) :: data2
419 real(kind=fms_au_kind_),
intent(in) :: yp1, ypn
421 real(kind=fms_au_kind_),
dimension(size(grid1)) :: y2, u
422 real(kind=fms_au_kind_) :: sig, p, qn, un, h, a ,b
423 integer :: n, m, i, k, klo, khi
424 integer,
parameter :: lkind = fms_au_kind_
430 if (grid1(i) <= grid1(i-1))
call mpp_error(fatal,
'grid1 not monotonic')
434 if (grid2(i) <= grid2(i-1))
call mpp_error(fatal,
'grid2 not monotonic')
437 if (grid1(1) > grid2(1) )
call mpp_error(fatal,
'grid2 lies outside grid1')
438 if (grid1(n) < grid2(m) )
call mpp_error(fatal,
'grid2 lies outside grid1')
440 if (yp1>0.99e30_lkind)
then
445 u(1) = (3.0_lkind)/(grid1(2)-grid1(1))*((data1(2)-data1(1))/(grid1(2)-grid1(1))-yp1)
449 sig = (grid1(i)-grid1(i-1))/(grid1(i+1)-grid1(i-1))
450 p = sig*y2(i-1) + 2.0_lkind
451 y2(i) = (sig-1.0_lkind)/p
452 u(i) = (6.0_lkind*((data1(i+1)-data1(i))/(grid1(i+1)-grid1(i))-(data1(i)-data1(i-1)) &
453 /(grid1(i)-grid1(i-1)))/(grid1(i+1)-grid1(i-1))-sig*u(i-1))/p
456 if (ypn>0.99e30_lkind)
then
461 un = (3.0_lkind)/(grid1(n)-grid1(n-1))*(ypn-(data1(n)-data1(n-1))/ &
462 (grid1(n)-grid1(n-1)))
465 y2(n) = (un-qn*u(n-1))/(qn*y2(n-1)+1.0_lkind)
468 y2(k) = y2(k)*y2(k+1)+u(k)
472 n = nearest_index(grid2(k),grid1)
473 if (grid1(n) < grid2(k))
then
484 h = grid1(khi)-grid1(klo)
485 a = (grid1(khi) - grid2(k))/h
486 b = (grid2(k) - grid1(klo))/h
487 data2(k) = a*data1(klo) + b*data1(khi)+ ((a**3-a)*y2(klo) + (b**3-b)*y2(khi))*(h**2) &
491 end subroutine interp_1d_cubic_spline_
495 subroutine interp_1d_1d_(grid1,grid2,data1,data2, method, yp1, yp2)
497 real(kind=fms_au_kind_),
dimension(:),
intent(in) :: grid1, data1, grid2
498 real(kind=fms_au_kind_),
dimension(:),
intent(inout) :: data2
499 character(len=*),
optional,
intent(in) :: method
500 real(kind=fms_au_kind_),
optional,
intent(in) :: yp1, yp2
502 real(kind=fms_au_kind_) :: y1, y2
503 character(len=32) :: interp_method
504 integer :: k2, ks, ke
505 integer,
parameter :: lkind = fms_au_kind_
509 interp_method =
"linear"
510 if(
present(method)) interp_method = method
513 if(
present(yp1)) y1 = yp1
516 if(
present(yp2)) y2 = yp2
517 call find_index(grid1, grid2(1), grid2(k2), ks, ke)
518 select case(trim(interp_method))
520 call interp_1d_linear(grid1(ks:ke),grid2,data1(ks:ke),data2)
522 call interp_1d_cubic_spline(grid1(ks:ke),grid2,data1(ks:ke),data2, y1, y2)
524 call mpp_error(fatal,
"axis_utils: interp_method should be linear or cubic_spline")
529 end subroutine interp_1d_1d_
534 subroutine interp_1d_2d_(grid1,grid2,data1,data2)
536 real(kind=fms_au_kind_),
dimension(:,:),
intent(in) :: grid1, data1, grid2
537 real(kind=fms_au_kind_),
dimension(:,:),
intent(inout) :: data2
539 integer :: n1, n2, n, k2, ks, ke
545 if (n1 /= n2)
call mpp_error(fatal,
'grid size mismatch')
548 call find_index(grid1(n,:), grid2(n,1), grid2(n,k2), ks, ke)
549 call interp_1d_linear(grid1(n,ks:ke),grid2(n,:),data1(n,ks:ke),data2(n,:))
554 end subroutine interp_1d_2d_
558 subroutine interp_1d_3d_(grid1,grid2,data1,data2, method, yp1, yp2)
560 real(fms_au_kind_),
dimension(:,:,:),
intent(in) :: grid1, data1, grid2
561 real(fms_au_kind_),
dimension(:,:,:),
intent(inout) :: data2
562 character(len=*),
optional,
intent(in) :: method
563 real(kind=fms_au_kind_),
optional,
intent(in) :: yp1, yp2
565 integer :: n1, n2, m1, m2, k2, n, m
566 real(kind=fms_au_kind_) :: y1, y2
567 character(len=32) :: interp_method
569 integer,
parameter :: lkind = fms_au_kind_
577 interp_method =
"linear"
578 if(
present(method)) interp_method = method
581 if(
present(yp1)) y1 = yp1
583 if(
present(yp2)) y2 = yp2
585 if (n1 /= n2 .or. m1 /= m2)
call mpp_error(fatal,
'grid size mismatch')
587 select case(trim(interp_method))
591 call find_index(grid1(n,m,:), grid2(n,m,1), grid2(n,m,k2), ks, ke)
592 call interp_1d_linear(grid1(n,m,ks:ke),grid2(n,m,:),data1(n,m,ks:ke),data2(n,m,:))
599 call find_index(grid1(n,m,:), grid2(n,m,1), grid2(n,m,k2), ks, ke)
600 call interp_1d_cubic_spline(grid1(n,m,ks:ke),grid2(n,m,:), data1(n,m,ks:ke),data2(n,m,:), y1, y2)
605 call mpp_error(fatal,
"axis_utils: interp_method should be linear or cubic_spline")
610 end subroutine interp_1d_3d_
614 subroutine find_index_(grid1, xs, xe, ks, ke)
615 real(kind=fms_au_kind_),
dimension(:),
intent(in) :: grid1
616 real(kind=fms_au_kind_),
intent(in) :: xs, xe
617 integer,
intent(out) :: ks, ke
625 if(grid1(k) <= xs .and. grid1(k+1) > xs )
then
632 if(grid1(k) >= xe .and. grid1(k-1) < xe )
then
638 if(ks == 0 )
call mpp_error(fatal,
' xs locate outside of grid1')
639 if(ke == 0 )
call mpp_error(fatal,
' xe locate outside of grid1')
641 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.