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, &
78 uhbt_aux, vhbt_aux, u_cor_aux, v_cor_aux, BT_cont)
81 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
83 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
85 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
87 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
89 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
91 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
93 real,
intent(in) :: dt
96 real,
dimension(SZIB_(G),SZJ_(G)), &
97 optional,
intent(in) :: uhbt
99 real,
dimension(SZI_(G),SZJB_(G)), &
100 optional,
intent(in) :: vhbt
103 optional,
pointer :: obc
104 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
105 optional,
intent(in) :: visc_rem_u
111 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
112 optional,
intent(in) :: visc_rem_v
118 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
119 optional,
intent(out) :: u_cor
121 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
122 optional,
intent(out) :: v_cor
124 real,
dimension(SZIB_(G),SZJ_(G)), &
125 optional,
intent(in) :: uhbt_aux
128 real,
dimension(SZI_(G),SZJB_(G)), &
129 optional,
intent(in) :: vhbt_aux
132 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
133 optional,
intent(out) :: u_cor_aux
136 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
137 optional,
intent(out) :: v_cor_aux
146 integer :: is, ie, js, je, nz, stencil
150 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
152 h_min = gv%Angstrom_H
154 if (.not.
associated(cs))
call mom_error(fatal, &
155 "MOM_continuity_PPM: Module must be initialized before it is used.")
156 x_first = (mod(g%first_direction,2) == 0)
158 if (
present(visc_rem_u) .neqv.
present(visc_rem_v))
call mom_error(fatal, &
159 "MOM_continuity_PPM: Either both visc_rem_u and visc_rem_v or neither"// &
160 " one must be present in call to continuity_PPM.")
162 stencil = 3 ;
if (cs%simple_2nd) stencil = 2 ;
if (cs%upwind_1st) stencil = 1
166 lb%ish = g%isc ; lb%ieh = g%iec
167 lb%jsh = g%jsc-stencil ; lb%jeh = g%jec+stencil
168 call zonal_mass_flux(u, hin, uh, dt, g, gv, us, cs, lb, uhbt, obc, visc_rem_u, &
169 u_cor, uhbt_aux, u_cor_aux, bt_cont)
171 call cpu_clock_begin(id_clock_update)
173 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
174 h(i,j,k) = hin(i,j,k) - dt* g%IareaT(i,j) * (uh(i,j,k) - uh(i-1,j,k))
177 enddo ;
enddo ;
enddo
178 call cpu_clock_end(id_clock_update)
180 lb%ish = g%isc ; lb%ieh = g%iec ; lb%jsh = g%jsc ; lb%jeh = g%jec
184 call meridional_mass_flux(v, h, vh, dt, g, gv, us, cs, lb, vhbt, obc, visc_rem_v, &
185 v_cor, vhbt_aux, v_cor_aux, bt_cont)
187 call cpu_clock_begin(id_clock_update)
189 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
190 h(i,j,k) = h(i,j,k) - dt*g%IareaT(i,j) * (vh(i,j,k) - vh(i,j-1,k))
192 if (h(i,j,k) < h_min) h(i,j,k) = h_min
193 enddo ;
enddo ;
enddo
194 call cpu_clock_end(id_clock_update)
198 lb%ish = g%isc-stencil ; lb%ieh = g%iec+stencil
199 lb%jsh = g%jsc ; lb%jeh = g%jec
201 call meridional_mass_flux(v, hin, vh, dt, g, gv, us, cs, lb, vhbt, obc, visc_rem_v, &
202 v_cor, vhbt_aux, v_cor_aux, bt_cont)
204 call cpu_clock_begin(id_clock_update)
206 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
207 h(i,j,k) = hin(i,j,k) - dt*g%IareaT(i,j) * (vh(i,j,k) - vh(i,j-1,k))
208 enddo ;
enddo ;
enddo
209 call cpu_clock_end(id_clock_update)
213 lb%ish = g%isc ; lb%ieh = g%iec ; lb%jsh = g%jsc ; lb%jeh = g%jec
214 call zonal_mass_flux(u, h, uh, dt, g, gv, us, cs, lb, uhbt, obc, visc_rem_u, &
215 u_cor, uhbt_aux, u_cor_aux, bt_cont)
217 call cpu_clock_begin(id_clock_update)
219 do k=1,nz ;
do j=lb%jsh,lb%jeh ;
do i=lb%ish,lb%ieh
220 h(i,j,k) = h(i,j,k) - dt* g%IareaT(i,j) * (uh(i,j,k) - uh(i-1,j,k))
222 if (h(i,j,k) < h_min) h(i,j,k) = h_min
223 enddo ;
enddo ;
enddo
224 call cpu_clock_end(id_clock_update)
228 end subroutine continuity_ppm
231 subroutine zonal_mass_flux(u, h_in, uh, dt, G, GV, US, CS, LB, uhbt, OBC, &
232 visc_rem_u, u_cor, uhbt_aux, u_cor_aux, BT_cont)
235 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
237 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
239 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
242 real,
intent(in) :: dt
247 optional,
pointer :: OBC
248 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
249 optional,
intent(in) :: visc_rem_u
254 real,
dimension(SZIB_(G),SZJ_(G)), &
255 optional,
intent(in) :: uhbt
257 real,
dimension(SZIB_(G),SZJ_(G)), &
258 optional,
intent(in) :: uhbt_aux
260 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
261 optional,
intent(out) :: u_cor
264 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
265 optional,
intent(out) :: u_cor_aux
272 real,
dimension(SZIB_(G),SZK_(G)) :: duhdu
273 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_L, h_R
274 real,
dimension(SZIB_(G)) :: &
281 logical,
dimension(SZIB_(G)) :: do_I
282 real,
dimension(SZIB_(G),SZK_(G)) :: &
284 real,
dimension(SZIB_(G)) :: FAuI
292 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
293 logical :: do_aux, local_specified_BC, use_visc_rem, set_BT_cont, any_simple_OBC
294 logical :: local_Flather_OBC, local_open_BC, is_simple
297 do_aux = (
present(uhbt_aux) .and.
present(u_cor_aux))
298 use_visc_rem =
present(visc_rem_u)
299 local_specified_bc = .false. ; set_bt_cont = .false. ; local_flather_obc = .false.
300 local_open_bc = .false.
301 if (
present(bt_cont)) set_bt_cont = (
associated(bt_cont))
302 if (
present(obc))
then ;
if (
associated(obc))
then
303 local_specified_bc = obc%specified_u_BCs_exist_globally
304 local_flather_obc = obc%Flather_u_BCs_exist_globally
305 local_open_bc = obc%open_u_BCs_exist_globally
307 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
309 cfl_dt = cs%CFL_limit_adjust / dt
311 if (cs%aggress_adjust) cfl_dt = i_dt
313 call cpu_clock_begin(id_clock_update)
317 if (cs%upwind_1st)
then
318 do j=jsh,jeh ;
do i=ish-1,ieh+1
319 h_l(i,j,k) = h_in(i,j,k) ; h_r(i,j,k) = h_in(i,j,k)
322 call ppm_reconstruction_x(h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), g, lb, &
323 2.0*gv%Angstrom_H, cs%monotonic, simple_2nd=cs%simple_2nd, obc=obc)
325 do i=ish-1,ieh ; visc_rem(i,k) = 1.0 ;
enddo
327 call cpu_clock_end(id_clock_update)
329 call cpu_clock_begin(id_clock_correct)
337 do i=ish-1,ieh ; do_i(i) = .true. ; visc_rem_max(i) = 0.0 ;
enddo
340 if (use_visc_rem)
then ;
do i=ish-1,ieh
341 visc_rem(i,k) = visc_rem_u(i,j,k)
342 visc_rem_max(i) = max(visc_rem_max(i), visc_rem(i,k))
344 call zonal_flux_layer(u(:,j,k), h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), &
345 uh(:,j,k), duhdu(:,k), visc_rem(:,k), &
346 dt, g, j, ish, ieh, do_i, cs%vol_CFL, obc)
347 if (local_specified_bc)
then
349 if (obc%segment(obc%segnum_u(i,j))%specified) &
350 uh(i,j,k) = obc%segment(obc%segnum_u(i,j))%normal_trans(i,j,k)
355 if ((.not.use_visc_rem).or.(.not.cs%use_visc_rem_max))
then ;
do i=ish-1,ieh
356 visc_rem_max(i) = 1.0
359 if (
present(uhbt) .or. do_aux .or. set_bt_cont)
then
364 if (visc_rem_max(i) > 0.0) i_vrm = 1.0 / visc_rem_max(i)
366 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
367 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
368 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif
369 du_max_cfl(i) = 2.0* (cfl_dt * dx_w) * i_vrm
370 du_min_cfl(i) = -2.0 * (cfl_dt * dx_e) * i_vrm
371 uh_tot_0(i) = 0.0 ; duhdu_tot_0(i) = 0.0
373 do k=1,nz ;
do i=ish-1,ieh
374 duhdu_tot_0(i) = duhdu_tot_0(i) + duhdu(i,k)
375 uh_tot_0(i) = uh_tot_0(i) + uh(i,j,k)
377 if (use_visc_rem)
then
378 if (cs%aggress_adjust)
then
379 do k=1,nz ;
do i=ish-1,ieh
381 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
382 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
383 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif
385 du_lim = 0.499*((dx_w*i_dt - u(i,j,k)) + min(0.0,u(i-1,j,k)))
386 if (du_max_cfl(i) * visc_rem(i,k) > du_lim) &
387 du_max_cfl(i) = du_lim / visc_rem(i,k)
389 du_lim = 0.499*((-dx_e*i_dt - u(i,j,k)) + max(0.0,u(i+1,j,k)))
390 if (du_min_cfl(i) * visc_rem(i,k) < du_lim) &
391 du_min_cfl(i) = du_lim / visc_rem(i,k)
394 do k=1,nz ;
do i=ish-1,ieh
396 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
397 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
398 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif
400 if (du_max_cfl(i) * visc_rem(i,k) > dx_w*cfl_dt - u(i,j,k)) &
401 du_max_cfl(i) = (dx_w*cfl_dt - u(i,j,k)) / visc_rem(i,k)
402 if (du_min_cfl(i) * visc_rem(i,k) < -dx_e*cfl_dt - u(i,j,k)) &
403 du_min_cfl(i) = -(dx_e*cfl_dt + u(i,j,k)) / visc_rem(i,k)
407 if (cs%aggress_adjust)
then
408 do k=1,nz ;
do i=ish-1,ieh
410 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
411 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
412 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif
414 du_max_cfl(i) = min(du_max_cfl(i), 0.499 * &
415 ((dx_w*i_dt - u(i,j,k)) + min(0.0,u(i-1,j,k))) )
416 du_min_cfl(i) = max(du_min_cfl(i), 0.499 * &
417 ((-dx_e*i_dt - u(i,j,k)) + max(0.0,u(i+1,j,k))) )
420 do k=1,nz ;
do i=ish-1,ieh
422 dx_w = ratio_max(g%areaT(i,j), g%dy_Cu(i,j), 1000.0*g%dxT(i,j))
423 dx_e = ratio_max(g%areaT(i+1,j), g%dy_Cu(i,j), 1000.0*g%dxT(i+1,j))
424 else ; dx_w = g%dxT(i,j) ; dx_e = g%dxT(i+1,j) ;
endif
426 du_max_cfl(i) = min(du_max_cfl(i), dx_w*cfl_dt - u(i,j,k))
427 du_min_cfl(i) = max(du_min_cfl(i), -(dx_e*cfl_dt + u(i,j,k)))
432 du_max_cfl(i) = max(du_max_cfl(i),0.0)
433 du_min_cfl(i) = min(du_min_cfl(i),0.0)
438 any_simple_obc = .false.
439 if (
present(uhbt) .or. do_aux .or. set_bt_cont)
then
440 if (local_specified_bc .or. local_flather_obc)
then ;
do i=ish-1,ieh
442 is_simple = obc%segment(obc%segnum_u(i,j))%specified
443 do_i(i) = .not.(obc%segnum_u(i,j) /= obc_none .and. is_simple)
444 any_simple_obc = any_simple_obc .or. is_simple
445 enddo ;
else ;
do i=ish-1,ieh
450 if (
present(uhbt))
then
451 call zonal_flux_adjust(u, h_in, h_l, h_r, uhbt(:,j), uh_tot_0, &
452 duhdu_tot_0, du, du_max_cfl, du_min_cfl, dt, g, &
453 cs, visc_rem, j, ish, ieh, do_i, .true., uh, obc=obc)
455 if (
present(u_cor))
then ;
do k=1,nz
456 do i=ish-1,ieh ; u_cor(i,j,k) = u(i,j,k) + du(i) * visc_rem(i,k) ;
enddo
457 if (local_specified_bc)
then ;
do i=ish-1,ieh
458 if (obc%segment(obc%segnum_u(i,j))%specified) &
459 u_cor(i,j,k) = obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)
466 call zonal_flux_adjust(u, h_in, h_l, h_r, uhbt_aux(:,j), uh_tot_0, &
467 duhdu_tot_0, du, du_max_cfl, du_min_cfl, dt, g, &
468 cs, visc_rem, j, ish, ieh, do_i, .false., obc=obc)
471 do i=ish-1,ieh ; u_cor_aux(i,j,k) = u(i,j,k) + du(i) * visc_rem(i,k) ;
enddo
472 if (local_specified_bc)
then ;
do i=ish-1,ieh
473 if (obc%segment(obc%segnum_u(i,j))%specified) &
474 u_cor_aux(i,j,k) = obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)
479 if (set_bt_cont)
then
480 call set_zonal_bt_cont(u, h_in, h_l, h_r, bt_cont, uh_tot_0, duhdu_tot_0,&
481 du_max_cfl, du_min_cfl, dt, g, us, cs, visc_rem, &
482 visc_rem_max, j, ish, ieh, do_i)
483 if (any_simple_obc)
then
485 do_i(i) = obc%segment(obc%segnum_u(i,j))%specified
486 if (do_i(i)) faui(i) = gv%H_subroundoff*g%dy_Cu(i,j)
488 do k=1,nz ;
do i=ish-1,ieh ;
if (do_i(i))
then
489 if ((abs(obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)) > 0.0) .and. &
490 (obc%segment(obc%segnum_u(i,j))%specified)) &
491 faui(i) = faui(i) + obc%segment(obc%segnum_u(i,j))%normal_trans(i,j,k) / &
492 obc%segment(obc%segnum_u(i,j))%normal_vel(i,j,k)
493 endif ;
enddo ;
enddo
494 do i=ish-1,ieh ;
if (do_i(i))
then
495 bt_cont%FA_u_W0(i,j) = us%m_to_L*faui(i) ; bt_cont%FA_u_E0(i,j) = us%m_to_L*faui(i)
496 bt_cont%FA_u_WW(i,j) = us%m_to_L*faui(i) ; bt_cont%FA_u_EE(i,j) = us%m_to_L*faui(i)
497 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
504 if (local_open_bc .and. set_bt_cont)
then
505 do n = 1, obc%number_of_segments
506 if (obc%segment(n)%open .and. obc%segment(n)%is_E_or_W)
then
507 i = obc%segment(n)%HI%IsdB
508 if (obc%segment(n)%direction == obc_direction_e)
then
509 do j = obc%segment(n)%HI%Jsd, obc%segment(n)%HI%Jed
511 do k=1,nz ; fa_u = fa_u + h_in(i,j,k)*us%m_to_L*g%dy_Cu(i,j) ;
enddo
512 bt_cont%FA_u_W0(i,j) = fa_u ; bt_cont%FA_u_E0(i,j) = fa_u
513 bt_cont%FA_u_WW(i,j) = fa_u ; bt_cont%FA_u_EE(i,j) = fa_u
514 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
517 do j = obc%segment(n)%HI%Jsd, obc%segment(n)%HI%Jed
519 do k=1,nz ; fa_u = fa_u + h_in(i+1,j,k)*us%m_to_L*g%dy_Cu(i,j) ;
enddo
520 bt_cont%FA_u_W0(i,j) = fa_u ; bt_cont%FA_u_E0(i,j) = fa_u
521 bt_cont%FA_u_WW(i,j) = fa_u ; bt_cont%FA_u_EE(i,j) = fa_u
522 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
528 call cpu_clock_end(id_clock_correct)
530 if (set_bt_cont)
then ;
if (
allocated(bt_cont%h_u))
then
531 if (
present(u_cor))
then
532 call zonal_face_thickness(u_cor, h_in, h_l, h_r, bt_cont%h_u, dt, g, lb, &
533 cs%vol_CFL, cs%marginal_faces, visc_rem_u, obc)
535 call zonal_face_thickness(u, h_in, h_l, h_r, bt_cont%h_u, dt, g, lb, &
536 cs%vol_CFL, cs%marginal_faces, visc_rem_u, obc)
540 end subroutine zonal_mass_flux
543 subroutine zonal_flux_layer(u, h, h_L, h_R, uh, duhdu, visc_rem, dt, G, j, &
544 ish, ieh, do_I, vol_CFL, OBC)
546 real,
dimension(SZIB_(G)),
intent(in) :: u
547 real,
dimension(SZIB_(G)),
intent(in) :: visc_rem
552 real,
dimension(SZI_(G)),
intent(in) :: h
553 real,
dimension(SZI_(G)),
intent(in) :: h_L
554 real,
dimension(SZI_(G)),
intent(in) :: h_R
555 real,
dimension(SZIB_(G)),
intent(inout) :: uh
557 real,
dimension(SZIB_(G)),
intent(inout) :: duhdu
559 real,
intent(in) :: dt
560 integer,
intent(in) :: j
561 integer,
intent(in) :: ish
562 integer,
intent(in) :: ieh
563 logical,
dimension(SZIB_(G)),
intent(in) :: do_I
564 logical,
intent(in) :: vol_CFL
573 logical :: local_open_BC
575 local_open_bc = .false.
576 if (
present(obc))
then ;
if (
associated(obc))
then
577 local_open_bc = obc%open_u_BCs_exist_globally
580 do i=ish-1,ieh ;
if (do_i(i))
then
583 if (vol_cfl)
then ; cfl = (u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
584 else ; cfl = u(i) * dt * g%IdxT(i,j) ;
endif
585 curv_3 = h_l(i) + h_r(i) - 2.0*h(i)
586 uh(i) = g%dy_Cu(i,j) * u(i) * &
587 (h_r(i) + cfl * (0.5*(h_l(i) - h_r(i)) + curv_3*(cfl - 1.5)))
588 h_marg = h_r(i) + cfl * ((h_l(i) - h_r(i)) + 3.0*curv_3*(cfl - 1.0))
589 elseif (u(i) < 0.0)
then
590 if (vol_cfl)
then ; cfl = (-u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
591 else ; cfl = -u(i) * dt * g%IdxT(i+1,j) ;
endif
592 curv_3 = h_l(i+1) + h_r(i+1) - 2.0*h(i+1)
593 uh(i) = g%dy_Cu(i,j) * u(i) * &
594 (h_l(i+1) + cfl * (0.5*(h_r(i+1)-h_l(i+1)) + curv_3*(cfl - 1.5)))
595 h_marg = h_l(i+1) + cfl * ((h_r(i+1)-h_l(i+1)) + 3.0*curv_3*(cfl - 1.0))
598 h_marg = 0.5 * (h_l(i+1) + h_r(i))
600 duhdu(i) = g%dy_Cu(i,j) * h_marg * visc_rem(i)
603 if (local_open_bc)
then
604 do i=ish-1,ieh ;
if (do_i(i))
then
605 if (obc%segment(obc%segnum_u(i,j))%open)
then
606 if (obc%segment(obc%segnum_u(i,j))%direction == obc_direction_e)
then
607 uh(i) = g%dy_Cu(i,j) * u(i) * h(i)
608 duhdu(i) = g%dy_Cu(i,j) * h(i) * visc_rem(i)
610 uh(i) = g%dy_Cu(i,j) * u(i) * h(i+1)
611 duhdu(i) = g%dy_Cu(i,j) * h(i+1) * visc_rem(i)
616 end subroutine zonal_flux_layer
619 subroutine zonal_face_thickness(u, h, h_L, h_R, h_u, dt, G, LB, vol_CFL, &
620 marginal, visc_rem_u, OBC)
622 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
623 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
625 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
627 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
629 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(inout) :: h_u
630 real,
intent(in) :: dt
632 logical,
intent(in) :: vol_CFL
634 logical,
intent(in) :: marginal
636 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)), &
637 optional,
intent(in) :: visc_rem_u
650 logical :: local_open_BC
651 integer :: i, j, k, ish, ieh, jsh, jeh, nz, n
652 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
655 do k=1,nz ;
do j=jsh,jeh ;
do i=ish-1,ieh
656 if (u(i,j,k) > 0.0)
then
657 if (vol_cfl)
then ; cfl = (u(i,j,k) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
658 else ; cfl = u(i,j,k) * dt * g%IdxT(i,j) ;
endif
659 curv_3 = h_l(i,j,k) + h_r(i,j,k) - 2.0*h(i,j,k)
660 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))
661 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))
662 elseif (u(i,j,k) < 0.0)
then
663 if (vol_cfl)
then ; cfl = (-u(i,j,k)*dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
664 else ; cfl = -u(i,j,k) * dt * g%IdxT(i+1,j) ;
endif
665 curv_3 = h_l(i+1,j,k) + h_r(i+1,j,k) - 2.0*h(i+1,j,k)
666 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))
667 h_marg = h_l(i+1,j,k) + cfl * ((h_r(i+1,j,k)-h_l(i+1,j,k)) + &
668 3.0*curv_3*(cfl - 1.0))
670 h_avg = 0.5 * (h_l(i+1,j,k) + h_r(i,j,k))
673 h_marg = 0.5 * (h_l(i+1,j,k) + h_r(i,j,k))
678 if (marginal)
then ; h_u(i,j,k) = h_marg
679 else ; h_u(i,j,k) = h_avg ;
endif
680 enddo ;
enddo ;
enddo
681 if (
present(visc_rem_u))
then
683 do k=1,nz ;
do j=jsh,jeh ;
do i=ish-1,ieh
684 h_u(i,j,k) = h_u(i,j,k) * visc_rem_u(i,j,k)
685 enddo ;
enddo ;
enddo
688 local_open_bc = .false.
689 if (
present(obc))
then ;
if (
associated(obc))
then
690 local_open_bc = obc%open_u_BCs_exist_globally
692 if (local_open_bc)
then
693 do n = 1, obc%number_of_segments
694 if (obc%segment(n)%open .and. obc%segment(n)%is_E_or_W)
then
695 i = obc%segment(n)%HI%IsdB
696 if (obc%segment(n)%direction == obc_direction_e)
then
697 if (
present(visc_rem_u))
then ;
do k=1,nz
698 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
699 h_u(i,j,k) = h(i,j,k) * visc_rem_u(i,j,k)
701 enddo ;
else ;
do k=1,nz
702 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
703 h_u(i,j,k) = h(i,j,k)
707 if (
present(visc_rem_u))
then ;
do k=1,nz
708 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
709 h_u(i,j,k) = h(i+1,j,k) * visc_rem_u(i,j,k)
711 enddo ;
else ;
do k=1,nz
712 do j = obc%segment(n)%HI%jsd, obc%segment(n)%HI%jed
713 h_u(i,j,k) = h(i+1,j,k)
721 end subroutine zonal_face_thickness
725 subroutine zonal_flux_adjust(u, h_in, h_L, h_R, uhbt, uh_tot_0, duhdu_tot_0, &
726 du, du_max_CFL, du_min_CFL, dt, G, CS, visc_rem, &
727 j, ish, ieh, do_I_in, full_precision, uh_3d, OBC)
729 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
730 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
732 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
734 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
736 real,
dimension(SZIB_(G),SZK_(G)),
intent(in) :: visc_rem
741 real,
dimension(SZIB_(G)),
optional,
intent(in) :: uhbt
744 real,
dimension(SZIB_(G)),
intent(in) :: du_max_CFL
746 real,
dimension(SZIB_(G)),
intent(in) :: du_min_CFL
748 real,
dimension(SZIB_(G)),
intent(in) :: uh_tot_0
750 real,
dimension(SZIB_(G)),
intent(in) :: duhdu_tot_0
752 real,
dimension(SZIB_(G)),
intent(out) :: du
754 real,
intent(in) :: dt
756 integer,
intent(in) :: j
757 integer,
intent(in) :: ish
758 integer,
intent(in) :: ieh
759 logical,
dimension(SZIB_(G)),
intent(in) :: do_I_in
761 logical,
optional,
intent(in) :: full_precision
764 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
optional,
intent(inout) :: uh_3d
768 real,
dimension(SZIB_(G),SZK_(G)) :: &
771 real,
dimension(SZIB_(G)) :: &
782 integer :: i, k, nz, itt, max_itts = 20
783 logical :: full_prec, domore, do_I(SZIB_(G))
786 full_prec = .true. ;
if (
present(full_precision)) full_prec = full_precision
788 uh_aux(:,:) = 0.0 ; duhdu(:,:) = 0.0
790 if (
present(uh_3d))
then ;
do k=1,nz ;
do i=ish-1,ieh
791 uh_aux(i,k) = uh_3d(i,j,k)
792 enddo ;
enddo ;
endif
795 du(i) = 0.0 ; do_i(i) = do_i_in(i)
796 du_max(i) = du_max_cfl(i) ; du_min(i) = du_min_cfl(i)
797 uh_err(i) = uh_tot_0(i) - uhbt(i) ; duhdu_tot(i) = duhdu_tot_0(i)
798 uh_err_best(i) = abs(uh_err(i))
804 case (:1) ; tol_eta = 1e-6 * cs%tol_eta
805 case (2) ; tol_eta = 1e-4 * cs%tol_eta
806 case (3) ; tol_eta = 1e-2 * cs%tol_eta
807 case default ; tol_eta = cs%tol_eta
810 tol_eta = cs%tol_eta_aux ;
if (itt<=1) tol_eta = 1e-6 * cs%tol_eta_aux
815 if (uh_err(i) > 0.0)
then ; du_max(i) = du(i)
816 elseif (uh_err(i) < 0.0)
then ; du_min(i) = du(i)
817 else ; do_i(i) = .false. ;
endif
820 do i=ish-1,ieh ;
if (do_i(i))
then
821 if ((dt*min(g%IareaT(i,j),g%IareaT(i+1,j))*abs(uh_err(i)) > tol_eta) .or.&
822 (cs%better_iter .and. ((abs(uh_err(i)) > tol_vel * duhdu_tot(i)) .or.&
823 (abs(uh_err(i)) > uh_err_best(i))) ))
then
827 ddu = -uh_err(i) / duhdu_tot(i)
830 if (abs(ddu) < 1.0e-15*abs(du(i)))
then
832 elseif (ddu > 0.0)
then
833 if (du(i) >= du_max(i))
then
834 du(i) = 0.5*(du_prev + du_max(i))
835 if (du_max(i) - du_prev < 1.0e-15*abs(du(i))) do_i(i) = .false.
838 if (du(i) <= du_min(i))
then
839 du(i) = 0.5*(du_prev + du_min(i))
840 if (du_prev - du_min(i) < 1.0e-15*abs(du(i))) do_i(i) = .false.
845 du(i) = du(i) - uh_err(i) / duhdu_tot(i)
846 if ((du(i) >= du_max(i)) .or. (du(i) <= du_min(i))) &
847 du(i) = 0.5*(du_max(i) + du_min(i))
849 if (do_i(i)) domore = .true.
854 if (.not.domore)
exit
856 if ((itt < max_itts) .or.
present(uh_3d))
then ;
do k=1,nz
857 do i=ish-1,ieh ; u_new(i) = u(i,j,k) + du(i) * visc_rem(i,k) ;
enddo
858 call zonal_flux_layer(u_new, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), &
859 uh_aux(:,k), duhdu(:,k), visc_rem(:,k), &
860 dt, g, j, ish, ieh, do_i, cs%vol_CFL, obc)
863 if (itt < max_itts)
then
865 uh_err(i) = -uhbt(i) ; duhdu_tot(i) = 0.0
867 do k=1,nz ;
do i=ish-1,ieh
868 uh_err(i) = uh_err(i) + uh_aux(i,k)
869 duhdu_tot(i) = duhdu_tot(i) + duhdu(i,k)
872 uh_err_best(i) = min(uh_err_best(i), abs(uh_err(i)))
880 if (
present(uh_3d))
then ;
do k=1,nz ;
do i=ish-1,ieh
881 uh_3d(i,j,k) = uh_aux(i,k)
882 enddo ;
enddo ;
endif
884 end subroutine zonal_flux_adjust
888 subroutine set_zonal_bt_cont(u, h_in, h_L, h_R, BT_cont, uh_tot_0, duhdu_tot_0, &
889 du_max_CFL, du_min_CFL, dt, G, US, CS, visc_rem, &
890 visc_rem_max, j, ish, ieh, do_I)
892 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
893 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
895 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
897 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
901 real,
dimension(SZIB_(G)),
intent(in) :: uh_tot_0
903 real,
dimension(SZIB_(G)),
intent(in) :: duhdu_tot_0
905 real,
dimension(SZIB_(G)),
intent(in) :: du_max_CFL
907 real,
dimension(SZIB_(G)),
intent(in) :: du_min_CFL
909 real,
intent(in) :: dt
912 real,
dimension(SZIB_(G),SZK_(G)),
intent(in) :: visc_rem
917 real,
dimension(SZIB_(G)),
intent(in) :: visc_rem_max
918 integer,
intent(in) :: j
919 integer,
intent(in) :: ish
920 integer,
intent(in) :: ieh
921 logical,
dimension(SZIB_(G)),
intent(in) :: do_I
924 real,
dimension(SZIB_(G)) :: &
957 nz = g%ke ; idt = 1.0/dt
958 min_visc_rem = 0.1 ; cfl_min = 1e-6
961 do i=ish-1,ieh ; zeros(i) = 0.0 ;
enddo
962 call zonal_flux_adjust(u, h_in, h_l, h_r, zeros, uh_tot_0, &
963 duhdu_tot_0, du0, du_max_cfl, du_min_cfl, dt, g, &
964 cs, visc_rem, j, ish, ieh, do_i, .true.)
971 if (do_i(i)) domore = .true.
972 du_cfl(i) = (cfl_min * idt) * g%dxCu(i,j)
973 dur(i) = min(0.0,du0(i) - du_cfl(i))
974 dul(i) = max(0.0,du0(i) + du_cfl(i))
975 famt_l(i) = 0.0 ; famt_r(i) = 0.0 ; famt_0(i) = 0.0
976 uhtot_l(i) = 0.0 ; uhtot_r(i) = 0.0
979 if (.not.domore)
then
980 do k=1,nz ;
do i=ish-1,ieh
981 bt_cont%FA_u_W0(i,j) = 0.0 ; bt_cont%FA_u_WW(i,j) = 0.0
982 bt_cont%FA_u_E0(i,j) = 0.0 ; bt_cont%FA_u_EE(i,j) = 0.0
983 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
988 do k=1,nz ;
do i=ish-1,ieh ;
if (do_i(i))
then
989 visc_rem_lim = max(visc_rem(i,k), min_visc_rem*visc_rem_max(i))
990 if (visc_rem_lim > 0.0)
then
991 if (u(i,j,k) + dur(i)*visc_rem_lim > -du_cfl(i)*visc_rem(i,k)) &
992 dur(i) = -(u(i,j,k) + du_cfl(i)*visc_rem(i,k)) / visc_rem_lim
993 if (u(i,j,k) + dul(i)*visc_rem_lim < du_cfl(i)*visc_rem(i,k)) &
994 dul(i) = -(u(i,j,k) - du_cfl(i)*visc_rem(i,k)) / visc_rem_lim
996 endif ;
enddo ;
enddo
999 do i=ish-1,ieh ;
if (do_i(i))
then
1000 u_l(i) = u(i,j,k) + dul(i) * visc_rem(i,k)
1001 u_r(i) = u(i,j,k) + dur(i) * visc_rem(i,k)
1002 u_0(i) = u(i,j,k) + du0(i) * visc_rem(i,k)
1004 call zonal_flux_layer(u_0, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_0, &
1005 fa_marg_0, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1007 call zonal_flux_layer(u_l, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_l, &
1008 fa_marg_l, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1010 call zonal_flux_layer(u_r, h_in(:,j,k), h_l(:,j,k), h_r(:,j,k), uh_r, &
1011 fa_marg_r, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1013 do i=ish-1,ieh ;
if (do_i(i))
then
1014 famt_0(i) = famt_0(i) + fa_marg_0(i)
1015 famt_l(i) = famt_l(i) + fa_marg_l(i)
1016 famt_r(i) = famt_r(i) + fa_marg_r(i)
1017 uhtot_l(i) = uhtot_l(i) + uh_l(i)
1018 uhtot_r(i) = uhtot_r(i) + uh_r(i)
1021 do i=ish-1,ieh ;
if (do_i(i))
then
1022 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1023 if ((dul(i) - du0(i)) /= 0.0) &
1024 fa_avg = uhtot_l(i) / (dul(i) - du0(i))
1025 if (fa_avg > max(fa_0, famt_l(i)))
then ; fa_avg = max(fa_0, famt_l(i))
1026 elseif (fa_avg < min(fa_0, famt_l(i)))
then ; fa_0 = fa_avg ;
endif
1028 bt_cont%FA_u_W0(i,j) = us%m_to_L*fa_0 ; bt_cont%FA_u_WW(i,j) = us%m_to_L*famt_l(i)
1029 if (abs(fa_0-famt_l(i)) <= 1e-12*fa_0)
then ; bt_cont%uBT_WW(i,j) = 0.0 ;
else
1030 bt_cont%uBT_WW(i,j) = us%m_s_to_L_T*(1.5 * (dul(i) - du0(i))) * &
1031 ((famt_l(i) - fa_avg) / (famt_l(i) - fa_0))
1034 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1035 if ((dur(i) - du0(i)) /= 0.0) &
1036 fa_avg = uhtot_r(i) / (dur(i) - du0(i))
1037 if (fa_avg > max(fa_0, famt_r(i)))
then ; fa_avg = max(fa_0, famt_r(i))
1038 elseif (fa_avg < min(fa_0, famt_r(i)))
then ; fa_0 = fa_avg ;
endif
1040 bt_cont%FA_u_E0(i,j) = us%m_to_L*fa_0 ; bt_cont%FA_u_EE(i,j) = us%m_to_L*famt_r(i)
1041 if (abs(famt_r(i) - fa_0) <= 1e-12*fa_0)
then ; bt_cont%uBT_EE(i,j) = 0.0 ;
else
1042 bt_cont%uBT_EE(i,j) = us%m_s_to_L_T*(1.5 * (dur(i) - du0(i))) * &
1043 ((famt_r(i) - fa_avg) / (famt_r(i) - fa_0))
1046 bt_cont%FA_u_W0(i,j) = 0.0 ; bt_cont%FA_u_WW(i,j) = 0.0
1047 bt_cont%FA_u_E0(i,j) = 0.0 ; bt_cont%FA_u_EE(i,j) = 0.0
1048 bt_cont%uBT_WW(i,j) = 0.0 ; bt_cont%uBT_EE(i,j) = 0.0
1051 end subroutine set_zonal_bt_cont
1054 subroutine meridional_mass_flux(v, h_in, vh, dt, G, GV, US, CS, LB, vhbt, OBC, &
1055 visc_rem_v, v_cor, vhbt_aux, v_cor_aux, BT_cont)
1058 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1059 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
1061 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(out) :: vh
1063 real,
intent(in) :: dt
1069 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1070 optional,
intent(in) :: visc_rem_v
1075 real,
dimension(SZI_(G),SZJB_(G)),
optional,
intent(in) :: vhbt
1077 real,
dimension(SZI_(G),SZJB_(G)),
optional,
intent(in) :: vhbt_aux
1079 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1080 optional,
intent(out) :: v_cor
1083 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1084 optional,
intent(out) :: v_cor_aux
1090 real,
dimension(SZI_(G),SZK_(G)) :: &
1092 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)) :: &
1094 real,
dimension(SZI_(G)) :: &
1101 logical,
dimension(SZI_(G)) :: do_I
1102 real,
dimension(SZI_(G)) :: FAvi
1104 real,
dimension(SZI_(G),SZK_(G)) :: &
1112 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
1113 logical :: do_aux, local_specified_BC, use_visc_rem, set_BT_cont, any_simple_OBC
1114 logical :: local_Flather_OBC, is_simple, local_open_BC
1117 do_aux = (
present(vhbt_aux) .and.
present(v_cor_aux))
1118 use_visc_rem =
present(visc_rem_v)
1119 local_specified_bc = .false. ; set_bt_cont = .false. ; local_flather_obc = .false.
1120 local_open_bc = .false.
1121 if (
present(bt_cont)) set_bt_cont = (
associated(bt_cont))
1122 if (
present(obc))
then ;
if (
associated(obc))
then ;
if (obc%OBC_pe)
then
1123 local_specified_bc = obc%specified_v_BCs_exist_globally
1124 local_flather_obc = obc%Flather_v_BCs_exist_globally
1125 local_open_bc = obc%open_v_BCs_exist_globally
1126 endif ;
endif ;
endif
1127 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
1129 cfl_dt = cs%CFL_limit_adjust / dt
1131 if (cs%aggress_adjust) cfl_dt = i_dt
1133 call cpu_clock_begin(id_clock_update)
1137 if (cs%upwind_1st)
then
1138 do j=jsh-1,jeh+1 ;
do i=ish,ieh
1139 h_l(i,j,k) = h_in(i,j,k) ; h_r(i,j,k) = h_in(i,j,k)
1142 call ppm_reconstruction_y(h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), g, lb, &
1143 2.0*gv%Angstrom_H, cs%monotonic, simple_2nd=cs%simple_2nd, obc=obc)
1145 do i=ish,ieh ; visc_rem(i,k) = 1.0 ;
enddo
1147 call cpu_clock_end(id_clock_update)
1149 call cpu_clock_begin(id_clock_correct)
1159 do i=ish,ieh ; do_i(i) = .true. ; visc_rem_max(i) = 0.0 ;
enddo
1162 if (use_visc_rem)
then ;
do i=ish,ieh
1163 visc_rem(i,k) = visc_rem_v(i,j,k)
1164 visc_rem_max(i) = max(visc_rem_max(i), visc_rem(i,k))
1166 call merid_flux_layer(v(:,j,k), h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), &
1167 vh(:,j,k), dvhdv(:,k), visc_rem(:,k), &
1168 dt, g, j, ish, ieh, do_i, cs%vol_CFL, obc)
1169 if (local_specified_bc)
then
1171 if (obc%segment(obc%segnum_v(i,j))%specified) &
1172 vh(i,j,k) = obc%segment(obc%segnum_v(i,j))%normal_trans(i,j,k)
1176 if ((.not.use_visc_rem) .or. (.not.cs%use_visc_rem_max))
then ;
do i=ish,ieh
1177 visc_rem_max(i) = 1.0
1180 if (
present(vhbt) .or. do_aux .or. set_bt_cont)
then
1185 if (visc_rem_max(i) > 0.0) i_vrm = 1.0 / visc_rem_max(i)
1186 if (cs%vol_CFL)
then
1187 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1188 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1189 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif
1190 dv_max_cfl(i) = 2.0 * (cfl_dt * dy_s) * i_vrm
1191 dv_min_cfl(i) = -2.0 * (cfl_dt * dy_n) * i_vrm
1192 vh_tot_0(i) = 0.0 ; dvhdv_tot_0(i) = 0.0
1194 do k=1,nz ;
do i=ish,ieh
1195 dvhdv_tot_0(i) = dvhdv_tot_0(i) + dvhdv(i,k)
1196 vh_tot_0(i) = vh_tot_0(i) + vh(i,j,k)
1199 if (use_visc_rem)
then
1200 if (cs%aggress_adjust)
then
1201 do k=1,nz ;
do i=ish,ieh
1202 if (cs%vol_CFL)
then
1203 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1204 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1205 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif
1206 dv_lim = 0.499*((dy_s*i_dt - v(i,j,k)) + min(0.0,v(i,j-1,k)))
1207 if (dv_max_cfl(i) * visc_rem(i,k) > dv_lim) &
1208 dv_max_cfl(i) = dv_lim / visc_rem(i,k)
1210 dv_lim = 0.499*((-dy_n*cfl_dt - v(i,j,k)) + max(0.0,v(i,j+1,k)))
1211 if (dv_min_cfl(i) * visc_rem(i,k) < dv_lim) &
1212 dv_min_cfl(i) = dv_lim / visc_rem(i,k)
1215 do k=1,nz ;
do i=ish,ieh
1216 if (cs%vol_CFL)
then
1217 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1218 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1219 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif
1220 if (dv_max_cfl(i) * visc_rem(i,k) > dy_s*cfl_dt - v(i,j,k)) &
1221 dv_max_cfl(i) = (dy_s*cfl_dt - v(i,j,k)) / visc_rem(i,k)
1222 if (dv_min_cfl(i) * visc_rem(i,k) < -dy_n*cfl_dt - v(i,j,k)) &
1223 dv_min_cfl(i) = -(dy_n*cfl_dt + v(i,j,k)) / visc_rem(i,k)
1227 if (cs%aggress_adjust)
then
1228 do k=1,nz ;
do i=ish,ieh
1229 if (cs%vol_CFL)
then
1230 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1231 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1232 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif
1233 dv_max_cfl(i) = min(dv_max_cfl(i), 0.499 * &
1234 ((dy_s*i_dt - v(i,j,k)) + min(0.0,v(i,j-1,k))) )
1235 dv_min_cfl(i) = max(dv_min_cfl(i), 0.499 * &
1236 ((-dy_n*i_dt - v(i,j,k)) + max(0.0,v(i,j+1,k))) )
1239 do k=1,nz ;
do i=ish,ieh
1240 if (cs%vol_CFL)
then
1241 dy_s = ratio_max(g%areaT(i,j), g%dx_Cv(i,j), 1000.0*g%dyT(i,j))
1242 dy_n = ratio_max(g%areaT(i,j+1), g%dx_Cv(i,j), 1000.0*g%dyT(i,j+1))
1243 else ; dy_s = g%dyT(i,j) ; dy_n = g%dyT(i,j+1) ;
endif
1244 dv_max_cfl(i) = min(dv_max_cfl(i), dy_s*cfl_dt - v(i,j,k))
1245 dv_min_cfl(i) = max(dv_min_cfl(i), -(dy_n*cfl_dt + v(i,j,k)))
1250 dv_max_cfl(i) = max(dv_max_cfl(i),0.0)
1251 dv_min_cfl(i) = min(dv_min_cfl(i),0.0)
1256 any_simple_obc = .false.
1257 if (
present(vhbt) .or. do_aux .or. set_bt_cont)
then
1258 if (local_specified_bc .or. local_flather_obc)
then ;
do i=ish,ieh
1260 is_simple = obc%segment(obc%segnum_v(i,j))%specified
1261 do_i(i) = .not.(obc%segnum_v(i,j) /= obc_none .and. is_simple)
1262 any_simple_obc = any_simple_obc .or. is_simple
1263 enddo ;
else ;
do i=ish,ieh
1268 if (
present(vhbt))
then
1269 call meridional_flux_adjust(v, h_in, h_l, h_r, vhbt(:,j), vh_tot_0, &
1270 dvhdv_tot_0, dv, dv_max_cfl, dv_min_cfl, dt, g, &
1271 cs, visc_rem, j, ish, ieh, do_i, .true., vh, obc=obc)
1273 if (
present(v_cor))
then ;
do k=1,nz
1274 do i=ish,ieh ; v_cor(i,j,k) = v(i,j,k) + dv(i) * visc_rem(i,k) ;
enddo
1275 if (local_specified_bc)
then ;
do i=ish,ieh
1276 if (obc%segment(obc%segnum_v(i,j))%specified) &
1277 v_cor(i,j,k) = obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)
1283 call meridional_flux_adjust(v, h_in, h_l, h_r, vhbt_aux(:,j), vh_tot_0, &
1284 dvhdv_tot_0, dv, dv_max_cfl, dv_min_cfl, dt, g, &
1285 cs, visc_rem, j, ish, ieh, do_i, .false., obc=obc)
1288 do i=ish,ieh ; v_cor_aux(i,j,k) = v(i,j,k) + dv(i) * visc_rem(i,k) ;
enddo
1289 if (local_specified_bc)
then ;
do i=ish,ieh
1290 if (obc%segment(obc%segnum_v(i,j))%specified) &
1291 v_cor_aux(i,j,k) = obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)
1296 if (set_bt_cont)
then
1297 call set_merid_bt_cont(v, h_in, h_l, h_r, bt_cont, vh_tot_0, dvhdv_tot_0,&
1298 dv_max_cfl, dv_min_cfl, dt, g, us, cs, visc_rem, &
1299 visc_rem_max, j, ish, ieh, do_i)
1300 if (any_simple_obc)
then
1302 do_i(i) = (obc%segment(obc%segnum_v(i,j))%specified)
1303 if (do_i(i)) favi(i) = gv%H_subroundoff*g%dx_Cv(i,j)
1305 do k=1,nz ;
do i=ish,ieh ;
if (do_i(i))
then
1306 if ((abs(obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)) > 0.0) .and. &
1307 (obc%segment(obc%segnum_v(i,j))%specified)) &
1308 favi(i) = favi(i) + &
1309 obc%segment(obc%segnum_v(i,j))%normal_trans(i,j,k) / &
1310 obc%segment(obc%segnum_v(i,j))%normal_vel(i,j,k)
1311 endif ;
enddo ;
enddo
1312 do i=ish,ieh ;
if (do_i(i))
then
1313 bt_cont%FA_v_S0(i,j) = us%m_to_L*favi(i) ; bt_cont%FA_v_N0(i,j) = us%m_to_L*favi(i)
1314 bt_cont%FA_v_SS(i,j) = us%m_to_L*favi(i) ; bt_cont%FA_v_NN(i,j) = us%m_to_L*favi(i)
1315 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1323 if (local_open_bc .and. set_bt_cont)
then
1324 do n = 1, obc%number_of_segments
1325 if (obc%segment(n)%open .and. obc%segment(n)%is_N_or_S)
then
1326 j = obc%segment(n)%HI%JsdB
1327 if (obc%segment(n)%direction == obc_direction_n)
then
1328 do i = obc%segment(n)%HI%Isd, obc%segment(n)%HI%Ied
1330 do k=1,nz ; fa_v = fa_v + h_in(i,j,k)*us%m_to_L*g%dx_Cv(i,j) ;
enddo
1331 bt_cont%FA_v_S0(i,j) = fa_v ; bt_cont%FA_v_N0(i,j) = fa_v
1332 bt_cont%FA_v_SS(i,j) = fa_v ; bt_cont%FA_v_NN(i,j) = fa_v
1333 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1336 do i = obc%segment(n)%HI%Isd, obc%segment(n)%HI%Ied
1338 do k=1,nz ; fa_v = fa_v + h_in(i,j+1,k)*us%m_to_L*g%dx_Cv(i,j) ;
enddo
1339 bt_cont%FA_v_S0(i,j) = fa_v ; bt_cont%FA_v_N0(i,j) = fa_v
1340 bt_cont%FA_v_SS(i,j) = fa_v ; bt_cont%FA_v_NN(i,j) = fa_v
1341 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1347 call cpu_clock_end(id_clock_correct)
1349 if (set_bt_cont)
then ;
if (
allocated(bt_cont%h_v))
then
1350 if (
present(v_cor))
then
1351 call merid_face_thickness(v_cor, h_in, h_l, h_r, bt_cont%h_v, dt, g, lb, &
1352 cs%vol_CFL, cs%marginal_faces, visc_rem_v, obc)
1354 call merid_face_thickness(v, h_in, h_l, h_r, bt_cont%h_v, dt, g, lb, &
1355 cs%vol_CFL, cs%marginal_faces, visc_rem_v, obc)
1359 end subroutine meridional_mass_flux
1362 subroutine merid_flux_layer(v, h, h_L, h_R, vh, dvhdv, visc_rem, dt, G, J, &
1363 ish, ieh, do_I, vol_CFL, OBC)
1365 real,
dimension(SZI_(G)),
intent(in) :: v
1366 real,
dimension(SZI_(G)),
intent(in) :: visc_rem
1371 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h
1373 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_L
1375 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_R
1377 real,
dimension(SZI_(G)),
intent(inout) :: vh
1379 real,
dimension(SZI_(G)),
intent(inout) :: dvhdv
1381 real,
intent(in) :: dt
1382 integer,
intent(in) :: j
1383 integer,
intent(in) :: ish
1384 integer,
intent(in) :: ieh
1385 logical,
dimension(SZI_(G)),
intent(in) :: do_I
1386 logical,
intent(in) :: vol_CFL
1395 logical :: local_open_BC
1397 local_open_bc = .false.
1398 if (
present(obc))
then ;
if (
associated(obc))
then
1399 local_open_bc = obc%open_u_BCs_exist_globally
1402 do i=ish,ieh ;
if (do_i(i))
then
1403 if (v(i) > 0.0)
then
1404 if (vol_cfl)
then ; cfl = (v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1405 else ; cfl = v(i) * dt * g%IdyT(i,j) ;
endif
1406 curv_3 = h_l(i,j) + h_r(i,j) - 2.0*h(i,j)
1407 vh(i) = g%dx_Cv(i,j) * v(i) * ( h_r(i,j) + cfl * &
1408 (0.5*(h_l(i,j) - h_r(i,j)) + curv_3*(cfl - 1.5)) )
1409 h_marg = h_r(i,j) + cfl * ((h_l(i,j) - h_r(i,j)) + &
1410 3.0*curv_3*(cfl - 1.0))
1411 elseif (v(i) < 0.0)
then
1412 if (vol_cfl)
then ; cfl = (-v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1413 else ; cfl = -v(i) * dt * g%IdyT(i,j+1) ;
endif
1414 curv_3 = h_l(i,j+1) + h_r(i,j+1) - 2.0*h(i,j+1)
1415 vh(i) = g%dx_Cv(i,j) * v(i) * ( h_l(i,j+1) + cfl * &
1416 (0.5*(h_r(i,j+1)-h_l(i,j+1)) + curv_3*(cfl - 1.5)) )
1417 h_marg = h_l(i,j+1) + cfl * ((h_r(i,j+1)-h_l(i,j+1)) + &
1418 3.0*curv_3*(cfl - 1.0))
1421 h_marg = 0.5 * (h_l(i,j+1) + h_r(i,j))
1423 dvhdv(i) = g%dx_Cv(i,j) * h_marg * visc_rem(i)
1426 if (local_open_bc)
then
1427 do i=ish,ieh ;
if (do_i(i))
then
1428 if (obc%segment(obc%segnum_v(i,j))%open)
then
1429 if (obc%segment(obc%segnum_v(i,j))%direction == obc_direction_n)
then
1430 vh(i) = g%dx_Cv(i,j) * v(i) * h(i,j)
1431 dvhdv(i) = g%dx_Cv(i,j) * h(i,j) * visc_rem(i)
1433 vh(i) = g%dx_Cv(i,j) * v(i) * h(i,j+1)
1434 dvhdv(i) = g%dx_Cv(i,j) * h(i,j+1) * visc_rem(i)
1439 end subroutine merid_flux_layer
1442 subroutine merid_face_thickness(v, h, h_L, h_R, h_v, dt, G, LB, vol_CFL, &
1443 marginal, visc_rem_v, OBC)
1445 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1446 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
1448 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
1450 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
1452 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(inout) :: h_v
1454 real,
intent(in) :: dt
1456 logical,
intent(in) :: vol_CFL
1458 logical,
intent(in) :: marginal
1460 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
optional,
intent(in) :: visc_rem_v
1473 logical :: local_open_BC
1474 integer :: i, j, k, ish, ieh, jsh, jeh, n, nz
1475 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh ; nz = g%ke
1478 do k=1,nz ;
do j=jsh-1,jeh ;
do i=ish,ieh
1479 if (v(i,j,k) > 0.0)
then
1480 if (vol_cfl)
then ; cfl = (v(i,j,k) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1481 else ; cfl = v(i,j,k) * dt * g%IdyT(i,j) ;
endif
1482 curv_3 = h_l(i,j,k) + h_r(i,j,k) - 2.0*h(i,j,k)
1483 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))
1484 h_marg = h_r(i,j,k) + cfl * ((h_l(i,j,k) - h_r(i,j,k)) + &
1485 3.0*curv_3*(cfl - 1.0))
1486 elseif (v(i,j,k) < 0.0)
then
1487 if (vol_cfl)
then ; cfl = (-v(i,j,k)*dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1488 else ; cfl = -v(i,j,k) * dt * g%IdyT(i,j+1) ;
endif
1489 curv_3 = h_l(i,j+1,k) + h_r(i,j+1,k) - 2.0*h(i,j+1,k)
1490 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))
1491 h_marg = h_l(i,j+1,k) + cfl * ((h_r(i,j+1,k)-h_l(i,j+1,k)) + &
1492 3.0*curv_3*(cfl - 1.0))
1494 h_avg = 0.5 * (h_l(i,j+1,k) + h_r(i,j,k))
1497 h_marg = 0.5 * (h_l(i,j+1,k) + h_r(i,j,k))
1502 if (marginal)
then ; h_v(i,j,k) = h_marg
1503 else ; h_v(i,j,k) = h_avg ;
endif
1504 enddo ;
enddo ;
enddo
1506 if (
present(visc_rem_v))
then
1508 do k=1,nz ;
do j=jsh-1,jeh ;
do i=ish,ieh
1509 h_v(i,j,k) = h_v(i,j,k) * visc_rem_v(i,j,k)
1510 enddo ;
enddo ;
enddo
1513 local_open_bc = .false.
1514 if (
present(obc))
then ;
if (
associated(obc))
then
1515 local_open_bc = obc%open_u_BCs_exist_globally
1517 if (local_open_bc)
then
1518 do n = 1, obc%number_of_segments
1519 if (obc%segment(n)%open .and. obc%segment(n)%is_N_or_S)
then
1520 j = obc%segment(n)%HI%JsdB
1521 if (obc%segment(n)%direction == obc_direction_n)
then
1522 if (
present(visc_rem_v))
then ;
do k=1,nz
1523 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1524 h_v(i,j,k) = h(i,j,k) * visc_rem_v(i,j,k)
1526 enddo ;
else ;
do k=1,nz
1527 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1528 h_v(i,j,k) = h(i,j,k)
1532 if (
present(visc_rem_v))
then ;
do k=1,nz
1533 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1534 h_v(i,j,k) = h(i,j+1,k) * visc_rem_v(i,j,k)
1536 enddo ;
else ;
do k=1,nz
1537 do i = obc%segment(n)%HI%isd, obc%segment(n)%HI%ied
1538 h_v(i,j,k) = h(i,j+1,k)
1546 end subroutine merid_face_thickness
1549 subroutine meridional_flux_adjust(v, h_in, h_L, h_R, vhbt, vh_tot_0, dvhdv_tot_0, &
1550 dv, dv_max_CFL, dv_min_CFL, dt, G, CS, visc_rem, &
1551 j, ish, ieh, do_I_in, full_precision, vh_3d, OBC)
1553 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1555 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1557 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),&
1559 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
1561 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: visc_rem
1567 real,
dimension(SZI_(G)), &
1568 optional,
intent(in) :: vhbt
1570 real,
dimension(SZI_(G)),
intent(in) :: dv_max_CFL
1571 real,
dimension(SZI_(G)),
intent(in) :: dv_min_CFL
1572 real,
dimension(SZI_(G)),
intent(in) :: vh_tot_0
1574 real,
dimension(SZI_(G)),
intent(in) :: dvhdv_tot_0
1576 real,
dimension(SZI_(G)),
intent(out) :: dv
1577 real,
intent(in) :: dt
1579 integer,
intent(in) :: j
1580 integer,
intent(in) :: ish
1581 integer,
intent(in) :: ieh
1582 logical,
dimension(SZI_(G)), &
1583 intent(in) :: do_I_in
1584 logical,
optional,
intent(in) :: full_precision
1586 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)), &
1587 optional,
intent(inout) :: vh_3d
1591 real,
dimension(SZI_(G),SZK_(G)) :: &
1594 real,
dimension(SZI_(G)) :: &
1605 integer :: i, k, nz, itt, max_itts = 20
1606 logical :: full_prec, domore, do_I(SZI_(G))
1609 full_prec = .true. ;
if (
present(full_precision)) full_prec = full_precision
1611 vh_aux(:,:) = 0.0 ; dvhdv(:,:) = 0.0
1613 if (
present(vh_3d))
then ;
do k=1,nz ;
do i=ish,ieh
1614 vh_aux(i,k) = vh_3d(i,j,k)
1615 enddo ;
enddo ;
endif
1618 dv(i) = 0.0 ; do_i(i) = do_i_in(i)
1619 dv_max(i) = dv_max_cfl(i) ; dv_min(i) = dv_min_cfl(i)
1620 vh_err(i) = vh_tot_0(i) - vhbt(i) ; dvhdv_tot(i) = dvhdv_tot_0(i)
1621 vh_err_best(i) = abs(vh_err(i))
1627 case (:1) ; tol_eta = 1e-6 * cs%tol_eta
1628 case (2) ; tol_eta = 1e-4 * cs%tol_eta
1629 case (3) ; tol_eta = 1e-2 * cs%tol_eta
1630 case default ; tol_eta = cs%tol_eta
1633 tol_eta = cs%tol_eta_aux ;
if (itt<=1) tol_eta = 1e-6 * cs%tol_eta_aux
1635 tol_vel = cs%tol_vel
1638 if (vh_err(i) > 0.0)
then ; dv_max(i) = dv(i)
1639 elseif (vh_err(i) < 0.0)
then ; dv_min(i) = dv(i)
1640 else ; do_i(i) = .false. ;
endif
1643 do i=ish,ieh ;
if (do_i(i))
then
1644 if ((dt*min(g%IareaT(i,j),g%IareaT(i,j+1))*abs(vh_err(i)) > tol_eta) .or.&
1645 (cs%better_iter .and. ((abs(vh_err(i)) > tol_vel * dvhdv_tot(i)) .or.&
1646 (abs(vh_err(i)) > vh_err_best(i))) ))
then
1650 ddv = -vh_err(i) / dvhdv_tot(i)
1653 if (abs(ddv) < 1.0e-15*abs(dv(i)))
then
1655 elseif (ddv > 0.0)
then
1656 if (dv(i) >= dv_max(i))
then
1657 dv(i) = 0.5*(dv_prev + dv_max(i))
1658 if (dv_max(i) - dv_prev < 1.0e-15*abs(dv(i))) do_i(i) = .false.
1661 if (dv(i) <= dv_min(i))
then
1662 dv(i) = 0.5*(dv_prev + dv_min(i))
1663 if (dv_prev - dv_min(i) < 1.0e-15*abs(dv(i))) do_i(i) = .false.
1668 dv(i) = dv(i) - vh_err(i) / dvhdv_tot(i)
1669 if ((dv(i) >= dv_max(i)) .or. (dv(i) <= dv_min(i))) &
1670 dv(i) = 0.5*(dv_max(i) + dv_min(i))
1672 if (do_i(i)) domore = .true.
1677 if (.not.domore)
exit
1679 if ((itt < max_itts) .or.
present(vh_3d))
then ;
do k=1,nz
1680 do i=ish,ieh ; v_new(i) = v(i,j,k) + dv(i) * visc_rem(i,k) ;
enddo
1681 call merid_flux_layer(v_new, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), &
1682 vh_aux(:,k), dvhdv(:,k), visc_rem(:,k), &
1683 dt, g, j, ish, ieh, do_i, cs%vol_CFL, obc)
1686 if (itt < max_itts)
then
1688 vh_err(i) = -vhbt(i) ; dvhdv_tot(i) = 0.0
1690 do k=1,nz ;
do i=ish,ieh
1691 vh_err(i) = vh_err(i) + vh_aux(i,k)
1692 dvhdv_tot(i) = dvhdv_tot(i) + dvhdv(i,k)
1695 vh_err_best(i) = min(vh_err_best(i), abs(vh_err(i)))
1703 if (
present(vh_3d))
then ;
do k=1,nz ;
do i=ish,ieh
1704 vh_3d(i,j,k) = vh_aux(i,k)
1705 enddo ;
enddo ;
endif
1707 end subroutine meridional_flux_adjust
1711 subroutine set_merid_bt_cont(v, h_in, h_L, h_R, BT_cont, vh_tot_0, dvhdv_tot_0, &
1712 dv_max_CFL, dv_min_CFL, dt, G, US, CS, visc_rem, &
1713 visc_rem_max, j, ish, ieh, do_I)
1715 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
1716 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_in
1718 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_L
1720 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h_R
1724 real,
dimension(SZI_(G)),
intent(in) :: vh_tot_0
1726 real,
dimension(SZI_(G)),
intent(in) :: dvhdv_tot_0
1728 real,
dimension(SZI_(G)),
intent(in) :: dv_max_CFL
1729 real,
dimension(SZI_(G)),
intent(in) :: dv_min_CFL
1730 real,
intent(in) :: dt
1733 real,
dimension(SZI_(G),SZK_(G)),
intent(in) :: visc_rem
1738 real,
dimension(SZI_(G)),
intent(in) :: visc_rem_max
1739 integer,
intent(in) :: j
1740 integer,
intent(in) :: ish
1741 integer,
intent(in) :: ieh
1742 logical,
dimension(SZI_(G)),
intent(in) :: do_I
1745 real,
dimension(SZI_(G)) :: &
1765 real :: visc_rem_lim
1768 real :: min_visc_rem
1778 nz = g%ke ; idt = 1.0/dt
1779 min_visc_rem = 0.1 ; cfl_min = 1e-6
1782 do i=ish,ieh ; zeros(i) = 0.0 ;
enddo
1783 call meridional_flux_adjust(v, h_in, h_l, h_r, zeros, vh_tot_0, &
1784 dvhdv_tot_0, dv0, dv_max_cfl, dv_min_cfl, dt, g, &
1785 cs, visc_rem, j, ish, ieh, do_i, .true.)
1791 do i=ish,ieh ;
if (do_i(i))
then
1793 dv_cfl(i) = (cfl_min * idt) * g%dyCv(i,j)
1794 dvr(i) = min(0.0,dv0(i) - dv_cfl(i))
1795 dvl(i) = max(0.0,dv0(i) + dv_cfl(i))
1796 famt_l(i) = 0.0 ; famt_r(i) = 0.0 ; famt_0(i) = 0.0
1797 vhtot_l(i) = 0.0 ; vhtot_r(i) = 0.0
1800 if (.not.domore)
then
1801 do k=1,nz ;
do i=ish,ieh
1802 bt_cont%FA_v_S0(i,j) = 0.0 ; bt_cont%FA_v_SS(i,j) = 0.0
1803 bt_cont%vBT_SS(i,j) = 0.0
1804 bt_cont%FA_v_N0(i,j) = 0.0 ; bt_cont%FA_v_NN(i,j) = 0.0
1805 bt_cont%vBT_NN(i,j) = 0.0
1810 do k=1,nz ;
do i=ish,ieh ;
if (do_i(i))
then
1811 visc_rem_lim = max(visc_rem(i,k), min_visc_rem*visc_rem_max(i))
1812 if (visc_rem_lim > 0.0)
then
1813 if (v(i,j,k) + dvr(i)*visc_rem_lim > -dv_cfl(i)*visc_rem(i,k)) &
1814 dvr(i) = -(v(i,j,k) + dv_cfl(i)*visc_rem(i,k)) / visc_rem_lim
1815 if (v(i,j,k) + dvl(i)*visc_rem_lim < dv_cfl(i)*visc_rem(i,k)) &
1816 dvl(i) = -(v(i,j,k) - dv_cfl(i)*visc_rem(i,k)) / visc_rem_lim
1818 endif ;
enddo ;
enddo
1820 do i=ish,ieh ;
if (do_i(i))
then
1821 v_l(i) = v(i,j,k) + dvl(i) * visc_rem(i,k)
1822 v_r(i) = v(i,j,k) + dvr(i) * visc_rem(i,k)
1823 v_0(i) = v(i,j,k) + dv0(i) * visc_rem(i,k)
1825 call merid_flux_layer(v_0, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_0, &
1826 fa_marg_0, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1828 call merid_flux_layer(v_l, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_l, &
1829 fa_marg_l, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1831 call merid_flux_layer(v_r, h_in(:,:,k), h_l(:,:,k), h_r(:,:,k), vh_r, &
1832 fa_marg_r, visc_rem(:,k), dt, g, j, ish, ieh, do_i, &
1834 do i=ish,ieh ;
if (do_i(i))
then
1835 famt_0(i) = famt_0(i) + fa_marg_0(i)
1836 famt_l(i) = famt_l(i) + fa_marg_l(i)
1837 famt_r(i) = famt_r(i) + fa_marg_r(i)
1838 vhtot_l(i) = vhtot_l(i) + vh_l(i)
1839 vhtot_r(i) = vhtot_r(i) + vh_r(i)
1842 do i=ish,ieh ;
if (do_i(i))
then
1843 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1844 if ((dvl(i) - dv0(i)) /= 0.0) &
1845 fa_avg = vhtot_l(i) / (dvl(i) - dv0(i))
1846 if (fa_avg > max(fa_0, famt_l(i)))
then ; fa_avg = max(fa_0, famt_l(i))
1847 elseif (fa_avg < min(fa_0, famt_l(i)))
then ; fa_0 = fa_avg ;
endif
1848 bt_cont%FA_v_S0(i,j) = us%m_to_L*fa_0 ; bt_cont%FA_v_SS(i,j) = us%m_to_L*famt_l(i)
1849 if (abs(fa_0-famt_l(i)) <= 1e-12*fa_0)
then ; bt_cont%vBT_SS(i,j) = 0.0 ;
else
1850 bt_cont%vBT_SS(i,j) = us%m_s_to_L_T*(1.5 * (dvl(i) - dv0(i))) * &
1851 ((famt_l(i) - fa_avg) / (famt_l(i) - fa_0))
1854 fa_0 = famt_0(i) ; fa_avg = famt_0(i)
1855 if ((dvr(i) - dv0(i)) /= 0.0) &
1856 fa_avg = vhtot_r(i) / (dvr(i) - dv0(i))
1857 if (fa_avg > max(fa_0, famt_r(i)))
then ; fa_avg = max(fa_0, famt_r(i))
1858 elseif (fa_avg < min(fa_0, famt_r(i)))
then ; fa_0 = fa_avg ;
endif
1859 bt_cont%FA_v_N0(i,j) = us%m_to_L*fa_0 ; bt_cont%FA_v_NN(i,j) = us%m_to_L*famt_r(i)
1860 if (abs(famt_r(i) - fa_0) <= 1e-12*fa_0)
then ; bt_cont%vBT_NN(i,j) = 0.0 ;
else
1861 bt_cont%vBT_NN(i,j) = us%m_s_to_L_T*(1.5 * (dvr(i) - dv0(i))) * &
1862 ((famt_r(i) - fa_avg) / (famt_r(i) - fa_0))
1865 bt_cont%FA_v_S0(i,j) = 0.0 ; bt_cont%FA_v_SS(i,j) = 0.0
1866 bt_cont%FA_v_N0(i,j) = 0.0 ; bt_cont%FA_v_NN(i,j) = 0.0
1867 bt_cont%vBT_SS(i,j) = 0.0 ; bt_cont%vBT_NN(i,j) = 0.0
1870 end subroutine set_merid_bt_cont
1873 subroutine ppm_reconstruction_x(h_in, h_L, h_R, G, LB, h_min, monotonic, simple_2nd, OBC)
1875 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1876 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_L
1878 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_R
1881 real,
intent(in) :: h_min
1883 logical,
optional,
intent(in) :: monotonic
1886 logical,
optional,
intent(in) :: simple_2nd
1892 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1893 real,
parameter :: oneSixth = 1./6.
1894 real :: h_ip1, h_im1
1896 logical :: use_CW84, use_2nd
1897 character(len=256) :: mesg
1898 integer :: i, j, isl, iel, jsl, jel, n, stencil
1899 logical :: local_open_BC
1902 use_cw84 = .false. ;
if (
present(monotonic)) use_cw84 = monotonic
1903 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1905 local_open_bc = .false.
1906 if (
present(obc))
then ;
if (
associated(obc))
then
1907 local_open_bc = obc%open_u_BCs_exist_globally
1910 isl = lb%ish-1 ; iel = lb%ieh+1 ; jsl = lb%jsh ; jel = lb%jeh
1913 stencil = 2 ;
if (use_2nd) stencil = 1
1915 if ((isl-stencil < g%isd) .or. (iel+stencil > g%ied))
then
1916 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_x called with a ", &
1917 & "x-halo that needs to be increased by ",i2,".")') &
1918 stencil + max(g%isd-isl,iel-g%ied)
1919 call mom_error(fatal,mesg)
1921 if ((jsl < g%jsd) .or. (jel > g%jed))
then
1922 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_x called with a ", &
1923 & "y-halo that needs to be increased by ",i2,".")') &
1924 max(g%jsd-jsl,jel-g%jed)
1925 call mom_error(fatal,mesg)
1929 do j=jsl,jel ;
do i=isl,iel
1930 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1931 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1932 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) )
1933 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) )
1936 do j=jsl,jel ;
do i=isl-1,iel+1
1937 if ((g%mask2dT(i-1,j) * g%mask2dT(i,j) * g%mask2dT(i+1,j)) == 0.0)
then
1941 slp(i,j) = 0.5 * (h_in(i+1,j) - h_in(i-1,j))
1943 dmx = max(h_in(i+1,j), h_in(i-1,j), h_in(i,j)) - h_in(i,j)
1944 dmn = h_in(i,j) - min(h_in(i+1,j), h_in(i-1,j), h_in(i,j))
1945 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
1950 if (local_open_bc)
then
1951 do n=1, obc%number_of_segments
1952 segment => obc%segment(n)
1953 if (.not. segment%on_pe) cycle
1954 if (segment%direction == obc_direction_e .or. &
1955 segment%direction == obc_direction_w)
then
1957 do j=segment%HI%jsd,segment%HI%jed
1965 do j=jsl,jel ;
do i=isl,iel
1970 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1971 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1973 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) ) + onesixth*( slp(i-1,j) - slp(i,j) )
1974 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i+1,j) )
1978 if (local_open_bc)
then
1979 do n=1, obc%number_of_segments
1980 segment => obc%segment(n)
1981 if (.not. segment%on_pe) cycle
1982 if (segment%direction == obc_direction_e)
then
1984 do j=segment%HI%jsd,segment%HI%jed
1985 h_l(i+1,j) = h_in(i,j)
1986 h_r(i+1,j) = h_in(i,j)
1987 h_l(i,j) = h_in(i,j)
1988 h_r(i,j) = h_in(i,j)
1990 elseif (segment%direction == obc_direction_w)
then
1992 do j=segment%HI%jsd,segment%HI%jed
1993 h_l(i,j) = h_in(i+1,j)
1994 h_r(i,j) = h_in(i+1,j)
1995 h_l(i+1,j) = h_in(i+1,j)
1996 h_r(i+1,j) = h_in(i+1,j)
2003 call ppm_limit_cw84(h_in, h_l, h_r, g, isl, iel, jsl, jel)
2005 call ppm_limit_pos(h_in, h_l, h_r, h_min, g, isl, iel, jsl, jel)
2009 end subroutine ppm_reconstruction_x
2012 subroutine ppm_reconstruction_y(h_in, h_L, h_R, G, LB, h_min, monotonic, simple_2nd, OBC)
2014 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2015 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_L
2017 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_R
2020 real,
intent(in) :: h_min
2022 logical,
optional,
intent(in) :: monotonic
2025 logical,
optional,
intent(in) :: simple_2nd
2031 real,
dimension(SZI_(G),SZJ_(G)) :: slp
2032 real,
parameter :: oneSixth = 1./6.
2033 real :: h_jp1, h_jm1
2035 logical :: use_CW84, use_2nd
2036 character(len=256) :: mesg
2037 integer :: i, j, isl, iel, jsl, jel, n, stencil
2038 logical :: local_open_BC
2041 use_cw84 = .false. ;
if (
present(monotonic)) use_cw84 = monotonic
2042 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
2044 local_open_bc = .false.
2045 if (
present(obc))
then ;
if (
associated(obc))
then
2046 local_open_bc = obc%open_u_BCs_exist_globally
2049 isl = lb%ish ; iel = lb%ieh ; jsl = lb%jsh-1 ; jel = lb%jeh+1
2052 stencil = 2 ;
if (use_2nd) stencil = 1
2054 if ((isl < g%isd) .or. (iel > g%ied))
then
2055 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_y called with a ", &
2056 & "x-halo that needs to be increased by ",i2,".")') &
2057 max(g%isd-isl,iel-g%ied)
2058 call mom_error(fatal,mesg)
2060 if ((jsl-stencil < g%jsd) .or. (jel+stencil > g%jed))
then
2061 write(mesg,
'("In MOM_continuity_PPM, PPM_reconstruction_y called with a ", &
2062 & "y-halo that needs to be increased by ",i2,".")') &
2063 stencil + max(g%jsd-jsl,jel-g%jed)
2064 call mom_error(fatal,mesg)
2068 do j=jsl,jel ;
do i=isl,iel
2069 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2070 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2071 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) )
2072 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) )
2075 do j=jsl-1,jel+1 ;
do i=isl,iel
2076 if ((g%mask2dT(i,j-1) * g%mask2dT(i,j) * g%mask2dT(i,j+1)) == 0.0)
then
2080 slp(i,j) = 0.5 * (h_in(i,j+1) - h_in(i,j-1))
2082 dmx = max(h_in(i,j+1), h_in(i,j-1), h_in(i,j)) - h_in(i,j)
2083 dmn = h_in(i,j) - min(h_in(i,j+1), h_in(i,j-1), h_in(i,j))
2084 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
2089 if (local_open_bc)
then
2090 do n=1, obc%number_of_segments
2091 segment => obc%segment(n)
2092 if (.not. segment%on_pe) cycle
2093 if (segment%direction == obc_direction_s .or. &
2094 segment%direction == obc_direction_n)
then
2096 do i=segment%HI%isd,segment%HI%ied
2104 do j=jsl,jel ;
do i=isl,iel
2107 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2108 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2110 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) ) + onesixth*( slp(i,j-1) - slp(i,j) )
2111 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i,j+1) )
2115 if (local_open_bc)
then
2116 do n=1, obc%number_of_segments
2117 segment => obc%segment(n)
2118 if (.not. segment%on_pe) cycle
2119 if (segment%direction == obc_direction_n)
then
2121 do i=segment%HI%isd,segment%HI%ied
2122 h_l(i,j+1) = h_in(i,j)
2123 h_r(i,j+1) = h_in(i,j)
2124 h_l(i,j) = h_in(i,j)
2125 h_r(i,j) = h_in(i,j)
2127 elseif (segment%direction == obc_direction_s)
then
2129 do i=segment%HI%isd,segment%HI%ied
2130 h_l(i,j) = h_in(i,j+1)
2131 h_r(i,j) = h_in(i,j+1)
2132 h_l(i,j+1) = h_in(i,j+1)
2133 h_r(i,j+1) = h_in(i,j+1)
2140 call ppm_limit_cw84(h_in, h_l, h_r, g, isl, iel, jsl, jel)
2142 call ppm_limit_pos(h_in, h_l, h_r, h_min, g, isl, iel, jsl, jel)
2146 end subroutine ppm_reconstruction_y
2152 subroutine ppm_limit_pos(h_in, h_L, h_R, h_min, G, iis, iie, jis, jie)
2154 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2155 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2156 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2157 real,
intent(in) :: h_min
2159 integer,
intent(in) :: iis
2160 integer,
intent(in) :: iie
2161 integer,
intent(in) :: jis
2162 integer,
intent(in) :: jie
2165 real :: curv, dh, scale
2166 character(len=256) :: mesg
2169 do j=jis,jie ;
do i=iis,iie
2172 curv = 3.0*(h_l(i,j) + h_r(i,j) - 2.0*h_in(i,j))
2173 if (curv > 0.0)
then
2174 dh = h_r(i,j) - h_l(i,j)
2175 if (abs(dh) < curv)
then
2176 if (h_in(i,j) <= h_min)
then
2177 h_l(i,j) = h_in(i,j) ; h_r(i,j) = h_in(i,j)
2178 elseif (12.0*curv*(h_in(i,j) - h_min) < (curv**2 + 3.0*dh**2))
then
2181 scale = 12.0*curv*(h_in(i,j) - h_min) / (curv**2 + 3.0*dh**2)
2182 h_l(i,j) = h_in(i,j) + scale*(h_l(i,j) - h_in(i,j))
2183 h_r(i,j) = h_in(i,j) + scale*(h_r(i,j) - h_in(i,j))
2189 end subroutine ppm_limit_pos
2193 subroutine ppm_limit_cw84(h_in, h_L, h_R, G, iis, iie, jis, jie)
2195 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2196 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2198 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2200 integer,
intent(in) :: iis
2201 integer,
intent(in) :: iie
2202 integer,
intent(in) :: jis
2203 integer,
intent(in) :: jie
2206 real :: h_i, RLdiff, RLdiff2, RLmean, FunFac
2207 character(len=256) :: mesg
2210 do j=jis,jie ;
do i=iis,iie
2214 if ( ( h_r(i,j) - h_i ) * ( h_i - h_l(i,j) ) <= 0. )
then
2215 h_l(i,j) = h_i ; h_r(i,j) = h_i
2217 rldiff = h_r(i,j) - h_l(i,j)
2218 rlmean = 0.5 * ( h_r(i,j) + h_l(i,j) )
2219 funfac = 6. * rldiff * ( h_i - rlmean )
2220 rldiff2 = rldiff * rldiff
2221 if ( funfac > rldiff2 ) h_l(i,j) = 3. * h_i - 2. * h_r(i,j)
2222 if ( funfac < -rldiff2 ) h_r(i,j) = 3. * h_i - 2. * h_l(i,j)
2227 end subroutine ppm_limit_cw84
2230 function ratio_max(a, b, maxrat)
result(ratio)
2231 real,
intent(in) :: a
2232 real,
intent(in) :: b
2233 real,
intent(in) :: maxrat
2236 if (abs(a) > abs(maxrat*b))
then
2241 end function ratio_max
2244 subroutine continuity_ppm_init(Time, G, GV, param_file, diag, CS)
2245 type(time_type),
target,
intent(in) :: time
2250 type(
diag_ctrl),
target,
intent(inout) :: diag
2254 #include "version_variable.h"
2256 character(len=40) :: mdl =
"MOM_continuity_PPM"
2258 if (
associated(cs))
then
2259 call mom_error(warning,
"continuity_PPM_init called with associated control structure.")
2266 call get_param(param_file, mdl,
"MONOTONIC_CONTINUITY", cs%monotonic, &
2267 "If true, CONTINUITY_PPM uses the Colella and Woodward "//&
2268 "monotonic limiter. The default (false) is to use a "//&
2269 "simple positive definite limiter.", default=.false.)
2270 call get_param(param_file, mdl,
"SIMPLE_2ND_PPM_CONTINUITY", cs%simple_2nd, &
2271 "If true, CONTINUITY_PPM uses a simple 2nd order "//&
2272 "(arithmetic mean) interpolation of the edge values. "//&
2273 "This may give better PV conservation properties. While "//&
2274 "it formally reduces the accuracy of the continuity "//&
2275 "solver itself in the strongly advective limit, it does "//&
2276 "not reduce the overall order of accuracy of the dynamic "//&
2277 "core.", default=.false.)
2278 call get_param(param_file, mdl,
"UPWIND_1ST_CONTINUITY", cs%upwind_1st, &
2279 "If true, CONTINUITY_PPM becomes a 1st-order upwind "//&
2280 "continuity solver. This scheme is highly diffusive "//&
2281 "but may be useful for debugging or in single-column "//&
2282 "mode where its minimal stencil is useful.", default=.false.)
2283 call get_param(param_file, mdl,
"ETA_TOLERANCE", cs%tol_eta, &
2284 "The tolerance for the differences between the "//&
2285 "barotropic and baroclinic estimates of the sea surface "//&
2286 "height due to the fluxes through each face. The total "//&
2287 "tolerance for SSH is 4 times this value. The default "//&
2288 "is 0.5*NK*ANGSTROM, and this should not be set less "//&
2289 "than about 10^-15*MAXIMUM_DEPTH.", units=
"m", scale=gv%m_to_H, &
2290 default=0.5*g%ke*gv%Angstrom_m, unscaled=tol_eta_m)
2292 call get_param(param_file, mdl,
"ETA_TOLERANCE_AUX", cs%tol_eta_aux, &
2293 "The tolerance for free-surface height discrepancies "//&
2294 "between the barotropic solution and the sum of the "//&
2295 "layer thicknesses when calculating the auxiliary "//&
2296 "corrected velocities. By default, this is the same as "//&
2297 "ETA_TOLERANCE, but can be made larger for efficiency.", &
2298 units=
"m", default=tol_eta_m, scale=gv%m_to_H)
2299 call get_param(param_file, mdl,
"VELOCITY_TOLERANCE", cs%tol_vel, &
2300 "The tolerance for barotropic velocity discrepancies "//&
2301 "between the barotropic solution and the sum of the "//&
2302 "layer thicknesses.", units=
"m s-1", default=3.0e8)
2304 call get_param(param_file, mdl,
"CONT_PPM_AGGRESS_ADJUST", cs%aggress_adjust,&
2305 "If true, allow the adjusted velocities to have a "//&
2306 "relative CFL change up to 0.5.", default=.false.)
2307 cs%vol_CFL = cs%aggress_adjust
2308 call get_param(param_file, mdl,
"CONT_PPM_VOLUME_BASED_CFL", cs%vol_CFL, &
2309 "If true, use the ratio of the open face lengths to the "//&
2310 "tracer cell areas when estimating CFL numbers. The "//&
2311 "default is set by CONT_PPM_AGGRESS_ADJUST.", &
2312 default=cs%aggress_adjust, do_not_read=cs%aggress_adjust)
2313 call get_param(param_file, mdl,
"CONTINUITY_CFL_LIMIT", cs%CFL_limit_adjust, &
2314 "The maximum CFL of the adjusted velocities.", units=
"nondim", &
2316 call get_param(param_file, mdl,
"CONT_PPM_BETTER_ITER", cs%better_iter, &
2317 "If true, stop corrective iterations using a velocity "//&
2318 "based criterion and only stop if the iteration is "//&
2319 "better than all predecessors.", default=.true.)
2320 call get_param(param_file, mdl,
"CONT_PPM_USE_VISC_REM_MAX", &
2321 cs%use_visc_rem_max, &
2322 "If true, use more appropriate limiting bounds for "//&
2323 "corrections in strongly viscous columns.", default=.true.)
2324 call get_param(param_file, mdl,
"CONT_PPM_MARGINAL_FACE_AREAS", cs%marginal_faces, &
2325 "If true, use the marginal face areas from the continuity "//&
2326 "solver for use as the weights in the barotropic solver. "//&
2327 "Otherwise use the transport averaged areas.", default=.true.)
2331 id_clock_update = cpu_clock_id(
'(Ocean continuity update)', grain=clock_routine)
2332 id_clock_correct = cpu_clock_id(
'(Ocean continuity correction)', grain=clock_routine)
2334 end subroutine continuity_ppm_init
2337 function continuity_ppm_stencil(CS)
result(stencil)
2341 stencil = 3 ;
if (cs%simple_2nd) stencil = 2 ;
if (cs%upwind_1st) stencil = 1
2343 end function continuity_ppm_stencil
2346 subroutine continuity_ppm_end(CS)
2349 end subroutine continuity_ppm_end