23 implicit none ;
private 25 #include <MOM_memory.h> 33 real :: ml_restrat_coef
38 real :: ml_restrat_coef2
43 logical :: mle_use_pbl_mld
46 real :: mle_mld_decay_time
47 real :: mle_mld_decay_time2
48 real :: mle_density_diff
53 real :: mle_mld_stretch
55 logical :: mle_use_mld_ave_bug
56 logical :: debug = .false.
60 real,
dimension(:,:),
pointer :: &
61 mld_filtered => null(), &
62 mld_filtered_slow => null()
66 integer :: id_urestrat_time = -1
67 integer :: id_vrestrat_time = -1
68 integer :: id_uhml = -1
69 integer :: id_vhml = -1
70 integer :: id_mld = -1
71 integer :: id_rml = -1
72 integer :: id_udml = -1
73 integer :: id_vdml = -1
74 integer :: id_uml = -1
75 integer :: id_vml = -1
80 character(len=40) ::
mdl =
"MOM_mixed_layer_restrat" 87 subroutine mixedlayer_restrat(h, uhtr, vhtr, tv, fluxes, dt, MLD, VarMix, G, GV, CS)
90 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
91 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
92 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
94 type(
forcing),
intent(in) :: fluxes
95 real,
intent(in) :: dt
96 real,
dimension(:,:),
pointer :: MLD
100 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
101 "Module must be initialized before it is used.")
106 call mixedlayer_restrat_general(h, uhtr, vhtr, tv, fluxes, dt, mld, varmix, g, gv, cs)
112 subroutine mixedlayer_restrat_general(h, uhtr, vhtr, tv, fluxes, dt, MLD_in, VarMix, G, GV, CS)
116 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
117 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
118 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
120 type(
forcing),
intent(in) :: fluxes
121 real,
intent(in) :: dt
122 real,
dimension(:,:),
pointer :: MLD_in
126 real :: uhml(szib_(g),szj_(g),szk_(g))
127 real :: vhml(szi_(g),szjb_(g),szk_(g))
128 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
132 real,
dimension(SZI_(G),SZJ_(G)) :: &
140 real :: rho_ml(szi_(g))
151 real :: Ihtot,Ihtot_slow
157 real :: uDml(szib_(g))
158 real :: vDml(szi_(g))
159 real :: uDml_slow(szib_(g))
160 real :: vDml_slow(szi_(g))
161 real :: utimescale_diag(szib_(g),szj_(g))
162 real :: vtimescale_diag(szi_(g),szjb_(g))
165 real :: uDml_diag(szib_(g),szj_(g)), vDml_diag(szi_(g),szjb_(g))
166 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
167 real,
dimension(SZI_(G)) :: rhoSurf, deltaRhoAtKm1, deltaRhoAtK, dK, dKm1, pRef_MLD
168 real,
dimension(SZI_(G)) :: rhoAtK, rho1, d1, pRef_N2
169 real :: aFac, bFac, ddRho
170 real :: hAtVel, zpa, zpb, dh, res_scaling_fac, I_l_f
171 logical :: proper_averaging, line_is_empty, keep_going, res_upscale
173 real :: PSI, PSI1, z, BOTTOP, XP, DD
176 psi1(z) = max(0., (1. - (2.*z+1.)**2 ) * (1. + (5./21.)*(2.*z+1.)**2) )
177 bottop(z) = 0.5*(1.-sign(1.,z+0.5))
178 xp(z) = max(0., min(1., (-z-0.5)*2./(1.+2.*cs%MLE_tail_dh) ) )
179 dd(z) = (1.-3.*(xp(z)**2)+2.*(xp(z)**3))**(1.+2.*cs%MLE_tail_dh)
180 psi(z) = max( psi1(z), dd(z)*bottop(z) )
182 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
183 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
185 if (.not.
associated(tv%eqn_of_state))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
186 "An equation of state must be used with this module.")
187 if (.not.
associated(varmix) .and. cs%front_length>0.)
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
188 "The resolution argument, Rd/dx, was not associated.")
190 if (cs%MLE_density_diff > 0.)
then 194 dk(:) = 0.5 * h(:,j,1) * gv%H_to_m
195 call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pref_mld, rhosurf, is-1, ie-is+3, tv%eqn_of_state)
200 dk(:) = dk(:) + 0.5 * ( h(:,j,k) + h(:,j,k-1) ) * gv%H_to_m
202 deltarhoatkm1(:) = deltarhoatk(:)
203 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pref_mld, deltarhoatk, is-1, ie-is+3, tv%eqn_of_state)
204 deltarhoatk(:) = deltarhoatk(:) - rhosurf(:)
206 ddrho = deltarhoatk(i) - deltarhoatkm1(i)
207 if ((mld_fast(i,j)==0.) .and. (ddrho>0.) .and. &
208 (deltarhoatkm1(i)<cs%MLE_density_diff) .and. (deltarhoatk(i)>=cs%MLE_density_diff))
then 209 afac = ( cs%MLE_density_diff - deltarhoatkm1(i) ) / ddrho
210 mld_fast(i,j) = dk(i) * afac + dkm1(i) * (1. - afac)
215 mld_fast(i,j) = cs%MLE_MLD_stretch * mld_fast(i,j)
216 if ((mld_fast(i,j)==0.) .and. (deltarhoatk(i)<cs%MLE_density_diff)) mld_fast(i,j) = dk(i)
219 elseif (cs%MLE_use_PBL_MLD)
then 220 if (.not.
associated(mld_in))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
221 "Argument MLD_in was not associated!")
222 do j = js-1, je+1 ;
do i = is-1, ie+1
223 mld_fast(i,j) = cs%MLE_MLD_stretch * mld_in(i,j)
226 call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
227 "No MLD to use for MLE parameterization.")
231 if (cs%MLE_MLD_decay_time>0.)
then 233 call hchksum(cs%MLD_filtered,
'mixed_layer_restrat: MLD_filtered',g%HI,haloshift=1)
234 call hchksum(mld_in,
'mixed_layer_restrat: MLD in',g%HI,haloshift=1)
236 afac = cs%MLE_MLD_decay_time / ( dt + cs%MLE_MLD_decay_time )
237 bfac = dt / ( dt + cs%MLE_MLD_decay_time )
238 do j = js-1, je+1 ;
do i = is-1, ie+1
242 cs%MLD_filtered(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered(i,j) )
243 mld_fast(i,j) = cs%MLD_filtered(i,j)
248 if (cs%MLE_MLD_decay_time2>0.)
then 250 call hchksum(cs%MLD_filtered_slow,
'mixed_layer_restrat: MLD_filtered_slow',g%HI,haloshift=1)
251 call hchksum(mld_fast,
'mixed_layer_restrat: MLD fast',g%HI,haloshift=1)
253 afac = cs%MLE_MLD_decay_time2 / ( dt + cs%MLE_MLD_decay_time2 )
254 bfac = dt / ( dt + cs%MLE_MLD_decay_time2 )
255 do j = js-1, je+1 ;
do i = is-1, ie+1
259 cs%MLD_filtered_slow(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered_slow(i,j) )
260 mld_slow(i,j) = cs%MLD_filtered_slow(i,j)
263 do j = js-1, je+1 ;
do i = is-1, ie+1
264 mld_slow(i,j) = mld_fast(i,j)
268 udml(:) = 0.0 ; vdml(:) = 0.0
269 udml_slow(:) = 0.0 ; vdml_slow(:) = 0.0
271 g_rho0 = gv%g_Earth/gv%Rho0
272 h_neglect = gv%H_subroundoff
273 dz_neglect = gv%H_subroundoff*gv%H_to_m
274 proper_averaging = .not. cs%MLE_use_MLD_ave_bug
275 if (cs%front_length>0.)
then 277 i_l_f = 1./cs%front_length
279 res_upscale = .false.
296 htot_fast(i,j) = 0.0 ; rml_av_fast(i,j) = 0.0
297 htot_slow(i,j) = 0.0 ; rml_av_slow(i,j) = 0.0
302 h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom),0.0)
305 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho_ml(:),is-1,ie-is+3,tv%eqn_of_state)
306 line_is_empty = .true.
308 if (htot_fast(i,j) < mld_fast(i,j))
then 310 if (proper_averaging) dh = min( h(i,j,k), mld_fast(i,j)-htot_fast(i,j) )
311 rml_av_fast(i,j) = rml_av_fast(i,j) + dh*rho_ml(i)
312 htot_fast(i,j) = htot_fast(i,j) + dh
313 line_is_empty = .false.
315 if (htot_slow(i,j) < mld_slow(i,j))
then 316 dh = min( h(i,j,k), mld_slow(i,j)-htot_slow(i,j) )
317 rml_av_slow(i,j) = rml_av_slow(i,j) + dh*rho_ml(i)
318 htot_slow(i,j) = htot_slow(i,j) + dh
319 line_is_empty = .false.
322 if (line_is_empty) keep_going=.false.
327 rml_av_fast(i,j) = -(g_rho0*rml_av_fast(i,j)) / (htot_fast(i,j) + h_neglect)
328 rml_av_slow(i,j) = -(g_rho0*rml_av_slow(i,j)) / (htot_slow(i,j) + h_neglect)
333 call hchksum(h,
'mixed_layer_restrat: h',g%HI,haloshift=1)
334 call hchksum(fluxes%ustar,
'mixed_layer_restrat: u*',g%HI,haloshift=1)
335 call hchksum(mld_fast,
'mixed_layer_restrat: MLD',g%HI,haloshift=1)
336 call hchksum(rml_av_fast,
'mixed_layer_restrat: rml',g%HI,haloshift=1)
345 do j=js,je ;
do i=is-1,ie
346 u_star = 0.5*(fluxes%ustar(i,j) + fluxes%ustar(i+1,j))
347 absf = 0.5*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
349 if (res_upscale) res_scaling_fac = &
350 ( sqrt( 0.5 * ( g%dxCu(i,j)**2 + g%dyCu(i,j)**2 ) ) * i_l_f ) &
351 * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i+1,j) ) )
356 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect) * gv%H_to_m
357 mom_mixrate = (0.41*9.8696)*u_star**2 / &
358 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
359 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
360 timescale = timescale * cs%ml_restrat_coef
361 if (res_upscale) timescale = timescale * res_scaling_fac
362 udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
363 g%IdxCu(i,j)*(rml_av_fast(i+1,j)-rml_av_fast(i,j)) * (h_vel**2 * gv%m_to_H)
365 h_vel = 0.5*((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect) * gv%H_to_m
366 mom_mixrate = (0.41*9.8696)*u_star**2 / &
367 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
368 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
369 timescale = timescale * cs%ml_restrat_coef2
370 if (res_upscale) timescale = timescale * res_scaling_fac
371 udml_slow(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
372 g%IdxCu(i,j)*(rml_av_slow(i+1,j)-rml_av_slow(i,j)) * (h_vel**2 * gv%m_to_H)
374 if (udml(i) + udml_slow(i) == 0.)
then 375 do k=1,nz ; uhml(i,j,k) = 0.0 ;
enddo 377 ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
378 ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect)
379 zpa = 0.0 ; zpb = 0.0
383 hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
385 zpa = zpa - (hatvel * ihtot)
386 a(k) = a(k) - psi(zpa)
388 if (a(k)*udml(i) > 0.0)
then 389 if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
390 elseif (a(k)*udml(i) < 0.0)
then 391 if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k) / a(k)
396 hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
398 zpb = zpb - (hatvel * ihtot_slow)
399 b(k) = b(k) - psi(zpb)
401 if (b(k)*udml_slow(i) > 0.0)
then 402 if (b(k)*udml_slow(i) > h_avail(i,j,k) - a(k)*udml(i)) &
403 udml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*udml(i) ) / b(k)
404 elseif (b(k)*udml_slow(i) < 0.0)
then 405 if (-b(k)*udml_slow(i) > h_avail(i+1,j,k) + a(k)*udml(i)) &
406 udml_slow(i) = -max( 0., h_avail(i+1,j,k) + a(k)*udml(i) ) / b(k)
410 uhml(i,j,k) = a(k)*udml(i) + b(k)*udml_slow(i)
411 uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
415 utimescale_diag(i,j) = timescale
416 udml_diag(i,j) = udml(i)
421 do j=js-1,je ;
do i=is,ie
422 u_star = 0.5*(fluxes%ustar(i,j) + fluxes%ustar(i,j+1))
423 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
425 if (res_upscale) res_scaling_fac = &
426 ( sqrt( 0.5 * ( g%dxCv(i,j)**2 + g%dyCv(i,j)**2 ) ) * i_l_f ) &
427 * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i,j+1) ) )
432 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect) * gv%H_to_m
433 mom_mixrate = (0.41*9.8696)*u_star**2 / &
434 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
435 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
436 timescale = timescale * cs%ml_restrat_coef
437 if (res_upscale) timescale = timescale * res_scaling_fac
438 vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
439 g%IdyCv(i,j)*(rml_av_fast(i,j+1)-rml_av_fast(i,j)) * (h_vel**2 * gv%m_to_H)
441 h_vel = 0.5*((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect) * gv%H_to_m
442 mom_mixrate = (0.41*9.8696)*u_star**2 / &
443 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
444 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
445 timescale = timescale * cs%ml_restrat_coef2
446 if (res_upscale) timescale = timescale * res_scaling_fac
447 vdml_slow(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
448 g%IdyCv(i,j)*(rml_av_slow(i,j+1)-rml_av_slow(i,j)) * (h_vel**2 * gv%m_to_H)
450 if (vdml(i) + vdml_slow(i) == 0.)
then 451 do k=1,nz ; vhml(i,j,k) = 0.0 ;
enddo 453 ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
454 ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect)
455 zpa = 0.0 ; zpb = 0.0
459 hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
461 zpa = zpa - (hatvel * ihtot)
462 a(k) = a(k) - psi( zpa )
464 if (a(k)*vdml(i) > 0.0)
then 465 if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
466 elseif (a(k)*vdml(i) < 0.0)
then 467 if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k) / a(k)
472 hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
474 zpb = zpb - (hatvel * ihtot_slow)
475 b(k) = b(k) - psi(zpb)
477 if (b(k)*vdml_slow(i) > 0.0)
then 478 if (b(k)*vdml_slow(i) > h_avail(i,j,k) - a(k)*vdml(i)) &
479 vdml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*vdml(i) ) / b(k)
480 elseif (b(k)*vdml_slow(i) < 0.0)
then 481 if (-b(k)*vdml_slow(i) > h_avail(i,j+1,k) + a(k)*vdml(i)) &
482 vdml_slow(i) = -max( 0., h_avail(i,j+1,k) + a(k)*vdml(i) ) / b(k)
486 vhml(i,j,k) = a(k)*vdml(i) + b(k)*vdml_slow(i)
487 vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
491 vtimescale_diag(i,j) = timescale
492 vdml_diag(i,j) = vdml(i)
496 do j=js,je ;
do k=1,nz ;
do i=is,ie
497 h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
498 ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
499 enddo ;
enddo ;
enddo 503 if (query_averaging_enabled(cs%diag))
then 504 if (cs%id_urestrat_time > 0)
call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
505 if (cs%id_vrestrat_time > 0)
call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
506 if (cs%id_uhml > 0)
call post_data(cs%id_uhml, uhml, cs%diag)
507 if (cs%id_vhml > 0)
call post_data(cs%id_vhml, vhml, cs%diag)
508 if (cs%id_MLD > 0)
call post_data(cs%id_MLD, mld_fast, cs%diag)
509 if (cs%id_Rml > 0)
call post_data(cs%id_Rml, rml_av_fast, cs%diag)
510 if (cs%id_uDml > 0)
call post_data(cs%id_uDml, udml_diag, cs%diag)
511 if (cs%id_vDml > 0)
call post_data(cs%id_vDml, vdml_diag, cs%diag)
513 if (cs%id_uml > 0)
then 514 do j=js,je ;
do i=is,ie
515 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
516 udml_diag(i,j) = udml_diag(i,j) / (0.01*h_vel) * g%IdyCu(i,j) * (psi(0.)-psi(-.01))
518 call post_data(cs%id_uml, udml_diag, cs%diag)
520 if (cs%id_vml > 0)
then 521 do j=js,je ;
do i=is,ie
522 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
523 vdml_diag(i,j) = vdml_diag(i,j) / (0.01*h_vel) * g%IdxCv(i,j) * (psi(0.)-psi(-.01))
525 call post_data(cs%id_vml, vdml_diag, cs%diag)
540 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
541 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
542 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
544 type(
forcing),
intent(in) :: fluxes
545 real,
intent(in) :: dt
548 real :: uhml(szib_(g),szj_(g),szk_(g))
549 real :: vhml(szi_(g),szjb_(g),szk_(g))
550 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
554 real,
dimension(SZI_(G),SZJ_(G)) :: &
558 real :: Rho0(szi_(g))
576 real :: uDml(szib_(g))
577 real :: vDml(szi_(g))
578 real :: utimescale_diag(szib_(g),szj_(g))
579 real :: vtimescale_diag(szi_(g),szjb_(g))
582 real :: uDml_diag(szib_(g),szj_(g)), vDml_diag(szi_(g),szjb_(g))
585 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, nkml
586 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
587 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nkml = gv%nkml
589 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
590 "Module must be initialized before it is used.")
591 if ((nkml<2) .or. (cs%ml_restrat_coef<=0.0))
return 593 udml(:) = 0.0 ; vdml(:) = 0.0
595 g_rho0 = gv%g_Earth/gv%Rho0
596 use_eos =
associated(tv%eqn_of_state)
597 h_neglect = gv%H_subroundoff
598 dz_neglect = gv%H_subroundoff*gv%H_to_m
600 if (.not.use_eos)
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
601 "An equation of state must be used with this module.")
616 htot(i,j) = 0.0 ; rml_av(i,j) = 0.0
619 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho0(:),is-1,ie-is+3,tv%eqn_of_state)
621 rml_av(i,j) = rml_av(i,j) + h(i,j,k)*rho0(i)
622 htot(i,j) = htot(i,j) + h(i,j,k)
623 h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom),0.0)
628 rml_av(i,j) = (g_rho0*rml_av(i,j)) / (htot(i,j) + h_neglect)
639 do i=is,ie ; utimescale_diag(i,j) = 0.0 ;
enddo 640 do i=is,ie ; vtimescale_diag(i,j) = 0.0 ;
enddo 642 h_vel = 0.5*(htot(i,j) + htot(i+1,j)) * gv%H_to_m
644 u_star = 0.5*(fluxes%ustar(i,j) + fluxes%ustar(i+1,j))
645 absf = 0.5*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
649 mom_mixrate = (0.41*9.8696)*u_star**2 / &
650 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
651 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
653 timescale = timescale * cs%ml_restrat_coef
656 utimescale_diag(i,j) = timescale
658 udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)* &
659 g%IdxCu(i,j)*(rml_av(i+1,j)-rml_av(i,j)) * (h_vel**2 * gv%m_to_H)
661 if (udml(i) == 0)
then 662 do k=1,nkml ; uhml(i,j,k) = 0.0 ;
enddo 664 i2htot = 1.0 / (htot(i,j) + htot(i+1,j) + h_neglect)
669 hx2 = (h(i,j,k) + h(i+1,j,k) + h_neglect)
670 a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
671 z_topx2 = z_topx2 + hx2
672 if (a(k)*udml(i) > 0.0)
then 673 if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
675 if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k)/a(k)
679 uhml(i,j,k) = a(k)*udml(i)
680 uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
684 udml_diag(is:ie,j) = udml(is:ie)
689 do j=js-1,je ;
do i=is,ie
690 h_vel = 0.5*(htot(i,j) + htot(i,j+1)) * gv%H_to_m
692 u_star = 0.5*(fluxes%ustar(i,j) + fluxes%ustar(i,j+1))
693 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
697 mom_mixrate = (0.41*9.8696)*u_star**2 / &
698 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
699 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
701 timescale = timescale * cs%ml_restrat_coef
704 vtimescale_diag(i,j) = timescale
706 vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)* &
707 g%IdyCv(i,j)*(rml_av(i,j+1)-rml_av(i,j)) * (h_vel**2 * gv%m_to_H)
708 if (vdml(i) == 0)
then 709 do k=1,nkml ; vhml(i,j,k) = 0.0 ;
enddo 711 i2htot = 1.0 / (htot(i,j) + htot(i,j+1) + h_neglect)
716 hx2 = (h(i,j,k) + h(i,j+1,k) + h_neglect)
717 a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
718 z_topx2 = z_topx2 + hx2
719 if (a(k)*vdml(i) > 0.0)
then 720 if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
722 if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k)/a(k)
726 vhml(i,j,k) = a(k)*vdml(i)
727 vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
731 vdml_diag(is:ie,j) = vdml(is:ie)
735 do j=js,je ;
do k=1,nkml ;
do i=is,ie
736 h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
737 ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
738 enddo ;
enddo ;
enddo 746 if (query_averaging_enabled(cs%diag) .and. &
747 ((cs%id_urestrat_time > 0) .or. (cs%id_vrestrat_time > 0)))
then 748 call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
749 call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
751 if (query_averaging_enabled(cs%diag) .and. &
752 ((cs%id_uhml>0) .or. (cs%id_vhml>0)))
then 754 do j=js,je ;
do i=isq,ieq ; uhml(i,j,k) = 0.0 ;
enddo ;
enddo 755 do j=jsq,jeq ;
do i=is,ie ; vhml(i,j,k) = 0.0 ;
enddo ;
enddo 757 if (cs%id_uhml > 0)
call post_data(cs%id_uhml, uhml, cs%diag)
758 if (cs%id_vhml > 0)
call post_data(cs%id_vhml, vhml, cs%diag)
759 if (cs%id_MLD > 0)
call post_data(cs%id_MLD, htot, cs%diag)
760 if (cs%id_Rml > 0)
call post_data(cs%id_Rml, rml_av, cs%diag)
761 if (cs%id_uDml > 0)
call post_data(cs%id_uDml, udml_diag, cs%diag)
762 if (cs%id_vDml > 0)
call post_data(cs%id_vDml, vdml_diag, cs%diag)
770 type(time_type),
intent(in) :: Time
774 type(
diag_ctrl),
target,
intent(inout) :: diag
778 #include "version_variable.h" 779 character(len=48) :: flux_units
784 "If true, a density-gradient dependent re-stratifying \n"//&
785 "flow is imposed in the mixed layer. Can be used in ALE mode\n"//&
786 "without restriction but in layer mode can only be used if\n"//&
787 "BULKMIXEDLAYER is true.", default=.false.)
790 if (.not.
associated(cs))
then 791 call mom_error(fatal,
"mixedlayer_restrat_init called without an "// &
792 "associated control structure.")
796 cs%MLE_MLD_decay_time = -9.e9
797 cs%MLE_density_diff = -9.e9
798 cs%MLE_tail_dh = -9.e9
799 cs%MLE_use_PBL_MLD = .false.
800 cs%MLE_MLD_stretch = -9.e9
802 call get_param(param_file,
mdl,
"DEBUG", cs%debug, default=.false., do_not_log=.true.)
803 call get_param(param_file,
mdl,
"FOX_KEMPER_ML_RESTRAT_COEF", cs%ml_restrat_coef, &
804 "A nondimensional coefficient that is proportional to \n"//&
805 "the ratio of the deformation radius to the dominant \n"//&
806 "lengthscale of the submesoscale mixed layer \n"//&
807 "instabilities, times the minimum of the ratio of the \n"//&
808 "mesoscale eddy kinetic energy to the large-scale \n"//&
809 "geostrophic kinetic energy or 1 plus the square of the \n"//&
810 "grid spacing over the deformation radius, as detailed \n"//&
811 "by Fox-Kemper et al. (2010)", units=
"nondim", default=0.0)
815 call get_param(param_file,
mdl,
"FOX_KEMPER_ML_RESTRAT_COEF2", cs%ml_restrat_coef2, &
816 "As for FOX_KEMPER_ML_RESTRAT_COEF but used in a second application\n"//&
817 "of the MLE restratification parameterization.", units=
"nondim", default=0.0)
818 call get_param(param_file,
mdl,
"MLE_FRONT_LENGTH", cs%front_length, &
819 "If non-zero, is the frontal-length scale used to calculate the\n"//&
820 "upscaling of buoyancy gradients that is otherwise represented\n"//&
821 "by the parameter FOX_KEMPER_ML_RESTRAT_COEF. If MLE_FRONT_LENGTH is\n"//&
822 "non-zero, it is recommended to set FOX_KEMPER_ML_RESTRAT_COEF=1.0.",&
823 units=
"m", default=0.0)
824 call get_param(param_file,
mdl,
"MLE_USE_PBL_MLD", cs%MLE_use_PBL_MLD, &
825 "If true, the MLE parameterization will use the mixed-layer\n"//&
826 "depth provided by the active PBL parameterization. If false,\n"//&
827 "MLE will estimate a MLD based on a density difference with the\n"//&
828 "surface using the parameter MLE_DENSITY_DIFF.", default=.false.)
829 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
830 "The time-scale for a running-mean filter applied to the mixed-layer\n"//&
831 "depth used in the MLE restratification parameterization. When\n"//&
832 "the MLD deepens below the current running-mean the running-mean\n"//&
833 "is instantaneously set to the current MLD.", units=
"s", default=0.)
834 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
835 "The time-scale for a running-mean filter applied to the filtered\n"//&
836 "mixed-layer depth used in a second MLE restratification parameterization.\n"//&
837 "When the MLD deepens below the current running-mean the running-mean\n"//&
838 "is instantaneously set to the current MLD.", units=
"s", default=0.)
839 if (.not. cs%MLE_use_PBL_MLD)
then 840 call get_param(param_file,
mdl,
"MLE_DENSITY_DIFF", cs%MLE_density_diff, &
841 "Density difference used to detect the mixed-layer\n"//&
842 "depth used for the mixed-layer eddy parameterization\n"//&
843 "by Fox-Kemper et al. (2010)", units=
"kg/m3", default=0.03)
845 call get_param(param_file,
mdl,
"MLE_TAIL_DH", cs%MLE_tail_dh, &
846 "Fraction by which to extend the mixed-layer restratification\n"//&
847 "depth used for a smoother stream function at the base of\n"//&
848 "the mixed-layer.", units=
"nondim", default=0.0)
849 call get_param(param_file,
mdl,
"MLE_MLD_STRETCH", cs%MLE_MLD_stretch, &
850 "A scaling coefficient for stretching/shrinking the MLD\n"//&
851 "used in the MLE scheme. This simply multiplies MLD wherever used.",&
852 units=
"nondim", default=1.0)
853 call get_param(param_file,
mdl,
"MLE_USE_MLD_AVE_BUG", cs%MLE_use_MLD_ave_bug, &
854 "If true, do not account for MLD mismatch to interface positions.",&
860 if (gv%Boussinesq)
then ; flux_units =
"meter3 second-1" 861 else ; flux_units =
"kilogram second-1" ;
endif 863 cs%id_uhml = register_diag_field(
'ocean_model',
'uhml', diag%axesCuL, time, &
864 'Zonal Thickness Flux to Restratify Mixed Layer', flux_units, &
865 y_cell_method=
'sum', v_extensive=.true.)
866 cs%id_vhml = register_diag_field(
'ocean_model',
'vhml', diag%axesCvL, time, &
867 'Meridional Thickness Flux to Restratify Mixed Layer', flux_units, &
868 x_cell_method=
'sum', v_extensive=.true.)
869 cs%id_urestrat_time = register_diag_field(
'ocean_model',
'MLu_restrat_time', diag%axesCu1, time, &
870 'Mixed Layer Zonal Restratification Timescale',
'second')
871 cs%id_vrestrat_time = register_diag_field(
'ocean_model',
'MLv_restrat_time', diag%axesCv1, time, &
872 'Mixed Layer Meridional Restratification Timescale',
'second')
873 cs%id_MLD = register_diag_field(
'ocean_model',
'MLD_restrat', diag%axesT1, time, &
874 'Mixed Layer Depth as used in the mixed-layer restratification parameterization',
'meter')
875 cs%id_Rml = register_diag_field(
'ocean_model',
'ML_buoy_restrat', diag%axesT1, time, &
876 'Mixed Layer Buoyancy as used in the mixed-layer restratification parameterization',
'm/s^2')
877 cs%id_uDml = register_diag_field(
'ocean_model',
'udml_restrat', diag%axesCu1, time, &
878 'Transport stream function amplitude for zonal restratification of mixed layer',
'm3/s')
879 cs%id_vDml = register_diag_field(
'ocean_model',
'vdml_restrat', diag%axesCv1, time, &
880 'Transport stream function amplitude for meridional restratification of mixed layer',
'm3/s')
881 cs%id_uml = register_diag_field(
'ocean_model',
'uml_restrat', diag%axesCu1, time, &
882 'Surface zonal velocity component of mixed layer restratification',
'm/s')
883 cs%id_vml = register_diag_field(
'ocean_model',
'vml_restrat', diag%axesCv1, time, &
884 'Surface meridional velocity component of mixed layer restratification',
'm/s')
887 if (
associated(cs%MLD_filtered))
call pass_var(cs%MLD_filtered, g%domain)
900 logical :: mixedlayer_restrat_init
903 call get_param(param_file,
mdl,
"MIXEDLAYER_RESTRAT", mixedlayer_restrat_init, &
904 default=.false., do_not_log=.true.)
905 if (.not. mixedlayer_restrat_init)
return 908 if (
associated(cs))
call mom_error(fatal, &
909 "mixedlayer_restrat_register_restarts called with an associated control structure.")
912 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
913 default=0., do_not_log=.true.)
914 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
915 default=0., do_not_log=.true.)
916 if (cs%MLE_MLD_decay_time>0. .or. cs%MLE_MLD_decay_time2>0.)
then 918 allocate(cs%MLD_filtered(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered(:,:) = 0.
919 vd =
var_desc(
"MLD_MLE_filtered",
"m",
"Time-filtered MLD for use in MLE", &
920 hor_grid=
'h', z_grid=
'1')
923 if (cs%MLE_MLD_decay_time2>0.)
then 925 allocate(cs%MLD_filtered_slow(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered_slow(:,:) = 0.
926 vd =
var_desc(
"MLD_MLE_filtered_slow",
"m",
"c Slower time-filtered MLD for use in MLE", &
927 hor_grid=
'h', z_grid=
'1')
Control structure for mom_mixed_layer_restrat.
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
This module implements boundary forcing for MOM6.
subroutine, public mixedlayer_restrat(h, uhtr, vhtr, tv, fluxes, dt, MLD, VarMix, G, GV, CS)
Driver for the mixed-layer restratification parameterization. The code branches between two different...
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
Provides the ocean grid type.
logical function, public mixedlayer_restrat_init(Time, G, GV, param_file, diag, CS)
Initialize the mixed layer restratification module.
subroutine mixedlayer_restrat_bml(h, uhtr, vhtr, tv, fluxes, dt, G, GV, CS)
Calculates a restratifying flow assuming a 2-layer bulk mixed layer.
This module contains I/O framework code.
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Variable mixing coefficients.
Container for horizontal index ranges for data, computational and global domains. ...
Variable mixing coefficients.
character(len=40) mdl
This module's name.
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Provides subroutines for quantities specific to the equation of state.
Type for describing a variable, typically a tracer.
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine, public mixedlayer_restrat_register_restarts(HI, param_file, CS, restart_CS)
Allocate and register fields in the mixed layer restratification structure for restarts.
subroutine mixedlayer_restrat_general(h, uhtr, vhtr, tv, fluxes, dt, MLD_in, VarMix, G, GV, CS)
Calculates a restratifying flow in the mixed layer.
subroutine, public mom_error(level, message, all_print)
Parameterization of mixed layer restratification by unresolved mixed-layer eddies.