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.