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, differential_diffuse_t_s, tridiagts
34 public find_uv_at_h, diagnosemldbydensitydifference, applyboundaryfluxesinout, set_pen_shortwave
35 public diagnosemldbyenergy
44 logical :: do_rivermix = .false.
46 real :: rivermix_depth = 0.0
47 logical :: reclaim_frazil
50 logical :: pressure_dependent_frazil
54 logical :: ignore_fluxes_over_land
58 logical :: use_river_heat_content
61 logical :: use_calving_heat_content
68 logical :: chl_from_file
70 type(time_type),
pointer :: time => null()
74 integer :: id_createdh = -1
75 integer :: id_brine_lay = -1
76 integer :: id_pensw_diag = -1
77 integer :: id_penswflux_diag = -1
78 integer :: id_nonpensw_diag = -1
79 integer :: id_chl = -1
82 real,
allocatable,
dimension(:,:) :: createdh
84 real,
allocatable,
dimension(:,:,:) :: pensw_diag
86 real,
allocatable,
dimension(:,:,:) :: penswflux_diag
88 real,
allocatable,
dimension(:,:) :: nonpensw_diag
94 integer :: id_clock_uv_at_h, id_clock_frazil
103 subroutine make_frazil(h, tv, G, GV, US, CS, p_surf, halo)
106 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
113 real,
dimension(SZI_(G),SZJ_(G)), &
114 optional,
intent(in) :: p_surf
115 integer,
optional,
intent(in) :: halo
118 real,
dimension(SZI_(G)) :: &
122 real,
dimension(SZI_(G),SZK_(G)) :: &
128 integer :: i, j, k, is, ie, js, je, nz
130 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
131 if (
present(halo))
then 132 is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
135 call cpu_clock_begin(id_clock_frazil)
137 if (.not.cs%pressure_dependent_frazil)
then 138 do k=1,nz ;
do i=is,ie ; pressure(i,k) = 0.0 ;
enddo ;
enddo 140 h_to_rl2_t2 = gv%H_to_RZ * gv%g_Earth
146 if (
PRESENT(p_surf))
then ;
do i=is,ie
150 do i=is,ie ; fraz_col(i) = 0.0 ;
enddo 152 if (cs%pressure_dependent_frazil)
then 154 pressure(i,1) = ps(i) + (0.5*h_to_rl2_t2)*h(i,j,1)
156 do k=2,nz ;
do i=is,ie
157 pressure(i,k) = pressure(i,k-1) + &
158 (0.5*h_to_rl2_t2) * (h(i,j,k) + h(i,j,k-1))
162 if (cs%reclaim_frazil)
then 164 do i=is,ie ;
if (tv%frazil(i,j) > 0.0)
then 165 if (.not.t_fr_set)
then 167 1, ie-i+1, tv%eqn_of_state, pres_scale=us%RL2_T2_to_Pa)
171 if (tv%T(i,j,1) > t_freeze(i))
then 174 hc = (tv%C_p*gv%H_to_RZ) * h(i,j,1)
175 if (tv%frazil(i,j) - hc * (tv%T(i,j,1) - t_freeze(i)) <= 0.0)
then 176 tv%T(i,j,1) = tv%T(i,j,1) - tv%frazil(i,j) / hc
179 tv%frazil(i,j) = tv%frazil(i,j) - hc * (tv%T(i,j,1) - t_freeze(i))
180 tv%T(i,j,1) = t_freeze(i)
189 if ((g%mask2dT(i,j) > 0.0) .and. &
190 ((tv%T(i,j,k) < 0.0) .or. (fraz_col(i) > 0.0)))
then 191 if (.not.t_fr_set)
then 193 1, ie-i+1, tv%eqn_of_state, pres_scale=us%RL2_T2_to_Pa)
197 hc = (tv%C_p*gv%H_to_RZ) * h(i,j,k)
198 if (h(i,j,k) <= 10.0*(gv%Angstrom_H + gv%H_subroundoff))
then 200 if (tv%T(i,j,k) < t_freeze(i))
then 201 fraz_col(i) = fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k))
202 tv%T(i,j,k) = t_freeze(i)
204 elseif ((fraz_col(i) > 0.0) .or. (tv%T(i,j,k) < t_freeze(i)))
then 205 if (fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k)) < 0.0)
then 206 tv%T(i,j,k) = tv%T(i,j,k) - fraz_col(i) / hc
209 fraz_col(i) = fraz_col(i) + hc * (t_freeze(i) - tv%T(i,j,k))
210 tv%T(i,j,k) = t_freeze(i)
217 tv%frazil(i,j) = tv%frazil(i,j) + fraz_col(i)
220 call cpu_clock_end(id_clock_frazil)
222 end subroutine make_frazil
226 subroutine differential_diffuse_t_s(h, T, S, Kd_T, Kd_S, dt, G, GV)
229 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
231 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
233 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
235 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
236 intent(inout) :: kd_t
239 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1), &
243 real,
intent(in) :: dt
246 real,
dimension(SZI_(G)) :: &
249 real,
dimension(SZI_(G),SZK_(G)) :: &
251 real,
dimension(SZI_(G),SZK_(G)+1) :: &
261 integer :: i, j, k, is, ie, js, je, nz
263 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
264 h_neglect = gv%H_subroundoff
269 i_h_int = 1.0 / (0.5 * (h(i,j,1) + h(i,j,2)) + h_neglect)
270 mix_t(i,2) = ((dt * kd_t(i,j,2)) * gv%Z_to_H**2) * i_h_int
271 mix_s(i,2) = ((dt * kd_s(i,j,2)) * gv%Z_to_H**2) * i_h_int
273 h_tr = h(i,j,1) + h_neglect
274 b1_t(i) = 1.0 / (h_tr + mix_t(i,2))
275 b1_s(i) = 1.0 / (h_tr + mix_s(i,2))
276 d1_t(i) = h_tr * b1_t(i)
277 d1_s(i) = h_tr * b1_s(i)
278 t(i,j,1) = (b1_t(i)*h_tr)*t(i,j,1)
279 s(i,j,1) = (b1_s(i)*h_tr)*s(i,j,1)
281 do k=2,nz-1 ;
do i=is,ie
283 i_h_int = 1.0 / (0.5 * (h(i,j,k) + h(i,j,k+1)) + h_neglect)
284 mix_t(i,k+1) = ((dt * kd_t(i,j,k+1)) * gv%Z_to_H**2) * i_h_int
285 mix_s(i,k+1) = ((dt * kd_s(i,j,k+1)) * gv%Z_to_H**2) * i_h_int
287 c1_t(i,k) = mix_t(i,k) * b1_t(i)
288 c1_s(i,k) = mix_s(i,k) * b1_s(i)
290 h_tr = h(i,j,k) + h_neglect
291 b_denom_t = h_tr + d1_t(i)*mix_t(i,k)
292 b_denom_s = h_tr + d1_s(i)*mix_s(i,k)
293 b1_t(i) = 1.0 / (b_denom_t + mix_t(i,k+1))
294 b1_s(i) = 1.0 / (b_denom_s + mix_s(i,k+1))
295 d1_t(i) = b_denom_t * b1_t(i)
296 d1_s(i) = b_denom_s * b1_s(i)
298 t(i,j,k) = b1_t(i) * (h_tr*t(i,j,k) + mix_t(i,k)*t(i,j,k-1))
299 s(i,j,k) = b1_s(i) * (h_tr*s(i,j,k) + mix_s(i,k)*s(i,j,k-1))
302 c1_t(i,nz) = mix_t(i,nz) * b1_t(i)
303 c1_s(i,nz) = mix_s(i,nz) * b1_s(i)
305 h_tr = h(i,j,nz) + h_neglect
306 b1_t(i) = 1.0 / (h_tr + d1_t(i)*mix_t(i,nz))
307 b1_s(i) = 1.0 / (h_tr + d1_s(i)*mix_s(i,nz))
309 t(i,j,nz) = b1_t(i) * (h_tr*t(i,j,nz) + mix_t(i,nz)*t(i,j,nz-1))
310 s(i,j,nz) = b1_s(i) * (h_tr*s(i,j,nz) + mix_s(i,nz)*s(i,j,nz-1))
312 do k=nz-1,1,-1 ;
do i=is,ie
313 t(i,j,k) = t(i,j,k) + c1_t(i,k+1)*t(i,j,k+1)
314 s(i,j,k) = s(i,j,k) + c1_s(i,k+1)*s(i,j,k+1)
317 end subroutine differential_diffuse_t_s
322 subroutine adjust_salt(h, tv, G, GV, CS, halo)
325 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
331 integer,
optional,
intent(in) :: halo
334 real :: salt_add_col(szi_(g),szj_(g))
337 integer :: i, j, k, is, ie, js, je, nz
339 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
340 if (
present(halo))
then 341 is = g%isc-halo ; ie = g%iec+halo ; js = g%jsc-halo ; je = g%jec+halo
346 s_min = tv%min_salinity
348 salt_add_col(:,:) = 0.0
352 do k=nz,1,-1 ;
do i=is,ie
353 if ( (g%mask2dT(i,j) > 0.0) .and. &
354 ((tv%S(i,j,k) < s_min) .or. (salt_add_col(i,j) > 0.0)) )
then 355 mc = gv%H_to_RZ * h(i,j,k)
356 if (h(i,j,k) <= 10.0*gv%Angstrom_H)
then 358 if (tv%S(i,j,k) < s_min)
then 359 salt_add_col(i,j) = salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k))
362 elseif (salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k)) <= 0.0)
then 363 tv%S(i,j,k) = tv%S(i,j,k) - salt_add_col(i,j) / mc
364 salt_add_col(i,j) = 0.0
366 salt_add_col(i,j) = salt_add_col(i,j) + mc * (s_min - tv%S(i,j,k))
372 tv%salt_deficit(i,j) = tv%salt_deficit(i,j) + salt_add_col(i,j)
377 end subroutine adjust_salt
381 subroutine tridiagts(G, GV, is, ie, js, je, hold, ea, eb, T, S)
384 integer,
intent(in) :: is
385 integer,
intent(in) :: ie
386 integer,
intent(in) :: js
387 integer,
intent(in) :: je
388 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: hold
390 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: ea
392 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: eb
394 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: t
395 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: s
398 real :: b1(szib_(g)), d1(szib_(g))
399 real :: c1(szib_(g),szk_(g))
400 real :: h_tr, b_denom_1
406 h_tr = hold(i,j,1) + gv%H_subroundoff
407 b1(i) = 1.0 / (h_tr + eb(i,j,1))
409 t(i,j,1) = (b1(i)*h_tr)*t(i,j,1)
410 s(i,j,1) = (b1(i)*h_tr)*s(i,j,1)
412 do k=2,g%ke ;
do i=is,ie
413 c1(i,k) = eb(i,j,k-1) * b1(i)
414 h_tr = hold(i,j,k) + gv%H_subroundoff
415 b_denom_1 = h_tr + d1(i)*ea(i,j,k)
416 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
417 d1(i) = b_denom_1 * b1(i)
418 t(i,j,k) = b1(i) * (h_tr*t(i,j,k) + ea(i,j,k)*t(i,j,k-1))
419 s(i,j,k) = b1(i) * (h_tr*s(i,j,k) + ea(i,j,k)*s(i,j,k-1))
421 do k=g%ke-1,1,-1 ;
do i=is,ie
422 t(i,j,k) = t(i,j,k) + c1(i,k+1)*t(i,j,k+1)
423 s(i,j,k) = s(i,j,k) + c1(i,k+1)*s(i,j,k+1)
426 end subroutine tridiagts
430 subroutine find_uv_at_h(u, v, h, u_h, v_h, G, GV, US, ea, eb)
434 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
436 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
438 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
440 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
442 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
444 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
445 optional,
intent(in) :: ea
448 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
449 optional,
intent(in) :: eb
457 real :: b1(szi_(g)), d1(szi_(g)), c1(szi_(g),szk_(g))
458 real :: a_n(szi_(g)), a_s(szi_(g))
459 real :: a_e(szi_(g)), a_w(szi_(g))
461 real :: sum_area, idenom
462 logical :: mix_vertically
463 integer :: i, j, k, is, ie, js, je, nz
464 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
465 call cpu_clock_begin(id_clock_uv_at_h)
466 h_neglect = gv%H_subroundoff
468 mix_vertically =
present(ea)
469 if (
present(ea) .neqv.
present(eb))
call mom_error(fatal, &
470 "find_uv_at_h: Either both ea and eb or neither one must be present "// &
471 "in call to find_uv_at_h.")
477 sum_area = g%areaCu(i-1,j) + g%areaCu(i,j)
478 if (sum_area>0.0)
then 479 idenom = sqrt(0.5*g%IareaT(i,j) / sum_area)
480 a_w(i) = g%areaCu(i-1,j) * idenom
481 a_e(i) = g%areaCu(i,j) * idenom
483 a_w(i) = 0.0 ; a_e(i) = 0.0
486 sum_area = g%areaCv(i,j-1) + g%areaCv(i,j)
487 if (sum_area>0.0)
then 488 idenom = sqrt(0.5*g%IareaT(i,j) / sum_area)
489 a_s(i) = g%areaCv(i,j-1) * idenom
490 a_n(i) = g%areaCv(i,j) * idenom
492 a_s(i) = 0.0 ; a_n(i) = 0.0
496 if (mix_vertically)
then 498 b_denom_1 = h(i,j,1) + h_neglect
499 b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
500 d1(i) = b_denom_1 * b1(i)
501 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))
502 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))
504 do k=2,nz ;
do i=is,ie
505 c1(i,k) = eb(i,j,k-1) * b1(i)
506 b_denom_1 = h(i,j,k) + d1(i)*ea(i,j,k) + h_neglect
507 b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
508 d1(i) = b_denom_1 * b1(i)
509 u_h(i,j,k) = (h(i,j,k) * (a_e(i)*u(i,j,k) + a_w(i)*u(i-1,j,k)) + &
510 ea(i,j,k)*u_h(i,j,k-1))*b1(i)
511 v_h(i,j,k) = (h(i,j,k) * (a_n(i)*v(i,j,k) + a_s(i)*v(i,j-1,k)) + &
512 ea(i,j,k)*v_h(i,j,k-1))*b1(i)
514 do k=nz-1,1,-1 ;
do i=is,ie
515 u_h(i,j,k) = u_h(i,j,k) + c1(i,k+1)*u_h(i,j,k+1)
516 v_h(i,j,k) = v_h(i,j,k) + c1(i,k+1)*v_h(i,j,k+1)
519 do k=1,nz ;
do i=is,ie
520 u_h(i,j,k) = a_e(i)*u(i,j,k) + a_w(i)*u(i-1,j,k)
521 v_h(i,j,k) = a_n(i)*v(i,j,k) + a_s(i)*v(i,j-1,k)
526 call cpu_clock_end(id_clock_uv_at_h)
527 end subroutine find_uv_at_h
530 subroutine set_pen_shortwave(optics, fluxes, G, GV, US, CS, opacity_CSp, tracer_flow_CSp)
533 type(
forcing),
intent(inout) :: fluxes
544 real,
dimension(SZI_(G),SZJ_(G)) :: chl_2d
545 real,
dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: chl_3d
546 character(len=128) :: mesg
547 integer :: i, j, k, is, ie, js, je
548 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
550 if (.not.
associated(optics))
return 552 if (cs%var_pen_sw)
then 553 if (cs%chl_from_file)
then 556 call time_interp_external(cs%sbc_chl, cs%Time, chl_2d)
557 do j=js,je ;
do i=is,ie
558 if ((g%mask2dT(i,j) > 0.5) .and. (chl_2d(i,j) < 0.0))
then 559 write(mesg,
'(" Time_interp negative chl of ",(1pe12.4)," at i,j = ",& 560 & 2(i3), "lon/lat = ",(1pe12.4)," E ", (1pe12.4), " N.")') &
561 chl_2d(i,j), i, j, g%geoLonT(i,j), g%geoLatT(i,j)
562 call mom_error(fatal,
"MOM_diabatic_aux set_pen_shortwave: "//trim(mesg))
566 if (cs%id_chl > 0)
call post_data(cs%id_chl, chl_2d, cs%diag)
568 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
569 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, us, opacity_csp, chl_2d=chl_2d)
571 if (.not.
associated(tracer_flow_csp))
call mom_error(fatal, &
572 "The tracer flow control structure must be associated when the model sets "//&
573 "the chlorophyll internally in set_pen_shortwave.")
574 call get_chl_from_model(chl_3d, g, tracer_flow_csp)
576 if (cs%id_chl > 0)
call post_data(cs%id_chl, chl_3d(:,:,1), cs%diag)
578 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
579 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, us, opacity_csp, chl_3d=chl_3d)
582 call set_opacity(optics, fluxes%sw, fluxes%sw_vis_dir, fluxes%sw_vis_dif, &
583 fluxes%sw_nir_dir, fluxes%sw_nir_dif, g, gv, us, opacity_csp)
586 end subroutine set_pen_shortwave
591 subroutine diagnosemldbydensitydifference(id_MLD, h, tv, densityDiff, G, GV, US, diagPtr, &
592 id_N2subML, id_MLDsq, dz_subML)
596 integer,
intent(in) :: id_mld
597 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
601 real,
intent(in) :: densitydiff
603 integer,
optional,
intent(in) :: id_n2subml
604 integer,
optional,
intent(in) :: id_mldsq
605 real,
optional,
intent(in) :: dz_subml
609 real,
dimension(SZI_(G)) :: deltarhoatkm1, deltarhoatk
610 real,
dimension(SZI_(G)) :: pref_mld, pref_n2
611 real,
dimension(SZI_(G)) :: h_subml, dh_n2
612 real,
dimension(SZI_(G)) :: t_subml, t_deeper
613 real,
dimension(SZI_(G)) :: s_subml, s_deeper
614 real,
dimension(SZI_(G)) :: rho_subml, rho_deeper
615 real,
dimension(SZI_(G)) :: dk, dkm1
616 real,
dimension(SZI_(G)) :: rhosurf
617 real,
dimension(SZI_(G), SZJ_(G)) :: mld
618 real,
dimension(SZI_(G), SZJ_(G)) :: submln2
619 real,
dimension(SZI_(G), SZJ_(G)) :: mld2
620 logical,
dimension(SZI_(G)) :: n2_region_set
626 integer,
dimension(2) :: eosdom
627 integer :: i, j, is, ie, js, je, k, nz, id_n2, id_sq
629 id_n2 = -1 ;
if (
PRESENT(id_n2subml)) id_n2 = id_n2subml
631 id_sq = -1 ;
if (
PRESENT(id_mldsq)) id_sq = id_mldsq
633 ge_rho0 = us%L_to_Z**2*gv%g_Earth / (gv%Rho0)
634 dh_subml = 50.*gv%m_to_H ;
if (
present(dz_subml)) dh_subml = gv%Z_to_H*dz_subml
636 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
639 eosdom(:) = eos_domain(g%HI)
641 do i=is,ie ; dk(i) = 0.5 * h(i,j,1) * gv%H_to_Z ;
enddo 642 call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pref_mld, rhosurf, tv%eqn_of_state, eosdom)
648 h_subml(i) = h(i,j,1) ; dh_n2(i) = 0.0
649 t_subml(i) = 0.0 ; s_subml(i) = 0.0 ; t_deeper(i) = 0.0 ; s_deeper(i) = 0.0
650 n2_region_set(i) = (g%mask2dT(i,j)<0.5)
656 dk(i) = dk(i) + 0.5 * ( h(i,j,k) + h(i,j,k-1) ) * gv%H_to_Z
663 if (mld(i,j)==0.0)
then 664 h_subml(i) = h_subml(i) + h(i,j,k)
665 elseif (.not.n2_region_set(i))
then 666 if (dh_n2(i)==0.0)
then 667 t_subml(i) = tv%T(i,j,k) ; s_subml(i) = tv%S(i,j,k)
668 h_subml(i) = h_subml(i) + 0.5 * h(i,j,k)
669 dh_n2(i) = 0.5 * h(i,j,k)
670 elseif (dh_n2(i) + h(i,j,k) < dh_subml)
then 671 dh_n2(i) = dh_n2(i) + h(i,j,k)
673 t_deeper(i) = tv%T(i,j,k) ; s_deeper(i) = tv%S(i,j,k)
674 dh_n2(i) = dh_n2(i) + 0.5 * h(i,j,k)
675 n2_region_set(i) = .true.
682 do i=is,ie ; deltarhoatkm1(i) = deltarhoatk(i) ;
enddo 683 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pref_mld, deltarhoatk, tv%eqn_of_state, eosdom)
685 deltarhoatk(i) = deltarhoatk(i) - rhosurf(i)
686 ddrho = deltarhoatk(i) - deltarhoatkm1(i)
687 if ((mld(i,j)==0.) .and. (ddrho>0.) .and. &
688 (deltarhoatkm1(i)<densitydiff) .and. (deltarhoatk(i)>=densitydiff))
then 689 afac = ( densitydiff - deltarhoatkm1(i) ) / ddrho
690 mld(i,j) = dk(i) * afac + dkm1(i) * (1. - afac)
692 if (id_sq > 0) mld2(i,j) = mld(i,j)**2
696 if ((mld(i,j)==0.) .and. (deltarhoatk(i)<densitydiff)) mld(i,j) = dk(i)
700 do i=is,ie ; pref_n2(i) = (gv%g_Earth * gv%H_to_RZ) * (h_subml(i) + 0.5*dh_n2(i)) ;
enddo 706 call calculate_density(t_subml, s_subml, pref_n2, rho_subml, tv%eqn_of_state, eosdom)
707 call calculate_density(t_deeper, s_deeper, pref_n2, rho_deeper, tv%eqn_of_state, eosdom)
708 do i=is,ie ;
if ((g%mask2dT(i,j)>0.5) .and. n2_region_set(i))
then 709 submln2(i,j) = ge_rho0 * (rho_deeper(i) - rho_subml(i)) / (gv%H_to_z * dh_n2(i))
714 if (id_mld > 0)
call post_data(id_mld, mld, diagptr)
715 if (id_n2 > 0)
call post_data(id_n2, submln2, diagptr)
716 if (id_sq > 0)
call post_data(id_sq, mld2, diagptr)
718 end subroutine diagnosemldbydensitydifference
722 subroutine diagnosemldbyenergy(id_MLD, h, tv, G, GV, US, Mixing_Energy, diagPtr)
744 integer,
dimension(3),
intent(in) :: id_mld
748 real,
dimension(3),
intent(in) :: mixing_energy
749 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
756 real,
dimension(SZI_(G), SZJ_(G),3) :: mld
757 real,
dimension(SZK_(G)) :: z_l, z_u, dz, rho_c, pref_mld
758 real,
dimension(3) :: pe_threshold
761 real :: pe_threshold_fraction, pe, pe_mixed, pe_mixed_tst
762 real :: rhodz_ml, h_ml, rhodz_ml_tst, h_ml_tst
765 real :: r1, d1, r2, d2
766 real :: ca, cb,d ,cc, cd, ca2, cb2, c, cc2
767 real :: gx, gpx, hx, ihx, hpx, ix, ipx, fgx, fpx, x, x2
770 integer :: i, j, is, ie, js, je, k, nz
772 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
776 pe_threshold_fraction = 1.e-4
779 pe_threshold(im) = mixing_energy(im)/gv%g_earth
782 do j=js,je;
do i=is,ie
783 if (g%mask2dT(i,j) > 0.0)
then 785 call calculate_density(tv%T(i,j,:), tv%S(i,j,:), pref_mld, rho_c, 1, nz, &
786 tv%eqn_of_state, scale=us%kg_m3_to_R)
789 dz(k) = h(i,j,k) * gv%H_to_Z
795 z_l(k) = z_l(k-1)-dz(k)
811 pe = pe + 0.5 * rho_c(k) * (z_u(k)**2 - z_l(k)**2)
814 h_ml_tst = h_ml + dz(k)
815 rhodz_ml_tst = rhodz_ml + rho_c(k) * dz(k)
818 rho_ml = rhodz_ml_tst/h_ml_tst
823 pe_mixed_tst = 0.5 * rho_ml * (0.**2 - (0. - h_ml_tst)**2)
826 if (pe_mixed_tst - pe <= pe_threshold(im))
then 828 rhodz_ml = rhodz_ml_tst
853 cb = -(r1 * d1 + r2 * (2. * d1))
855 cc = -(r1 * d1 * (2. * d1) + (r2 * d))
859 c = d2**2 + d1**2 + 2. * (d1 * d2)
874 gx = 0.5 * (ca * (x*x*x) + cb * x**2 + cc * x + cd)
875 gpx = 0.5 * (3. * (ca * x**2) + 2. * (cb * x) + cc)
881 ix = 0.5 * (ca2 * x**2 + cb2 * x + cc2)
882 ipx = 0.5 * (2. * ca2 * x + cb2)
885 pe_mixed = gx * ihx + ix
886 fgx = pe_mixed - (pe + pe_threshold(im))
887 fpx = (gpx * hx - hpx * gx) * ihx**2 + ipx
892 if (abs(fgx) > pe_threshold(im) * pe_threshold_fraction)
then 895 if (x2 < 0. .or. x2 > dz(k))
then 919 if (id_mld(1) > 0)
call post_data(id_mld(1), mld(:,:,1), diagptr)
920 if (id_mld(2) > 0)
call post_data(id_mld(2), mld(:,:,2), diagptr)
921 if (id_mld(3) > 0)
call post_data(id_mld(3), mld(:,:,3), diagptr)
923 end subroutine diagnosemldbyenergy
928 subroutine applyboundaryfluxesinout(CS, G, GV, US, dt, fluxes, optics, nsw, h, tv, &
929 aggregate_FW_forcing, evap_CFL_limit, &
930 minimum_forcing_depth, cTKE, dSV_dT, dSV_dS, &
936 real,
intent(in) :: dt
937 type(
forcing),
intent(inout) :: fluxes
939 integer,
intent(in) :: nsw
941 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
945 logical,
intent(in) :: aggregate_fw_forcing
946 real,
intent(in) :: evap_cfl_limit
948 real,
intent(in) :: minimum_forcing_depth
950 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
951 optional,
intent(out) :: ctke
953 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
954 optional,
intent(out) :: dsv_dt
956 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
957 optional,
intent(out) :: dsv_ds
959 real,
dimension(SZI_(G),SZJ_(G)), &
960 optional,
intent(out) :: skinbuoyflux
963 integer,
parameter :: maxgroundings = 5
964 integer :: numberofgroundings, iground(maxgroundings), jground(maxgroundings)
965 real :: h_limit_fluxes
966 real :: iforcingdepthscale
968 real :: dthickness, dtemp, dsalt
969 real :: fractionofforcing, hold, ithickness
970 real :: rivermixconst
972 real,
dimension(SZI_(G)) :: &
992 real,
dimension(SZI_(G), SZK_(G)) :: &
998 real,
dimension(SZI_(G)) :: &
1001 real,
dimension(max(nsw,1),SZI_(G)) :: &
1006 real,
dimension(max(nsw,1),SZI_(G),SZK_(G)) :: &
1009 real,
dimension(maxGroundings) :: hgrounding
1010 real :: temp_in, salin_in
1015 logical :: calculate_energetics
1016 logical :: calculate_buoyancy
1017 integer,
dimension(2) :: eosdom
1018 integer :: i, j, is, ie, js, je, k, nz, n, nb
1019 character(len=45) :: mesg
1021 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1025 calculate_energetics = (
present(ctke) .and.
present(dsv_dt) .and.
present(dsv_ds))
1026 calculate_buoyancy =
present(skinbuoyflux)
1027 if (calculate_buoyancy) skinbuoyflux(:,:) = 0.0
1028 if (
present(ctke)) ctke(:,:,:) = 0.0
1029 g_hconv2 = (us%L_to_Z**2*gv%g_Earth * gv%H_to_RZ) * gv%H_to_RZ
1030 eosdom(:) = eos_domain(g%HI)
1033 if (.not.
associated(fluxes%sw) .and. .not.calculate_energetics)
return 1035 if (calculate_buoyancy)
then 1036 surfpressure(:) = 0.0
1037 gorho = us%L_to_Z**2*gv%g_Earth / gv%Rho0
1045 h_limit_fluxes = max(gv%Angstrom_H, 1.e-30*gv%m_to_H)
1048 if (cs%id_createdH>0) cs%createdH(:,:) = 0.
1049 numberofgroundings = 0
1070 do k=1,nz ;
do i=is,ie
1072 t2d(i,k) = tv%T(i,j,k)
1075 if (calculate_energetics)
then 1079 if (
associated(tv%p_surf))
then 1080 do i=is,ie ; pres(i) = tv%p_surf(i,j) ;
enddo 1082 do i=is,ie ; pres(i) = 0.0 ;
enddo 1086 d_pres(i) = (gv%g_Earth * gv%H_to_RZ) * h2d(i,k)
1087 p_lay(i) = pres(i) + 0.5*d_pres(i)
1088 pres(i) = pres(i) + d_pres(i)
1091 dsv_dt(:,j,k), dsv_ds(:,j,k), tv%eqn_of_state, eosdom)
1092 do i=is,ie ; dsv_dt_2d(i,k) = dsv_dt(i,j,k) ;
enddo 1094 pen_tke_2d(:,:) = 0.0
1098 if (.not.
associated(fluxes%sw)) cycle
1100 if (nsw>0)
call extract_optics_slice(optics, j, g, gv, opacity=opacityband, opacity_scale=(1.0/gv%m_to_H))
1145 if (calculate_buoyancy)
then 1146 call extractfluxes1d(g, gv, us, fluxes, optics, nsw, j, dt, &
1147 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1148 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1149 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw, &
1150 net_heat_rate=netheat_rate, net_salt_rate=netsalt_rate, &
1151 netmassinout_rate=netmassinout_rate, pen_sw_bnd_rate=pen_sw_bnd_rate)
1153 call extractfluxes1d(g, gv, us, fluxes, optics, nsw, j, dt, &
1154 h_limit_fluxes, cs%use_river_heat_content, cs%use_calving_heat_content, &
1155 h2d, t2d, netmassinout, netmassout, netheat, netsalt, &
1156 pen_sw_bnd, tv, aggregate_fw_forcing, nonpensw=nonpensw)
1161 if (aggregate_fw_forcing)
then 1162 netmassout(i) = netmassinout(i)
1165 netmassin(i) = netmassinout(i) - netmassout(i)
1167 if (g%mask2dT(i,j)>0.0)
then 1168 fluxes%netMassOut(i,j) = netmassout(i)
1169 fluxes%netMassIn(i,j) = netmassin(i)
1171 fluxes%netMassOut(i,j) = 0.0
1172 fluxes%netMassIn(i,j) = 0.0
1182 if (g%mask2dT(i,j)>0.)
then 1188 dthickness = netmassin(i)
1194 netmassin(i) = netmassin(i) - dthickness
1198 dtemp = dtemp + dthickness*temp_in
1201 if (
associated(fluxes%heat_content_massin)) &
1202 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1203 t2d(i,k) * max(0.,dthickness) * gv%H_to_RZ * fluxes%C_p * idt
1204 if (
associated(fluxes%heat_content_massout)) &
1205 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1206 t2d(i,k) * min(0.,dthickness) * gv%H_to_RZ * fluxes%C_p * idt
1207 if (
associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1208 t2d(i,k) * dthickness * gv%H_to_RZ
1211 if (calculate_energetics .and.
associated(fluxes%lrunoff) .and. cs%do_rivermix)
then 1222 if (gv%Boussinesq)
then 1223 rivermixconst = -0.5*(cs%rivermix_depth*dt) * ( us%L_to_Z**2*gv%g_Earth ) * gv%Rho0
1225 rivermixconst = -0.5*(cs%rivermix_depth*dt) * gv%Rho0 * ( us%L_to_Z**2*gv%g_Earth )
1227 ctke(i,j,k) = ctke(i,j,k) + max(0.0, rivermixconst*dsv_ds(i,j,1) * &
1228 (fluxes%lrunoff(i,j) + fluxes%frunoff(i,j)) * tv%S(i,j,1))
1233 h2d(i,k) = h2d(i,k) + dthickness
1234 if (h2d(i,k) > 0.0)
then 1235 if (calculate_energetics .and. (dthickness > 0.))
then 1238 ctke(i,j,k) = ctke(i,j,k) + 0.5*g_hconv2*(hold*dthickness) * &
1239 ((t2d(i,k) - temp_in) * dsv_dt(i,j,k) + (tv%S(i,j,k) - salin_in) * dsv_ds(i,j,k))
1241 ithickness = 1.0/h2d(i,k)
1243 if (dthickness /= 0. .or. dtemp /= 0.) t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1244 if (dthickness /= 0. .or. dsalt /= 0.) tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1256 iforcingdepthscale = 1. / max(gv%H_subroundoff, minimum_forcing_depth - netmassout(i) )
1258 fractionofforcing = min(1.0, h2d(i,k)*iforcingdepthscale)
1263 if (-fractionofforcing*netmassout(i) > evap_cfl_limit*h2d(i,k))
then 1264 fractionofforcing = -evap_cfl_limit*h2d(i,k)/netmassout(i)
1269 dthickness = max( fractionofforcing*netmassout(i), -h2d(i,k) )
1270 dtemp = fractionofforcing*netheat(i)
1272 dsalt = max( fractionofforcing*netsalt(i), -0.9999*h2d(i,k)*tv%S(i,j,k))
1276 netmassout(i) = netmassout(i) - dthickness
1277 netheat(i) = netheat(i) - dtemp
1278 netsalt(i) = netsalt(i) - dsalt
1281 dtemp = dtemp + dthickness*t2d(i,k)
1284 if (
associated(fluxes%heat_content_massin)) &
1285 fluxes%heat_content_massin(i,j) = fluxes%heat_content_massin(i,j) + &
1286 t2d(i,k) * max(0.,dthickness) * gv%H_to_RZ * fluxes%C_p * idt
1287 if (
associated(fluxes%heat_content_massout)) &
1288 fluxes%heat_content_massout(i,j) = fluxes%heat_content_massout(i,j) + &
1289 t2d(i,k) * min(0.,dthickness) * gv%H_to_RZ * fluxes%C_p * idt
1290 if (
associated(tv%TempxPmE)) tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + &
1291 t2d(i,k) * dthickness * gv%H_to_RZ
1295 h2d(i,k) = h2d(i,k) + dthickness
1297 if (h2d(i,k) > 0.)
then 1298 if (calculate_energetics)
then 1304 ctke(i,j,k) = ctke(i,j,k) - (0.5*h2d(i,k)*g_hconv2) * &
1305 ((dtemp - dthickness*t2d(i,k)) * dsv_dt(i,j,k) + &
1306 (dsalt - dthickness*tv%S(i,j,k)) * dsv_ds(i,j,k))
1308 ithickness = 1.0/h2d(i,k)
1309 t2d(i,k) = (hold*t2d(i,k) + dtemp)*ithickness
1310 tv%S(i,j,k) = (hold*tv%S(i,j,k) + dsalt)*ithickness
1311 elseif (h2d(i,k) < 0.0)
then 1312 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (h<0)')
1313 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1314 write(0,*)
'applyBoundaryFluxesInOut(): netT,netS,netH=',netheat(i),netsalt(i),netmassinout(i)
1315 write(0,*)
'applyBoundaryFluxesInOut(): dT,dS,dH=',dtemp,dsalt,dthickness
1316 write(0,*)
'applyBoundaryFluxesInOut(): h(n),h(n+1),k=',hold,h2d(i,k),k
1317 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1318 "Complete mass loss in column!")
1324 elseif ((abs(netheat(i))+abs(netsalt(i))+abs(netmassin(i))+abs(netmassout(i)))>0.)
then 1326 if (.not. cs%ignore_fluxes_over_land)
then 1327 call forcing_singlepointprint(fluxes,g,i,j,
'applyBoundaryFluxesInOut (land)')
1328 write(0,*)
'applyBoundaryFluxesInOut(): lon,lat=',g%geoLonT(i,j),g%geoLatT(i,j)
1329 write(0,*)
'applyBoundaryFluxesInOut(): netHeat,netSalt,netMassIn,netMassOut=',&
1330 netheat(i),netsalt(i),netmassin(i),netmassout(i)
1332 call mom_error(fatal,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1333 "Mass loss over land?")
1339 if (netmassin(i)+netmassout(i) /= 0.0)
then 1341 numberofgroundings = numberofgroundings +1
1342 if (numberofgroundings<=maxgroundings)
then 1343 iground(numberofgroundings) = i
1344 jground(numberofgroundings) = j
1345 hgrounding(numberofgroundings) = netmassin(i)+netmassout(i)
1348 if (cs%id_createdH>0) cs%createdH(i,j) = cs%createdH(i,j) - (netmassin(i)+netmassout(i))/dt
1359 if (cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then 1360 do k=1,nz ;
do i=is,ie
1361 cs%penSW_diag(i,j,k) = t2d(i,k)
1362 cs%penSWflux_diag(i,j,k) = 0.0
1365 cs%penSWflux_diag(i,j,k) = 0.0
1369 if (calculate_energetics)
then 1370 call absorbremainingsw(g, gv, us, h2d, opacityband, nsw, optics, j, dt, h_limit_fluxes, &
1371 .false., .true., t2d, pen_sw_bnd, tke=pen_tke_2d, dsv_dt=dsv_dt_2d)
1373 do k=1,nz ;
do i=is,ie
1374 ctke(i,j,k) = ctke(i,j,k) + pen_tke_2d(i,k)
1377 call absorbremainingsw(g, gv, us, h2d, opacityband, nsw, optics, j, dt, h_limit_fluxes, &
1378 .false., .true., t2d, pen_sw_bnd)
1384 do k=1,nz ;
do i=is,ie
1386 tv%T(i,j,k) = t2d(i,k)
1391 if (cs%id_penSW_diag > 0 .or. cs%id_penSWflux_diag > 0)
then 1394 do k=1,nz ;
do i=is,ie
1395 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_RZ
1404 if (cs%id_penSWflux_diag > 0)
then 1405 do k=nz,1,-1 ;
do i=is,ie
1406 cs%penSWflux_diag(i,j,k) = cs%penSW_diag(i,j,k) + cs%penSWflux_diag(i,j,k+1)
1413 if (cs%id_nonpenSW_diag > 0)
then 1415 cs%nonpenSW_diag(i,j) = nonpensw(i) * idt * tv%C_p * gv%H_to_RZ
1424 if (calculate_buoyancy)
then 1427 netpen_rate(:) = 0.0
1434 do i=is,ie ;
do nb=1,nsw ; netpen_rate(i) = netpen_rate(i) + pen_sw_bnd_rate(nb,i) ;
enddo ;
enddo 1437 if (
associated(tv%p_surf))
then ;
do i=is,ie ; surfpressure(i) = tv%p_surf(i,j) ;
enddo ;
endif 1439 tv%eqn_of_state, eosdom)
1446 skinbuoyflux(i,j) = - gorho * gv%H_to_Z * &
1447 (drhods(i) * (netsalt_rate(i) - tv%S(i,j,1)*netmassinout_rate(i)) + &
1448 drhodt(i) * ( netheat_rate(i) + netpen_rate(i)) )
1455 if (cs%id_createdH > 0)
call post_data(cs%id_createdH , cs%createdH , cs%diag)
1456 if (cs%id_penSW_diag > 0)
call post_data(cs%id_penSW_diag , cs%penSW_diag , cs%diag)
1457 if (cs%id_penSWflux_diag > 0)
call post_data(cs%id_penSWflux_diag, cs%penSWflux_diag, cs%diag)
1458 if (cs%id_nonpenSW_diag > 0)
call post_data(cs%id_nonpenSW_diag , cs%nonpenSW_diag , cs%diag)
1461 if (numberofgroundings>0 .and. .not. cs%ignore_fluxes_over_land)
then 1462 do i = 1, min(numberofgroundings, maxgroundings)
1463 call forcing_singlepointprint(fluxes,g,iground(i),jground(i),
'applyBoundaryFluxesInOut (grounding)')
1464 write(mesg(1:45),
'(3es15.3)') g%geoLonT( iground(i), jground(i) ), &
1465 g%geoLatT( iground(i), jground(i)), hgrounding(i)*gv%H_to_m
1466 call mom_error(warning,
"MOM_diabatic_driver.F90, applyBoundaryFluxesInOut(): "//&
1467 "Mass created. x,y,dh= "//trim(mesg), all_print=.true.)
1470 if (numberofgroundings - maxgroundings > 0)
then 1471 write(mesg,
'(i4)') numberofgroundings - maxgroundings
1472 call mom_error(warning,
"MOM_diabatic_driver:F90, applyBoundaryFluxesInOut(): "//&
1473 trim(mesg) //
" groundings remaining")
1477 end subroutine applyboundaryfluxesinout
1480 subroutine diabatic_aux_init(Time, G, GV, US, param_file, diag, CS, useALEalgorithm, use_ePBL)
1481 type(time_type),
target,
intent(in) :: time
1486 type(
diag_ctrl),
target,
intent(inout) :: diag
1489 logical,
intent(in) :: usealealgorithm
1491 logical,
intent(in) :: use_epbl
1496 #include "version_variable.h" 1497 character(len=40) :: mdl =
"MOM_diabatic_aux" 1498 character(len=48) :: thickness_units
1499 character(len=200) :: inputdir
1500 character(len=240) :: chl_filename
1501 character(len=128) :: chl_file
1503 character(len=32) :: chl_varname
1504 logical :: use_temperature
1505 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz, nbands
1506 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = g%ke
1507 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1509 if (
associated(cs))
then 1510 call mom_error(warning,
"diabatic_aux_init called with an "// &
1511 "associated control structure.")
1522 "The following parameters are used for auxiliary diabatic processes.")
1524 call get_param(param_file, mdl,
"ENABLE_THERMODYNAMICS", use_temperature, &
1525 "If true, temperature and salinity are used as state "//&
1526 "variables.", default=.true.)
1528 call get_param(param_file, mdl,
"RECLAIM_FRAZIL", cs%reclaim_frazil, &
1529 "If true, try to use any frazil heat deficit to cool any "//&
1530 "overlying layers down to the freezing point, thereby "//&
1531 "avoiding the creation of thin ice when the SST is above "//&
1532 "the freezing point.", default=.true.)
1533 call get_param(param_file, mdl,
"PRESSURE_DEPENDENT_FRAZIL", &
1534 cs%pressure_dependent_frazil, &
1535 "If true, use a pressure dependent freezing temperature "//&
1536 "when making frazil. The default is false, which will be "//&
1537 "faster but is inappropriate with ice-shelf cavities.", &
1541 call get_param(param_file, mdl,
"IGNORE_FLUXES_OVER_LAND", cs%ignore_fluxes_over_land,&
1542 "If true, the model does not check if fluxes are being applied "//&
1543 "over land points. This is needed when the ocean is coupled "//&
1544 "with ice shelves and sea ice, since the sea ice mask needs to "//&
1545 "be different than the ocean mask to avoid sea ice formation "//&
1546 "under ice shelves. This flag only works when use_ePBL = True.", default=.false.)
1547 call get_param(param_file, mdl,
"DO_RIVERMIX", cs%do_rivermix, &
1548 "If true, apply additional mixing wherever there is "//&
1549 "runoff, so that it is mixed down to RIVERMIX_DEPTH "//&
1550 "if the ocean is that deep.", default=.false.)
1551 if (cs%do_rivermix) &
1552 call get_param(param_file, mdl,
"RIVERMIX_DEPTH", cs%rivermix_depth, &
1553 "The depth to which rivers are mixed if DO_RIVERMIX is "//&
1554 "defined.", units=
"m", default=0.0, scale=us%m_to_Z)
1556 cs%do_rivermix = .false. ; cs%rivermix_depth = 0.0 ; cs%ignore_fluxes_over_land = .false.
1559 if (gv%nkml == 0)
then 1560 call get_param(param_file, mdl,
"USE_RIVER_HEAT_CONTENT", cs%use_river_heat_content, &
1561 "If true, use the fluxes%runoff_Hflx field to set the "//&
1562 "heat carried by runoff, instead of using SST*CP*liq_runoff.", &
1564 call get_param(param_file, mdl,
"USE_CALVING_HEAT_CONTENT", cs%use_calving_heat_content, &
1565 "If true, use the fluxes%calving_Hflx field to set the "//&
1566 "heat carried by runoff, instead of using SST*CP*froz_runoff.", &
1569 cs%use_river_heat_content = .false.
1570 cs%use_calving_heat_content = .false.
1573 if (usealealgorithm)
then 1574 cs%id_createdH = register_diag_field(
'ocean_model',
"created_H",diag%axesT1, &
1575 time,
"The volume flux added to stop the ocean from drying out and becoming negative in depth", &
1576 "m s-1", conversion=gv%H_to_m*us%s_to_T)
1577 if (cs%id_createdH>0)
allocate(cs%createdH(isd:ied,jsd:jed))
1580 cs%id_penSW_diag = register_diag_field(
'ocean_model',
'rsdoabsorb', &
1581 diag%axesTL, time,
'Convergence of Penetrative Shortwave Flux in Sea Water Layer',&
1582 'W m-2', conversion=us%QRZ_T_to_W_m2, &
1583 standard_name=
'net_rate_of_absorption_of_shortwave_energy_in_ocean_layer', v_extensive=.true.)
1587 cs%id_penSWflux_diag = register_diag_field(
'ocean_model',
'rsdo', &
1588 diag%axesTi, time,
'Downwelling Shortwave Flux in Sea Water at Grid Cell Upper Interface',&
1589 'W m-2', conversion=us%QRZ_T_to_W_m2, standard_name=
'downwelling_shortwave_flux_in_sea_water')
1592 if (cs%id_penSW_diag>0 .or. cs%id_penSWflux_diag>0)
then 1593 allocate(cs%penSW_diag(isd:ied,jsd:jed,nz)) ; cs%penSW_diag(:,:,:) = 0.0
1594 allocate(cs%penSWflux_diag(isd:ied,jsd:jed,nz+1)) ; cs%penSWflux_diag(:,:,:) = 0.0
1598 cs%id_nonpenSW_diag = register_diag_field(
'ocean_model',
'nonpenSW', &
1599 diag%axesT1, time, &
1600 'Non-downwelling SW radiation (i.e., SW absorbed in ocean surface with LW,SENS,LAT)',&
1601 'W m-2', conversion=us%QRZ_T_to_W_m2, &
1602 standard_name=
'nondownwelling_shortwave_flux_in_sea_water')
1603 if (cs%id_nonpenSW_diag > 0)
then 1604 allocate(cs%nonpenSW_diag(isd:ied,jsd:jed)) ; cs%nonpenSW_diag(:,:) = 0.0
1608 if (use_temperature)
then 1609 call get_param(param_file, mdl,
"VAR_PEN_SW", cs%var_pen_sw, &
1610 "If true, use one of the CHL_A schemes specified by "//&
1611 "OPACITY_SCHEME to determine the e-folding depth of "//&
1612 "incoming short wave radiation.", default=.false.)
1613 if (cs%var_pen_sw)
then 1615 call get_param(param_file, mdl,
"CHL_FROM_FILE", cs%chl_from_file, &
1616 "If true, chl_a is read from a file.", default=.true.)
1617 if (cs%chl_from_file)
then 1618 call time_interp_external_init()
1620 call get_param(param_file, mdl,
"INPUTDIR", inputdir, default=
".")
1621 call get_param(param_file, mdl,
"CHL_FILE", chl_file, &
1622 "CHL_FILE is the file containing chl_a concentrations in "//&
1623 "the variable CHL_A. It is used when VAR_PEN_SW and "//&
1624 "CHL_FROM_FILE are true.", fail_if_missing=.true.)
1625 chl_filename = trim(slasher(inputdir))//trim(chl_file)
1626 call log_param(param_file, mdl,
"INPUTDIR/CHL_FILE", chl_filename)
1627 call get_param(param_file, mdl,
"CHL_VARNAME", chl_varname, &
1628 "Name of CHL_A variable in CHL_FILE.", default=
'CHL_A')
1629 cs%sbc_chl = init_external_field(chl_filename, trim(chl_varname), domain=g%Domain%mpp_domain)
1632 cs%id_chl = register_diag_field(
'ocean_model',
'Chl_opac', diag%axesT1, time, &
1633 'Surface chlorophyll A concentration used to find opacity',
'mg m-3')
1637 id_clock_uv_at_h = cpu_clock_id(
'(Ocean find_uv_at_h)', grain=clock_routine)
1638 id_clock_frazil = cpu_clock_id(
'(Ocean frazil)', grain=clock_routine)
1640 end subroutine diabatic_aux_init
1644 subroutine diabatic_aux_end(CS)
1648 if (.not.
associated(cs))
return 1650 if (cs%id_createdH >0)
deallocate(cs%createdH)
1651 if (cs%id_penSW_diag >0)
deallocate(cs%penSW_diag)
1652 if (cs%id_penSWflux_diag >0)
deallocate(cs%penSWflux_diag)
1653 if (cs%id_nonpenSW_diag >0)
deallocate(cs%nonpenSW_diag)
1655 if (
associated(cs))
deallocate(cs)
1657 end subroutine diabatic_aux_end
This module implements boundary forcing for MOM6.
Calculate the derivatives of specific volume with temperature and salinity from T, S, and P.
Provides functions for some diabatic processes such as fraxil, brine rejection, tendency due to surfa...
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
Calculates the freezing point of sea water from T, S and P.
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.
Orchestrates the registration and calling of tracer packages.
Make a diagnostic available for averaging or output.
The control structure with paramters for the MOM_opacity module.
Describes various unit conversion factors.
Control structure for diabatic_aux.
Routines used to calculate the opacity of the ocean.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Routines for error handling and I/O management.
The control structure for orchestrating the calling of tracer packages.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Provides subroutines for quantities specific to the equation of state.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
This type is used to store information about ocean optical properties.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.