20 implicit none ;
private
24 #include <MOM_memory.h>
28 integer :: coriolis_scheme
41 integer :: pv_adv_scheme
45 real :: f_eff_max_blend
60 logical :: bound_coriolis
66 logical :: coriolis_en_dis
72 type(time_type),
pointer :: time
75 integer :: id_rv = -1, id_pv = -1, id_gkeu = -1, id_gkev = -1
76 integer :: id_rvxu = -1, id_rvxv = -1
111 subroutine coradcalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, US, CS)
114 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
115 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
116 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
117 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uh
119 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vh
121 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(out) :: cau
123 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(out) :: cav
131 real,
dimension(SZIB_(G),SZJB_(G)) :: &
136 real,
dimension(SZIB_(G),SZJ_(G)) :: &
142 real,
dimension(SZI_(G),SZJ_(G)) :: &
146 real,
dimension(SZIB_(G),SZJ_(G)) :: &
152 real,
dimension(SZI_(G),SZJB_(G)) :: &
158 real,
dimension(SZI_(G),SZJ_(G)) :: &
164 real,
dimension(SZIB_(G),SZJB_(G)) :: &
172 real,
dimension(SZIB_(G),SZJB_(G),SZK_(G)) :: &
175 real :: fv1, fv2, fu1, fu2
176 real :: max_fv, max_fu
177 real :: min_fv, min_fu
179 real,
parameter :: c1_12=1.0/12.0
180 real,
parameter :: c1_24=1.0/24.0
181 real :: absolute_vorticity
182 real :: relative_vorticity
184 real :: max_ihq, min_ihq
194 real :: c1, c2, c3, slope
210 real :: quheff,qvheff
211 integer :: i, j, k, n, is, ie, js, je, isq, ieq, jsq, jeq, nz
218 if (.not.
associated(cs))
call mom_error(fatal, &
219 "MOM_CoriolisAdv: Module must be initialized before it is used.")
220 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
221 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nz = g%ke
222 h_neglect = gv%H_subroundoff
223 eps_vel = 1.0e-10*us%m_s_to_L_T
224 h_tiny = gv%Angstrom_H
227 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+2
228 area_h(i,j) = g%mask2dT(i,j) * g%areaT(i,j)
230 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
231 if (.not. obc%segment(n)%on_pe) cycle
232 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
233 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then
234 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
236 area_h(i,j+1) = area_h(i,j)
238 area_h(i,j) = area_h(i,j+1)
241 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then
242 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
243 if (obc%segment(n)%direction == obc_direction_e)
then
244 area_h(i+1,j) = area_h(i,j)
246 area_h(i,j) = area_h(i+1,j)
252 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
253 area_q(i,j) = (area_h(i,j) + area_h(i+1,j+1)) + &
254 (area_h(i+1,j) + area_h(i,j+1))
266 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
267 dvdx(i,j) = (v(i+1,j,k)*g%dyCv(i+1,j) - v(i,j,k)*g%dyCv(i,j))
268 dudy(i,j) = (u(i,j+1,k)*g%dxCu(i,j+1) - u(i,j,k)*g%dxCu(i,j))
270 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+2
271 harea_v(i,j) = 0.5*(area_h(i,j) * h(i,j,k) + area_h(i,j+1) * h(i,j+1,k))
273 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+1
274 harea_u(i,j) = 0.5*(area_h(i,j) * h(i,j,k) + area_h(i+1,j) * h(i+1,j,k))
276 if (cs%Coriolis_En_Dis)
then
277 do j=jsq,jeq+1 ;
do i=is-1,ie
278 uh_center(i,j) = 0.5 * (g%dy_Cu(i,j) * u(i,j,k)) * (h(i,j,k) + h(i+1,j,k))
280 do j=js-1,je ;
do i=isq,ieq+1
281 vh_center(i,j) = 0.5 * (g%dx_Cv(i,j) * v(i,j,k)) * (h(i,j,k) + h(i,j+1,k))
287 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
288 if (.not. obc%segment(n)%on_pe) cycle
289 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
290 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then
291 if (obc%zero_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
292 dvdx(i,j) = 0. ; dudy(i,j) = 0.
294 if (obc%freeslip_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
297 if (obc%computed_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
299 dudy(i,j) = 2.0*(obc%segment(n)%tangential_vel(i,j,k) - u(i,j,k))*g%dxCu(i,j)
301 dudy(i,j) = 2.0*(u(i,j+1,k) - obc%segment(n)%tangential_vel(i,j,k))*g%dxCu(i,j+1)
304 if (obc%specified_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
306 dudy(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dxCu(i,j)*g%dyBu(i,j)
308 dudy(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dxCu(i,j+1)*g%dyBu(i,j)
313 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
315 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j,k)
317 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j+1,k)
321 if (cs%Coriolis_En_Dis)
then
322 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
324 vh_center(i,j) = g%dx_Cv(i,j) * v(i,j,k) * h(i,j,k)
326 vh_center(i,j) = g%dx_Cv(i,j) * v(i,j,k) * h(i,j+1,k)
330 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then
331 if (obc%zero_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
332 dvdx(i,j) = 0. ; dudy(i,j) = 0.
334 if (obc%freeslip_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
337 if (obc%computed_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
338 if (obc%segment(n)%direction == obc_direction_e)
then
339 dvdx(i,j) = 2.0*(obc%segment(n)%tangential_vel(i,j,k) - v(i,j,k))*g%dyCv(i,j)
341 dvdx(i,j) = 2.0*(v(i+1,j,k) - obc%segment(n)%tangential_vel(i,j,k))*g%dyCv(i+1,j)
344 if (obc%specified_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
345 if (obc%segment(n)%direction == obc_direction_e)
then
346 dvdx(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dyCv(i,j)*g%dxBu(i,j)
348 dvdx(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dyCv(i+1,j)*g%dxBu(i,j)
353 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
354 if (obc%segment(n)%direction == obc_direction_e)
then
355 harea_u(i,j) = 0.5*(area_h(i,j) + area_h(i+1,j)) * h(i,j,k)
357 harea_u(i,j) = 0.5*(area_h(i,j) + area_h(i+1,j)) * h(i+1,j,k)
360 if (cs%Coriolis_En_Dis)
then
361 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
362 if (obc%segment(n)%direction == obc_direction_e)
then
363 uh_center(i,j) = g%dy_Cu(i,j) * u(i,j,k) * h(i,j,k)
365 uh_center(i,j) = g%dy_Cu(i,j) * u(i,j,k) * h(i+1,j,k)
372 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
373 if (.not. obc%segment(n)%on_pe) cycle
376 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
377 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then
378 do i = max(isq-1,obc%segment(n)%HI%IsdB), min(ieq+1,obc%segment(n)%HI%IedB)
380 if (area_h(i,j) + area_h(i+1,j) > 0.0)
then
381 harea_u(i,j+1) = harea_u(i,j) * ((area_h(i,j+1) + area_h(i+1,j+1)) / &
382 (area_h(i,j) + area_h(i+1,j)))
383 else ; harea_u(i,j+1) = 0.0 ;
endif
385 if (area_h(i,j+1) + area_h(i+1,j+1) > 0.0)
then
386 harea_u(i,j) = harea_u(i,j+1) * ((area_h(i,j) + area_h(i+1,j)) / &
387 (area_h(i,j+1) + area_h(i+1,j+1)))
388 else ; harea_u(i,j) = 0.0 ;
endif
391 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then
392 do j = max(jsq-1,obc%segment(n)%HI%JsdB), min(jeq+1,obc%segment(n)%HI%JedB)
393 if (obc%segment(n)%direction == obc_direction_e)
then
394 if (area_h(i,j) + area_h(i,j+1) > 0.0)
then
395 harea_v(i+1,j) = harea_v(i,j) * ((area_h(i+1,j) + area_h(i+1,j+1)) / &
396 (area_h(i,j) + area_h(i,j+1)))
397 else ; harea_v(i+1,j) = 0.0 ;
endif
399 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j+1,k)
400 if (area_h(i+1,j) + area_h(i+1,j+1) > 0.0)
then
401 harea_v(i,j) = harea_v(i+1,j) * ((area_h(i,j) + area_h(i,j+1)) / &
402 (area_h(i+1,j) + area_h(i+1,j+1)))
403 else ; harea_v(i,j) = 0.0 ;
endif
409 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
410 if (cs%no_slip )
then
411 relative_vorticity = (2.0-g%mask2dBu(i,j)) * (dvdx(i,j) - dudy(i,j)) * g%IareaBu(i,j)
413 relative_vorticity = g%mask2dBu(i,j) * (dvdx(i,j) - dudy(i,j)) * g%IareaBu(i,j)
415 absolute_vorticity = g%CoriolisBu(i,j) + relative_vorticity
417 if (area_q(i,j) > 0.0)
then
418 harea_q = (harea_u(i,j) + harea_u(i,j+1)) + (harea_v(i,j) + harea_v(i+1,j))
419 ih = area_q(i,j) / (harea_q + h_neglect*area_q(i,j))
421 q(i,j) = absolute_vorticity * ih
422 abs_vort(i,j) = absolute_vorticity
425 if (cs%bound_Coriolis)
then
426 fv1 = absolute_vorticity * v(i+1,j,k)
427 fv2 = absolute_vorticity * v(i,j,k)
428 fu1 = -absolute_vorticity * u(i,j+1,k)
429 fu2 = -absolute_vorticity * u(i,j,k)
431 max_fvq(i,j) = fv1 ; min_fvq(i,j) = fv2
433 max_fvq(i,j) = fv2 ; min_fvq(i,j) = fv1
436 max_fuq(i,j) = fu1 ; min_fuq(i,j) = fu2
438 max_fuq(i,j) = fu2 ; min_fuq(i,j) = fu1
442 if (cs%id_rv > 0) rv(i,j,k) = relative_vorticity
443 if (cs%id_PV > 0) pv(i,j,k) = q(i,j)
444 if (
associated(ad%rv_x_v) .or.
associated(ad%rv_x_u)) &
445 q2(i,j) = relative_vorticity * ih
455 a(i,j) = (q(i,j) + (q(i+1,j) + q(i,j-1))) * c1_12
456 d(i,j) = ((q(i,j) + q(i+1,j-1)) + q(i,j-1)) * c1_12
459 b(i,j) = (q(i,j) + (q(i-1,j) + q(i,j-1))) * c1_12
460 c(i,j) = ((q(i,j) + q(i-1,j-1)) + q(i,j-1)) * c1_12
464 do j=jsq,jeq+1 ;
do i=isq,ieq+1
465 a(i-1,j) = (2.0*(q(i,j) + q(i-1,j-1)) + (q(i-1,j) + q(i,j-1))) * c1_24
466 d(i-1,j) = ((q(i,j) + q(i-1,j-1)) + 2.0*(q(i-1,j) + q(i,j-1))) * c1_24
467 b(i,j) = ((q(i,j) + q(i-1,j-1)) + 2.0*(q(i-1,j) + q(i,j-1))) * c1_24
468 c(i,j) = (2.0*(q(i,j) + q(i-1,j-1)) + (q(i-1,j) + q(i,j-1))) * c1_24
469 ep_u(i,j) = ((q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
470 ep_v(i,j) = (-(q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
472 elseif (cs%Coriolis_Scheme ==
al_blend)
then
473 fe_m2 = cs%F_eff_max_blend - 2.0
474 rat_lin = 1.5 * fe_m2 / max(cs%wt_lin_blend, 1.0e-16)
477 if (cs%F_eff_max_blend <= 2.0)
then ; fe_m2 = -1. ; rat_lin = -1.0 ;
endif
479 do j=jsq,jeq+1 ;
do i=isq,ieq+1
480 min_ihq = min(ih_q(i-1,j-1), ih_q(i,j-1), ih_q(i-1,j), ih_q(i,j))
481 max_ihq = max(ih_q(i-1,j-1), ih_q(i,j-1), ih_q(i-1,j), ih_q(i,j))
483 if (max_ihq < 1.0e15*min_ihq) rat_m1 = max_ihq / min_ihq - 1.0
490 if (rat_m1 <= fe_m2)
then ; al_wt = 1.0
491 elseif (rat_m1 < 1.5*fe_m2)
then ; al_wt = 3.0*fe_m2 / rat_m1 - 2.0
492 else ; al_wt = 0.0 ;
endif
495 if (rat_m1 <= 1.5*fe_m2)
then ; sad_wt = 0.0
496 elseif (rat_m1 <= rat_lin)
then
497 sad_wt = 1.0 - (1.5*fe_m2) / rat_m1
498 elseif (rat_m1 < 2.0*rat_lin)
then
499 sad_wt = 1.0 - (cs%wt_lin_blend / rat_lin) * (rat_m1 - 2.0*rat_lin)
500 else ; sad_wt = 1.0 ;
endif
502 a(i-1,j) = sad_wt * 0.25 * q(i-1,j) + (1.0 - sad_wt) * &
503 ( ((2.0-al_wt)* q(i-1,j) + al_wt*q(i,j-1)) + &
504 2.0 * (q(i,j) + q(i-1,j-1)) ) * c1_24
505 d(i-1,j) = sad_wt * 0.25 * q(i-1,j-1) + (1.0 - sad_wt) * &
506 ( ((2.0-al_wt)* q(i-1,j-1) + al_wt*q(i,j)) + &
507 2.0 * (q(i-1,j) + q(i,j-1)) ) * c1_24
508 b(i,j) = sad_wt * 0.25 * q(i,j) + (1.0 - sad_wt) * &
509 ( ((2.0-al_wt)* q(i,j) + al_wt*q(i-1,j-1)) + &
510 2.0 * (q(i-1,j) + q(i,j-1)) ) * c1_24
511 c(i,j) = sad_wt * 0.25 * q(i,j-1) + (1.0 - sad_wt) * &
512 ( ((2.0-al_wt)* q(i,j-1) + al_wt*q(i-1,j)) + &
513 2.0 * (q(i,j) + q(i-1,j-1)) ) * c1_24
514 ep_u(i,j) = al_wt * ((q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
515 ep_v(i,j) = al_wt * (-(q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
519 if (cs%Coriolis_En_Dis)
then
521 c1 = 1.0-1.5*0.5 ; c2 = 1.0-0.5 ; c3 = 2.0 ; slope = 0.5
523 do j=jsq,jeq+1 ;
do i=is-1,ie
527 if (g%dy_Cu(i,j) == 0.0) uhc = uhm
529 if (abs(uhc) < 0.1*abs(uhm))
then
531 elseif (abs(uhc) > c1*abs(uhm))
then
532 if (abs(uhc) < c2*abs(uhm))
then ; uhc = (3.0*uhc+(1.0-c2*3.0)*uhm)
533 elseif (abs(uhc) <= c3*abs(uhm))
then ; uhc = uhm
534 else ; uhc = slope*uhc+(1.0-c3*slope)*uhm
539 uh_min(i,j) = uhm ; uh_max(i,j) = uhc
541 uh_max(i,j) = uhm ; uh_min(i,j) = uhc
544 do j=js-1,je ;
do i=isq,ieq+1
548 if (g%dx_Cv(i,j) == 0.0) vhc = vhm
550 if (abs(vhc) < 0.1*abs(vhm))
then
552 elseif (abs(vhc) > c1*abs(vhm))
then
553 if (abs(vhc) < c2*abs(vhm))
then ; vhc = (3.0*vhc+(1.0-c2*3.0)*vhm)
554 elseif (abs(vhc) <= c3*abs(vhm))
then ; vhc = vhm
555 else ; vhc = slope*vhc+(1.0-c3*slope)*vhm
560 vh_min(i,j) = vhm ; vh_max(i,j) = vhc
562 vh_max(i,j) = vhm ; vh_min(i,j) = vhc
568 call gradke(u, v, h, ke, kex, key, k, obc, g, us, cs)
574 if (cs%Coriolis_En_Dis)
then
576 do j=js,je ;
do i=isq,ieq
577 if (q(i,j)*u(i,j,k) == 0.0)
then
578 temp1 = q(i,j) * ( (vh_max(i,j)+vh_max(i+1,j)) &
579 + (vh_min(i,j)+vh_min(i+1,j)) )*0.5
580 elseif (q(i,j)*u(i,j,k) < 0.0)
then
581 temp1 = q(i,j) * (vh_max(i,j)+vh_max(i+1,j))
583 temp1 = q(i,j) * (vh_min(i,j)+vh_min(i+1,j))
585 if (q(i,j-1)*u(i,j,k) == 0.0)
then
586 temp2 = q(i,j-1) * ( (vh_max(i,j-1)+vh_max(i+1,j-1)) &
587 + (vh_min(i,j-1)+vh_min(i+1,j-1)) )*0.5
588 elseif (q(i,j-1)*u(i,j,k) < 0.0)
then
589 temp2 = q(i,j-1) * (vh_max(i,j-1)+vh_max(i+1,j-1))
591 temp2 = q(i,j-1) * (vh_min(i,j-1)+vh_min(i+1,j-1))
593 cau(i,j,k) = 0.25 * g%IdxCu(i,j) * (temp1 + temp2)
597 do j=js,je ;
do i=isq,ieq
598 cau(i,j,k) = 0.25 * &
599 (q(i,j) * (vh(i+1,j,k) + vh(i,j,k)) + &
600 q(i,j-1) * (vh(i,j-1,k) + vh(i+1,j-1,k))) * g%IdxCu(i,j)
604 do j=js,je ;
do i=isq,ieq
605 cau(i,j,k) = 0.125 * (g%IdxCu(i,j) * (q(i,j) + q(i,j-1))) * &
606 ((vh(i+1,j,k) + vh(i,j,k)) + (vh(i,j-1,k) + vh(i+1,j-1,k)))
610 (cs%Coriolis_Scheme ==
al_blend))
then
612 do j=js,je ;
do i=isq,ieq
613 cau(i,j,k) = ((a(i,j) * vh(i+1,j,k) + c(i,j) * vh(i,j-1,k)) + &
614 (b(i,j) * vh(i,j,k) + d(i,j) * vh(i+1,j-1,k))) * g%IdxCu(i,j)
620 do j=js,je ;
do i=isq,ieq
621 heff1 = abs(vh(i,j,k) * g%IdxCv(i,j)) / (eps_vel+abs(v(i,j,k)))
622 heff1 = max(heff1, min(h(i,j,k),h(i,j+1,k)))
623 heff1 = min(heff1, max(h(i,j,k),h(i,j+1,k)))
624 heff2 = abs(vh(i,j-1,k) * g%IdxCv(i,j-1)) / (eps_vel+abs(v(i,j-1,k)))
625 heff2 = max(heff2, min(h(i,j-1,k),h(i,j,k)))
626 heff2 = min(heff2, max(h(i,j-1,k),h(i,j,k)))
627 heff3 = abs(vh(i+1,j,k) * g%IdxCv(i+1,j)) / (eps_vel+abs(v(i+1,j,k)))
628 heff3 = max(heff3, min(h(i+1,j,k),h(i+1,j+1,k)))
629 heff3 = min(heff3, max(h(i+1,j,k),h(i+1,j+1,k)))
630 heff4 = abs(vh(i+1,j-1,k) * g%IdxCv(i+1,j-1)) / (eps_vel+abs(v(i+1,j-1,k)))
631 heff4 = max(heff4, min(h(i+1,j-1,k),h(i+1,j,k)))
632 heff4 = min(heff4, max(h(i+1,j-1,k),h(i+1,j,k)))
634 cau(i,j,k) = 0.5*(abs_vort(i,j)+abs_vort(i,j-1)) * &
635 ((vh(i,j,k) + vh(i+1,j-1,k)) + (vh(i,j-1,k) + vh(i+1,j,k)) ) / &
636 (h_tiny + ((heff1+heff4) + (heff2+heff3)) ) * g%IdxCu(i,j)
638 vheff = ((vh(i,j,k) + vh(i+1,j-1,k)) + (vh(i,j-1,k) + vh(i+1,j,k)) )
639 qvheff = 0.5*( (abs_vort(i,j)+abs_vort(i,j-1))*vheff &
640 -(abs_vort(i,j)-abs_vort(i,j-1))*abs(vheff) )
641 cau(i,j,k) = (qvheff / ( h_tiny + ((heff1+heff4) + (heff2+heff3)) ) ) * g%IdxCu(i,j)
647 (cs%Coriolis_Scheme ==
al_blend))
then ;
do j=js,je ;
do i=isq,ieq
648 cau(i,j,k) = cau(i,j,k) + &
649 (ep_u(i,j)*uh(i-1,j,k) - ep_u(i+1,j)*uh(i+1,j,k)) * g%IdxCu(i,j)
650 enddo ;
enddo ;
endif
653 if (cs%bound_Coriolis)
then
654 do j=js,je ;
do i=isq,ieq
655 max_fv = max(max_fvq(i,j), max_fvq(i,j-1))
656 min_fv = min(min_fvq(i,j), min_fvq(i,j-1))
659 if (cau(i,j,k) > max_fv)
then
662 if (cau(i,j,k) < min_fv) cau(i,j,k) = min_fv
668 do j=js,je ;
do i=isq,ieq
669 cau(i,j,k) = cau(i,j,k) - kex(i,j)
670 if (
associated(ad%gradKEu)) ad%gradKEu(i,j,k) = -kex(i,j)
678 if (cs%Coriolis_En_Dis)
then
680 do j=jsq,jeq ;
do i=is,ie
681 if (q(i-1,j)*v(i,j,k) == 0.0)
then
682 temp1 = q(i-1,j) * ( (uh_max(i-1,j)+uh_max(i-1,j+1)) &
683 + (uh_min(i-1,j)+uh_min(i-1,j+1)) )*0.5
684 elseif (q(i-1,j)*v(i,j,k) > 0.0)
then
685 temp1 = q(i-1,j) * (uh_max(i-1,j)+uh_max(i-1,j+1))
687 temp1 = q(i-1,j) * (uh_min(i-1,j)+uh_min(i-1,j+1))
689 if (q(i,j)*v(i,j,k) == 0.0)
then
690 temp2 = q(i,j) * ( (uh_max(i,j)+uh_max(i,j+1)) &
691 + (uh_min(i,j)+uh_min(i,j+1)) )*0.5
692 elseif (q(i,j)*v(i,j,k) > 0.0)
then
693 temp2 = q(i,j) * (uh_max(i,j)+uh_max(i,j+1))
695 temp2 = q(i,j) * (uh_min(i,j)+uh_min(i,j+1))
697 cav(i,j,k) = -0.25 * g%IdyCv(i,j) * (temp1 + temp2)
701 do j=jsq,jeq ;
do i=is,ie
702 cav(i,j,k) = - 0.25* &
703 (q(i-1,j)*(uh(i-1,j,k) + uh(i-1,j+1,k)) + &
704 q(i,j)*(uh(i,j,k) + uh(i,j+1,k))) * g%IdyCv(i,j)
708 do j=jsq,jeq ;
do i=is,ie
709 cav(i,j,k) = -0.125 * (g%IdyCv(i,j) * (q(i-1,j) + q(i,j))) * &
710 ((uh(i-1,j,k) + uh(i-1,j+1,k)) + (uh(i,j,k) + uh(i,j+1,k)))
714 (cs%Coriolis_Scheme ==
al_blend))
then
716 do j=jsq,jeq ;
do i=is,ie
717 cav(i,j,k) = - ((a(i-1,j) * uh(i-1,j,k) + &
718 c(i,j+1) * uh(i,j+1,k)) &
719 + (b(i,j) * uh(i,j,k) + &
720 d(i-1,j+1) * uh(i-1,j+1,k))) * g%IdyCv(i,j)
726 do j=jsq,jeq ;
do i=is,ie
727 heff1 = abs(uh(i,j,k) * g%IdyCu(i,j)) / (eps_vel+abs(u(i,j,k)))
728 heff1 = max(heff1, min(h(i,j,k),h(i+1,j,k)))
729 heff1 = min(heff1, max(h(i,j,k),h(i+1,j,k)))
730 heff2 = abs(uh(i-1,j,k) * g%IdyCu(i-1,j)) / (eps_vel+abs(u(i-1,j,k)))
731 heff2 = max(heff2, min(h(i-1,j,k),h(i,j,k)))
732 heff2 = min(heff2, max(h(i-1,j,k),h(i,j,k)))
733 heff3 = abs(uh(i,j+1,k) * g%IdyCu(i,j+1)) / (eps_vel+abs(u(i,j+1,k)))
734 heff3 = max(heff3, min(h(i,j+1,k),h(i+1,j+1,k)))
735 heff3 = min(heff3, max(h(i,j+1,k),h(i+1,j+1,k)))
736 heff4 = abs(uh(i-1,j+1,k) * g%IdyCu(i-1,j+1)) / (eps_vel+abs(u(i-1,j+1,k)))
737 heff4 = max(heff4, min(h(i-1,j+1,k),h(i,j+1,k)))
738 heff4 = min(heff4, max(h(i-1,j+1,k),h(i,j+1,k)))
740 cav(i,j,k) = - 0.5*(abs_vort(i,j)+abs_vort(i-1,j)) * &
741 ((uh(i ,j ,k)+uh(i-1,j+1,k)) + &
742 (uh(i-1,j ,k)+uh(i ,j+1,k)) ) / &
743 (h_tiny + ((heff1+heff4) +(heff2+heff3)) ) * g%IdyCv(i,j)
745 uheff = ((uh(i ,j ,k)+uh(i-1,j+1,k)) + &
746 (uh(i-1,j ,k)+uh(i ,j+1,k)) )
747 quheff = 0.5*( (abs_vort(i,j)+abs_vort(i-1,j))*uheff &
748 -(abs_vort(i,j)-abs_vort(i-1,j))*abs(uheff) )
749 cav(i,j,k) = - quheff / &
750 (h_tiny + ((heff1+heff4) +(heff2+heff3)) ) * g%IdyCv(i,j)
756 (cs%Coriolis_Scheme ==
al_blend))
then ;
do j=jsq,jeq ;
do i=is,ie
757 cav(i,j,k) = cav(i,j,k) + &
758 (ep_v(i,j)*vh(i,j-1,k) - ep_v(i,j+1)*vh(i,j+1,k)) * g%IdyCv(i,j)
759 enddo ;
enddo ;
endif
761 if (cs%bound_Coriolis)
then
762 do j=jsq,jeq ;
do i=is,ie
763 max_fu = max(max_fuq(i,j),max_fuq(i-1,j))
764 min_fu = min(min_fuq(i,j),min_fuq(i-1,j))
765 if (cav(i,j,k) > max_fu)
then
768 if (cav(i,j,k) < min_fu) cav(i,j,k) = min_fu
774 do j=jsq,jeq ;
do i=is,ie
775 cav(i,j,k) = cav(i,j,k) - key(i,j)
776 if (
associated(ad%gradKEv)) ad%gradKEv(i,j,k) = -key(i,j)
779 if (
associated(ad%rv_x_u) .or.
associated(ad%rv_x_v))
then
782 if (
associated(ad%rv_x_u))
then
783 do j=jsq,jeq ;
do i=is,ie
784 ad%rv_x_u(i,j,k) = - 0.25* &
785 (q2(i-1,j)*(uh(i-1,j,k) + uh(i-1,j+1,k)) + &
786 q2(i,j)*(uh(i,j,k) + uh(i,j+1,k))) * g%IdyCv(i,j)
790 if (
associated(ad%rv_x_v))
then
791 do j=js,je ;
do i=isq,ieq
792 ad%rv_x_v(i,j,k) = 0.25 * &
793 (q2(i,j) * (vh(i+1,j,k) + vh(i,j,k)) + &
794 q2(i,j-1) * (vh(i,j-1,k) + vh(i+1,j-1,k))) * g%IdxCu(i,j)
798 if (
associated(ad%rv_x_u))
then
799 do j=jsq,jeq ;
do i=is,ie
800 ad%rv_x_u(i,j,k) = -g%IdyCv(i,j) * c1_12 * &
801 ((q2(i,j) + q2(i-1,j) + q2(i-1,j-1)) * uh(i-1,j,k) + &
802 (q2(i-1,j) + q2(i,j) + q2(i,j-1)) * uh(i,j,k) + &
803 (q2(i-1,j) + q2(i,j+1) + q2(i,j)) * uh(i,j+1,k) + &
804 (q2(i,j) + q2(i-1,j+1) + q2(i-1,j)) * uh(i-1,j+1,k))
808 if (
associated(ad%rv_x_v))
then
809 do j=js,je ;
do i=isq,ieq
810 ad%rv_x_v(i,j,k) = g%IdxCu(i,j) * c1_12 * &
811 ((q2(i+1,j) + q2(i,j) + q2(i,j-1)) * vh(i+1,j,k) + &
812 (q2(i-1,j) + q2(i,j) + q2(i,j-1)) * vh(i,j,k) + &
813 (q2(i-1,j-1) + q2(i,j) + q2(i,j-1)) * vh(i,j-1,k) + &
814 (q2(i+1,j-1) + q2(i,j) + q2(i,j-1)) * vh(i+1,j-1,k))
823 if (query_averaging_enabled(cs%diag))
then
824 if (cs%id_rv > 0)
call post_data(cs%id_rv, rv, cs%diag)
825 if (cs%id_PV > 0)
call post_data(cs%id_PV, pv, cs%diag)
826 if (cs%id_gKEu>0)
call post_data(cs%id_gKEu, ad%gradKEu, cs%diag)
827 if (cs%id_gKEv>0)
call post_data(cs%id_gKEv, ad%gradKEv, cs%diag)
828 if (cs%id_rvxu > 0)
call post_data(cs%id_rvxu, ad%rv_x_u, cs%diag)
829 if (cs%id_rvxv > 0)
call post_data(cs%id_rvxv, ad%rv_x_v, cs%diag)
836 subroutine gradke(u, v, h, KE, KEx, KEy, k, OBC, G, US, CS)
838 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
839 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
840 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
841 real,
dimension(SZI_(G) ,SZJ_(G) ),
intent(out) :: KE
842 real,
dimension(SZIB_(G),SZJ_(G) ),
intent(out) :: KEx
844 real,
dimension(SZI_(G) ,SZJB_(G)),
intent(out) :: KEy
846 integer,
intent(in) :: k
851 real :: um, up, vm, vp
852 real :: um2, up2, vm2, vp2
853 real :: um2a, up2a, vm2a, vp2a
854 integer :: i, j, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, n
856 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
857 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
865 do j=jsq,jeq+1 ;
do i=isq,ieq+1
866 ke(i,j) = ( ( g%areaCu( i ,j)*(u( i ,j,k)*u( i ,j,k)) + &
867 g%areaCu(i-1,j)*(u(i-1,j,k)*u(i-1,j,k)) ) + &
868 ( g%areaCv(i, j )*(v(i, j ,k)*v(i, j ,k)) + &
869 g%areaCv(i,j-1)*(v(i,j-1,k)*v(i,j-1,k)) ) )*0.25*g%IareaT(i,j)
874 do j=jsq,jeq+1 ;
do i=isq,ieq+1
875 up = 0.5*( u(i-1,j,k) + abs( u(i-1,j,k) ) ) ; up2 = up*up
876 um = 0.5*( u( i ,j,k) - abs( u( i ,j,k) ) ) ; um2 = um*um
877 vp = 0.5*( v(i,j-1,k) + abs( v(i,j-1,k) ) ) ; vp2 = vp*vp
878 vm = 0.5*( v(i, j ,k) - abs( v(i, j ,k) ) ) ; vm2 = vm*vm
879 ke(i,j) = ( max(up2,um2) + max(vp2,vm2) ) *0.5
884 do j=jsq,jeq+1 ;
do i=isq,ieq+1
885 up = 0.5*( u(i-1,j,k) + abs( u(i-1,j,k) ) ) ; up2a = up*up*g%areaCu(i-1,j)
886 um = 0.5*( u( i ,j,k) - abs( u( i ,j,k) ) ) ; um2a = um*um*g%areaCu( i ,j)
887 vp = 0.5*( v(i,j-1,k) + abs( v(i,j-1,k) ) ) ; vp2a = vp*vp*g%areaCv(i,j-1)
888 vm = 0.5*( v(i, j ,k) - abs( v(i, j ,k) ) ) ; vm2a = vm*vm*g%areaCv(i, j )
889 ke(i,j) = ( max(um2a,up2a) + max(vm2a,vp2a) )*0.5*g%IareaT(i,j)
894 do j=js,je ;
do i=isq,ieq
895 kex(i,j) = (ke(i+1,j) - ke(i,j)) * g%IdxCu(i,j)
899 do j=jsq,jeq ;
do i=is,ie
900 key(i,j) = (ke(i,j+1) - ke(i,j)) * g%IdyCv(i,j)
903 if (
associated(obc))
then
904 do n=1,obc%number_of_segments
905 if (obc%segment(n)%is_N_or_S)
then
906 do i=obc%segment(n)%HI%isd,obc%segment(n)%HI%ied
907 key(i,obc%segment(n)%HI%JsdB) = 0.
909 elseif (obc%segment(n)%is_E_or_W)
then
910 do j=obc%segment(n)%HI%jsd,obc%segment(n)%HI%jed
911 kex(obc%segment(n)%HI%IsdB,j) = 0.
921 type(time_type),
target,
intent(in) :: time
926 type(
diag_ctrl),
target,
intent(inout) :: diag
931 #include "version_variable.h"
932 character(len=40) :: mdl =
"MOM_CoriolisAdv"
933 character(len=20) :: tmpstr
934 character(len=400) :: mesg
935 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz
937 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = gv%ke
938 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
940 if (
associated(cs))
then
941 call mom_error(warning,
"CoriolisAdv_init called with associated control structure.")
946 cs%diag => diag ; cs%Time => time
950 call get_param(param_file, mdl,
"NOSLIP", cs%no_slip, &
951 "If true, no slip boundary conditions are used; otherwise "//&
952 "free slip boundary conditions are assumed. The "//&
953 "implementation of the free slip BCs on a C-grid is much "//&
954 "cleaner than the no slip BCs. The use of free slip BCs "//&
955 "is strongly encouraged, and no slip BCs are not used with "//&
956 "the biharmonic viscosity.", default=.false.)
958 call get_param(param_file, mdl,
"CORIOLIS_EN_DIS", cs%Coriolis_En_Dis, &
959 "If true, two estimates of the thickness fluxes are used "//&
960 "to estimate the Coriolis term, and the one that "//&
961 "dissipates energy relative to the other one is used.", &
966 call get_param(param_file, mdl,
"CORIOLIS_SCHEME", tmpstr, &
967 "CORIOLIS_SCHEME selects the discretization for the "//&
968 "Coriolis terms. Valid values are: \n"//&
969 "\t SADOURNY75_ENERGY - Sadourny, 1975; energy cons. \n"//&
970 "\t ARAKAWA_HSU90 - Arakawa & Hsu, 1990 \n"//&
971 "\t SADOURNY75_ENSTRO - Sadourny, 1975; enstrophy cons. \n"//&
972 "\t ARAKAWA_LAMB81 - Arakawa & Lamb, 1981; En. + Enst.\n"//&
973 "\t ARAKAWA_LAMB_BLEND - A blend of Arakawa & Lamb with \n"//&
974 "\t Arakawa & Hsu and Sadourny energy", &
990 cs%Coriolis_En_Dis = .false.
992 call mom_mesg(
'CoriolisAdv_init: Coriolis_Scheme ="'//trim(tmpstr)//
'"', 0)
993 call mom_error(fatal,
"CoriolisAdv_init: Unrecognized setting "// &
994 "#define CORIOLIS_SCHEME "//trim(tmpstr)//
" found in input file.")
996 if (cs%Coriolis_Scheme ==
al_blend)
then
997 call get_param(param_file, mdl,
"CORIOLIS_BLEND_WT_LIN", cs%wt_lin_blend, &
998 "A weighting value for the ratio of inverse thicknesses, "//&
999 "beyond which the blending between Sadourny Energy and "//&
1000 "Arakawa & Hsu goes linearly to 0 when CORIOLIS_SCHEME "//&
1001 "is ARAWAKA_LAMB_BLEND. This must be between 1 and 1e-16.", &
1002 units=
"nondim", default=0.125)
1003 call get_param(param_file, mdl,
"CORIOLIS_BLEND_F_EFF_MAX", cs%F_eff_max_blend, &
1004 "The factor by which the maximum effective Coriolis "//&
1005 "acceleration from any point can be increased when "//&
1006 "blending different discretizations with the "//&
1007 "ARAKAWA_LAMB_BLEND Coriolis scheme. This must be "//&
1008 "greater than 2.0 (the max value for Sadourny energy).", &
1009 units=
"nondim", default=4.0)
1010 cs%wt_lin_blend = min(1.0, max(cs%wt_lin_blend,1e-16))
1011 if (cs%F_eff_max_blend < 2.0)
call mom_error(warning,
"CoriolisAdv_init: "//&
1012 "CORIOLIS_BLEND_F_EFF_MAX should be at least 2.")
1015 mesg =
"If true, the Coriolis terms at u-points are bounded by "//&
1016 "the four estimates of (f+rv)v from the four neighboring "//&
1017 "v-points, and similarly at v-points."
1019 mesg = trim(mesg)//
" This option is "//&
1020 "always effectively false with CORIOLIS_EN_DIS defined and "//&
1023 mesg = trim(mesg)//
" This option would "//&
1024 "have no effect on the SADOURNY Coriolis scheme if it "//&
1025 "were possible to use centered difference thickness fluxes."
1027 call get_param(param_file, mdl,
"BOUND_CORIOLIS", cs%bound_Coriolis, mesg, &
1030 (cs%Coriolis_Scheme ==
robust_enstro)) cs%bound_Coriolis = .false.
1033 call get_param(param_file, mdl,
"KE_SCHEME", tmpstr, &
1034 "KE_SCHEME selects the discretization for acceleration "//&
1035 "due to the kinetic energy gradient. Valid values are: \n"//&
1036 "\t KE_ARAKAWA, KE_SIMPLE_GUDONOV, KE_GUDONOV", &
1039 select case (tmpstr)
1044 call mom_mesg(
'CoriolisAdv_init: KE_Scheme ="'//trim(tmpstr)//
'"', 0)
1045 call mom_error(fatal,
"CoriolisAdv_init: "// &
1046 "#define KE_SCHEME "//trim(tmpstr)//
" in input file is invalid.")
1050 call get_param(param_file, mdl,
"PV_ADV_SCHEME", tmpstr, &
1051 "PV_ADV_SCHEME selects the discretization for PV "//&
1052 "advection. Valid values are: \n"//&
1053 "\t PV_ADV_CENTERED - centered (aka Sadourny, 75) \n"//&
1054 "\t PV_ADV_UPWIND1 - upwind, first order", &
1062 call mom_mesg(
'CoriolisAdv_init: PV_Adv_Scheme ="'//trim(tmpstr)//
'"', 0)
1063 call mom_error(fatal,
"CoriolisAdv_init: "// &
1064 "#DEFINE PV_ADV_SCHEME in input file is invalid.")
1068 'Relative Vorticity',
's-1', conversion=us%s_to_T)
1071 'Potential Vorticity',
'm-1 s-1', conversion=gv%m_to_H*us%s_to_T)
1074 'Zonal Acceleration from Grad. Kinetic Energy',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1075 if (cs%id_gKEu > 0)
call safe_alloc_ptr(ad%gradKEu,isdb,iedb,jsd,jed,nz)
1078 'Meridional Acceleration from Grad. Kinetic Energy',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1079 if (cs%id_gKEv > 0)
call safe_alloc_ptr(ad%gradKEv,isd,ied,jsdb,jedb,nz)
1082 'Meridional Acceleration from Relative Vorticity',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1083 if (cs%id_rvxu > 0)
call safe_alloc_ptr(ad%rv_x_u,isd,ied,jsdb,jedb,nz)
1086 'Zonal Acceleration from Relative Vorticity',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1087 if (cs%id_rvxv > 0)
call safe_alloc_ptr(ad%rv_x_v,isdb,iedb,jsd,jed,nz)