This subroutine ensures that there is a degree of horizontal smoothness in the depths of the near-surface interfaces.
109 type(ocean_grid_type),
intent(inout) :: g
110 type(verticalgrid_type),
intent(in) :: gv
111 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
113 type(thermo_var_ptrs),
intent(inout) :: tv
116 real,
intent(in) :: dt
117 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
121 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
125 type(unit_scale_type),
intent(in) :: us
126 type(regularize_layers_cs),
pointer :: cs
129 real,
dimension(SZIB_(G),SZJ_(G)) :: &
131 real,
dimension(SZI_(G),SZJB_(G)) :: &
133 real,
dimension(SZI_(G),SZJ_(G)) :: &
135 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: &
138 real,
dimension(SZI_(G),SZK_(G)+1) :: &
140 real,
dimension(SZI_(G),SZK_(G)) :: &
154 real,
dimension(SZI_(G)) :: &
159 h_add_tgt, h_add_tot, &
160 h_tot1, th_tot1, sh_tot1, &
161 h_tot3, th_tot3, sh_tot3, &
162 h_tot2, th_tot2, sh_tot2
163 real,
dimension(SZK_(G)) :: &
168 real :: e_e, e_w, e_n, e_s
173 real,
dimension(SZK_(G)+1) :: &
174 int_flux, int_tflux, int_sflux, int_rflux
181 real :: int_top, int_bot
186 logical :: cols_left, ent_any, more_ent_i(szi_(g)), ent_i(szi_(g))
187 logical :: det_any, det_i(szi_(g))
188 logical :: do_j(szj_(g)), do_i(szi_(g)), find_i(szi_(g))
189 logical :: debug = .false.
190 logical :: fatal_error
191 character(len=256) :: mesg
192 integer,
dimension(2) :: eosdom
193 integer :: i, j, k, is, ie, js, je, nz, nkmb, nkml, k1, k2, k3, ks, nz_filt, kmax_d_ea
195 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
197 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_regularize_layers: "//&
198 "Module must be initialized before it is used.")
200 if (gv%nkml<1)
return 201 nkmb = gv%nk_rho_varies ; nkml = gv%nkml
202 if (.not.
associated(tv%eqn_of_state))
call mom_error(fatal, &
203 "MOM_regularize_layers: This module now requires the use of temperature and "//&
204 "an equation of state.")
206 h_neglect = gv%H_subroundoff
207 debug = (debug .or. cs%debug)
209 i_dtol = 1.0 / max(cs%h_def_tol2 - cs%h_def_tol1, 1e-40)
210 i_dtol34 = 1.0 / max(cs%h_def_tol4 - cs%h_def_tol3, 1e-40)
212 p_ref_cv(:) = tv%P_Ref
213 eosdom(:) = eos_domain(g%HI)
215 do j=js-1,je+1 ;
do i=is-1,ie+1
218 do k=1,nz ;
do j=js-1,je+1 ;
do i=is-1,ie+1
219 e(i,j,k+1) = e(i,j,k) - h(i,j,k)
220 enddo ;
enddo ;
enddo 222 call find_deficit_ratios(e, def_rat_u, def_rat_v, g, gv, cs, h=h)
225 do j=js,je ; do_j(j) = .false. ;
enddo 226 do j=js,je ;
do i=is,ie
227 def_rat_h(i,j) = max(def_rat_u(i-1,j), def_rat_u(i,j), &
228 def_rat_v(i,j-1), def_rat_v(i,j))
229 if (def_rat_h(i,j) > cs%h_def_tol1) do_j(j) = .true.
236 do j=js,je ;
if (do_j(j))
then 242 do k=1,nz ;
do i=is,ie ; d_ea(i,k) = 0.0 ; d_eb(i,k) = 0.0 ;
enddo ;
enddo 247 do_i(i) = def_rat_h(i,j) > cs%h_def_tol1
248 if (def_rat_h(i,j) > max_def_rat) max_def_rat = def_rat_h(i,j)
250 nz_filt = nkmb+1 ;
if (max_def_rat > cs%h_def_tol3) nz_filt = nz+1
255 do k=1,nz_filt ;
do i=is,ie ;
if (do_i(i))
then 256 if (g%mask2dCu(i,j) <= 0.0)
then ; e_e = e(i,j,k) ;
else 257 e_e = max(e(i+1,j,k) + min(e(i,j,k) - e(i+1,j,nz+1), 0.0), &
258 e(i,j,nz+1) + (nz+1-k)*gv%Angstrom_H)
261 if (g%mask2dCu(i-1,j) <= 0.0)
then ; e_w = e(i,j,k) ;
else 262 e_w = max(e(i-1,j,k) + min(e(i,j,k) - e(i-1,j,nz+1), 0.0), &
263 e(i,j,nz+1) + (nz+1-k)*gv%Angstrom_H)
265 if (g%mask2dCv(i,j) <= 0.0)
then ; e_n = e(i,j,k) ;
else 266 e_n = max(e(i,j+1,k) + min(e(i,j,k) - e(i,j+1,nz+1), 0.0), &
267 e(i,j,nz+1) + (nz+1-k)*gv%Angstrom_H)
269 if (g%mask2dCv(i,j-1) <= 0.0)
then ; e_s = e(i,j,k) ;
else 270 e_s = max(e(i,j-1,k) + min(e(i,j,k) - e(i,j-1,nz+1), 0.0), &
271 e(i,j,nz+1) + (nz+1-k)*gv%Angstrom_H)
274 wt = max(0.0, min(1.0, i_dtol*(def_rat_h(i,j)-cs%h_def_tol1)))
276 e_filt(i,k) = (1.0 - 0.5*wt) * e(i,j,k) + &
277 wt * 0.125 * ((e_e + e_w) + (e_n + e_s))
279 endif ;
enddo ;
enddo 280 do k=1,nz ;
do i=is,ie
282 t_2d(i,k) = tv%T(i,j,k) ; s_2d(i,k) = tv%S(i,j,k)
286 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then 287 h_2d_init(i,k) = h(i,j,k)
288 t_2d_init(i,k) = tv%T(i,j,k) ; s_2d_init(i,k) = tv%S(i,j,k)
289 endif ;
enddo ;
enddo 295 more_ent_i(i) = .false. ; ent_i(i) = .false.
296 h_add_tgt(i) = 0.0 ; h_add_tot(i) = 0.0
297 if (do_i(i) .and. (e_2d(i,nkmb+1) > e_filt(i,nkmb+1)))
then 298 more_ent_i(i) = .true. ; ent_i(i) = .true. ; ent_any = .true.
299 h_add_tgt(i) = e_2d(i,nkmb+1) - e_filt(i,nkmb+1)
306 do i=is,ie ;
if (more_ent_i(i))
then 307 if (h_2d(i,k) - gv%Angstrom_H > h_neglect)
then 308 if (e_2d(i,nkmb+1)-e_filt(i,nkmb+1) > h_2d(i,k) - gv%Angstrom_H)
then 309 h_add = h_2d(i,k) - gv%Angstrom_H
310 h_2d(i,k) = gv%Angstrom_H
311 e_2d(i,nkmb+1) = e_2d(i,nkmb+1) - h_add
313 h_add = e_2d(i,nkmb+1) - e_filt(i,nkmb+1)
314 h_2d(i,k) = h_2d(i,k) - h_add
315 if (cs%answers_2018)
then 316 e_2d(i,nkmb+1) = e_2d(i,nkmb+1) - h_add
318 e_2d(i,nkmb+1) = e_filt(i,nkmb+1)
321 d_eb(i,k-1) = d_eb(i,k-1) + h_add
322 h_add_tot(i) = h_add_tot(i) + h_add
323 h_prev = h_2d(i,nkmb)
324 h_2d(i,nkmb) = h_2d(i,nkmb) + h_add
326 t_2d(i,nkmb) = (h_prev*t_2d(i,nkmb) + h_add*t_2d(i,k)) / h_2d(i,nkmb)
327 s_2d(i,nkmb) = (h_prev*s_2d(i,nkmb) + h_add*s_2d(i,k)) / h_2d(i,nkmb)
329 if ((e_2d(i,nkmb+1) <= e_filt(i,nkmb+1)) .or. &
330 (h_add_tot(i) > 0.6*h_add_tgt(i)))
then 331 more_ent_i(i) = .false.
339 if (.not.cols_left)
exit 343 do k=ks,nkmb,-1 ;
do i=is,ie ;
if (ent_i(i))
then 344 d_eb(i,k) = d_eb(i,k) + d_eb(i,k+1)
345 endif ;
enddo ;
enddo 357 if ((max_def_rat > cs%h_def_tol3) .and. (cs%reg_sfc_detrain))
then 359 det_i(i) = .false. ; rcv_tol(i) = 0.0
360 if (do_i(i) .and. (e_2d(i,nkmb+1) < e_filt(i,nkmb+1)) .and. &
361 (def_rat_h(i,j) > cs%h_def_tol3))
then 362 det_i(i) = .true. ; det_any = .true.
364 rcv_tol(i) = cs%density_match_tol * min((def_rat_h(i,j) - cs%h_def_tol3), 1.0)
369 call cpu_clock_begin(id_clock_eos)
371 call calculate_density(t_2d(:,k), s_2d(:,k), p_ref_cv, rcv(:,k), tv%eqn_of_state, eosdom)
373 call cpu_clock_end(id_clock_eos)
375 do i=is,ie ;
if (det_i(i))
then 381 rcv_min_det = (gv%Rlay(k2) + rcv_tol(i)*(gv%Rlay(k2-1)-gv%Rlay(k2)))
383 rcv_max_det = (gv%Rlay(k2) + rcv_tol(i)*(gv%Rlay(k2+1)-gv%Rlay(k2)))
385 rcv_max_det = (gv%Rlay(nz) + rcv_tol(i)*(gv%Rlay(nz)-gv%Rlay(nz-1)))
387 if (rcv(i,k1) > rcv_max_det) &
390 h_deficit = (e_filt(i,k2)-e_filt(i,k2+1)) - h_2d(i,k2)
391 if ((e_filt(i,k2) > e_2d(i,k1+1)) .and. (h_deficit > 0.0) .and. &
392 (rcv(i,k1) < rcv_max_det) .and. (rcv(i,k1) > rcv_min_det))
then 394 h_add = min(e_filt(i,k2) - e_2d(i,k2), h_deficit )
395 if (h_add < h_2d(i,k1))
then 397 if (h_add > 0.0)
then 399 h_2d(i,k2) = h_2d(i,k2) + h_add
400 e_2d(i,k2) = e_2d(i,k2+1) + h_2d(i,k2)
401 d_ea(i,k2) = d_ea(i,k2) + h_add
402 kmax_d_ea = max(kmax_d_ea, k2)
404 t_2d(i,k2) = (h_prev*t_2d(i,k2) + h_add*t_2d(i,k1)) / h_2d(i,k2)
405 s_2d(i,k2) = (h_prev*s_2d(i,k2) + h_add*s_2d(i,k1)) / h_2d(i,k2)
406 h_det_tot = h_det_tot + h_add
408 h_2d(i,k1) = h_2d(i,k1) - h_add
409 do k3=k1,nkmb ; e_2d(i,k3+1) = e_2d(i,k3) - h_2d(i,k3) ;
enddo 410 do k3=k1+1,nkmb ; d_ea(i,k3) = d_ea(i,k3) + h_add ;
enddo 413 call mom_error(fatal,
"h_add is negative. Some logic is wrong.")
419 if (k2>nkmb+1) e_2d(i,k2) = e_2d(i,k2) + h_det_tot
423 h_2d(i,k2) = h_2d(i,k2) + h_add
424 e_2d(i,k2) = e_2d(i,k2+1) + h_2d(i,k2)
425 d_ea(i,k2) = d_ea(i,k2) + h_add
426 kmax_d_ea = max(kmax_d_ea, k2)
427 t_2d(i,k2) = (h_prev*t_2d(i,k2) + h_add*t_2d(i,k1)) / h_2d(i,k2)
428 s_2d(i,k2) = (h_prev*s_2d(i,k2) + h_add*s_2d(i,k1)) / h_2d(i,k2)
429 h_det_tot = h_det_tot + h_add
432 do k3=k1,nkmb ; e_2d(i,k3+1) = e_2d(i,k3) - h_2d(i,k3) ;
enddo 433 do k3=k1+1,nkmb ; d_ea(i,k3) = d_ea(i,k3) + h_add ;
enddo 442 if (k2>nkmb+1) e_2d(i,k2) = e_2d(i,k2) + h_det_tot
447 do k=kmax_d_ea-1,nkmb+1,-1 ;
do i=is,ie ;
if (det_i(i))
then 448 d_ea(i,k) = d_ea(i,k) + d_ea(i,k+1)
449 endif ;
enddo ;
enddo 452 do i=is,ie ; h_tot3(i) = 0.0 ; th_tot3(i) = 0.0 ; sh_tot3(i) = 0.0 ;
enddo 453 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then 454 h_tot3(i) = h_tot3(i) + h_2d(i,k)
455 th_tot3(i) = th_tot3(i) + h_2d(i,k) * t_2d(i,k)
456 sh_tot3(i) = sh_tot3(i) + h_2d(i,k) * s_2d(i,k)
457 endif ;
enddo ;
enddo 460 do i=is,ie ;
if (do_i(i))
then 463 scale = e_2d(i,nkmb+1) / e_filt(i,nkmb+1)
464 do k=2,nkmb+1 ; e_filt(i,k) = e_filt(i,k) * scale ;
enddo 468 if (e_filt(i,2) < e_2d(i,nkml))
then 469 scale = (e_2d(i,nkml) - e_filt(i,nkmb+1)) / &
470 ((e_filt(i,2) - e_filt(i,nkmb+1)) + h_neglect)
472 e_filt(i,k) = e_filt(i,nkmb+1) + scale * (e_filt(i,k) - e_filt(i,nkmb+1))
474 e_filt(i,2) = e_2d(i,nkml)
482 int_flux(k) = 0.0 ; int_rflux(k) = 0.0
483 int_tflux(k) = 0.0 ; int_sflux(k) = 0.0
486 int_bot = max(e_2d(i,k1+1),e_filt(i,k2+1))
487 h_add = int_top - int_bot
491 d_ea(i,k3) = d_ea(i,k3) + h_add
492 int_flux(k3) = int_flux(k3) + h_add
493 int_tflux(k3) = int_tflux(k3) + h_add*t_2d(i,k1)
494 int_sflux(k3) = int_sflux(k3) + h_add*s_2d(i,k1)
496 elseif (k1 > k2)
then 498 d_eb(i,k3) = d_eb(i,k3) + h_add
499 int_flux(k3+1) = int_flux(k3+1) - h_add
500 int_tflux(k3+1) = int_tflux(k3+1) - h_add*t_2d(i,k1)
501 int_sflux(k3+1) = int_sflux(k3+1) - h_add*s_2d(i,k1)
505 if (int_bot <= e_filt(i,k2+1))
then 508 elseif (int_bot <= e_2d(i,k1+1))
then 512 call mom_error(fatal, &
513 "Regularize_surface: Could not increment target or source.")
515 if ((k1 > nkmb) .or. (k2 > nkmb))
exit 519 call mom_error(fatal,
"Regularize_surface: Did not assign fluid to layer nkmb.")
523 do k=1,nkmb ; h_prev_1d(k) = h_2d(i,k) ;
enddo 524 h_2d(i,1) = h_2d(i,1) - int_flux(2)
526 h_2d(i,k) = h_2d(i,k) + (int_flux(k) - int_flux(k+1))
530 h_2d(i,nkmb) = h_2d(i,nkmb) + int_flux(nkmb)
532 t_2d(i,1) = (t_2d(i,1)*h_prev_1d(1) - int_tflux(2)) / h_2d(i,1)
533 s_2d(i,1) = (s_2d(i,1)*h_prev_1d(1) - int_sflux(2)) / h_2d(i,1)
535 t_2d(i,k) = (t_2d(i,k)*h_prev_1d(k) + (int_tflux(k) - int_tflux(k+1))) / h_2d(i,k)
536 s_2d(i,k) = (s_2d(i,k)*h_prev_1d(k) + (int_sflux(k) - int_sflux(k+1))) / h_2d(i,k)
538 t_2d(i,nkmb) = (t_2d(i,nkmb)*h_prev_1d(nkmb) + int_tflux(nkmb) ) / h_2d(i,nkmb)
539 s_2d(i,nkmb) = (s_2d(i,nkmb)*h_prev_1d(nkmb) + int_sflux(nkmb) ) / h_2d(i,nkmb)
544 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then 546 tv%T(i,j,k) = t_2d(i,k) ; tv%S(i,j,k) = s_2d(i,k)
547 ea(i,j,k) = ea(i,j,k) + d_ea(i,k)
548 eb(i,j,k) = eb(i,j,k) + d_eb(i,k)
549 endif ;
enddo ;
enddo 552 do i=is,ie ; h_tot1(i) = 0.0 ; th_tot1(i) = 0.0 ; sh_tot1(i) = 0.0 ;
enddo 553 do i=is,ie ; h_tot2(i) = 0.0 ; th_tot2(i) = 0.0 ; sh_tot2(i) = 0.0 ;
enddo 555 do k=1,nz ;
do i=is,ie ;
if (do_i(i))
then 556 h_tot1(i) = h_tot1(i) + h_2d_init(i,k)
557 h_tot2(i) = h_tot2(i) + h(i,j,k)
559 th_tot1(i) = th_tot1(i) + h_2d_init(i,k) * t_2d_init(i,k)
560 th_tot2(i) = th_tot2(i) + h(i,j,k) * tv%T(i,j,k)
561 sh_tot1(i) = sh_tot1(i) + h_2d_init(i,k) * s_2d_init(i,k)
562 sh_tot2(i) = sh_tot2(i) + h(i,j,k) * tv%S(i,j,k)
563 if (h(i,j,k) < 0.0) &
564 call mom_error(fatal,
"regularize_surface: Negative thicknesses.")
565 if (k==1)
then ; h_predicted = h_2d_init(i,k) + (d_eb(i,k) - d_ea(i,k+1))
566 elseif (k==nz)
then ; h_predicted = h_2d_init(i,k) + (d_ea(i,k) - d_eb(i,k-1))
568 h_predicted = h_2d_init(i,k) + ((d_ea(i,k) - d_eb(i,k-1)) + &
569 (d_eb(i,k) - d_ea(i,k+1)))
571 if (abs(h(i,j,k) - h_predicted) > max(1e-9*abs(h_predicted),gv%Angstrom_H)) &
572 call mom_error(fatal,
"regularize_surface: d_ea mismatch.")
573 endif ;
enddo ;
enddo 574 do i=is,ie ;
if (do_i(i))
then 575 fatal_error = .false.
576 if (abs(h_tot1(i) - h_tot2(i)) > 1e-12*h_tot1(i))
then 577 write(mesg,
'(ES11.4," became ",ES11.4," diff ",ES11.4)') &
578 h_tot1(i), h_tot2(i), (h_tot1(i) - h_tot2(i))
579 call mom_error(warning,
"regularize_surface: Mass non-conservation."//&
583 if (abs(th_tot1(i) - th_tot2(i)) > 1e-12*(th_tot1(i)+10.0*h_tot1(i)))
then 584 write(mesg,
'(ES11.4," became ",ES11.4," diff ",ES11.4," int diff ",ES11.4)') &
585 th_tot1(i), th_tot2(i), (th_tot1(i) - th_tot2(i)), (th_tot1(i) - th_tot3(i))
586 call mom_error(warning,
"regularize_surface: Heat non-conservation."//&
590 if (abs(sh_tot1(i) - sh_tot2(i)) > 1e-12*(sh_tot1(i)+10.0*h_tot1(i)))
then 591 write(mesg,
'(ES11.4," became ",ES11.4," diff ",ES11.4," int diff ",ES11.4)') &
592 sh_tot1(i), sh_tot2(i), (sh_tot1(i) - sh_tot2(i)), (sh_tot1(i) - sh_tot3(i))
593 call mom_error(warning,
"regularize_surface: Salinity non-conservation."//&
597 if (fatal_error)
then 598 write(mesg,
'("Error at lat/lon ",2(ES11.4))') g%geoLatT(i,j), g%geoLonT(i,j)
599 call mom_error(fatal,
"regularize_surface: Terminating with fatal error. "//&
607 if (cs%id_def_rat > 0)
call post_data(cs%id_def_rat, def_rat_h, cs%diag)