21 subroutine horiz_interp_conserve_new_1dx1d_ ( Interp, lon_in, lat_in, lon_out, lat_out, verbose)
22 type(horiz_interp_type),
intent(inout) :: Interp
23 real(FMS_HI_KIND_),
intent(in),
dimension(:) :: lon_in , lat_in
24 real(FMS_HI_KIND_),
intent(in),
dimension(:) :: lon_out, lat_out
25 integer,
intent(in),
optional :: verbose
28 real(FMS_HI_KIND_),
dimension(size(lat_out(:))-1,2) :: sph
29 real(FMS_HI_KIND_),
dimension(size(lon_out(:))-1,2) :: theta
30 real(FMS_HI_KIND_),
dimension(size(lat_in(:))) :: slat_in
31 real(FMS_HI_KIND_),
dimension(size(lon_in(:))-1) :: dlon_in
32 real(FMS_HI_KIND_),
dimension(size(lat_in(:))-1) :: dsph_in
33 real(FMS_HI_KIND_),
dimension(size(lon_out(:))-1) :: dlon_out
34 real(FMS_HI_KIND_),
dimension(size(lat_out(:))-1) :: dsph_out
35 real(FMS_HI_KIND_) :: blon, fac, hpi, tpi, eps
36 integer,
parameter :: num_iters = 4
37 integer :: i, j, m, n, nlon_in, nlat_in, nlon_out, nlat_out, &
38 iverbose, m2, n2, iter
40 character(len=64) :: mesg
41 integer,
parameter :: kindl = fms_hi_kind_
43 if(.not. module_is_initialized)
call mpp_error(fatal, &
44 'HORIZ_INTERP_CONSERVE_NEW_1DX1D_: horiz_interp_conserve_init is not called')
46 if(great_circle_algorithm)
call mpp_error(fatal, &
47 'HORIZ_INTERP_CONSERVE_NEW_1DX1D_: great_circle_algorithm is not implemented, contact developer')
49 iverbose = 0;
if (
present(verbose)) iverbose = verbose
52 root_pe = mpp_root_pe()
54 hpi = 0.5_kindl * real(pi, fms_hi_kind_)
55 tpi = 4.0_kindl * real(hpi, fms_hi_kind_)
57 nlon_in =
size(lon_in(:))-1; nlat_in =
size(lat_in(:))-1
58 nlon_out =
size(lon_out(:))-1; nlat_out =
size(lat_out(:))-1
60 allocate ( interp % HI_KIND_TYPE_ % facj (nlat_out,2), interp % jlat (nlat_out,2), &
61 interp % HI_KIND_TYPE_ % faci (nlon_out,2), interp % ilon (nlon_out,2), &
62 interp % HI_KIND_TYPE_ % area_src (nlon_in, nlat_in), &
63 interp % HI_KIND_TYPE_ % area_dst (nlon_out, nlat_out) )
69 slat_in(j) = sin(lat_in(j))
73 dsph_in(j) = abs(slat_in(j+1)-slat_in(j))
77 dlon_in(i) = abs(lon_in(i+1)-lon_in(i))
82 if (lat_in(1) > lat_in(nlat_in+1)) s2n = .false.
88 dsph_out(n) = abs(sin(lat_out(n+1))-sin(lat_out(n)))
92 theta(m,1) = lon_out(m)
93 theta(m,2) = lon_out(m+1)
94 dlon_out(m) = abs(lon_out(m+1)-lon_out(m))
97 interp%nlon_src = nlon_in; interp%nlat_src = nlat_in
98 interp%nlon_dst = nlon_out; interp%nlat_dst = nlat_out
105 if (lat_out(n) < lat_out(n+1))
then
106 sph(n,1) = sin(lat_out(n))
107 sph(n,2) = sin(lat_out(n+1))
109 sph(n,1) = sin(lat_out(n+1))
110 sph(n,2) = sin(lat_out(n))
121 if ( (s2n .and. (slat_in(j)-sph(n,n2)) <= eps .and. &
122 (sph(n,n2)-slat_in(j+1)) <= eps) .or. &
123 (.not.s2n .and. (slat_in(j+1)-sph(n,n2)) <= eps .and. &
124 (sph(n,n2)-slat_in(j)) <= eps) )
then
125 interp%jlat(n,n2) = j
127 fac = (sph(n,n2)-slat_in(j))/(slat_in(j+1)-slat_in(j))
129 if (n2 == 1) interp%HI_KIND_TYPE_%facj(n,n2) = 1.0_kindl - fac
130 if (n2 == 2) interp%HI_KIND_TYPE_%facj(n,n2) = fac
132 if (n2 == 1) interp%HI_KIND_TYPE_%facj(n,n2) = fac
133 if (n2 == 2) interp%HI_KIND_TYPE_%facj(n,n2) = 1.0_kindl - fac
138 if ( interp%jlat(n,n2) /= 0 )
exit
141 eps = epsilon(sph)*real(10.0_kindl**iter, kindl)
144 if ( interp%jlat(n,n2) == 0 )
then
145 write (mesg,710) n,sph(n,n2)
146 710
format (
': n,sph=',i3,f14.7,40x)
147 call mpp_error(fatal,
'horiz_interp_conserve_mod:no latitude index found'//trim(mesg))
158 if ( blon < lon_in(1) ) blon = blon + tpi
159 if ( blon > lon_in(nlon_in+1) ) blon = blon - tpi
164 if ( (lon_in(i)-blon) <= eps .and. &
165 (blon-lon_in(i+1)) <= eps )
then
166 interp%ilon(m,m2) = i
167 fac = (blon-lon_in(i))/(lon_in(i+1)-lon_in(i))
168 if (m2 == 1) interp%HI_KIND_TYPE_%faci(m,m2) = 1.0_kindl - fac
169 if (m2 == 2) interp%HI_KIND_TYPE_%faci(m,m2) = fac
173 if ( interp%ilon(m,m2) /= 0 )
exit
176 eps = epsilon(blon)*real(10.0_kindl**iter, kindl)
179 if ( interp%ilon(m,m2) == 0 )
then
180 print *,
'lon_out,blon,blon_in,eps=', &
181 theta(m,m2),blon,lon_in(1),lon_in(nlon_in+1),eps
182 call mpp_error(fatal,
'horiz_interp_conserve_mod: no longitude index found')
191 interp%HI_KIND_TYPE_%area_src(i,j) = dlon_in(i) * dsph_in(j)
199 interp%HI_KIND_TYPE_%area_dst(m,n) = dlon_out(m) * dsph_out(n)
206 if (iverbose > 2)
then
207 write (*,801) (i,interp%ilon(i,1),interp%ilon(i,2), &
208 interp%HI_KIND_TYPE_%faci(i,1),interp%HI_KIND_TYPE_%faci(i,2),i=1,nlon_out)
209 write (*,802) (j,interp%jlat(j,1),interp%jlat(j,2), &
210 interp%HI_KIND_TYPE_%facj(j,1),interp%HI_KIND_TYPE_%facj(j,2),j=1,nlat_out)
211 801
format (/,2x,
'i',4x,
'is',5x,
'ie',4x,
'facis',4x,
'facie', &
213 802
format (/,2x,
'j',4x,
'js',5x,
'je',4x,
'facjs',4x,
'facje', &
218 interp% HI_KIND_TYPE_ % is_allocated = .true.
219 interp% interp_method = conserve
221 end subroutine horiz_interp_conserve_new_1dx1d_
225 subroutine horiz_interp_conserve_new_1dx2d_ ( Interp, lon_in, lat_in, lon_out, lat_out, &
226 mask_in, mask_out, verbose)
227 type(horiz_interp_type),
intent(inout) :: Interp
228 real(FMS_HI_KIND_),
intent(in),
dimension(:) :: lon_in , lat_in
229 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: lon_out, lat_out
230 real(FMS_HI_KIND_),
intent(in),
optional,
dimension(:,:) :: mask_in
231 real(FMS_HI_KIND_),
intent(inout),
optional,
dimension(:,:) :: mask_out
232 integer,
intent(in),
optional :: verbose
235 integer :: create_xgrid_1DX2D_order1, get_maxxgrid, maxxgrid
236 integer :: create_xgrid_great_circle
237 integer :: nlon_in, nlat_in, nlon_out, nlat_out, nxgrid, i, j
238 real(r8_kind),
dimension(size(lon_in(:))-1, size(lat_in(:))-1) :: mask_src
239 integer,
allocatable,
dimension(:) :: i_src, j_src, i_dst, j_dst
240 real(r8_kind),
allocatable,
dimension(:) :: xgrid_area, clon, clat
241 real(r8_kind),
allocatable,
dimension(:,:) :: dst_area, lon_src, lat_src
242 real(r8_kind),
allocatable,
dimension(:) :: lat_in_flip
243 real(r8_kind),
allocatable,
dimension(:,:) :: mask_src_flip
244 real(r8_kind),
allocatable,
dimension(:) :: lon_in_r8, lat_in_r8
245 real(r8_kind),
allocatable,
dimension(:,:) :: lon_out_r8, lat_out_r8
247 integer :: nincrease, ndecrease
250 integer(kind=1) :: one_byte(8)
251 integer,
parameter :: kindl = fms_hi_kind_
253 if(.not. module_is_initialized)
call mpp_error(fatal, &
254 'HORIZ_INTERP_CONSERVE_NEW_1DX2D_: horiz_interp_conserve_init is not called')
256 wordsz=
size(transfer(lon_in(1), one_byte))
257 if(wordsz .NE. 4 .AND. wordsz .NE. 8)
call mpp_error(fatal, &
258 'HORIZ_INTERP_CONSERVE_NEW_1DX2D_: wordsz should be 4 or 8')
260 if( (
size(lon_out,1) .NE.
size(lat_out,1)) .OR. (
size(lon_out,2) .NE.
size(lat_out,2)) ) &
261 call mpp_error(fatal,
'horiz_interp_conserve_mod: size mismatch between lon_out and lat_out')
262 nlon_in =
size(lon_in(:)) - 1; nlat_in =
size(lat_in(:)) - 1
263 nlon_out =
size(lon_out,1) - 1; nlat_out =
size(lon_out,2) - 1
265 mask_src = 1.0_r8_kind
266 if(
present(mask_in))
then
267 if( (
size(mask_in,1) .NE. nlon_in) .OR. (
size(mask_in,2) .NE. nlat_in))
call mpp_error(fatal, &
268 'horiz_interp_conserve_mod: size mismatch between mask_in and lon_in/lat_in')
269 mask_src = real(mask_in, r8_kind)
272 maxxgrid = get_maxxgrid()
273 allocate(i_src(maxxgrid), j_src(maxxgrid), i_dst(maxxgrid), j_dst(maxxgrid) )
274 allocate( xgrid_area(maxxgrid), dst_area(nlon_out, nlat_out) )
280 if( lat_in(j+1) > lat_in(j) )
then
281 nincrease = nincrease + 1
282 else if ( lat_in(j+1) < lat_in(j) )
then
283 ndecrease = ndecrease + 1
287 if(nincrease == nlat_in)
then
289 else if(ndecrease == nlat_in)
then
292 call mpp_error(fatal,
'horiz_interp_conserve_mod: nlat_in should be equal to nincreaase or ndecrease')
295 allocate(lon_out_r8(
size(lon_out,1),
size(lon_out,2)))
296 allocate(lat_out_r8(
size(lat_out,1),
size(lat_out,2)))
297 lon_out_r8 = real(lon_out, r8_kind)
298 lat_out_r8 = real(lat_out, r8_kind)
300 if( .not. great_circle_algorithm )
then
302 allocate(lat_in_flip(nlat_in+1), mask_src_flip(nlon_in,nlat_in))
304 lat_in_flip(j) = real(lat_in(nlat_in+2-j), r8_kind)
307 mask_src_flip(:,j) = mask_src(:,nlat_in+1-j)
309 allocate(lon_in_r8(
size(lon_in)))
310 lon_in_r8 = real(lon_in, r8_kind)
311 nxgrid = create_xgrid_1dx2d_order1(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_flip, &
312 lon_out_r8, lat_out_r8, mask_src_flip, i_src, j_src, i_dst, j_dst, xgrid_area)
313 deallocate(lon_in_r8, lat_in_flip, mask_src_flip)
315 allocate(lon_in_r8(
size(lon_in)))
316 allocate(lat_in_r8(
size(lat_in)))
317 lon_in_r8 = real(lon_in, r8_kind)
318 lat_in_r8 = real(lat_in, r8_kind)
319 nxgrid = create_xgrid_1dx2d_order1(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_r8, lon_out_r8, &
320 & lat_out_r8, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area)
321 deallocate(lon_in_r8,lat_in_r8)
324 allocate(lon_src(nlon_in+1,nlat_in+1), lat_src(nlon_in+1,nlat_in+1))
325 allocate(clon(maxxgrid), clat(maxxgrid))
327 allocate(mask_src_flip(nlon_in,nlat_in))
330 lon_src(i,j) = real(lon_in(i), r8_kind)
331 lat_src(i,j) = real(lat_in(nlat_in+2-j), r8_kind)
335 mask_src_flip(:,j) = mask_src(:,nlat_in+1-j)
337 nxgrid = create_xgrid_great_circle(nlon_in, nlat_in, nlon_out, nlat_out, lon_src, lat_src, lon_out_r8, &
338 & lat_out_r8, mask_src_flip, i_src, j_src, i_dst, j_dst, xgrid_area, clon, clat)
339 deallocate(mask_src_flip)
343 lon_src(i,j) = real(lon_in(i), r8_kind)
344 lat_src(i,j) = real(lat_in(j), r8_kind)
347 nxgrid = create_xgrid_great_circle(nlon_in, nlat_in, nlon_out, nlat_out, lon_src, lat_src, lon_out_r8, &
348 & lat_out_r8, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area, clon, clat)
350 deallocate(lon_src, lat_src, clon, clat)
353 deallocate(lon_out_r8, lat_out_r8)
355 allocate(interp%i_src(nxgrid), interp%j_src(nxgrid) )
356 allocate(interp%i_dst(nxgrid), interp%j_dst(nxgrid) )
357 allocate(interp%HI_KIND_TYPE_%area_frac_dst(nxgrid) )
359 interp%nxgrid = nxgrid
360 interp%i_src = i_src(1:nxgrid)+1
361 interp%j_src = j_src(1:nxgrid)+1
362 if(flip_lat) interp%j_src = nlat_in+1-interp%j_src
363 interp%i_dst = i_dst(1:nxgrid)+1
364 interp%j_dst = j_dst(1:nxgrid)+1
367 dst_area = 0.0_r8_kind
369 dst_area(interp%i_dst(i), interp%j_dst(i)) = dst_area(interp%i_dst(i), interp%j_dst(i)) + xgrid_area(i)
373 interp%HI_KIND_TYPE_%area_frac_dst(i) = real(xgrid_area(i)/dst_area(interp%i_dst(i), interp%j_dst(i) ), &
376 interp%nlon_src = nlon_in; interp%nlat_src = nlat_in
377 interp%nlon_dst = nlon_out; interp%nlat_dst = nlat_out
378 if(
present(mask_out))
then
379 if( (
size(mask_out,1) .NE. nlon_out) .OR. (
size(mask_out,2) .NE. nlat_out) )
call mpp_error(fatal, &
380 'horiz_interp_conserve_mod: size mismatch between mask_out and lon_out/lat_out')
383 mask_out(interp%i_dst(i),interp%j_dst(i)) = mask_out(interp%i_dst(i), &
384 & interp%j_dst(i)) + interp%HI_KIND_TYPE_%area_frac_dst(i)
388 deallocate(i_src, j_src, i_dst, j_dst, xgrid_area, dst_area )
390 interp% HI_KIND_TYPE_ % is_allocated = .true.
391 interp% interp_method = conserve
393 end subroutine horiz_interp_conserve_new_1dx2d_
397 subroutine horiz_interp_conserve_new_2dx1d_ ( Interp, lon_in, lat_in, lon_out, lat_out, &
398 mask_in, mask_out, verbose)
399 type(horiz_interp_type),
intent(inout) :: Interp
400 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: lon_in , lat_in
401 real(FMS_HI_KIND_),
intent(in),
dimension(:) :: lon_out, lat_out
402 real(FMS_HI_KIND_),
intent(in),
optional,
dimension(:,:) :: mask_in
403 real(FMS_HI_KIND_),
intent(inout),
optional,
dimension(:,:) :: mask_out
404 integer,
intent(in),
optional :: verbose
406 integer :: create_xgrid_2DX1D_order1, get_maxxgrid, maxxgrid
407 integer :: create_xgrid_great_circle
408 integer :: nlon_in, nlat_in, nlon_out, nlat_out, nxgrid, i, j
409 integer,
allocatable,
dimension(:) :: i_src, j_src, i_dst, j_dst
410 real(r8_kind),
allocatable,
dimension(:,:) :: dst_area
411 real(r8_kind),
dimension(size(lon_in,1)-1, size(lon_in,2)-1) :: mask_src
412 real(r8_kind),
allocatable,
dimension(:) :: xgrid_area, clon, clat
413 real(r8_kind),
allocatable,
dimension(:) :: lon_out_r8, lat_out_r8
414 real(r8_kind),
allocatable,
dimension(:,:) :: lon_in_r8, lat_in_r8
415 real(r8_kind),
allocatable,
dimension(:,:) :: lon_dst, lat_dst
417 integer(kind=1) :: one_byte(8)
418 integer,
parameter :: kindl = fms_hi_kind_
420 if(.not. module_is_initialized)
call mpp_error(fatal, &
421 'HORIZ_INTERP_CONSERVE_NEW_2DX1D_: horiz_interp_conserve_init is not called')
423 wordsz=
size(transfer(lon_in(1,1), one_byte))
424 if(wordsz .NE. 8)
call mpp_error(fatal, &
425 'HORIZ_INTERP_CONSERVE_NEW_2DX1D_: currently only support 64-bit real(FMS_HI_KIND_), contact developer')
427 if( (
size(lon_in,1) .NE.
size(lat_in,1)) .OR. (
size(lon_in,2) .NE.
size(lat_in,2)) ) &
428 call mpp_error(fatal,
'horiz_interp_conserve_mod: size mismatch between lon_in and lat_in')
429 nlon_in =
size(lon_in,1) - 1; nlat_in =
size(lon_in,2) - 1
430 nlon_out =
size(lon_out(:)) - 1; nlat_out =
size(lat_out(:)) - 1
432 mask_src = 1.0_r8_kind
433 if(
present(mask_in))
then
434 if( (
size(mask_in,1) .NE. nlon_in) .OR. (
size(mask_in,2) .NE. nlat_in))
call mpp_error(fatal, &
435 'horiz_interp_conserve_mod: size mismatch between mask_in and lon_in/lat_in')
436 mask_src = real(mask_in, r8_kind)
439 maxxgrid = get_maxxgrid()
440 allocate(i_src(maxxgrid), j_src(maxxgrid), i_dst(maxxgrid), j_dst(maxxgrid) )
441 allocate( xgrid_area(maxxgrid), dst_area(nlon_out, nlat_out) )
443 allocate(lon_in_r8(
size(lon_in,1),
size(lon_in, 2)))
444 allocate(lat_in_r8(
size(lat_in,1),
size(lat_in, 2)))
445 allocate(lon_out_r8(
size(lon_out)))
446 allocate(lat_out_r8(
size(lat_out)))
447 lon_out_r8 = real(lon_out, r8_kind)
448 lat_out_r8 = real(lat_out, r8_kind)
449 lon_in_r8 = real(lon_in, r8_kind)
450 lat_in_r8 = real(lat_in, r8_kind)
452 if( .not. great_circle_algorithm )
then
453 nxgrid = create_xgrid_2dx1d_order1(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_r8, &
454 lon_out_r8, lat_out_r8, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area)
456 allocate(lon_dst(nlon_out+1, nlat_out+1), lat_dst(nlon_out+1, nlat_out+1) )
457 allocate(clon(maxxgrid), clat(maxxgrid))
460 lon_dst(i,j) = real(lon_out(i), r8_kind)
461 lat_dst(i,j) = real(lat_out(j), r8_kind)
464 nxgrid = create_xgrid_great_circle(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_r8, lon_dst, &
465 & lat_dst, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area, clon, clat)
467 deallocate(lon_out_r8,lat_out_r8, lon_in_r8, lat_in_r8)
468 allocate(interp%i_src(nxgrid), interp%j_src(nxgrid) )
469 allocate(interp%i_dst(nxgrid), interp%j_dst(nxgrid) )
470 allocate(interp%HI_KIND_TYPE_%area_frac_dst(nxgrid) )
472 interp%nxgrid = nxgrid
473 interp%i_src = i_src(1:nxgrid)+1
474 interp%j_src = j_src(1:nxgrid)+1
475 interp%i_dst = i_dst(1:nxgrid)+1
476 interp%j_dst = j_dst(1:nxgrid)+1
479 dst_area = 0.0_r8_kind
481 dst_area(interp%i_dst(i), interp%j_dst(i)) = dst_area(interp%i_dst(i), interp%j_dst(i)) + xgrid_area(i)
485 interp%HI_KIND_TYPE_%area_frac_dst(i) = real(xgrid_area(i)/dst_area(interp%i_dst(i), interp%j_dst(i) ), &
488 interp%nlon_src = nlon_in; interp%nlat_src = nlat_in
489 interp%nlon_dst = nlon_out; interp%nlat_dst = nlat_out
490 if(
present(mask_out))
then
491 if( (
size(mask_out,1) .NE. nlon_out) .OR. (
size(mask_out,2) .NE. nlat_out) )
call mpp_error(fatal, &
492 'horiz_interp_conserve_mod: size mismatch between mask_out and lon_out/lat_out')
495 mask_out(interp%i_dst(i),interp%j_dst(i)) = mask_out(interp%i_dst(i), &
496 & interp%j_dst(i)) + interp%HI_KIND_TYPE_%area_frac_dst(i)
500 deallocate(i_src, j_src, i_dst, j_dst, xgrid_area, dst_area)
502 interp% HI_KIND_TYPE_ % is_allocated = .true.
503 interp% interp_method = conserve
505 end subroutine horiz_interp_conserve_new_2dx1d_
509 subroutine horiz_interp_conserve_new_2dx2d_ ( Interp, lon_in, lat_in, lon_out, lat_out, &
510 mask_in, mask_out, verbose)
511 type(horiz_interp_type),
intent(inout) :: Interp
512 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: lon_in , lat_in
513 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: lon_out, lat_out
514 real(FMS_HI_KIND_),
intent(in),
optional,
dimension(:,:) :: mask_in
515 real(FMS_HI_KIND_),
intent(inout),
optional,
dimension(:,:) :: mask_out
516 integer,
intent(in),
optional :: verbose
518 integer :: create_xgrid_2DX2D_order1, get_maxxgrid, maxxgrid
519 integer :: create_xgrid_great_circle
520 integer :: nlon_in, nlat_in, nlon_out, nlat_out, nxgrid, i
521 integer,
allocatable,
dimension(:) :: i_src, j_src, i_dst, j_dst
522 real(r8_kind),
dimension(size(lon_in,1)-1, size(lon_in,2)-1) :: mask_src
523 real(r8_kind),
allocatable,
dimension(:) :: xgrid_area, clon, clat
524 real(r8_kind),
allocatable,
dimension(:,:) :: dst_area
525 real(r8_kind),
allocatable,
dimension(:,:) :: lon_in_r8, lat_in_r8
526 real(r8_kind),
allocatable,
dimension(:,:) :: lon_out_r8, lat_out_r8
528 integer(kind=1) :: one_byte(8)
529 integer,
parameter :: kindl = fms_hi_kind_
531 if(.not. module_is_initialized)
call mpp_error(fatal, &
532 'HORIZ_INTERP_CONSERVE_NEW_2DX2D_: horiz_interp_conserve_init is not called')
534 wordsz=
size(transfer(lon_in(1,1), one_byte))
535 if(wordsz .NE. 4 .AND. wordsz .NE. 8)
call mpp_error(fatal, &
536 'HORIZ_INTERP_CONSERVE_NEW_2DX2D_: wordsz should be 4 or 8')
538 if( (
size(lon_in,1) .NE.
size(lat_in,1)) .OR. (
size(lon_in,2) .NE.
size(lat_in,2)) ) &
539 call mpp_error(fatal,
'horiz_interp_conserve_mod: size mismatch between lon_in and lat_in')
540 if( (
size(lon_out,1) .NE.
size(lat_out,1)) .OR. (
size(lon_out,2) .NE.
size(lat_out,2)) ) &
541 call mpp_error(fatal,
'horiz_interp_conserve_mod: size mismatch between lon_out and lat_out')
542 nlon_in =
size(lon_in,1) - 1; nlat_in =
size(lon_in,2) - 1
543 nlon_out =
size(lon_out,1) - 1; nlat_out =
size(lon_out,2) - 1
545 mask_src = 1.0_r8_kind
546 if(
present(mask_in))
then
547 if( (
size(mask_in,1) .NE. nlon_in) .OR. (
size(mask_in,2) .NE. nlat_in))
call mpp_error(fatal, &
548 'horiz_interp_conserve_mod: size mismatch between mask_in and lon_in/lat_in')
549 mask_src = real(mask_in, r8_kind)
552 maxxgrid = get_maxxgrid()
553 allocate(i_src(maxxgrid), j_src(maxxgrid), i_dst(maxxgrid), j_dst(maxxgrid) )
554 allocate( xgrid_area(maxxgrid), dst_area(nlon_out, nlat_out) )
556 allocate(lon_in_r8(
size(lon_in,1),
size(lon_in,2)))
557 allocate(lat_in_r8(
size(lat_in,1),
size(lat_in,2)))
558 allocate(lon_out_r8(
size(lon_out,1),
size(lon_out,2)))
559 allocate(lat_out_r8(
size(lat_out,1),
size(lat_out,2)))
560 lon_in_r8 = real(lon_in,r8_kind)
561 lat_in_r8 = real(lat_in, r8_kind)
562 lon_out_r8 = real(lon_out, r8_kind)
563 lat_out_r8 = real(lat_out, r8_kind)
565 if( .not. great_circle_algorithm )
then
566 nxgrid = create_xgrid_2dx2d_order1(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_r8, lon_out_r8, &
567 & lat_out_r8, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area)
569 allocate(clon(maxxgrid), clat(maxxgrid))
570 nxgrid = create_xgrid_great_circle(nlon_in, nlat_in, nlon_out, nlat_out, lon_in_r8, lat_in_r8, lon_out_r8, &
571 & lat_out_r8, mask_src, i_src, j_src, i_dst, j_dst, xgrid_area, clon, clat)
572 deallocate(clon, clat)
575 deallocate(lon_in_r8, lat_in_r8, lon_out_r8, lat_out_r8)
577 allocate(interp%i_src(nxgrid), interp%j_src(nxgrid) )
578 allocate(interp%i_dst(nxgrid), interp%j_dst(nxgrid) )
579 allocate(interp%HI_KIND_TYPE_%area_frac_dst(nxgrid) )
581 interp%nxgrid = nxgrid
582 interp%i_src = i_src(1:nxgrid)+1
583 interp%j_src = j_src(1:nxgrid)+1
584 interp%i_dst = i_dst(1:nxgrid)+1
585 interp%j_dst = j_dst(1:nxgrid)+1
588 dst_area = 0.0_r8_kind
590 dst_area(interp%i_dst(i), interp%j_dst(i)) = dst_area(interp%i_dst(i), interp%j_dst(i)) + xgrid_area(i)
594 interp%HI_KIND_TYPE_%area_frac_dst(i) = real(xgrid_area(i)/dst_area(interp%i_dst(i), interp%j_dst(i)), &
598 interp%nlon_src = nlon_in; interp%nlat_src = nlat_in
599 interp%nlon_dst = nlon_out; interp%nlat_dst = nlat_out
600 if(
present(mask_out))
then
601 if( (
size(mask_out,1) .NE. nlon_out) .OR. (
size(mask_out,2) .NE. nlat_out) )
call mpp_error(fatal, &
602 'horiz_interp_conserve_mod: size mismatch between mask_out and lon_out/lat_out')
605 mask_out(interp%i_dst(i),interp%j_dst(i)) = mask_out(interp%i_dst(i), &
606 & interp%j_dst(i)) + interp%HI_KIND_TYPE_%area_frac_dst(i)
610 deallocate(i_src, j_src, i_dst, j_dst, xgrid_area, dst_area )
612 interp% HI_KIND_TYPE_ % is_allocated = .true.
613 interp% interp_method = conserve
615 end subroutine horiz_interp_conserve_new_2dx2d_
626 type (horiz_interp_type),
intent(in) :: Interp
627 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: data_in
628 real(FMS_HI_KIND_),
intent(out),
dimension(:,:) :: data_out
629 integer,
intent(in),
optional :: verbose
631 real(FMS_HI_KIND_),
intent(in),
dimension(:,:),
optional :: mask_in
636 real(FMS_HI_KIND_),
intent(out),
dimension(:,:),
optional :: mask_out
642 if (
size(data_in,1) /= interp%nlon_src .or.
size(data_in,2) /= interp%nlat_src) &
643 call mpp_error(fatal,
'horiz_interp_conserve_mod: size of input array incorrect')
645 if (
size(data_out,1) /= interp%nlon_dst .or.
size(data_out,2) /= interp%nlat_dst) &
646 call mpp_error(fatal,
'horiz_interp_conserve_mod: size of output array incorrect')
648 select case ( interp%version)
650 call horiz_interp_conserve_version1(interp, data_in, data_out, verbose, mask_in, mask_out)
652 if(
present(mask_in) .OR.
present(mask_out) )
call mpp_error(fatal,
'HORIZ_INTERP_CONSERVE_:'// &
653 &
' for version 2, mask_in and mask_out must be passed in horiz_interp_new, not in horiz_interp')
654 call horiz_interp_conserve_version2(interp, data_in, data_out, verbose)
660 subroutine horiz_interp_conserve_version1_ ( Interp, data_in, data_out, verbose, &
663 type (horiz_interp_type),
intent(in) :: Interp
664 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: data_in
665 real(FMS_HI_KIND_),
intent(out),
dimension(:,:) :: data_out
666 integer,
intent(in),
optional :: verbose
667 real(FMS_HI_KIND_),
intent(in),
dimension(:,:),
optional :: mask_in
668 real(FMS_HI_KIND_),
intent(out),
dimension(:,:),
optional :: mask_out
670 integer :: m, n, nlon_in, nlat_in, nlon_out, nlat_out, &
671 miss_in, miss_out, is, ie, js, je, &
673 real(FMS_HI_KIND_) :: dsum, wsum, avg_in, min_in, max_in, &
674 avg_out, min_out, max_out, eps, asum, &
675 dwtsum, wtsum, arsum, fis, fie, fjs, fje
676 integer,
parameter :: kindl = fms_hi_kind_
678 iverbose = 0;
if (
present(verbose)) iverbose = verbose
682 nlon_in = interp%nlon_src; nlat_in = interp%nlat_src
683 nlon_out = interp%nlon_dst; nlat_out = interp%nlat_dst
685 if (
present(mask_in))
then
686 if ( count(mask_in < -.0001_kindl .or. mask_in > 1.0001_kindl) > 0 ) &
687 call mpp_error(fatal,
'horiz_interp_conserve_mod: input mask not between 0,1')
697 if (interp%jlat(n,1) <= interp%jlat(n,2))
then
698 js = interp%jlat(n,1); je = interp%jlat(n,2)
699 fjs = interp%HI_KIND_TYPE_%facj(n,1); fje = interp%HI_KIND_TYPE_%facj(n,2)
701 js = interp%jlat(n,2); je = interp%jlat(n,1)
702 fjs = interp%HI_KIND_TYPE_%facj(n,2); fje = interp%HI_KIND_TYPE_%facj(n,1)
707 is = interp%ilon(m,1); ie = interp%ilon(m,2)
708 fis = interp%HI_KIND_TYPE_%faci(m,1); fie = interp%HI_KIND_TYPE_%faci(m,2)
727 ie = interp%ilon(m,2)
728 fie = interp%HI_KIND_TYPE_%faci(m,2)
732 if (
present(mask_in))
then
733 call data_sum( data_in(is:ie,js:je), interp%HI_KIND_TYPE_%area_src(is:ie,js:je), &
734 fis, fie, fjs,fje, dwtsum, wtsum, arsum, mask_in(is:ie,js:je) )
735 else if(
allocated(interp%HI_KIND_TYPE_%mask_in) )
then
736 call data_sum( data_in(is:ie,js:je), interp%HI_KIND_TYPE_%area_src(is:ie,js:je), &
737 fis, fie, fjs,fje, dwtsum, wtsum, arsum, interp%HI_KIND_TYPE_%mask_in(is:ie,js:je) )
739 call data_sum( data_in(is:ie,js:je), interp%HI_KIND_TYPE_%area_src(is:ie,js:je), &
740 fis, fie, fjs,fje, dwtsum, wtsum, arsum )
744 if (wtsum > eps)
then
745 data_out(m,n) = dwtsum/wtsum
746 if (
present(mask_out)) mask_out(m,n) = wtsum/arsum
748 data_out(m,n) = 0.0_kindl
749 if (
present(mask_out)) mask_out(m,n) = 0.0_kindl
759 if (iverbose > 0)
then
763 call stats(data_in, interp%HI_KIND_TYPE_%area_src, asum, dsum, wsum, min_in, max_in, miss_in, mask_in)
766 if(pe == root_pe)
then
767 if (wsum > 0.0_kindl)
then
770 print *,
'horiz_interp stats: input area equals zero '
773 if (iverbose > 1) print
'(2f16.11)',
'global sum area_in = ', asum, wsum
777 call stats(data_out, interp%HI_KIND_TYPE_%area_dst, asum, dsum, wsum, min_out, max_out, miss_out, mask_out)
779 if(pe == root_pe)
then
780 if (wsum > 0.0_kindl )
then
783 print *,
'horiz_interp stats: output area equals zero '
786 if (iverbose > 1) print
'(2f16.11)',
'global sum area_out = ', asum, wsum
790 if(pe == root_pe)
then
792 write (*,901) min_in ,max_in ,avg_in
793 if (
present(mask_in))
write (*,903) miss_in
794 write (*,902) min_out,max_out,avg_out
795 if (
present(mask_out))
write (*,903) miss_out
798 900
format (/,1x,10(
'-'),
' output from horiz_interp ',10(
'-'))
799 901
format (
' input: min=',f16.9,
' max=',f16.9,
' avg=',f22.15)
800 902
format (
' output: min=',f16.9,
' max=',f16.9,
' avg=',f22.15)
801 903
format (
' number of missing points = ',i6)
806 end subroutine horiz_interp_conserve_version1_
809 subroutine horiz_interp_conserve_version2_ ( Interp, data_in, data_out, verbose )
811 type (horiz_interp_type),
intent(in) :: Interp
812 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: data_in
813 real(FMS_HI_KIND_),
intent(out),
dimension(:,:) :: data_out
814 integer,
intent(in),
optional :: verbose
815 integer :: i, i_src, j_src, i_dst, j_dst
816 integer,
parameter :: kindl = fms_hi_kind_
819 do i = 1, interp%nxgrid
820 i_src = interp%i_src(i); j_src = interp%j_src(i)
821 i_dst = interp%i_dst(i); j_dst = interp%j_dst(i)
822 data_out(i_dst, j_dst) = data_out(i_dst, j_dst) + data_in(i_src,j_src)*interp%HI_KIND_TYPE_%area_frac_dst(i)
825 end subroutine horiz_interp_conserve_version2_
830 subroutine stats_ ( dat, area, asum, dsum, wsum, low, high, miss, mask )
831 real(FMS_HI_KIND_),
intent(in) :: dat(:,:), area(:,:)
832 real(FMS_HI_KIND_),
intent(out) :: asum, dsum, wsum, low, high
833 integer,
intent(out) :: miss
834 real(FMS_HI_KIND_),
intent(in),
optional :: mask(:,:)
835 integer,
parameter :: kindl = fms_hi_kind_
837 integer :: pe, root_pe, npes, p, buffer_int(1)
838 real(FMS_HI_KIND_) :: buffer_real(5)
841 root_pe = mpp_root_pe()
846 if (
present(mask))
then
847 asum = sum(area(:,:))
848 dsum = sum(area(:,:)*dat(:,:)*mask(:,:))
849 wsum = sum(area(:,:)*mask(:,:))
850 miss = count(mask(:,:) <= 0.5_kindl)
851 low = minval(dat(:,:),mask=mask(:,:) > 0.5_kindl )
852 high = maxval(dat(:,:),mask=mask(:,:) > 0.5_kindl )
854 asum = sum(area(:,:))
855 dsum = sum(area(:,:)*dat(:,:))
856 wsum = sum(area(:,:))
858 low = minval(dat(:,:))
859 high = maxval(dat(:,:))
865 if(pe == root_pe)
then
868 call mpp_recv(buffer_real(1),glen=5,from_pe=root_pe+p, tag=comm_tag_1)
869 asum = asum + buffer_real(1)
870 dsum = dsum + buffer_real(2)
871 wsum = wsum + buffer_real(3)
872 low = min(low, buffer_real(4))
873 high = max(high, buffer_real(5))
874 call mpp_recv(buffer_int(1),glen=1,from_pe=root_pe+p, tag=comm_tag_2)
875 miss = miss + buffer_int(1)
878 buffer_real(1) = asum
879 buffer_real(2) = dsum
880 buffer_real(3) = wsum
882 buffer_real(5) = high
884 call mpp_send(buffer_real(1),plen=5,to_pe=root_pe, tag=comm_tag_1)
886 call mpp_send(buffer_int(1),plen=1,to_pe=root_pe, tag=comm_tag_2)
896 subroutine data_sum_( grid_data, area, facis, facie, facjs, facje, &
897 dwtsum, wtsum, arsum, mask )
900 real(FMS_HI_KIND_),
intent(in),
dimension(:,:) :: grid_data, area
901 real(FMS_HI_KIND_),
intent(in) :: facis, facie, facjs, facje
902 real(FMS_HI_KIND_),
intent(inout) :: dwtsum, wtsum, arsum
903 real(FMS_HI_KIND_),
intent(in),
optional :: mask(:,:)
911 real(FMS_HI_KIND_),
dimension(size(area,1),size(area,2)) :: wt
912 real(FMS_HI_KIND_) :: asum
916 id=
size(area,1); jd=
size(area,2)
919 wt( 1,:)=wt( 1,:)*facis
920 wt(id,:)=wt(id,:)*facie
921 wt(:, 1)=wt(:, 1)*facjs
922 wt(:,jd)=wt(:,jd)*facje
927 if (
present(mask))
then
929 dwtsum = dwtsum + sum(wt*grid_data)
930 wtsum = wtsum + sum(wt)
932 dwtsum = dwtsum + sum(wt*grid_data)
subroutine horiz_interp_conserve_(Interp, data_in, data_out, verbose, mask_in, mask_out)
Subroutine for performing the horizontal interpolation between two grids.
subroutine stats_(dat, area, asum, dsum, wsum, low, high, miss, mask)
This statistics is for conservative scheme.
subroutine data_sum_(grid_data, area, facis, facie, facjs, facje, dwtsum, wtsum, arsum, mask)
sums up the data and weights for a single output grid box
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function mpp_npes()
Returns processor count for current pelist.
integer function mpp_pe()
Returns processor ID.