20 implicit none ;
private 22 public coradcalc, coriolisadv_init, coriolisadv_end
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
78 integer :: id_hf_gkeu_2d = -1, id_hf_gkev_2d = -1
80 integer :: id_hf_rvxu_2d = -1, id_hf_rvxv_2d = -1
85 integer,
parameter :: sadourny75_energy = 1
86 integer,
parameter :: arakawa_hsu90 = 2
87 integer,
parameter :: robust_enstro = 3
88 integer,
parameter :: sadourny75_enstro = 4
89 integer,
parameter :: arakawa_lamb81 = 5
90 integer,
parameter :: al_blend = 6
91 character*(20),
parameter :: sadourny75_energy_string =
"SADOURNY75_ENERGY" 92 character*(20),
parameter :: arakawa_hsu_string =
"ARAKAWA_HSU90" 93 character*(20),
parameter :: robust_enstro_string =
"ROBUST_ENSTRO" 94 character*(20),
parameter :: sadourny75_enstro_string =
"SADOURNY75_ENSTRO" 95 character*(20),
parameter :: arakawa_lamb_string =
"ARAKAWA_LAMB81" 96 character*(20),
parameter :: al_blend_string =
"ARAKAWA_LAMB_BLEND" 99 integer,
parameter :: ke_arakawa = 10
100 integer,
parameter :: ke_simple_gudonov = 11
101 integer,
parameter :: ke_gudonov = 12
102 character*(20),
parameter :: ke_arakawa_string =
"KE_ARAKAWA" 103 character*(20),
parameter :: ke_simple_gudonov_string =
"KE_SIMPLE_GUDONOV" 104 character*(20),
parameter :: ke_gudonov_string =
"KE_GUDONOV" 107 integer,
parameter :: pv_adv_centered = 21
108 integer,
parameter :: pv_adv_upwind1 = 22
109 character*(20),
parameter :: pv_adv_centered_string =
"PV_ADV_CENTERED" 110 character*(20),
parameter :: pv_adv_upwind1_string =
"PV_ADV_UPWIND1" 116 subroutine coradcalc(u, v, h, uh, vh, CAu, CAv, OBC, AD, G, GV, US, CS)
119 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
120 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
121 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
122 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: uh
124 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: vh
126 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(out) :: cau
128 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(out) :: cav
136 real,
dimension(SZIB_(G),SZJB_(G)) :: &
141 real,
dimension(SZIB_(G),SZJ_(G)) :: &
147 real,
dimension(SZI_(G),SZJ_(G)) :: &
151 real,
dimension(SZIB_(G),SZJ_(G)) :: &
157 real,
dimension(SZI_(G),SZJB_(G)) :: &
163 real,
dimension(SZI_(G),SZJ_(G)) :: &
169 real,
dimension(SZIB_(G),SZJB_(G)) :: &
177 real,
dimension(SZIB_(G),SZJB_(G),SZK_(G)) :: &
180 real :: fv1, fv2, fu1, fu2
181 real :: max_fv, max_fu
182 real :: min_fv, min_fu
184 real,
parameter :: c1_12=1.0/12.0
185 real,
parameter :: c1_24=1.0/24.0
186 real :: absolute_vorticity
187 real :: relative_vorticity
189 real :: max_ihq, min_ihq
199 real :: c1, c2, c3, slope
215 real :: quheff,qvheff
216 integer :: i, j, k, n, is, ie, js, je, isq, ieq, jsq, jeq, nz
219 real,
allocatable,
dimension(:,:) :: &
220 hf_gkeu_2d, hf_gkev_2d, &
221 hf_rvxu_2d, hf_rvxv_2d
233 if (.not.
associated(cs))
call mom_error(fatal, &
234 "MOM_CoriolisAdv: Module must be initialized before it is used.")
235 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
236 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB ; nz = g%ke
237 h_neglect = gv%H_subroundoff
238 eps_vel = 1.0e-10*us%m_s_to_L_T
239 h_tiny = gv%Angstrom_H
242 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+2
243 area_h(i,j) = g%mask2dT(i,j) * g%areaT(i,j)
245 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
246 if (.not. obc%segment(n)%on_pe) cycle
247 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
248 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then 249 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
250 if (obc%segment(n)%direction == obc_direction_n)
then 251 area_h(i,j+1) = area_h(i,j)
253 area_h(i,j) = area_h(i,j+1)
256 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then 257 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
258 if (obc%segment(n)%direction == obc_direction_e)
then 259 area_h(i+1,j) = area_h(i,j)
261 area_h(i,j) = area_h(i+1,j)
267 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
268 area_q(i,j) = (area_h(i,j) + area_h(i+1,j+1)) + &
269 (area_h(i+1,j) + area_h(i,j+1))
281 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
282 dvdx(i,j) = (v(i+1,j,k)*g%dyCv(i+1,j) - v(i,j,k)*g%dyCv(i,j))
283 dudy(i,j) = (u(i,j+1,k)*g%dxCu(i,j+1) - u(i,j,k)*g%dxCu(i,j))
285 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+2
286 harea_v(i,j) = 0.5*(area_h(i,j) * h(i,j,k) + area_h(i,j+1) * h(i,j+1,k))
288 do j=jsq-1,jeq+2 ;
do i=isq-1,ieq+1
289 harea_u(i,j) = 0.5*(area_h(i,j) * h(i,j,k) + area_h(i+1,j) * h(i+1,j,k))
291 if (cs%Coriolis_En_Dis)
then 292 do j=jsq,jeq+1 ;
do i=is-1,ie
293 uh_center(i,j) = 0.5 * (g%dy_Cu(i,j) * u(i,j,k)) * (h(i,j,k) + h(i+1,j,k))
295 do j=js-1,je ;
do i=isq,ieq+1
296 vh_center(i,j) = 0.5 * (g%dx_Cv(i,j) * v(i,j,k)) * (h(i,j,k) + h(i,j+1,k))
302 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
303 if (.not. obc%segment(n)%on_pe) cycle
304 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
305 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then 306 if (obc%zero_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
307 dvdx(i,j) = 0. ; dudy(i,j) = 0.
309 if (obc%freeslip_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
312 if (obc%computed_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
313 if (obc%segment(n)%direction == obc_direction_n)
then 314 dudy(i,j) = 2.0*(obc%segment(n)%tangential_vel(i,j,k) - u(i,j,k))*g%dxCu(i,j)
316 dudy(i,j) = 2.0*(u(i,j+1,k) - obc%segment(n)%tangential_vel(i,j,k))*g%dxCu(i,j+1)
319 if (obc%specified_vorticity)
then ;
do i=obc%segment(n)%HI%IsdB,obc%segment(n)%HI%IedB
320 if (obc%segment(n)%direction == obc_direction_n)
then 321 dudy(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dxCu(i,j)*g%dyBu(i,j)
323 dudy(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dxCu(i,j+1)*g%dyBu(i,j)
328 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
329 if (obc%segment(n)%direction == obc_direction_n)
then 330 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j,k)
332 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j+1,k)
336 if (cs%Coriolis_En_Dis)
then 337 do i = max(isq-1,obc%segment(n)%HI%isd), min(ieq+2,obc%segment(n)%HI%ied)
338 if (obc%segment(n)%direction == obc_direction_n)
then 339 vh_center(i,j) = g%dx_Cv(i,j) * v(i,j,k) * h(i,j,k)
341 vh_center(i,j) = g%dx_Cv(i,j) * v(i,j,k) * h(i,j+1,k)
345 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then 346 if (obc%zero_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
347 dvdx(i,j) = 0. ; dudy(i,j) = 0.
349 if (obc%freeslip_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
352 if (obc%computed_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
353 if (obc%segment(n)%direction == obc_direction_e)
then 354 dvdx(i,j) = 2.0*(obc%segment(n)%tangential_vel(i,j,k) - v(i,j,k))*g%dyCv(i,j)
356 dvdx(i,j) = 2.0*(v(i+1,j,k) - obc%segment(n)%tangential_vel(i,j,k))*g%dyCv(i+1,j)
359 if (obc%specified_vorticity)
then ;
do j=obc%segment(n)%HI%JsdB,obc%segment(n)%HI%JedB
360 if (obc%segment(n)%direction == obc_direction_e)
then 361 dvdx(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dyCv(i,j)*g%dxBu(i,j)
363 dvdx(i,j) = obc%segment(n)%tangential_grad(i,j,k)*g%dyCv(i+1,j)*g%dxBu(i,j)
368 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
369 if (obc%segment(n)%direction == obc_direction_e)
then 370 harea_u(i,j) = 0.5*(area_h(i,j) + area_h(i+1,j)) * h(i,j,k)
372 harea_u(i,j) = 0.5*(area_h(i,j) + area_h(i+1,j)) * h(i+1,j,k)
375 if (cs%Coriolis_En_Dis)
then 376 do j = max(jsq-1,obc%segment(n)%HI%jsd), min(jeq+2,obc%segment(n)%HI%jed)
377 if (obc%segment(n)%direction == obc_direction_e)
then 378 uh_center(i,j) = g%dy_Cu(i,j) * u(i,j,k) * h(i,j,k)
380 uh_center(i,j) = g%dy_Cu(i,j) * u(i,j,k) * h(i+1,j,k)
387 if (
associated(obc))
then ;
do n=1,obc%number_of_segments
388 if (.not. obc%segment(n)%on_pe) cycle
391 i = obc%segment(n)%HI%IsdB ; j = obc%segment(n)%HI%JsdB
392 if (obc%segment(n)%is_N_or_S .and. (j >= jsq-1) .and. (j <= jeq+1))
then 393 do i = max(isq-1,obc%segment(n)%HI%IsdB), min(ieq+1,obc%segment(n)%HI%IedB)
394 if (obc%segment(n)%direction == obc_direction_n)
then 395 if (area_h(i,j) + area_h(i+1,j) > 0.0)
then 396 harea_u(i,j+1) = harea_u(i,j) * ((area_h(i,j+1) + area_h(i+1,j+1)) / &
397 (area_h(i,j) + area_h(i+1,j)))
398 else ; harea_u(i,j+1) = 0.0 ;
endif 400 if (area_h(i,j+1) + area_h(i+1,j+1) > 0.0)
then 401 harea_u(i,j) = harea_u(i,j+1) * ((area_h(i,j) + area_h(i+1,j)) / &
402 (area_h(i,j+1) + area_h(i+1,j+1)))
403 else ; harea_u(i,j) = 0.0 ;
endif 406 elseif (obc%segment(n)%is_E_or_W .and. (i >= isq-1) .and. (i <= ieq+1))
then 407 do j = max(jsq-1,obc%segment(n)%HI%JsdB), min(jeq+1,obc%segment(n)%HI%JedB)
408 if (obc%segment(n)%direction == obc_direction_e)
then 409 if (area_h(i,j) + area_h(i,j+1) > 0.0)
then 410 harea_v(i+1,j) = harea_v(i,j) * ((area_h(i+1,j) + area_h(i+1,j+1)) / &
411 (area_h(i,j) + area_h(i,j+1)))
412 else ; harea_v(i+1,j) = 0.0 ;
endif 414 harea_v(i,j) = 0.5 * (area_h(i,j) + area_h(i,j+1)) * h(i,j+1,k)
415 if (area_h(i+1,j) + area_h(i+1,j+1) > 0.0)
then 416 harea_v(i,j) = harea_v(i+1,j) * ((area_h(i,j) + area_h(i,j+1)) / &
417 (area_h(i+1,j) + area_h(i+1,j+1)))
418 else ; harea_v(i,j) = 0.0 ;
endif 424 do j=jsq-1,jeq+1 ;
do i=isq-1,ieq+1
425 if (cs%no_slip )
then 426 relative_vorticity = (2.0-g%mask2dBu(i,j)) * (dvdx(i,j) - dudy(i,j)) * g%IareaBu(i,j)
428 relative_vorticity = g%mask2dBu(i,j) * (dvdx(i,j) - dudy(i,j)) * g%IareaBu(i,j)
430 absolute_vorticity = g%CoriolisBu(i,j) + relative_vorticity
432 if (area_q(i,j) > 0.0)
then 433 harea_q = (harea_u(i,j) + harea_u(i,j+1)) + (harea_v(i,j) + harea_v(i+1,j))
434 ih = area_q(i,j) / (harea_q + h_neglect*area_q(i,j))
436 q(i,j) = absolute_vorticity * ih
437 abs_vort(i,j) = absolute_vorticity
440 if (cs%bound_Coriolis)
then 441 fv1 = absolute_vorticity * v(i+1,j,k)
442 fv2 = absolute_vorticity * v(i,j,k)
443 fu1 = -absolute_vorticity * u(i,j+1,k)
444 fu2 = -absolute_vorticity * u(i,j,k)
446 max_fvq(i,j) = fv1 ; min_fvq(i,j) = fv2
448 max_fvq(i,j) = fv2 ; min_fvq(i,j) = fv1
451 max_fuq(i,j) = fu1 ; min_fuq(i,j) = fu2
453 max_fuq(i,j) = fu2 ; min_fuq(i,j) = fu1
457 if (cs%id_rv > 0) rv(i,j,k) = relative_vorticity
458 if (cs%id_PV > 0) pv(i,j,k) = q(i,j)
459 if (
associated(ad%rv_x_v) .or.
associated(ad%rv_x_u)) &
460 q2(i,j) = relative_vorticity * ih
467 if (cs%Coriolis_Scheme == arakawa_hsu90)
then 470 a(i,j) = (q(i,j) + (q(i+1,j) + q(i,j-1))) * c1_12
471 d(i,j) = ((q(i,j) + q(i+1,j-1)) + q(i,j-1)) * c1_12
474 b(i,j) = (q(i,j) + (q(i-1,j) + q(i,j-1))) * c1_12
475 c(i,j) = ((q(i,j) + q(i-1,j-1)) + q(i,j-1)) * c1_12
478 elseif (cs%Coriolis_Scheme == arakawa_lamb81)
then 479 do j=jsq,jeq+1 ;
do i=isq,ieq+1
480 a(i-1,j) = (2.0*(q(i,j) + q(i-1,j-1)) + (q(i-1,j) + q(i,j-1))) * c1_24
481 d(i-1,j) = ((q(i,j) + q(i-1,j-1)) + 2.0*(q(i-1,j) + q(i,j-1))) * c1_24
482 b(i,j) = ((q(i,j) + q(i-1,j-1)) + 2.0*(q(i-1,j) + q(i,j-1))) * c1_24
483 c(i,j) = (2.0*(q(i,j) + q(i-1,j-1)) + (q(i-1,j) + q(i,j-1))) * c1_24
484 ep_u(i,j) = ((q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
485 ep_v(i,j) = (-(q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
487 elseif (cs%Coriolis_Scheme == al_blend)
then 488 fe_m2 = cs%F_eff_max_blend - 2.0
489 rat_lin = 1.5 * fe_m2 / max(cs%wt_lin_blend, 1.0e-16)
492 if (cs%F_eff_max_blend <= 2.0)
then ; fe_m2 = -1. ; rat_lin = -1.0 ;
endif 494 do j=jsq,jeq+1 ;
do i=isq,ieq+1
495 min_ihq = min(ih_q(i-1,j-1), ih_q(i,j-1), ih_q(i-1,j), ih_q(i,j))
496 max_ihq = max(ih_q(i-1,j-1), ih_q(i,j-1), ih_q(i-1,j), ih_q(i,j))
498 if (max_ihq < 1.0e15*min_ihq) rat_m1 = max_ihq / min_ihq - 1.0
505 if (rat_m1 <= fe_m2)
then ; al_wt = 1.0
506 elseif (rat_m1 < 1.5*fe_m2)
then ; al_wt = 3.0*fe_m2 / rat_m1 - 2.0
507 else ; al_wt = 0.0 ;
endif 510 if (rat_m1 <= 1.5*fe_m2)
then ; sad_wt = 0.0
511 elseif (rat_m1 <= rat_lin)
then 512 sad_wt = 1.0 - (1.5*fe_m2) / rat_m1
513 elseif (rat_m1 < 2.0*rat_lin)
then 514 sad_wt = 1.0 - (cs%wt_lin_blend / rat_lin) * (rat_m1 - 2.0*rat_lin)
515 else ; sad_wt = 1.0 ;
endif 517 a(i-1,j) = sad_wt * 0.25 * q(i-1,j) + (1.0 - sad_wt) * &
518 ( ((2.0-al_wt)* q(i-1,j) + al_wt*q(i,j-1)) + &
519 2.0 * (q(i,j) + q(i-1,j-1)) ) * c1_24
520 d(i-1,j) = sad_wt * 0.25 * q(i-1,j-1) + (1.0 - sad_wt) * &
521 ( ((2.0-al_wt)* q(i-1,j-1) + al_wt*q(i,j)) + &
522 2.0 * (q(i-1,j) + q(i,j-1)) ) * c1_24
523 b(i,j) = sad_wt * 0.25 * q(i,j) + (1.0 - sad_wt) * &
524 ( ((2.0-al_wt)* q(i,j) + al_wt*q(i-1,j-1)) + &
525 2.0 * (q(i-1,j) + q(i,j-1)) ) * c1_24
526 c(i,j) = sad_wt * 0.25 * q(i,j-1) + (1.0 - sad_wt) * &
527 ( ((2.0-al_wt)* q(i,j-1) + al_wt*q(i-1,j)) + &
528 2.0 * (q(i,j) + q(i-1,j-1)) ) * c1_24
529 ep_u(i,j) = al_wt * ((q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
530 ep_v(i,j) = al_wt * (-(q(i,j) - q(i-1,j-1)) + (q(i-1,j) - q(i,j-1))) * c1_24
534 if (cs%Coriolis_En_Dis)
then 536 c1 = 1.0-1.5*0.5 ; c2 = 1.0-0.5 ; c3 = 2.0 ; slope = 0.5
538 do j=jsq,jeq+1 ;
do i=is-1,ie
542 if (g%dy_Cu(i,j) == 0.0) uhc = uhm
544 if (abs(uhc) < 0.1*abs(uhm))
then 546 elseif (abs(uhc) > c1*abs(uhm))
then 547 if (abs(uhc) < c2*abs(uhm))
then ; uhc = (3.0*uhc+(1.0-c2*3.0)*uhm)
548 elseif (abs(uhc) <= c3*abs(uhm))
then ; uhc = uhm
549 else ; uhc = slope*uhc+(1.0-c3*slope)*uhm
554 uh_min(i,j) = uhm ; uh_max(i,j) = uhc
556 uh_max(i,j) = uhm ; uh_min(i,j) = uhc
559 do j=js-1,je ;
do i=isq,ieq+1
563 if (g%dx_Cv(i,j) == 0.0) vhc = vhm
565 if (abs(vhc) < 0.1*abs(vhm))
then 567 elseif (abs(vhc) > c1*abs(vhm))
then 568 if (abs(vhc) < c2*abs(vhm))
then ; vhc = (3.0*vhc+(1.0-c2*3.0)*vhm)
569 elseif (abs(vhc) <= c3*abs(vhm))
then ; vhc = vhm
570 else ; vhc = slope*vhc+(1.0-c3*slope)*vhm
575 vh_min(i,j) = vhm ; vh_max(i,j) = vhc
577 vh_max(i,j) = vhm ; vh_min(i,j) = vhc
583 call gradke(u, v, h, ke, kex, key, k, obc, g, us, cs)
588 if (cs%Coriolis_Scheme == sadourny75_energy)
then 589 if (cs%Coriolis_En_Dis)
then 591 do j=js,je ;
do i=isq,ieq
592 if (q(i,j)*u(i,j,k) == 0.0)
then 593 temp1 = q(i,j) * ( (vh_max(i,j)+vh_max(i+1,j)) &
594 + (vh_min(i,j)+vh_min(i+1,j)) )*0.5
595 elseif (q(i,j)*u(i,j,k) < 0.0)
then 596 temp1 = q(i,j) * (vh_max(i,j)+vh_max(i+1,j))
598 temp1 = q(i,j) * (vh_min(i,j)+vh_min(i+1,j))
600 if (q(i,j-1)*u(i,j,k) == 0.0)
then 601 temp2 = q(i,j-1) * ( (vh_max(i,j-1)+vh_max(i+1,j-1)) &
602 + (vh_min(i,j-1)+vh_min(i+1,j-1)) )*0.5
603 elseif (q(i,j-1)*u(i,j,k) < 0.0)
then 604 temp2 = q(i,j-1) * (vh_max(i,j-1)+vh_max(i+1,j-1))
606 temp2 = q(i,j-1) * (vh_min(i,j-1)+vh_min(i+1,j-1))
608 cau(i,j,k) = 0.25 * g%IdxCu(i,j) * (temp1 + temp2)
612 do j=js,je ;
do i=isq,ieq
613 cau(i,j,k) = 0.25 * &
614 (q(i,j) * (vh(i+1,j,k) + vh(i,j,k)) + &
615 q(i,j-1) * (vh(i,j-1,k) + vh(i+1,j-1,k))) * g%IdxCu(i,j)
618 elseif (cs%Coriolis_Scheme == sadourny75_enstro)
then 619 do j=js,je ;
do i=isq,ieq
620 cau(i,j,k) = 0.125 * (g%IdxCu(i,j) * (q(i,j) + q(i,j-1))) * &
621 ((vh(i+1,j,k) + vh(i,j,k)) + (vh(i,j-1,k) + vh(i+1,j-1,k)))
623 elseif ((cs%Coriolis_Scheme == arakawa_hsu90) .or. &
624 (cs%Coriolis_Scheme == arakawa_lamb81) .or. &
625 (cs%Coriolis_Scheme == al_blend))
then 627 do j=js,je ;
do i=isq,ieq
628 cau(i,j,k) = ((a(i,j) * vh(i+1,j,k) + c(i,j) * vh(i,j-1,k)) + &
629 (b(i,j) * vh(i,j,k) + d(i,j) * vh(i+1,j-1,k))) * g%IdxCu(i,j)
631 elseif (cs%Coriolis_Scheme == robust_enstro)
then 635 do j=js,je ;
do i=isq,ieq
636 heff1 = abs(vh(i,j,k) * g%IdxCv(i,j)) / (eps_vel+abs(v(i,j,k)))
637 heff1 = max(heff1, min(h(i,j,k),h(i,j+1,k)))
638 heff1 = min(heff1, max(h(i,j,k),h(i,j+1,k)))
639 heff2 = abs(vh(i,j-1,k) * g%IdxCv(i,j-1)) / (eps_vel+abs(v(i,j-1,k)))
640 heff2 = max(heff2, min(h(i,j-1,k),h(i,j,k)))
641 heff2 = min(heff2, max(h(i,j-1,k),h(i,j,k)))
642 heff3 = abs(vh(i+1,j,k) * g%IdxCv(i+1,j)) / (eps_vel+abs(v(i+1,j,k)))
643 heff3 = max(heff3, min(h(i+1,j,k),h(i+1,j+1,k)))
644 heff3 = min(heff3, max(h(i+1,j,k),h(i+1,j+1,k)))
645 heff4 = abs(vh(i+1,j-1,k) * g%IdxCv(i+1,j-1)) / (eps_vel+abs(v(i+1,j-1,k)))
646 heff4 = max(heff4, min(h(i+1,j-1,k),h(i+1,j,k)))
647 heff4 = min(heff4, max(h(i+1,j-1,k),h(i+1,j,k)))
648 if (cs%PV_Adv_Scheme == pv_adv_centered)
then 649 cau(i,j,k) = 0.5*(abs_vort(i,j)+abs_vort(i,j-1)) * &
650 ((vh(i,j,k) + vh(i+1,j-1,k)) + (vh(i,j-1,k) + vh(i+1,j,k)) ) / &
651 (h_tiny + ((heff1+heff4) + (heff2+heff3)) ) * g%IdxCu(i,j)
652 elseif (cs%PV_Adv_Scheme == pv_adv_upwind1)
then 653 vheff = ((vh(i,j,k) + vh(i+1,j-1,k)) + (vh(i,j-1,k) + vh(i+1,j,k)) )
654 qvheff = 0.5*( (abs_vort(i,j)+abs_vort(i,j-1))*vheff &
655 -(abs_vort(i,j)-abs_vort(i,j-1))*abs(vheff) )
656 cau(i,j,k) = (qvheff / ( h_tiny + ((heff1+heff4) + (heff2+heff3)) ) ) * g%IdxCu(i,j)
661 if ((cs%Coriolis_Scheme == arakawa_lamb81) .or. &
662 (cs%Coriolis_Scheme == al_blend))
then ;
do j=js,je ;
do i=isq,ieq
663 cau(i,j,k) = cau(i,j,k) + &
664 (ep_u(i,j)*uh(i-1,j,k) - ep_u(i+1,j)*uh(i+1,j,k)) * g%IdxCu(i,j)
665 enddo ;
enddo ;
endif 668 if (cs%bound_Coriolis)
then 669 do j=js,je ;
do i=isq,ieq
670 max_fv = max(max_fvq(i,j), max_fvq(i,j-1))
671 min_fv = min(min_fvq(i,j), min_fvq(i,j-1))
674 if (cau(i,j,k) > max_fv)
then 677 if (cau(i,j,k) < min_fv) cau(i,j,k) = min_fv
683 do j=js,je ;
do i=isq,ieq
684 cau(i,j,k) = cau(i,j,k) - kex(i,j)
685 if (
associated(ad%gradKEu)) ad%gradKEu(i,j,k) = -kex(i,j)
692 if (cs%Coriolis_Scheme == sadourny75_energy)
then 693 if (cs%Coriolis_En_Dis)
then 695 do j=jsq,jeq ;
do i=is,ie
696 if (q(i-1,j)*v(i,j,k) == 0.0)
then 697 temp1 = q(i-1,j) * ( (uh_max(i-1,j)+uh_max(i-1,j+1)) &
698 + (uh_min(i-1,j)+uh_min(i-1,j+1)) )*0.5
699 elseif (q(i-1,j)*v(i,j,k) > 0.0)
then 700 temp1 = q(i-1,j) * (uh_max(i-1,j)+uh_max(i-1,j+1))
702 temp1 = q(i-1,j) * (uh_min(i-1,j)+uh_min(i-1,j+1))
704 if (q(i,j)*v(i,j,k) == 0.0)
then 705 temp2 = q(i,j) * ( (uh_max(i,j)+uh_max(i,j+1)) &
706 + (uh_min(i,j)+uh_min(i,j+1)) )*0.5
707 elseif (q(i,j)*v(i,j,k) > 0.0)
then 708 temp2 = q(i,j) * (uh_max(i,j)+uh_max(i,j+1))
710 temp2 = q(i,j) * (uh_min(i,j)+uh_min(i,j+1))
712 cav(i,j,k) = -0.25 * g%IdyCv(i,j) * (temp1 + temp2)
716 do j=jsq,jeq ;
do i=is,ie
717 cav(i,j,k) = - 0.25* &
718 (q(i-1,j)*(uh(i-1,j,k) + uh(i-1,j+1,k)) + &
719 q(i,j)*(uh(i,j,k) + uh(i,j+1,k))) * g%IdyCv(i,j)
722 elseif (cs%Coriolis_Scheme == sadourny75_enstro)
then 723 do j=jsq,jeq ;
do i=is,ie
724 cav(i,j,k) = -0.125 * (g%IdyCv(i,j) * (q(i-1,j) + q(i,j))) * &
725 ((uh(i-1,j,k) + uh(i-1,j+1,k)) + (uh(i,j,k) + uh(i,j+1,k)))
727 elseif ((cs%Coriolis_Scheme == arakawa_hsu90) .or. &
728 (cs%Coriolis_Scheme == arakawa_lamb81) .or. &
729 (cs%Coriolis_Scheme == al_blend))
then 731 do j=jsq,jeq ;
do i=is,ie
732 cav(i,j,k) = - ((a(i-1,j) * uh(i-1,j,k) + &
733 c(i,j+1) * uh(i,j+1,k)) &
734 + (b(i,j) * uh(i,j,k) + &
735 d(i-1,j+1) * uh(i-1,j+1,k))) * g%IdyCv(i,j)
737 elseif (cs%Coriolis_Scheme == robust_enstro)
then 741 do j=jsq,jeq ;
do i=is,ie
742 heff1 = abs(uh(i,j,k) * g%IdyCu(i,j)) / (eps_vel+abs(u(i,j,k)))
743 heff1 = max(heff1, min(h(i,j,k),h(i+1,j,k)))
744 heff1 = min(heff1, max(h(i,j,k),h(i+1,j,k)))
745 heff2 = abs(uh(i-1,j,k) * g%IdyCu(i-1,j)) / (eps_vel+abs(u(i-1,j,k)))
746 heff2 = max(heff2, min(h(i-1,j,k),h(i,j,k)))
747 heff2 = min(heff2, max(h(i-1,j,k),h(i,j,k)))
748 heff3 = abs(uh(i,j+1,k) * g%IdyCu(i,j+1)) / (eps_vel+abs(u(i,j+1,k)))
749 heff3 = max(heff3, min(h(i,j+1,k),h(i+1,j+1,k)))
750 heff3 = min(heff3, max(h(i,j+1,k),h(i+1,j+1,k)))
751 heff4 = abs(uh(i-1,j+1,k) * g%IdyCu(i-1,j+1)) / (eps_vel+abs(u(i-1,j+1,k)))
752 heff4 = max(heff4, min(h(i-1,j+1,k),h(i,j+1,k)))
753 heff4 = min(heff4, max(h(i-1,j+1,k),h(i,j+1,k)))
754 if (cs%PV_Adv_Scheme == pv_adv_centered)
then 755 cav(i,j,k) = - 0.5*(abs_vort(i,j)+abs_vort(i-1,j)) * &
756 ((uh(i ,j ,k)+uh(i-1,j+1,k)) + &
757 (uh(i-1,j ,k)+uh(i ,j+1,k)) ) / &
758 (h_tiny + ((heff1+heff4) +(heff2+heff3)) ) * g%IdyCv(i,j)
759 elseif (cs%PV_Adv_Scheme == pv_adv_upwind1)
then 760 uheff = ((uh(i ,j ,k)+uh(i-1,j+1,k)) + &
761 (uh(i-1,j ,k)+uh(i ,j+1,k)) )
762 quheff = 0.5*( (abs_vort(i,j)+abs_vort(i-1,j))*uheff &
763 -(abs_vort(i,j)-abs_vort(i-1,j))*abs(uheff) )
764 cav(i,j,k) = - quheff / &
765 (h_tiny + ((heff1+heff4) +(heff2+heff3)) ) * g%IdyCv(i,j)
770 if ((cs%Coriolis_Scheme == arakawa_lamb81) .or. &
771 (cs%Coriolis_Scheme == al_blend))
then ;
do j=jsq,jeq ;
do i=is,ie
772 cav(i,j,k) = cav(i,j,k) + &
773 (ep_v(i,j)*vh(i,j-1,k) - ep_v(i,j+1)*vh(i,j+1,k)) * g%IdyCv(i,j)
774 enddo ;
enddo ;
endif 776 if (cs%bound_Coriolis)
then 777 do j=jsq,jeq ;
do i=is,ie
778 max_fu = max(max_fuq(i,j),max_fuq(i-1,j))
779 min_fu = min(min_fuq(i,j),min_fuq(i-1,j))
780 if (cav(i,j,k) > max_fu)
then 783 if (cav(i,j,k) < min_fu) cav(i,j,k) = min_fu
789 do j=jsq,jeq ;
do i=is,ie
790 cav(i,j,k) = cav(i,j,k) - key(i,j)
791 if (
associated(ad%gradKEv)) ad%gradKEv(i,j,k) = -key(i,j)
794 if (
associated(ad%rv_x_u) .or.
associated(ad%rv_x_v))
then 796 if (cs%Coriolis_Scheme == sadourny75_energy)
then 797 if (
associated(ad%rv_x_u))
then 798 do j=jsq,jeq ;
do i=is,ie
799 ad%rv_x_u(i,j,k) = - 0.25* &
800 (q2(i-1,j)*(uh(i-1,j,k) + uh(i-1,j+1,k)) + &
801 q2(i,j)*(uh(i,j,k) + uh(i,j+1,k))) * g%IdyCv(i,j)
805 if (
associated(ad%rv_x_v))
then 806 do j=js,je ;
do i=isq,ieq
807 ad%rv_x_v(i,j,k) = 0.25 * &
808 (q2(i,j) * (vh(i+1,j,k) + vh(i,j,k)) + &
809 q2(i,j-1) * (vh(i,j-1,k) + vh(i+1,j-1,k))) * g%IdxCu(i,j)
813 if (
associated(ad%rv_x_u))
then 814 do j=jsq,jeq ;
do i=is,ie
815 ad%rv_x_u(i,j,k) = -g%IdyCv(i,j) * c1_12 * &
816 ((q2(i,j) + q2(i-1,j) + q2(i-1,j-1)) * uh(i-1,j,k) + &
817 (q2(i-1,j) + q2(i,j) + q2(i,j-1)) * uh(i,j,k) + &
818 (q2(i-1,j) + q2(i,j+1) + q2(i,j)) * uh(i,j+1,k) + &
819 (q2(i,j) + q2(i-1,j+1) + q2(i-1,j)) * uh(i-1,j+1,k))
823 if (
associated(ad%rv_x_v))
then 824 do j=js,je ;
do i=isq,ieq
825 ad%rv_x_v(i,j,k) = g%IdxCu(i,j) * c1_12 * &
826 ((q2(i+1,j) + q2(i,j) + q2(i,j-1)) * vh(i+1,j,k) + &
827 (q2(i-1,j) + q2(i,j) + q2(i,j-1)) * vh(i,j,k) + &
828 (q2(i-1,j-1) + q2(i,j) + q2(i,j-1)) * vh(i,j-1,k) + &
829 (q2(i+1,j-1) + q2(i,j) + q2(i,j-1)) * vh(i+1,j-1,k))
838 if (query_averaging_enabled(cs%diag))
then 839 if (cs%id_rv > 0)
call post_data(cs%id_rv, rv, cs%diag)
840 if (cs%id_PV > 0)
call post_data(cs%id_PV, pv, cs%diag)
841 if (cs%id_gKEu>0)
call post_data(cs%id_gKEu, ad%gradKEu, cs%diag)
842 if (cs%id_gKEv>0)
call post_data(cs%id_gKEv, ad%gradKEv, cs%diag)
843 if (cs%id_rvxu > 0)
call post_data(cs%id_rvxu, ad%rv_x_u, cs%diag)
844 if (cs%id_rvxv > 0)
call post_data(cs%id_rvxv, ad%rv_x_v, cs%diag)
866 if (cs%id_hf_gKEu_2d > 0)
then 867 allocate(hf_gkeu_2d(g%IsdB:g%IedB,g%jsd:g%jed))
868 hf_gkeu_2d(:,:) = 0.0
869 do k=1,nz ;
do j=js,je ;
do i=isq,ieq
870 hf_gkeu_2d(i,j) = hf_gkeu_2d(i,j) + ad%gradKEu(i,j,k) * ad%diag_hfrac_u(i,j,k)
871 enddo ;
enddo ;
enddo 872 call post_data(cs%id_hf_gKEu_2d, hf_gkeu_2d, cs%diag)
873 deallocate(hf_gkeu_2d)
876 if (cs%id_hf_gKEv_2d > 0)
then 877 allocate(hf_gkev_2d(g%isd:g%ied,g%JsdB:g%JedB))
878 hf_gkev_2d(:,:) = 0.0
879 do k=1,nz ;
do j=jsq,jeq ;
do i=is,ie
880 hf_gkev_2d(i,j) = hf_gkev_2d(i,j) + ad%gradKEv(i,j,k) * ad%diag_hfrac_v(i,j,k)
881 enddo ;
enddo ;
enddo 882 call post_data(cs%id_hf_gKEv_2d, hf_gkev_2d, cs%diag)
883 deallocate(hf_gkev_2d)
902 if (cs%id_hf_rvxv_2d > 0)
then 903 allocate(hf_rvxv_2d(g%IsdB:g%IedB,g%jsd:g%jed))
904 hf_rvxv_2d(:,:) = 0.0
905 do k=1,nz ;
do j=js,je ;
do i=isq,ieq
906 hf_rvxv_2d(i,j) = hf_rvxv_2d(i,j) + ad%rv_x_v(i,j,k) * ad%diag_hfrac_u(i,j,k)
907 enddo ;
enddo ;
enddo 908 call post_data(cs%id_hf_rvxv_2d, hf_rvxv_2d, cs%diag)
909 deallocate(hf_rvxv_2d)
912 if (cs%id_hf_rvxu_2d > 0)
then 913 allocate(hf_rvxu_2d(g%isd:g%ied,g%JsdB:g%JedB))
914 hf_rvxu_2d(:,:) = 0.0
915 do k=1,nz ;
do j=jsq,jeq ;
do i=is,ie
916 hf_rvxu_2d(i,j) = hf_rvxu_2d(i,j) + ad%rv_x_u(i,j,k) * ad%diag_hfrac_v(i,j,k)
917 enddo ;
enddo ;
enddo 918 call post_data(cs%id_hf_rvxu_2d, hf_rvxu_2d, cs%diag)
919 deallocate(hf_rvxu_2d)
923 end subroutine coradcalc
927 subroutine gradke(u, v, h, KE, KEx, KEy, k, OBC, G, US, CS)
929 real,
dimension(SZIB_(G),SZJ_(G),SZK_(G)),
intent(in) :: u
930 real,
dimension(SZI_(G),SZJB_(G),SZK_(G)),
intent(in) :: v
931 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
932 real,
dimension(SZI_(G) ,SZJ_(G) ),
intent(out) :: KE
933 real,
dimension(SZIB_(G),SZJ_(G) ),
intent(out) :: KEx
935 real,
dimension(SZI_(G) ,SZJB_(G)),
intent(out) :: KEy
937 integer,
intent(in) :: k
942 real :: um, up, vm, vp
943 real :: um2, up2, vm2, vp2
944 real :: um2a, up2a, vm2a, vp2a
945 integer :: i, j, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz, n
947 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
948 isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
952 if (cs%KE_Scheme == ke_arakawa)
then 956 do j=jsq,jeq+1 ;
do i=isq,ieq+1
957 ke(i,j) = ( ( g%areaCu( i ,j)*(u( i ,j,k)*u( i ,j,k)) + &
958 g%areaCu(i-1,j)*(u(i-1,j,k)*u(i-1,j,k)) ) + &
959 ( g%areaCv(i, j )*(v(i, j ,k)*v(i, j ,k)) + &
960 g%areaCv(i,j-1)*(v(i,j-1,k)*v(i,j-1,k)) ) )*0.25*g%IareaT(i,j)
962 elseif (cs%KE_Scheme == ke_simple_gudonov)
then 965 do j=jsq,jeq+1 ;
do i=isq,ieq+1
966 up = 0.5*( u(i-1,j,k) + abs( u(i-1,j,k) ) ) ; up2 = up*up
967 um = 0.5*( u( i ,j,k) - abs( u( i ,j,k) ) ) ; um2 = um*um
968 vp = 0.5*( v(i,j-1,k) + abs( v(i,j-1,k) ) ) ; vp2 = vp*vp
969 vm = 0.5*( v(i, j ,k) - abs( v(i, j ,k) ) ) ; vm2 = vm*vm
970 ke(i,j) = ( max(up2,um2) + max(vp2,vm2) ) *0.5
972 elseif (cs%KE_Scheme == ke_gudonov)
then 975 do j=jsq,jeq+1 ;
do i=isq,ieq+1
976 up = 0.5*( u(i-1,j,k) + abs( u(i-1,j,k) ) ) ; up2a = up*up*g%areaCu(i-1,j)
977 um = 0.5*( u( i ,j,k) - abs( u( i ,j,k) ) ) ; um2a = um*um*g%areaCu( i ,j)
978 vp = 0.5*( v(i,j-1,k) + abs( v(i,j-1,k) ) ) ; vp2a = vp*vp*g%areaCv(i,j-1)
979 vm = 0.5*( v(i, j ,k) - abs( v(i, j ,k) ) ) ; vm2a = vm*vm*g%areaCv(i, j )
980 ke(i,j) = ( max(um2a,up2a) + max(vm2a,vp2a) )*0.5*g%IareaT(i,j)
985 do j=js,je ;
do i=isq,ieq
986 kex(i,j) = (ke(i+1,j) - ke(i,j)) * g%IdxCu(i,j)
990 do j=jsq,jeq ;
do i=is,ie
991 key(i,j) = (ke(i,j+1) - ke(i,j)) * g%IdyCv(i,j)
994 if (
associated(obc))
then 995 do n=1,obc%number_of_segments
996 if (obc%segment(n)%is_N_or_S)
then 997 do i=obc%segment(n)%HI%isd,obc%segment(n)%HI%ied
998 key(i,obc%segment(n)%HI%JsdB) = 0.
1000 elseif (obc%segment(n)%is_E_or_W)
then 1001 do j=obc%segment(n)%HI%jsd,obc%segment(n)%HI%jed
1002 kex(obc%segment(n)%HI%IsdB,j) = 0.
1008 end subroutine gradke
1011 subroutine coriolisadv_init(Time, G, GV, US, param_file, diag, AD, CS)
1012 type(time_type),
target,
intent(in) :: time
1017 type(
diag_ctrl),
target,
intent(inout) :: diag
1022 #include "version_variable.h" 1023 character(len=40) :: mdl =
"MOM_CoriolisAdv" 1024 character(len=20) :: tmpstr
1025 character(len=400) :: mesg
1026 integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, nz
1028 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nz = gv%ke
1029 isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1031 if (
associated(cs))
then 1032 call mom_error(warning,
"CoriolisAdv_init called with associated control structure.")
1037 cs%diag => diag ; cs%Time => time
1041 call get_param(param_file, mdl,
"NOSLIP", cs%no_slip, &
1042 "If true, no slip boundary conditions are used; otherwise "//&
1043 "free slip boundary conditions are assumed. The "//&
1044 "implementation of the free slip BCs on a C-grid is much "//&
1045 "cleaner than the no slip BCs. The use of free slip BCs "//&
1046 "is strongly encouraged, and no slip BCs are not used with "//&
1047 "the biharmonic viscosity.", default=.false.)
1049 call get_param(param_file, mdl,
"CORIOLIS_EN_DIS", cs%Coriolis_En_Dis, &
1050 "If true, two estimates of the thickness fluxes are used "//&
1051 "to estimate the Coriolis term, and the one that "//&
1052 "dissipates energy relative to the other one is used.", &
1057 call get_param(param_file, mdl,
"CORIOLIS_SCHEME", tmpstr, &
1058 "CORIOLIS_SCHEME selects the discretization for the "//&
1059 "Coriolis terms. Valid values are: \n"//&
1060 "\t SADOURNY75_ENERGY - Sadourny, 1975; energy cons. \n"//&
1061 "\t ARAKAWA_HSU90 - Arakawa & Hsu, 1990 \n"//&
1062 "\t SADOURNY75_ENSTRO - Sadourny, 1975; enstrophy cons. \n"//&
1063 "\t ARAKAWA_LAMB81 - Arakawa & Lamb, 1981; En. + Enst.\n"//&
1064 "\t ARAKAWA_LAMB_BLEND - A blend of Arakawa & Lamb with \n"//&
1065 "\t Arakawa & Hsu and Sadourny energy", &
1066 default=sadourny75_energy_string)
1067 tmpstr = uppercase(tmpstr)
1068 select case (tmpstr)
1069 case (sadourny75_energy_string)
1070 cs%Coriolis_Scheme = sadourny75_energy
1071 case (arakawa_hsu_string)
1072 cs%Coriolis_Scheme = arakawa_hsu90
1073 case (sadourny75_enstro_string)
1074 cs%Coriolis_Scheme = sadourny75_enstro
1075 case (arakawa_lamb_string)
1076 cs%Coriolis_Scheme = arakawa_lamb81
1077 case (al_blend_string)
1078 cs%Coriolis_Scheme = al_blend
1079 case (robust_enstro_string)
1080 cs%Coriolis_Scheme = robust_enstro
1081 cs%Coriolis_En_Dis = .false.
1083 call mom_mesg(
'CoriolisAdv_init: Coriolis_Scheme ="'//trim(tmpstr)//
'"', 0)
1084 call mom_error(fatal,
"CoriolisAdv_init: Unrecognized setting "// &
1085 "#define CORIOLIS_SCHEME "//trim(tmpstr)//
" found in input file.")
1087 if (cs%Coriolis_Scheme == al_blend)
then 1088 call get_param(param_file, mdl,
"CORIOLIS_BLEND_WT_LIN", cs%wt_lin_blend, &
1089 "A weighting value for the ratio of inverse thicknesses, "//&
1090 "beyond which the blending between Sadourny Energy and "//&
1091 "Arakawa & Hsu goes linearly to 0 when CORIOLIS_SCHEME "//&
1092 "is ARAWAKA_LAMB_BLEND. This must be between 1 and 1e-16.", &
1093 units=
"nondim", default=0.125)
1094 call get_param(param_file, mdl,
"CORIOLIS_BLEND_F_EFF_MAX", cs%F_eff_max_blend, &
1095 "The factor by which the maximum effective Coriolis "//&
1096 "acceleration from any point can be increased when "//&
1097 "blending different discretizations with the "//&
1098 "ARAKAWA_LAMB_BLEND Coriolis scheme. This must be "//&
1099 "greater than 2.0 (the max value for Sadourny energy).", &
1100 units=
"nondim", default=4.0)
1101 cs%wt_lin_blend = min(1.0, max(cs%wt_lin_blend,1e-16))
1102 if (cs%F_eff_max_blend < 2.0)
call mom_error(warning,
"CoriolisAdv_init: "//&
1103 "CORIOLIS_BLEND_F_EFF_MAX should be at least 2.")
1106 mesg =
"If true, the Coriolis terms at u-points are bounded by "//&
1107 "the four estimates of (f+rv)v from the four neighboring "//&
1108 "v-points, and similarly at v-points." 1109 if (cs%Coriolis_En_Dis .and. (cs%Coriolis_Scheme == sadourny75_energy))
then 1110 mesg = trim(mesg)//
" This option is "//&
1111 "always effectively false with CORIOLIS_EN_DIS defined and "//&
1112 "CORIOLIS_SCHEME set to "//trim(sadourny75_energy_string)//
"." 1114 mesg = trim(mesg)//
" This option would "//&
1115 "have no effect on the SADOURNY Coriolis scheme if it "//&
1116 "were possible to use centered difference thickness fluxes." 1118 call get_param(param_file, mdl,
"BOUND_CORIOLIS", cs%bound_Coriolis, mesg, &
1120 if ((cs%Coriolis_En_Dis .and. (cs%Coriolis_Scheme == sadourny75_energy)) .or. &
1121 (cs%Coriolis_Scheme == robust_enstro)) cs%bound_Coriolis = .false.
1124 call get_param(param_file, mdl,
"KE_SCHEME", tmpstr, &
1125 "KE_SCHEME selects the discretization for acceleration "//&
1126 "due to the kinetic energy gradient. Valid values are: \n"//&
1127 "\t KE_ARAKAWA, KE_SIMPLE_GUDONOV, KE_GUDONOV", &
1128 default=ke_arakawa_string)
1129 tmpstr = uppercase(tmpstr)
1130 select case (tmpstr)
1131 case (ke_arakawa_string); cs%KE_Scheme = ke_arakawa
1132 case (ke_simple_gudonov_string); cs%KE_Scheme = ke_simple_gudonov
1133 case (ke_gudonov_string); cs%KE_Scheme = ke_gudonov
1135 call mom_mesg(
'CoriolisAdv_init: KE_Scheme ="'//trim(tmpstr)//
'"', 0)
1136 call mom_error(fatal,
"CoriolisAdv_init: "// &
1137 "#define KE_SCHEME "//trim(tmpstr)//
" in input file is invalid.")
1141 call get_param(param_file, mdl,
"PV_ADV_SCHEME", tmpstr, &
1142 "PV_ADV_SCHEME selects the discretization for PV "//&
1143 "advection. Valid values are: \n"//&
1144 "\t PV_ADV_CENTERED - centered (aka Sadourny, 75) \n"//&
1145 "\t PV_ADV_UPWIND1 - upwind, first order", &
1146 default=pv_adv_centered_string)
1147 select case (uppercase(tmpstr))
1148 case (pv_adv_centered_string)
1149 cs%PV_Adv_Scheme = pv_adv_centered
1150 case (pv_adv_upwind1_string)
1151 cs%PV_Adv_Scheme = pv_adv_upwind1
1153 call mom_mesg(
'CoriolisAdv_init: PV_Adv_Scheme ="'//trim(tmpstr)//
'"', 0)
1154 call mom_error(fatal,
"CoriolisAdv_init: "// &
1155 "#DEFINE PV_ADV_SCHEME in input file is invalid.")
1158 cs%id_rv = register_diag_field(
'ocean_model',
'RV', diag%axesBL, time, &
1159 'Relative Vorticity',
's-1', conversion=us%s_to_T)
1161 cs%id_PV = register_diag_field(
'ocean_model',
'PV', diag%axesBL, time, &
1162 'Potential Vorticity',
'm-1 s-1', conversion=gv%m_to_H*us%s_to_T)
1164 cs%id_gKEu = register_diag_field(
'ocean_model',
'gKEu', diag%axesCuL, time, &
1165 'Zonal Acceleration from Grad. Kinetic Energy',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1166 if (cs%id_gKEu > 0)
call safe_alloc_ptr(ad%gradKEu,isdb,iedb,jsd,jed,nz)
1168 cs%id_gKEv = register_diag_field(
'ocean_model',
'gKEv', diag%axesCvL, time, &
1169 'Meridional Acceleration from Grad. Kinetic Energy',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1170 if (cs%id_gKEv > 0)
call safe_alloc_ptr(ad%gradKEv,isd,ied,jsdb,jedb,nz)
1172 cs%id_rvxu = register_diag_field(
'ocean_model',
'rvxu', diag%axesCvL, time, &
1173 'Meridional Acceleration from Relative Vorticity',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1174 if (cs%id_rvxu > 0)
call safe_alloc_ptr(ad%rv_x_u,isd,ied,jsdb,jedb,nz)
1176 cs%id_rvxv = register_diag_field(
'ocean_model',
'rvxv', diag%axesCuL, time, &
1177 'Zonal Acceleration from Relative Vorticity',
'm-1 s-2', conversion=us%L_T2_to_m_s2)
1178 if (cs%id_rvxv > 0)
call safe_alloc_ptr(ad%rv_x_v,isdb,iedb,jsd,jed,nz)
1196 cs%id_hf_gKEu_2d = register_diag_field(
'ocean_model',
'hf_gKEu_2d', diag%axesCu1, time, &
1197 'Depth-sum Fractional Thickness-weighted Zonal Acceleration from Grad. Kinetic Energy', &
1198 'm-1 s-2', conversion=us%L_T2_to_m_s2)
1199 if (cs%id_hf_gKEu_2d > 0)
then 1200 call safe_alloc_ptr(ad%gradKEu,isdb,iedb,jsd,jed,nz)
1201 call safe_alloc_ptr(ad%diag_hfrac_u,isdb,iedb,jsd,jed,nz)
1204 cs%id_hf_gKEv_2d = register_diag_field(
'ocean_model',
'hf_gKEv_2d', diag%axesCv1, time, &
1205 'Depth-sum Fractional Thickness-weighted Meridional Acceleration from Grad. Kinetic Energy', &
1206 'm-1 s-2', conversion=us%L_T2_to_m_s2)
1207 if (cs%id_hf_gKEv_2d > 0)
then 1208 call safe_alloc_ptr(ad%gradKEv,isd,ied,jsdb,jedb,nz)
1209 call safe_alloc_ptr(ad%diag_hfrac_v,isd,ied,jsd,jedb,nz)
1228 cs%id_hf_rvxu_2d = register_diag_field(
'ocean_model',
'hf_rvxu_2d', diag%axesCv1, time, &
1229 'Fractional Thickness-weighted Meridional Acceleration from Relative Vorticity', &
1230 'm-1 s-2', conversion=us%L_T2_to_m_s2)
1231 if (cs%id_hf_rvxu_2d > 0)
then 1232 call safe_alloc_ptr(ad%rv_x_u,isd,ied,jsdb,jedb,nz)
1233 call safe_alloc_ptr(ad%diag_hfrac_v,isd,ied,jsd,jedb,nz)
1236 cs%id_hf_rvxv_2d = register_diag_field(
'ocean_model',
'hf_rvxv_2d', diag%axesCu1, time, &
1237 'Depth-sum Fractional Thickness-weighted Zonal Acceleration from Relative Vorticity', &
1238 'm-1 s-2', conversion=us%L_T2_to_m_s2)
1239 if (cs%id_hf_rvxv_2d > 0)
then 1240 call safe_alloc_ptr(ad%rv_x_v,isdb,iedb,jsd,jed,nz)
1241 call safe_alloc_ptr(ad%diag_hfrac_u,isdb,iedb,jsd,jed,nz)
1244 end subroutine coriolisadv_init
1247 subroutine coriolisadv_end(CS)
1250 end subroutine coriolisadv_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.
Accelerations due to the Coriolis force and momentum advection.
The MOM6 facility to parse input files for runtime parameters.
Pointers to arrays with accelerations, which can later be used for derived diagnostics,...
Control structure for mom_coriolisadv.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
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.
Controls where open boundary conditions are applied.
Handy functions for manipulating strings.
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.