61 implicit none ;
private 63 #include <MOM_memory.h> 80 real,
pointer,
dimension(:,:,:) :: &
86 type(
p3d) :: tr_z(max_fields_)
87 type(
p3d) :: tr_model(max_fields_)
89 real :: missing_vel = -1.0e34
90 real :: missing_trans = -1.0e34
91 real :: missing_value = -1.0e34
92 real :: missing_tr(max_fields_) = -1.0e34
94 integer :: id_u_z = -1
95 integer :: id_v_z = -1
96 integer :: id_uh_z = -1
97 integer :: id_vh_z = -1
98 integer :: id_tr(max_fields_) = -1
99 integer :: id_tr_xyave(max_fields_) = -1
100 integer :: num_tr_used = 0
101 integer :: nk_zspace = -1
103 real,
pointer :: z_int(:) => null()
106 type(
axes_grp) :: axesbzi, axestzi, axescuzi, axescvzi
108 integer,
dimension(1) :: axesz_out
121 real,
dimension(SZI_(G), SZJ_(G), CS%nk_zspace),
intent(in) :: var
122 real,
dimension(SZI_(G), SZJ_(G), CS%nk_zspace) :: tmpForSumming, weight
123 real,
dimension(SZI_(G), SZJ_(G), CS%nk_zspace) :: localVar, valid_point, depth_weight
124 real,
dimension(CS%nk_zspace) :: global_z_mean, scalarij, weightij
125 real,
dimension(CS%nk_zspace) :: global_temp_scalar, global_weight_scalar
126 integer :: i, j, k, is, ie, js, je, nz, tracer
127 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ;
131 valid_point = 1. ; depth_weight = 0.
132 tmpforsumming(:,:,:) = 0. ; weight(:,:,:) = 0.
137 do k=1, nz ;
do j=js,je ;
do i=is, ie
139 depth_weight(i,j,k) = min( max( (-1.*g%bathyT(i,j)), cs%Z_int(k+1) ) - cs%Z_int(k), 0.)
142 if (var(i,j,k) == cs%missing_tr(tracer)) valid_point(i,j,k) = 0.
143 if (depth_weight(i,j,k) == 0.) valid_point(i,j,k) = 0.
146 if (valid_point(i,j,k) == 0.) localvar(i,j,k) = 0.
148 weight(i,j,k) = depth_weight(i,j,k) * ( (valid_point(i,j,k) * (g%areaT(i,j) * g%mask2dT(i,j))) )
149 tmpforsumming(i,j,k) = localvar(i,j,k) * weight(i,j,k)
150 enddo ;
enddo ;
enddo 156 if (scalarij(k) == 0)
then 157 global_z_mean(k) = 0.0
159 global_z_mean(k) = scalarij(k) / weightij(k)
170 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
171 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
173 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
175 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: ssh_in
177 real,
dimension(:,:),
pointer :: frac_shelf_h
194 real :: ssh(szi_(g),szj_(g))
196 real :: h_f(szk_(g)+1,szi_(g))
197 real :: u_f(szk_(g)+1,szib_(g))
198 real :: v_f(szk_(g)+1,szi_(g))
200 real :: tr_f(szk_(g),max(cs%num_tr_used,1),szi_(g))
201 integer :: nk_valid(szib_(g))
203 real :: D_pt(szib_(g))
204 real :: shelf_depth(szib_(g))
207 real :: wt(szk_(g)+1)
209 real :: z1(szk_(g)+1)
210 real :: z2(szk_(g)+1)
214 real :: sl_tr(max(cs%num_tr_used,1))
219 real :: layer_ave(cs%nk_zspace)
221 logical :: linear_velocity_profiles, ice_shelf
223 integer :: k_top, k_bot, k_bot_prev
224 integer :: i, j, k, k2, kz, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nk, m, nkml
225 integer :: IsgB, IegB, JsgB, JegB
226 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nk = g%ke
227 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
228 isgb = g%IsgB ; iegb = g%IegB ; jsgb = g%JsgB ; jegb = g%JegB
229 nkml = max(gv%nkml, 1)
230 angstrom = gv%Angstrom
232 linear_velocity_profiles = .true.
236 if (.not.
associated(cs))
call mom_error(fatal, &
237 "diagnostic_fields_zstar: Module must be initialized before it is used.")
239 ice_shelf =
associated(frac_shelf_h)
242 if ((cs%id_u_z <= 0) .and. (cs%id_v_z <= 0) .and. (cs%num_tr_used < 1))
return 245 if (cs%id_u_z > 0)
then 247 do kz=1,cs%nk_zspace ;
do j=js,je ;
do i=isq,ieq
248 cs%u_z(i,j,kz) = cs%missing_vel
249 enddo ;
enddo ;
enddo 257 d_pt(i) = 0.5*(g%bathyT(i+1,j)+g%bathyT(i,j))
259 if (frac_shelf_h(i,j)+frac_shelf_h(i+1,j) > 0.)
then 260 shelf_depth(i) = abs(0.5*(ssh(i+1,j)+ssh(i,j)))
264 do k=1,nk ;
do i=isq,ieq
265 if ((g%mask2dCu(i,j) > 0.5) .and. (h(i,j,k)+h(i+1,j,k) > 4.0*angstrom))
then 266 nk_valid(i) = nk_valid(i) + 1 ; k2 = nk_valid(i)
267 h_f(k2,i) = 0.5*(h(i,j,k)+h(i+1,j,k)) ; u_f(k2,i) = u(i,j,k)
270 do i=isq,ieq ;
if (g%mask2dCu(i,j) > 0.5)
then 273 nk_valid(i) = nk_valid(i) + 1 ; k2 = nk_valid(i)
274 h_f(k2,i) = angstrom ; u_f(k2,i) = 0.0
278 if (ice_shelf .and. shelf_depth(i) + 1.0e-3 > d_pt(i)) nk_valid(i)=0
282 do i=isq,ieq ;
if (nk_valid(i) > 0)
then 284 htot = 0.0 ;
do k=1,nk_valid(i) ; htot = htot + h_f(k,i) ;
enddo 286 if (htot*gv%H_to_m > 2.0*angstrom)
then 287 dilate = max((d_pt(i) - shelf_depth(i)),angstrom)/htot
289 e(nk_valid(i)+1) = -d_pt(i)
290 do k=nk_valid(i),1,-1 ; e(k) = e(k+1) + h_f(k,i)*dilate ;
enddo 293 k_bot = 1 ; k_bot_prev = -1
295 call find_overlap(e, cs%Z_int(kz), cs%Z_int(kz+1), nk_valid(i), &
296 k_bot, k_top, k_bot, wt, z1, z2)
297 if (k_top>nk_valid(i))
exit 301 if (cs%Z_int(kz)<=-shelf_depth(i))
then 303 if (linear_velocity_profiles)
then 305 if (k /= k_bot_prev)
then 308 if ((k < nk_valid(i)) .and. (k > nkml))
call &
312 cs%u_z(i,j,kz) = wt(k) * (u_f(k,i) + 0.5*slope*(z2(k) + z1(k)))
316 cs%u_z(i,j,kz) = cs%u_z(i,j,kz) + wt(k)*u_f(k,i)
318 if (k_bot > k_top)
then ; k = k_bot
321 if ((k < nk_valid(i)) .and. (k > nkml))
call &
324 cs%u_z(i,j,kz) = cs%u_z(i,j,kz) + wt(k) * &
325 (u_f(k,i) + 0.5*slope*(z2(k) + z1(k)))
331 cs%u_z(i,j,kz) = wt(k_top)*u_f(k_top,i)
333 cs%u_z(i,j,kz) = cs%u_z(i,j,kz) + wt(k)*u_f(k,i)
341 call post_data(cs%id_u_z, cs%u_z, cs%diag)
345 if (cs%id_v_z > 0)
then 346 do kz=1,cs%nk_zspace ;
do j=jsq,jeq ;
do i=is,ie
347 cs%v_z(i,j,kz) = cs%missing_vel
348 enddo ;
enddo ;
enddo 354 nk_valid(i) = 0 ; d_pt(i) = 0.5*(g%bathyT(i,j)+g%bathyT(i,j+1))
356 if (frac_shelf_h(i,j)+frac_shelf_h(i,j+1) > 0.)
then 357 shelf_depth(i) = abs(0.5*(ssh(i,j)+ssh(i,j+1)))
361 do k=1,nk ;
do i=is,ie
362 if ((g%mask2dCv(i,j) > 0.5) .and. (h(i,j,k)+h(i,j+1,k) > 4.0*angstrom))
then 363 nk_valid(i) = nk_valid(i) + 1 ; k2 = nk_valid(i)
364 h_f(k2,i) = 0.5*(h(i,j,k)+h(i,j+1,k)) ; v_f(k2,i) = v(i,j,k)
367 do i=is,ie ;
if (g%mask2dCv(i,j) > 0.5)
then 370 nk_valid(i) = nk_valid(i) + 1 ; k2 = nk_valid(i)
371 h_f(k2,i) = angstrom ; v_f(k2,i) = 0.0
372 if (ice_shelf .and. shelf_depth(i) + 1.0e-3 > d_pt(i)) nk_valid(i)=0
375 do i=is,ie ;
if (nk_valid(i) > 0)
then 377 htot = 0.0 ;
do k=1,nk_valid(i) ; htot = htot + h_f(k,i) ;
enddo 379 if (htot > 2.0*angstrom)
then 380 dilate = max((d_pt(i) - shelf_depth(i)),angstrom)/htot
382 e(nk_valid(i)+1) = -d_pt(i)
383 do k=nk_valid(i),1,-1 ; e(k) = e(k+1) + h_f(k,i)*dilate ;
enddo 386 k_bot = 1 ; k_bot_prev = -1
388 call find_overlap(e, cs%Z_int(kz), cs%Z_int(kz+1), nk_valid(i), &
389 k_bot, k_top, k_bot, wt, z1, z2)
390 if (k_top>nk_valid(i))
exit 393 if (cs%Z_int(kz)<=-shelf_depth(i))
then 394 if (linear_velocity_profiles)
then 396 if (k /= k_bot_prev)
then 399 if ((k < nk_valid(i)) .and. (k > nkml))
call &
403 cs%v_z(i,j,kz) = wt(k) * (v_f(k,i) + 0.5*slope*(z2(k) + z1(k)))
407 cs%v_z(i,j,kz) = cs%v_z(i,j,kz) + wt(k)*v_f(k,i)
409 if (k_bot > k_top)
then ; k = k_bot
412 if ((k < nk_valid(i)) .and. (k > nkml))
call &
415 cs%v_z(i,j,kz) = cs%v_z(i,j,kz) + wt(k) * &
416 (v_f(k,i) + 0.5*slope*(z2(k) + z1(k)))
422 cs%v_z(i,j,kz) = wt(k_top)*v_f(k_top,i)
424 cs%v_z(i,j,kz) = cs%v_z(i,j,kz) + wt(k)*v_f(k,i)
432 call post_data(cs%id_v_z, cs%v_z, cs%diag)
436 if (cs%num_tr_used > 0)
then 438 do m=1,cs%num_tr_used ;
do kz=1,cs%nk_zspace ;
do j=js,je ;
do i=is,ie
439 cs%tr_z(m)%p(i,j,kz) = cs%missing_tr(m)
440 enddo ;
enddo ;
enddo ;
enddo 446 nk_valid(i) = 0 ; d_pt(i) = g%bathyT(i,j)
448 if (frac_shelf_h(i,j) > 0.)
then 449 shelf_depth(i) = abs(ssh(i,j))
453 do k=1,nk ;
do i=is,ie
454 if ((g%mask2dT(i,j) > 0.5) .and. (h(i,j,k) > 2.0*angstrom))
then 455 nk_valid(i) = nk_valid(i) + 1 ; k2 = nk_valid(i)
457 if (ice_shelf .and. shelf_depth(i) + 1.0e-3 > d_pt(i)) nk_valid(i)=0
458 do m=1,cs%num_tr_used ; tr_f(k2,m,i) = cs%tr_model(m)%p(i,j,k) ;
enddo 462 do i=is,ie ;
if (nk_valid(i) > 0)
then 464 htot = 0.0 ;
do k=1,nk_valid(i) ; htot = htot + h_f(k,i) ;
enddo 466 if (htot > 2.0*angstrom)
then 467 dilate = max((d_pt(i) - shelf_depth(i)),angstrom)/htot
469 e(nk_valid(i)+1) = -d_pt(i)
470 do k=nk_valid(i),1,-1 ; e(k) = e(k+1) + h_f(k,i)*dilate ;
enddo 473 k_bot = 1 ; k_bot_prev = -1
475 call find_overlap(e, cs%Z_int(kz), cs%Z_int(kz+1), nk_valid(i), &
476 k_bot, k_top, k_bot, wt, z1, z2)
477 if (k_top>nk_valid(i))
exit 478 if (cs%Z_int(kz)<=-shelf_depth(i))
then 479 do m=1,cs%num_tr_used
481 if (k /= k_bot_prev)
then 484 if ((k < nk_valid(i)) .and. (k > nkml))
call &
488 cs%tr_z(m)%p(i,j,kz) = wt(k) * &
489 (tr_f(k,m,i) + 0.5*sl_tr(m)*(z2(k) + z1(k)))
493 cs%tr_z(m)%p(i,j,kz) = cs%tr_z(m)%p(i,j,kz) + wt(k)*tr_f(k,m,i)
495 if (k_bot > k_top)
then 499 if ((k < nk_valid(i)) .and. (k > nkml))
call &
502 cs%tr_z(m)%p(i,j,kz) = cs%tr_z(m)%p(i,j,kz) + wt(k) * &
503 (tr_f(k,m,i) + 0.5*sl_tr(m)*(z2(k) + z1(k)))
515 do m=1,cs%num_tr_used
516 if (cs%id_tr(m) > 0)
call post_data(cs%id_tr(m), cs%tr_z(m)%p, cs%diag)
517 if (cs%id_tr_xyave(m) > 0)
then 519 call post_data_1d_k(cs%id_tr_xyave(m), layer_ave, cs%diag)
531 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uh_int
533 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vh_int
535 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
537 real,
intent(in) :: dt
555 real,
dimension(SZI_(G), SZJ_(G)) :: &
560 real,
dimension(SZI_(G), max(CS%nk_zspace,1)) :: &
562 real,
dimension(SZIB_(G), max(CS%nk_zspace,1)) :: &
581 real :: Z_int_above(szib_(g))
583 integer :: kz(szib_(g))
585 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nk, nk_z
586 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nk = g%ke
587 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
589 if (.not.
associated(cs))
call mom_error(fatal, &
590 "calculate_Z_transport: Module must be initialized before it is used.")
591 if ((cs%id_uh_Z <= 0) .and. (cs%id_vh_Z <= 0))
return 593 idt = 1.0 ;
if (dt > 0.0) idt = 1.0 / dt
596 if (nk_z <= 0)
return 600 do j=jsq,jeq+1 ;
do i=isq,ieq+1
601 htot(i,j) = gv%H_subroundoff
603 do k=1,nk ;
do j=jsq,jeq+1 ;
do i=isq,ieq+1
604 htot(i,j) = htot(i,j) + h(i,j,k)
605 enddo ;
enddo ;
enddo 606 do j=jsq,jeq+1 ;
do i=isq,ieq+1
607 dilate(i,j) = g%bathyT(i,j) / htot(i,j)
611 if (cs%id_uh_Z > 0)
then ;
do j=js,je
613 kz(i) = nk_z ; z_int_above(i) = -0.5*(g%bathyT(i,j)+g%bathyT(i+1,j))
615 do k=nk_z,1,-1 ;
do i=isq,ieq
617 if (cs%Z_int(k) < z_int_above(i)) kz(i) = k-1
619 do k=nk,1,-1 ;
do i=isq,ieq
620 h_rem = 0.5*(dilate(i,j)*h(i,j,k) + dilate(i+1,j)*h(i+1,j,k))
621 uh_rem = uh_int(i,j,k)
622 z_int_above(i) = z_int_above(i) + h_rem
625 h_above = z_int_above(i) - cs%Z_int(kz(i))
626 if ((kz(i) == 1) .or. (h_above <= 0.0) .or. (h_rem <= 0.0))
then 628 uh_z(i,kz(i)) = uh_z(i,kz(i)) + uh_rem ;
exit 630 h_here = h_rem - h_above
631 uh_here = uh_rem * (h_here / h_rem)
633 h_rem = h_rem - h_here
634 uh_z(i,kz(i)) = uh_z(i,kz(i)) + uh_here
635 uh_rem = uh_rem - uh_here
640 do k=1,nk_z ;
do i=isq,ieq
641 cs%uh_z(i,j,k) = uh_z(i,k)*idt
646 if (cs%id_vh_Z > 0)
then ;
do j=jsq,jeq
648 kz(i) = nk_z ; z_int_above(i) = -0.5*(g%bathyT(i,j)+g%bathyT(i,j+1))
650 do k=nk_z,1,-1 ;
do i=is,ie
652 if (cs%Z_int(k) < z_int_above(i)) kz(i) = k-1
654 do k=nk,1,-1 ;
do i=is,ie
655 h_rem = 0.5*(dilate(i,j)*h(i,j,k) + dilate(i,j+1)*h(i,j+1,k))
656 vh_rem = vh_int(i,j,k)
657 z_int_above(i) = z_int_above(i) + h_rem
660 h_above = z_int_above(i) - cs%Z_int(kz(i))
661 if ((kz(i) == 1) .or. (h_above <= 0.0) .or. (h_rem <= 0.0))
then 663 vh_z(i,kz(i)) = vh_z(i,kz(i)) + vh_rem ;
exit 665 h_here = h_rem - h_above
666 vh_here = vh_rem * (h_here / h_rem)
668 h_rem = h_rem - h_here
669 vh_z(i,kz(i)) = vh_z(i,kz(i)) + vh_here
670 vh_rem = vh_rem - vh_here
675 do k=1,nk_z ;
do i=is,ie
676 cs%vh_z(i,j,k) = vh_z(i,k)*idt
680 if (cs%id_uh_Z > 0)
then 681 do k=1,nk_z ;
do j=js,je ;
do i=isq,ieq
682 cs%uh_z(i,j,k) = cs%uh_z(i,j,k)*gv%H_to_kg_m2
683 enddo ;
enddo ;
enddo 684 call post_data(cs%id_uh_Z, cs%uh_z, cs%diag)
687 if (cs%id_vh_Z > 0)
then 688 do k=1,nk_z ;
do j=jsq,jeq ;
do i=is,ie
689 cs%vh_z(i,j,k) = cs%vh_z(i,j,k)*gv%H_to_kg_m2
690 enddo ;
enddo ;
enddo 691 call post_data(cs%id_vh_Z, cs%vh_z, cs%diag)
700 subroutine find_overlap(e, Z_top, Z_bot, k_max, k_start, k_top, k_bot, wt, z1, z2)
701 real,
dimension(:),
intent(in) :: e
702 real,
intent(in) :: Z_top
703 real,
intent(in) :: Z_bot
704 integer,
intent(in) :: k_max
705 integer,
intent(in) :: k_start
706 integer,
intent(inout) :: k_top
708 integer,
intent(inout) :: k_bot
710 real,
dimension(:),
intent(out) :: wt
711 real,
dimension(:),
intent(out) :: z1, z2
736 real :: Ih, e_c, tot_wt, I_totwt
739 do k=k_start,k_max ;
if (e(k+1)<z_top)
exit ;
enddo 745 if (e(k+1)<=z_bot)
then 746 wt(k) = 1.0 ; k_bot = k
747 ih = 1.0 / (e(k)-e(k+1))
748 e_c = 0.5*(e(k)+e(k+1))
749 z1(k) = (e_c - min(e(k),z_top)) * ih
750 z2(k) = (e_c - z_bot) * ih
752 wt(k) = min(e(k),z_top) - e(k+1) ; tot_wt = wt(k)
753 z1(k) = (0.5*(e(k)+e(k+1)) - min(e(k),z_top)) / (e(k)-e(k+1))
757 if (e(k+1)<=z_bot)
then 759 wt(k) = e(k) - z_bot ; z1(k) = -0.5
760 z2(k) = (0.5*(e(k)+e(k+1)) - z_bot) / (e(k)-e(k+1))
762 wt(k) = e(k) - e(k+1) ; z1(k) = -0.5 ; z2(k) = 0.5
764 tot_wt = tot_wt + wt(k)
768 i_totwt = 1.0 / tot_wt
769 do k=k_top,k_bot ; wt(k) = i_totwt*wt(k) ;
enddo 777 real,
dimension(:),
intent(in) :: val
778 real,
dimension(:),
intent(in) :: e
779 real,
intent(out) :: slope
780 integer,
intent(in) :: k
793 if ((val(k)-val(k-1)) * (val(k)-val(k+1)) >= 0.0)
then 796 d1 = 0.5*(e(k-1)-e(k+1)) ; d2 = 0.5*(e(k)-e(k+2))
797 slope = (d1**2*(val(k+1) - val(k)) + d2**2*(val(k) - val(k-1))) * &
798 ((e(k) - e(k+1)) / (d1*d2*(d1+d2)))
801 slope = sign(1.0,slope) * min(abs(slope), &
802 2.0*(max(val(k-1),val(k),val(k+1)) - val(k)), &
803 2.0*(val(k) - min(val(k-1),val(k),val(k+1))))
812 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
814 type(
p3d),
dimension(:),
intent(in) :: in_ptrs
815 integer,
dimension(:),
intent(in) :: ids
816 integer,
intent(in) :: num_diags
821 real,
dimension(SZI_(G),SZJ_(G),max(CS%nk_zspace+1,1),max(num_diags,1)) :: &
823 real,
dimension(SZI_(G),SZK_(G)+1) :: e
824 real,
dimension(max(num_diags,1),SZI_(G),SZK_(G)+1) :: diag2d
826 real,
dimension(SZI_(G)) :: &
831 integer :: kL(szi_(g))
834 integer :: i, j, k, k2, kz, is, ie, js, je, nk, m
835 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nk = g%ke
837 if (num_diags < 1)
return 838 if (.not.
associated(cs))
call mom_error(fatal, &
839 "calc_Zint_diags: Module must be initialized before it is used.")
843 do i=is,ie ; htot(i) = 0.0 ; kl(i) = 1 ;
enddo 844 do k=1,nk ;
do i=is,ie ; htot(i) = htot(i) + h(i,j,k) ;
enddo ;
enddo 847 if (htot(i)*gv%H_to_m > 0.5) dilate(i) = (g%bathyT(i,j) - 0.0) / htot(i)
848 e(i,nk+1) = -g%bathyT(i,j)
850 do k=nk,1,-1 ;
do i=is,ie
851 e(i,k) = e(i,k+1) + h(i,j,k) * dilate(i)
855 do k=1,nk+1 ;
do i=is,ie ;
do m=1,num_diags
856 diag2d(m,i,k) = in_ptrs(m)%p(i,j,k)
857 enddo ;
enddo ;
enddo 859 do kz=1,cs%nk_zspace+1 ;
do i=is,ie
861 if (cs%Z_int(kz) < e(i,nk+1))
then 864 do k=kl(i),nk+1 ;
if (cs%Z_int(kz) > e(i,k))
exit ;
enddo 868 if (cs%Z_int(kz) > e(i,kl(i)-1))
call mom_error(fatal, &
869 "calc_Zint_diags: Interface depth mapping is incorrect.")
871 if ((kl(i)>1) .and. (kl(i)<=nk+1))
then 872 if (e(i,kl(i)-1) == e(i,kl(i)))
call mom_error(warning, &
873 "calc_Zint_diags: Interface depths equal.", all_print=.true.)
874 if (e(i,kl(i)-1) - e(i,kl(i)) < 0.0)
call mom_error(fatal, &
875 "calc_Zint_diags: Interface depths inverted.")
880 diag_on_z(i,j,kz,m) = diag2d(m,i,1)
882 elseif (kl(i) > nk+1)
then 884 diag_on_z(i,j,kz,m) = cs%missing_value
888 if (e(i,kl(i)-1) - e(i,kl(i)) > 0.0) &
889 wt = (cs%Z_int(kz) - e(i,kl(i))) / (e(i,kl(i)-1) - e(i,kl(i)))
890 if ((wt < 0.0) .or. (wt > 1.0))
call mom_error(fatal, &
891 "calc_Zint_diags: Bad value of wt found.")
893 diag_on_z(i,j,kz,m) = wt * diag2d(m,i,kl(i)-1) + &
894 (1.0-wt) * diag2d(m,i,kl(i))
902 if (ids(m) > 0)
call post_data(ids(m), diag_on_z(:,:,:,m), cs%diag)
908 subroutine register_z_tracer(tr_ptr, name, long_name, units, Time, G, CS, standard_name, &
909 cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
911 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
912 target,
intent(in) :: tr_ptr
913 character(len=*),
intent(in) :: name
914 character(len=*),
intent(in) :: long_name
915 character(len=*),
intent(in) :: units
916 character(len=*),
optional,
intent(in) :: standard_name
917 type(time_type),
intent(in) :: Time
920 character(len=*),
optional,
intent(in) :: cmor_field_name
921 character(len=*),
optional,
intent(in) :: cmor_long_name
922 character(len=*),
optional,
intent(in) :: cmor_units
923 character(len=*),
optional,
intent(in) :: cmor_standard_name
940 character(len=256) :: posted_standard_name
941 character(len=256) :: posted_cmor_units
942 character(len=256) :: posted_cmor_standard_name
943 character(len=256) :: posted_cmor_long_name
945 if (cs%nk_zspace<1)
return 947 if (
present(standard_name))
then 948 posted_standard_name = standard_name
950 posted_standard_name =
'not provided' 955 if (
present(cmor_field_name))
then 957 posted_cmor_units =
"not provided" 958 posted_cmor_standard_name =
"not provided" 959 posted_cmor_long_name =
"not provided" 963 posted_cmor_units = units
964 posted_cmor_long_name = long_name
965 posted_cmor_standard_name = posted_standard_name
968 if (
present(cmor_units)) posted_cmor_units = cmor_units
969 if (
present(cmor_standard_name)) posted_cmor_standard_name = cmor_standard_name
970 if (
present(cmor_long_name)) posted_cmor_long_name = cmor_long_name
973 trim(posted_cmor_units), trim(posted_cmor_standard_name), time, g, cs)
982 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
983 target,
intent(in) :: tr_ptr
984 character(len=*),
intent(in) :: name
985 character(len=*),
intent(in) :: long_name
986 character(len=*),
intent(in) :: units
987 character(len=*),
intent(in) :: standard_name
988 type(time_type),
intent(in) :: Time
1003 character(len=256) :: posted_standard_name
1004 integer :: isd, ied, jsd, jed, nk, m, id_test
1005 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nk = g%ke
1007 if (.not.
associated(cs))
call mom_error(fatal, &
1008 "register_Z_tracer: Module must be initialized before it is used.")
1010 if (cs%num_tr_used >= max_fields_)
then 1011 call mom_error(warning,
"MOM_diag_to_Z: Attempted to register and use "//&
1012 "more than MAX_FIELDS_ z-space tracers via register_Z_tracer.")
1016 m = cs%num_tr_used + 1
1018 cs%missing_tr(m) = cs%missing_value
1019 if (cs%nk_zspace > 0)
then 1020 cs%id_tr(m) = register_diag_field(
'ocean_model_zold', name, cs%axesTz, time, &
1021 long_name, units, missing_value=cs%missing_tr(m), &
1022 standard_name=standard_name)
1023 cs%id_tr_xyave(m) = register_diag_field(
'ocean_model_zold', name//
'_xyave', cs%axesZ, time, &
1024 long_name, units, missing_value=cs%missing_tr(m), &
1025 standard_name=standard_name)
1027 id_test = register_diag_field(
'ocean_model_zold', name, cs%diag%axesT1, time, &
1028 long_name, units, missing_value=cs%missing_tr(m), &
1029 standard_name=standard_name)
1030 if (id_test>0)
call mom_error(warning, &
1031 "MOM_diag_to_Z_init: "//trim(name)// &
1032 " cannot be output without an appropriate depth-space target file.")
1035 if (cs%id_tr(m) <= 0) cs%id_tr(m) = -1
1036 if (cs%id_tr_xyave(m) <= 0) cs%id_tr_xyave(m) = -1
1037 if (cs%id_tr(m) > 0 .or. cs%id_tr_xyave(m) > 0)
then 1039 call safe_alloc_ptr(cs%tr_z(m)%p,isd,ied,jsd,jed,cs%nk_zspace)
1040 cs%tr_model(m)%p => tr_ptr
1047 type(time_type),
intent(in) :: Time
1052 type(
diag_ctrl),
target,
intent(inout) :: diag
1065 #include "version_variable.h" 1067 character(len=40) :: mdl =
"MOM_diag_to_Z" 1068 character(len=200) :: in_dir, zgrid_file
1069 character(len=48) :: flux_units, string
1070 integer :: z_axis, zint_axis
1071 integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB, nk, id_test
1072 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nk = g%ke
1073 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1075 if (
associated(cs))
then 1076 call mom_error(warning,
"MOM_diag_to_Z_init called with an associated "// &
1077 "control structure.")
1082 if (gv%Boussinesq)
then ; flux_units =
"meter3 second-1" 1083 else ; flux_units =
"kilogram second-1" ;
endif 1090 call get_param(param_file, mdl,
"Z_OUTPUT_GRID_FILE", zgrid_file, &
1091 "The file that specifies the vertical grid for \n"//&
1092 "depth-space diagnostics, or blank to disable \n"//&
1093 "depth-space output.", default=
"")
1095 if (len_trim(zgrid_file) > 0)
then 1096 call get_param(param_file, mdl,
"INPUTDIR", in_dir, &
1097 "The directory in which input files are found.", default=
".")
1098 in_dir = slasher(in_dir)
1099 call get_z_depths(trim(in_dir)//trim(zgrid_file),
"zw", cs%Z_int,
"zt", &
1100 z_axis, zint_axis, cs%nk_zspace)
1101 call log_param(param_file, mdl,
"!INPUTDIR/Z_OUTPUT_GRID_FILE", &
1102 trim(in_dir)//trim(zgrid_file))
1103 call log_param(param_file, mdl,
"!NK_ZSPACE (from file)", cs%nk_zspace, &
1104 "The number of depth-space levels. This is determined \n"//&
1105 "from the size of the variable zw in the output grid file.", &
1111 if (cs%nk_zspace > 0)
then 1113 call define_axes_group(diag, (/ diag%axesB1%handles(1), diag%axesB1%handles(2), z_axis /), cs%axesBz)
1114 call define_axes_group(diag, (/ diag%axesT1%handles(1), diag%axesT1%handles(2), z_axis /), cs%axesTz)
1115 call define_axes_group(diag, (/ diag%axesCu1%handles(1), diag%axesCu1%handles(2), z_axis /), cs%axesCuz)
1116 call define_axes_group(diag, (/ diag%axesCv1%handles(1), diag%axesCv1%handles(2), z_axis /), cs%axesCvz)
1117 call define_axes_group(diag, (/ diag%axesB1%handles(1), diag%axesB1%handles(2), zint_axis /), cs%axesBzi)
1118 call define_axes_group(diag, (/ diag%axesT1%handles(1), diag%axesT1%handles(2), zint_axis /), cs%axesTzi)
1119 call define_axes_group(diag, (/ diag%axesCu1%handles(1), diag%axesCu1%handles(2), zint_axis /), cs%axesCuzi)
1120 call define_axes_group(diag, (/ diag%axesCv1%handles(1), diag%axesCv1%handles(2), zint_axis /), cs%axesCvzi)
1121 call define_axes_group(diag, (/ z_axis /), cs%axesZ)
1123 cs%id_u_z = register_diag_field(
'ocean_model_zold',
'u', cs%axesCuz, time, &
1124 'Zonal Velocity in Depth Space',
'meter second-1', &
1125 missing_value=cs%missing_vel, cmor_field_name=
'uo', cmor_units=
'm s-1',&
1126 cmor_standard_name=
'sea_water_x_velocity', cmor_long_name=
'Sea Water X Velocity')
1127 if (cs%id_u_z>0)
call safe_alloc_ptr(cs%u_z,isdb,iedb,jsd,jed,cs%nk_zspace)
1129 cs%id_v_z = register_diag_field(
'ocean_model_zold',
'v', cs%axesCvz, time, &
1130 'Meridional Velocity in Depth Space',
'meter second-1', &
1131 missing_value=cs%missing_vel, cmor_field_name=
'vo', cmor_units=
'm s-1',&
1132 cmor_standard_name=
'sea_water_y_velocity', cmor_long_name=
'Sea Water Y Velocity')
1133 if (cs%id_v_z>0)
call safe_alloc_ptr(cs%v_z,isd,ied,jsdb,jedb,cs%nk_zspace)
1135 cs%id_uh_z = register_diag_field(
'ocean_model_zold',
'uh', cs%axesCuz, time, &
1136 'Zonal Mass Transport (including SGS param) in Depth Space', flux_units, &
1137 missing_value=cs%missing_trans)
1138 if (cs%id_uh_z>0)
call safe_alloc_ptr(cs%uh_z,isdb,iedb,jsd,jed,cs%nk_zspace)
1140 cs%id_vh_z = register_diag_field(
'ocean_model_zold',
'vh', cs%axesCvz, time, &
1141 'Meridional Mass Transport (including SGS param) in Depth Space', flux_units,&
1142 missing_value=cs%missing_trans)
1143 if (cs%id_vh_z>0)
call safe_alloc_ptr(cs%vh_z,isd,ied,jsdb,jedb,cs%nk_zspace)
1153 subroutine get_z_depths(depth_file, int_depth_name, int_depth, cell_depth_name, &
1154 z_axis_index, edge_index, nk_out)
1155 character(len=*),
intent(in) :: depth_file
1156 character(len=*),
intent(in) :: int_depth_name
1157 real,
dimension(:),
pointer :: int_depth
1158 character(len=*),
intent(in) :: cell_depth_name
1159 integer,
intent(out) :: z_axis_index
1160 integer,
intent(out) :: edge_index
1161 integer,
intent(out) :: nk_out
1168 real,
allocatable :: cell_depth(:)
1169 character (len=200) :: units, long_name
1170 integer :: ncid, status, intid, intvid, layid, layvid, k, ni
1174 status = nf90_open(depth_file, nf90_nowrite, ncid);
1175 if (status /= nf90_noerr)
then 1176 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1177 " Difficulties opening "//trim(depth_file)//
" - "//&
1178 trim(nf90_strerror(status)))
1179 nk_out = -1 ;
return 1182 status = nf90_inq_dimid(ncid, int_depth_name, intid)
1183 if (status /= nf90_noerr)
then 1184 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1185 trim(nf90_strerror(status))//
" Getting ID of dimension "//&
1186 trim(int_depth_name)//
" in "//trim(depth_file))
1187 nk_out = -1 ;
return 1190 status = nf90_inquire_dimension(ncid, intid, len=ni)
1191 if (status /= nf90_noerr)
then 1192 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1193 trim(nf90_strerror(status))//
" Getting number of interfaces of "//&
1194 trim(int_depth_name)//
" in "//trim(depth_file))
1195 nk_out = -1 ;
return 1199 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1200 "At least two interface depths must be specified in "//trim(depth_file))
1201 nk_out = -1 ;
return 1204 status = nf90_inq_dimid(ncid, cell_depth_name, layid)
1205 if (status /= nf90_noerr)
call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1206 trim(nf90_strerror(status))//
" Getting ID of dimension "//&
1207 trim(cell_depth_name)//
" in "//trim(depth_file))
1209 status = nf90_inquire_dimension(ncid, layid, len=nk_out)
1210 if (status /= nf90_noerr)
call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1211 trim(nf90_strerror(status))//
" Getting number of interfaces of "//&
1212 trim(cell_depth_name)//
" in "//trim(depth_file))
1214 if (ni /= nk_out+1)
then 1215 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1216 "The interface depths must have one more point than cell centers in "//&
1218 nk_out = -1 ;
return 1221 allocate(int_depth(nk_out+1))
1222 allocate(cell_depth(nk_out))
1224 status = nf90_inq_varid(ncid, int_depth_name, intvid)
1225 if (status /= nf90_noerr)
call mom_error(fatal,
"MOM_diag_to_Z get_Z_depths: "//&
1226 trim(nf90_strerror(status))//
" Getting ID of variable "//&
1227 trim(int_depth_name)//
" in "//trim(depth_file))
1228 status = nf90_get_var(ncid, intvid, int_depth)
1229 if (status /= nf90_noerr)
call mom_error(fatal,
"MOM_diag_to_Z get_Z_depths: "//&
1230 trim(nf90_strerror(status))//
" Reading variable "//&
1231 trim(int_depth_name)//
" in "//trim(depth_file))
1232 status = nf90_get_att(ncid, intvid,
"units", units)
1233 if (status /= nf90_noerr) units =
"meters" 1234 status = nf90_get_att(ncid, intvid,
"long_name", long_name)
1235 if (status /= nf90_noerr) long_name =
"Depth of edges" 1236 edge_index = diag_axis_init(int_depth_name, int_depth, units,
'z', &
1237 long_name, direction=-1)
1240 status = nf90_inq_varid(ncid, cell_depth_name, layvid)
1241 if (status /= nf90_noerr)
call mom_error(fatal,
"MOM_diag_to_Z get_Z_depths: "//&
1242 trim(nf90_strerror(status))//
" Getting ID of variable "//&
1243 trim(cell_depth_name)//
" in "//trim(depth_file))
1244 status = nf90_get_var(ncid, layvid, cell_depth)
1245 if (status /= nf90_noerr)
call mom_error(fatal,
"MOM_diag_to_Z get_Z_depths: "//&
1246 trim(nf90_strerror(status))//
" Reading variable "//&
1247 trim(cell_depth_name)//
" in "//trim(depth_file))
1248 status = nf90_get_att(ncid, layvid,
"units", units)
1249 if (status /= nf90_noerr) units =
"meters" 1250 status = nf90_get_att(ncid, layvid,
"long_name", long_name)
1251 if (status /= nf90_noerr) long_name =
"Depth of cell center" 1253 z_axis_index = diag_axis_init(cell_depth_name, cell_depth, units,
'z',&
1254 long_name, edges = edge_index, direction=-1)
1256 deallocate(cell_depth)
1258 status = nf90_close(ncid)
1261 if (int_depth(1) < int_depth(2))
then 1262 do k=1,nk_out+1 ; int_depth(k) = -1*int_depth(k) ;
enddo 1266 do k=1,nk_out ;
if (int_depth(k) < int_depth(k+1))
then 1267 call mom_error(warning,
"MOM_diag_to_Z get_Z_depths: "//&
1268 "Inverted interface depths in output grid in "//depth_file)
1269 nk_out = -1 ;
deallocate(int_depth) ;
return 1278 if (
ASSOCIATED(cs%u_z))
deallocate(cs%u_z)
1279 if (
ASSOCIATED(cs%v_z))
deallocate(cs%v_z)
1280 if (
ASSOCIATED(cs%Z_int))
deallocate(cs%Z_int)
1281 do m=1,cs%num_tr_used ;
deallocate(cs%tr_z(m)%p) ;
enddo 1290 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1291 target,
intent(in) :: tr_ptr
1292 type(
vardesc),
intent(in) :: vardesc_tr
1293 type(time_type),
intent(in) :: Time
1296 integer :: ocean_register_diag_with_z
1307 character(len=64) :: var_name
1308 integer :: isd, ied, jsd, jed, nk, m, id_test
1309 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nk = g%ke
1310 if (.not.
associated(cs))
call mom_error(fatal, &
1311 "register_Z_tracer: Module must be initialized before it is used.")
1312 if (cs%nk_zspace<1)
return 1314 if (cs%num_tr_used >= max_fields_)
then 1315 call mom_error(warning,
"ocean_register_diag_with_z: Attempted to register and use "//&
1316 "more than MAX_FIELDS_ z-space tracers via ocean_register_diag_with_z.")
1325 vardesc_z = vardesc_tr
1326 call modify_vardesc(vardesc_z, z_grid=
"z", caller=
"ocean_register_diag_with_z")
1327 m = cs%num_tr_used + 1
1328 cs%missing_tr(m) = cs%missing_value
1333 if (cs%id_tr(m)>0)
then 1337 call safe_alloc_ptr(cs%tr_z(m)%p,isd,ied,jsd,jed,cs%nk_zspace)
1340 cs%tr_model(m)%p => tr_ptr
1345 call query_vardesc(vardesc_z, name=var_name, caller=
"ocean_register_diag_with_z")
1346 if (cs%id_tr(m)>0)
call mom_error(warning, &
1347 "ocean_register_diag_with_z: "//trim(var_name)// &
1348 " cannot be output without an appropriate depth-space target file.")
1354 integer :: register_Z_diag
1355 type(
vardesc),
intent(in) :: var_desc
1357 type(time_type),
intent(in) :: day
1358 real,
intent(in) :: missing
1360 character(len=64) :: var_name
1361 character(len=48) :: units
1362 character(len=240) :: longname
1363 character(len=8) :: hor_grid, z_grid
1366 call query_vardesc(var_desc, name=var_name, units=units, longname=longname, &
1367 hor_grid=hor_grid, z_grid=z_grid, caller=
"register_Zint_diag")
1371 select case (z_grid)
1374 select case (hor_grid)
1393 "register_Z_diag: unknown hor_grid component "//trim(hor_grid))
1398 "register_Z_diag: unknown z_grid component "//trim(z_grid))
1401 register_z_diag = register_diag_field(
"ocean_model_zold", trim(var_name), axes, &
1402 day, trim(longname), trim(units), missing_value=missing)
1407 integer :: register_Zint_diag
1408 type(
vardesc),
intent(in) :: var_desc
1410 type(time_type),
intent(in) :: day
1412 character(len=64) :: var_name
1413 character(len=48) :: units
1414 character(len=240) :: longname
1415 character(len=8) :: hor_grid
1418 call query_vardesc(var_desc, name=var_name, units=units, longname=longname, &
1419 hor_grid=hor_grid, caller=
"register_Zint_diag")
1421 if (cs%nk_zspace < 0)
then 1422 register_zint_diag = -1 ;
return 1427 select case (hor_grid)
1438 "register_Z_diag: unknown hor_grid component "//trim(hor_grid))
1441 register_zint_diag = register_diag_field(
"ocean_model_zold", trim(var_name),&
1442 axes, day, trim(longname), trim(units), missing_value=cs%missing_value)
subroutine, public find_limited_slope(val, e, slope, k)
This subroutine determines a limited slope for val to be advected with a piecewise limited scheme...
subroutine register_z_tracer_low(tr_ptr, name, long_name, units, standard_name, Time, G, CS)
This subroutine registers a tracer to be output in depth space.
subroutine, public find_overlap(e, Z_top, Z_bot, k_max, k_start, k_top, k_bot, wt, z1, z2)
This subroutine determines the layers bounded by interfaces e that overlap with the depth range betwe...
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
This module contains I/O framework code.
subroutine, public mom_diag_to_z_end(CS)
integer function, public ocean_register_diag_with_z(tr_ptr, vardesc_tr, G, Time, CS)
This subroutine registers a tracer to be output in depth space.
subroutine get_z_depths(depth_file, int_depth_name, int_depth, cell_depth_name, z_axis_index, edge_index, nk_out)
This subroutine reads the depths of the interfaces bounding the intended layers from a NetCDF file...
real function, dimension(gv %ke), public global_layer_mean(var, h, G, GV)
subroutine, public calculate_z_diag_fields(u, v, h, ssh_in, frac_shelf_h, G, GV, CS)
This subroutine maps tracers and velocities into depth space for diagnostics.
subroutine, public register_z_tracer(tr_ptr, name, long_name, units, Time, G, CS, standard_name, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
This subroutine registers a tracer to be output in depth space.
Type for describing a variable, typically a tracer.
subroutine, public calculate_z_transport(uh_int, vh_int, h, dt, G, GV, CS)
This subroutine maps horizontal transport into depth space for diagnostic output. ...
real function, dimension(cs%nk_zspace) global_z_mean(var, G, CS, tracer)
integer function, public register_zint_diag(var_desc, CS, day)
subroutine, public mom_diag_to_z_init(Time, G, GV, param_file, diag, CS)
subroutine, public query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine queries vardesc.
subroutine, public mom_error(level, message, all_print)
subroutine, public calc_zint_diags(h, in_ptrs, ids, num_diags, G, GV, CS)
subroutine, public modify_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine modifies the named elements of a vardesc type. All arguments are optional, except the vardesc type to be modified.
integer, parameter no_zspace
integer function register_z_diag(var_desc, CS, day, missing)