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
Extrapolate and interpolate data.
Wraps the FMS time manager functions.
Horizontal interpolation.
Ocean grid type. See mom_grid for details.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Wraps the MPP cpu clock functions.
This module contains I/O framework code.
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Do a halo update on a pair of arrays representing the two components of a vector. ...
Interfaces to non-domain-oriented communication subroutines, including the MOM6 reproducing sums faci...
Describes the decomposed MOM domain and has routines for communications across PEs.
Routines for error handling and I/O management.
Type for describing a variable, typically a tracer.
An overloaded interface to log version information about modules.
Indicate whether a file exists, perhaps with domain decomposition.
An overloaded interface to read various types of parameters.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Handy functions for manipulating strings.
Provides transparent structures with groups of MOM6 variables and supporting routines.
Do a halo update on an array.
An overloaded interface to read and log the values of various types of parameters.
Provides checksumming functions for debugging.