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