6 use mom_cpu_clock,
only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
12 use mom_open_boundary,
only : obc_direction_e, obc_direction_w, obc_direction_n, obc_direction_s
17 implicit none ;
private 19 #include <MOM_memory.h> 21 public continuity_ppm, continuity_ppm_init, continuity_ppm_end, continuity_ppm_stencil
24 integer :: id_clock_update, id_clock_correct
47 real :: cfl_limit_adjust
48 logical :: aggress_adjust
54 logical :: better_iter
57 logical :: use_visc_rem_max
59 logical :: marginal_faces
68 integer :: ish, ieh, jsh, jeh
76 subroutine continuity_ppm(u, v, hin, h, uh, vh, dt, G, GV, US, CS, uhbt, vhbt, OBC, &
77 visc_rem_u, visc_rem_v, u_cor, v_cor, BT_cont)
80 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
82 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
84 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
86 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
88 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
90 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
92 real,
intent(in) :: dt
95 real,
dimension(SZIB_(G),SZJ_(G)), &
96 optional,
intent(in) :: uhbt
98 real,
dimension(SZI_(G),SZJB_(G)), &
99 optional,
intent(in) :: vhbt
102 optional,
pointer :: obc
103 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
104 optional,
intent(in) :: visc_rem_u
110 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
111 optional,
intent(in) :: visc_rem_v
117 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
118 optional,
intent(out) :: u_cor
120 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
121 optional,
intent(out) :: v_cor
130 integer :: is, ie, js, je, nz, stencil
134 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
136 h_min = gv%Angstrom_H
138 if (.not.
associated(cs))
call mom_error(fatal, &
139 "MOM_continuity_PPM: Module must be initialized before it is used.")
140 x_first = (mod(g%first_direction,2) == 0)
142 if (
present(visc_rem_u) .neqv.
present(visc_rem_v))
call mom_error(fatal, &
143 "MOM_continuity_PPM: Either both visc_rem_u and visc_rem_v or neither"// &
144 " one must be present in call to continuity_PPM.")
146 stencil = 3 ;
if (cs%simple_2nd) stencil = 2 ;
if (cs%upwind_1st) stencil = 1
150 lb%ish = g%isc ; lb%ieh = g%iec
151 lb%jsh = g%jsc-stencil ; lb%jeh = g%jec+stencil
152 call zonal_mass_flux(u, hin, uh, dt, g, gv, us, cs, lb, uhbt, obc, visc_rem_u, u_cor, bt_cont)
154 call cpu_clock_begin(id_clock_update)
156 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
157 h(i,j,k) = hin(i,j,k) - dt * g%IareaT(i,j) * (uh(i,j,k) - uh(i-1,j,k))
160 enddo ;
enddo ;
enddo 161 call cpu_clock_end(id_clock_update)
163 lb%ish = g%isc ; lb%ieh = g%iec ; lb%jsh = g%jsc ; lb%jeh = g%jec
167 call meridional_mass_flux(v, h, vh, dt, g, gv, us, cs, lb, vhbt, obc, visc_rem_v, v_cor, bt_cont)
169 call cpu_clock_begin(id_clock_update)
171 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
172 h(i,j,k) = h(i,j,k) - dt * g%IareaT(i,j) * (vh(i,j,k) - vh(i,j-1,k))
174 if (h(i,j,k) < h_min) h(i,j,k) = h_min
175 enddo ;
enddo ;
enddo 176 call cpu_clock_end(id_clock_update)
180 lb%ish = g%isc-stencil ; lb%ieh = g%iec+stencil
181 lb%jsh = g%jsc ; lb%jeh = g%jec
183 call meridional_mass_flux(v, hin, vh, dt, g, gv, us, cs, lb, vhbt, obc, visc_rem_v, v_cor, bt_cont)
185 call cpu_clock_begin(id_clock_update)
187 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
188 h(i,j,k) = hin(i,j,k) - dt * g%IareaT(i,j) * (vh(i,j,k) - vh(i,j-1,k))
189 enddo ;
enddo ;
enddo 190 call cpu_clock_end(id_clock_update)
194 lb%ish = g%isc ; lb%ieh = g%iec ; lb%jsh = g%jsc ; lb%jeh = g%jec
195 call zonal_mass_flux(u, h, uh, dt, g, gv, us, cs, lb, uhbt, obc, visc_rem_u, u_cor, bt_cont)
197 call cpu_clock_begin(id_clock_update)
199 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
200 h(i,j,k) = h(i,j,k) - dt * g%IareaT(i,j) * (uh(i,j,k) - uh(i-1,j,k))
202 if (h(i,j,k) < h_min) h(i,j,k) = h_min
203 enddo ;
enddo ;
enddo 204 call cpu_clock_end(id_clock_update)
208 end subroutine continuity_ppm
211 subroutine zonal_mass_flux(u, h_in, uh, dt, G, GV, US, CS, LB, uhbt, OBC, &
212 visc_rem_u, u_cor, BT_cont)
215 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
217 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
219 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
222 real,
intent(in) :: dt
227 optional,
pointer :: OBC
228 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
229 optional,
intent(in) :: visc_rem_u
234 real,
dimension(SZIB_(G),SZJ_(G)), &
235 optional,
intent(in) :: uhbt
237 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
238 optional,
intent(out) :: u_cor
245 real,
dimension(SZIB_(G),SZK_(G)) :: duhdu
246 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_L, h_R
247 real,
dimension(SZIB_(G)) :: &
254 logical,
dimension(SZIB_(G)) :: do_I
255 real,
dimension(SZIB_(G),SZK_(G)) :: &
257 real,
dimension(SZIB_(G)) :: FAuI
265 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
267 logical :: local_specified_BC, use_visc_rem, set_BT_cont, any_simple_OBC
268 logical :: local_Flather_OBC, local_open_BC, is_simple
271 use_visc_rem =
present(visc_rem_u)
272 local_specified_bc = .false. ; set_bt_cont = .false. ; local_flather_obc = .false.
273 local_open_bc = .false.
274 if (
present(bt_cont)) set_bt_cont = (
associated(bt_cont))
275 if (
present(obc))
then ;
if (
associated(obc))
then 276 local_specified_bc = obc%specified_u_BCs_exist_globally
277 local_flather_obc = obc%Flather_u_BCs_exist_globally
278 local_open_bc = obc%open_u_BCs_exist_globally
280 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
282 cfl_dt = cs%CFL_limit_adjust / dt
284 if (cs%aggress_adjust) cfl_dt = i_dt
286 call cpu_clock_begin(id_clock_update)
290 if (cs%upwind_1st)
then 291 do j=jsh,jeh ;
do i=ish-1,ieh+1
292 h_l(i,j,k) = h_in(i,j,k) ; h_r(i,j,k) = h_in(i,j,k)
295 call ppm_reconstruction_x(h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), g, lb, &
296 2.0*gv%Angstrom_H, cs%monotonic, simple_2nd=cs%simple_2nd, obc=obc)
298 do i=ish-1,ieh ; visc_rem(i,k) = 1.0 ;
enddo 300 call cpu_clock_end(id_clock_update)
302 call cpu_clock_begin(id_clock_correct)
311 do i=ish-1,ieh ; do_i(i) = .true. ; visc_rem_max(i) = 0.0 ;
enddo 314 if (use_visc_rem)
then ;
do i=ish-1,ieh
315 visc_rem(i,k) = visc_rem_u(i,j,k)
316 visc_rem_max(i) = max(visc_rem_max(i), visc_rem(i,k))
318 call zonal_flux_layer(u(:,j,k), h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), &
319 uh(:,j,k), duhdu(:,k), visc_rem(:,k), &
320 dt, g, us, j, ish, ieh, do_i, cs%vol_CFL, obc)
321 if (local_specified_bc)
then 323 l_seg = obc%segnum_u(i,j)
325 if (l_seg /= obc_none)
then 326 if (obc%segment(l_seg)%specified) &
327 uh(i,j,k) = obc%segment(l_seg)%normal_trans(i,j,k)
333 if ((.not.use_visc_rem).or.(.not.cs%use_visc_rem_max))
then ;
do i=ish-1,ieh
334 visc_rem_max(i) = 1.0
337 if (
present(uhbt) .or. set_bt_cont)
then 342 if (visc_rem_max(i) > 0.0) i_vrm = 1.0 / visc_rem_max(i)
344 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
345 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
346 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif 347 du_max_cfl(i) = 2.0* (cfl_dt * dx_w) * i_vrm
348 du_min_cfl(i) = -2.0 * (cfl_dt * dx_e) * i_vrm
349 uh_tot_0(i) = 0.0 ; duhdu_tot_0(i) = 0.0
351 do k=1,nz ;
do i=ish-1,ieh
352 duhdu_tot_0(i) = duhdu_tot_0(i) + duhdu(i,k)
353 uh_tot_0(i) = uh_tot_0(i) + uh(i,j,k)
355 if (use_visc_rem)
then 356 if (cs%aggress_adjust)
then 357 do k=1,nz ;
do i=ish-1,ieh
359 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
360 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
361 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif 363 du_lim = 0.499*((dx_w*i_dt - u(i,j,k)) + min(0.0,u(i-1,j,k)))
364 if (du_max_cfl(i) * visc_rem(i,k) > du_lim) &
365 du_max_cfl(i) = du_lim / visc_rem(i,k)
367 du_lim = 0.499*((-dx_e*i_dt - u(i,j,k)) + max(0.0,u(i+1,j,k)))
368 if (du_min_cfl(i) * visc_rem(i,k) < du_lim) &
369 du_min_cfl(i) = du_lim / visc_rem(i,k)
372 do k=1,nz ;
do i=ish-1,ieh
374 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
375 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
376 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif 378 if (du_max_cfl(i) * visc_rem(i,k) > dx_w*cfl_dt - u(i,j,k)) &
379 du_max_cfl(i) = (dx_w*cfl_dt - u(i,j,k)) / visc_rem(i,k)
380 if (du_min_cfl(i) * visc_rem(i,k) < -dx_e*cfl_dt - u(i,j,k)) &
381 du_min_cfl(i) = -(dx_e*cfl_dt + u(i,j,k)) / visc_rem(i,k)
385 if (cs%aggress_adjust)
then 386 do k=1,nz ;
do i=ish-1,ieh
388 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
389 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
390 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif 392 du_max_cfl(i) = min(du_max_cfl(i), 0.499 * &
393 ((dx_w*i_dt - u(i,j,k)) + min(0.0,u(i-1,j,k))) )
394 du_min_cfl(i) = max(du_min_cfl(i), 0.499 * &
395 ((-dx_e*i_dt - u(i,j,k)) + max(0.0,u(i+1,j,k))) )
398 do k=1,nz ;
do i=ish-1,ieh
400 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
401 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
402 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif 404 du_max_cfl(i) = min(du_max_cfl(i), dx_w*cfl_dt - u(i,j,k))
405 du_min_cfl(i) = max(du_min_cfl(i), -(dx_e*cfl_dt + u(i,j,k)))
410 du_max_cfl(i) = max(du_max_cfl(i),0.0)
411 du_min_cfl(i) = min(du_min_cfl(i),0.0)
414 any_simple_obc = .false.
415 if (
present(uhbt) .or. set_bt_cont)
then 416 if (local_specified_bc .or. local_flather_obc)
then ;
do i=ish-1,ieh
417 l_seg = obc%segnum_u(i,j)
421 if (l_seg /= obc_none) &
422 is_simple = obc%segment(l_seg)%specified
423 do_i(i) = .not. (l_seg /= obc_none .and. is_simple)
424 any_simple_obc = any_simple_obc .or. is_simple
425 enddo ;
else ;
do i=ish-1,ieh
430 if (
present(uhbt))
then 431 call zonal_flux_adjust(u, h_in, h_l, h_r, uhbt(:,j), uh_tot_0, duhdu_tot_0, du, &
432 du_max_cfl, du_min_cfl, dt, g, us, cs, visc_rem, &
433 j, ish, ieh, do_i, .true., uh, obc=obc)
435 if (
present(u_cor))
then ;
do k=1,nz
436 do i=ish-1,ieh ; u_cor(i,j,k) = u(i,j,k) + du(i) * visc_rem(i,k) ;
enddo 437 if (local_specified_bc)
then ;
do i=ish-1,ieh
438 l_seg = obc%segnum_u(i,j)
440 if (l_seg /= obc_none)
then 441 if (obc%segment(l_seg)%specified) &
442 u_cor(i,j,k) = obc%segment(l_seg)%normal_vel(i,j,k)
449 if (set_bt_cont)
then 450 call set_zonal_bt_cont(u, h_in, h_l, h_r, bt_cont, uh_tot_0, duhdu_tot_0,&
451 du_max_cfl, du_min_cfl, dt, g, us, cs, visc_rem, &
452 visc_rem_max, j, ish, ieh, do_i)
453 if (any_simple_obc)
then 455 l_seg = obc%segnum_u(i,j)
458 if (l_seg /= obc_none) &
459 do_i(i) = obc%segment(l_seg)%specified
461 if (do_i(i)) faui(i) = gv%H_subroundoff*g%dy_Cu(i,j)
464 do k=1,nz ;
do i=ish-1,ieh ;
if (do_i(i))
then 465 if ((abs(obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)) > 0.0) .and. &
466 (obc%segment(obc%segnum_u(i,j))%specified)) &
467 faui(i) = faui(i) + obc%segment(obc%segnum_u(i,j))%normal_trans(i,j,k) / &
468 obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)
469 endif ;
enddo ;
enddo 470 do i=ish-1,ieh ;
if (do_i(i))
then 471 bt_cont%FA_u_W0(i,j) = faui(i) ; bt_cont%FA_u_E0(i,j) = faui(i)
472 bt_cont%FA_u_WW(i,j) = faui(i) ; bt_cont%FA_u_EE(i,j) = faui(i)
473 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
482 if (local_open_bc .and. set_bt_cont)
then 483 do n = 1, obc%number_of_segments
484 if (obc%segment(n)%open .and. obc%segment(n)%is_E_or_W)
then 485 i = obc%segment(n)%HI%IsdB
486 if (obc%segment(n)%direction == obc_direction_e)
then 487 do j = obc%segment(n)%HI%Jsd, obc%segment(n)%HI%Jed
489 do k=1,nz ; fa_u = fa_u + h_in(i,j,k)*g%dy_Cu(i,j) ;
enddo 490 bt_cont%FA_u_W0(i,j) = fa_u ; bt_cont%FA_u_E0(i,j) = fa_u
491 bt_cont%FA_u_WW(i,j) = fa_u ; bt_cont%FA_u_EE(i,j) = fa_u
492 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
495 do j = obc%segment(n)%HI%Jsd, obc%segment(n)%HI%Jed
497 do k=1,nz ; fa_u = fa_u + h_in(i+1,j,k)*g%dy_Cu(i,j) ;
enddo 498 bt_cont%FA_u_W0(i,j) = fa_u ; bt_cont%FA_u_E0(i,j) = fa_u
499 bt_cont%FA_u_WW(i,j) = fa_u ; bt_cont%FA_u_EE(i,j) = fa_u
500 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
506 call cpu_clock_end(id_clock_correct)
508 if (set_bt_cont)
then ;
if (
allocated(bt_cont%h_u))
then 509 if (
present(u_cor))
then 510 call zonal_face_thickness(u_cor, h_in, h_l, h_r, bt_cont%h_u, dt, g, us, lb, &
511 cs%vol_CFL, cs%marginal_faces, visc_rem_u, obc)
513 call zonal_face_thickness(u, h_in, h_l, h_r, bt_cont%h_u, dt, g, us, lb, &
514 cs%vol_CFL, cs%marginal_faces, visc_rem_u, obc)
518 end subroutine zonal_mass_flux
521 subroutine zonal_flux_layer(u, h, h_L, h_R, uh, duhdu, visc_rem, dt, G, US, j, &
522 ish, ieh, do_I, vol_CFL, OBC)
524 real,
dimension(SZIB_(G)),
intent(in) :: u
525 real,
dimension(SZIB_(G)),
intent(in) :: visc_rem
530 real,
dimension(SZI_(G)),
intent(in) :: h
531 real,
dimension(SZI_(G)),
intent(in) :: h_L
532 real,
dimension(SZI_(G)),
intent(in) :: h_R
533 real,
dimension(SZIB_(G)),
intent(inout) :: uh
535 real,
dimension(SZIB_(G)),
intent(inout) :: duhdu
537 real,
intent(in) :: dt
539 integer,
intent(in) :: j
540 integer,
intent(in) :: ish
541 integer,
intent(in) :: ieh
542 logical,
dimension(SZIB_(G)),
intent(in) :: do_I
543 logical,
intent(in) :: vol_CFL
553 logical :: local_open_BC
555 local_open_bc = .false.
556 if (
present(obc))
then ;
if (
associated(obc))
then 557 local_open_bc = obc%open_u_BCs_exist_globally
560 do i=ish-1,ieh ;
if (do_i(i))
then 563 if (vol_cfl)
then ; cfl = (u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
564 else ; cfl = u(i) * dt * g%IdxT(i,j) ;
endif 565 curv_3 = h_l(i) + h_r(i) - 2.0*h(i)
566 uh(i) = g%dy_Cu(i,j) * u(i) * &
567 (h_r(i) + cfl * (0.5*(h_l(i) - h_r(i)) + curv_3*(cfl - 1.5)))
568 h_marg = h_r(i) + cfl * ((h_l(i) - h_r(i)) + 3.0*curv_3*(cfl - 1.0))
569 elseif (u(i) < 0.0)
then 570 if (vol_cfl)
then ; cfl = (-u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
571 else ; cfl = -u(i) * dt * g%IdxT(i+1,j) ;
endif 572 curv_3 = h_l(i+1) + h_r(i+1) - 2.0*h(i+1)
573 uh(i) = g%dy_Cu(i,j) * u(i) * &
574 (h_l(i+1) + cfl * (0.5*(h_r(i+1)-h_l(i+1)) + curv_3*(cfl - 1.5)))
575 h_marg = h_l(i+1) + cfl * ((h_r(i+1)-h_l(i+1)) + 3.0*curv_3*(cfl - 1.0))
578 h_marg = 0.5 * (h_l(i+1) + h_r(i))
580 duhdu(i) = g%dy_Cu(i,j) * h_marg * visc_rem(i)
583 if (local_open_bc)
then 584 do i=ish-1,ieh ;
if (do_i(i))
then 585 l_seg = obc%segnum_u(i,j)
587 if (l_seg /= obc_none)
then 588 if (obc%segment(l_seg)%open)
then 589 if (obc%segment(l_seg)%direction == obc_direction_e)
then 590 uh(i) = g%dy_Cu(i,j) * u(i) * h(i)
591 duhdu(i) = g%dy_Cu(i,j) * h(i) * visc_rem(i)
593 uh(i) = g%dy_Cu(i,j) * u(i) * h(i+1)
594 duhdu(i) = g%dy_Cu(i,j) * h(i+1) * visc_rem(i)
600 end subroutine zonal_flux_layer
603 subroutine zonal_face_thickness(u, h, h_L, h_R, h_u, dt, G, US, LB, vol_CFL, &
604 marginal, visc_rem_u, OBC)
606 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
607 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
609 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
611 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
613 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h_u
614 real,
intent(in) :: dt
617 logical,
intent(in) :: vol_CFL
619 logical,
intent(in) :: marginal
621 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
622 optional,
intent(in) :: visc_rem_u
635 logical :: local_open_BC
636 integer :: i, j, k, ish, ieh, jsh, jeh, nz, n
637 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
640 do k=1,nz ;
do j=jsh,jeh ;
do i=ish-1,ieh
641 if (u(i,j,k) > 0.0)
then 642 if (vol_cfl)
then ; cfl = (u(i,j,k) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
643 else ; cfl = u(i,j,k) * dt * g%IdxT(i,j) ;
endif 644 curv_3 = h_l(i,j,k) + h_r(i,j,k) - 2.0*h(i,j,k)
645 h_avg = h_r(i,j,k) + cfl * (0.5*(h_l(i,j,k) - h_r(i,j,k)) + curv_3*(cfl - 1.5))
646 h_marg = h_r(i,j,k) + cfl * ((h_l(i,j,k) - h_r(i,j,k)) + 3.0*curv_3*(cfl - 1.0))
647 elseif (u(i,j,k) < 0.0)
then 648 if (vol_cfl)
then ; cfl = (-u(i,j,k)*dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
649 else ; cfl = -u(i,j,k) * dt * g%IdxT(i+1,j) ;
endif 650 curv_3 = h_l(i+1,j,k) + h_r(i+1,j,k) - 2.0*h(i+1,j,k)
651 h_avg = h_l(i+1,j,k) + cfl * (0.5*(h_r(i+1,j,k)-h_l(i+1,j,k)) + curv_3*(cfl - 1.5))
652 h_marg = h_l(i+1,j,k) + cfl * ((h_r(i+1,j,k)-h_l(i+1,j,k)) + &
653 3.0*curv_3*(cfl - 1.0))
655 h_avg = 0.5 * (h_l(i+1,j,k) + h_r(i,j,k))
658 h_marg = 0.5 * (h_l(i+1,j,k) + h_r(i,j,k))
663 if (marginal)
then ; h_u(i,j,k) = h_marg
664 else ; h_u(i,j,k) = h_avg ;
endif 665 enddo ;
enddo ;
enddo 666 if (
present(visc_rem_u))
then 668 do k=1,nz ;
do j=jsh,jeh ;
do i=ish-1,ieh
669 h_u(i,j,k) = h_u(i,j,k) * visc_rem_u(i,j,k)
670 enddo ;
enddo ;
enddo 673 local_open_bc = .false.
674 if (
present(obc))
then ;
if (
associated(obc))
then 675 local_open_bc = obc%open_u_BCs_exist_globally
677 if (local_open_bc)
then 678 do n = 1, obc%number_of_segments
679 if (obc%segment(n)%open .and. obc%segment(n)%is_E_or_W)
then 680 i = obc%segment(n)%HI%IsdB
681 if (obc%segment(n)%direction == obc_direction_e)
then 682 if (
present(visc_rem_u))
then ;
do k=1,nz
683 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
684 h_u(i,j,k) = h(i,j,k) * visc_rem_u(i,j,k)
686 enddo ;
else ;
do k=1,nz
687 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
688 h_u(i,j,k) = h(i,j,k)
692 if (
present(visc_rem_u))
then ;
do k=1,nz
693 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
694 h_u(i,j,k) = h(i+1,j,k) * visc_rem_u(i,j,k)
696 enddo ;
else ;
do k=1,nz
697 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
698 h_u(i,j,k) = h(i+1,j,k)
706 end subroutine zonal_face_thickness
710 subroutine zonal_flux_adjust(u, h_in, h_L, h_R, uhbt, uh_tot_0, duhdu_tot_0, &
711 du, du_max_CFL, du_min_CFL, dt, G, US, CS, visc_rem, &
712 j, ish, ieh, do_I_in, full_precision, uh_3d, OBC)
714 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
715 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
717 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
719 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
721 real,
dimension(SZIB_(G),SZK_(G)),
intent(in) :: visc_rem
726 real,
dimension(SZIB_(G)),
optional,
intent(in) :: uhbt
729 real,
dimension(SZIB_(G)),
intent(in) :: du_max_CFL
731 real,
dimension(SZIB_(G)),
intent(in) :: du_min_CFL
733 real,
dimension(SZIB_(G)),
intent(in) :: uh_tot_0
735 real,
dimension(SZIB_(G)),
intent(in) :: duhdu_tot_0
737 real,
dimension(SZIB_(G)),
intent(out) :: du
739 real,
intent(in) :: dt
742 integer,
intent(in) :: j
743 integer,
intent(in) :: ish
744 integer,
intent(in) :: ieh
745 logical,
dimension(SZIB_(G)),
intent(in) :: do_I_in
747 logical,
optional,
intent(in) :: full_precision
750 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
optional,
intent(inout) :: uh_3d
754 real,
dimension(SZIB_(G),SZK_(G)) :: &
757 real,
dimension(SZIB_(G)) :: &
768 integer :: i, k, nz, itt, max_itts = 20
769 logical :: full_prec, domore, do_I(SZIB_(G))
772 full_prec = .true. ;
if (
present(full_precision)) full_prec = full_precision
774 uh_aux(:,:) = 0.0 ; duhdu(:,:) = 0.0
776 if (
present(uh_3d))
then ;
do k=1,nz ;
do i=ish-1,ieh
777 uh_aux(i,k) = uh_3d(i,j,k)
778 enddo ;
enddo ;
endif 781 du(i) = 0.0 ; do_i(i) = do_i_in(i)
782 du_max(i) = du_max_cfl(i) ; du_min(i) = du_min_cfl(i)
783 uh_err(i) = uh_tot_0(i) - uhbt(i) ; duhdu_tot(i) = duhdu_tot_0(i)
784 uh_err_best(i) = abs(uh_err(i))
790 case (:1) ; tol_eta = 1e-6 * cs%tol_eta
791 case (2) ; tol_eta = 1e-4 * cs%tol_eta
792 case (3) ; tol_eta = 1e-2 * cs%tol_eta
793 case default ; tol_eta = cs%tol_eta
796 tol_eta = cs%tol_eta_aux ;
if (itt<=1) tol_eta = 1e-6 * cs%tol_eta_aux
801 if (uh_err(i) > 0.0)
then ; du_max(i) = du(i)
802 elseif (uh_err(i) < 0.0)
then ; du_min(i) = du(i)
803 else ; do_i(i) = .false. ;
endif 806 do i=ish-1,ieh ;
if (do_i(i))
then 807 if ((dt * min(g%IareaT(i,j),g%IareaT(i+1,j))*abs(uh_err(i)) > tol_eta) .or. &
808 (cs%better_iter .and. ((abs(uh_err(i)) > tol_vel * duhdu_tot(i)) .or. &
809 (abs(uh_err(i)) > uh_err_best(i))) ))
then 813 ddu = -uh_err(i) / duhdu_tot(i)
816 if (abs(ddu) < 1.0e-15*abs(du(i)))
then 818 elseif (ddu > 0.0)
then 819 if (du(i) >= du_max(i))
then 820 du(i) = 0.5*(du_prev + du_max(i))
821 if (du_max(i) - du_prev < 1.0e-15*abs(du(i))) do_i(i) = .false.
824 if (du(i) <= du_min(i))
then 825 du(i) = 0.5*(du_prev + du_min(i))
826 if (du_prev - du_min(i) < 1.0e-15*abs(du(i))) do_i(i) = .false.
831 du(i) = du(i) - uh_err(i) / duhdu_tot(i)
832 if ((du(i) >= du_max(i)) .or. (du(i) <= du_min(i))) &
833 du(i) = 0.5*(du_max(i) + du_min(i))
835 if (do_i(i)) domore = .true.
840 if (.not.domore)
exit 842 if ((itt < max_itts) .or.
present(uh_3d))
then ;
do k=1,nz
843 do i=ish-1,ieh ; u_new(i) = u(i,j,k) + du(i) * visc_rem(i,k) ;
enddo 844 call zonal_flux_layer(u_new, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), &
845 uh_aux(:,k), duhdu(:,k), visc_rem(:,k), &
846 dt, g, us, j, ish, ieh, do_i, cs%vol_CFL, obc)
849 if (itt < max_itts)
then 851 uh_err(i) = -uhbt(i) ; duhdu_tot(i) = 0.0
853 do k=1,nz ;
do i=ish-1,ieh
854 uh_err(i) = uh_err(i) + uh_aux(i,k)
855 duhdu_tot(i) = duhdu_tot(i) + duhdu(i,k)
858 uh_err_best(i) = min(uh_err_best(i), abs(uh_err(i)))
866 if (
present(uh_3d))
then ;
do k=1,nz ;
do i=ish-1,ieh
867 uh_3d(i,j,k) = uh_aux(i,k)
868 enddo ;
enddo ;
endif 870 end subroutine zonal_flux_adjust
874 subroutine set_zonal_bt_cont(u, h_in, h_L, h_R, BT_cont, uh_tot_0, duhdu_tot_0, &
875 du_max_CFL, du_min_CFL, dt, G, US, CS, visc_rem, &
876 visc_rem_max, j, ish, ieh, do_I)
878 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
879 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
881 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
883 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
887 real,
dimension(SZIB_(G)),
intent(in) :: uh_tot_0
889 real,
dimension(SZIB_(G)),
intent(in) :: duhdu_tot_0
891 real,
dimension(SZIB_(G)),
intent(in) :: du_max_CFL
893 real,
dimension(SZIB_(G)),
intent(in) :: du_min_CFL
895 real,
intent(in) :: dt
898 real,
dimension(SZIB_(G),SZK_(G)),
intent(in) :: visc_rem
903 real,
dimension(SZIB_(G)),
intent(in) :: visc_rem_max
904 integer,
intent(in) :: j
905 integer,
intent(in) :: ish
906 integer,
intent(in) :: ieh
907 logical,
dimension(SZIB_(G)),
intent(in) :: do_I
910 real,
dimension(SZIB_(G)) :: &
943 nz = g%ke ; idt = 1.0 / dt
944 min_visc_rem = 0.1 ; cfl_min = 1e-6
947 do i=ish-1,ieh ; zeros(i) = 0.0 ;
enddo 948 call zonal_flux_adjust(u, h_in, h_l, h_r, zeros, uh_tot_0, duhdu_tot_0, du0, &
949 du_max_cfl, du_min_cfl, dt, g, us, cs, visc_rem, &
950 j, ish, ieh, do_i, .true.)
957 if (do_i(i)) domore = .true.
958 du_cfl(i) = (cfl_min * idt) * g%dxCu(i,j)
959 dur(i) = min(0.0,du0(i) - du_cfl(i))
960 dul(i) = max(0.0,du0(i) + du_cfl(i))
961 famt_l(i) = 0.0 ; famt_r(i) = 0.0 ; famt_0(i) = 0.0
962 uhtot_l(i) = 0.0 ; uhtot_r(i) = 0.0
965 if (.not.domore)
then 966 do k=1,nz ;
do i=ish-1,ieh
967 bt_cont%FA_u_W0(i,j) = 0.0 ; bt_cont%FA_u_WW(i,j) = 0.0
968 bt_cont%FA_u_E0(i,j) = 0.0 ; bt_cont%FA_u_EE(i,j) = 0.0
969 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
974 do k=1,nz ;
do i=ish-1,ieh ;
if (do_i(i))
then 975 visc_rem_lim = max(visc_rem(i,k), min_visc_rem*visc_rem_max(i))
976 if (visc_rem_lim > 0.0)
then 977 if (u(i,j,k) + dur(i)*visc_rem_lim > -du_cfl(i)*visc_rem(i,k)) &
978 dur(i) = -(u(i,j,k) + du_cfl(i)*visc_rem(i,k)) / visc_rem_lim
979 if (u(i,j,k) + dul(i)*visc_rem_lim < du_cfl(i)*visc_rem(i,k)) &
980 dul(i) = -(u(i,j,k) - du_cfl(i)*visc_rem(i,k)) / visc_rem_lim
982 endif ;
enddo ;
enddo 985 do i=ish-1,ieh ;
if (do_i(i))
then 986 u_l(i) = u(i,j,k) + dul(i) * visc_rem(i,k)
987 u_r(i) = u(i,j,k) + dur(i) * visc_rem(i,k)
988 u_0(i) = u(i,j,k) + du0(i) * visc_rem(i,k)
990 call zonal_flux_layer(u_0, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_0, duhdu_0, &
991 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
992 call zonal_flux_layer(u_l, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_l, duhdu_l, &
993 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
994 call zonal_flux_layer(u_r, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_r, duhdu_r, &
995 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
996 do i=ish-1,ieh ;
if (do_i(i))
then 997 famt_0(i) = famt_0(i) + duhdu_0(i)
998 famt_l(i) = famt_l(i) + duhdu_l(i)
999 famt_r(i) = famt_r(i) + duhdu_r(i)
1000 uhtot_l(i) = uhtot_l(i) + uh_l(i)
1001 uhtot_r(i) = uhtot_r(i) + uh_r(i)
1004 do i=ish-1,ieh ;
if (do_i(i))
then 1005 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1006 if ((dul(i) - du0(i)) /= 0.0) &
1007 fa_avg = uhtot_l(i) / (dul(i) - du0(i))
1008 if (fa_avg > max(fa_0, famt_l(i)))
then ; fa_avg = max(fa_0, famt_l(i))
1009 elseif (fa_avg < min(fa_0, famt_l(i)))
then ; fa_0 = fa_avg ;
endif 1011 bt_cont%FA_u_W0(i,j) = fa_0 ; bt_cont%FA_u_WW(i,j) = famt_l(i)
1012 if (abs(fa_0-famt_l(i)) <= 1e-12*fa_0)
then ; bt_cont%uBT_WW(i,j) = 0.0 ;
else 1013 bt_cont%uBT_WW(i,j) = (1.5 * (dul(i) - du0(i))) * &
1014 ((famt_l(i) - fa_avg) / (famt_l(i) - fa_0))
1017 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1018 if ((dur(i) - du0(i)) /= 0.0) &
1019 fa_avg = uhtot_r(i) / (dur(i) - du0(i))
1020 if (fa_avg > max(fa_0, famt_r(i)))
then ; fa_avg = max(fa_0, famt_r(i))
1021 elseif (fa_avg < min(fa_0, famt_r(i)))
then ; fa_0 = fa_avg ;
endif 1023 bt_cont%FA_u_E0(i,j) = fa_0 ; bt_cont%FA_u_EE(i,j) = famt_r(i)
1024 if (abs(famt_r(i) - fa_0) <= 1e-12*fa_0)
then ; bt_cont%uBT_EE(i,j) = 0.0 ;
else 1025 bt_cont%uBT_EE(i,j) = (1.5 * (dur(i) - du0(i))) * &
1026 ((famt_r(i) - fa_avg) / (famt_r(i) - fa_0))
1029 bt_cont%FA_u_W0(i,j) = 0.0 ; bt_cont%FA_u_WW(i,j) = 0.0
1030 bt_cont%FA_u_E0(i,j) = 0.0 ; bt_cont%FA_u_EE(i,j) = 0.0
1031 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
1034 end subroutine set_zonal_bt_cont
1037 subroutine meridional_mass_flux(v, h_in, vh, dt, G, GV, US, CS, LB, vhbt, OBC, &
1038 visc_rem_v, v_cor, BT_cont)
1041 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1042 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
1044 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(out) :: vh
1046 real,
intent(in) :: dt
1052 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1053 optional,
intent(in) :: visc_rem_v
1058 real,
dimension(SZI_(G),SZJB_(G)),
optional,
intent(in) :: vhbt
1060 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1061 optional,
intent(out) :: v_cor
1067 real,
dimension(SZI_(G),SZK_(G)) :: &
1069 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
1071 real,
dimension(SZI_(G)) :: &
1078 logical,
dimension(SZI_(G)) :: do_I
1079 real,
dimension(SZI_(G)) :: FAvi
1081 real,
dimension(SZI_(G),SZK_(G)) :: &
1089 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
1091 logical :: local_specified_BC, use_visc_rem, set_BT_cont, any_simple_OBC
1092 logical :: local_Flather_OBC, is_simple, local_open_BC
1095 use_visc_rem =
present(visc_rem_v)
1096 local_specified_bc = .false. ; set_bt_cont = .false. ; local_flather_obc = .false.
1097 local_open_bc = .false.
1098 if (
present(bt_cont)) set_bt_cont = (
associated(bt_cont))
1099 if (
present(obc))
then ;
if (
associated(obc))
then ;
if (obc%OBC_pe)
then 1100 local_specified_bc = obc%specified_v_BCs_exist_globally
1101 local_flather_obc = obc%Flather_v_BCs_exist_globally
1102 local_open_bc = obc%open_v_BCs_exist_globally
1103 endif ;
endif ;
endif 1104 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
1106 cfl_dt = cs%CFL_limit_adjust / dt
1108 if (cs%aggress_adjust) cfl_dt = i_dt
1110 call cpu_clock_begin(id_clock_update)
1114 if (cs%upwind_1st)
then 1115 do j=jsh-1,jeh+1 ;
do i=ish,ieh
1116 h_l(i,j,k) = h_in(i,j,k) ; h_r(i,j,k) = h_in(i,j,k)
1119 call ppm_reconstruction_y(h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), g, lb, &
1120 2.0*gv%Angstrom_H, cs%monotonic, simple_2nd=cs%simple_2nd, obc=obc)
1122 do i=ish,ieh ; visc_rem(i,k) = 1.0 ;
enddo 1124 call cpu_clock_end(id_clock_update)
1126 call cpu_clock_begin(id_clock_correct)
1135 do i=ish,ieh ; do_i(i) = .true. ; visc_rem_max(i) = 0.0 ;
enddo 1138 if (use_visc_rem)
then ;
do i=ish,ieh
1139 visc_rem(i,k) = visc_rem_v(i,j,k)
1140 visc_rem_max(i) = max(visc_rem_max(i), visc_rem(i,k))
1142 call merid_flux_layer(v(:,j,k), h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), &
1143 vh(:,j,k), dvhdv(:,k), visc_rem(:,k), &
1144 dt, g, us, j, ish, ieh, do_i, cs%vol_CFL, obc)
1145 if (local_specified_bc)
then 1147 l_seg = obc%segnum_v(i,j)
1149 if (l_seg /= obc_none)
then 1150 if (obc%segment(l_seg)%specified) &
1151 vh(i,j,k) = obc%segment(l_seg)%normal_trans(i,j,k)
1156 if ((.not.use_visc_rem) .or. (.not.cs%use_visc_rem_max))
then ;
do i=ish,ieh
1157 visc_rem_max(i) = 1.0
1160 if (
present(vhbt) .or. set_bt_cont)
then 1165 if (visc_rem_max(i) > 0.0) i_vrm = 1.0 / visc_rem_max(i)
1166 if (cs%vol_CFL)
then 1167 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1168 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1169 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif 1170 dv_max_cfl(i) = 2.0 * (cfl_dt * dy_s) * i_vrm
1171 dv_min_cfl(i) = -2.0 * (cfl_dt * dy_n) * i_vrm
1172 vh_tot_0(i) = 0.0 ; dvhdv_tot_0(i) = 0.0
1174 do k=1,nz ;
do i=ish,ieh
1175 dvhdv_tot_0(i) = dvhdv_tot_0(i) + dvhdv(i,k)
1176 vh_tot_0(i) = vh_tot_0(i) + vh(i,j,k)
1179 if (use_visc_rem)
then 1180 if (cs%aggress_adjust)
then 1181 do k=1,nz ;
do i=ish,ieh
1182 if (cs%vol_CFL)
then 1183 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1184 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1185 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif 1186 dv_lim = 0.499*((dy_s*i_dt - v(i,j,k)) + min(0.0,v(i,j-1,k)))
1187 if (dv_max_cfl(i) * visc_rem(i,k) > dv_lim) &
1188 dv_max_cfl(i) = dv_lim / visc_rem(i,k)
1190 dv_lim = 0.499*((-dy_n*cfl_dt - v(i,j,k)) + max(0.0,v(i,j+1,k)))
1191 if (dv_min_cfl(i) * visc_rem(i,k) < dv_lim) &
1192 dv_min_cfl(i) = dv_lim / visc_rem(i,k)
1195 do k=1,nz ;
do i=ish,ieh
1196 if (cs%vol_CFL)
then 1197 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1198 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1199 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif 1200 if (dv_max_cfl(i) * visc_rem(i,k) > dy_s*cfl_dt - v(i,j,k)) &
1201 dv_max_cfl(i) = (dy_s*cfl_dt - v(i,j,k)) / visc_rem(i,k)
1202 if (dv_min_cfl(i) * visc_rem(i,k) < -dy_n*cfl_dt - v(i,j,k)) &
1203 dv_min_cfl(i) = -(dy_n*cfl_dt + v(i,j,k)) / visc_rem(i,k)
1207 if (cs%aggress_adjust)
then 1208 do k=1,nz ;
do i=ish,ieh
1209 if (cs%vol_CFL)
then 1210 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1211 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1212 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif 1213 dv_max_cfl(i) = min(dv_max_cfl(i), 0.499 * &
1214 ((dy_s*i_dt - v(i,j,k)) + min(0.0,v(i,j-1,k))) )
1215 dv_min_cfl(i) = max(dv_min_cfl(i), 0.499 * &
1216 ((-dy_n*i_dt - v(i,j,k)) + max(0.0,v(i,j+1,k))) )
1219 do k=1,nz ;
do i=ish,ieh
1220 if (cs%vol_CFL)
then 1221 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1222 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1223 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif 1224 dv_max_cfl(i) = min(dv_max_cfl(i), dy_s*cfl_dt - v(i,j,k))
1225 dv_min_cfl(i) = max(dv_min_cfl(i), -(dy_n*cfl_dt + v(i,j,k)))
1230 dv_max_cfl(i) = max(dv_max_cfl(i),0.0)
1231 dv_min_cfl(i) = min(dv_min_cfl(i),0.0)
1234 any_simple_obc = .false.
1235 if (
present(vhbt) .or. set_bt_cont)
then 1236 if (local_specified_bc .or. local_flather_obc)
then ;
do i=ish,ieh
1237 l_seg = obc%segnum_v(i,j)
1241 if (l_seg /= obc_none) &
1242 is_simple = obc%segment(l_seg)%specified
1243 do_i(i) = .not.(l_seg /= obc_none .and. is_simple)
1244 any_simple_obc = any_simple_obc .or. is_simple
1245 enddo ;
else ;
do i=ish,ieh
1250 if (
present(vhbt))
then 1251 call meridional_flux_adjust(v, h_in, h_l, h_r, vhbt(:,j), vh_tot_0, dvhdv_tot_0, dv, &
1252 dv_max_cfl, dv_min_cfl, dt, g, us, cs, visc_rem, &
1253 j, ish, ieh, do_i, .true., vh, obc=obc)
1255 if (
present(v_cor))
then ;
do k=1,nz
1256 do i=ish,ieh ; v_cor(i,j,k) = v(i,j,k) + dv(i) * visc_rem(i,k) ;
enddo 1257 if (local_specified_bc)
then ;
do i=ish,ieh
1258 l_seg = obc%segnum_v(i,j)
1260 if (l_seg /= obc_none)
then 1261 if (obc%segment(obc%segnum_v(i,j))%specified) &
1262 v_cor(i,j,k) = obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)
1268 if (set_bt_cont)
then 1269 call set_merid_bt_cont(v, h_in, h_l, h_r, bt_cont, vh_tot_0, dvhdv_tot_0,&
1270 dv_max_cfl, dv_min_cfl, dt, g, us, cs, visc_rem, &
1271 visc_rem_max, j, ish, ieh, do_i)
1272 if (any_simple_obc)
then 1274 l_seg = obc%segnum_v(i,j)
1277 if(l_seg /= obc_none) &
1278 do_i(i) = (obc%segment(l_seg)%specified)
1280 if (do_i(i)) favi(i) = gv%H_subroundoff*g%dx_Cv(i,j)
1283 do k=1,nz ;
do i=ish,ieh ;
if (do_i(i))
then 1284 if ((abs(obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)) > 0.0) .and. &
1285 (obc%segment(obc%segnum_v(i,j))%specified)) &
1286 favi(i) = favi(i) + obc%segment(obc%segnum_v(i,j))%normal_trans(i,j,k) / &
1287 obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)
1288 endif ;
enddo ;
enddo 1289 do i=ish,ieh ;
if (do_i(i))
then 1290 bt_cont%FA_v_S0(i,j) = favi(i) ; bt_cont%FA_v_N0(i,j) = favi(i)
1291 bt_cont%FA_v_SS(i,j) = favi(i) ; bt_cont%FA_v_NN(i,j) = favi(i)
1292 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1301 if (local_open_bc .and. set_bt_cont)
then 1302 do n = 1, obc%number_of_segments
1303 if (obc%segment(n)%open .and. obc%segment(n)%is_N_or_S)
then 1304 j = obc%segment(n)%HI%JsdB
1305 if (obc%segment(n)%direction == obc_direction_n)
then 1306 do i = obc%segment(n)%HI%Isd, obc%segment(n)%HI%Ied
1308 do k=1,nz ; fa_v = fa_v + h_in(i,j,k)*g%dx_Cv(i,j) ;
enddo 1309 bt_cont%FA_v_S0(i,j) = fa_v ; bt_cont%FA_v_N0(i,j) = fa_v
1310 bt_cont%FA_v_SS(i,j) = fa_v ; bt_cont%FA_v_NN(i,j) = fa_v
1311 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1314 do i = obc%segment(n)%HI%Isd, obc%segment(n)%HI%Ied
1316 do k=1,nz ; fa_v = fa_v + h_in(i,j+1,k)*g%dx_Cv(i,j) ;
enddo 1317 bt_cont%FA_v_S0(i,j) = fa_v ; bt_cont%FA_v_N0(i,j) = fa_v
1318 bt_cont%FA_v_SS(i,j) = fa_v ; bt_cont%FA_v_NN(i,j) = fa_v
1319 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1325 call cpu_clock_end(id_clock_correct)
1327 if (set_bt_cont)
then ;
if (
allocated(bt_cont%h_v))
then 1328 if (
present(v_cor))
then 1329 call merid_face_thickness(v_cor, h_in, h_l, h_r, bt_cont%h_v, dt, g, us, lb, &
1330 cs%vol_CFL, cs%marginal_faces, visc_rem_v, obc)
1332 call merid_face_thickness(v, h_in, h_l, h_r, bt_cont%h_v, dt, g, us, lb, &
1333 cs%vol_CFL, cs%marginal_faces, visc_rem_v, obc)
1337 end subroutine meridional_mass_flux
1340 subroutine merid_flux_layer(v, h, h_L, h_R, vh, dvhdv, visc_rem, dt, G, US, J, &
1341 ish, ieh, do_I, vol_CFL, OBC)
1343 real,
dimension(SZI_(G)),
intent(in) :: v
1344 real,
dimension(SZI_(G)),
intent(in) :: visc_rem
1349 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h
1351 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_L
1353 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_R
1355 real,
dimension(SZI_(G)),
intent(inout) :: vh
1357 real,
dimension(SZI_(G)),
intent(inout) :: dvhdv
1359 real,
intent(in) :: dt
1361 integer,
intent(in) :: j
1362 integer,
intent(in) :: ish
1363 integer,
intent(in) :: ieh
1364 logical,
dimension(SZI_(G)),
intent(in) :: do_I
1365 logical,
intent(in) :: vol_CFL
1375 logical :: local_open_BC
1377 local_open_bc = .false.
1378 if (
present(obc))
then ;
if (
associated(obc))
then 1379 local_open_bc = obc%open_v_BCs_exist_globally
1382 do i=ish,ieh ;
if (do_i(i))
then 1383 if (v(i) > 0.0)
then 1384 if (vol_cfl)
then ; cfl = (v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1385 else ; cfl = v(i) * dt * g%IdyT(i,j) ;
endif 1386 curv_3 = h_l(i,j) + h_r(i,j) - 2.0*h(i,j)
1387 vh(i) = g%dx_Cv(i,j) * v(i) * ( h_r(i,j) + cfl * &
1388 (0.5*(h_l(i,j) - h_r(i,j)) + curv_3*(cfl - 1.5)) )
1389 h_marg = h_r(i,j) + cfl * ((h_l(i,j) - h_r(i,j)) + &
1390 3.0*curv_3*(cfl - 1.0))
1391 elseif (v(i) < 0.0)
then 1392 if (vol_cfl)
then ; cfl = (-v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1393 else ; cfl = -v(i) * dt * g%IdyT(i,j+1) ;
endif 1394 curv_3 = h_l(i,j+1) + h_r(i,j+1) - 2.0*h(i,j+1)
1395 vh(i) = g%dx_Cv(i,j) * v(i) * ( h_l(i,j+1) + cfl * &
1396 (0.5*(h_r(i,j+1)-h_l(i,j+1)) + curv_3*(cfl - 1.5)) )
1397 h_marg = h_l(i,j+1) + cfl * ((h_r(i,j+1)-h_l(i,j+1)) + &
1398 3.0*curv_3*(cfl - 1.0))
1401 h_marg = 0.5 * (h_l(i,j+1) + h_r(i,j))
1403 dvhdv(i) = g%dx_Cv(i,j) * h_marg * visc_rem(i)
1406 if (local_open_bc)
then 1407 do i=ish,ieh ;
if (do_i(i))
then 1408 l_seg = obc%segnum_v(i,j)
1410 if (l_seg /= obc_none)
then 1411 if (obc%segment(l_seg)%open)
then 1412 if (obc%segment(l_seg)%direction == obc_direction_n)
then 1413 vh(i) = g%dx_Cv(i,j) * v(i) * h(i,j)
1414 dvhdv(i) = g%dx_Cv(i,j) * h(i,j) * visc_rem(i)
1416 vh(i) = g%dx_Cv(i,j) * v(i) * h(i,j+1)
1417 dvhdv(i) = g%dx_Cv(i,j) * h(i,j+1) * visc_rem(i)
1423 end subroutine merid_flux_layer
1426 subroutine merid_face_thickness(v, h, h_L, h_R, h_v, dt, G, US, LB, vol_CFL, &
1427 marginal, visc_rem_v, OBC)
1429 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1430 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1432 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
1434 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
1436 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: h_v
1438 real,
intent(in) :: dt
1441 logical,
intent(in) :: vol_CFL
1443 logical,
intent(in) :: marginal
1445 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
optional,
intent(in) :: visc_rem_v
1458 logical :: local_open_BC
1459 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
1460 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
1463 do k=1,nz ;
do j=jsh-1,jeh ;
do i=ish,ieh
1464 if (v(i,j,k) > 0.0)
then 1465 if (vol_cfl)
then ; cfl = (v(i,j,k) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1466 else ; cfl = v(i,j,k) * dt * g%IdyT(i,j) ;
endif 1467 curv_3 = h_l(i,j,k) + h_r(i,j,k) - 2.0*h(i,j,k)
1468 h_avg = h_r(i,j,k) + cfl * (0.5*(h_l(i,j,k) - h_r(i,j,k)) + curv_3*(cfl - 1.5))
1469 h_marg = h_r(i,j,k) + cfl * ((h_l(i,j,k) - h_r(i,j,k)) + &
1470 3.0*curv_3*(cfl - 1.0))
1471 elseif (v(i,j,k) < 0.0)
then 1472 if (vol_cfl)
then ; cfl = (-v(i,j,k)*dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1473 else ; cfl = -v(i,j,k) * dt * g%IdyT(i,j+1) ;
endif 1474 curv_3 = h_l(i,j+1,k) + h_r(i,j+1,k) - 2.0*h(i,j+1,k)
1475 h_avg = h_l(i,j+1,k) + cfl * (0.5*(h_r(i,j+1,k)-h_l(i,j+1,k)) + curv_3*(cfl - 1.5))
1476 h_marg = h_l(i,j+1,k) + cfl * ((h_r(i,j+1,k)-h_l(i,j+1,k)) + &
1477 3.0*curv_3*(cfl - 1.0))
1479 h_avg = 0.5 * (h_l(i,j+1,k) + h_r(i,j,k))
1482 h_marg = 0.5 * (h_l(i,j+1,k) + h_r(i,j,k))
1487 if (marginal)
then ; h_v(i,j,k) = h_marg
1488 else ; h_v(i,j,k) = h_avg ;
endif 1489 enddo ;
enddo ;
enddo 1491 if (
present(visc_rem_v))
then 1493 do k=1,nz ;
do j=jsh-1,jeh ;
do i=ish,ieh
1494 h_v(i,j,k) = h_v(i,j,k) * visc_rem_v(i,j,k)
1495 enddo ;
enddo ;
enddo 1498 local_open_bc = .false.
1499 if (
present(obc))
then ;
if (
associated(obc))
then 1500 local_open_bc = obc%open_v_BCs_exist_globally
1502 if (local_open_bc)
then 1503 do n = 1, obc%number_of_segments
1504 if (obc%segment(n)%open .and. obc%segment(n)%is_N_or_S)
then 1505 j = obc%segment(n)%HI%JsdB
1506 if (obc%segment(n)%direction == obc_direction_n)
then 1507 if (
present(visc_rem_v))
then ;
do k=1,nz
1508 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1509 h_v(i,j,k) = h(i,j,k) * visc_rem_v(i,j,k)
1511 enddo ;
else ;
do k=1,nz
1512 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1513 h_v(i,j,k) = h(i,j,k)
1517 if (
present(visc_rem_v))
then ;
do k=1,nz
1518 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1519 h_v(i,j,k) = h(i,j+1,k) * visc_rem_v(i,j,k)
1521 enddo ;
else ;
do k=1,nz
1522 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1523 h_v(i,j,k) = h(i,j+1,k)
1531 end subroutine merid_face_thickness
1534 subroutine meridional_flux_adjust(v, h_in, h_L, h_R, vhbt, vh_tot_0, dvhdv_tot_0, &
1535 dv, dv_max_CFL, dv_min_CFL, dt, G, US, CS, visc_rem, &
1536 j, ish, ieh, do_I_in, full_precision, vh_3d, OBC)
1538 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1540 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1542 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),&
1544 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1546 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: visc_rem
1552 real,
dimension(SZI_(G)), &
1553 optional,
intent(in) :: vhbt
1555 real,
dimension(SZI_(G)),
intent(in) :: dv_max_CFL
1556 real,
dimension(SZI_(G)),
intent(in) :: dv_min_CFL
1557 real,
dimension(SZI_(G)),
intent(in) :: vh_tot_0
1559 real,
dimension(SZI_(G)),
intent(in) :: dvhdv_tot_0
1561 real,
dimension(SZI_(G)),
intent(out) :: dv
1562 real,
intent(in) :: dt
1565 integer,
intent(in) :: j
1566 integer,
intent(in) :: ish
1567 integer,
intent(in) :: ieh
1568 logical,
dimension(SZI_(G)), &
1569 intent(in) :: do_I_in
1570 logical,
optional,
intent(in) :: full_precision
1572 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1573 optional,
intent(inout) :: vh_3d
1577 real,
dimension(SZI_(G),SZK_(G)) :: &
1580 real,
dimension(SZI_(G)) :: &
1591 integer :: i, k, nz, itt, max_itts = 20
1592 logical :: full_prec, domore, do_I(SZI_(G))
1595 full_prec = .true. ;
if (
present(full_precision)) full_prec = full_precision
1597 vh_aux(:,:) = 0.0 ; dvhdv(:,:) = 0.0
1599 if (
present(vh_3d))
then ;
do k=1,nz ;
do i=ish,ieh
1600 vh_aux(i,k) = vh_3d(i,j,k)
1601 enddo ;
enddo ;
endif 1604 dv(i) = 0.0 ; do_i(i) = do_i_in(i)
1605 dv_max(i) = dv_max_cfl(i) ; dv_min(i) = dv_min_cfl(i)
1606 vh_err(i) = vh_tot_0(i) - vhbt(i) ; dvhdv_tot(i) = dvhdv_tot_0(i)
1607 vh_err_best(i) = abs(vh_err(i))
1613 case (:1) ; tol_eta = 1e-6 * cs%tol_eta
1614 case (2) ; tol_eta = 1e-4 * cs%tol_eta
1615 case (3) ; tol_eta = 1e-2 * cs%tol_eta
1616 case default ; tol_eta = cs%tol_eta
1619 tol_eta = cs%tol_eta_aux ;
if (itt<=1) tol_eta = 1e-6 * cs%tol_eta_aux
1621 tol_vel = cs%tol_vel
1624 if (vh_err(i) > 0.0)
then ; dv_max(i) = dv(i)
1625 elseif (vh_err(i) < 0.0)
then ; dv_min(i) = dv(i)
1626 else ; do_i(i) = .false. ;
endif 1629 do i=ish,ieh ;
if (do_i(i))
then 1630 if ((dt * min(g%IareaT(i,j),g%IareaT(i,j+1))*abs(vh_err(i)) > tol_eta) .or. &
1631 (cs%better_iter .and. ((abs(vh_err(i)) > tol_vel * dvhdv_tot(i)) .or. &
1632 (abs(vh_err(i)) > vh_err_best(i))) ))
then 1636 ddv = -vh_err(i) / dvhdv_tot(i)
1639 if (abs(ddv) < 1.0e-15*abs(dv(i)))
then 1641 elseif (ddv > 0.0)
then 1642 if (dv(i) >= dv_max(i))
then 1643 dv(i) = 0.5*(dv_prev + dv_max(i))
1644 if (dv_max(i) - dv_prev < 1.0e-15*abs(dv(i))) do_i(i) = .false.
1647 if (dv(i) <= dv_min(i))
then 1648 dv(i) = 0.5*(dv_prev + dv_min(i))
1649 if (dv_prev - dv_min(i) < 1.0e-15*abs(dv(i))) do_i(i) = .false.
1654 dv(i) = dv(i) - vh_err(i) / dvhdv_tot(i)
1655 if ((dv(i) >= dv_max(i)) .or. (dv(i) <= dv_min(i))) &
1656 dv(i) = 0.5*(dv_max(i) + dv_min(i))
1658 if (do_i(i)) domore = .true.
1663 if (.not.domore)
exit 1665 if ((itt < max_itts) .or.
present(vh_3d))
then ;
do k=1,nz
1666 do i=ish,ieh ; v_new(i) = v(i,j,k) + dv(i) * visc_rem(i,k) ;
enddo 1667 call merid_flux_layer(v_new, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), &
1668 vh_aux(:,k), dvhdv(:,k), visc_rem(:,k), &
1669 dt, g, us, j, ish, ieh, do_i, cs%vol_CFL, obc)
1672 if (itt < max_itts)
then 1674 vh_err(i) = -vhbt(i) ; dvhdv_tot(i) = 0.0
1676 do k=1,nz ;
do i=ish,ieh
1677 vh_err(i) = vh_err(i) + vh_aux(i,k)
1678 dvhdv_tot(i) = dvhdv_tot(i) + dvhdv(i,k)
1681 vh_err_best(i) = min(vh_err_best(i), abs(vh_err(i)))
1689 if (
present(vh_3d))
then ;
do k=1,nz ;
do i=ish,ieh
1690 vh_3d(i,j,k) = vh_aux(i,k)
1691 enddo ;
enddo ;
endif 1693 end subroutine meridional_flux_adjust
1697 subroutine set_merid_bt_cont(v, h_in, h_L, h_R, BT_cont, vh_tot_0, dvhdv_tot_0, &
1698 dv_max_CFL, dv_min_CFL, dt, G, US, CS, visc_rem, &
1699 visc_rem_max, j, ish, ieh, do_I)
1701 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1702 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
1704 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
1706 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
1710 real,
dimension(SZI_(G)),
intent(in) :: vh_tot_0
1712 real,
dimension(SZI_(G)),
intent(in) :: dvhdv_tot_0
1714 real,
dimension(SZI_(G)),
intent(in) :: dv_max_CFL
1716 real,
dimension(SZI_(G)),
intent(in) :: dv_min_CFL
1718 real,
intent(in) :: dt
1721 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: visc_rem
1726 real,
dimension(SZI_(G)),
intent(in) :: visc_rem_max
1727 integer,
intent(in) :: j
1728 integer,
intent(in) :: ish
1729 integer,
intent(in) :: ieh
1730 logical,
dimension(SZI_(G)),
intent(in) :: do_I
1733 real,
dimension(SZI_(G)) :: &
1753 real :: visc_rem_lim
1756 real :: min_visc_rem
1766 nz = g%ke ; idt = 1.0 / dt
1767 min_visc_rem = 0.1 ; cfl_min = 1e-6
1770 do i=ish,ieh ; zeros(i) = 0.0 ;
enddo 1771 call meridional_flux_adjust(v, h_in, h_l, h_r, zeros, vh_tot_0, dvhdv_tot_0, dv0, &
1772 dv_max_cfl, dv_min_cfl, dt, g, us, cs, visc_rem, &
1773 j, ish, ieh, do_i, .true.)
1779 do i=ish,ieh ;
if (do_i(i))
then 1781 dv_cfl(i) = (cfl_min * idt) * g%dyCv(i,j)
1782 dvr(i) = min(0.0,dv0(i) - dv_cfl(i))
1783 dvl(i) = max(0.0,dv0(i) + dv_cfl(i))
1784 famt_l(i) = 0.0 ; famt_r(i) = 0.0 ; famt_0(i) = 0.0
1785 vhtot_l(i) = 0.0 ; vhtot_r(i) = 0.0
1788 if (.not.domore)
then 1789 do k=1,nz ;
do i=ish,ieh
1790 bt_cont%FA_v_S0(i,j) = 0.0 ; bt_cont%FA_v_SS(i,j) = 0.0
1791 bt_cont%vBT_SS(i,j) = 0.0
1792 bt_cont%FA_v_N0(i,j) = 0.0 ; bt_cont%FA_v_NN(i,j) = 0.0
1793 bt_cont%vBT_NN(i,j) = 0.0
1798 do k=1,nz ;
do i=ish,ieh ;
if (do_i(i))
then 1799 visc_rem_lim = max(visc_rem(i,k), min_visc_rem*visc_rem_max(i))
1800 if (visc_rem_lim > 0.0)
then 1801 if (v(i,j,k) + dvr(i)*visc_rem_lim > -dv_cfl(i)*visc_rem(i,k)) &
1802 dvr(i) = -(v(i,j,k) + dv_cfl(i)*visc_rem(i,k)) / visc_rem_lim
1803 if (v(i,j,k) + dvl(i)*visc_rem_lim < dv_cfl(i)*visc_rem(i,k)) &
1804 dvl(i) = -(v(i,j,k) - dv_cfl(i)*visc_rem(i,k)) / visc_rem_lim
1806 endif ;
enddo ;
enddo 1808 do i=ish,ieh ;
if (do_i(i))
then 1809 v_l(i) = v(i,j,k) + dvl(i) * visc_rem(i,k)
1810 v_r(i) = v(i,j,k) + dvr(i) * visc_rem(i,k)
1811 v_0(i) = v(i,j,k) + dv0(i) * visc_rem(i,k)
1813 call merid_flux_layer(v_0, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_0, dvhdv_0, &
1814 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
1815 call merid_flux_layer(v_l, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_l, dvhdv_l, &
1816 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
1817 call merid_flux_layer(v_r, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_r, dvhdv_r, &
1818 visc_rem(:,k), dt, g, us, j, ish, ieh, do_i, cs%vol_CFL)
1819 do i=ish,ieh ;
if (do_i(i))
then 1820 famt_0(i) = famt_0(i) + dvhdv_0(i)
1821 famt_l(i) = famt_l(i) + dvhdv_l(i)
1822 famt_r(i) = famt_r(i) + dvhdv_r(i)
1823 vhtot_l(i) = vhtot_l(i) + vh_l(i)
1824 vhtot_r(i) = vhtot_r(i) + vh_r(i)
1827 do i=ish,ieh ;
if (do_i(i))
then 1828 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1829 if ((dvl(i) - dv0(i)) /= 0.0) &
1830 fa_avg = vhtot_l(i) / (dvl(i) - dv0(i))
1831 if (fa_avg > max(fa_0, famt_l(i)))
then ; fa_avg = max(fa_0, famt_l(i))
1832 elseif (fa_avg < min(fa_0, famt_l(i)))
then ; fa_0 = fa_avg ;
endif 1833 bt_cont%FA_v_S0(i,j) = fa_0 ; bt_cont%FA_v_SS(i,j) = famt_l(i)
1834 if (abs(fa_0-famt_l(i)) <= 1e-12*fa_0)
then ; bt_cont%vBT_SS(i,j) = 0.0 ;
else 1835 bt_cont%vBT_SS(i,j) = (1.5 * (dvl(i) - dv0(i))) * &
1836 ((famt_l(i) - fa_avg) / (famt_l(i) - fa_0))
1839 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1840 if ((dvr(i) - dv0(i)) /= 0.0) &
1841 fa_avg = vhtot_r(i) / (dvr(i) - dv0(i))
1842 if (fa_avg > max(fa_0, famt_r(i)))
then ; fa_avg = max(fa_0, famt_r(i))
1843 elseif (fa_avg < min(fa_0, famt_r(i)))
then ; fa_0 = fa_avg ;
endif 1844 bt_cont%FA_v_N0(i,j) = fa_0 ; bt_cont%FA_v_NN(i,j) = famt_r(i)
1845 if (abs(famt_r(i) - fa_0) <= 1e-12*fa_0)
then ; bt_cont%vBT_NN(i,j) = 0.0 ;
else 1846 bt_cont%vBT_NN(i,j) = (1.5 * (dvr(i) - dv0(i))) * &
1847 ((famt_r(i) - fa_avg) / (famt_r(i) - fa_0))
1850 bt_cont%FA_v_S0(i,j) = 0.0 ; bt_cont%FA_v_SS(i,j) = 0.0
1851 bt_cont%FA_v_N0(i,j) = 0.0 ; bt_cont%FA_v_NN(i,j) = 0.0
1852 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1855 end subroutine set_merid_bt_cont
1858 subroutine ppm_reconstruction_x(h_in, h_L, h_R, G, LB, h_min, monotonic, simple_2nd, OBC)
1860 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1861 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_L
1863 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_R
1866 real,
intent(in) :: h_min
1868 logical,
optional,
intent(in) :: monotonic
1871 logical,
optional,
intent(in) :: simple_2nd
1877 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1878 real,
parameter :: oneSixth = 1./6.
1879 real :: h_ip1, h_im1
1881 logical :: use_CW84, use_2nd
1882 character(len=256) :: mesg
1883 integer :: i, j, isl, iel, jsl, jel, n, stencil
1884 logical :: local_open_BC
1887 use_cw84 = .false. ;
if (
present(monotonic)) use_cw84 = monotonic
1888 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1890 local_open_bc = .false.
1891 if (
present(obc))
then ;
if (
associated(obc))
then 1892 local_open_bc = obc%open_u_BCs_exist_globally
1895 isl = lb%ish-1 ; iel = lb%ieh+1 ; jsl = lb%jsh ; jel = lb%jeh
1898 stencil = 2 ;
if (use_2nd) stencil = 1
1900 if ((isl-stencil < g%isd) .or. (iel+stencil > g%ied))
then 1901 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_x called with a ", & 1902 & "x-halo that needs to be increased by ",i2,".")') &
1903 stencil + max(g%isd-isl,iel-g%ied)
1904 call mom_error(fatal,mesg)
1906 if ((jsl < g%jsd) .or. (jel > g%jed))
then 1907 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_x called with a ", & 1908 & "y-halo that needs to be increased by ",i2,".")') &
1909 max(g%jsd-jsl,jel-g%jed)
1910 call mom_error(fatal,mesg)
1914 do j=jsl,jel ;
do i=isl,iel
1915 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1916 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1917 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) )
1918 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) )
1921 do j=jsl,jel ;
do i=isl-1,iel+1
1922 if ((g%mask2dT(i-1,j) * g%mask2dT(i,j) * g%mask2dT(i+1,j)) == 0.0)
then 1926 slp(i,j) = 0.5 * (h_in(i+1,j) - h_in(i-1,j))
1928 dmx = max(h_in(i+1,j), h_in(i-1,j), h_in(i,j)) - h_in(i,j)
1929 dmn = h_in(i,j) - min(h_in(i+1,j), h_in(i-1,j), h_in(i,j))
1930 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
1935 if (local_open_bc)
then 1936 do n=1, obc%number_of_segments
1937 segment => obc%segment(n)
1938 if (.not. segment%on_pe) cycle
1939 if (segment%direction == obc_direction_e .or. &
1940 segment%direction == obc_direction_w)
then 1942 do j=segment%HI%jsd,segment%HI%jed
1950 do j=jsl,jel ;
do i=isl,iel
1955 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1956 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1958 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) ) + onesixth*( slp(i-1,j) - slp(i,j) )
1959 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i+1,j) )
1963 if (local_open_bc)
then 1964 do n=1, obc%number_of_segments
1965 segment => obc%segment(n)
1966 if (.not. segment%on_pe) cycle
1967 if (segment%direction == obc_direction_e)
then 1969 do j=segment%HI%jsd,segment%HI%jed
1970 h_l(i+1,j) = h_in(i,j)
1971 h_r(i+1,j) = h_in(i,j)
1972 h_l(i,j) = h_in(i,j)
1973 h_r(i,j) = h_in(i,j)
1975 elseif (segment%direction == obc_direction_w)
then 1977 do j=segment%HI%jsd,segment%HI%jed
1978 h_l(i,j) = h_in(i+1,j)
1979 h_r(i,j) = h_in(i+1,j)
1980 h_l(i+1,j) = h_in(i+1,j)
1981 h_r(i+1,j) = h_in(i+1,j)
1988 call ppm_limit_cw84(h_in, h_l, h_r, g, isl, iel, jsl, jel)
1990 call ppm_limit_pos(h_in, h_l, h_r, h_min, g, isl, iel, jsl, jel)
1994 end subroutine ppm_reconstruction_x
1997 subroutine ppm_reconstruction_y(h_in, h_L, h_R, G, LB, h_min, monotonic, simple_2nd, OBC)
1999 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2000 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_L
2002 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_R
2005 real,
intent(in) :: h_min
2007 logical,
optional,
intent(in) :: monotonic
2010 logical,
optional,
intent(in) :: simple_2nd
2016 real,
dimension(SZI_(G),SZJ_(G)) :: slp
2017 real,
parameter :: oneSixth = 1./6.
2018 real :: h_jp1, h_jm1
2020 logical :: use_CW84, use_2nd
2021 character(len=256) :: mesg
2022 integer :: i, j, isl, iel, jsl, jel, n, stencil
2023 logical :: local_open_BC
2026 use_cw84 = .false. ;
if (
present(monotonic)) use_cw84 = monotonic
2027 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
2029 local_open_bc = .false.
2030 if (
present(obc))
then ;
if (
associated(obc))
then 2031 local_open_bc = obc%open_v_BCs_exist_globally
2034 isl = lb%ish ; iel = lb%ieh ; jsl = lb%jsh-1 ; jel = lb%jeh+1
2037 stencil = 2 ;
if (use_2nd) stencil = 1
2039 if ((isl < g%isd) .or. (iel > g%ied))
then 2040 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_y called with a ", & 2041 & "x-halo that needs to be increased by ",i2,".")') &
2042 max(g%isd-isl,iel-g%ied)
2043 call mom_error(fatal,mesg)
2045 if ((jsl-stencil < g%jsd) .or. (jel+stencil > g%jed))
then 2046 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_y called with a ", & 2047 & "y-halo that needs to be increased by ",i2,".")') &
2048 stencil + max(g%jsd-jsl,jel-g%jed)
2049 call mom_error(fatal,mesg)
2053 do j=jsl,jel ;
do i=isl,iel
2054 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2055 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2056 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) )
2057 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) )
2060 do j=jsl-1,jel+1 ;
do i=isl,iel
2061 if ((g%mask2dT(i,j-1) * g%mask2dT(i,j) * g%mask2dT(i,j+1)) == 0.0)
then 2065 slp(i,j) = 0.5 * (h_in(i,j+1) - h_in(i,j-1))
2067 dmx = max(h_in(i,j+1), h_in(i,j-1), h_in(i,j)) - h_in(i,j)
2068 dmn = h_in(i,j) - min(h_in(i,j+1), h_in(i,j-1), h_in(i,j))
2069 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
2074 if (local_open_bc)
then 2075 do n=1, obc%number_of_segments
2076 segment => obc%segment(n)
2077 if (.not. segment%on_pe) cycle
2078 if (segment%direction == obc_direction_s .or. &
2079 segment%direction == obc_direction_n)
then 2081 do i=segment%HI%isd,segment%HI%ied
2089 do j=jsl,jel ;
do i=isl,iel
2092 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2093 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2095 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) ) + onesixth*( slp(i,j-1) - slp(i,j) )
2096 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i,j+1) )
2100 if (local_open_bc)
then 2101 do n=1, obc%number_of_segments
2102 segment => obc%segment(n)
2103 if (.not. segment%on_pe) cycle
2104 if (segment%direction == obc_direction_n)
then 2106 do i=segment%HI%isd,segment%HI%ied
2107 h_l(i,j+1) = h_in(i,j)
2108 h_r(i,j+1) = h_in(i,j)
2109 h_l(i,j) = h_in(i,j)
2110 h_r(i,j) = h_in(i,j)
2112 elseif (segment%direction == obc_direction_s)
then 2114 do i=segment%HI%isd,segment%HI%ied
2115 h_l(i,j) = h_in(i,j+1)
2116 h_r(i,j) = h_in(i,j+1)
2117 h_l(i,j+1) = h_in(i,j+1)
2118 h_r(i,j+1) = h_in(i,j+1)
2125 call ppm_limit_cw84(h_in, h_l, h_r, g, isl, iel, jsl, jel)
2127 call ppm_limit_pos(h_in, h_l, h_r, h_min, g, isl, iel, jsl, jel)
2131 end subroutine ppm_reconstruction_y
2137 subroutine ppm_limit_pos(h_in, h_L, h_R, h_min, G, iis, iie, jis, jie)
2139 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2140 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2141 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2142 real,
intent(in) :: h_min
2144 integer,
intent(in) :: iis
2145 integer,
intent(in) :: iie
2146 integer,
intent(in) :: jis
2147 integer,
intent(in) :: jie
2150 real :: curv, dh, scale
2151 character(len=256) :: mesg
2154 do j=jis,jie ;
do i=iis,iie
2157 curv = 3.0*(h_l(i,j) + h_r(i,j) - 2.0*h_in(i,j))
2158 if (curv > 0.0)
then 2159 dh = h_r(i,j) - h_l(i,j)
2160 if (abs(dh) < curv)
then 2161 if (h_in(i,j) <= h_min)
then 2162 h_l(i,j) = h_in(i,j) ; h_r(i,j) = h_in(i,j)
2163 elseif (12.0*curv*(h_in(i,j) - h_min) < (curv**2 + 3.0*dh**2))
then 2166 scale = 12.0*curv*(h_in(i,j) - h_min) / (curv**2 + 3.0*dh**2)
2167 h_l(i,j) = h_in(i,j) + scale*(h_l(i,j) - h_in(i,j))
2168 h_r(i,j) = h_in(i,j) + scale*(h_r(i,j) - h_in(i,j))
2174 end subroutine ppm_limit_pos
2178 subroutine ppm_limit_cw84(h_in, h_L, h_R, G, iis, iie, jis, jie)
2180 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2181 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2183 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2185 integer,
intent(in) :: iis
2186 integer,
intent(in) :: iie
2187 integer,
intent(in) :: jis
2188 integer,
intent(in) :: jie
2191 real :: h_i, RLdiff, RLdiff2, RLmean, FunFac
2192 character(len=256) :: mesg
2195 do j=jis,jie ;
do i=iis,iie
2199 if ( ( h_r(i,j) - h_i ) * ( h_i - h_l(i,j) ) <= 0. )
then 2200 h_l(i,j) = h_i ; h_r(i,j) = h_i
2202 rldiff = h_r(i,j) - h_l(i,j)
2203 rlmean = 0.5 * ( h_r(i,j) + h_l(i,j) )
2204 funfac = 6. * rldiff * ( h_i - rlmean )
2205 rldiff2 = rldiff * rldiff
2206 if ( funfac > rldiff2 ) h_l(i,j) = 3. * h_i - 2. * h_r(i,j)
2207 if ( funfac < -rldiff2 ) h_r(i,j) = 3. * h_i - 2. * h_l(i,j)
2212 end subroutine ppm_limit_cw84
2215 function ratio_max(a, b, maxrat)
result(ratio)
2216 real,
intent(in) :: a
2217 real,
intent(in) :: b
2218 real,
intent(in) :: maxrat
2221 if (abs(a) > abs(maxrat*b))
then 2226 end function ratio_max
2229 subroutine continuity_ppm_init(Time, G, GV, US, param_file, diag, CS)
2230 type(time_type),
target,
intent(in) :: time
2236 type(
diag_ctrl),
target,
intent(inout) :: diag
2240 #include "version_variable.h" 2242 character(len=40) :: mdl =
"MOM_continuity_PPM" 2244 if (
associated(cs))
then 2245 call mom_error(warning,
"continuity_PPM_init called with associated control structure.")
2252 call get_param(param_file, mdl,
"MONOTONIC_CONTINUITY", cs%monotonic, &
2253 "If true, CONTINUITY_PPM uses the Colella and Woodward "//&
2254 "monotonic limiter. The default (false) is to use a "//&
2255 "simple positive definite limiter.", default=.false.)
2256 call get_param(param_file, mdl,
"SIMPLE_2ND_PPM_CONTINUITY", cs%simple_2nd, &
2257 "If true, CONTINUITY_PPM uses a simple 2nd order "//&
2258 "(arithmetic mean) interpolation of the edge values. "//&
2259 "This may give better PV conservation properties. While "//&
2260 "it formally reduces the accuracy of the continuity "//&
2261 "solver itself in the strongly advective limit, it does "//&
2262 "not reduce the overall order of accuracy of the dynamic "//&
2263 "core.", default=.false.)
2264 call get_param(param_file, mdl,
"UPWIND_1ST_CONTINUITY", cs%upwind_1st, &
2265 "If true, CONTINUITY_PPM becomes a 1st-order upwind "//&
2266 "continuity solver. This scheme is highly diffusive "//&
2267 "but may be useful for debugging or in single-column "//&
2268 "mode where its minimal stencil is useful.", default=.false.)
2269 call get_param(param_file, mdl,
"ETA_TOLERANCE", cs%tol_eta, &
2270 "The tolerance for the differences between the "//&
2271 "barotropic and baroclinic estimates of the sea surface "//&
2272 "height due to the fluxes through each face. The total "//&
2273 "tolerance for SSH is 4 times this value. The default "//&
2274 "is 0.5*NK*ANGSTROM, and this should not be set less "//&
2275 "than about 10^-15*MAXIMUM_DEPTH.", units=
"m", scale=gv%m_to_H, &
2276 default=0.5*g%ke*gv%Angstrom_m, unscaled=tol_eta_m)
2279 call get_param(param_file, mdl,
"ETA_TOLERANCE_AUX", cs%tol_eta_aux, &
2280 "The tolerance for free-surface height discrepancies "//&
2281 "between the barotropic solution and the sum of the "//&
2282 "layer thicknesses when calculating the auxiliary "//&
2283 "corrected velocities. By default, this is the same as "//&
2284 "ETA_TOLERANCE, but can be made larger for efficiency.", &
2285 units=
"m", default=tol_eta_m, scale=gv%m_to_H)
2286 call get_param(param_file, mdl,
"VELOCITY_TOLERANCE", cs%tol_vel, &
2287 "The tolerance for barotropic velocity discrepancies "//&
2288 "between the barotropic solution and the sum of the "//&
2289 "layer thicknesses.", units=
"m s-1", default=3.0e8, scale=us%m_s_to_L_T)
2292 call get_param(param_file, mdl,
"CONT_PPM_AGGRESS_ADJUST", cs%aggress_adjust,&
2293 "If true, allow the adjusted velocities to have a "//&
2294 "relative CFL change up to 0.5.", default=.false.)
2295 cs%vol_CFL = cs%aggress_adjust
2296 call get_param(param_file, mdl,
"CONT_PPM_VOLUME_BASED_CFL", cs%vol_CFL, &
2297 "If true, use the ratio of the open face lengths to the "//&
2298 "tracer cell areas when estimating CFL numbers. The "//&
2299 "default is set by CONT_PPM_AGGRESS_ADJUST.", &
2300 default=cs%aggress_adjust, do_not_read=cs%aggress_adjust)
2301 call get_param(param_file, mdl,
"CONTINUITY_CFL_LIMIT", cs%CFL_limit_adjust, &
2302 "The maximum CFL of the adjusted velocities.", units=
"nondim", &
2304 call get_param(param_file, mdl,
"CONT_PPM_BETTER_ITER", cs%better_iter, &
2305 "If true, stop corrective iterations using a velocity "//&
2306 "based criterion and only stop if the iteration is "//&
2307 "better than all predecessors.", default=.true.)
2308 call get_param(param_file, mdl,
"CONT_PPM_USE_VISC_REM_MAX", &
2309 cs%use_visc_rem_max, &
2310 "If true, use more appropriate limiting bounds for "//&
2311 "corrections in strongly viscous columns.", default=.true.)
2312 call get_param(param_file, mdl,
"CONT_PPM_MARGINAL_FACE_AREAS", cs%marginal_faces, &
2313 "If true, use the marginal face areas from the continuity "//&
2314 "solver for use as the weights in the barotropic solver. "//&
2315 "Otherwise use the transport averaged areas.", default=.true.)
2319 id_clock_update = cpu_clock_id(
'(Ocean continuity update)', grain=clock_routine)
2320 id_clock_correct = cpu_clock_id(
'(Ocean continuity correction)', grain=clock_routine)
2322 end subroutine continuity_ppm_init
2325 function continuity_ppm_stencil(CS)
result(stencil)
2329 stencil = 3 ;
if (cs%simple_2nd) stencil = 2 ;
if (cs%upwind_1st) stencil = 1
2331 end function continuity_ppm_stencil
2334 subroutine continuity_ppm_end(CS)
2337 end subroutine continuity_ppm_end
Ocean grid type. See mom_grid for details.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Open boundary segment data structure.
Wraps the MPP cpu clock functions.
The MOM6 facility to parse input files for runtime parameters.
Container for information about the summed layer transports and how they will vary as the barotropic ...
Control structure for mom_continuity_ppm.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
A container for loop bounds.
Routines for error handling and I/O management.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Solve the layer continuity equation using the PPM method for layer fluxes.
Controls where open boundary conditions are applied.
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.
An overloaded interface to read and log the values of various types of parameters.