7 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
8 use mom_cpu_clock,
only : clock_module_driver, clock_module, clock_routine
25 use time_interp_external_mod,
only : init_external_field, time_interp_external
26 use time_interp_external_mod,
only : time_interp_external_init
28 implicit none ;
private
30 #include <MOM_memory.h>
32 public diabatic_aux_init, diabatic_aux_end
33 public make_frazil, adjust_salt, insert_brine, differential_diffuse_t_s, tridiagts
34 public find_uv_at_h, diagnosemldbydensitydifference, applyboundaryfluxesinout, set_pen_shortwave
43 logical :: do_rivermix = .false.
45 real :: rivermix_depth = 0.0
46 logical :: reclaim_frazil
49 logical :: pressure_dependent_frazil
53 logical :: ignore_fluxes_over_land
57 logical :: use_river_heat_content
60 logical :: use_calving_heat_content
67 logical :: chl_from_file
69 type(time_type),
pointer :: time => null()
73 integer :: id_createdh = -1
74 integer :: id_brine_lay = -1
75 integer :: id_pensw_diag = -1
76 integer :: id_penswflux_diag = -1
77 integer :: id_nonpensw_diag = -1
78 integer :: id_chl = -1
81 real,
allocatable,
dimension(:,:) :: createdh
83 real,
allocatable,
dimension(:,:,:) :: pensw_diag
85 real,
allocatable,
dimension(:,:,:) :: penswflux_diag
87 real,
allocatable,
dimension(:,:) :: nonpensw_diag
93 integer :: id_clock_uv_at_h, id_clock_frazil
102 subroutine make_frazil(h, tv, G, GV, CS, p_surf, halo)
105 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
111 real,
dimension(SZI_(G),SZJ_(G)), &
112 optional,
intent(in) :: p_surf
113 integer,
optional,
intent(in) :: halo
116 real,
dimension(SZI_(G)) :: &
120 real,
dimension(SZI_(G),SZK_(G)) :: &
125 integer :: i, j, k, is, ie, js, je, nz
127 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
128 if (
present(halo))
then
129 is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
132 call cpu_clock_begin(id_clock_frazil)
134 if (.not.cs%pressure_dependent_frazil)
then
135 do k=1,nz ;
do i=is,ie ; pressure(i,k) = 0.0 ;
enddo ;
enddo
142 if (
PRESENT(p_surf))
then ;
do i=is,ie
146 do i=is,ie ; fraz_col(i) = 0.0 ;
enddo
148 if (cs%pressure_dependent_frazil)
then
150 pressure(i,1) = ps(i) + (0.5*gv%H_to_Pa)*h(i,j,1)
152 do k=2,nz ;
do i=is,ie
153 pressure(i,k) = pressure(i,k-1) + &
154 (0.5*gv%H_to_Pa) * (h(i,j,k) + h(i,j,k-1))
158 if (cs%reclaim_frazil)
then
160 do i=is,ie ;
if (tv%frazil(i,j) > 0.0)
then
161 if (.not.t_fr_set)
then
163 1, ie-i+1, tv%eqn_of_state)
167 if (tv%T(i,j,1) > t_freeze(i))
then
170 hc = (tv%C_p*gv%H_to_kg_m2) * h(i,j,1)
171 if (tv%frazil(i,j) - hc * (tv%T(i,j,1) - t_freeze(i)) <= 0.0)
then
172 tv%T(i,j,1) = tv%T(i,j,1) - tv%frazil(i,j)/hc
175 tv%frazil(i,j) = tv%frazil(i,j) - hc * (tv%T(i,j,1) - t_freeze(i))
176 tv%T(i,j,1) = t_freeze(i)
185 if ((g%mask2dT(i,j) > 0.0) .and. &
186 ((tv%T(i,j,k) < 0.0) .or. (fraz_col(i) > 0.0)))
then
187 if (.not.t_fr_set)
then
189 1, ie-i+1, tv%eqn_of_state)
193 hc = (tv%C_p*gv%H_to_kg_m2) * h(i,j,k)
194 if (h(i,j,k) <= 10.0*gv%Angstrom_H)
then
196 if (tv%T(i,j,k) < t_freeze(i))
then
197 fraz_col(i) = fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k))
198 tv%T(i,j,k) = t_freeze(i)
201 if (fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k)) <= 0.0)
then
202 tv%T(i,j,k) = tv%T(i,j,k) - fraz_col(i)/hc
205 fraz_col(i) = fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k))
206 tv%T(i,j,k) = t_freeze(i)
213 tv%frazil(i,j) = tv%frazil(i,j) + fraz_col(i)
216 call cpu_clock_end(id_clock_frazil)
218 end subroutine make_frazil
222 subroutine differential_diffuse_t_s(h, tv, visc, dt, G, GV)
225 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
231 real,
intent(in) :: dt
234 real,
dimension(SZI_(G)) :: &
237 real,
dimension(SZI_(G),SZK_(G)) :: &
239 real,
dimension(SZI_(G),SZK_(G)+1) :: &
249 real,
dimension(:,:,:),
pointer :: t=>null(), s=>null()
250 real,
dimension(:,:,:),
pointer :: kd_t=>null(), kd_s=>null()
251 integer :: i, j, k, is, ie, js, je, nz
253 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
254 h_neglect = gv%H_subroundoff
256 if (.not.
associated(tv%T))
call mom_error(fatal, &
257 "differential_diffuse_T_S: Called with an unassociated tv%T")
258 if (.not.
associated(tv%S))
call mom_error(fatal, &
259 "differential_diffuse_T_S: Called with an unassociated tv%S")
260 if (.not.
associated(visc%Kd_extra_T))
call mom_error(fatal, &
261 "differential_diffuse_T_S: Called with an unassociated visc%Kd_extra_T")
262 if (.not.
associated(visc%Kd_extra_S))
call mom_error(fatal, &
263 "differential_diffuse_T_S: Called with an unassociated visc%Kd_extra_S")
265 t => tv%T ; s => tv%S
266 kd_t => visc%Kd_extra_T ; kd_s => visc%Kd_extra_S
272 i_h_int = 1.0 / (0.5 * (h(i,j,1) + h(i,j,2)) + h_neglect)
273 mix_t(i,2) = ((dt * kd_t(i,j,2)) * gv%Z_to_H**2) * i_h_int
274 mix_s(i,2) = ((dt * kd_s(i,j,2)) * gv%Z_to_H**2) * i_h_int
276 h_tr = h(i,j,1) + h_neglect
277 b1_t(i) = 1.0 / (h_tr + mix_t(i,2))
278 b1_s(i) = 1.0 / (h_tr + mix_s(i,2))
279 d1_t(i) = h_tr * b1_t(i)
280 d1_s(i) = h_tr * b1_s(i)
281 t(i,j,1) = (b1_t(i)*h_tr)*t(i,j,1)
282 s(i,j,1) = (b1_s(i)*h_tr)*s(i,j,1)
284 do k=2,nz-1 ;
do i=is,ie
286 i_h_int = 1.0 / (0.5 * (h(i,j,k) + h(i,j,k+1)) + h_neglect)
287 mix_t(i,k+1) = ((dt * kd_t(i,j,k+1)) * gv%Z_to_H**2) * i_h_int
288 mix_s(i,k+1) = ((dt * kd_s(i,j,k+1)) * gv%Z_to_H**2) * i_h_int
290 c1_t(i,k) = mix_t(i,k) * b1_t(i)
291 c1_s(i,k) = mix_s(i,k) * b1_s(i)
293 h_tr = h(i,j,k) + h_neglect
294 b_denom_t = h_tr + d1_t(i)*mix_t(i,k)
295 b_denom_s = h_tr + d1_s(i)*mix_s(i,k)
296 b1_t(i) = 1.0 / (b_denom_t + mix_t(i,k+1))
297 b1_s(i) = 1.0 / (b_denom_s + mix_s(i,k+1))
298 d1_t(i) = b_denom_t * b1_t(i)
299 d1_s(i) = b_denom_s * b1_s(i)
301 t(i,j,k) = b1_t(i) * (h_tr*t(i,j,k) + mix_t(i,k)*t(i,j,k-1))
302 s(i,j,k) = b1_s(i) * (h_tr*s(i,j,k) + mix_s(i,k)*s(i,j,k-1))
305 c1_t(i,nz) = mix_t(i,nz) * b1_t(i)
306 c1_s(i,nz) = mix_s(i,nz) * b1_s(i)
308 h_tr = h(i,j,nz) + h_neglect
309 b1_t(i) = 1.0 / (h_tr + d1_t(i)*mix_t(i,nz))
310 b1_s(i) = 1.0 / (h_tr + d1_s(i)*mix_s(i,nz))
312 t(i,j,nz) = b1_t(i) * (h_tr*t(i,j,nz) + mix_t(i,nz)*t(i,j,nz-1))
313 s(i,j,nz) = b1_s(i) * (h_tr*s(i,j,nz) + mix_s(i,nz)*s(i,j,nz-1))
315 do k=nz-1,1,-1 ;
do i=is,ie
316 t(i,j,k) = t(i,j,k) + c1_t(i,k+1)*t(i,j,k+1)
317 s(i,j,k) = s(i,j,k) + c1_s(i,k+1)*s(i,j,k+1)
320 end subroutine differential_diffuse_t_s
325 subroutine adjust_salt(h, tv, G, GV, CS, halo)
328 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
334 integer,
optional,
intent(in) :: halo
337 real :: salt_add_col(szi_(g),szj_(g))
340 integer :: i, j, k, is, ie, js, je, nz
342 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
343 if (
present(halo))
then
344 is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
349 s_min = tv%min_salinity
351 salt_add_col(:,:) = 0.0
355 do k=nz,1,-1 ;
do i=is,ie
356 if ( (g%mask2dT(i,j) > 0.0) .and. &
357 ((tv%S(i,j,k) < s_min) .or. (salt_add_col(i,j) > 0.0)) )
then
358 mc = gv%H_to_kg_m2 * h(i,j,k)
359 if (h(i,j,k) <= 10.0*gv%Angstrom_H)
then
361 if (tv%S(i,j,k) < s_min)
then
362 salt_add_col(i,j) = salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k))
365 elseif (salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k)) <= 0.0)
then
366 tv%S(i,j,k) = tv%S(i,j,k) - salt_add_col(i,j) / mc
367 salt_add_col(i,j) = 0.0
369 salt_add_col(i,j) = salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k))
375 tv%salt_deficit(i,j) = tv%salt_deficit(i,j) + salt_add_col(i,j)
380 end subroutine adjust_salt
385 subroutine insert_brine(h, tv, G, GV, fluxes, nkmb, CS, dt, id_brine_lay)
388 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
392 type(
forcing),
intent(in) :: fluxes
393 integer,
intent(in) :: nkmb
396 real,
intent(in) :: dt
397 integer,
intent(in) :: id_brine_lay
401 real :: salt(szi_(g))
403 real :: dzbr(szi_(g))
404 real :: inject_layer(szi_(g),szj_(g))
406 real :: p_ref_cv(szi_(g))
407 real :: t(szi_(g),szk_(g))
408 real :: s(szi_(g),szk_(g))
409 real :: h_2d(szi_(g),szk_(g))
410 real :: rcv(szi_(g),szk_(g))
412 real :: s_new,r_new,t0,scale, cdz
413 integer :: i, j, k, is, ie, js, je, nz, ks
415 real,
parameter :: brine_dz = 1.0
416 real,
parameter :: s_max = 45.0
418 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
420 if (.not.
associated(fluxes%salt_flux))
return
422 p_ref_cv(:) = tv%P_ref
424 inject_layer(:,:) = nz
428 salt(:)=0.0 ; dzbr(:)=0.0
430 do i=is,ie ;
if (g%mask2dT(i,j) > 0.)
then
431 salt(i) = dt * (1000. * fluxes%salt_flux(i,j))
436 t(i,k)=tv%T(i,j,k); s(i,k)=tv%S(i,j,k)
438 h_2d(i,k)=max(h(i,j,k), gv%Angstrom_H)
442 ie-is+1, tv%eqn_of_state)
449 do k=nkmb+1,nz-1 ;
do i=is,ie
450 if ((g%mask2dT(i,j) > 0.0) .and. dzbr(i) < brine_dz .and. salt(i) > 0.)
then
451 mc = gv%H_to_kg_m2 * h_2d(i,k)
452 s_new = s(i,k) + salt(i)/mc
455 if (r_new < 0.5*(rcv(i,k)+rcv(i,k+1)) .and. s_new<s_max)
then
456 dzbr(i)=dzbr(i)+h_2d(i,k)
457 inject_layer(i,j) = min(inject_layer(i,j),real(k))
463 do k=nkmb,gv%nkml+1,-1 ;
do i=is,ie
464 if ((g%mask2dT(i,j) > 0.0) .and. dzbr(i) < brine_dz .and. salt(i) > 0.)
then
465 mc = gv%H_to_kg_m2 * h_2d(i,k)
466 dzbr(i)=dzbr(i)+h_2d(i,k)
467 inject_layer(i,j) = min(inject_layer(i,j),real(k))
473 do k=1,gv%nkml ;
do i=is,ie
474 if ((g%mask2dT(i,j) > 0.0) .and. dzbr(i) < brine_dz .and. salt(i) > 0.)
then
475 mc = gv%H_to_kg_m2 * h_2d(i,k)
476 dzbr(i)=dzbr(i)+h_2d(i,k)
477 inject_layer(i,j) = min(inject_layer(i,j),real(k))
483 if ((g%mask2dT(i,j) > 0.0) .and. salt(i) > 0.)
then
488 mc = gv%H_to_kg_m2 * h_2d(i,k)
489 scale = h_2d(i,k)/dzbr(i)
492 tv%S(i,j,k) = tv%S(i,j,k) + scale*salt(i)/mc
499 if (cs%id_brine_lay > 0)
call post_data(cs%id_brine_lay, inject_layer, cs%diag)
501 end subroutine insert_brine
505 subroutine tridiagts(G, GV, is, ie, js, je, hold, ea, eb, T, S)
508 integer,
intent(in) :: is
509 integer,
intent(in) :: ie
510 integer,
intent(in) :: js
511 integer,
intent(in) :: je
512 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: hold
514 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: ea
516 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: eb
518 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: t
519 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: s
522 real :: b1(szib_(g)), d1(szib_(g))
523 real :: c1(szib_(g),szk_(g))
524 real :: h_tr, b_denom_1
530 h_tr = hold(i,j,1) + gv%H_subroundoff
531 b1(i) = 1.0 / (h_tr + eb(i,j,1))
533 t(i,j,1) = (b1(i)*h_tr)*t(i,j,1)
534 s(i,j,1) = (b1(i)*h_tr)*s(i,j,1)
536 do k=2,g%ke ;
do i=is,ie
537 c1(i,k) = eb(i,j,k-1) * b1(i)
538 h_tr = hold(i,j,k) + gv%H_subroundoff
539 b_denom_1 = h_tr + d1(i)*ea(i,j,k)
540 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
541 d1(i) = b_denom_1 * b1(i)
542 t(i,j,k) = b1(i) * (h_tr*t(i,j,k) + ea(i,j,k)*t(i,j,k-1))
543 s(i,j,k) = b1(i) * (h_tr*s(i,j,k) + ea(i,j,k)*s(i,j,k-1))
545 do k=g%ke-1,1,-1 ;
do i=is,ie
546 t(i,j,k) = t(i,j,k) + c1(i,k+1)*t(i,j,k+1)
547 s(i,j,k) = s(i,j,k) + c1(i,k+1)*s(i,j,k+1)
550 end subroutine tridiagts
554 subroutine find_uv_at_h(u, v, h, u_h, v_h, G, GV, ea, eb)
557 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
559 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
561 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
563 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
565 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
567 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
568 optional,
intent(in) :: ea
571 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
572 optional,
intent(in) :: eb
580 real :: b1(szi_(g)), d1(szi_(g)), c1(szi_(g),szk_(g))
581 real :: a_n(szi_(g)), a_s(szi_(g))
582 real :: a_e(szi_(g)), a_w(szi_(g))
585 logical :: mix_vertically
586 integer :: i, j, k, is, ie, js, je, nz
587 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
588 call cpu_clock_begin(id_clock_uv_at_h)
589 h_neglect = gv%H_subroundoff
591 mix_vertically =
present(ea)
592 if (
present(ea) .neqv.
present(eb))
call mom_error(fatal, &
593 "find_uv_at_h: Either both ea and eb or neither one must be present "// &
594 "in call to find_uv_at_h.")
600 s = g%areaCu(i-1,j)+g%areaCu(i,j)
602 idenom = sqrt(0.5*g%IareaT(i,j)/s)
603 a_w(i) = g%areaCu(i-1,j)*idenom
604 a_e(i) = g%areaCu(i,j)*idenom
606 a_w(i) = 0.0 ; a_e(i) = 0.0
609 s = g%areaCv(i,j-1)+g%areaCv(i,j)
611 idenom = sqrt(0.5*g%IareaT(i,j)/s)
612 a_s(i) = g%areaCv(i,j-1)*idenom
613 a_n(i) = g%areaCv(i,j)*idenom
615 a_s(i) = 0.0 ; a_n(i) = 0.0
619 if (mix_vertically)
then
621 b_denom_1 = h(i,j,1) + h_neglect
622 b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
623 d1(i) = b_denom_1 * b1(i)
624 u_h(i,j,1) = (h(i,j,1)*b1(i)) * (a_e(i)*u(i,j,1) + a_w(i)*u(i-1,j,1))
625 v_h(i,j,1) = (h(i,j,1)*b1(i)) * (a_n(i)*v(i,j,1) + a_s(i)*v(i,j-1,1))
627 do k=2,nz ;
do i=is,ie
628 c1(i,k) = eb(i,j,k-1) * b1(i)
629 b_denom_1 = h(i,j,k) + d1(i)*ea(i,j,k) + h_neglect
630 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
631 d1(i) = b_denom_1 * b1(i)
632 u_h(i,j,k) = (h(i,j,k) * (a_e(i)*u(i,j,k) + a_w(i)*u(i-1,j,k)) + &
633 ea(i,j,k)*u_h(i,j,k-1))*b1(i)
634 v_h(i,j,k) = (h(i,j,k) * (a_n(i)*v(i,j,k) + a_s(i)*v(i,j-1,k)) + &
635 ea(i,j,k)*v_h(i,j,k-1))*b1(i)
637 do k=nz-1,1,-1 ;
do i=is,ie
638 u_h(i,j,k) = u_h(i,j,k) + c1(i,k+1)*u_h(i,j,k+1)
639 v_h(i,j,k) = v_h(i,j,k) + c1(i,k+1)*v_h(i,j,k+1)
642 do k=1,nz ;
do i=is,ie
643 u_h(i,j,k) = a_e(i)*u(i,j,k) + a_w(i)*u(i-1,j,k)
644 v_h(i,j,k) = a_n(i)*v(i,j,k) + a_s(i)*v(i,j-1,k)
649 call cpu_clock_end(id_clock_uv_at_h)
650 end subroutine find_uv_at_h
653 subroutine set_pen_shortwave(optics, fluxes, G, GV, CS, opacity_CSp, tracer_flow_CSp)
656 type(
forcing),
intent(inout) :: fluxes
665 real,
dimension(SZI_(G),SZJ_(G)) :: chl_2d
666 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: chl_3d
667 character(len=128) :: mesg
668 integer :: i, j, k, is, ie, js, je
669 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
671 if (.not.
associated(optics))
return
673 if (cs%var_pen_sw)
then
674 if (cs%chl_from_file)
then
677 call time_interp_external(cs%sbc_chl, cs%Time, chl_2d)
678 do j=js,je ;
do i=is,ie
679 if ((g%mask2dT(i,j) > 0.5) .and. (chl_2d(i,j) < 0.0))
then
680 write(mesg,
'(" Time_interp negative chl of ",(1pe12.4)," at i,j = ",&
681 & 2(i3), "lon/lat = ",(1pe12.4)," E ", (1pe12.4), " N.")') &
682 chl_2d(i,j), i, j, g%geoLonT(i,j), g%geoLatT(i,j)
683 call mom_error(fatal,
"MOM_diabatic_aux set_pen_shortwave: "//trim(mesg))
687 if (cs%id_chl > 0)
call post_data(cs%id_chl, chl_2d, cs%diag)
689 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
690 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, opacity_csp, chl_2d=chl_2d)
692 if (.not.
associated(tracer_flow_csp))
call mom_error(fatal, &
693 "The tracer flow control structure must be associated when the model sets "//&
694 "the chlorophyll internally in set_pen_shortwave.")
695 call get_chl_from_model(chl_3d, g, tracer_flow_csp)
697 if (cs%id_chl > 0)
call post_data(cs%id_chl, chl_3d(:,:,1), cs%diag)
699 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
700 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, opacity_csp, chl_3d=chl_3d)
703 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
704 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, opacity_csp)
707 end subroutine set_pen_shortwave
712 subroutine diagnosemldbydensitydifference(id_MLD, h, tv, densityDiff, G, GV, US, diagPtr, &
713 id_N2subML, id_MLDsq, dz_subML)
717 integer,
intent(in) :: id_mld
718 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
722 real,
intent(in) :: densitydiff
724 integer,
optional,
intent(in) :: id_n2subml
725 integer,
optional,
intent(in) :: id_mldsq
726 real,
optional,
intent(in) :: dz_subml
730 real,
dimension(SZI_(G)) :: deltarhoatkm1, deltarhoatk
731 real,
dimension(SZI_(G)) :: pref_mld, pref_n2
732 real,
dimension(SZI_(G)) :: h_subml, dh_n2
733 real,
dimension(SZI_(G)) :: t_subml, t_deeper
734 real,
dimension(SZI_(G)) :: s_subml, s_deeper
735 real,
dimension(SZI_(G)) :: rho_subml, rho_deeper
736 real,
dimension(SZI_(G)) :: dk, dkm1
737 real,
dimension(SZI_(G)) :: rhosurf
738 real,
dimension(SZI_(G), SZJ_(G)) :: mld
739 real,
dimension(SZI_(G), SZJ_(G)) :: submln2
740 real,
dimension(SZI_(G), SZJ_(G)) :: mld2
741 logical,
dimension(SZI_(G)) :: n2_region_set
745 integer :: i, j, is, ie, js, je, k, nz, id_n2, id_sq
748 id_n2 = -1 ;
if (
PRESENT(id_n2subml)) id_n2 = id_n2subml
750 id_sq = -1 ;
if (
PRESENT(id_mldsq)) id_sq = id_mldsq
752 ge_rho0 = us%L_to_Z**2*gv%g_Earth / gv%Rho0
753 dh_subml = 50.*gv%m_to_H ;
if (
present(dz_subml)) dh_subml = gv%Z_to_H*dz_subml
755 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
759 do i=is,ie ; dk(i) = 0.5 * h(i,j,1) * gv%H_to_Z ;
enddo
760 call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pref_mld, rhosurf, is, ie-is+1, tv%eqn_of_state)
766 h_subml(i) = h(i,j,1) ; dh_n2(i) = 0.0
767 t_subml(i) = 0.0 ; s_subml(i) = 0.0 ; t_deeper(i) = 0.0 ; s_deeper(i) = 0.0
768 n2_region_set(i) = (g%mask2dT(i,j)<0.5)
774 dk(i) = dk(i) + 0.5 * ( h(i,j,k) + h(i,j,k-1) ) * gv%H_to_Z
781 if (mld(i,j)==0.0)
then
782 h_subml(i) = h_subml(i) + h(i,j,k)
783 elseif (.not.n2_region_set(i))
then
784 if (dh_n2(i)==0.0)
then
785 t_subml(i) = tv%T(i,j,k) ; s_subml(i) = tv%S(i,j,k)
786 h_subml(i) = h_subml(i) + 0.5 * h(i,j,k)
787 dh_n2(i) = 0.5 * h(i,j,k)
788 elseif (dh_n2(i) + h(i,j,k) < dh_subml)
then
789 dh_n2(i) = dh_n2(i) + h(i,j,k)
791 t_deeper(i) = tv%T(i,j,k) ; s_deeper(i) = tv%S(i,j,k)
792 dh_n2(i) = dh_n2(i) + 0.5 * h(i,j,k)
793 n2_region_set(i) = .true.
800 do i=is,ie ; deltarhoatkm1(i) = deltarhoatk(i) ;
enddo
801 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pref_mld, deltarhoatk, is, ie-is+1, tv%eqn_of_state)
803 deltarhoatk(i) = deltarhoatk(i) - rhosurf(i)
804 ddrho = deltarhoatk(i) - deltarhoatkm1(i)
805 if ((mld(i,j)==0.) .and. (ddrho>0.) .and. &
806 (deltarhoatkm1(i)<densitydiff) .and. (deltarhoatk(i)>=densitydiff))
then
807 afac = ( densitydiff - deltarhoatkm1(i) ) / ddrho
808 mld(i,j) = dk(i) * afac + dkm1(i) * (1. - afac)
810 if (id_sq > 0) mld2(i,j) = mld(i,j)**2
814 if ((mld(i,j)==0.) .and. (deltarhoatk(i)<densitydiff)) mld(i,j) = dk(i)
818 do i=is,ie ; pref_n2(i) = gv%H_to_Pa * (h_subml(i) + 0.5*dh_n2(i)) ;
enddo
824 call calculate_density(t_subml, s_subml, pref_n2, rho_subml, is, ie-is+1, tv%eqn_of_state)
825 call calculate_density(t_deeper, s_deeper, pref_n2, rho_deeper, is, ie-is+1, tv%eqn_of_state)
826 do i=is,ie ;
if ((g%mask2dT(i,j)>0.5) .and. n2_region_set(i))
then
827 submln2(i,j) = ge_rho0 * (rho_deeper(i) - rho_subml(i)) / (gv%H_to_z * dh_n2(i))
832 if (id_mld > 0)
call post_data(id_mld, mld, diagptr)
833 if (id_n2 > 0)
call post_data(id_n2, submln2, diagptr)
834 if (id_sq > 0)
call post_data(id_sq, mld2, diagptr)
836 end subroutine diagnosemldbydensitydifference
841 subroutine applyboundaryfluxesinout(CS, G, GV, US, dt, fluxes, optics, nsw, h, tv, &
842 aggregate_FW_forcing, evap_CFL_limit, &
843 minimum_forcing_depth, cTKE, dSV_dT, dSV_dS, &
849 real,
intent(in) :: dt
850 type(
forcing),
intent(inout) :: fluxes
852 integer,
intent(in) :: nsw
854 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
858 logical,
intent(in) :: aggregate_fw_forcing
859 real,
intent(in) :: evap_cfl_limit
861 real,
intent(in) :: minimum_forcing_depth
863 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
864 optional,
intent(out) :: ctke
866 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
867 optional,
intent(out) :: dsv_dt
869 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
870 optional,
intent(out) :: dsv_ds
872 real,
dimension(SZI_(G),SZJ_(G)), &
873 optional,
intent(out) :: skinbuoyflux
876 integer,
parameter :: maxgroundings = 5
877 integer :: numberofgroundings, iground(maxgroundings), jground(maxgroundings)
878 real :: h_limit_fluxes, iforcingdepthscale, idt
879 real :: dthickness, dtemp, dsalt
880 real :: fractionofforcing, hold, ithickness
881 real :: rivermixconst
882 real,
dimension(SZI_(G)) :: &
902 real,
dimension(SZI_(G), SZK_(G)) :: &
908 real,
dimension(SZI_(G),SZK_(G)+1) :: netpen
909 real,
dimension(max(nsw,1),SZI_(G)) :: &
914 real,
dimension(max(nsw,1),SZI_(G),SZK_(G)) :: &
917 real,
dimension(maxGroundings) :: hgrounding
918 real :: temp_in, salin_in
924 logical :: calculate_energetics
925 logical :: calculate_buoyancy
926 integer :: i, j, is, ie, js, je, k, nz, n
927 integer :: start, npts
928 character(len=45) :: mesg
930 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
933 if (.not.
associated(fluxes%sw))
return
936 dt_in_t = dt * us%s_to_T
939 calculate_energetics = (
present(ctke) .and.
present(dsv_dt) .and.
present(dsv_ds))
940 calculate_buoyancy =
present(skinbuoyflux)
941 if (calculate_buoyancy) skinbuoyflux(:,:) = 0.0
943 g_hconv2 = (us%m_to_Z**3 * us%T_to_s**2) * gv%H_to_Pa * gv%H_to_kg_m2
945 if (
present(ctke)) ctke(:,:,:) = 0.0
946 if (calculate_buoyancy)
then
947 surfpressure(:) = 0.0
948 gorho = us%L_to_Z**2*gv%g_Earth / gv%Rho0
949 start = 1 + g%isc - g%isd
950 npts = 1 + g%iec - g%isc
958 h_limit_fluxes = max(gv%Angstrom_H, 1.e-30*gv%m_to_H)
961 if (cs%id_createdH>0) cs%createdH(:,:) = 0.
962 numberofgroundings = 0
983 do k=1,nz ;
do i=is,ie
985 t2d(i,k) = tv%T(i,j,k)
987 if (nsw>0)
call extract_optics_slice(optics, j, g, gv, opacity=opacityband, opacity_scale=(1.0/gv%m_to_H))
989 if (calculate_energetics)
then
993 do i=is,ie ; pres(i) = 0.0 ;
enddo
996 d_pres(i) = gv%H_to_Pa * h2d(i,k)
997 p_lay(i) = pres(i) + 0.5*d_pres(i)
998 pres(i) = pres(i) + d_pres(i)
1000 call calculate_specific_vol_derivs(t2d(:,k), tv%S(:,j,k), p_lay(:),&
1001 dsv_dt(:,j,k), dsv_ds(:,j,k), is, ie-is+1, tv%eqn_of_state)
1002 do i=is,ie ; dsv_dt_2d(i,k) = dsv_dt(i,j,k) ;
enddo
1008 pen_tke_2d(:,:) = 0.0
1054 if (calculate_buoyancy)
then
1055 call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
1056 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1057 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1058 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw, &
1059 net_heat_rate=netheat_rate, net_salt_rate=netsalt_rate, &
1060 netmassinout_rate=netmassinout_rate, pen_sw_bnd_rate=pen_sw_bnd_rate)
1062 call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
1063 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1064 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1065 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw)
1070 if (aggregate_fw_forcing)
then
1071 netmassout(i) = netmassinout(i)
1074 netmassin(i) = netmassinout(i) - netmassout(i)
1076 if (g%mask2dT(i,j)>0.0)
then
1077 fluxes%netMassOut(i,j) = netmassout(i)
1078 fluxes%netMassIn(i,j) = netmassin(i)
1080 fluxes%netMassOut(i,j) = 0.0
1081 fluxes%netMassIn(i,j) = 0.0
1091 if (g%mask2dT(i,j)>0.)
then
1097 dthickness = netmassin(i)
1103 netmassin(i) = netmassin(i) - dthickness
1107 dtemp = dtemp + dthickness*temp_in
1110 if (
associated(fluxes%heat_content_massin)) &
1111 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1112 t2d(i,k) * max(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1113 if (
associated(fluxes%heat_content_massout)) &
1114 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1115 t2d(i,k) * min(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1116 if (
associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1117 t2d(i,k) * dthickness * gv%H_to_kg_m2
1120 if (calculate_energetics .and.
associated(fluxes%lrunoff) .and. cs%do_rivermix)
then
1131 rivermixconst = -0.5*(cs%rivermix_depth*dt)*(us%m_to_Z**3 * us%T_to_s**2) * gv%Z_to_H*gv%H_to_Pa
1133 ctke(i,j,k) = ctke(i,j,k) + max(0.0, rivermixconst*dsv_ds(i,j,1) * &
1134 (fluxes%lrunoff(i,j) + fluxes%frunoff(i,j)) * tv%S(i,j,1))
1139 h2d(i,k) = h2d(i,k) + dthickness
1140 if (h2d(i,k) > 0.0)
then
1141 if (calculate_energetics .and. (dthickness > 0.))
then
1144 ctke(i,j,k) = ctke(i,j,k) + 0.5*g_hconv2*(hold*dthickness) * &
1145 ((t2d(i,k) - temp_in) * dsv_dt(i,j,k) + (tv%S(i,j,k) - salin_in) * dsv_ds(i,j,k))
1147 ithickness = 1.0/h2d(i,k)
1149 if (dthickness /= 0. .or. dtemp /= 0.) t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1150 if (dthickness /= 0. .or. dsalt /= 0.) tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1162 iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth*gv%m_to_H - netmassout(i) )
1164 fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
1169 if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k))
then
1170 fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
1175 dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
1176 dtemp = fractionofforcing*netheat(i)
1178 dsalt = max( fractionofforcing*netsalt(i), -0.9999*h2d(i,k)*tv%S(i,j,k))
1182 netmassout(i) = netmassout(i) - dthickness
1183 netheat(i) = netheat(i) - dtemp
1184 netsalt(i) = netsalt(i) - dsalt
1187 dtemp = dtemp + dthickness*t2d(i,k)
1190 if (
associated(fluxes%heat_content_massin)) &
1191 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1192 t2d(i,k) * max(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1193 if (
associated(fluxes%heat_content_massout)) &
1194 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1195 t2d(i,k) * min(0.,dthickness) * gv%H_to_kg_m2 * fluxes%C_p * idt
1196 if (
associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1197 t2d(i,k) * dthickness * gv%H_to_kg_m2
1201 h2d(i,k) = h2d(i,k) + dthickness
1203 if (h2d(i,k) > 0.)
then
1204 if (calculate_energetics)
then
1210 ctke(i,j,k) = ctke(i,j,k) - (0.5*h2d(i,k)*g_hconv2) * &
1211 ((dtemp - dthickness*t2d(i,k)) * dsv_dt(i,j,k) + &
1212 (dsalt - dthickness*tv%S(i,j,k)) * dsv_ds(i,j,k))
1214 ithickness = 1.0/h2d(i,k)
1215 t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1216 tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1217 elseif (h2d(i,k) < 0.0)
then
1218 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (h<0)')
1219 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1220 write(0,*)
'applyBoundaryFluxesInOut(): netT,netS,netH=',netheat(i),netsalt(i),netmassinout(i)
1221 write(0,*)
'applyBoundaryFluxesInOut(): dT,dS,dH=',dtemp,dsalt,dthickness
1222 write(0,*)
'applyBoundaryFluxesInOut(): h(n),h(n+1),k=',hold,h2d(i,k),k
1223 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1224 "Complete mass loss in column!")
1230 elseif ((abs(netheat(i))+abs(netsalt(i))+abs(netmassin(i))+abs(netmassout(i)))>0.)
then
1232 if (.not. cs%ignore_fluxes_over_land)
then
1233 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (land)')
1234 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1235 write(0,*)
'applyBoundaryFluxesInOut(): netHeat,netSalt,netMassIn,netMassOut=',&
1236 netheat(i),netsalt(i),netmassin(i),netmassout(i)
1238 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1239 "Mass loss over land?")
1245 if (netmassin(i)+netmassout(i) /= 0.0)
then
1247 numberofgroundings = numberofgroundings +1
1248 if (numberofgroundings<=maxgroundings)
then
1249 iground(numberofgroundings) = i
1250 jground(numberofgroundings) = j
1251 hgrounding(numberofgroundings) = netmassin(i)+netmassout(i)
1254 if (cs%id_createdH>0) cs%createdH(i,j) = cs%createdH(i,j) - (netmassin(i)+netmassout(i))/dt
1265 if (cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then
1266 do k=1,nz ;
do i=is,ie
1267 cs%penSW_diag(i,j,k) = t2d(i,k)
1268 cs%penSWflux_diag(i,j,k) = 0.0
1271 cs%penSWflux_diag(i,j,k) = 0.0
1275 if (calculate_energetics)
then
1276 call absorbremainingsw(g, gv, us, h2d, opacityband, nsw, optics, j, dt_in_t, h_limit_fluxes, &
1277 .false., .true., t2d, pen_sw_bnd, tke=pen_tke_2d, dsv_dt=dsv_dt_2d)
1279 do k=1,nz ;
do i=is,ie
1280 ctke(i,j,k) = ctke(i,j,k) + pen_tke_2d(i,k)
1283 call absorbremainingsw(g, gv, us, h2d, opacityband, nsw, optics, j, dt_in_t, h_limit_fluxes, &
1284 .false., .true., t2d, pen_sw_bnd)
1290 do k=1,nz ;
do i=is,ie
1292 tv%T(i,j,k) = t2d(i,k)
1297 if (cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then
1300 do k=1,nz ;
do i=is,ie
1301 cs%penSW_diag(i,j,k) = (t2d(i,k)-cs%penSW_diag(i,j,k))*h(i,j,k) * idt * tv%C_p * gv%H_to_kg_m2
1310 if (cs%id_penSWflux_diag > 0)
then
1311 do k=nz,1,-1 ;
do i=is,ie
1312 cs%penSWflux_diag(i,j,k) = cs%penSW_diag(i,j,k) + cs%penSWflux_diag(i,j,k+1)
1319 if (cs%id_nonpenSW_diag > 0)
then
1321 cs%nonpenSW_diag(i,j) = nonpensw(i)
1330 if (calculate_buoyancy)
then
1336 call sumswoverbands(g, gv, us, h2d(:,:), optics_nbands(optics), optics, j, dt_in_t, &
1337 h_limit_fluxes, .true., pen_sw_bnd_rate, netpen)
1340 drhodt, drhods, start, npts, tv%eqn_of_state)
1347 skinbuoyflux(i,j) = - gorho * gv%H_to_Z * us%T_to_s * &
1348 (drhods(i) * (netsalt_rate(i) - tv%S(i,j,1)*netmassinout_rate(i)) + &
1349 drhodt(i) * ( netheat_rate(i) + netpen(i,1)) )
1356 if (cs%id_createdH > 0)
call post_data(cs%id_createdH , cs%createdH , cs%diag)
1357 if (cs%id_penSW_diag > 0)
call post_data(cs%id_penSW_diag , cs%penSW_diag , cs%diag)
1358 if (cs%id_penSWflux_diag > 0)
call post_data(cs%id_penSWflux_diag, cs%penSWflux_diag, cs%diag)
1359 if (cs%id_nonpenSW_diag > 0)
call post_data(cs%id_nonpenSW_diag , cs%nonpenSW_diag , cs%diag)
1362 if (numberofgroundings>0 .and. .not. cs%ignore_fluxes_over_land)
then
1363 do i = 1, min(numberofgroundings, maxgroundings)
1364 call forcing_singlepointprint(fluxes,g,iground(i),jground(i),
'applyBoundaryFluxesInOut (grounding)')
1365 write(mesg(1:45),
'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
1366 g%geoLatT( iground(i), jground(i)) , hgrounding(i)
1367 call mom_error(warning,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1368 "Mass created. x,y,dh= "//trim(mesg), all_print=.true.)
1371 if (numberofgroundings - maxgroundings > 0)
then
1372 write(mesg,
'(i4)') numberofgroundings - maxgroundings
1373 call mom_error(warning,
"MOM_diabatic_driver:F90, applyBoundaryFluxesInOut(): "//&
1374 trim(mesg) //
" groundings remaining")
1378 end subroutine applyboundaryfluxesinout
1381 subroutine diabatic_aux_init(Time, G, GV, US, param_file, diag, CS, useALEalgorithm, use_ePBL)
1382 type(time_type),
target,
intent(in) :: time
1387 type(
diag_ctrl),
target,
intent(inout) :: diag
1390 logical,
intent(in) :: usealealgorithm
1392 logical,
intent(in) :: use_epbl
1397 #include "version_variable.h"
1398 character(len=40) :: mdl =
"MOM_diabatic_aux"
1399 character(len=48) :: thickness_units
1400 character(len=200) :: inputdir
1401 character(len=240) :: chl_filename
1402 character(len=128) :: chl_file
1404 character(len=32) :: chl_varname
1405 logical :: use_temperature
1406 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz, nbands
1407 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
1408 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1410 if (
associated(cs))
then
1411 call mom_error(warning,
"diabatic_aux_init called with an "// &
1412 "associated control structure.")
1423 "The following parameters are used for auxiliary diabatic processes.")
1425 call get_param(param_file, mdl,
"ENABLE_THERMODYNAMICS", use_temperature, &
1426 "If true, temperature and salinity are used as state "//&
1427 "variables.", default=.true.)
1429 call get_param(param_file, mdl,
"RECLAIM_FRAZIL", cs%reclaim_frazil, &
1430 "If true, try to use any frazil heat deficit to cool any "//&
1431 "overlying layers down to the freezing point, thereby "//&
1432 "avoiding the creation of thin ice when the SST is above "//&
1433 "the freezing point.", default=.true.)
1434 call get_param(param_file, mdl,
"PRESSURE_DEPENDENT_FRAZIL", &
1435 cs%pressure_dependent_frazil, &
1436 "If true, use a pressure dependent freezing temperature "//&
1437 "when making frazil. The default is false, which will be "//&
1438 "faster but is inappropriate with ice-shelf cavities.", &
1442 call get_param(param_file, mdl,
"IGNORE_FLUXES_OVER_LAND", cs%ignore_fluxes_over_land,&
1443 "If true, the model does not check if fluxes are being applied "//&
1444 "over land points. This is needed when the ocean is coupled "//&
1445 "with ice shelves and sea ice, since the sea ice mask needs to "//&
1446 "be different than the ocean mask to avoid sea ice formation "//&
1447 "under ice shelves. This flag only works when use_ePBL = True.", default=.false.)
1448 call get_param(param_file, mdl,
"DO_RIVERMIX", cs%do_rivermix, &
1449 "If true, apply additional mixing wherever there is "//&
1450 "runoff, so that it is mixed down to RIVERMIX_DEPTH "//&
1451 "if the ocean is that deep.", default=.false.)
1452 if (cs%do_rivermix) &
1453 call get_param(param_file, mdl,
"RIVERMIX_DEPTH", cs%rivermix_depth, &
1454 "The depth to which rivers are mixed if DO_RIVERMIX is "//&
1455 "defined.", units=
"m", default=0.0, scale=us%m_to_Z)
1457 cs%do_rivermix = .false. ; cs%rivermix_depth = 0.0 ; cs%ignore_fluxes_over_land = .false.
1460 if (gv%nkml == 0)
then
1461 call get_param(param_file, mdl,
"USE_RIVER_HEAT_CONTENT", cs%use_river_heat_content, &
1462 "If true, use the fluxes%runoff_Hflx field to set the "//&
1463 "heat carried by runoff, instead of using SST*CP*liq_runoff.", &
1465 call get_param(param_file, mdl,
"USE_CALVING_HEAT_CONTENT", cs%use_calving_heat_content, &
1466 "If true, use the fluxes%calving_Hflx field to set the "//&
1467 "heat carried by runoff, instead of using SST*CP*froz_runoff.", &
1470 cs%use_river_heat_content = .false.
1471 cs%use_calving_heat_content = .false.
1474 if (usealealgorithm)
then
1475 cs%id_createdH = register_diag_field(
'ocean_model',
"created_H",diag%axesT1, &
1476 time,
"The volume flux added to stop the ocean from drying out and becoming negative in depth", &
1478 if (cs%id_createdH>0)
allocate(cs%createdH(isd:ied,jsd:jed))
1481 cs%id_penSW_diag = register_diag_field(
'ocean_model',
'rsdoabsorb', &
1482 diag%axesTL, time,
'Convergence of Penetrative Shortwave Flux in Sea Water Layer',&
1483 'W m-2', standard_name=
'net_rate_of_absorption_of_shortwave_energy_in_ocean_layer',v_extensive=.true.)
1487 cs%id_penSWflux_diag = register_diag_field(
'ocean_model',
'rsdo', &
1488 diag%axesTi, time,
'Downwelling Shortwave Flux in Sea Water at Grid Cell Upper Interface',&
1489 'W m-2', standard_name=
'downwelling_shortwave_flux_in_sea_water')
1492 if (cs%id_penSW_diag>0 .or. cs%id_penSWflux_diag>0)
then
1493 allocate(cs%penSW_diag(isd:ied,jsd:jed,nz))
1494 cs%penSW_diag(:,:,:) = 0.0
1495 allocate(cs%penSWflux_diag(isd:ied,jsd:jed,nz+1))
1496 cs%penSWflux_diag(:,:,:) = 0.0
1500 cs%id_nonpenSW_diag = register_diag_field(
'ocean_model',
'nonpenSW', &
1501 diag%axesT1, time, &
1502 'Non-downwelling SW radiation (i.e., SW absorbed in ocean surface with LW,SENS,LAT)',&
1503 'W m-2', standard_name=
'nondownwelling_shortwave_flux_in_sea_water')
1504 if (cs%id_nonpenSW_diag > 0)
then
1505 allocate(cs%nonpenSW_diag(isd:ied,jsd:jed))
1506 cs%nonpenSW_diag(:,:) = 0.0
1510 if (use_temperature)
then
1511 call get_param(param_file, mdl,
"VAR_PEN_SW", cs%var_pen_sw, &
1512 "If true, use one of the CHL_A schemes specified by "//&
1513 "OPACITY_SCHEME to determine the e-folding depth of "//&
1514 "incoming short wave radiation.", default=.false.)
1515 if (cs%var_pen_sw)
then
1517 call get_param(param_file, mdl,
"CHL_FROM_FILE", cs%chl_from_file, &
1518 "If true, chl_a is read from a file.", default=.true.)
1519 if (cs%chl_from_file)
then
1520 call time_interp_external_init()
1522 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
1523 call get_param(param_file, mdl,
"CHL_FILE", chl_file, &
1524 "CHL_FILE is the file containing chl_a concentrations in "//&
1525 "the variable CHL_A. It is used when VAR_PEN_SW and "//&
1526 "CHL_FROM_FILE are true.", fail_if_missing=.true.)
1527 chl_filename = trim(slasher(inputdir))//trim(chl_file)
1528 call log_param(param_file, mdl,
"INPUTDIR/CHL_FILE", chl_filename)
1529 call get_param(param_file, mdl,
"CHL_VARNAME", chl_varname, &
1530 "Name of CHL_A variable in CHL_FILE.", default=
'CHL_A')
1531 cs%sbc_chl = init_external_field(chl_filename, trim(chl_varname), domain=g%Domain%mpp_domain)
1534 cs%id_chl = register_diag_field(
'ocean_model',
'Chl_opac', diag%axesT1, time, &
1535 'Surface chlorophyll A concentration used to find opacity',
'mg m-3')
1539 id_clock_uv_at_h = cpu_clock_id(
'(Ocean find_uv_at_h)', grain=clock_routine)
1540 id_clock_frazil = cpu_clock_id(
'(Ocean frazil)', grain=clock_routine)
1542 end subroutine diabatic_aux_init
1546 subroutine diabatic_aux_end(CS)
1550 if (.not.
associated(cs))
return
1552 if (cs%id_createdH >0)
deallocate(cs%createdH)
1553 if (cs%id_penSW_diag >0)
deallocate(cs%penSW_diag)
1554 if (cs%id_penSWflux_diag >0)
deallocate(cs%penSWflux_diag)
1555 if (cs%id_nonpenSW_diag >0)
deallocate(cs%nonpenSW_diag)
1557 if (
associated(cs))
deallocate(cs)
1559 end subroutine diabatic_aux_end