1 !***********************************************************************
2 !* GNU Lesser General Public License
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 !> @defgroup horiz_interp_bicubic_mod horiz_interp_bicubic_mod
20 !> @ingroup horiz_interp
21 !> @brief Delivers methods for bicubic interpolation from a coarse regular grid
22 !! on a fine regular grid
24 !> This module delivers methods for bicubic interpolation from a
25 !! coarse regular grid on a fine regular grid.
31 !! are methods taken from
33 !! W. H. Press, S. A. Teukolski, W. T. Vetterling and B. P. Flannery,
34 !! Numerical Recipies in FORTRAN, The Art of Scientific Computing.
35 !! Cambridge University Press, 1992
38 !! martin.schmidt@io-warnemuende.de (2004)
40 !! martin.schmidt@io-warnemuende.de (2004)
42 !! Version 1.0.0.2005-07-06
43 !! The module is thought to interact with MOM-4.
44 !! Alle benotigten Felder werden extern von MOM verwaltet, da sie
45 !! nicht fur alle interpolierten Daten die gleiche Dimension haben mussen.
48 !> @brief File for @ref horiz_interp_bicubic_mod
50 module horiz_interp_bicubic_mod
52 use mpp_mod, only: mpp_error, FATAL, stdout, mpp_pe, mpp_root_pe
53 use fms_mod, only: write_version_number
54 use horiz_interp_type_mod, only: horiz_interp_type
55 use constants_mod, only: PI
62 public :: horiz_interp_bicubic, horiz_interp_bicubic_new, horiz_interp_bicubic_del, fill_xy
63 public :: horiz_interp_bicubic_init
65 !> Creates a new @ref horiz_interp_type for bicubic interpolation.
66 !> @ingroup horiz_interp_bicubic_mod
67 interface horiz_interp_bicubic_new
68 module procedure horiz_interp_bicubic_new_1d
69 module procedure horiz_interp_bicubic_new_1d_s
72 !> @addtogroup horiz_interp_bicubic_mod
75 ! Include variable "version" to be written to log file.
76 #include<file_version.h>
77 logical :: module_is_initialized = .FALSE.
78 integer :: verbose_bicubic = 0
81 ! xc, yc : co-ordinates of the coarse grid
82 ! xf, yf : co-ordinates of the fine grid
83 ! fc : variable to be interpolated at the coarse grid
84 ! dfc_x : x-derivative of fc at the coarse grid
85 ! dfc_y : y-derivative of fc at the coarse grid
86 ! dfc_xy : x-y-derivative of fc at the coarse grid
87 ! ff : variable to be interpolated at the fine grid
88 ! dff_x : x-derivative of fc at the fine grid
89 ! dff_y : y-derivative of fc at the fine grid
90 ! dff_xy : x-y-derivative of fc at the fine grid
96 module procedure fill_xy
102 !> @brief Initializes module and writes version number to logfile.out
103 subroutine horiz_interp_bicubic_init
105 if(module_is_initialized) return
106 call write_version_number("HORIZ_INTERP_BICUBIC_MOD", version)
107 module_is_initialized = .true.
110 end subroutine horiz_interp_bicubic_init
112 !#######################################################################
114 !> @brief Creates a new @ref horiz_interp_type
116 !> Allocates space and initializes a derived-type variable
117 !! that contains pre-computed interpolation indices and weights.
118 subroutine horiz_interp_bicubic_new_1d_s ( Interp, lon_in, lat_in, lon_out, lat_out, &
119 verbose, src_modulo )
121 !-----------------------------------------------------------------------
122 type(horiz_interp_type), intent(inout) :: Interp !< A derived-type variable containing indices
123 !! and weights used for subsequent interpolations. To
124 !! reinitialize this variable for a different grid-to-grid
125 !! interpolation you must first use the
126 !! @ref horiz_interp_bicubic_del interface.
127 real, intent(in), dimension(:) :: lon_in !< Longitude (radians) for source data grid
128 real, intent(in), dimension(:) :: lat_in !< Latitude (radians) for source data grid
129 real, intent(in), dimension(:,:) :: lon_out !< Longitude (radians) for output data grid
130 real, intent(in), dimension(:,:) :: lat_out !< Latitude (radians) for output data grid
131 integer, intent(in), optional :: verbose !< flag for print output amount
132 logical, intent(in), optional :: src_modulo !< indicates if the boundary condition along
133 !! zonal boundary is cyclic or not. Zonal boundary condition
134 !!is cyclic when true
135 integer :: i, j, ip1, im1, jp1, jm1
136 logical :: src_is_modulo
137 integer :: nlon_in, nlat_in, nlon_out, nlat_out
138 integer :: jcl, jcu, icl, icu, jj
142 if(present(verbose)) verbose_bicubic = verbose
143 src_is_modulo = .false.
144 if (present(src_modulo)) src_is_modulo = src_modulo
146 if(size(lon_out,1) /= size(lat_out,1) .or. size(lon_out,2) /= size(lat_out,2) ) &
147 call mpp_error(FATAL,'horiz_interp_bilinear_mod: when using bilinear ' // &
148 'interplation, the output grids should be geographical grids')
150 !--- get the grid size
151 nlon_in = size(lon_in) ; nlat_in = size(lat_in)
152 nlon_out = size(lon_out,1); nlat_out = size(lat_out,2)
153 Interp%nlon_src = nlon_in; Interp%nlat_src = nlat_in
154 Interp%nlon_dst = nlon_out; Interp%nlat_dst = nlat_out
155 ! use wti(:,:,1) for x-derivative, wti(:,:,2) for y-derivative, wti(:,:,3) for xy-derivative
156 allocate ( Interp%wti (nlon_in, nlat_in, 3) )
157 allocate ( Interp%lon_in (nlon_in) )
158 allocate ( Interp%lat_in (nlat_in) )
159 allocate ( Interp%rat_x (nlon_out, nlat_out) )
160 allocate ( Interp%rat_y (nlon_out, nlat_out) )
161 allocate ( Interp%i_lon (nlon_out, nlat_out, 2) )
162 allocate ( Interp%j_lat (nlon_out, nlat_out, 2) )
164 Interp%lon_in = lon_in
165 Interp%lat_in = lat_in
167 if ( verbose_bicubic > 0 ) then
169 write (unit,'(/,"Initialising bicubic interpolation, interface horiz_interp_bicubic_new_1d_s")')
170 write (unit,'(/," Longitude of coarse grid points (radian): xc(i) i=1, ",i4)') Interp%nlon_src
171 write (unit,'(1x,10f10.4)') (Interp%lon_in(jj),jj=1,Interp%nlon_src)
172 write (unit,'(/," Latitude of coarse grid points (radian): yc(j) j=1, ",i4)') Interp%nlat_src
173 write (unit,'(1x,10f10.4)') (Interp%lat_in(jj),jj=1,Interp%nlat_src)
174 do i=1, Interp%nlat_dst
176 write (unit,'(/," Longitude of fine grid points (radian): xf(i) i=1, ",i4)') Interp%nlat_dst
177 write (unit,'(1x,10f10.4)') (lon_out(jj,i),jj=1,Interp%nlon_dst)
179 do i=1, Interp%nlon_dst
181 write (unit,'(/," Latitude of fine grid points (radian): yf(j) j=1, ",i4)') Interp%nlon_dst
182 write (unit,'(1x,10f10.4)') (lat_out(i,jj),jj=1,Interp%nlat_dst)
187 !---------------------------------------------------------------------------
188 ! Find the x-derivative. Use central differences and forward or
189 ! backward steps at the boundaries
195 Interp%wti(i,j,1) = 1./(Interp%lon_in(ip1)-Interp%lon_in(im1))
200 !---------------------------------------------------------------------------
202 ! Find the y-derivative. Use central differences and forward or
203 ! backward steps at the boundaries
208 Interp%wti(i,j,2) = 1./(Interp%lat_in(jp1)-Interp%lat_in(jm1))
212 !---------------------------------------------------------------------------
214 ! Find the xy-derivative. Use central differences and forward or
215 ! backward steps at the boundaries
222 Interp%wti(i,j,3) = 1./((Interp%lon_in(ip1)-Interp%lon_in(im1))*(Interp%lat_in(jp1)-Interp%lat_in(jm1)))
225 !---------------------------------------------------------------------------
226 ! Now for each point at the dest-grid find the boundary points of
235 if( yz .le. Interp%lat_in(1) ) then
238 else if( yz .ge. Interp%lat_in(nlat_in) ) then
242 jcl = indl(Interp%lat_in, yz)
243 jcu = indu(Interp%lat_in, yz)
248 !--- cyclic condition, do we need to use do while
249 if( xz .gt. Interp%lon_in(nlon_in) ) xz = xz - tpi
250 if( xz .le. Interp%lon_in(1) ) xz = xz + tpi
251 if( xz .ge. Interp%lon_in(nlon_in) ) then
254 Interp%rat_x(i,j) = (xz - Interp%lon_in(icl))/(Interp%lon_in(icu) - Interp%lon_in(icl) + tpi)
256 icl = indl(Interp%lon_in, xz)
257 icu = indu(Interp%lon_in, xz)
258 Interp%rat_x(i,j) = (xz - Interp%lon_in(icl))/(Interp%lon_in(icu) - Interp%lon_in(icl))
260 Interp%j_lat(i,j,1) = jcl
261 Interp%j_lat(i,j,2) = jcu
262 Interp%i_lon(i,j,1) = icl
263 Interp%i_lon(i,j,2) = icu
265 Interp%rat_y(i,j) = 0.0
267 Interp%rat_y(i,j) = (yz - Interp%lat_in(jcl))/(Interp%lat_in(jcu) - Interp%lat_in(jcl))
269 ! if(yz.gt.Interp%lat_in(jcu)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d_s:
270 ! yf < ycl, no valid boundary point')
271 ! if(yz.lt.Interp%lat_in(jcl)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d_s:
272 ! yf > ycu, no valid boundary point')
273 ! if(xz.gt.Interp%lon_in(icu)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d_s:
274 ! xf < xcl, no valid boundary point')
275 ! if(xz.lt.Interp%lon_in(icl)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d_s:
276 ! xf > xcu, no valid boundary point')
279 end subroutine horiz_interp_bicubic_new_1d_s
281 !> @brief Creates a new @ref horiz_interp_type
283 !> Allocates space and initializes a derived-type variable
284 !! that contains pre-computed interpolation indices and weights.
285 subroutine horiz_interp_bicubic_new_1d ( Interp, lon_in, lat_in, lon_out, lat_out, &
286 verbose, src_modulo )
288 !-----------------------------------------------------------------------
289 type(horiz_interp_type), intent(inout) :: Interp
290 real, intent(in), dimension(:) :: lon_in , lat_in
291 real, intent(in), dimension(:) :: lon_out, lat_out
292 integer, intent(in), optional :: verbose
293 logical, intent(in), optional :: src_modulo
294 integer :: i, j, ip1, im1, jp1, jm1
295 logical :: src_is_modulo
296 integer :: nlon_in, nlat_in, nlon_out, nlat_out
297 integer :: jcl, jcu, icl, icu, jj
301 if(present(verbose)) verbose_bicubic = verbose
302 src_is_modulo = .false.
303 if (present(src_modulo)) src_is_modulo = src_modulo
305 !--- get the grid size
306 nlon_in = size(lon_in) ; nlat_in = size(lat_in)
307 nlon_out = size(lon_out); nlat_out = size(lat_out)
308 Interp%nlon_src = nlon_in; Interp%nlat_src = nlat_in
309 Interp%nlon_dst = nlon_out; Interp%nlat_dst = nlat_out
310 allocate ( Interp%wti (nlon_in, nlat_in, 3) )
311 allocate ( Interp%lon_in (nlon_in) )
312 allocate ( Interp%lat_in (nlat_in) )
313 allocate ( Interp%rat_x (nlon_out, nlat_out) )
314 allocate ( Interp%rat_y (nlon_out, nlat_out) )
315 allocate ( Interp%i_lon (nlon_out, nlat_out, 2) )
316 allocate ( Interp%j_lat (nlon_out, nlat_out, 2) )
318 Interp%lon_in = lon_in
319 Interp%lat_in = lat_in
321 if ( verbose_bicubic > 0 ) then
323 write (unit,'(/,"Initialising bicubic interpolation, interface horiz_interp_bicubic_new_1d")')
324 write (unit,'(/," Longitude of coarse grid points (radian): xc(i) i=1, ",i4)') Interp%nlon_src
325 write (unit,'(1x,10f10.4)') (Interp%lon_in(jj),jj=1,Interp%nlon_src)
326 write (unit,'(/," Latitude of coarse grid points (radian): yc(j) j=1, ",i4)') Interp%nlat_src
327 write (unit,'(1x,10f10.4)') (Interp%lat_in(jj),jj=1,Interp%nlat_src)
329 write (unit,'(/," Longitude of fine grid points (radian): xf(i) i=1, ",i4)') Interp%nlat_dst
330 write (unit,'(1x,10f10.4)') (lon_out(jj),jj=1,Interp%nlon_dst)
331 write (unit,'(/," Latitude of fine grid points (radian): yf(j) j=1, ",i4)') Interp%nlon_dst
332 write (unit,'(1x,10f10.4)') (lat_out(jj),jj=1,Interp%nlat_dst)
336 !---------------------------------------------------------------------------
337 ! Find the x-derivative. Use central differences and forward or
338 ! backward steps at the boundaries
344 Interp%wti(i,j,1) = 1./(lon_in(ip1)-lon_in(im1))
349 !---------------------------------------------------------------------------
351 ! Find the y-derivative. Use central differences and forward or
352 ! backward steps at the boundaries
357 Interp%wti(i,j,2) = 1./(lat_in(jp1)-lat_in(jm1))
361 !---------------------------------------------------------------------------
363 ! Find the xy-derivative. Use central differences and forward or
364 ! backward steps at the boundaries
371 Interp%wti(i,j,3) = 1./((lon_in(ip1)-lon_in(im1))*(lat_in(jp1)-lat_in(jm1)))
374 !---------------------------------------------------------------------------
375 ! Now for each point at the dest-grid find the boundary points of
381 if( yz .le. lat_in(1) ) then
384 else if( yz .ge. lat_in(nlat_in) ) then
388 jcl = indl(lat_in, yz)
389 jcu = indu(lat_in, yz)
395 !--- cyclic condition, do we need to use do while
396 if( xz .gt. lon_in(nlon_in) ) xz = xz - tpi
397 if( xz .le. lon_in(1) ) xz = xz + tpi
398 if( xz .ge. lon_in(nlon_in) ) then
401 Interp%rat_x(i,j) = (xz - Interp%lon_in(icl))/(Interp%lon_in(icu) - Interp%lon_in(icl) + tpi)
403 icl = indl(lon_in, xz)
404 icu = indu(lon_in, xz)
405 Interp%rat_x(i,j) = (xz - Interp%lon_in(icl))/(Interp%lon_in(icu) - Interp%lon_in(icl))
407 icl = indl(lon_in, xz)
408 icu = indu(lon_in, xz)
409 Interp%j_lat(i,j,1) = jcl
410 Interp%j_lat(i,j,2) = jcu
411 Interp%i_lon(i,j,1) = icl
412 Interp%i_lon(i,j,2) = icu
414 Interp%rat_y(i,j) = 0.0
416 Interp%rat_y(i,j) = (yz - Interp%lat_in(jcl))/(Interp%lat_in(jcu) - Interp%lat_in(jcl))
418 ! if(yz.gt.lat_in(jcu)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d: yf <
419 ! ycl, no valid boundary point')
420 ! if(yz.lt.lat_in(jcl)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d: yf >
421 ! ycu, no valid boundary point')
422 ! if(xz.gt.lon_in(icu)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d: xf <
423 ! xcl, no valid boundary point')
424 ! if(xz.lt.lon_in(icl)) call mpp_error(FATAL, ' horiz_interp_bicubic_new_1d: xf >
425 ! xcu, no valid boundary point')
429 end subroutine horiz_interp_bicubic_new_1d
431 !> @brief Perform bicubic horizontal interpolation
432 subroutine horiz_interp_bicubic( Interp, data_in, data_out, verbose, mask_in, mask_out, missing_value, &
434 type (horiz_interp_type), intent(in) :: Interp
435 real, intent(in), dimension(:,:) :: data_in
436 real, intent(out), dimension(:,:) :: data_out
437 integer, intent(in), optional :: verbose
438 real, intent(in), dimension(:,:), optional :: mask_in
439 real, intent(out), dimension(:,:), optional :: mask_out
440 real, intent(in), optional :: missing_value
441 integer, intent(in), optional :: missing_permit
444 real :: val, val1, val2
445 real, dimension(4) :: y, y1, y2, y12
446 integer :: icl, icu, jcl, jcu
447 integer :: iclp1, icup1, jclp1, jcup1
448 integer :: iclm1, icum1, jclm1, jcum1
451 if ( present(verbose) ) verbose_bicubic = verbose
453 ! if ( present(fill) ) fill_in = fill
454 ! use dfc_x and dfc_y as workspace
455 ! if ( fill_in ) call fill_xy(fc(ics:ice,jcs:jce), ics, ice, jcs, jce, maxpass=2)
456 ! where ( data_in .le. missing ) data_in(:,:) = 0.
458 do j=1, Interp%nlat_dst
459 do i=1, Interp%nlon_dst
460 yz = Interp%rat_y(i,j)
461 xz = Interp%rat_x(i,j)
462 jcl = Interp%j_lat(i,j,1)
463 jcu = Interp%j_lat(i,j,2)
464 icl = Interp%i_lon(i,j,1)
465 icu = Interp%i_lon(i,j,2)
469 xcl = Interp%lon_in(icl)
470 xcu = Interp%lon_in(icu)+tpi
472 iclp1 = min(icl+1,Interp%nlon_src)
474 xcl = Interp%lon_in(icl)
475 xcu = Interp%lon_in(icu)
478 icup1 = min(icu+1,Interp%nlon_src)
479 jclp1 = min(jcl+1,Interp%nlat_src)
481 jcup1 = min(jcu+1,Interp%nlat_src)
483 ycl = Interp%lat_in(jcl)
484 ycu = Interp%lat_in(jcu)
485 ! xcl = Interp%lon_in(icl)
486 ! xcu = Interp%lon_in(icu)
487 y(1) = data_in(icl,jcl)
488 y(2) = data_in(icu,jcl)
489 y(3) = data_in(icu,jcu)
490 y(4) = data_in(icl,jcu)
491 y1(1) = ( data_in(iclp1,jcl) - data_in(iclm1,jcl) ) * Interp%wti(icl,jcl,1)
492 y1(2) = ( data_in(icup1,jcl) - data_in(icum1,jcl) ) * Interp%wti(icu,jcl,1)
493 y1(3) = ( data_in(icup1,jcu) - data_in(icum1,jcu) ) * Interp%wti(icu,jcu,1)
494 y1(4) = ( data_in(iclp1,jcu) - data_in(iclm1,jcu) ) * Interp%wti(icl,jcu,1)
495 y2(1) = ( data_in(icl,jclp1) - data_in(icl,jclm1) ) * Interp%wti(icl,jcl,2)
496 y2(2) = ( data_in(icu,jclp1) - data_in(icu,jclm1) ) * Interp%wti(icu,jcl,2)
497 y2(3) = ( data_in(icu,jcup1) - data_in(icu,jcum1) ) * Interp%wti(icu,jcu,2)
498 y2(4) = ( data_in(icl,jcup1) - data_in(icl,jcum1) ) * Interp%wti(icl,jcu,2)
499 y12(1)= ( data_in(iclp1,jclp1) + data_in(iclm1,jclm1) - data_in(iclm1,jclp1) &
500 - data_in(iclp1,jclm1) ) * Interp%wti(icl,jcl,3)
501 y12(2)= ( data_in(icup1,jclp1) + data_in(icum1,jclm1) - data_in(icum1,jclp1) &
502 - data_in(icup1,jclm1) ) * Interp%wti(icu,jcl,3)
503 y12(3)= ( data_in(icup1,jcup1) + data_in(icum1,jcum1) - data_in(icum1,jcup1) &
504 - data_in(icup1,jcum1) ) * Interp%wti(icu,jcu,3)
505 y12(4)= ( data_in(iclp1,jcup1) + data_in(iclm1,jcum1) - data_in(iclm1,jcup1) &
506 - data_in(iclp1,jcum1) ) * Interp%wti(icl,jcu,3)
508 call bcuint(y,y1,y2,y12,xcl,xcu,ycl,ycu,xz,yz,val,val1,val2)
510 if(present(mask_out)) mask_out(i,j) = 1.
516 end subroutine horiz_interp_bicubic
519 !---------------------------------------------------------------------------
521 subroutine bcuint(y,y1,y2,y12,x1l,x1u,x2l,x2u,t,u,ansy,ansy1,ansy2)
522 real ansy,ansy1,ansy2,x1l,x1u,x2l,x2u,y(4),y1(4),y12(4),y2(4)
526 call bcucof(y,y1,y2,y12,x1u-x1l,x2u-x2l,c)
531 ansy=t*ansy+((c(i,4)*u+c(i,3))*u+c(i,2))*u+c(i,1)
532 ! ansy2=t*ansy2+(3.*c(i,4)*u+2.*c(i,3))*u+c(i,2)
533 ! ansy1=u*ansy1+(3.*c(4,i)*t+2.*c(3,i))*t+c(2,i)
535 ! ansy1=ansy1/(x1u-x1l) ! could be used for accuracy checks
536 ! ansy2=ansy2/(x2u-x2l) ! could be used for accuracy checks
538 ! (c) copr. 1986-92 numerical recipes software -3#(-)f.
539 end subroutine bcuint
540 !---------------------------------------------------------------------------
542 subroutine bcucof(y,y1,y2,y12,d1,d2,c)
543 real d1,d2,c(4,4),y(4),y1(4),y12(4),y2(4)
545 real d1d2,xx,cl(16),wt(16,16),x(16)
547 data wt/1., 0., -3., 2., 4*0., -3., 0., 9., -6., 2., 0., -6., 4., 8*0., &
548 3., 0., -9., 6., -2., 0., 6., -4., 10*0., 9., -6., 2*0., -6., &
549 4., 2*0., 3., -2., 6*0., -9., 6., 2*0., 6., -4., 4*0., 1., 0., &
550 -3., 2., -2., 0., 6., -4., 1., 0., -3., 2., 8*0., -1., 0., 3., &
551 -2., 1., 0., -3., 2., 10*0., -3., 2., 2*0., 3., -2., 6*0., 3., &
552 -2., 2*0., -6., 4., 2*0., 3., -2., 0., 1., -2., 1., 5*0., -3., &
553 6., -3., 0., 2., -4., 2., 9*0., 3., -6., 3., 0., -2., 4., -2., &
554 10*0., -3., 3., 2*0., 2., -2., 2*0., -1., 1., 6*0., 3., -3., &
555 2*0., -2., 2., 5*0., 1., -2., 1., 0., -2., 4., -2., 0., 1., -2., &
556 1., 9*0., -1., 2., -1., 0., 1., -2., 1., 10*0., 1., -1., 2*0., &
557 -1., 1., 6*0., -1., 1., 2*0., 2., -2., 2*0., -1., 1./
581 ! (c) copr. 1986-92 numerical recipes software -3#(-)f.
582 end subroutine bcucof
584 !-----------------------------------------------------------------------
586 !> find the lower neighbour of xf in field xc, return is the index
587 function indl(xc, xf)
588 real, intent(in) :: xc(1:)
589 real, intent(in) :: xf
594 if(xc(ii).gt.xf) return
597 call mpp_error(FATAL,'Error in indl')
601 !-----------------------------------------------------------------------
603 !> find the upper neighbour of xf in field xc, return is the index
604 function indu(xc, xf)
605 real, intent(in) :: xc(1:)
606 real, intent(in) :: xf
611 if(xc(ii).gt.xf) return
613 call mpp_error(FATAL,'Error in indu')
617 !-----------------------------------------------------------------------
619 subroutine fill_xy(fi, ics, ice, jcs, jce, mask, maxpass)
620 integer, intent(in) :: ics,ice,jcs,jce
621 real, intent(inout) :: fi(ics:ice,jcs:jce)
622 real, intent(in), optional :: mask(ics:ice,jcs:jce)
623 integer, intent(in) :: maxpass
624 real :: work_old(ics:ice,jcs:jce)
625 real :: work_new(ics:ice,jcs:jce)
627 real :: blank = -1.e30
630 integer :: inl, inr, jnl, jnu, i, j, is, js, iavr
635 work_new(:,:) = fi(:,:)
636 work_old(:,:) = work_new(:,:)
638 if ( present(mask) ) then
639 do while (.not.ready)
644 if (work_old(i,j).le.blank) then
653 if (work_old(is,js) .ne. blank .and. mask(is,js).ne.0.) then
654 tavr = tavr + work_old(is,js)
661 ! spreading is not allowed if the only valid neighbor is a corner point
662 ! otherwise an ill posed cellular automaton is established leading to
663 ! a spreading of constant values in diagonal direction
664 ! if all corner points are blanked the valid neighbor must be a direct one
665 ! and spreading is allowed
666 if (work_old(inl,jnu).eq.blank.and.&
667 work_old(inr,jnu).eq.blank.and.&
668 work_old(inr,jnl).eq.blank.and.&
669 work_old(inl,jnl).eq.blank) then
670 work_new(i,j)=tavr/iavr
674 work_new(i,j)=tavr/iavr
681 ! save changes made during this pass to work_old
682 work_old(:,:)=work_new(:,:)
683 if(ipass.eq.maxpass) ready=.true.
684 enddo !while (.not.ready)
685 fi(:,:) = work_new(:,:)
687 do while (.not.ready)
692 if (work_old(i,j).le.blank) then
701 if (work_old(is,js).gt.blank) then
702 tavr = tavr + work_old(is,js)
709 ! spreading is not allowed if the only valid neighbor is a corner point
710 ! otherwise an ill posed cellular automaton is established leading to
711 ! a spreading of constant values in diagonal direction
712 ! if all corner points are blanked the valid neighbor must be a direct one
713 ! and spreading is allowed
714 if (work_old(inl,jnu).le.blank.and. &
715 work_old(inr,jnu).le.blank.and. &
716 work_old(inr,jnl).le.blank.and. &
717 work_old(inl,jnl).le.blank) then
718 work_new(i,j)=tavr/iavr
722 work_new(i,j)=tavr/iavr
729 ! save changes made during this pass to work_old
730 work_old(:,:)=work_new(:,:)
731 if(ipass.eq.maxpass) ready=.true.
732 enddo !while (.not.ready)
733 fi(:,:) = work_new(:,:)
736 end subroutine fill_xy
738 subroutine horiz_interp_bicubic_del( Interp )
740 type (horiz_interp_type), intent(inout) :: Interp
742 if(associated(Interp%rat_x)) deallocate ( Interp%rat_x )
743 if(associated(Interp%rat_y)) deallocate ( Interp%rat_y )
744 if(associated(Interp%lon_in)) deallocate ( Interp%lon_in )
745 if(associated(Interp%lat_in)) deallocate ( Interp%lat_in )
746 if(associated(Interp%i_lon)) deallocate ( Interp%i_lon )
747 if(associated(Interp%j_lat)) deallocate ( Interp%j_lat )
748 if(associated(Interp%wti)) deallocate ( Interp%wti )
750 end subroutine horiz_interp_bicubic_del
752 end module horiz_interp_bicubic_mod
754 ! close documentation