6 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end
10 use mom_domains,
only : sum_across_pes, max_across_pes
33 implicit none ;
private
35 #include <MOM_memory.h>
42 real :: khtr_slope_cff
45 real :: khtr_passivity_coeff
48 real :: khtr_passivity_min
55 logical :: diffuse_ml_interior
57 logical :: check_diffusive_cfl
60 logical :: use_neutral_diffusion
62 logical :: use_lateral_boundary_diffusion
64 logical :: recalc_neutral_surf
72 logical :: show_call_tree
73 logical :: first_call = .true.
75 integer :: id_khtr_u = -1
76 integer :: id_khtr_v = -1
77 integer :: id_khtr_h = -1
78 integer :: id_cfl = -1
79 integer :: id_khdt_x = -1
80 integer :: id_khdt_y = -1
83 type(group_pass_type) :: pass_t
89 real,
dimension(:,:),
pointer :: p => null()
93 integer,
dimension(:,:),
pointer :: p => null()
106 subroutine tracer_hordiff(h, dt, MEKE, VarMix, G, GV, US, CS, Reg, tv, do_online_flag, read_khdt_x, read_khdt_y)
108 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
110 real,
intent(in) :: dt
124 logical,
optional,
intent(in) :: do_online_flag
126 real,
dimension(SZIB_(G),SZJ_(G)), &
127 optional,
intent(in) :: read_khdt_x
129 real,
dimension(SZI_(G),SZJB_(G)), &
130 optional,
intent(in) :: read_khdt_y
134 real,
dimension(SZI_(G),SZJ_(G)) :: &
141 real,
dimension(SZIB_(G),SZJ_(G)) :: &
147 real,
dimension(SZI_(G),SZJB_(G)) :: &
156 logical :: use_varmix, resoln_scaled, do_online, use_eady
157 integer :: s_idx, t_idx
158 integer :: i, j, k, m, is, ie, js, je, nz, ntr, itt, num_itts
170 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
173 if (
present(do_online_flag)) do_online = do_online_flag
175 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
176 "register_tracer must be called before tracer_hordiff.")
177 if (loc(reg)==0)
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
178 "register_tracer must be called before tracer_hordiff.")
179 if ((reg%ntr==0) .or. ((cs%KhTr <= 0.0) .and. .not.
associated(varmix)) )
return
181 if (cs%show_call_tree)
call calltree_enter(
"tracer_hordiff(), MOM_tracer_hor_diff.F90")
187 h_neglect = gv%H_subroundoff
189 if (cs%Diffuse_ML_interior .and. cs%first_call)
then ;
if (is_root_pe())
then
190 do m=1,ntr ;
if (
associated(reg%Tr(m)%df_x) .or.
associated(reg%Tr(m)%df_y)) &
191 call mom_error(warning,
"tracer_hordiff: Tracer "//trim(reg%Tr(m)%name)// &
192 " has associated 3-d diffusive flux diagnostics. These are not "//&
193 "valid when DIFFUSE_ML_TO_INTERIOR is defined. Use 2-d tracer "//&
194 "diffusion diagnostics instead to get accurate total fluxes.")
197 cs%first_call = .false.
201 use_varmix = .false. ; resoln_scaled = .false. ; use_eady = .false.
202 if (
Associated(varmix))
then
203 use_varmix = varmix%use_variable_mixing
204 resoln_scaled = varmix%Resoln_scaled_KhTr
205 use_eady = cs%KhTr_Slope_Cff > 0.
214 if (cs%show_call_tree)
call calltree_waypoint(
"Calculating diffusivity (tracer_hordiff)")
219 do j=js,je ;
do i=is-1,ie
221 if (use_eady) kh_loc = kh_loc + cs%KhTr_Slope_Cff*varmix%L2u(i,j)*varmix%SN_u(i,j)
222 if (
associated(meke%Kh)) &
223 kh_loc = kh_loc + meke%KhTr_fac*sqrt(meke%Kh(i,j)*meke%Kh(i+1,j))
224 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
226 kh_loc = kh_loc * 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i+1,j))
227 kh_u(i,j) = max(kh_loc, cs%KhTr_min)
228 if (cs%KhTr_passivity_coeff>0.)
then
229 rd_dx=0.5*( varmix%Rd_dx_h(i,j)+varmix%Rd_dx_h(i+1,j) )
230 kh_loc = kh_u(i,j)*max( cs%KhTr_passivity_min, cs%KhTr_passivity_coeff*rd_dx )
231 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
232 kh_u(i,j) = max(kh_loc, cs%KhTr_min)
236 do j=js-1,je ;
do i=is,ie
238 if (use_eady) kh_loc = kh_loc + cs%KhTr_Slope_Cff*varmix%L2v(i,j)*varmix%SN_v(i,j)
239 if (
associated(meke%Kh)) &
240 kh_loc = kh_loc + meke%KhTr_fac*sqrt(meke%Kh(i,j)*meke%Kh(i,j+1))
241 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
243 kh_loc = kh_loc * 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i,j+1))
244 kh_v(i,j) = max(kh_loc, cs%KhTr_min)
245 if (cs%KhTr_passivity_coeff>0.)
then
246 rd_dx = 0.5*( varmix%Rd_dx_h(i,j)+varmix%Rd_dx_h(i,j+1) )
247 kh_loc = kh_v(i,j)*max( cs%KhTr_passivity_min, cs%KhTr_passivity_coeff*rd_dx )
248 if (cs%KhTr_max > 0.) kh_loc = min(kh_loc, cs%KhTr_max)
249 kh_v(i,j) = max(kh_loc, cs%KhTr_min)
254 do j=js,je ;
do i=is-1,ie
255 khdt_x(i,j) = dt*(kh_u(i,j)*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
258 do j=js-1,je ;
do i=is,ie
259 khdt_y(i,j) = dt*(kh_v(i,j)*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
261 elseif (resoln_scaled)
then
263 do j=js,je ;
do i=is-1,ie
264 res_fn = 0.5 * (varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i+1,j))
265 kh_u(i,j) = max(cs%KhTr * res_fn, cs%KhTr_min)
266 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j))) * res_fn
269 do j=js-1,je ;
do i=is,ie
270 res_fn = 0.5*(varmix%Res_fn_h(i,j) + varmix%Res_fn_h(i,j+1))
271 kh_v(i,j) = max(cs%KhTr * res_fn, cs%KhTr_min)
272 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j))) * res_fn
275 if (cs%id_KhTr_u > 0)
then
277 do j=js,je ;
do i=is-1,ie
279 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
283 do j=js,je ;
do i=is-1,ie
284 khdt_x(i,j) = dt*(cs%KhTr*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
287 if (cs%id_KhTr_v > 0)
then
289 do j=js-1,je ;
do i=is,ie
291 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
295 do j=js-1,je ;
do i=is,ie
296 khdt_y(i,j) = dt*(cs%KhTr*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
301 if (cs%max_diff_CFL > 0.0)
then
302 if ((cs%id_KhTr_u > 0) .or. (cs%id_KhTr_h > 0))
then
304 do j=js,je ;
do i=is-1,ie
305 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i+1,j))
306 if (khdt_x(i,j) > khdt_max)
then
307 khdt_x(i,j) = khdt_max
308 if (dt*(g%dy_Cu(i,j)*g%IdxCu(i,j)) > 0.0) &
309 kh_u(i,j) = khdt_x(i,j) / (dt*(g%dy_Cu(i,j)*g%IdxCu(i,j)))
314 do j=js,je ;
do i=is-1,ie
315 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i+1,j))
316 khdt_x(i,j) = min(khdt_x(i,j), khdt_max)
319 if ((cs%id_KhTr_v > 0) .or. (cs%id_KhTr_h > 0))
then
321 do j=js-1,je ;
do i=is,ie
322 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i,j+1))
323 if (khdt_y(i,j) > khdt_max)
then
324 khdt_y(i,j) = khdt_max
325 if (dt*(g%dx_Cv(i,j)*g%IdyCv(i,j)) > 0.0) &
326 kh_v(i,j) = khdt_y(i,j) / (dt*(g%dx_Cv(i,j)*g%IdyCv(i,j)))
331 do j=js-1,je ;
do i=is,ie
332 khdt_max = 0.125*cs%max_diff_CFL * min(g%areaT(i,j), g%areaT(i,j+1))
333 khdt_y(i,j) = min(khdt_y(i,j), khdt_max)
340 do j=js,je ;
do i=is-1,ie
341 khdt_x(i,j) = us%m_to_L**2*read_khdt_x(i,j)
344 do j=js-1,je ;
do i=is,ie
345 khdt_y(i,j) = us%m_to_L**2*read_khdt_y(i,j)
350 if (cs%check_diffusive_CFL)
then
351 if (cs%show_call_tree)
call calltree_waypoint(
"Checking diffusive CFL (tracer_hordiff)")
353 do j=js,je ;
do i=is,ie
354 cfl(i,j) = 2.0*((khdt_x(i-1,j) + khdt_x(i,j)) + &
355 (khdt_y(i,j-1) + khdt_y(i,j))) * g%IareaT(i,j)
356 if (max_cfl < cfl(i,j)) max_cfl = cfl(i,j)
359 call max_across_pes(max_cfl)
361 num_itts = max(1, ceiling(max_cfl - 4.0*epsilon(max_cfl)))
362 i_numitts = 1.0 / (real(num_itts))
363 if (cs%id_CFL > 0)
call post_data(cs%id_CFL, cfl, cs%diag, mask=g%mask2dT)
364 elseif (cs%max_diff_CFL > 0.0)
then
365 num_itts = max(1, ceiling(cs%max_diff_CFL - 4.0*epsilon(cs%max_diff_CFL)))
366 i_numitts = 1.0 / (real(num_itts))
368 num_itts = 1 ; i_numitts = 1.0
372 if (
associated(reg%Tr(m)%df_x))
then
373 do k=1,nz ;
do j=js,je ;
do i=is-1,ie
374 reg%Tr(m)%df_x(i,j,k) = 0.0
375 enddo ;
enddo ;
enddo
377 if (
associated(reg%Tr(m)%df_y))
then
378 do k=1,nz ;
do j=js-1,je ;
do i=is,ie
379 reg%Tr(m)%df_y(i,j,k) = 0.0
380 enddo ;
enddo ;
enddo
382 if (
associated(reg%Tr(m)%df2d_x))
then
383 do j=js,je ;
do i=is-1,ie ; reg%Tr(m)%df2d_x(i,j) = 0.0 ;
enddo ;
enddo
385 if (
associated(reg%Tr(m)%df2d_y))
then
386 do j=js-1,je ;
do i=is,ie ; reg%Tr(m)%df2d_y(i,j) = 0.0 ;
enddo ;
enddo
390 if (cs%use_lateral_boundary_diffusion)
then
392 if (cs%show_call_tree)
call calltree_waypoint(
"Calling lateral boundary mixing (tracer_hordiff)")
396 do j=js-1,je ;
do i=is,ie
397 coef_y(i,j) = i_numitts * khdt_y(i,j)
401 coef_x(i,j) = i_numitts * khdt_x(i,j)
406 if (cs%show_call_tree)
call calltree_waypoint(
"Calling lateral boundary diffusion (tracer_hordiff)",itt)
411 cs%lateral_boundary_diffusion_CSp)
415 if (cs%use_neutral_diffusion)
then
417 if (cs%show_call_tree)
call calltree_waypoint(
"Calling neutral diffusion coeffs (tracer_hordiff)")
425 do j=js-1,je ;
do i=is,ie
426 coef_y(i,j) = i_numitts * khdt_y(i,j)
430 coef_x(i,j) = i_numitts * khdt_x(i,j)
435 if (cs%show_call_tree)
call calltree_waypoint(
"Calling neutral diffusion (tracer_hordiff)",itt)
438 if (cs%recalc_neutral_surf)
then
442 call neutral_diffusion(g, gv, h, coef_x, coef_y, i_numitts*dt, reg, us, cs%neutral_diffusion_CSp)
447 if (cs%show_call_tree)
call calltree_waypoint(
"Calculating horizontal diffusion (tracer_hordiff)")
453 if (cs%Diffuse_ML_interior)
then
455 if (cs%ML_KhTr_scale <= 0.0) cycle
456 scale = i_numitts * cs%ML_KhTr_scale
458 if ((k>gv%nkml) .and. (k<=gv%nk_rho_varies)) cycle
461 do j=js-1,je ;
do i=is,ie
462 coef_y(i,j) = ((scale * khdt_y(i,j))*2.0*(h(i,j,k)*h(i,j+1,k))) / &
463 (h(i,j,k)+h(i,j+1,k)+h_neglect)
468 coef_x(i,j) = ((scale * khdt_x(i,j))*2.0*(h(i,j,k)*h(i+1,j,k))) / &
469 (h(i,j,k)+h(i+1,j,k)+h_neglect)
473 ihdxdy(i,j) = g%IareaT(i,j) / (h(i,j,k)+h_neglect)
478 do j=js,je ;
do i=is,ie
479 dtr(i,j) = ihdxdy(i,j) * &
480 ((coef_x(i-1,j) * (reg%Tr(m)%t(i-1,j,k) - reg%Tr(m)%t(i,j,k)) - &
481 coef_x(i,j) * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k))) + &
482 (coef_y(i,j-1) * (reg%Tr(m)%t(i,j-1,k) - reg%Tr(m)%t(i,j,k)) - &
483 coef_y(i,j) * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k))))
485 if (
associated(reg%Tr(m)%df_x))
then ;
do j=js,je ;
do i=g%IscB,g%IecB
486 reg%Tr(m)%df_x(i,j,k) = reg%Tr(m)%df_x(i,j,k) + coef_x(i,j) &
487 * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k)) * idt
488 enddo ;
enddo ;
endif
489 if (
associated(reg%Tr(m)%df_y))
then ;
do j=g%JscB,g%JecB ;
do i=is,ie
490 reg%Tr(m)%df_y(i,j,k) = reg%Tr(m)%df_y(i,j,k) + coef_y(i,j) &
491 * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k)) * idt
492 enddo ;
enddo ;
endif
493 if (
associated(reg%Tr(m)%df2d_x))
then ;
do j=js,je ;
do i=g%IscB,g%IecB
494 reg%Tr(m)%df2d_x(i,j) = reg%Tr(m)%df2d_x(i,j) + coef_x(i,j) &
495 * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i+1,j,k)) * idt
496 enddo ;
enddo ;
endif
497 if (
associated(reg%Tr(m)%df2d_y))
then ;
do j=g%JscB,g%JecB ;
do i=is,ie
498 reg%Tr(m)%df2d_y(i,j) = reg%Tr(m)%df2d_y(i,j) + coef_y(i,j) &
499 * (reg%Tr(m)%t(i,j,k) - reg%Tr(m)%t(i,j+1,k)) * idt
500 enddo ;
enddo ;
endif
501 do j=js,je ;
do i=is,ie
502 reg%Tr(m)%t(i,j,k) = reg%Tr(m)%t(i,j,k) + dtr(i,j)
514 if (cs%Diffuse_ML_interior)
then
515 if (cs%show_call_tree)
call calltree_waypoint(
"Calling epipycnal_ML_diff (tracer_hordiff)")
527 if (cs%id_KhTr_u > 0)
then
528 do j=js,je ;
do i=is-1,ie
529 kh_u(i,j) = g%mask2dCu(i,j)*kh_u(i,j)
531 call post_data(cs%id_KhTr_u, kh_u, cs%diag, mask=g%mask2dCu)
533 if (cs%id_KhTr_v > 0)
then
534 do j=js-1,je ;
do i=is,ie
535 kh_v(i,j) = g%mask2dCv(i,j)*kh_v(i,j)
537 call post_data(cs%id_KhTr_v, kh_v, cs%diag, mask=g%mask2dCv)
539 if (cs%id_KhTr_h > 0)
then
541 do j=js,je ;
do i=is-1,ie
542 kh_u(i,j) = g%mask2dCu(i,j)*kh_u(i,j)
544 do j=js-1,je ;
do i=is,ie
545 kh_v(i,j) = g%mask2dCv(i,j)*kh_v(i,j)
547 do j=js,je ;
do i=is,ie
548 normalize = 1.0 / ((g%mask2dCu(i-1,j)+g%mask2dCu(i,j)) + &
549 (g%mask2dCv(i,j-1)+g%mask2dCv(i,j)) + gv%H_subroundoff)
550 kh_h(i,j) = normalize*g%mask2dT(i,j)*((kh_u(i-1,j)+kh_u(i,j)) + &
551 (kh_v(i,j-1)+kh_v(i,j)))
553 call post_data(cs%id_KhTr_h, kh_h, cs%diag, mask=g%mask2dT)
558 call uvchksum(
"After tracer diffusion khdt_[xy]", khdt_x, khdt_y, &
559 g%HI, haloshift=0, symmetric=.true., scale=us%L_to_m**2)
560 if (cs%use_neutral_diffusion)
then
561 call uvchksum(
"After tracer diffusion Coef_[xy]", coef_x, coef_y, &
562 g%HI, haloshift=0, symmetric=.true., scale=us%L_to_m**2)
566 if (cs%id_khdt_x > 0)
call post_data(cs%id_khdt_x, khdt_x, cs%diag)
567 if (cs%id_khdt_y > 0)
call post_data(cs%id_khdt_y, khdt_y, cs%diag)
578 GV, US, CS, tv, num_itts)
581 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
582 real,
intent(in) :: dt
584 integer,
intent(in) :: ntr
585 real,
dimension(SZIB_(G),SZJ_(G)),
intent(in) :: khdt_epi_x
588 real,
dimension(SZI_(G),SZJB_(G)),
intent(in) :: khdt_epi_y
594 integer,
intent(in) :: num_itts
597 real,
dimension(SZI_(G), SZJ_(G)) :: &
599 real,
dimension(SZI_(G), SZJ_(G), max(1,GV%nk_rho_varies)) :: &
604 type(
p2d),
dimension(SZJ_(G)) :: &
605 deep_wt_Lu, deep_wt_Ru, &
608 type(
p2d),
dimension(SZJB_(G)) :: &
609 deep_wt_Lv, deep_wt_Rv, &
612 type(
p2di),
dimension(SZJ_(G)) :: &
615 type(
p2di),
dimension(SZJB_(G)) :: &
619 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: &
621 real,
dimension(SZI_(G), SZJ_(G), SZK_(G)) :: Tr_flux_3d, Tr_adj_vert_L, Tr_adj_vert_R
623 real,
dimension(SZI_(G), SZK_(G), SZJ_(G)) :: &
626 integer,
dimension(SZI_(G), SZK_(G), SZJ_(G)) :: &
630 real,
dimension(SZK_(G)) :: &
637 integer,
dimension(SZK_(G)) :: &
641 integer,
dimension(SZI_(G), SZJ_(G)) :: &
647 integer,
dimension(SZJ_(G)) :: &
649 integer,
dimension(SZIB_(G), SZJ_(G)) :: &
651 integer,
dimension(SZI_(G), SZJB_(G)) :: &
657 real :: rho_pair, rho_a, rho_b
670 logical,
dimension(SZK_(G)) :: &
674 real :: p_ref_cv(SZI_(G))
676 integer :: k_max, k_min, k_test, itmp
677 integer :: i, j, k, k2, m, is, ie, js, je, nz, nkmb
678 integer :: isd, ied, jsd, jed, IsdB, IedB, k_size
679 integer :: kL, kR, kLa, kLb, kRa, kRb, nP, itt, ns, max_itt
680 integer :: PEmax_kRho
681 integer :: isv, iev, jsv, jev
683 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
684 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
685 isdb = g%IsdB ; iedb = g%IedB
687 nkmb = gv%nk_rho_varies
689 if (num_itts <= 1)
then
690 max_itt = 1 ; i_maxitt = 1.0
692 max_itt = num_itts ; i_maxitt = 1.0 / (real(max_itt))
695 do i=is-2,ie+2 ; p_ref_cv(i) = tv%P_Ref ;
enddo
700 do k=1,nkmb ;
do j=js-2,je+2
702 rho_coord(:,j,k), is-2, ie-is+5, tv%eqn_of_state, scale=us%kg_m3_to_R)
705 do j=js-2,je+2 ;
do i=is-2,ie+2
706 rml_max(i,j) = rho_coord(i,j,1)
707 num_srt(i,j) = 0 ; max_krho(i,j) = 0
709 do k=2,nkmb ;
do j=js-2,je+2 ;
do i=is-2,ie+2
710 if (rml_max(i,j) < rho_coord(i,j,k)) rml_max(i,j) = rho_coord(i,j,k)
711 enddo ;
enddo ;
enddo
717 do j=js-2,je+2 ;
do i=is-2,ie+2 ;
if (g%mask2dT(i,j) > 0.5)
then
718 if (rml_max(i,j) > gv%Rlay(nz))
then ; max_krho(i,j) = nz+1
719 elseif (rml_max(i,j) <= gv%Rlay(nkmb+1))
then ; max_krho(i,j) = nkmb+1
721 k_min = nkmb+2 ; k_max = nz
723 k_test = (k_min + k_max) / 2
724 if (rml_max(i,j) <= gv%Rlay(k_test-1))
then ; k_max = k_test-1
725 elseif (gv%Rlay(k_test) < rml_max(i,j))
then ; k_min = k_test+1
726 else ; max_krho(i,j) = k_test ;
exit ;
endif
728 if (k_min == k_max)
then ; max_krho(i,j) = k_max ;
exit ;
endif
731 endif ;
enddo ;
enddo
734 do j=js-1,je+1 ;
do i=is-1,ie+1
735 k_end_srt(i,j) = max(max_krho(i,j), max_krho(i-1,j), max_krho(i+1,j), &
736 max_krho(i,j-1), max_krho(i,j+1))
737 if (pemax_krho < k_end_srt(i,j)) pemax_krho = k_end_srt(i,j)
739 if (pemax_krho > nz) pemax_krho = nz
741 h_exclude = 10.0*(gv%Angstrom_H + gv%H_subroundoff)
747 do k=1,nkmb ;
do i=is-1,ie+1 ;
if (g%mask2dT(i,j) > 0.5)
then
748 if (h(i,j,k) > h_exclude)
then
749 num_srt(i,j) = num_srt(i,j) + 1 ; ns = num_srt(i,j)
751 rho_srt(i,ns,j) = rho_coord(i,j,k)
752 h_srt(i,ns,j) = h(i,j,k)
754 endif ;
enddo ;
enddo
755 do k=nkmb+1,pemax_krho ;
do i=is-1,ie+1 ;
if (g%mask2dT(i,j) > 0.5)
then
756 if ((k<=k_end_srt(i,j)) .and. (h(i,j,k) > h_exclude))
then
757 num_srt(i,j) = num_srt(i,j) + 1 ; ns = num_srt(i,j)
759 rho_srt(i,ns,j) = gv%Rlay(k)
760 h_srt(i,ns,j) = h(i,j,k)
762 endif ;
enddo ;
enddo
767 do j=js-1,je+1;
do i=is-1,ie+1
768 do k=2,num_srt(i,j) ;
if (rho_srt(i,k,j) < rho_srt(i,k-1,j))
then
770 do k2 = k,2,-1 ;
if (rho_srt(i,k2,j) >= rho_srt(i,k2-1,j))
exit
771 itmp = k0_srt(i,k2-1,j) ; k0_srt(i,k2-1,j) = k0_srt(i,k2,j) ; k0_srt(i,k2,j) = itmp
772 tmp = rho_srt(i,k2-1,j) ; rho_srt(i,k2-1,j) = rho_srt(i,k2,j) ; rho_srt(i,k2,j) = tmp
773 tmp = h_srt(i,k2-1,j) ; h_srt(i,k2-1,j) = h_srt(i,k2,j) ; h_srt(i,k2,j) = tmp
780 do i=is-1,ie+1 ; max_srt(j) = max(max_srt(j), num_srt(i,j)) ;
enddo
785 k_size = max(2*max_srt(j),1)
786 allocate(deep_wt_lu(j)%p(isdb:iedb,k_size))
787 allocate(deep_wt_ru(j)%p(isdb:iedb,k_size))
788 allocate(hp_lu(j)%p(isdb:iedb,k_size))
789 allocate(hp_ru(j)%p(isdb:iedb,k_size))
790 allocate(k0a_lu(j)%p(isdb:iedb,k_size))
791 allocate(k0a_ru(j)%p(isdb:iedb,k_size))
792 allocate(k0b_lu(j)%p(isdb:iedb,k_size))
793 allocate(k0b_ru(j)%p(isdb:iedb,k_size))
803 do j=js,je ;
do i=is-1,ie ;
if (g%mask2dCu(i,j) > 0.5)
then
806 do k=1,num_srt(i,j) ; h_demand_l(k) = 0.0 ; h_used_l(k) = 0.0 ;
enddo
807 do k=1,num_srt(i+1,j) ; h_demand_r(k) = 0.0 ; h_used_r(k) = 0.0 ;
enddo
814 if (rho_srt(i,1,j) < rho_srt(i+1,1,j))
then
816 do kl=2,num_srt(i,j) ;
if (rho_srt(i,kl,j) >= rho_srt(i+1,1,j))
exit ;
enddo
817 elseif (rho_srt(i+1,1,j) < rho_srt(i,1,j))
then
819 do kr=2,num_srt(i+1,j) ;
if (rho_srt(i+1,kr,j) >= rho_srt(i,1,j))
exit ;
enddo
825 if ((kl > num_srt(i,j)) .or. (kr > num_srt(i+1,j)))
exit
827 if (rho_srt(i,kl,j) > rho_srt(i+1,kr,j))
then
830 rho_pair = rho_srt(i+1,kr,j)
832 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
833 k0a_lu(j)%p(i,k) = k0_srt(i,kl-1,j) ; k0a_ru(j)%p(i,k) = k0b_ru(j)%p(i,k)
834 kbs_lp(k) = kl ; kbs_rp(k) = kr
836 rho_a = rho_srt(i,kl-1,j) ; rho_b = rho_srt(i,kl,j)
837 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
838 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
839 deep_wt_lu(j)%p(i,k) = wt_b ; deep_wt_ru(j)%p(i,k) = 1.0
841 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j) * wt_b
842 h_demand_l(kl-1) = h_demand_l(kl-1) + 0.5*h_srt(i+1,kr,j) * (1.0-wt_b)
844 kr = kr+1 ; left_set(k) = .false. ; right_set(k) = .true.
845 elseif (rho_srt(i,kl,j) < rho_srt(i+1,kr,j))
then
848 rho_pair = rho_srt(i,kl,j)
849 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
850 k0a_lu(j)%p(i,k) = k0b_lu(j)%p(i,k) ; k0a_ru(j)%p(i,k) = k0_srt(i+1,kr-1,j)
852 kbs_lp(k) = kl ; kbs_rp(k) = kr
854 rho_a = rho_srt(i+1,kr-1,j) ; rho_b = rho_srt(i+1,kr,j)
855 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
856 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
857 deep_wt_lu(j)%p(i,k) = 1.0 ; deep_wt_ru(j)%p(i,k) = wt_b
859 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j) * wt_b
860 h_demand_r(kr-1) = h_demand_r(kr-1) + 0.5*h_srt(i,kl,j) * (1.0-wt_b)
862 kl = kl+1 ; left_set(k) = .true. ; right_set(k) = .false.
863 elseif ((k0_srt(i,kl,j) <= nkmb) .or. (k0_srt(i+1,kr,j) <= nkmb))
then
866 k0b_lu(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_ru(j)%p(i,k) = k0_srt(i+1,kr,j)
867 k0a_lu(j)%p(i,k) = k0b_lu(j)%p(i,k) ; k0a_ru(j)%p(i,k) = k0b_ru(j)%p(i,k)
868 kbs_lp(k) = kl ; kbs_rp(k) = kr
869 deep_wt_lu(j)%p(i,k) = 1.0 ; deep_wt_ru(j)%p(i,k) = 1.0
871 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j)
872 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
874 kl = kl+1 ; kr = kr+1 ; left_set(k) = .true. ; right_set(k) = .true.
878 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i+1,kr,j)
879 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
881 kl = kl+1 ; kr = kr+1
887 do k=1,num_srt(i+1,j)
888 h_supply_frac_r(k) = 1.0
889 if (h_demand_r(k) > 0.5*h_srt(i+1,k,j)) &
890 h_supply_frac_r(k) = 0.5*h_srt(i+1,k,j) / h_demand_r(k)
893 h_supply_frac_l(k) = 1.0
894 if (h_demand_l(k) > 0.5*h_srt(i,k,j)) &
895 h_supply_frac_l(k) = 0.5*h_srt(i,k,j) / h_demand_l(k)
900 kl = kbs_lp(k) ; kr = kbs_rp(k)
901 hp_lu(j)%p(i,k) = 0.0 ; hp_ru(j)%p(i,k) = 0.0
902 if (left_set(k))
then
903 if (deep_wt_ru(j)%p(i,k) < 1.0)
then
904 hp_ru(j)%p(i,k) = 0.5*h_srt(i,kl,j) * min(h_supply_frac_r(kr), h_supply_frac_r(kr-1))
905 wt_b = deep_wt_ru(j)%p(i,k)
906 h_used_r(kr-1) = h_used_r(kr-1) + (1.0 - wt_b)*hp_ru(j)%p(i,k)
907 h_used_r(kr) = h_used_r(kr) + wt_b*hp_ru(j)%p(i,k)
909 hp_ru(j)%p(i,k) = 0.5*h_srt(i,kl,j) * h_supply_frac_r(kr)
910 h_used_r(kr) = h_used_r(kr) + hp_ru(j)%p(i,k)
913 if (right_set(k))
then
914 if (deep_wt_lu(j)%p(i,k) < 1.0)
then
915 hp_lu(j)%p(i,k) = 0.5*h_srt(i+1,kr,j) * min(h_supply_frac_l(kl), h_supply_frac_l(kl-1))
916 wt_b = deep_wt_lu(j)%p(i,k)
917 h_used_l(kl-1) = h_used_l(kl-1) + (1.0 - wt_b)*hp_lu(j)%p(i,k)
918 h_used_l(kl) = h_used_l(kl) + wt_b*hp_lu(j)%p(i,k)
920 hp_lu(j)%p(i,k) = 0.5*h_srt(i+1,kr,j) * h_supply_frac_l(kl)
921 h_used_l(kl) = h_used_l(kl) + hp_lu(j)%p(i,k)
929 if (left_set(k)) hp_lu(j)%p(i,k) = hp_lu(j)%p(i,k) + &
930 (h_srt(i,kbs_lp(k),j) - h_used_l(kbs_lp(k)))
931 if (right_set(k)) hp_ru(j)%p(i,k) = hp_ru(j)%p(i,k) + &
932 (h_srt(i+1,kbs_rp(k),j) - h_used_r(kbs_rp(k)))
935 endif ;
enddo ;
enddo
938 k_size = max(max_srt(j)+max_srt(j+1),1)
939 allocate(deep_wt_lv(j)%p(isd:ied,k_size))
940 allocate(deep_wt_rv(j)%p(isd:ied,k_size))
941 allocate(hp_lv(j)%p(isd:ied,k_size))
942 allocate(hp_rv(j)%p(isd:ied,k_size))
943 allocate(k0a_lv(j)%p(isd:ied,k_size))
944 allocate(k0a_rv(j)%p(isd:ied,k_size))
945 allocate(k0b_lv(j)%p(isd:ied,k_size))
946 allocate(k0b_rv(j)%p(isd:ied,k_size))
956 do j=js-1,je ;
do i=is,ie ;
if (g%mask2dCv(i,j) > 0.5)
then
959 do k=1,num_srt(i,j) ; h_demand_l(k) = 0.0 ; h_used_l(k) = 0.0 ;
enddo
960 do k=1,num_srt(i,j+1) ; h_demand_r(k) = 0.0 ; h_used_r(k) = 0.0 ;
enddo
967 if (rho_srt(i,1,j) < rho_srt(i,1,j+1))
then
969 do kl=2,num_srt(i,j) ;
if (rho_srt(i,kl,j) >= rho_srt(i,1,j+1))
exit ;
enddo
970 elseif (rho_srt(i,1,j+1) < rho_srt(i,1,j))
then
972 do kr=2,num_srt(i,j+1) ;
if (rho_srt(i,kr,j+1) >= rho_srt(i,1,j))
exit ;
enddo
978 if ((kl > num_srt(i,j)) .or. (kr > num_srt(i,j+1)))
exit
980 if (rho_srt(i,kl,j) > rho_srt(i,kr,j+1))
then
983 rho_pair = rho_srt(i,kr,j+1)
985 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
986 k0a_lv(j)%p(i,k) = k0_srt(i,kl-1,j) ; k0a_rv(j)%p(i,k) = k0b_rv(j)%p(i,k)
987 kbs_lp(k) = kl ; kbs_rp(k) = kr
989 rho_a = rho_srt(i,kl-1,j) ; rho_b = rho_srt(i,kl,j)
990 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
991 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
992 deep_wt_lv(j)%p(i,k) = wt_b ; deep_wt_rv(j)%p(i,k) = 1.0
994 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1) * wt_b
995 h_demand_l(kl-1) = h_demand_l(kl-1) + 0.5*h_srt(i,kr,j+1) * (1.0-wt_b)
997 kr = kr+1 ; left_set(k) = .false. ; right_set(k) = .true.
998 elseif (rho_srt(i,kl,j) < rho_srt(i,kr,j+1))
then
1001 rho_pair = rho_srt(i,kl,j)
1002 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
1003 k0a_lv(j)%p(i,k) = k0b_lv(j)%p(i,k) ; k0a_rv(j)%p(i,k) = k0_srt(i,kr-1,j+1)
1005 kbs_lp(k) = kl ; kbs_rp(k) = kr
1007 rho_a = rho_srt(i,kr-1,j+1) ; rho_b = rho_srt(i,kr,j+1)
1008 wt_b = 1.0 ;
if (abs(rho_a - rho_b) > abs(rho_pair - rho_a)) &
1009 wt_b = (rho_pair - rho_a) / (rho_b - rho_a)
1010 deep_wt_lv(j)%p(i,k) = 1.0 ; deep_wt_rv(j)%p(i,k) = wt_b
1012 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j) * wt_b
1013 h_demand_r(kr-1) = h_demand_r(kr-1) + 0.5*h_srt(i,kl,j) * (1.0-wt_b)
1015 kl = kl+1 ; left_set(k) = .true. ; right_set(k) = .false.
1016 elseif ((k0_srt(i,kl,j) <= nkmb) .or. (k0_srt(i,kr,j+1) <= nkmb))
then
1019 k0b_lv(j)%p(i,k) = k0_srt(i,kl,j) ; k0b_rv(j)%p(i,k) = k0_srt(i,kr,j+1)
1020 k0a_lv(j)%p(i,k) = k0b_lv(j)%p(i,k) ; k0a_rv(j)%p(i,k) = k0b_rv(j)%p(i,k)
1021 kbs_lp(k) = kl ; kbs_rp(k) = kr
1022 deep_wt_lv(j)%p(i,k) = 1.0 ; deep_wt_rv(j)%p(i,k) = 1.0
1024 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1)
1025 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
1027 kl = kl+1 ; kr = kr+1 ; left_set(k) = .true. ; right_set(k) = .true.
1031 h_demand_l(kl) = h_demand_l(kl) + 0.5*h_srt(i,kr,j+1)
1032 h_demand_r(kr) = h_demand_r(kr) + 0.5*h_srt(i,kl,j)
1034 kl = kl+1 ; kr = kr+1
1040 do k=1,num_srt(i,j+1)
1041 h_supply_frac_r(k) = 1.0
1042 if (h_demand_r(k) > 0.5*h_srt(i,k,j+1)) &
1043 h_supply_frac_r(k) = 0.5*h_srt(i,k,j+1) / h_demand_r(k)
1046 h_supply_frac_l(k) = 1.0
1047 if (h_demand_l(k) > 0.5*h_srt(i,k,j)) &
1048 h_supply_frac_l(k) = 0.5*h_srt(i,k,j) / h_demand_l(k)
1053 kl = kbs_lp(k) ; kr = kbs_rp(k)
1054 hp_lv(j)%p(i,k) = 0.0 ; hp_rv(j)%p(i,k) = 0.0
1055 if (left_set(k))
then
1056 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1057 hp_rv(j)%p(i,k) = 0.5*h_srt(i,kl,j) * min(h_supply_frac_r(kr), h_supply_frac_r(kr-1))
1058 wt_b = deep_wt_rv(j)%p(i,k)
1059 h_used_r(kr-1) = h_used_r(kr-1) + (1.0 - wt_b) * hp_rv(j)%p(i,k)
1060 h_used_r(kr) = h_used_r(kr) + wt_b * hp_rv(j)%p(i,k)
1062 hp_rv(j)%p(i,k) = 0.5*h_srt(i,kl,j) * h_supply_frac_r(kr)
1063 h_used_r(kr) = h_used_r(kr) + hp_rv(j)%p(i,k)
1066 if (right_set(k))
then
1067 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1068 hp_lv(j)%p(i,k) = 0.5*h_srt(i,kr,j+1) * min(h_supply_frac_l(kl), h_supply_frac_l(kl-1))
1069 wt_b = deep_wt_lv(j)%p(i,k)
1070 h_used_l(kl-1) = h_used_l(kl-1) + (1.0 - wt_b) * hp_lv(j)%p(i,k)
1071 h_used_l(kl) = h_used_l(kl) + wt_b * hp_lv(j)%p(i,k)
1073 hp_lv(j)%p(i,k) = 0.5*h_srt(i,kr,j+1) * h_supply_frac_l(kl)
1074 h_used_l(kl) = h_used_l(kl) + hp_lv(j)%p(i,k)
1082 if (left_set(k)) hp_lv(j)%p(i,k) = hp_lv(j)%p(i,k) + &
1083 (h_srt(i,kbs_lp(k),j) - h_used_l(kbs_lp(k)))
1084 if (right_set(k)) hp_rv(j)%p(i,k) = hp_rv(j)%p(i,k) + &
1085 (h_srt(i,kbs_rp(k),j+1) - h_used_r(kbs_rp(k)))
1089 endif ;
enddo ;
enddo
1094 do k=1,pemax_krho ;
do j=js-1,je+1 ;
do i=is-1,ie+1
1095 tr_flux_conv(i,j,k) = 0.0
1096 enddo ;
enddo ;
enddo
1101 call do_group_pass(cs%pass_t, g%Domain, clock=
id_clock_pass)
1111 do j=js,je ;
do i=is-1,ie ;
if (g%mask2dCu(i,j) > 0.5)
then
1115 if (npu(i,j) >= 1)
then
1116 tr_min_face = min(tr(m)%t(i,j,1), tr(m)%t(i+1,j,1))
1117 tr_max_face = max(tr(m)%t(i,j,1), tr(m)%t(i+1,j,1))
1119 tr_min_face = min(tr_min_face, tr(m)%t(i,j,k), tr(m)%t(i+1,j,k))
1120 tr_max_face = max(tr_max_face, tr(m)%t(i,j,k), tr(m)%t(i+1,j,k))
1124 kla = nkmb+1 ;
if (max_krho(i,j) < nz+1) kla = max_krho(i,j)
1125 klb = kla ;
if (max_krho(i,j) < nz) klb = max_krho(i,j)+1
1126 kra = nkmb+1 ;
if (max_krho(i+1,j) < nz+1) kra = max_krho(i+1,j)
1127 krb = kra ;
if (max_krho(i+1,j) < nz) krb = max_krho(i+1,j)+1
1128 tr_la = tr_min_face ; tr_lb = tr_la ; tr_ra = tr_la ; tr_rb = tr_la
1129 if (h(i,j,kla) > h_exclude) tr_la = tr(m)%t(i,j,kla)
1130 if (h(i,j,klb) > h_exclude) tr_la = tr(m)%t(i,j,klb)
1131 if (h(i+1,j,kra) > h_exclude) tr_ra = tr(m)%t(i+1,j,kra)
1132 if (h(i+1,j,krb) > h_exclude) tr_rb = tr(m)%t(i+1,j,krb)
1133 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1134 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1138 tr_lb = tr(m)%t(i,j,k0b_lu(j)%p(i,k))
1139 tr_rb = tr(m)%t(i+1,j,k0b_ru(j)%p(i,k))
1140 tr_la = tr_lb ; tr_ra = tr_rb
1141 if (deep_wt_lu(j)%p(i,k) < 1.0) tr_la = tr(m)%t(i,j,k0a_lu(j)%p(i,k))
1142 if (deep_wt_ru(j)%p(i,k) < 1.0) tr_ra = tr(m)%t(i+1,j,k0a_ru(j)%p(i,k))
1143 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1144 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1149 klb = k0b_lu(j)%p(i,k) ; tr_lb = tr(m)%t(i,j,klb) ; tr_av_l = tr_lb
1150 if (deep_wt_lu(j)%p(i,k) < 1.0)
then
1151 kla = k0a_lu(j)%p(i,k) ; tr_la = tr(m)%t(i,j,kla)
1152 wt_b = deep_wt_lu(j)%p(i,k)
1153 tr_av_l = wt_b*tr_lb + (1.0-wt_b)*tr_la
1156 krb = k0b_ru(j)%p(i,k) ; tr_rb = tr(m)%t(i+1,j,krb) ; tr_av_r = tr_rb
1157 if (deep_wt_ru(j)%p(i,k) < 1.0)
then
1158 kra = k0a_ru(j)%p(i,k) ; tr_ra = tr(m)%t(i+1,j,kra)
1159 wt_b = deep_wt_ru(j)%p(i,k)
1160 tr_av_r = wt_b*tr_rb + (1.0-wt_b)*tr_ra
1163 h_l = hp_lu(j)%p(i,k) ; h_r = hp_ru(j)%p(i,k)
1164 tr_flux = i_maxitt * khdt_epi_x(i,j) * (tr_av_l - tr_av_r) * &
1165 ((2.0 * h_l * h_r) / (h_l + h_r))
1168 if (deep_wt_lu(j)%p(i,k) >= 1.0)
then
1169 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - tr_flux
1172 wt_b = deep_wt_lu(j)%p(i,k) ; wt_a = 1.0 - wt_b
1173 vol = hp_lu(j)%p(i,k) * g%areaT(i,j)
1181 if (tr_flux > 0.0)
then
1182 if (tr_la < tr_lb)
then ;
if (vol*(tr_la-tr_min_face) < tr_flux) &
1183 tr_adj_vert = -wt_a * min(tr_flux - vol * (tr_la-tr_min_face), &
1184 (vol*wt_b) * (tr_lb - tr_la))
1185 else ;
if (vol*(tr_lb-tr_min_face) < tr_flux) &
1186 tr_adj_vert = wt_b * min(tr_flux - vol * (tr_lb-tr_min_face), &
1187 (vol*wt_a) * (tr_la - tr_lb))
1189 elseif (tr_flux < 0.0)
then
1190 if (tr_la > tr_lb)
then ;
if (vol * (tr_max_face-tr_la) < -tr_flux) &
1191 tr_adj_vert = wt_a * min(-tr_flux - vol * (tr_max_face-tr_la), &
1192 (vol*wt_b) * (tr_la - tr_lb))
1193 else ;
if (vol*(tr_max_face-tr_lb) < -tr_flux) &
1194 tr_adj_vert = -wt_b * min(-tr_flux - vol * (tr_max_face-tr_lb), &
1195 (vol*wt_a)*(tr_lb - tr_la))
1199 tr_flux_conv(i,j,kla) = tr_flux_conv(i,j,kla) - (wt_a*tr_flux + tr_adj_vert)
1200 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - (wt_b*tr_flux - tr_adj_vert)
1203 if (deep_wt_ru(j)%p(i,k) >= 1.0)
then
1204 tr_flux_conv(i+1,j,krb) = tr_flux_conv(i+1,j,krb) + tr_flux
1207 wt_b = deep_wt_ru(j)%p(i,k) ; wt_a = 1.0 - wt_b
1208 vol = hp_ru(j)%p(i,k) * g%areaT(i+1,j)
1216 if (tr_flux < 0.0)
then
1217 if (tr_ra < tr_rb)
then ;
if (vol * (tr_ra-tr_min_face) < -tr_flux) &
1218 tr_adj_vert = -wt_a * min(-tr_flux - vol * (tr_ra-tr_min_face), &
1219 (vol*wt_b) * (tr_rb - tr_ra))
1220 else ;
if (vol*(tr_rb-tr_min_face) < (-tr_flux)) &
1221 tr_adj_vert = wt_b * min(-tr_flux - vol * (tr_rb-tr_min_face), &
1222 (vol*wt_a) * (tr_ra - tr_rb))
1224 elseif (tr_flux > 0.0)
then
1225 if (tr_ra > tr_rb)
then ;
if (vol * (tr_max_face-tr_ra) < tr_flux) &
1226 tr_adj_vert = wt_a * min(tr_flux - vol * (tr_max_face-tr_ra), &
1227 (vol*wt_b) * (tr_ra - tr_rb))
1228 else ;
if (vol*(tr_max_face-tr_rb) < tr_flux) &
1229 tr_adj_vert = -wt_b * min(tr_flux - vol * (tr_max_face-tr_rb), &
1230 (vol*wt_a)*(tr_rb - tr_ra))
1234 tr_flux_conv(i+1,j,kra) = tr_flux_conv(i+1,j,kra) + &
1235 (wt_a*tr_flux - tr_adj_vert)
1236 tr_flux_conv(i+1,j,krb) = tr_flux_conv(i+1,j,krb) + &
1237 (wt_b*tr_flux + tr_adj_vert)
1239 if (
associated(tr(m)%df2d_x)) &
1240 tr(m)%df2d_x(i,j) = tr(m)%df2d_x(i,j) + tr_flux * idt
1242 endif ;
enddo ;
enddo
1251 do j=js-1,je ;
do i=is,ie ;
if (g%mask2dCv(i,j) > 0.5)
then
1255 if (npv(i,j) >= 1)
then
1256 tr_min_face = min(tr(m)%t(i,j,1), tr(m)%t(i,j+1,1))
1257 tr_max_face = max(tr(m)%t(i,j,1), tr(m)%t(i,j+1,1))
1259 tr_min_face = min(tr_min_face, tr(m)%t(i,j,k), tr(m)%t(i,j+1,k))
1260 tr_max_face = max(tr_max_face, tr(m)%t(i,j,k), tr(m)%t(i,j+1,k))
1264 kla = nkmb+1 ;
if (max_krho(i,j) < nz+1) kla = max_krho(i,j)
1265 klb = kla ;
if (max_krho(i,j) < nz) klb = max_krho(i,j)+1
1266 kra = nkmb+1 ;
if (max_krho(i,j+1) < nz+1) kra = max_krho(i,j+1)
1267 krb = kra ;
if (max_krho(i,j+1) < nz) krb = max_krho(i,j+1)+1
1268 tr_la = tr_min_face ; tr_lb = tr_la ; tr_ra = tr_la ; tr_rb = tr_la
1269 if (h(i,j,kla) > h_exclude) tr_la = tr(m)%t(i,j,kla)
1270 if (h(i,j,klb) > h_exclude) tr_la = tr(m)%t(i,j,klb)
1271 if (h(i,j+1,kra) > h_exclude) tr_ra = tr(m)%t(i,j+1,kra)
1272 if (h(i,j+1,krb) > h_exclude) tr_rb = tr(m)%t(i,j+1,krb)
1273 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1274 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1278 tr_lb = tr(m)%t(i,j,k0b_lv(j)%p(i,k)) ; tr_rb = tr(m)%t(i,j+1,k0b_rv(j)%p(i,k))
1279 tr_la = tr_lb ; tr_ra = tr_rb
1280 if (deep_wt_lv(j)%p(i,k) < 1.0) tr_la = tr(m)%t(i,j,k0a_lv(j)%p(i,k))
1281 if (deep_wt_rv(j)%p(i,k) < 1.0) tr_ra = tr(m)%t(i,j+1,k0a_rv(j)%p(i,k))
1282 tr_min_face = min(tr_min_face, tr_la, tr_lb, tr_ra, tr_rb)
1283 tr_max_face = max(tr_max_face, tr_la, tr_lb, tr_ra, tr_rb)
1288 klb = k0b_lv(j)%p(i,k) ; tr_lb = tr(m)%t(i,j,klb) ; tr_av_l = tr_lb
1289 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1290 kla = k0a_lv(j)%p(i,k) ; tr_la = tr(m)%t(i,j,kla)
1291 wt_b = deep_wt_lv(j)%p(i,k)
1292 tr_av_l = wt_b * tr_lb + (1.0-wt_b) * tr_la
1295 krb = k0b_rv(j)%p(i,k) ; tr_rb = tr(m)%t(i,j+1,krb) ; tr_av_r = tr_rb
1296 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1297 kra = k0a_rv(j)%p(i,k) ; tr_ra = tr(m)%t(i,j+1,kra)
1298 wt_b = deep_wt_rv(j)%p(i,k)
1299 tr_av_r = wt_b * tr_rb + (1.0-wt_b) * tr_ra
1302 h_l = hp_lv(j)%p(i,k) ; h_r = hp_rv(j)%p(i,k)
1303 tr_flux = i_maxitt * ((2.0 * h_l * h_r) / (h_l + h_r)) * &
1304 khdt_epi_y(i,j) * (tr_av_l - tr_av_r)
1305 tr_flux_3d(i,j,k) = tr_flux
1307 if (deep_wt_lv(j)%p(i,k) < 1.0)
then
1309 wt_b = deep_wt_lv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1310 vol = hp_lv(j)%p(i,k) * g%areaT(i,j)
1314 if (tr_flux > 0.0)
then
1315 if (tr_la < tr_lb)
then ;
if (vol * (tr_la-tr_min_face) < tr_flux) &
1316 tr_adj_vert = -wt_a * min(tr_flux - vol * (tr_la-tr_min_face), &
1317 (vol*wt_b) * (tr_lb - tr_la))
1318 else ;
if (vol*(tr_lb-tr_min_face) < tr_flux) &
1319 tr_adj_vert = wt_b * min(tr_flux - vol * (tr_lb-tr_min_face), &
1320 (vol*wt_a) * (tr_la - tr_lb))
1322 elseif (tr_flux < 0.0)
then
1323 if (tr_la > tr_lb)
then ;
if (vol * (tr_max_face-tr_la) < -tr_flux) &
1324 tr_adj_vert = wt_a * min(-tr_flux - vol * (tr_max_face-tr_la), &
1325 (vol*wt_b) * (tr_la - tr_lb))
1326 else ;
if (vol*(tr_max_face-tr_lb) < -tr_flux) &
1327 tr_adj_vert = -wt_b * min(-tr_flux - vol * (tr_max_face-tr_lb), &
1328 (vol*wt_a)*(tr_lb - tr_la))
1331 tr_adj_vert_l(i,j,k) = tr_adj_vert
1334 if (deep_wt_rv(j)%p(i,k) < 1.0)
then
1336 wt_b = deep_wt_rv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1337 vol = hp_rv(j)%p(i,k) * g%areaT(i,j+1)
1341 if (tr_flux < 0.0)
then
1342 if (tr_ra < tr_rb)
then ;
if (vol * (tr_ra-tr_min_face) < -tr_flux) &
1343 tr_adj_vert = -wt_a * min(-tr_flux - vol * (tr_ra-tr_min_face), &
1344 (vol*wt_b) * (tr_rb - tr_ra))
1345 else ;
if (vol*(tr_rb-tr_min_face) < (-tr_flux)) &
1346 tr_adj_vert = wt_b * min(-tr_flux - vol * (tr_rb-tr_min_face), &
1347 (vol*wt_a) * (tr_ra - tr_rb))
1349 elseif (tr_flux > 0.0)
then
1350 if (tr_ra > tr_rb)
then ;
if (vol * (tr_max_face-tr_ra) < tr_flux) &
1351 tr_adj_vert = wt_a * min(tr_flux - vol * (tr_max_face-tr_ra), &
1352 (vol*wt_b) * (tr_ra - tr_rb))
1353 else ;
if (vol*(tr_max_face-tr_rb) < tr_flux) &
1354 tr_adj_vert = -wt_b * min(tr_flux - vol * (tr_max_face-tr_rb), &
1355 (vol*wt_a)*(tr_rb - tr_ra))
1358 tr_adj_vert_r(i,j,k) = tr_adj_vert
1360 if (
associated(tr(m)%df2d_y)) &
1361 tr(m)%df2d_y(i,j) = tr(m)%df2d_y(i,j) + tr_flux * idt
1363 endif ;
enddo ;
enddo
1368 do i=is,ie ;
do j=js-1,je ;
if (g%mask2dCv(i,j) > 0.5)
then
1370 klb = k0b_lv(j)%p(i,k); krb = k0b_rv(j)%p(i,k)
1371 if (deep_wt_lv(j)%p(i,k) >= 1.0)
then
1372 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - tr_flux_3d(i,j,k)
1374 kla = k0a_lv(j)%p(i,k)
1375 wt_b = deep_wt_lv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1376 tr_flux_conv(i,j,kla) = tr_flux_conv(i,j,kla) - (wt_a*tr_flux_3d(i,j,k) + tr_adj_vert_l(i,j,k))
1377 tr_flux_conv(i,j,klb) = tr_flux_conv(i,j,klb) - (wt_b*tr_flux_3d(i,j,k) - tr_adj_vert_l(i,j,k))
1379 if (deep_wt_rv(j)%p(i,k) >= 1.0)
then
1380 tr_flux_conv(i,j+1,krb) = tr_flux_conv(i,j+1,krb) + tr_flux_3d(i,j,k)
1382 kra = k0a_rv(j)%p(i,k)
1383 wt_b = deep_wt_rv(j)%p(i,k) ; wt_a = 1.0 - wt_b
1384 tr_flux_conv(i,j+1,kra) = tr_flux_conv(i,j+1,kra) + &
1385 (wt_a*tr_flux_3d(i,j,k) - tr_adj_vert_r(i,j,k))
1386 tr_flux_conv(i,j+1,krb) = tr_flux_conv(i,j+1,krb) + &
1387 (wt_b*tr_flux_3d(i,j,k) + tr_adj_vert_r(i,j,k))
1390 endif ;
enddo ;
enddo
1392 do k=1,pemax_krho ;
do j=js,je ;
do i=is,ie
1393 if ((g%mask2dT(i,j) > 0.5) .and. (h(i,j,k) > 0.0))
then
1394 tr(m)%t(i,j,k) = tr(m)%t(i,j,k) + tr_flux_conv(i,j,k) / &
1395 (h(i,j,k)*g%areaT(i,j))
1396 tr_flux_conv(i,j,k) = 0.0
1398 enddo ;
enddo ;
enddo
1404 deallocate(deep_wt_lu(j)%p) ;
deallocate(deep_wt_ru(j)%p)
1405 deallocate(hp_lu(j)%p) ;
deallocate(hp_ru(j)%p)
1406 deallocate(k0a_lu(j)%p) ;
deallocate(k0a_ru(j)%p)
1407 deallocate(k0b_lu(j)%p) ;
deallocate(k0b_ru(j)%p)
1411 deallocate(deep_wt_lv(j)%p) ;
deallocate(deep_wt_rv(j)%p)
1412 deallocate(hp_lv(j)%p) ;
deallocate(hp_rv(j)%p)
1413 deallocate(k0a_lv(j)%p) ;
deallocate(k0a_rv(j)%p)
1414 deallocate(k0b_lv(j)%p) ;
deallocate(k0b_rv(j)%p)
1422 type(time_type),
target,
intent(in) :: time
1425 type(
diag_ctrl),
target,
intent(inout) :: diag
1426 type(
eos_type),
target,
intent(in) :: eos
1427 type(
diabatic_cs),
pointer,
intent(in) :: diabatic_csp
1432 #include "version_variable.h"
1433 character(len=40) :: mdl =
"MOM_tracer_hor_diff"
1434 character(len=256) :: mesg
1436 if (
associated(cs))
then
1437 call mom_error(warning,
"tracer_hor_diff_init called with associated control structure.")
1443 cs%show_call_tree = calltree_showquery()
1447 call get_param(param_file, mdl,
"KHTR", cs%KhTr, &
1448 "The background along-isopycnal tracer diffusivity.", &
1449 units=
"m2 s-1", default=0.0, scale=us%m_to_L**2*us%T_to_s)
1450 call get_param(param_file, mdl,
"KHTR_SLOPE_CFF", cs%KhTr_Slope_Cff, &
1451 "The scaling coefficient for along-isopycnal tracer "//&
1452 "diffusivity using a shear-based (Visbeck-like) "//&
1453 "parameterization. A non-zero value enables this param.", &
1454 units=
"nondim", default=0.0)
1455 call get_param(param_file, mdl,
"KHTR_MIN", cs%KhTr_Min, &
1456 "The minimum along-isopycnal tracer diffusivity.", &
1457 units=
"m2 s-1", default=0.0, scale=us%m_to_L**2*us%T_to_s)
1458 call get_param(param_file, mdl,
"KHTR_MAX", cs%KhTr_Max, &
1459 "The maximum along-isopycnal tracer diffusivity.", &
1460 units=
"m2 s-1", default=0.0, scale=us%m_to_L**2*us%T_to_s)
1461 call get_param(param_file, mdl,
"KHTR_PASSIVITY_COEFF", cs%KhTr_passivity_coeff, &
1462 "The coefficient that scales deformation radius over "//&
1463 "grid-spacing in passivity, where passivity is the ratio "//&
1464 "between along isopycnal mixing of tracers to thickness mixing. "//&
1465 "A non-zero value enables this parameterization.", &
1466 units=
"nondim", default=0.0)
1467 call get_param(param_file, mdl,
"KHTR_PASSIVITY_MIN", cs%KhTr_passivity_min, &
1468 "The minimum passivity which is the ratio between "//&
1469 "along isopycnal mixing of tracers to thickness mixing.", &
1470 units=
"nondim", default=0.5)
1471 call get_param(param_file, mdl,
"DIFFUSE_ML_TO_INTERIOR", cs%Diffuse_ML_interior, &
1472 "If true, enable epipycnal mixing between the surface "//&
1473 "boundary layer and the interior.", default=.false.)
1474 call get_param(param_file, mdl,
"CHECK_DIFFUSIVE_CFL", cs%check_diffusive_CFL, &
1475 "If true, use enough iterations the diffusion to ensure "//&
1476 "that the diffusive equivalent of the CFL limit is not "//&
1477 "violated. If false, always use the greater of 1 or "//&
1478 "MAX_TR_DIFFUSION_CFL iteration.", default=.false.)
1479 call get_param(param_file, mdl,
"MAX_TR_DIFFUSION_CFL", cs%max_diff_CFL, &
1480 "If positive, locally limit the along-isopycnal tracer "//&
1481 "diffusivity to keep the diffusive CFL locally at or "//&
1482 "below this value. The number of diffusive iterations "//&
1483 "is often this value or the next greater integer.", &
1484 units=
"nondim", default=-1.0)
1485 call get_param(param_file, mdl,
"RECALC_NEUTRAL_SURF", cs%recalc_neutral_surf, &
1486 "If true, then recalculate the neutral surfaces if the \n"//&
1487 "diffusive CFL is exceeded. If false, assume that the \n"//&
1488 "positions of the surfaces do not change \n", default = .false.)
1489 cs%ML_KhTR_scale = 1.0
1490 if (cs%Diffuse_ML_interior)
then
1491 call get_param(param_file, mdl,
"ML_KHTR_SCALE", cs%ML_KhTR_scale, &
1492 "With Diffuse_ML_interior, the ratio of the truly "//&
1493 "horizontal diffusivity in the mixed layer to the "//&
1494 "epipycnal diffusivity. The valid range is 0 to 1.", &
1495 units=
"nondim", default=1.0)
1498 cs%use_neutral_diffusion = neutral_diffusion_init(time, g, param_file, diag, eos, diabatic_csp, &
1499 cs%neutral_diffusion_CSp )
1500 if (cs%use_neutral_diffusion .and. cs%Diffuse_ML_interior)
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
1501 "USE_NEUTRAL_DIFFUSION and DIFFUSE_ML_TO_INTERIOR are mutually exclusive!")
1502 cs%use_lateral_boundary_diffusion = lateral_boundary_diffusion_init(time, g, param_file, diag, diabatic_csp, &
1503 cs%lateral_boundary_diffusion_CSp)
1504 if (cs%use_neutral_diffusion .and. cs%Diffuse_ML_interior)
call mom_error(fatal,
"MOM_tracer_hor_diff: "// &
1505 "USE_LATERAL_BOUNDARY_DIFFUSION and DIFFUSE_ML_TO_INTERIOR are mutually exclusive!")
1507 call get_param(param_file, mdl,
"DEBUG", cs%debug, default=.false.)
1509 id_clock_diffuse = cpu_clock_id(
'(Ocean diffuse tracer)', grain=clock_module)
1510 id_clock_epimix = cpu_clock_id(
'(Ocean epipycnal diffuse tracer)',grain=clock_module)
1511 id_clock_pass = cpu_clock_id(
'(Ocean tracer halo updates)', grain=clock_routine)
1512 id_clock_sync = cpu_clock_id(
'(Ocean tracer global synch)', grain=clock_routine)
1520 'Epipycnal tracer diffusivity at zonal faces of tracer cell',
'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
1522 'Epipycnal tracer diffusivity at meridional faces of tracer cell',
'm2 s-1', conversion=us%L_to_m**2*us%s_to_T)
1524 'Epipycnal tracer diffusivity at tracer cell center',
'm2 s-1', conversion=us%L_to_m**2*us%s_to_T, &
1525 cmor_field_name=
'diftrelo', &
1526 cmor_standard_name=
'ocean_tracer_epineutral_laplacian_diffusivity', &
1527 cmor_long_name =
'Ocean Tracer Epineutral Laplacian Diffusivity')
1530 'Epipycnal tracer diffusivity operator at zonal faces of tracer cell',
'm2', conversion=us%L_to_m**2)
1532 'Epipycnal tracer diffusivity operator at meridional faces of tracer cell',
'm2', conversion=us%L_to_m**2)
1533 if (cs%check_diffusive_CFL)
then
1535 'Grid CFL number for lateral/neutral tracer diffusion',
'nondim')
1544 call neutral_diffusion_end(cs%neutral_diffusion_CSp)
1545 if (
associated(cs))
deallocate(cs)