7 use mom_coms,
only : max_across_pes, min_across_pes
8 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
11 use mom_domains,
only : root_pe, to_all, scalar_pair, cgrid_ne, agrid
19 use mom_io,
only : open_file, read_data, read_axis_data, single_file, multiple
24 use mom_time_manager,
only : get_external_field_axes, get_external_field_missing
27 use mpp_io_mod,
only : axistype
28 use mpp_domains_mod,
only : mpp_global_field, mpp_get_compute_domain
29 use mpp_mod,
only : mpp_broadcast,mpp_root_pe,mpp_sync,mpp_sync_self
30 use mpp_mod,
only : mpp_max
31 use horiz_interp_mod,
only : horiz_interp_new, horiz_interp,horiz_interp_type
32 use horiz_interp_mod,
only : horiz_interp_init, horiz_interp_del
34 use mpp_io_mod,
only : mpp_get_axis_data
35 use mpp_io_mod,
only : mpp_single
38 implicit none ;
private
40 #include <MOM_memory.h>
48 module procedure fill_boundaries_real
49 module procedure fill_boundaries_int
54 module procedure horiz_interp_and_extrap_tracer_record
55 module procedure horiz_interp_and_extrap_tracer_fms_id
61 subroutine mystats(array, missing, is, ie, js, je, k, mesg)
62 real,
dimension(:,:),
intent(in) :: array
63 real,
intent(in) :: missing
69 character(len=*) :: mesg
74 character(len=120) :: lmesg
75 mina = 9.e24 ; maxa = -9.e24 ; found = .false.
77 do j=js,je ;
do i=is,ie
78 if (array(i,j) /= array(i,j)) stop
'Nan!'
79 if (abs(array(i,j)-missing) > 1.e-6*abs(missing))
then
81 mina = min(mina, array(i,j))
82 maxa = max(maxa, array(i,j))
90 call min_across_pes(mina)
91 call max_across_pes(maxa)
92 if (is_root_pe())
then
93 write(lmesg(1:120),
'(2(a,es12.4),a,i3,x,a)') &
94 'init_from_Z: min=',mina,
' max=',maxa,
' Level=',k,trim(mesg)
95 call mom_mesg(lmesg,2)
98 end subroutine mystats
104 subroutine fill_miss_2d(aout, good, fill, prev, G, smooth, num_pass, relc, crit, debug, answers_2018)
108 real,
dimension(SZI_(G),SZJ_(G)), &
109 intent(inout) :: aout
110 real,
dimension(SZI_(G),SZJ_(G)), &
113 real,
dimension(SZI_(G),SZJ_(G)), &
116 real,
dimension(SZI_(G),SZJ_(G)), &
117 optional,
intent(in) :: prev
118 logical,
optional,
intent(in) :: smooth
120 integer,
optional,
intent(in) :: num_pass
121 real,
optional,
intent(in) :: relc
122 real,
optional,
intent(in) :: crit
123 logical,
optional,
intent(in) :: debug
124 logical,
optional,
intent(in) :: answers_2018
128 real,
dimension(SZI_(G),SZJ_(G)) :: b,r
129 real,
dimension(SZI_(G),SZJ_(G)) :: fill_pts, good_, good_new
131 character(len=256) :: mesg
133 real :: east,west,north,south,sor
134 real :: ge,gw,gn,gs,ngood
135 logical :: do_smooth,siena_bug
136 real :: nfill, nfill_prev
137 integer,
parameter :: num_pass_default = 10000
138 real,
parameter :: relc_default = 0.25, crit_default = 1.e-3
141 integer :: is, ie, js, je
142 real :: relax_coeff, acrit, ares
143 logical :: debug_it, ans_2018
146 if (
PRESENT(debug)) debug_it=debug
148 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
150 npass = num_pass_default
151 if (
PRESENT(num_pass)) npass = num_pass
153 relax_coeff = relc_default
154 if (
PRESENT(relc)) relax_coeff = relc
157 if (
PRESENT(crit)) acrit = crit
160 if (
PRESENT(smooth)) do_smooth=smooth
162 ans_2018 = .true. ;
if (
PRESENT(answers_2018)) ans_2018 = answers_2018
164 fill_pts(:,:) = fill(:,:)
166 nfill = sum(fill(is:ie,js:je))
167 call sum_across_pes(nfill)
170 good_(:,:) = good(:,:)
173 do while (nfill > 0.0)
179 good_new(:,:)=good_(:,:)
181 do j=js,je ;
do i=is,ie
183 if (good_(i,j) == 1.0 .or. fill(i,j) == 0.) cycle
185 ge=good_(i+1,j) ; gw=good_(i-1,j)
186 gn=good_(i,j+1) ; gs=good_(i,j-1)
187 east=0.0 ; west=0.0 ; north=0.0 ; south=0.0
188 if (ge == 1.0) east = aout(i+1,j)*ge
189 if (gw == 1.0) west = aout(i-1,j)*gw
190 if (gn == 1.0) north = aout(i,j+1)*gn
191 if (gs == 1.0) south = aout(i,j-1)*gs
196 ngood = (ge+gw) + (gn+gs)
200 b(i,j)=(east+west+north+south)/ngood
202 b(i,j) = ((east+west) + (north+south))/ngood
209 aout(is:ie,js:je) = b(is:ie,js:je)
210 good_(is:ie,js:je) = good_new(is:ie,js:je)
212 nfill = sum(fill_pts(is:ie,js:je))
213 call sum_across_pes(nfill)
215 if (nfill == nfill_prev .and.
PRESENT(prev))
then
216 do j=js,je ;
do i=is,ie ;
if (fill_pts(i,j) == 1.0)
then
217 aout(i,j) = prev(i,j)
219 endif ;
enddo ;
enddo
220 elseif (nfill == nfill_prev)
then
221 call mom_error(warning, &
222 'Unable to fill missing points using either data at the same vertical level from a connected basin'//&
223 'or using a point from a previous vertical level. Make sure that the original data has some valid'//&
224 'data in all basins.', .true.)
225 write(mesg,*)
'nfill=',nfill
226 call mom_error(warning, mesg, .true.)
229 nfill = sum(fill_pts(is:ie,js:je))
230 call sum_across_pes(nfill)
234 if (do_smooth)
then ;
do k=1,npass
236 do j=js,je ;
do i=is,ie
237 if (fill(i,j) == 1)
then
238 east = max(good(i+1,j),fill(i+1,j)) ; west = max(good(i-1,j),fill(i-1,j))
239 north = max(good(i,j+1),fill(i,j+1)) ; south = max(good(i,j-1),fill(i,j-1))
241 r(i,j) = relax_coeff*(south*aout(i,j-1)+north*aout(i,j+1) + &
242 west*aout(i-1,j)+east*aout(i+1,j) - &
243 (south+north+west+east)*aout(i,j))
245 r(i,j) = relax_coeff*( ((south*aout(i,j-1) + north*aout(i,j+1)) + &
246 (west*aout(i-1,j)+east*aout(i+1,j))) - &
247 ((south+north)+(west+east))*aout(i,j) )
254 do j=js,je ;
do i=is,ie
255 aout(i,j) = r(i,j) + aout(i,j)
256 ares = max(ares, abs(r(i,j)))
258 call max_across_pes(ares)
259 if (ares <= acrit)
exit
262 do j=js,je ;
do i=is,ie
263 if (good_(i,j) == 0.0 .and. fill_pts(i,j) == 1.0)
then
264 write(mesg,*)
'In fill_miss, fill, good,i,j= ',fill_pts(i,j),good_(i,j),i,j
265 call mom_error(warning, mesg, .true.)
266 call mom_error(fatal,
"MOM_initialize: "// &
267 "fill is true and good is false after fill_miss, how did this happen? ")
271 end subroutine fill_miss_2d
274 subroutine horiz_interp_and_extrap_tracer_record(filename, varnam, conversion, recnum, G, tr_z, &
275 mask_z, z_in, z_edges_in, missing_value, reentrant_x, &
276 tripolar_n, homogenize, m_to_Z, answers_2018, ongrid)
278 character(len=*),
intent(in) :: filename
280 character(len=*),
intent(in) :: varnam
281 real,
intent(in) :: conversion
282 integer,
intent(in) :: recnum
284 real,
allocatable,
dimension(:,:,:) :: tr_z
286 real,
allocatable,
dimension(:,:,:) :: mask_z
288 real,
allocatable,
dimension(:) :: z_in
289 real,
allocatable,
dimension(:) :: z_edges_in
290 real,
intent(out) :: missing_value
291 logical,
intent(in) :: reentrant_x
292 logical,
intent(in) :: tripolar_n
293 logical,
optional,
intent(in) :: homogenize
295 real,
optional,
intent(in) :: m_to_Z
297 logical,
optional,
intent(in) :: answers_2018
300 logical,
optional,
intent(in) :: ongrid
305 real,
dimension(:,:),
allocatable :: tr_in, tr_inp
308 real,
dimension(:,:),
allocatable :: mask_in
311 integer :: rcode, ncid, varid, ndims, id, jd, kd, jdp
313 integer,
dimension(4) :: start, count, dims, dim_id
314 real,
dimension(:,:),
allocatable :: x_in, y_in
315 real,
dimension(:),
allocatable :: lon_in, lat_in
316 real,
dimension(:),
allocatable :: lat_inp, last_row
317 real :: max_lat, min_lat, pole, max_depth, npole
319 real :: add_offset, scale_factor
322 character(len=8) :: laynum
323 type(horiz_interp_type) :: Interp
324 integer :: is, ie, js, je
325 integer :: isc,iec,jsc,jec
326 integer :: isg, ieg, jsg, jeg
327 integer :: isd, ied, jsd, jed
328 integer :: id_clock_read
329 character(len=12) :: dim_name(4)
330 logical :: debug=.false.
331 real :: npoints,varAvg
332 real,
dimension(SZI_(G),SZJ_(G)) :: lon_out, lat_out, tr_out, mask_out
333 real,
dimension(SZI_(G),SZJ_(G)) :: good, fill
334 real,
dimension(SZI_(G),SZJ_(G)) :: tr_outf,tr_prev
335 real,
dimension(SZI_(G),SZJ_(G)) :: good2,fill2
336 real,
dimension(SZI_(G),SZJ_(G)) :: nlevs
338 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
339 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
340 isg = g%isg ; ieg = g%ieg ; jsg = g%jsg ; jeg = g%jeg
342 id_clock_read = cpu_clock_id(
'(Initialize tracer from Z) read', grain=clock_loop)
345 if (
present(ongrid)) is_ongrid=ongrid
347 if (
allocated(tr_z))
deallocate(tr_z)
348 if (
allocated(mask_z))
deallocate(mask_z)
349 if (
allocated(z_edges_in))
deallocate(z_edges_in)
356 call cpu_clock_begin(id_clock_read)
358 rcode = nf90_open(filename, nf90_nowrite, ncid)
359 if (rcode /= 0)
call mom_error(fatal,
"error opening file "//trim(filename)//&
360 " in hinterp_extrap")
361 rcode = nf90_inq_varid(ncid, varnam, varid)
362 if (rcode /= 0)
call mom_error(fatal,
"error finding variable "//trim(varnam)//&
363 " in file "//trim(filename)//
" in hinterp_extrap")
365 rcode = nf90_inquire_variable(ncid, varid, ndims=ndims, dimids=dims)
366 if (rcode /= 0)
call mom_error(fatal,
'error inquiring dimensions hinterp_extrap')
367 if (ndims < 3)
call mom_error(fatal,
"Variable "//trim(varnam)//
" in file "// &
368 trim(filename)//
" has too few dimensions.")
370 rcode = nf90_inquire_dimension(ncid, dims(1), dim_name(1), len=id)
371 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 1 data for "// &
372 trim(varnam)//
" in file "// trim(filename)//
" in hinterp_extrap")
373 rcode = nf90_inq_varid(ncid, dim_name(1), dim_id(1))
374 if (rcode /= 0)
call mom_error(fatal,
"error finding variable "//trim(dim_name(1))//&
375 " in file "//trim(filename)//
" in hinterp_extrap")
376 rcode = nf90_inquire_dimension(ncid, dims(2), dim_name(2), len=jd)
377 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 2 data for "// &
378 trim(varnam)//
" in file "// trim(filename)//
" in hinterp_extrap")
379 rcode = nf90_inq_varid(ncid, dim_name(2), dim_id(2))
380 if (rcode /= 0)
call mom_error(fatal,
"error finding variable "//trim(dim_name(2))//&
381 " in file "//trim(filename)//
" in hinterp_extrap")
382 rcode = nf90_inquire_dimension(ncid, dims(3), dim_name(3), len=kd)
383 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 3 data for "// &
384 trim(varnam)//
" in file "// trim(filename)//
" in hinterp_extrap")
385 rcode = nf90_inq_varid(ncid, dim_name(3), dim_id(3))
386 if (rcode /= 0)
call mom_error(fatal,
"error finding variable "//trim(dim_name(3))//&
387 " in file "//trim(filename)//
" in hinterp_extrap")
390 rcode = nf90_get_att(ncid, varid,
"_FillValue", missing_value)
391 if (rcode /= 0)
call mom_error(fatal,
"error finding missing value for "//&
392 trim(varnam)//
" in file "// trim(filename)//
" in hinterp_extrap")
394 rcode = nf90_get_att(ncid, varid,
"add_offset", add_offset)
395 if (rcode /= 0) add_offset = 0.0
397 rcode = nf90_get_att(ncid, varid,
"scale_factor", scale_factor)
398 if (rcode /= 0) scale_factor = 1.0
400 if (
allocated(lon_in))
deallocate(lon_in)
401 if (
allocated(lat_in))
deallocate(lat_in)
402 if (
allocated(z_in))
deallocate(z_in)
403 if (
allocated(z_edges_in))
deallocate(z_edges_in)
404 if (
allocated(tr_z))
deallocate(tr_z)
405 if (
allocated(mask_z))
deallocate(mask_z)
407 allocate(lon_in(id),lat_in(jd),z_in(kd),z_edges_in(kd+1))
408 allocate(tr_z(isd:ied,jsd:jed,kd), mask_z(isd:ied,jsd:jed,kd))
410 start = 1; count = 1; count(1) = id
411 rcode = nf90_get_var(ncid, dim_id(1), lon_in, start, count)
412 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 1 values for var_name "// &
413 trim(varnam)//
",dim_name "//trim(dim_name(1))//
" in file "// trim(filename)//
" in hinterp_extrap")
414 start = 1; count = 1; count(1) = jd
415 rcode = nf90_get_var(ncid, dim_id(2), lat_in, start, count)
416 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 2 values for var_name "// &
417 trim(varnam)//
",dim_name "//trim(dim_name(2))//
" in file "// trim(filename)//
" in hinterp_extrap")
418 start = 1; count = 1; count(1) = kd
419 rcode = nf90_get_var(ncid, dim_id(3), z_in, start, count)
420 if (rcode /= 0)
call mom_error(fatal,
"error reading dimension 3 values for var_name "// &
421 trim(varnam//
",dim_name "//trim(dim_name(3)))//
" in file "// trim(filename)//
" in hinterp_extrap")
423 call cpu_clock_end(id_clock_read)
425 if (
present(m_to_z))
then ;
do k=1,kd ; z_in(k) = m_to_z * z_in(k) ;
enddo ;
endif
430 if (.not. is_ongrid)
then
431 max_lat = maxval(lat_in)
432 if (max_lat < 90.0)
then
435 allocate(lat_inp(jdp))
436 lat_inp(1:jd)=lat_in(:)
439 allocate(lat_in(1:jdp))
447 z_edges_in(k)=0.5*(z_in(k-1)+z_in(k))
449 z_edges_in(kd+1)=2.0*z_in(kd) - z_in(kd-1)
452 allocate(tr_in(is:ie,js:je)) ; tr_in(:,:)=0.0
453 allocate(mask_in(is:ie,js:je)) ; mask_in(:,:)=0.0
455 call horiz_interp_init()
456 lon_in = lon_in*pi_180
457 lat_in = lat_in*pi_180
458 allocate(x_in(id,jdp),y_in(id,jdp))
459 call meshgrid(lon_in,lat_in, x_in, y_in)
460 lon_out(:,:) = g%geoLonT(:,:)*pi_180
461 lat_out(:,:) = g%geoLatT(:,:)*pi_180
462 allocate(tr_in(id,jd)) ; tr_in(:,:)=0.0
463 allocate(tr_inp(id,jdp)) ; tr_inp(:,:)=0.0
464 allocate(mask_in(id,jdp)) ; mask_in(:,:)=0.0
465 allocate(last_row(id)) ; last_row(:)=0.0
470 max_depth = maxval(g%bathyT)
471 call mpp_max(max_depth)
473 if (z_edges_in(kd+1)<max_depth) z_edges_in(kd+1)=max_depth
474 roundoff = 3.0*epsilon(missing_value)
480 write(laynum,
'(I8)') k ; laynum = adjustl(laynum)
483 start(1) = is+g%HI%idg_offset ; start(2) = js+g%HI%jdg_offset ; start(3) = k
484 count(1) = ie-is+1 ; count(2) = je-js+1; count(3) = 1
485 rcode = nf90_get_var(ncid,varid, tr_in, start, count)
486 if (rcode /= 0)
call mom_error(fatal,
"hinterp_and_extract_from_Fie: "//&
487 "error reading level "//trim(laynum)//
" of variable "//&
488 trim(varnam)//
" in file "// trim(filename))
492 if (abs(tr_in(i,j)-missing_value) > abs(roundoff*missing_value))
then
494 tr_in(i,j) = (tr_in(i,j)*scale_factor+add_offset) * conversion
496 tr_in(i,j) = missing_value
502 if (is_root_pe())
then
503 start = 1 ; start(3) = k ; count(:) = 1 ; count(1) = id ; count(2) = jd
504 rcode = nf90_get_var(ncid,varid, tr_in, start, count)
505 if (rcode /= 0)
call mom_error(fatal,
"hinterp_and_extract_from_Fie: "//&
506 "error reading level "//trim(laynum)//
" of variable "//&
507 trim(varnam)//
" in file "// trim(filename))
510 last_row(:)=tr_in(:,jd); pole=0.0;npole=0.0
512 if (abs(tr_in(i,jd)-missing_value) > abs(roundoff*missing_value))
then
513 pole = pole+last_row(i)
522 tr_inp(:,1:jd) = tr_in(:,:)
525 tr_inp(:,:) = tr_in(:,:)
530 call mpp_broadcast(tr_inp, id*jdp, root_pe())
535 if (abs(tr_inp(i,j)-missing_value) > abs(roundoff*missing_value))
then
537 tr_inp(i,j) = (tr_inp(i,j)*scale_factor+add_offset) * conversion
539 tr_inp(i,j) = missing_value
549 if (.not. is_ongrid)
then
551 call horiz_interp_new(interp,x_in,y_in,lon_out(is:ie,js:je),lat_out(is:ie,js:je), &
552 interp_method=
'bilinear',src_modulo=.true.)
556 call mystats(tr_inp,missing_value, is,ie,js,je,k,
'Tracer from file')
562 tr_out(is:ie,js:je)=tr_in(is:ie,js:je)
564 call horiz_interp(interp,tr_inp,tr_out(is:ie,js:je), missing_value=missing_value, new_missing_handle=.true.)
570 if (abs(tr_out(i,j)-missing_value) < abs(roundoff*missing_value)) mask_out(i,j)=0.
574 fill = 0.0; good = 0.0
576 npoints = 0 ; varavg = 0.
579 if (mask_out(i,j) < 1.0)
then
580 tr_out(i,j)=missing_value
583 npoints = npoints + 1
584 varavg = varavg + tr_out(i,j)
586 if (g%mask2dT(i,j) == 1.0 .and. z_edges_in(k) <= g%bathyT(i,j) .and. mask_out(i,j) < 1.0) &
594 call mystats(tr_out,missing_value, is,ie,js,je,k,
'variable from horiz_interp()')
598 if (
PRESENT(homogenize))
then
600 call sum_across_pes(npoints)
601 call sum_across_pes(varavg)
603 varavg = varavg/real(npoints)
611 tr_outf(:,:) = tr_out(:,:)
612 if (k==1) tr_prev(:,:) = tr_outf(:,:)
613 good2(:,:) = good(:,:)
614 fill2(:,:) = fill(:,:)
616 call fill_miss_2d(tr_outf, good2, fill2, tr_prev, g, smooth=.true., answers_2018=answers_2018)
617 call mystats(tr_outf, missing_value, is, ie, js, je, k,
'field from fill_miss_2d()')
619 tr_z(:,:,k) = tr_outf(:,:) * g%mask2dT(:,:)
620 mask_z(:,:,k) = good2(:,:) + fill2(:,:)
622 tr_prev(:,:) = tr_z(:,:,k)
625 call hchksum(tr_prev,
'field after fill ',g%HI)
630 end subroutine horiz_interp_and_extrap_tracer_record
633 subroutine horiz_interp_and_extrap_tracer_fms_id(fms_id, Time, conversion, G, tr_z, mask_z, &
634 z_in, z_edges_in, missing_value, reentrant_x, &
635 tripolar_n, homogenize, spongeOngrid, m_to_Z, answers_2018)
637 integer,
intent(in) :: fms_id
638 type(time_type),
intent(in) :: Time
639 real,
intent(in) :: conversion
641 real,
allocatable,
dimension(:,:,:) :: tr_z
643 real,
allocatable,
dimension(:,:,:) :: mask_z
645 real,
allocatable,
dimension(:) :: z_in
646 real,
allocatable,
dimension(:) :: z_edges_in
647 real,
intent(out) :: missing_value
648 logical,
intent(in) :: reentrant_x
649 logical,
intent(in) :: tripolar_n
650 logical,
optional,
intent(in) :: homogenize
652 logical,
optional,
intent(in) :: spongeOngrid
653 real,
optional,
intent(in) :: m_to_Z
655 logical,
optional,
intent(in) :: answers_2018
660 real,
dimension(:,:),
allocatable :: tr_in,tr_inp
663 real,
dimension(:,:,:),
allocatable :: data_in
665 real,
dimension(:,:),
allocatable :: mask_in
668 integer :: rcode, ncid, varid, ndims, id, jd, kd, jdp
670 integer,
dimension(4) :: start, count, dims, dim_id
671 real,
dimension(:,:),
allocatable :: x_in, y_in
672 real,
dimension(:),
allocatable :: lon_in, lat_in
673 real,
dimension(:),
allocatable :: lat_inp, last_row
674 real :: max_lat, min_lat, pole, max_depth, npole
677 character(len=8) :: laynum
678 type(horiz_interp_type) :: Interp
679 type(axistype),
dimension(4) :: axes_data
680 integer :: is, ie, js, je
681 integer :: isc,iec,jsc,jec
682 integer :: isg, ieg, jsg, jeg
683 integer :: isd, ied, jsd, jed
684 integer :: id_clock_read
685 integer,
dimension(4) :: fld_sz
686 character(len=12) :: dim_name(4)
687 logical :: debug=.false.
688 logical :: spongeDataOngrid
689 real :: npoints,varAvg
690 real,
dimension(SZI_(G),SZJ_(G)) :: lon_out, lat_out, tr_out, mask_out
691 real,
dimension(SZI_(G),SZJ_(G)) :: good, fill
692 real,
dimension(SZI_(G),SZJ_(G)) :: tr_outf,tr_prev
693 real,
dimension(SZI_(G),SZJ_(G)) :: good2,fill2
694 real,
dimension(SZI_(G),SZJ_(G)) :: nlevs
699 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
700 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
701 isg = g%isg ; ieg = g%ieg ; jsg = g%jsg ; jeg = g%jeg
703 id_clock_read = cpu_clock_id(
'(Initialize tracer from Z) read', grain=clock_loop)
710 call cpu_clock_begin(id_clock_read)
712 fld_sz = get_external_field_size(fms_id)
713 if (
allocated(lon_in))
deallocate(lon_in)
714 if (
allocated(lat_in))
deallocate(lat_in)
715 if (
allocated(z_in))
deallocate(z_in)
716 if (
allocated(z_edges_in))
deallocate(z_edges_in)
717 if (
allocated(tr_z))
deallocate(tr_z)
718 if (
allocated(mask_z))
deallocate(mask_z)
720 axes_data = get_external_field_axes(fms_id)
722 id = fld_sz(1) ; jd = fld_sz(2) ; kd = fld_sz(3)
724 spongedataongrid=.false.
725 if (
PRESENT(spongeongrid)) spongedataongrid=spongeongrid
726 if (.not. spongedataongrid)
then
727 allocate(lon_in(id),lat_in(jd))
728 call mpp_get_axis_data(axes_data(1), lon_in)
729 call mpp_get_axis_data(axes_data(2), lat_in)
732 allocate(z_in(kd),z_edges_in(kd+1))
734 allocate(tr_z(isd:ied,jsd:jed,kd), mask_z(isd:ied,jsd:jed,kd))
736 call mpp_get_axis_data(axes_data(3), z_in)
738 if (
present(m_to_z))
then ;
do k=1,kd ; z_in(k) = m_to_z * z_in(k) ;
enddo ;
endif
740 call cpu_clock_end(id_clock_read)
742 missing_value = get_external_field_missing(fms_id)
744 if (.not. spongedataongrid)
then
746 max_lat = maxval(lat_in)
748 if (max_lat < 90.0)
then
751 allocate(lat_inp(jdp))
752 lat_inp(1:jd) = lat_in(:)
755 allocate(lat_in(1:jdp))
756 lat_in(:) = lat_inp(:)
760 call horiz_interp_init()
761 lon_in = lon_in*pi_180
762 lat_in = lat_in*pi_180
763 allocate(x_in(id,jdp), y_in(id,jdp))
764 call meshgrid(lon_in, lat_in, x_in, y_in)
765 lon_out(:,:) = g%geoLonT(:,:)*pi_180
766 lat_out(:,:) = g%geoLatT(:,:)*pi_180
767 allocate(data_in(id,jd,kd)) ; data_in(:,:,:)=0.0
768 allocate(tr_in(id,jd)) ; tr_in(:,:)=0.0
769 allocate(tr_inp(id,jdp)) ; tr_inp(:,:)=0.0
770 allocate(mask_in(id,jdp)) ; mask_in(:,:)=0.0
771 allocate(last_row(id)) ; last_row(:)=0.0
773 allocate(data_in(isd:ied,jsd:jed,kd))
778 z_edges_in(k) = 0.5*(z_in(k-1)+z_in(k))
780 z_edges_in(kd+1) = 2.0*z_in(kd) - z_in(kd-1)
783 max_depth = maxval(g%bathyT)
784 call mpp_max(max_depth)
786 if (z_edges_in(kd+1)<max_depth) z_edges_in(kd+1)=max_depth
791 if (.not.spongedataongrid)
then
793 call time_interp_external(fms_id, time, data_in, verbose=.true., turns=turns)
798 write(laynum,
'(I8)') k ; laynum = adjustl(laynum)
799 if (is_root_pe())
then
800 tr_in(1:id,1:jd) = data_in(1:id,1:jd,k)
802 last_row(:)=tr_in(:,jd); pole=0.0;npole=0.0
804 if (abs(tr_in(i,jd)-missing_value) > abs(roundoff*missing_value))
then
805 pole = pole+last_row(i)
814 tr_inp(:,1:jd) = tr_in(:,:)
817 tr_inp(:,:) = tr_in(:,:)
822 call mpp_broadcast(tr_inp, id*jdp, root_pe())
827 do j=1,jdp ;
do i=1,id
828 if (abs(tr_inp(i,j)-missing_value) > abs(roundoff*missing_value))
then
830 tr_inp(i,j) = tr_inp(i,j) * conversion
832 tr_inp(i,j) = missing_value
838 call horiz_interp_new(interp, x_in, y_in, lon_out(is:ie,js:je), lat_out(is:ie,js:je), &
839 interp_method=
'bilinear', src_modulo=.true.)
843 call mystats(tr_in, missing_value, 1, id, 1, jd, k,
'Tracer from file')
848 call horiz_interp(interp, tr_inp, tr_out(is:ie,js:je), missing_value=missing_value, &
849 new_missing_handle=.true.)
852 do j=js,je ;
do i=is,ie
853 if (abs(tr_out(i,j)-missing_value) < abs(roundoff*missing_value)) mask_out(i,j) = 0.
856 fill(:,:) = 0.0 ; good(:,:) = 0.0
858 npoints = 0 ; varavg = 0.
859 do j=js,je ;
do i=is,ie
860 if (mask_out(i,j) < 1.0)
then
861 tr_out(i,j) = missing_value
864 npoints = npoints + 1
865 varavg = varavg + tr_out(i,j)
867 if ((g%mask2dT(i,j) == 1.0) .and. (z_edges_in(k) <= g%bathyT(i,j)) .and. &
868 (mask_out(i,j) < 1.0)) &
875 call mystats(tr_out, missing_value, is, ie, js, je, k,
'variable from horiz_interp()')
879 if (
PRESENT(homogenize))
then ;
if (homogenize)
then
880 call sum_across_pes(npoints)
881 call sum_across_pes(varavg)
883 varavg = varavg/real(npoints)
890 tr_outf(:,:) = tr_out(:,:)
891 if (k==1) tr_prev(:,:) = tr_outf(:,:)
892 good2(:,:) = good(:,:)
893 fill2(:,:) = fill(:,:)
895 call fill_miss_2d(tr_outf, good2, fill2, tr_prev, g, smooth=.true., answers_2018=answers_2018)
903 tr_z(:,:,k) = tr_outf(:,:)*g%mask2dT(:,:)
904 mask_z(:,:,k) = good2(:,:) + fill2(:,:)
905 tr_prev(:,:) = tr_z(:,:,k)
908 call hchksum(tr_prev,
'field after fill ',g%HI)
913 call time_interp_external(fms_id, time, data_in, verbose=.true., turns=turns)
917 tr_z(i,j,k)=data_in(i,j,k)
918 if (abs(tr_z(i,j,k)-missing_value) < abs(roundoff*missing_value)) mask_z(i,j,k) = 0.
924 end subroutine horiz_interp_and_extrap_tracer_fms_id
927 subroutine meshgrid(x, y, x_T, y_T)
928 real,
dimension(:),
intent(in) :: x
929 real,
dimension(:),
intent(in) :: y
930 real,
dimension(size(x,1),size(y,1)),
intent(inout) :: x_T
931 real,
dimension(size(x,1),size(y,1)),
intent(inout) :: y_T
935 ni=
size(x,1) ; nj=
size(y,1)
937 do j=1,nj ;
do i=1,ni
941 do j=1,nj ;
do i=1,ni
945 end subroutine meshgrid
950 function fill_boundaries_int(m,cyclic_x,tripolar_n)
result(mp)
951 integer,
dimension(:,:),
intent(in) :: m
952 logical,
intent(in) :: cyclic_x
953 logical,
intent(in) :: tripolar_n
954 integer,
dimension(0:size(m,1)+1,0:size(m,2)+1) :: mp
956 real,
dimension(size(m,1),size(m,2)) :: m_real
957 real,
dimension(0:size(m,1)+1,0:size(m,2)+1) :: mp_real
961 mp_real = fill_boundaries_real(m_real,cyclic_x,tripolar_n)
965 end function fill_boundaries_int
968 function fill_boundaries_real(m,cyclic_x,tripolar_n)
result(mp)
969 real,
dimension(:,:),
intent(in) :: m
970 logical,
intent(in) :: cyclic_x
971 logical,
intent(in) :: tripolar_n
972 real,
dimension(0:size(m,1)+1,0:size(m,2)+1) :: mp
976 ni=
size(m,1); nj=
size(m,2)
981 mp(0,1:nj)=m(ni,1:nj)
982 mp(ni+1,1:nj)=m(1,1:nj)
985 mp(ni+1,1:nj)=m(ni,1:nj)
991 mp(i,nj+1)=m(ni-i+1,nj)
994 mp(1:ni,nj+1)=m(1:ni,nj)
997 end function fill_boundaries_real
1005 subroutine smooth_heights(zi,fill,bad,sor,niter,cyclic_x, tripolar_n)
1006 real,
dimension(:,:),
intent(inout) :: zi
1007 integer,
dimension(size(zi,1),size(zi,2)),
intent(in) :: fill
1008 integer,
dimension(size(zi,1),size(zi,2)),
intent(in) :: bad
1009 real,
intent(in) :: sor
1010 integer,
intent(in) :: niter
1011 logical,
intent(in) :: cyclic_x
1012 logical,
intent(in) :: tripolar_n
1015 real,
dimension(size(zi,1),size(zi,2)) :: res, m
1016 integer,
dimension(size(zi,1),size(zi,2),4) :: B
1017 real,
dimension(0:size(zi,1)+1,0:size(zi,2)+1) :: mp
1018 integer,
dimension(0:size(zi,1)+1,0:size(zi,2)+1) :: nm
1023 ni=
size(zi,1) ; nj=
size(zi,2)
1033 if (fill(i,j) == 1)
then
1034 b(i,j,1)=1-nm(i+1,j);b(i,j,2)=1-nm(i-1,j)
1035 b(i,j,3)=1-nm(i,j+1);b(i,j,4)=1-nm(i,j-1)
1043 if (fill(i,j) == 1)
then
1044 bsum = real(b(i,j,1)+b(i,j,2)+b(i,j,3)+b(i,j,4))
1046 res(i,j)=isum*(b(i,j,1)*mp(i+1,j)+b(i,j,2)*mp(i-1,j)+&
1047 b(i,j,3)*mp(i,j+1)+b(i,j,4)*mp(i,j-1)) - mp(i,j)
1051 res(:,:)=res(:,:)*sor
1055 mp(i,j)=mp(i,j)+res(i,j)
1059 zi(:,:)=mp(1:ni,1:nj)
1063 end subroutine smooth_heights