24 implicit none ;
private
26 #include <MOM_memory.h>
39 real :: ml_restrat_coef
43 real :: ml_restrat_coef2
48 logical :: mle_use_pbl_mld
51 real :: mle_mld_decay_time
52 real :: mle_mld_decay_time2
53 real :: mle_density_diff
57 real :: mle_mld_stretch
59 logical :: mle_use_mld_ave_bug
60 logical :: debug = .false.
64 real,
dimension(:,:),
pointer :: &
65 mld_filtered => null(), &
66 mld_filtered_slow => null()
70 integer :: id_urestrat_time = -1
71 integer :: id_vrestrat_time = -1
72 integer :: id_uhml = -1
73 integer :: id_vhml = -1
74 integer :: id_mld = -1
75 integer :: id_rml = -1
76 integer :: id_udml = -1
77 integer :: id_vdml = -1
78 integer :: id_uml = -1
79 integer :: id_vml = -1
84 character(len=40) ::
mdl =
"MOM_mixed_layer_restrat"
91 subroutine mixedlayer_restrat(h, uhtr, vhtr, tv, forces, dt, MLD, VarMix, G, GV, US, CS)
95 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
96 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
98 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
102 real,
intent(in) :: dt
103 real,
dimension(:,:),
pointer :: mld
108 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
109 "Module must be initialized before it is used.")
114 call mixedlayer_restrat_general(h, uhtr, vhtr, tv, forces, dt, mld, varmix, g, gv, us, cs)
120 subroutine mixedlayer_restrat_general(h, uhtr, vhtr, tv, forces, dt, MLD_in, VarMix, G, GV, US, CS)
125 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
126 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
128 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
132 real,
intent(in) :: dt
133 real,
dimension(:,:),
pointer :: MLD_in
138 real :: uhml(SZIB_(G),SZJ_(G),SZK_(G))
139 real :: vhml(SZI_(G),SZJB_(G),SZK_(G))
140 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
143 real,
dimension(SZI_(G),SZJ_(G)) :: &
151 real :: rho_ml(SZI_(G))
162 real :: Ihtot,Ihtot_slow
168 real :: uDml(SZIB_(G))
169 real :: vDml(SZI_(G))
170 real :: uDml_slow(SZIB_(G))
171 real :: vDml_slow(SZI_(G))
172 real :: utimescale_diag(SZIB_(G),SZJ_(G))
173 real :: vtimescale_diag(SZI_(G),SZJB_(G))
175 real :: uDml_diag(SZIB_(G),SZJ_(G)), vDml_diag(SZI_(G),SZJB_(G))
176 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
177 real,
dimension(SZI_(G)) :: rhoSurf, deltaRhoAtKm1, deltaRhoAtK
178 real,
dimension(SZI_(G)) :: dK, dKm1
179 real,
dimension(SZI_(G)) :: pRef_MLD
180 real,
dimension(SZI_(G)) :: rhoAtK, rho1, d1, pRef_N2
183 real :: hAtVel, zpa, zpb, dh, res_scaling_fac
185 logical :: proper_averaging, line_is_empty, keep_going, res_upscale
187 real :: PSI, PSI1, z, BOTTOP, XP, DD
190 psi1(z) = max(0., (1. - (2.*z+1.)**2 ) * (1. + (5./21.)*(2.*z+1.)**2) )
191 bottop(z) = 0.5*(1.-sign(1.,z+0.5))
192 xp(z) = max(0., min(1., (-z-0.5)*2./(1.+2.*cs%MLE_tail_dh) ) )
193 dd(z) = (1.-3.*(xp(z)**2)+2.*(xp(z)**3))**(1.+2.*cs%MLE_tail_dh)
194 psi(z) = max( psi1(z), dd(z)*bottop(z) )
196 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
197 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
199 if (.not.
associated(tv%eqn_of_state))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
200 "An equation of state must be used with this module.")
201 if (.not.
associated(varmix) .and. cs%front_length>0.)
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
202 "The resolution argument, Rd/dx, was not associated.")
204 if (cs%MLE_density_diff > 0.)
then
208 dk(:) = 0.5 * h(:,j,1)
209 call calculate_density(tv%T(:,j,1), tv%S(:,j,1), pref_mld, rhosurf, is-1, ie-is+3, &
210 tv%eqn_of_state, scale=us%kg_m3_to_R)
215 dk(:) = dk(:) + 0.5 * ( h(:,j,k) + h(:,j,k-1) )
217 deltarhoatkm1(:) = deltarhoatk(:)
218 call calculate_density(tv%T(:,j,k), tv%S(:,j,k), pref_mld, deltarhoatk, is-1, ie-is+3, &
219 tv%eqn_of_state, scale=us%kg_m3_to_R)
221 deltarhoatk(i) = deltarhoatk(i) - rhosurf(i)
224 ddrho = deltarhoatk(i) - deltarhoatkm1(i)
225 if ((mld_fast(i,j)==0.) .and. (ddrho>0.) .and. &
226 (deltarhoatkm1(i)<cs%MLE_density_diff) .and. (deltarhoatk(i)>=cs%MLE_density_diff))
then
227 afac = ( cs%MLE_density_diff - deltarhoatkm1(i) ) / ddrho
228 mld_fast(i,j) = dk(i) * afac + dkm1(i) * (1. - afac)
233 mld_fast(i,j) = cs%MLE_MLD_stretch * mld_fast(i,j)
234 if ((mld_fast(i,j)==0.) .and. (deltarhoatk(i)<cs%MLE_density_diff)) &
235 mld_fast(i,j) = dk(i)
238 elseif (cs%MLE_use_PBL_MLD)
then
239 if (.not.
associated(mld_in))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
240 "Argument MLD_in was not associated!")
241 do j = js-1, je+1 ;
do i = is-1, ie+1
242 mld_fast(i,j) = (cs%MLE_MLD_stretch * gv%m_to_H) * mld_in(i,j)
245 call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
246 "No MLD to use for MLE parameterization.")
250 if (cs%MLE_MLD_decay_time>0.)
then
252 call hchksum(cs%MLD_filtered,
'mixed_layer_restrat: MLD_filtered',g%HI,haloshift=1,scale=gv%H_to_m)
253 call hchksum(mld_in,
'mixed_layer_restrat: MLD in',g%HI,haloshift=1)
255 afac = cs%MLE_MLD_decay_time / ( dt + cs%MLE_MLD_decay_time )
256 bfac = dt / ( dt + cs%MLE_MLD_decay_time )
257 do j = js-1, je+1 ;
do i = is-1, ie+1
261 cs%MLD_filtered(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered(i,j) )
262 mld_fast(i,j) = cs%MLD_filtered(i,j)
267 if (cs%MLE_MLD_decay_time2>0.)
then
269 call hchksum(cs%MLD_filtered_slow,
'mixed_layer_restrat: MLD_filtered_slow',g%HI,haloshift=1,scale=gv%H_to_m)
270 call hchksum(mld_fast,
'mixed_layer_restrat: MLD fast',g%HI,haloshift=1,scale=gv%H_to_m)
272 afac = cs%MLE_MLD_decay_time2 / ( dt + cs%MLE_MLD_decay_time2 )
273 bfac = dt / ( dt + cs%MLE_MLD_decay_time2 )
274 do j = js-1, je+1 ;
do i = is-1, ie+1
278 cs%MLD_filtered_slow(i,j) = max( mld_fast(i,j), bfac*mld_fast(i,j) + afac*cs%MLD_filtered_slow(i,j) )
279 mld_slow(i,j) = cs%MLD_filtered_slow(i,j)
282 do j = js-1, je+1 ;
do i = is-1, ie+1
283 mld_slow(i,j) = mld_fast(i,j)
287 udml(:) = 0.0 ; vdml(:) = 0.0
288 udml_slow(:) = 0.0 ; vdml_slow(:) = 0.0
290 g_rho0 = gv%g_Earth / gv%Rho0
291 h_neglect = gv%H_subroundoff
292 dz_neglect = gv%H_subroundoff*gv%H_to_Z
293 proper_averaging = .not. cs%MLE_use_MLD_ave_bug
294 if (cs%front_length>0.)
then
296 i_lfront = 1. / cs%front_length
298 res_upscale = .false.
315 htot_fast(i,j) = 0.0 ; rml_av_fast(i,j) = 0.0
316 htot_slow(i,j) = 0.0 ; rml_av_slow(i,j) = 0.0
321 h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom_H),0.0)
324 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho_ml(:),is-1,ie-is+3,tv%eqn_of_state, scale=us%kg_m3_to_R)
325 line_is_empty = .true.
327 if (htot_fast(i,j) < mld_fast(i,j))
then
329 if (proper_averaging) dh = min( h(i,j,k), mld_fast(i,j)-htot_fast(i,j) )
330 rml_av_fast(i,j) = rml_av_fast(i,j) + dh*rho_ml(i)
331 htot_fast(i,j) = htot_fast(i,j) + dh
332 line_is_empty = .false.
334 if (htot_slow(i,j) < mld_slow(i,j))
then
335 dh = min( h(i,j,k), mld_slow(i,j)-htot_slow(i,j) )
336 rml_av_slow(i,j) = rml_av_slow(i,j) + dh*rho_ml(i)
337 htot_slow(i,j) = htot_slow(i,j) + dh
338 line_is_empty = .false.
341 if (line_is_empty) keep_going=.false.
346 rml_av_fast(i,j) = -(g_rho0*rml_av_fast(i,j)) / (htot_fast(i,j) + h_neglect)
347 rml_av_slow(i,j) = -(g_rho0*rml_av_slow(i,j)) / (htot_slow(i,j) + h_neglect)
352 call hchksum(h,
'mixed_layer_restrat: h', g%HI, haloshift=1, scale=gv%H_to_m)
353 call hchksum(forces%ustar,
'mixed_layer_restrat: u*', g%HI, haloshift=1, scale=us%Z_to_m*us%s_to_T)
354 call hchksum(mld_fast,
'mixed_layer_restrat: MLD', g%HI, haloshift=1, scale=gv%H_to_m)
355 call hchksum(rml_av_fast,
'mixed_layer_restrat: rml', g%HI, haloshift=1, &
356 scale=us%m_to_Z*us%L_to_m**2*us%s_to_T**2)
365 do j=js,je ;
do i=is-1,ie
366 u_star = 0.5*(forces%ustar(i,j) + forces%ustar(i+1,j))
367 absf = 0.5*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
369 if (res_upscale) res_scaling_fac = &
370 ( sqrt( 0.5 * ( g%dxCu(i,j)**2 + g%dyCu(i,j)**2 ) ) * i_lfront ) &
371 * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i+1,j) ) )
376 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect) * gv%H_to_Z
377 mom_mixrate = (0.41*9.8696)*u_star**2 / &
378 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
379 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
380 timescale = timescale * cs%ml_restrat_coef
381 if (res_upscale) timescale = timescale * res_scaling_fac
382 udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)*g%IdxCu(i,j) * &
383 (rml_av_fast(i+1,j)-rml_av_fast(i,j)) * (h_vel**2 * gv%Z_to_H)
385 h_vel = 0.5*((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect) * gv%H_to_Z
386 mom_mixrate = (0.41*9.8696)*u_star**2 / &
387 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
388 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
389 timescale = timescale * cs%ml_restrat_coef2
390 if (res_upscale) timescale = timescale * res_scaling_fac
391 udml_slow(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)*g%IdxCu(i,j) * &
392 (rml_av_slow(i+1,j)-rml_av_slow(i,j)) * (h_vel**2 * gv%Z_to_H)
394 if (udml(i) + udml_slow(i) == 0.)
then
395 do k=1,nz ; uhml(i,j,k) = 0.0 ;
enddo
397 ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
398 ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i+1,j)) + h_neglect)
399 zpa = 0.0 ; zpb = 0.0
403 hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
405 zpa = zpa - (hatvel * ihtot)
406 a(k) = a(k) - psi(zpa)
408 if (a(k)*udml(i) > 0.0)
then
409 if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
410 elseif (a(k)*udml(i) < 0.0)
then
411 if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k) / a(k)
416 hatvel = 0.5*(h(i,j,k) + h(i+1,j,k))
418 zpb = zpb - (hatvel * ihtot_slow)
419 b(k) = b(k) - psi(zpb)
421 if (b(k)*udml_slow(i) > 0.0)
then
422 if (b(k)*udml_slow(i) > h_avail(i,j,k) - a(k)*udml(i)) &
423 udml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*udml(i) ) / b(k)
424 elseif (b(k)*udml_slow(i) < 0.0)
then
425 if (-b(k)*udml_slow(i) > h_avail(i+1,j,k) + a(k)*udml(i)) &
426 udml_slow(i) = -max( 0., h_avail(i+1,j,k) + a(k)*udml(i) ) / b(k)
430 uhml(i,j,k) = a(k)*udml(i) + b(k)*udml_slow(i)
431 uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
435 utimescale_diag(i,j) = timescale
436 udml_diag(i,j) = udml(i)
441 do j=js-1,je ;
do i=is,ie
442 u_star = 0.5*(forces%ustar(i,j) + forces%ustar(i,j+1))
443 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
445 if (res_upscale) res_scaling_fac = &
446 ( sqrt( 0.5 * ( (g%dxCv(i,j))**2 + (g%dyCv(i,j))**2 ) ) * i_lfront ) &
447 * min( 1., 0.5*( varmix%Rd_dx_h(i,j) + varmix%Rd_dx_h(i,j+1) ) )
452 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect) * gv%H_to_Z
453 mom_mixrate = (0.41*9.8696)*u_star**2 / &
454 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
455 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
456 timescale = timescale * cs%ml_restrat_coef
457 if (res_upscale) timescale = timescale * res_scaling_fac
458 vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)*g%IdyCv(i,j) * &
459 (rml_av_fast(i,j+1)-rml_av_fast(i,j)) * (h_vel**2 * gv%Z_to_H)
461 h_vel = 0.5*((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect) * gv%H_to_Z
462 mom_mixrate = (0.41*9.8696)*u_star**2 / &
463 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
464 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
465 timescale = timescale * cs%ml_restrat_coef2
466 if (res_upscale) timescale = timescale * res_scaling_fac
467 vdml_slow(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)*g%IdyCv(i,j) * &
468 (rml_av_slow(i,j+1)-rml_av_slow(i,j)) * (h_vel**2 * gv%Z_to_H)
470 if (vdml(i) + vdml_slow(i) == 0.)
then
471 do k=1,nz ; vhml(i,j,k) = 0.0 ;
enddo
473 ihtot = 2.0 / ((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
474 ihtot_slow = 2.0 / ((htot_slow(i,j) + htot_slow(i,j+1)) + h_neglect)
475 zpa = 0.0 ; zpb = 0.0
479 hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
481 zpa = zpa - (hatvel * ihtot)
482 a(k) = a(k) - psi( zpa )
484 if (a(k)*vdml(i) > 0.0)
then
485 if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
486 elseif (a(k)*vdml(i) < 0.0)
then
487 if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k) / a(k)
492 hatvel = 0.5*(h(i,j,k) + h(i,j+1,k))
494 zpb = zpb - (hatvel * ihtot_slow)
495 b(k) = b(k) - psi(zpb)
497 if (b(k)*vdml_slow(i) > 0.0)
then
498 if (b(k)*vdml_slow(i) > h_avail(i,j,k) - a(k)*vdml(i)) &
499 vdml_slow(i) = max( 0., h_avail(i,j,k) - a(k)*vdml(i) ) / b(k)
500 elseif (b(k)*vdml_slow(i) < 0.0)
then
501 if (-b(k)*vdml_slow(i) > h_avail(i,j+1,k) + a(k)*vdml(i)) &
502 vdml_slow(i) = -max( 0., h_avail(i,j+1,k) + a(k)*vdml(i) ) / b(k)
506 vhml(i,j,k) = a(k)*vdml(i) + b(k)*vdml_slow(i)
507 vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
511 vtimescale_diag(i,j) = timescale
512 vdml_diag(i,j) = vdml(i)
516 do j=js,je ;
do k=1,nz ;
do i=is,ie
517 h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
518 ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
519 enddo ;
enddo ;
enddo
524 if (cs%id_uhml > 0 .or. cs%id_vhml > 0) &
526 call pass_var(h, g%domain, to_west+to_south+omit_corners, halo=1)
530 if (query_averaging_enabled(cs%diag))
then
531 if (cs%id_urestrat_time > 0)
call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
532 if (cs%id_vrestrat_time > 0)
call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
533 if (cs%id_uhml > 0)
call post_data(cs%id_uhml, uhml, cs%diag)
534 if (cs%id_vhml > 0)
call post_data(cs%id_vhml, vhml, cs%diag)
535 if (cs%id_MLD > 0)
call post_data(cs%id_MLD, mld_fast, cs%diag)
536 if (cs%id_Rml > 0)
call post_data(cs%id_Rml, rml_av_fast, cs%diag)
537 if (cs%id_uDml > 0)
call post_data(cs%id_uDml, udml_diag, cs%diag)
538 if (cs%id_vDml > 0)
call post_data(cs%id_vDml, vdml_diag, cs%diag)
540 if (cs%id_uml > 0)
then
541 do j=js,je ;
do i=is-1,ie
542 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i+1,j)) + h_neglect)
543 udml_diag(i,j) = udml_diag(i,j) / (0.01*h_vel) * g%IdyCu(i,j) * (psi(0.)-psi(-.01))
545 call post_data(cs%id_uml, udml_diag, cs%diag)
547 if (cs%id_vml > 0)
then
548 do j=js-1,je ;
do i=is,ie
549 h_vel = 0.5*((htot_fast(i,j) + htot_fast(i,j+1)) + h_neglect)
550 vdml_diag(i,j) = vdml_diag(i,j) / (0.01*h_vel) * g%IdxCv(i,j) * (psi(0.)-psi(-.01))
552 call post_data(cs%id_vml, vdml_diag, cs%diag)
568 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h
569 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: uhtr
571 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: vhtr
575 real,
intent(in) :: dt
578 real :: uhml(SZIB_(G),SZJ_(G),SZK_(G))
579 real :: vhml(SZI_(G),SZJB_(G),SZK_(G))
580 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
583 real,
dimension(SZI_(G),SZJ_(G)) :: &
587 real :: Rho0(SZI_(G))
605 real :: uDml(SZIB_(G))
606 real :: vDml(SZI_(G))
607 real :: utimescale_diag(SZIB_(G),SZJ_(G))
608 real :: vtimescale_diag(SZI_(G),SZJB_(G))
611 real :: uDml_diag(SZIB_(G),SZJ_(G)), vDml_diag(SZI_(G),SZJB_(G))
614 integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, nkml
615 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
616 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nkml = gv%nkml
618 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
619 "Module must be initialized before it is used.")
620 if ((nkml<2) .or. (cs%ml_restrat_coef<=0.0))
return
622 udml(:) = 0.0 ; vdml(:) = 0.0
624 g_rho0 = gv%g_Earth / gv%Rho0
625 use_eos =
associated(tv%eqn_of_state)
626 h_neglect = gv%H_subroundoff
627 dz_neglect = gv%H_subroundoff*gv%H_to_Z
629 if (.not.use_eos)
call mom_error(fatal,
"MOM_mixedlayer_restrat: "// &
630 "An equation of state must be used with this module.")
645 htot(i,j) = 0.0 ; rml_av(i,j) = 0.0
648 call calculate_density(tv%T(:,j,k),tv%S(:,j,k),p0,rho0(:),is-1,ie-is+3,tv%eqn_of_state, scale=us%kg_m3_to_R)
650 rml_av(i,j) = rml_av(i,j) + h(i,j,k)*rho0(i)
651 htot(i,j) = htot(i,j) + h(i,j,k)
652 h_avail(i,j,k) = max(i4dt*g%areaT(i,j)*(h(i,j,k)-gv%Angstrom_H),0.0)
657 rml_av(i,j) = (g_rho0*rml_av(i,j)) / (htot(i,j) + h_neglect)
667 do j=js,je;
do i=is-1,ie
668 h_vel = 0.5*(htot(i,j) + htot(i+1,j)) * gv%H_to_Z
670 u_star = 0.5*(forces%ustar(i,j) + forces%ustar(i+1,j))
671 absf = 0.5*(abs(g%CoriolisBu(i,j-1)) + abs(g%CoriolisBu(i,j)))
675 mom_mixrate = (0.41*9.8696)*u_star**2 / &
676 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
677 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
679 timescale = timescale * cs%ml_restrat_coef
682 udml(i) = timescale * g%mask2dCu(i,j)*g%dyCu(i,j)*g%IdxCu(i,j) * &
683 (rml_av(i+1,j)-rml_av(i,j)) * (h_vel**2 * gv%Z_to_H)
685 if (udml(i) == 0)
then
686 do k=1,nkml ; uhml(i,j,k) = 0.0 ;
enddo
688 i2htot = 1.0 / (htot(i,j) + htot(i+1,j) + h_neglect)
693 hx2 = (h(i,j,k) + h(i+1,j,k) + h_neglect)
694 a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
695 z_topx2 = z_topx2 + hx2
696 if (a(k)*udml(i) > 0.0)
then
697 if (a(k)*udml(i) > h_avail(i,j,k)) udml(i) = h_avail(i,j,k) / a(k)
699 if (-a(k)*udml(i) > h_avail(i+1,j,k)) udml(i) = -h_avail(i+1,j,k)/a(k)
703 uhml(i,j,k) = a(k)*udml(i)
704 uhtr(i,j,k) = uhtr(i,j,k) + uhml(i,j,k)*dt
708 udml_diag(i,j) = udml(i)
709 utimescale_diag(i,j) = timescale
714 do j=js-1,je ;
do i=is,ie
715 h_vel = 0.5*(htot(i,j) + htot(i,j+1)) * gv%H_to_Z
717 u_star = 0.5*(forces%ustar(i,j) + forces%ustar(i,j+1))
718 absf = 0.5*(abs(g%CoriolisBu(i-1,j)) + abs(g%CoriolisBu(i,j)))
722 mom_mixrate = (0.41*9.8696)*u_star**2 / &
723 (absf*h_vel**2 + 4.0*(h_vel+dz_neglect)*u_star)
724 timescale = 0.0625 * (absf + 2.0*mom_mixrate) / (absf**2 + mom_mixrate**2)
726 timescale = timescale * cs%ml_restrat_coef
729 vdml(i) = timescale * g%mask2dCv(i,j)*g%dxCv(i,j)*g%IdyCv(i,j) * &
730 (rml_av(i,j+1)-rml_av(i,j)) * (h_vel**2 * gv%Z_to_H)
731 if (vdml(i) == 0)
then
732 do k=1,nkml ; vhml(i,j,k) = 0.0 ;
enddo
734 i2htot = 1.0 / (htot(i,j) + htot(i,j+1) + h_neglect)
739 hx2 = (h(i,j,k) + h(i,j+1,k) + h_neglect)
740 a(k) = (hx2 * i2htot) * (2.0 - 4.0*(z_topx2+0.5*hx2)*i2htot)
741 z_topx2 = z_topx2 + hx2
742 if (a(k)*vdml(i) > 0.0)
then
743 if (a(k)*vdml(i) > h_avail(i,j,k)) vdml(i) = h_avail(i,j,k) / a(k)
745 if (-a(k)*vdml(i) > h_avail(i,j+1,k)) vdml(i) = -h_avail(i,j+1,k)/a(k)
749 vhml(i,j,k) = a(k)*vdml(i)
750 vhtr(i,j,k) = vhtr(i,j,k) + vhml(i,j,k)*dt
754 vtimescale_diag(i,j) = timescale
755 vdml_diag(i,j) = vdml(i)
759 do j=js,je ;
do k=1,nkml ;
do i=is,ie
760 h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * &
761 ((uhml(i,j,k) - uhml(i-1,j,k)) + (vhml(i,j,k) - vhml(i,j-1,k)))
762 enddo ;
enddo ;
enddo
767 if (cs%id_uhml > 0 .or. cs%id_vhml > 0) &
769 call pass_var(h, g%domain, to_west+to_south+omit_corners, halo=1)
773 if (query_averaging_enabled(cs%diag) .and. &
774 ((cs%id_urestrat_time > 0) .or. (cs%id_vrestrat_time > 0)))
then
775 call post_data(cs%id_urestrat_time, utimescale_diag, cs%diag)
776 call post_data(cs%id_vrestrat_time, vtimescale_diag, cs%diag)
778 if (query_averaging_enabled(cs%diag) .and. &
779 ((cs%id_uhml>0) .or. (cs%id_vhml>0)))
then
781 do j=js,je ;
do i=isq,ieq ; uhml(i,j,k) = 0.0 ;
enddo ;
enddo
782 do j=jsq,jeq ;
do i=is,ie ; vhml(i,j,k) = 0.0 ;
enddo ;
enddo
784 if (cs%id_uhml > 0)
call post_data(cs%id_uhml, uhml, cs%diag)
785 if (cs%id_vhml > 0)
call post_data(cs%id_vhml, vhml, cs%diag)
786 if (cs%id_MLD > 0)
call post_data(cs%id_MLD, htot, cs%diag)
787 if (cs%id_Rml > 0)
call post_data(cs%id_Rml, rml_av, cs%diag)
788 if (cs%id_uDml > 0)
call post_data(cs%id_uDml, udml_diag, cs%diag)
789 if (cs%id_vDml > 0)
call post_data(cs%id_vDml, vdml_diag, cs%diag)
797 type(time_type),
intent(in) :: time
802 type(
diag_ctrl),
target,
intent(inout) :: diag
809 real :: flux_to_kg_per_s
811 # include "version_variable.h"
817 "If true, a density-gradient dependent re-stratifying "//&
818 "flow is imposed in the mixed layer. Can be used in ALE mode "//&
819 "without restriction but in layer mode can only be used if "//&
820 "BULKMIXEDLAYER is true.", default=.false.)
823 if (.not.
associated(cs))
then
824 call mom_error(fatal,
"mixedlayer_restrat_init called without an associated control structure.")
828 cs%MLE_MLD_decay_time = -9.e9*us%s_to_T
829 cs%MLE_density_diff = -9.e9*us%kg_m3_to_R
830 cs%MLE_tail_dh = -9.e9
831 cs%MLE_use_PBL_MLD = .false.
832 cs%MLE_MLD_stretch = -9.e9
834 call get_param(param_file,
mdl,
"DEBUG", cs%debug, default=.false., do_not_log=.true.)
835 call get_param(param_file,
mdl,
"FOX_KEMPER_ML_RESTRAT_COEF", cs%ml_restrat_coef, &
836 "A nondimensional coefficient that is proportional to "//&
837 "the ratio of the deformation radius to the dominant "//&
838 "lengthscale of the submesoscale mixed layer "//&
839 "instabilities, times the minimum of the ratio of the "//&
840 "mesoscale eddy kinetic energy to the large-scale "//&
841 "geostrophic kinetic energy or 1 plus the square of the "//&
842 "grid spacing over the deformation radius, as detailed "//&
843 "by Fox-Kemper et al. (2010)", units=
"nondim", default=0.0)
847 call get_param(param_file,
mdl,
"FOX_KEMPER_ML_RESTRAT_COEF2", cs%ml_restrat_coef2, &
848 "As for FOX_KEMPER_ML_RESTRAT_COEF but used in a second application "//&
849 "of the MLE restratification parameterization.", units=
"nondim", default=0.0)
850 call get_param(param_file,
mdl,
"MLE_FRONT_LENGTH", cs%front_length, &
851 "If non-zero, is the frontal-length scale used to calculate the "//&
852 "upscaling of buoyancy gradients that is otherwise represented "//&
853 "by the parameter FOX_KEMPER_ML_RESTRAT_COEF. If MLE_FRONT_LENGTH is "//&
854 "non-zero, it is recommended to set FOX_KEMPER_ML_RESTRAT_COEF=1.0.",&
855 units=
"m", default=0.0, scale=us%m_to_L)
856 call get_param(param_file,
mdl,
"MLE_USE_PBL_MLD", cs%MLE_use_PBL_MLD, &
857 "If true, the MLE parameterization will use the mixed-layer "//&
858 "depth provided by the active PBL parameterization. If false, "//&
859 "MLE will estimate a MLD based on a density difference with the "//&
860 "surface using the parameter MLE_DENSITY_DIFF.", default=.false.)
861 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
862 "The time-scale for a running-mean filter applied to the mixed-layer "//&
863 "depth used in the MLE restratification parameterization. When "//&
864 "the MLD deepens below the current running-mean the running-mean "//&
865 "is instantaneously set to the current MLD.", units=
"s", default=0., scale=us%s_to_T)
866 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
867 "The time-scale for a running-mean filter applied to the filtered "//&
868 "mixed-layer depth used in a second MLE restratification parameterization. "//&
869 "When the MLD deepens below the current running-mean the running-mean "//&
870 "is instantaneously set to the current MLD.", units=
"s", default=0., scale=us%s_to_T)
871 if (.not. cs%MLE_use_PBL_MLD)
then
872 call get_param(param_file,
mdl,
"MLE_DENSITY_DIFF", cs%MLE_density_diff, &
873 "Density difference used to detect the mixed-layer "//&
874 "depth used for the mixed-layer eddy parameterization "//&
875 "by Fox-Kemper et al. (2010)", units=
"kg/m3", default=0.03, scale=us%kg_m3_to_R)
877 call get_param(param_file,
mdl,
"MLE_TAIL_DH", cs%MLE_tail_dh, &
878 "Fraction by which to extend the mixed-layer restratification "//&
879 "depth used for a smoother stream function at the base of "//&
880 "the mixed-layer.", units=
"nondim", default=0.0)
881 call get_param(param_file,
mdl,
"MLE_MLD_STRETCH", cs%MLE_MLD_stretch, &
882 "A scaling coefficient for stretching/shrinking the MLD "//&
883 "used in the MLE scheme. This simply multiplies MLD wherever used.",&
884 units=
"nondim", default=1.0)
885 call get_param(param_file,
mdl,
"MLE_USE_MLD_AVE_BUG", cs%MLE_use_MLD_ave_bug, &
886 "If true, do not account for MLD mismatch to interface positions.",&
892 flux_to_kg_per_s = gv%H_to_kg_m2 * us%L_to_m**2 * us%s_to_T
894 cs%id_uhml = register_diag_field(
'ocean_model',
'uhml', diag%axesCuL, time, &
895 'Zonal Thickness Flux to Restratify Mixed Layer',
'kg s-1', &
896 conversion=flux_to_kg_per_s, y_cell_method=
'sum', v_extensive=.true.)
897 cs%id_vhml = register_diag_field(
'ocean_model',
'vhml', diag%axesCvL, time, &
898 'Meridional Thickness Flux to Restratify Mixed Layer',
'kg s-1', &
899 conversion=flux_to_kg_per_s, x_cell_method=
'sum', v_extensive=.true.)
900 cs%id_urestrat_time = register_diag_field(
'ocean_model',
'MLu_restrat_time', diag%axesCu1, time, &
901 'Mixed Layer Zonal Restratification Timescale',
's', conversion=us%T_to_s)
902 cs%id_vrestrat_time = register_diag_field(
'ocean_model',
'MLv_restrat_time', diag%axesCv1, time, &
903 'Mixed Layer Meridional Restratification Timescale',
's', conversion=us%T_to_s)
904 cs%id_MLD = register_diag_field(
'ocean_model',
'MLD_restrat', diag%axesT1, time, &
905 'Mixed Layer Depth as used in the mixed-layer restratification parameterization',
'm', &
906 conversion=gv%H_to_m)
907 cs%id_Rml = register_diag_field(
'ocean_model',
'ML_buoy_restrat', diag%axesT1, time, &
908 'Mixed Layer Buoyancy as used in the mixed-layer restratification parameterization', &
909 'm s2', conversion=us%m_to_Z*(us%L_to_m**2)*(us%s_to_T**2))
910 cs%id_uDml = register_diag_field(
'ocean_model',
'udml_restrat', diag%axesCu1, time, &
911 'Transport stream function amplitude for zonal restratification of mixed layer', &
912 'm3 s-1', conversion=gv%H_to_m*(us%L_to_m**2)*us%s_to_T)
913 cs%id_vDml = register_diag_field(
'ocean_model',
'vdml_restrat', diag%axesCv1, time, &
914 'Transport stream function amplitude for meridional restratification of mixed layer', &
915 'm3 s-1', conversion=gv%H_to_m*(us%L_to_m**2)*us%s_to_T)
916 cs%id_uml = register_diag_field(
'ocean_model',
'uml_restrat', diag%axesCu1, time, &
917 'Surface zonal velocity component of mixed layer restratification', &
918 'm s-1', conversion=us%L_T_to_m_s)
919 cs%id_vml = register_diag_field(
'ocean_model',
'vml_restrat', diag%axesCv1, time, &
920 'Surface meridional velocity component of mixed layer restratification', &
921 'm s-1', conversion=us%L_T_to_m_s)
924 if (cs%MLE_MLD_decay_time>0. .or. cs%MLE_MLD_decay_time2>0.)
then
926 (gv%m_to_H_restart /= 0.0) .and. (gv%m_to_H_restart /= gv%m_to_H))
then
927 h_rescale = gv%m_to_H / gv%m_to_H_restart
928 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
929 cs%MLD_filtered(i,j) = h_rescale * cs%MLD_filtered(i,j)
933 if (cs%MLE_MLD_decay_time2>0.)
then
934 if (
query_initialized(cs%MLD_filtered_slow,
"MLD_MLE_filtered_slow", restart_cs) .and. &
935 (gv%m_to_H_restart /= 0.0) .and. (gv%m_to_H_restart /= gv%m_to_H))
then
936 h_rescale = gv%m_to_H / gv%m_to_H_restart
937 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
938 cs%MLD_filtered_slow(i,j) = h_rescale * cs%MLD_filtered_slow(i,j)
944 if (
associated(cs%MLD_filtered))
call pass_var(cs%MLD_filtered, g%domain)
961 default=.false., do_not_log=.true.)
965 if (
associated(cs))
call mom_error(fatal, &
966 "mixedlayer_restrat_register_restarts called with an associated control structure.")
969 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME", cs%MLE_MLD_decay_time, &
970 default=0., do_not_log=.true.)
971 call get_param(param_file,
mdl,
"MLE_MLD_DECAY_TIME2", cs%MLE_MLD_decay_time2, &
972 default=0., do_not_log=.true.)
973 if (cs%MLE_MLD_decay_time>0. .or. cs%MLE_MLD_decay_time2>0.)
then
975 allocate(cs%MLD_filtered(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered(:,:) = 0.
976 vd =
var_desc(
"MLD_MLE_filtered",
"m",
"Time-filtered MLD for use in MLE", &
977 hor_grid=
'h', z_grid=
'1')
980 if (cs%MLE_MLD_decay_time2>0.)
then
982 allocate(cs%MLD_filtered_slow(hi%isd:hi%ied,hi%jsd:hi%jed)) ; cs%MLD_filtered_slow(:,:) = 0.
983 vd =
var_desc(
"MLD_MLE_filtered_slow",
"m",
"c Slower time-filtered MLD for use in MLE", &
984 hor_grid=
'h', z_grid=
'1')