12 use mom_domains, only : agrid, to_south, to_west, to_all
14 use mom_domains, only : group_pass_type, start_group_pass, complete_group_pass
21 use mom_time_manager, only : time_type, time_type_to_real,
operator(+),
operator(/),
operator(-)
29 implicit none ;
private 31 #include <MOM_memory.h> 33 public propagate_int_tide
34 public internal_tides_init, internal_tides_end
35 public get_lowmode_loss
39 logical :: do_int_tides
42 integer :: nangle = 24
43 integer :: energized_angle = -1
53 real,
allocatable,
dimension(:,:) :: refl_angle
56 real :: nullangle = -999.9
57 real,
allocatable,
dimension(:,:) :: refl_pref
60 logical,
allocatable,
dimension(:,:) :: refl_pref_logical
63 logical,
allocatable,
dimension(:,:) :: refl_dbl
67 real,
allocatable,
dimension(:,:,:,:) :: cp
69 real,
allocatable,
dimension(:,:,:,:,:) :: tke_leak_loss
71 real,
allocatable,
dimension(:,:,:,:,:) :: tke_quad_loss
73 real,
allocatable,
dimension(:,:,:,:,:) :: tke_froude_loss
75 real,
allocatable,
dimension(:,:) :: tke_itidal_loss_fixed
79 real,
allocatable,
dimension(:,:,:,:,:) :: tke_itidal_loss
81 real,
allocatable,
dimension(:,:) :: tot_leak_loss
83 real,
allocatable,
dimension(:,:) :: tot_quad_loss
85 real,
allocatable,
dimension(:,:) :: tot_itidal_loss
87 real,
allocatable,
dimension(:,:) :: tot_froude_loss
89 real,
allocatable,
dimension(:,:) :: tot_allprocesses_loss
93 type(time_type),
pointer :: time => null()
94 character(len=200) :: inputdir
98 logical :: apply_background_drag
100 logical :: apply_bottom_drag
102 logical :: apply_wave_drag
104 logical :: apply_froude_drag
106 real,
dimension(:,:,:,:,:),
pointer :: en => null()
109 real,
dimension(:,:,:),
pointer :: en_restart => null()
111 real,
allocatable,
dimension(:) :: frequency
120 integer :: id_tot_en = -1, id_tke_itidal_input = -1, id_itide_drag = -1
121 integer :: id_refl_pref = -1, id_refl_ang = -1, id_land_mask = -1
122 integer :: id_dx_cv = -1, id_dy_cu = -1
124 integer :: id_tot_leak_loss = -1, id_tot_quad_loss = -1, id_tot_itidal_loss = -1
125 integer :: id_tot_froude_loss = -1, id_tot_allprocesses_loss = -1
127 integer,
allocatable,
dimension(:,:) :: &
129 id_itidal_loss_mode, &
130 id_allprocesses_loss_mode, &
134 integer,
allocatable,
dimension(:,:) :: &
136 id_itidal_loss_ang_mode
144 integer :: ish, ieh, jsh, jeh
152 subroutine propagate_int_tide(h, tv, cn, TKE_itidal_input, vel_btTide, Nb, dt, &
157 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
161 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: TKE_itidal_input
163 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: vel_btTide
165 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: Nb
166 real,
intent(in) :: dt
170 real,
dimension(SZI_(G),SZJ_(G),CS%nMode), &
174 real,
dimension(SZI_(G),SZJ_(G),2) :: &
176 real,
dimension(SZI_(G),SZJ_(G),CS%nFreq,CS%nMode) :: &
180 real,
dimension(SZI_(G),SZJB_(G)) :: &
183 real,
dimension(SZI_(G),SZJ_(G)) :: &
185 tot_leak_loss, tot_quad_loss, tot_itidal_loss, tot_Froude_loss, tot_allprocesses_loss, &
188 itidal_loss_mode, allprocesses_loss_mode
190 real :: frac_per_sector, f2, Kmag2
198 real :: En_new, En_check
199 real :: En_initial, Delta_E_check
200 real :: TKE_Froude_loss_check, TKE_Froude_loss_tot
201 character(len=160) :: mesg
202 integer :: a, m, fr, i, j, is, ie, js, je, isd, ied, jsd, jed, nAngle, nzm
203 integer :: id_g, jd_g
204 type(group_pass_type),
save :: pass_test, pass_En
206 if (.not.
associated(cs))
return 207 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
208 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nangle = cs%NAngle
209 i_rho0 = 1.0 / gv%Rho0
210 cn_subro = 1e-100*us%m_s_to_L_T
220 if (cs%energized_angle <= 0)
then 221 frac_per_sector = 1.0 /
real(cs%nangle * cs%nmode * cs%nfreq)
222 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
223 f2 = 0.25*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
224 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2))
225 if (cs%frequency(fr)**2 > f2) &
226 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) + dt*frac_per_sector*(1.0-cs%q_itides) * &
227 tke_itidal_input(i,j)
228 enddo ;
enddo ;
enddo ;
enddo ;
enddo 229 elseif (cs%energized_angle <= cs%nAngle)
then 230 frac_per_sector = 1.0 /
real(cs%nmode * cs%nfreq)
231 a = cs%energized_angle
232 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do j=js,je ;
do i=is,ie
233 f2 = 0.25*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
234 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2))
235 if (cs%frequency(fr)**2 > f2) &
236 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) + dt*frac_per_sector*(1.0-cs%q_itides) * &
237 tke_itidal_input(i,j)
238 enddo ;
enddo ;
enddo ;
enddo 240 call mom_error(warning,
"Internal tide energy is being put into a angular "//&
241 "band that does not exist.")
245 do j=jsd,jed ;
do i=isd,ied ; test(i,j,1) = 1.0 ; test(i,j,2) = 0.0 ;
enddo ;
enddo 246 do m=1,cs%nMode ;
do fr=1,cs%nFreq
249 call create_group_pass(pass_test, test(:,:,1), test(:,:,2), g%domain, stagger=agrid)
250 call start_group_pass(pass_test, g%domain)
253 do m=1,cs%nMode ;
do fr=1,cs%nFreq
254 call refract(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), 0.5*dt, &
255 g, us, cs%nAngle, cs%use_PPMang)
259 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
260 do j=js,je ;
do i=is,ie
261 if (cs%En(i,j,a,fr,m)<0.0)
then 262 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
263 write(mesg,*)
'After first refraction: En<0.0 at ig=', id_g,
', jg=', jd_g, &
264 'En=',cs%En(i,j,a,fr,m)
265 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
266 cs%En(i,j,a,fr,m) = 0.0
270 enddo ;
enddo ;
enddo 272 call do_group_pass(pass_en, g%domain)
274 call complete_group_pass(pass_test, g%domain)
277 call correct_halo_rotation(cs%En, test, g, cs%nAngle)
280 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
281 call propagate(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), dt, &
282 g, us, cs, cs%NAngle)
286 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
287 do j=js,je ;
do i=is,ie
288 if (cs%En(i,j,a,fr,m)<0.0)
then 289 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
290 if (abs(cs%En(i,j,a,fr,m))>1.0)
then 291 write(mesg,*)
'After propagation: En<0.0 at ig=', id_g,
', jg=', jd_g, &
292 'En=', cs%En(i,j,a,fr,m)
293 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
296 cs%En(i,j,a,fr,m) = 0.0
299 enddo ;
enddo ;
enddo 302 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
303 call refract(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), 0.5*dt, &
304 g, us, cs%NAngle, cs%use_PPMang)
308 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
309 do j=js,je ;
do i=is,ie
310 if (cs%En(i,j,a,fr,m)<0.0)
then 311 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
312 write(mesg,*)
'After second refraction: En<0.0 at ig=', id_g,
', jg=', jd_g, &
313 'En=',cs%En(i,j,a,fr,m)
314 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
315 cs%En(i,j,a,fr,m) = 0.0
319 enddo ;
enddo ;
enddo 322 if (cs%apply_background_drag .or. cs%apply_bottom_drag &
323 .or. cs%apply_wave_drag .or. cs%apply_Froude_drag &
324 .or. (cs%id_tot_En > 0))
then 326 tot_en_mode(:,:,:,:) = 0.0
327 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
328 do j=jsd,jed ;
do i=isd,ied ;
do a=1,cs%nAngle
329 tot_en(i,j) = tot_en(i,j) + cs%En(i,j,a,fr,m)
330 tot_en_mode(i,j,fr,m) = tot_en_mode(i,j,fr,m) + cs%En(i,j,a,fr,m)
331 enddo ;
enddo ;
enddo 336 if (cs%apply_background_drag)
then 337 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=jsd,jed ;
do i=isd,ied
340 cs%TKE_leak_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * cs%decay_rate
341 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) / (1.0 + dt * cs%decay_rate)
342 enddo ;
enddo ;
enddo ;
enddo ;
enddo 345 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
346 do j=js,je ;
do i=is,ie
347 if (cs%En(i,j,a,fr,m)<0.0)
then 348 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
349 write(mesg,*)
'After leak loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
350 'En=',cs%En(i,j,a,fr,m)
351 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
352 cs%En(i,j,a,fr,m) = 0.0
356 enddo ;
enddo ;
enddo 359 if (cs%apply_bottom_drag)
then 360 do j=jsd,jed ;
do i=isd,ied
362 i_d_here = 1.0 / (max(g%bathyT(i,j), 1.0*us%m_to_Z))
363 drag_scale(i,j) = cs%cdrag * sqrt(max(0.0, us%L_to_Z**2*vel_bttide(i,j)**2 + &
364 tot_en(i,j) * i_rho0 * i_d_here)) * i_d_here
366 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=jsd,jed ;
do i=isd,ied
369 cs%TKE_quad_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * drag_scale(i,j)
370 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) / (1.0 + dt * drag_scale(i,j))
371 enddo ;
enddo ;
enddo ;
enddo ;
enddo 374 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
375 do j=js,je ;
do i=is,ie
376 if (cs%En(i,j,a,fr,m)<0.0)
then 377 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
378 write(mesg,*)
'After bottom loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
379 'En=',cs%En(i,j,a,fr,m)
380 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
381 cs%En(i,j,a,fr,m) = 0.0
386 enddo ;
enddo ;
enddo 391 if (cs%apply_wave_drag .or. cs%apply_Froude_drag)
then 392 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
394 call wave_structure(h, tv, g, gv, us, cn(:,:,m), m, cs%frequency(fr), &
395 cs%wave_structure_CSp, tot_en_mode(:,:,fr,m), full_halos=.true.)
397 do j=jsd,jed ;
do i=isd,ied
398 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
399 nzm = cs%wave_structure_CSp%num_intfaces(i,j)
400 ub(i,j,fr,m) = cs%wave_structure_CSp%Uavg_profile(i,j,nzm)
401 umax(i,j,fr,m) = maxval(cs%wave_structure_CSp%Uavg_profile(i,j,1:nzm))
406 if (cs%apply_wave_drag)
then 408 call itidal_lowmode_loss(g, us, cs, nb, ub, cs%En, cs%TKE_itidal_loss_fixed, &
409 cs%TKE_itidal_loss, dt, full_halos=.false.)
412 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
413 do j=js,je ;
do i=is,ie
414 if (cs%En(i,j,a,fr,m)<0.0)
then 415 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
416 write(mesg,*)
'After wave drag loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
417 'En=',cs%En(i,j,a,fr,m)
418 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
419 cs%En(i,j,a,fr,m) = 0.0
423 enddo ;
enddo ;
enddo 426 if (cs%apply_Froude_drag)
then 428 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
429 freq2 = cs%frequency(fr)**2
430 do j=jsd,jed ;
do i=isd,ied
431 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
433 f2 = 0.25*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
434 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2))
435 kmag2 = (freq2 - f2) / (cn(i,j,m)**2 + cn_subro**2)
437 if (kmag2 > 0.0)
then 438 c_phase = sqrt(freq2/kmag2)
439 nzm = cs%wave_structure_CSp%num_intfaces(i,j)
440 fr2_max = (umax(i,j,fr,m) / c_phase)**2
442 if (fr2_max > 1.0)
then 443 en_initial = sum(cs%En(i,j,:,fr,m))
445 loss_rate = (1.0 - fr2_max) / (fr2_max * dt)
448 cs%TKE_Froude_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * abs(loss_rate)
450 en_new = cs%En(i,j,a,fr,m)/fr2_max
451 en_check = cs%En(i,j,a,fr,m) - cs%TKE_Froude_loss(i,j,a,fr,m)*dt
453 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m)/fr2_max
455 if (abs(en_new - en_check) > 1e-10*us%kg_m3_to_R*us%m_to_Z**3*us%T_to_s**2)
then 456 call mom_error(warning,
"MOM_internal_tides: something is wrong with Fr-breaking.", &
458 write(mesg,*)
"En_new=", en_new ,
"En_check=", en_check
459 call mom_error(warning,
"MOM_internal_tides: "//trim(mesg), all_print=.true.)
463 delta_e_check = en_initial - sum(cs%En(i,j,:,fr,m))
464 tke_froude_loss_check = abs(delta_e_check)/dt
465 tke_froude_loss_tot = sum(cs%TKE_Froude_loss(i,j,:,fr,m))
466 if (abs(tke_froude_loss_check - tke_froude_loss_tot) > 1e-10)
then 467 call mom_error(warning,
"MOM_internal_tides: something is wrong with Fr energy update.", &
469 write(mesg,*)
"TKE_Froude_loss_check=", tke_froude_loss_check, &
470 "TKE_Froude_loss_tot=", tke_froude_loss_tot
471 call mom_error(warning,
"MOM_internal_tides: "//trim(mesg), all_print=.true.)
475 cs%cp(i,j,fr,m) = c_phase
480 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
481 do j=js,je ;
do i=is,ie
482 if (cs%En(i,j,a,fr,m)<0.0)
then 483 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
484 write(mesg,*)
'After Froude loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
485 'En=',cs%En(i,j,a,fr,m)
486 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
487 cs%En(i,j,a,fr,m) = 0.0
492 enddo ;
enddo ;
enddo 495 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
496 call sum_en(g,cs,cs%En(:,:,:,fr,m),
'prop_int_tide')
500 if (query_averaging_enabled(cs%diag))
then 502 if (cs%id_tot_En > 0)
call post_data(cs%id_tot_En, tot_en, cs%diag)
503 if (cs%id_itide_drag > 0)
call post_data(cs%id_itide_drag, drag_scale, cs%diag)
504 if (cs%id_TKE_itidal_input > 0)
call post_data(cs%id_TKE_itidal_input, &
505 tke_itidal_input, cs%diag)
508 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_En_mode(fr,m) > 0)
then 510 do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
511 tot_en(i,j) = tot_en(i,j) + cs%En(i,j,a,fr,m)
512 enddo ;
enddo ;
enddo 513 call post_data(cs%id_En_mode(fr,m), tot_en, cs%diag)
514 endif ;
enddo ;
enddo 517 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_En_ang_mode(fr,m) > 0)
then 518 call post_data(cs%id_En_ang_mode(fr,m), cs%En(:,:,:,fr,m) , cs%diag)
519 endif ;
enddo ;
enddo 522 tot_leak_loss(:,:) = 0.0
523 tot_quad_loss(:,:) = 0.0
524 tot_itidal_loss(:,:) = 0.0
525 tot_froude_loss(:,:) = 0.0
526 tot_allprocesses_loss(:,:) = 0.0
527 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
528 tot_leak_loss(i,j) = tot_leak_loss(i,j) + cs%TKE_leak_loss(i,j,a,fr,m)
529 tot_quad_loss(i,j) = tot_quad_loss(i,j) + cs%TKE_quad_loss(i,j,a,fr,m)
530 tot_itidal_loss(i,j) = tot_itidal_loss(i,j) + cs%TKE_itidal_loss(i,j,a,fr,m)
531 tot_froude_loss(i,j) = tot_froude_loss(i,j) + cs%TKE_Froude_loss(i,j,a,fr,m)
532 enddo ;
enddo ;
enddo ;
enddo ;
enddo 533 do j=js,je ;
do i=is,ie
534 tot_allprocesses_loss(i,j) = tot_leak_loss(i,j) + tot_quad_loss(i,j) + &
535 tot_itidal_loss(i,j) + tot_froude_loss(i,j)
537 cs%tot_leak_loss = tot_leak_loss
538 cs%tot_quad_loss = tot_quad_loss
539 cs%tot_itidal_loss = tot_itidal_loss
540 cs%tot_Froude_loss = tot_froude_loss
541 cs%tot_allprocesses_loss = tot_allprocesses_loss
542 if (cs%id_tot_leak_loss > 0)
then 543 call post_data(cs%id_tot_leak_loss, tot_leak_loss, cs%diag)
545 if (cs%id_tot_quad_loss > 0)
then 546 call post_data(cs%id_tot_quad_loss, tot_quad_loss, cs%diag)
548 if (cs%id_tot_itidal_loss > 0)
then 549 call post_data(cs%id_tot_itidal_loss, tot_itidal_loss, cs%diag)
551 if (cs%id_tot_Froude_loss > 0)
then 552 call post_data(cs%id_tot_Froude_loss, tot_froude_loss, cs%diag)
554 if (cs%id_tot_allprocesses_loss > 0)
then 555 call post_data(cs%id_tot_allprocesses_loss, tot_allprocesses_loss, cs%diag)
559 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
560 if (cs%id_itidal_loss_mode(fr,m) > 0 .or. cs%id_allprocesses_loss_mode(fr,m) > 0)
then 561 itidal_loss_mode(:,:) = 0.0
562 allprocesses_loss_mode(:,:) = 0.0
563 do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
564 itidal_loss_mode(i,j) = itidal_loss_mode(i,j) + cs%TKE_itidal_loss(i,j,a,fr,m)
565 allprocesses_loss_mode(i,j) = allprocesses_loss_mode(i,j) + &
566 cs%TKE_leak_loss(i,j,a,fr,m) + cs%TKE_quad_loss(i,j,a,fr,m) + &
567 cs%TKE_itidal_loss(i,j,a,fr,m) + cs%TKE_Froude_loss(i,j,a,fr,m)
568 enddo ;
enddo ;
enddo 569 call post_data(cs%id_itidal_loss_mode(fr,m), itidal_loss_mode, cs%diag)
570 call post_data(cs%id_allprocesses_loss_mode(fr,m), allprocesses_loss_mode, cs%diag)
571 endif ;
enddo ;
enddo 574 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_itidal_loss_ang_mode(fr,m) > 0)
then 575 call post_data(cs%id_itidal_loss_ang_mode(fr,m), cs%TKE_itidal_loss(:,:,:,fr,m) , cs%diag)
576 endif ;
enddo ;
enddo 579 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_Ub_mode(fr,m) > 0)
then 580 call post_data(cs%id_Ub_mode(fr,m), ub(:,:,fr,m), cs%diag)
581 endif ;
enddo ;
enddo 584 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_cp_mode(fr,m) > 0)
then 585 call post_data(cs%id_cp_mode(fr,m), cs%cp(:,:,fr,m), cs%diag)
586 endif ;
enddo ;
enddo 590 end subroutine propagate_int_tide
593 subroutine sum_en(G, CS, En, label)
597 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle), &
599 character(len=*),
intent(in) :: label
602 real :: tmpForSumming
611 tmpforsumming = global_area_mean(en(:,:,a),g)*g%areaT_global
612 en_sum = en_sum + tmpforsumming
631 end subroutine sum_en
635 subroutine itidal_lowmode_loss(G, US, CS, Nb, Ub, En, TKE_loss_fixed, TKE_loss, dt, full_halos)
640 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
642 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%nFreq,CS%nMode), &
645 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
646 intent(in) :: TKE_loss_fixed
648 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle,CS%nFreq,CS%nMode), &
650 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle,CS%nFreq,CS%nMode), &
651 intent(out) :: TKE_loss
653 real,
intent(in) :: dt
654 logical,
optional,
intent(in) :: full_halos
657 integer :: j,i,m,fr,a, is, ie, js, je
660 real :: TKE_sum_check
661 real :: frac_per_sector
667 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
669 q_itides = cs%q_itides
670 en_negl = 1e-30*us%kg_m3_to_R*us%m_to_Z**3*us%T_to_s**2
672 if (
present(full_halos))
then ;
if (full_halos)
then 673 is = g%isd ; ie = g%ied ; js = g%jsd ; je = g%jed
676 do j=js,je ;
do i=is,ie ;
do m=1,cs%nMode ;
do fr=1,cs%nFreq
681 en_tot = en_tot + en(i,j,a,fr,m)
685 tke_loss_tot = q_itides * tke_loss_fixed(i,j) * nb(i,j) * ub(i,j,fr,m)**2
689 if (en_tot > 0.0)
then 691 frac_per_sector = en(i,j,a,fr,m)/en_tot
692 tke_loss(i,j,a,fr,m) = frac_per_sector*tke_loss_tot
693 loss_rate = tke_loss(i,j,a,fr,m) / (en(i,j,a,fr,m) + en_negl)
694 en(i,j,a,fr,m) = en(i,j,a,fr,m) / (1.0 + dt*loss_rate)
698 tke_loss(i,j,:,fr,m) = 0.0
719 enddo ;
enddo ;
enddo ;
enddo 721 end subroutine itidal_lowmode_loss
727 subroutine get_lowmode_loss(i,j,G,CS,mechanism,TKE_loss_sum)
728 integer,
intent(in) :: i
729 integer,
intent(in) :: j
733 character(len=*),
intent(in) :: mechanism
734 real,
intent(out) :: TKE_loss_sum
737 if (mechanism ==
'LeakDrag') tke_loss_sum = cs%tot_leak_loss(i,j)
738 if (mechanism ==
'QuadDrag') tke_loss_sum = cs%tot_quad_loss(i,j)
739 if (mechanism ==
'WaveDrag') tke_loss_sum = cs%tot_itidal_loss(i,j)
740 if (mechanism ==
'Froude') tke_loss_sum = cs%tot_Froude_loss(i,j)
742 end subroutine get_lowmode_loss
745 subroutine refract(En, cn, freq, dt, G, US, NAngle, use_PPMang)
747 integer,
intent(in) :: NAngle
749 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
753 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
755 real,
intent(in) :: freq
756 real,
intent(in) :: dt
758 logical,
intent(in) :: use_PPMang
761 integer,
parameter :: stencil = 2
762 real,
dimension(SZI_(G),1-stencil:NAngle+stencil) :: &
764 real,
dimension(1-stencil:NAngle+stencil) :: &
766 real,
dimension(SZI_(G)) :: &
767 Dk_Dt_Kmag, Dl_Dt_Kmag
768 real,
dimension(SZI_(G),0:nAngle) :: &
770 real,
dimension(SZI_(G),SZJ_(G),1-stencil:NAngle+stencil) :: &
777 real :: Angle_size, dt_Angle_size, angle
778 real :: Ifreq, Kmag2, I_Kmag
780 integer :: is, ie, js, je, asd, aed, na
783 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; na =
size(en,3)
784 asd = 1-stencil ; aed = nangle+stencil
787 cn_subro = 1e-100*us%m_s_to_L_T
788 angle_size = (8.0*atan(1.0)) / (
real(nangle))
789 dt_angle_size = dt / angle_size
792 angle = (
real(A) - 0.5) * angle_size
793 cos_angle(a) = cos(angle) ; sin_angle(a) = sin(angle)
800 do a=1,na ;
do i=is,ie
801 en2d(i,a) = en(i,j,a)
803 do a=asd,0 ;
do i=is,ie
804 en2d(i,a) = en2d(i,a+nangle)
805 en2d(i,nangle+stencil+a) = en2d(i,stencil+a)
810 f2 = 0.25* ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
811 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
812 favg = 0.25*((g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j-1)) + &
813 (g%CoriolisBu(i,j-1) + g%CoriolisBu(i-1,j)))
814 df_dx = 0.5*((g%CoriolisBu(i,j) + g%CoriolisBu(i,j-1)) - &
815 (g%CoriolisBu(i-1,j) + g%CoriolisBu(i-1,j-1))) * g%IdxT(i,j)
816 dlncn_dx = 0.5*( g%IdxCu(i,j) * (cn(i+1,j) - cn(i,j)) / &
817 (0.5*(cn(i+1,j) + cn(i,j)) + cn_subro) + &
818 g%IdxCu(i-1,j) * (cn(i,j) - cn(i-1,j)) / &
819 (0.5*(cn(i,j) + cn(i-1,j)) + cn_subro) )
820 df_dy = 0.5*((g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j)) - &
821 (g%CoriolisBu(i,j-1) + g%CoriolisBu(i-1,j-1))) * g%IdyT(i,j)
822 dlncn_dy = 0.5*( g%IdyCv(i,j) * (cn(i,j+1) - cn(i,j)) / &
823 (0.5*(cn(i,j+1) + cn(i,j)) + cn_subro) + &
824 g%IdyCv(i,j-1) * (cn(i,j) - cn(i,j-1)) / &
825 (0.5*(cn(i,j) + cn(i,j-1)) + cn_subro) )
826 kmag2 = (freq**2 - f2) / (cn(i,j)**2 + cn_subro**2)
827 if (kmag2 > 0.0)
then 828 i_kmag = 1.0 / sqrt(kmag2)
829 dk_dt_kmag(i) = -ifreq * (favg*df_dx + (freq**2 - f2) * dlncn_dx) * i_kmag
830 dl_dt_kmag(i) = -ifreq * (favg*df_dy + (freq**2 - f2) * dlncn_dy) * i_kmag
838 do a=asd,aed ;
do i=is,ie
839 cfl_ang(i,j,a) = (cos_angle(a) * dl_dt_kmag(i) - sin_angle(a) * dk_dt_kmag(i)) * dt_angle_size
840 if (abs(cfl_ang(i,j,a)) > 1.0)
then 841 call mom_error(warning,
"refract: CFL exceeds 1.", .true.)
842 if (cfl_ang(i,j,a) > 0.0)
then ; cfl_ang(i,j,a) = 1.0 ;
else ; cfl_ang(i,j,a) = -1.0 ;
endif 847 if (.not.use_ppmang)
then 849 do a=0,na ;
do i=is,ie
850 if (cfl_ang(i,j,a) > 0.0)
then 851 flux_e(i,a) = cfl_ang(i,j,a) * en2d(i,a)
853 flux_e(i,a) = cfl_ang(i,j,a) * en2d(i,a+1)
859 call ppm_angular_advect(en2d(i,:),cfl_ang(i,j,:),flux_e(i,:),nangle,dt,stencil)
864 do a=1,na ;
do i=is,ie
868 en(i,j,a) = en2d(i,a) + (flux_e(i,a-1) - flux_e(i,a))
871 end subroutine refract
875 subroutine ppm_angular_advect(En2d, CFL_ang, Flux_En, NAngle, dt, halo_ang)
876 integer,
intent(in) :: NAngle
878 real,
intent(in) :: dt
879 integer,
intent(in) :: halo_ang
880 real,
dimension(1-halo_ang:NAngle+halo_ang), &
883 real,
dimension(1-halo_ang:NAngle+halo_ang), &
884 intent(in) :: CFL_ang
885 real,
dimension(0:NAngle),
intent(out) :: Flux_En
898 real,
parameter :: oneSixth = 1.0/6.0
902 angle_size = (8.0*atan(1.0)) / (
real(nangle))
903 i_angle_size = 1 / angle_size
907 u_ang = cfl_ang(a)*angle_size*i_dt
908 if (u_ang >= 0.0)
then 912 ep = en2d(a+1)*i_angle_size
913 ec = en2d(a) *i_angle_size
914 em = en2d(a-1)*i_angle_size
916 al = ( 5.*ec + ( 2.*em - ep ) ) * onesixth
917 al = max( min(ec,em), al) ; al = min( max(ec,em), al)
918 ar = ( 5.*ec + ( 2.*ep - em ) ) * onesixth
919 ar = max( min(ec,ep), ar) ; ar = min( max(ec,ep), ar)
921 if ((ep-ec)*(ec-em) <= 0.)
then 923 elseif ( 3.0*da*(2.*ec - (ar + al)) > (da*da) )
then 925 elseif ( 3.0*da*(2.*ec - (ar + al)) < - (da*da) )
then 928 curv_3 = (ar + al) - 2.0*ec
930 flux = u_ang*( ar + cfl_ang(a) * ( 0.5*(al - ar) + curv_3 * (cfl_ang(a) - 1.5) ) )
932 flux_en(a) = dt * flux
938 ep = en2d(a+2)*i_angle_size
939 ec = en2d(a+1)*i_angle_size
940 em = en2d(a) *i_angle_size
942 al = ( 5.*ec + ( 2.*em - ep ) ) * onesixth
943 al = max( min(ec,em), al) ; al = min( max(ec,em), al)
944 ar = ( 5.*ec + ( 2.*ep - em ) ) * onesixth
945 ar = max( min(ec,ep), ar) ; ar = min( max(ec,ep), ar)
947 if ((ep-ec)*(ec-em) <= 0.)
then 949 elseif ( 3.0*da*(2.*ec - (ar + al)) > (da*da) )
then 951 elseif ( 3.0*da*(2.*ec - (ar + al)) < - (da*da) )
then 954 curv_3 = (ar + al) - 2.0*ec
957 flux = u_ang*( al - cfl_ang(a) * ( 0.5*(ar - al) + curv_3 * (-cfl_ang(a) - 1.5) ) )
959 flux_en(a) = dt * flux
963 end subroutine ppm_angular_advect
966 subroutine propagate(En, cn, freq, dt, G, US, CS, NAngle)
968 integer,
intent(in) :: NAngle
970 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
974 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
976 real,
intent(in) :: freq
977 real,
intent(in) :: dt
982 real,
dimension(G%IsdB:G%IedB,G%JsdB:G%JedB) :: &
984 integer,
parameter :: stencil = 2
985 real,
dimension(SZIB_(G),SZJ_(G)) :: &
987 real,
dimension(SZI_(G),SZJB_(G)) :: &
989 real,
dimension(0:NAngle) :: &
991 real,
dimension(NAngle) :: &
992 Cgx_av, Cgy_av, dCgx, dCgy
994 real :: Angle_size, I_Angle_size, angle
998 integer :: is, ie, js, je, asd, aed, na
999 integer :: ish, ieh, jsh, jeh
1002 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; na =
size(en,3)
1003 asd = 1-stencil ; aed = nangle+stencil
1017 jsh = js-1 ; jeh = je+1 ; ish = is-1 ; ieh = ie+1
1019 angle_size = (8.0*atan(1.0)) /
real(nangle)
1020 i_angle_size = 1.0 / angle_size
1022 if (cs%corner_adv)
then 1028 do j=jsh-1,jeh ;
do i=ish-1,ieh
1029 f2 = g%CoriolisBu(i,j)**2
1030 speed(i,j) = 0.25*(cn(i,j) + cn(i+1,j) + cn(i+1,j+1) + cn(i,j+1)) * &
1031 sqrt(max(freq2 - f2, 0.0)) * ifreq
1035 lb%jsh = js ; lb%jeh = je ; lb%ish = is ; lb%ieh = ie
1036 call propagate_corner_spread(en(:,:,a), a, nangle, speed, dt, g, cs, lb)
1043 angle = (
real(A) - 0.5) * angle_size
1044 cos_angle(a) = cos(angle) ; sin_angle(a) = sin(angle)
1048 cgx_av(a) = (sin_angle(a) - sin_angle(a-1)) * i_angle_size
1049 cgy_av(a) = -(cos_angle(a) - cos_angle(a-1)) * i_angle_size
1050 dcgx(a) = sqrt(0.5 + 0.5*(sin_angle(a)*cos_angle(a) - &
1051 sin_angle(a-1)*cos_angle(a-1)) * i_angle_size - &
1053 dcgy(a) = sqrt(0.5 - 0.5*(sin_angle(a)*cos_angle(a) - &
1054 sin_angle(a-1)*cos_angle(a-1)) * i_angle_size - &
1058 do j=jsh,jeh ;
do i=ish-1,ieh
1059 f2 = 0.5 * (g%CoriolisBu(i,j)**2 + g%CoriolisBu(i,j-1)**2)
1060 speed_x(i,j) = 0.5*(cn(i,j) + cn(i+1,j)) * g%mask2dCu(i,j) * &
1061 sqrt(max(freq2 - f2, 0.0)) * ifreq
1063 do j=jsh-1,jeh ;
do i=ish,ieh
1064 f2 = 0.5 * (g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j)**2)
1065 speed_y(i,j) = 0.5*(cn(i,j) + cn(i,j+1)) * g%mask2dCv(i,j) * &
1066 sqrt(max(freq2 - f2, 0.0)) * ifreq
1070 lb%jsh = jsh ; lb%jeh = jeh ; lb%ish = ish ; lb%ieh = ieh
1071 call propagate_x(en, speed_x, cgx_av, dcgx, dt, g, us, cs%nAngle, cs, lb)
1081 lb%jsh = jsh ; lb%jeh = jeh ; lb%ish = ish ; lb%ieh = ieh
1082 call propagate_y(en, speed_y, cgy_av, dcgy, dt, g, us, cs%nAngle, cs, lb)
1088 end subroutine propagate
1093 subroutine propagate_corner_spread(En, energized_wedge, NAngle, speed, dt, G, CS, LB)
1095 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
1098 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed), &
1101 integer,
intent(in) :: energized_wedge
1102 integer,
intent(in) :: NAngle
1104 real,
intent(in) :: dt
1109 integer :: i, j, k, ish, ieh, jsh, jeh, m
1110 real :: TwoPi, Angle_size
1111 real :: energized_angle
1116 real :: I_Nsubwedges
1117 real :: cos_thetaDT, sin_thetaDT
1118 real :: xNE,xNW,xSW,xSE,yNE,yNW,ySW,ySE
1119 real :: CFL_xNE,CFL_xNW,CFL_xSW,CFL_xSE,CFL_yNE,CFL_yNW,CFL_ySW,CFL_ySE,CFL_max
1120 real :: xN,xS,xE,xW,yN,yS,yE,yW
1123 real :: slopeN,slopeW,slopeS,slopeE, bN,bW,bS,bE
1124 real :: aNE,aN,aNW,aW,aSW,aS,aSE,aE,aC
1127 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: x,y
1128 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: Idx,Idy
1129 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: dx,dy
1130 real,
dimension(2) :: E_new
1133 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1134 twopi = (8.0*atan(1.0))
1135 nsubrays =
real(size(e_new))
1136 i_nsubwedges = 1./(nsubrays - 1)
1138 angle_size = twopi /
real(nangle)
1139 energized_angle = angle_size *
real(energized_wedge - 1) 1142 do j=jsh-1,jeh ;
do i=ish-1,ieh
1145 x(i,j) = g%US%m_to_L*g%geoLonBu(i,j)
1146 y(i,j) = g%US%m_to_L*g%geoLatBu(i,j)
1147 idx(i,j) = g%IdxBu(i,j) ; dx(i,j) = g%dxBu(i,j)
1148 idy(i,j) = g%IdyBu(i,j) ; dy(i,j) = g%dyBu(i,j)
1151 do j=jsh,jeh ;
do i=ish,ieh
1152 do m=1,int(nsubrays)
1153 theta = energized_angle - 0.5*angle_size +
real(m - 1)*Angle_size*I_Nsubwedges
1154 if (theta < 0.0)
then 1155 theta = theta + twopi
1156 elseif (theta > twopi)
then 1157 theta = theta - twopi
1159 cos_thetadt = cos(theta)*dt
1160 sin_thetadt = sin(theta)*dt
1163 xg = x(i,j); yg = y(i,j)
1164 xne = xg - speed(i,j)*cos_thetadt
1165 yne = yg - speed(i,j)*sin_thetadt
1166 cfl_xne = (xg-xne)*idx(i,j)
1167 cfl_yne = (yg-yne)*idy(i,j)
1169 xg = x(i-1,j); yg = y(i-1,j)
1170 xnw = xg - speed(i-1,j)*cos_thetadt
1171 ynw = yg - speed(i-1,j)*sin_thetadt
1172 cfl_xnw = (xg-xnw)*idx(i-1,j)
1173 cfl_ynw = (yg-ynw)*idy(i-1,j)
1175 xg = x(i-1,j-1); yg = y(i-1,j-1)
1176 xsw = xg - speed(i-1,j-1)*cos_thetadt
1177 ysw = yg - speed(i-1,j-1)*sin_thetadt
1178 cfl_xsw = (xg-xsw)*idx(i-1,j-1)
1179 cfl_ysw = (yg-ysw)*idy(i-1,j-1)
1181 xg = x(i,j-1); yg = y(i,j-1)
1182 xse = xg - speed(i,j-1)*cos_thetadt
1183 yse = yg - speed(i,j-1)*sin_thetadt
1184 cfl_xse = (xg-xse)*idx(i,j-1)
1185 cfl_yse = (yg-yse)*idy(i,j-1)
1187 cfl_max = max(abs(cfl_xne),abs(cfl_xnw),abs(cfl_xsw), &
1188 abs(cfl_xse),abs(cfl_yne),abs(cfl_ynw), &
1189 abs(cfl_ysw),abs(cfl_yse))
1190 if (cfl_max > 1.0)
then 1191 call mom_error(warning,
"propagate_corner_spread: CFL exceeds 1.", .true.)
1195 if (0.0 <= theta .and. theta < 0.25*twopi)
then 1198 elseif (0.25*twopi <= theta .and. theta < 0.5*twopi)
then 1201 elseif (0.5*twopi <= theta .and. theta < 0.75*twopi)
then 1204 elseif (0.75*twopi <= theta .and. theta <= 1.00*twopi)
then 1212 slopen = (yne - ynw)/(xne - xnw)
1213 bn = -slopen*xne + yne
1216 if (xnw == xsw)
then 1219 slopew = (ynw - ysw)/(xnw - xsw)
1220 bw = -slopew*xnw + ynw
1221 xw = (yw - bw)/slopew
1224 slopes = (ysw - yse)/(xsw - xse)
1225 bs = -slopes*xsw + ysw
1228 if (xne == xse)
then 1231 slopee = (yse - yne)/(xse - xne)
1232 be = -slopee*xse + yse
1233 xe = (ye - be)/slopee
1237 ane = 0.0; an = 0.0; anw = 0.0;
1238 aw = 0.0; asw = 0.0; as = 0.0;
1239 ase = 0.0; ae = 0.0; ac = 0.0;
1240 if (0.0 <= theta .and. theta < 0.25*twopi)
then 1241 xcrn = x(i-1,j-1); ycrn = y(i-1,j-1)
1243 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1244 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1245 a3 = (yw - ynw)*(0.5*(xw + xnw))
1246 a4 = (ynw - yn)*(0.5*(xnw + xn))
1247 aw = a1 + a2 + a3 + a4
1249 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1250 a2 = (ys - ysw)*(0.5*(xs + xsw))
1251 a3 = (ysw - yw)*(0.5*(xsw + xw))
1252 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1253 asw = a1 + a2 + a3 + a4
1255 a1 = (ye - yse)*(0.5*(xe + xse))
1256 a2 = (yse - ys)*(0.5*(xse + xs))
1257 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1258 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1259 as = a1 + a2 + a3 + a4
1261 a1 = (yne - ye)*(0.5*(xne + xe))
1262 a2 = (ye - ycrn)*(0.5*(xe + xcrn))
1263 a3 = (ycrn - yn)*(0.5*(xcrn + xn))
1264 a4 = (yn - yne)*(0.5*(xn + xne))
1265 ac = a1 + a2 + a3 + a4
1266 elseif (0.25*twopi <= theta .and. theta < 0.5*twopi)
then 1267 xcrn = x(i,j-1); ycrn = y(i,j-1)
1269 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1270 a2 = (ys - ysw)*(0.5*(xs + xsw))
1271 a3 = (ysw - yw)*(0.5*(xsw + xw))
1272 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1273 as = a1 + a2 + a3 + a4
1275 a1 = (ye - yse)*(0.5*(xe + xse))
1276 a2 = (yse - ys)*(0.5*(xse + xs))
1277 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1278 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1279 ase = a1 + a2 + a3 + a4
1281 a1 = (yne - ye)*(0.5*(xne + xe))
1282 a2 = (ye - ycrn)*(0.5*(xe + xcrn))
1283 a3 = (ycrn - yn)*(0.5*(xcrn + xn))
1284 a4 = (yn - yne)*(0.5*(xn + xne))
1285 ae = a1 + a2 + a3 + a4
1287 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1288 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1289 a3 = (yw - ynw)*(0.5*(xw + xnw))
1290 a4 = (ynw - yn)*(0.5*(xnw + xn))
1291 ac = a1 + a2 + a3 + a4
1292 elseif (0.5*twopi <= theta .and. theta < 0.75*twopi)
then 1293 xcrn = x(i,j); ycrn = y(i,j)
1295 a1 = (ye - yse)*(0.5*(xe + xse))
1296 a2 = (yse - ys)*(0.5*(xse + xs))
1297 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1298 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1299 ae = a1 + a2 + a3 + a4
1301 a1 = (yne - ye)*(0.5*(xne + xe))
1302 a2 = (ye - ycrn)*(0.5*(xe + xcrn))
1303 a3 = (ycrn - yn)*(0.5*(xcrn + xn))
1304 a4 = (yn - yne)*(0.5*(xn + xne))
1305 ane = a1 + a2 + a3 + a4
1307 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1308 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1309 a3 = (yw - ynw)*(0.5*(xw + xnw))
1310 a4 = (ynw - yn)*(0.5*(xnw + xn))
1311 an = a1 + a2 + a3 + a4
1313 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1314 a2 = (ys - ysw)*(0.5*(xs + xsw))
1315 a3 = (ysw - yw)*(0.5*(xsw + xw))
1316 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1317 ac = a1 + a2 + a3 + a4
1318 elseif (0.75*twopi <= theta .and. theta <= 1.00*twopi)
then 1319 xcrn = x(i-1,j); ycrn = y(i-1,j)
1321 a1 = (yne - ye)*(0.5*(xne + xe))
1322 a2 = (ye - ycrn)*(0.5*(xe + xcrn))
1323 a3 = (ycrn - yn)*(0.5*(xcrn + xn))
1324 a4 = (yn - yne)*(0.5*(xn + xne))
1325 an = a1 + a2 + a3 + a4
1327 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1328 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1329 a3 = (yw - ynw)*(0.5*(xw + xnw))
1330 a4 = (ynw - yn)*(0.5*(xnw + xn))
1331 anw = a1 + a2 + a3 + a4
1333 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1334 a2 = (ys - ysw)*(0.5*(xs + xsw))
1335 a3 = (ysw - yw)*(0.5*(xsw + xw))
1336 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1337 aw = a1 + a2 + a3 + a4
1339 a1 = (ye - yse)*(0.5*(xe + xse))
1340 a2 = (yse - ys)*(0.5*(xse + xs))
1341 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1342 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1343 ac = a1 + a2 + a3 + a4
1347 a_total = ane + an + anw + aw + asw + as + ase + ae + ac
1348 e_new(m) = (ane*en(i+1,j+1) + an*en(i,j+1) + anw*en(i-1,j+1) + &
1349 aw*en(i-1,j) + asw*en(i-1,j-1) + as*en(i,j-1) + &
1350 ase*en(i+1,j-1) + ae*en(i+1,j) + ac*en(i,j)) / (dx(i,j)*dy(i,j))
1353 en(i,j) = sum(e_new)/nsubrays
1355 end subroutine propagate_corner_spread
1358 subroutine propagate_x(En, speed_x, Cgx_av, dCgx, dt, G, US, Nangle, CS, LB)
1360 integer,
intent(in) :: NAngle
1362 real,
dimension(G%isd:G%ied,G%jsd:G%jed,Nangle), &
1365 real,
dimension(G%IsdB:G%IedB,G%jsd:G%jed), &
1366 intent(in) :: speed_x
1368 real,
dimension(Nangle),
intent(in) :: Cgx_av
1369 real,
dimension(Nangle),
intent(in) :: dCgx
1371 real,
intent(in) :: dt
1377 real,
dimension(SZI_(G),SZJ_(G)) :: &
1379 real,
dimension(SZIB_(G),SZJ_(G)) :: &
1381 real,
dimension(SZIB_(G)) :: &
1382 cg_p, cg_m, flux1, flux2
1384 real,
dimension(SZI_(G),SZJB_(G),Nangle) :: &
1386 integer :: i, j, k, ish, ieh, jsh, jeh, a
1388 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1391 if (cs%upwind_1st)
then 1392 do j=jsh,jeh ;
do i=ish-1,ieh+1
1393 enl(i,j) = en(i,j,a) ; enr(i,j) = en(i,j,a)
1396 call ppm_reconstruction_x(en(:,:,a), enl, enr, g, lb, simple_2nd=cs%simple_2nd)
1402 cg_p(i) = speed_x(i,j) * (cgx_av(a))
1404 call zonal_flux_en(cg_p, en(:,j,a), enl(:,j), enr(:,j), flux1, &
1405 dt, g, us, j, ish, ieh, cs%vol_CFL)
1406 do i=ish-1,ieh ; flux_x(i,j) = flux1(i);
enddo 1409 do j=jsh,jeh ;
do i=ish,ieh
1410 fdt_m(i,j,a) = dt*flux_x(i-1,j)
1411 fdt_p(i,j,a) = -dt*flux_x(i,j)
1418 call reflect(fdt_m, nangle, cs, g, lb)
1419 call teleport(fdt_m, nangle, cs, g, lb)
1420 call reflect(fdt_p, nangle, cs, g, lb)
1421 call teleport(fdt_p, nangle, cs, g, lb)
1424 do a=1,nangle ;
do j=jsh,jeh ;
do i=ish,ieh
1427 en(i,j,a) = en(i,j,a) + g%IareaT(i,j)*(fdt_m(i,j,a) + fdt_p(i,j,a))
1428 enddo ;
enddo ;
enddo 1430 end subroutine propagate_x
1433 subroutine propagate_y(En, speed_y, Cgy_av, dCgy, dt, G, US, Nangle, CS, LB)
1435 integer,
intent(in) :: NAngle
1437 real,
dimension(G%isd:G%ied,G%jsd:G%jed,Nangle), &
1440 real,
dimension(G%isd:G%ied,G%JsdB:G%JedB), &
1441 intent(in) :: speed_y
1443 real,
dimension(Nangle),
intent(in) :: Cgy_av
1444 real,
dimension(Nangle),
intent(in) :: dCgy
1446 real,
intent(in) :: dt
1452 real,
dimension(SZI_(G),SZJ_(G)) :: &
1454 real,
dimension(SZI_(G),SZJB_(G)) :: &
1456 real,
dimension(SZI_(G)) :: &
1457 cg_p, cg_m, flux1, flux2
1459 real,
dimension(SZI_(G),SZJB_(G),Nangle) :: &
1461 character(len=160) :: mesg
1462 integer :: i, j, k, ish, ieh, jsh, jeh, a
1464 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1467 if (cs%upwind_1st)
then 1468 do j=jsh-1,jeh+1 ;
do i=ish,ieh
1469 enl(i,j) = en(i,j,a) ; enr(i,j) = en(i,j,a)
1472 call ppm_reconstruction_y(en(:,:,a), enl, enr, g, lb, simple_2nd=cs%simple_2nd)
1478 cg_p(i) = speed_y(i,j) * (cgy_av(a))
1480 call merid_flux_en(cg_p, en(:,:,a), enl(:,:), enr(:,:), flux1, &
1481 dt, g, us, j, ish, ieh, cs%vol_CFL)
1482 do i=ish,ieh ; flux_y(i,j) = flux1(i);
enddo 1485 do j=jsh,jeh ;
do i=ish,ieh
1486 fdt_m(i,j,a) = dt*flux_y(i,j-1)
1487 fdt_p(i,j,a) = -dt*flux_y(i,j)
1500 call reflect(fdt_m, nangle, cs, g, lb)
1501 call teleport(fdt_m, nangle, cs, g, lb)
1502 call reflect(fdt_p, nangle, cs, g, lb)
1503 call teleport(fdt_p, nangle, cs, g, lb)
1506 do a=1,nangle ;
do j=jsh,jeh ;
do i=ish,ieh
1509 en(i,j,a) = en(i,j,a) + g%IareaT(i,j)*(fdt_m(i,j,a) + fdt_p(i,j,a))
1510 enddo ;
enddo ;
enddo 1512 end subroutine propagate_y
1515 subroutine zonal_flux_en(u, h, hL, hR, uh, dt, G, US, j, ish, ieh, vol_CFL)
1517 real,
dimension(SZIB_(G)),
intent(in) :: u
1518 real,
dimension(SZI_(G)),
intent(in) :: h
1520 real,
dimension(SZI_(G)),
intent(in) :: hL
1522 real,
dimension(SZI_(G)),
intent(in) :: hR
1524 real,
dimension(SZIB_(G)),
intent(inout) :: uh
1525 real,
intent(in) :: dt
1527 integer,
intent(in) :: j
1528 integer,
intent(in) :: ish
1529 integer,
intent(in) :: ieh
1530 logical,
intent(in) :: vol_CFL
1539 if (u(i) > 0.0)
then 1540 if (vol_cfl)
then ; cfl = (u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
1541 else ; cfl = u(i) * dt * g%IdxT(i,j) ;
endif 1542 curv_3 = (hl(i) + hr(i)) - 2.0*h(i)
1543 uh(i) = g%dy_Cu(i,j) * u(i) * &
1544 (hr(i) + cfl * (0.5*(hl(i) - hr(i)) + curv_3*(cfl - 1.5)))
1545 elseif (u(i) < 0.0)
then 1546 if (vol_cfl)
then ; cfl = (-u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
1547 else ; cfl = -u(i) * dt * g%IdxT(i+1,j) ;
endif 1548 curv_3 = (hl(i+1) + hr(i+1)) - 2.0*h(i+1)
1549 uh(i) = g%dy_Cu(i,j) * u(i) * &
1550 (hl(i+1) + cfl * (0.5*(hr(i+1)-hl(i+1)) + curv_3*(cfl - 1.5)))
1555 end subroutine zonal_flux_en
1558 subroutine merid_flux_en(v, h, hL, hR, vh, dt, G, US, J, ish, ieh, vol_CFL)
1560 real,
dimension(SZI_(G)),
intent(in) :: v
1561 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h
1563 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: hL
1565 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: hR
1567 real,
dimension(SZI_(G)),
intent(inout) :: vh
1568 real,
intent(in) :: dt
1570 integer,
intent(in) :: J
1571 integer,
intent(in) :: ish
1572 integer,
intent(in) :: ieh
1573 logical,
intent(in) :: vol_CFL
1582 if (v(i) > 0.0)
then 1583 if (vol_cfl)
then ; cfl = (v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1584 else ; cfl = v(i) * dt * g%IdyT(i,j) ;
endif 1585 curv_3 = hl(i,j) + hr(i,j) - 2.0*h(i,j)
1586 vh(i) = g%dx_Cv(i,j) * v(i) * ( hr(i,j) + cfl * &
1587 (0.5*(hl(i,j) - hr(i,j)) + curv_3*(cfl - 1.5)) )
1588 elseif (v(i) < 0.0)
then 1589 if (vol_cfl)
then ; cfl = (-v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1590 else ; cfl = -v(i) * dt * g%IdyT(i,j+1) ;
endif 1591 curv_3 = hl(i,j+1) + hr(i,j+1) - 2.0*h(i,j+1)
1592 vh(i) = g%dx_Cv(i,j) * v(i) * ( hl(i,j+1) + cfl * &
1593 (0.5*(hr(i,j+1)-hl(i,j+1)) + curv_3*(cfl - 1.5)) )
1598 end subroutine merid_flux_en
1601 subroutine reflect(En, NAngle, CS, G, LB)
1603 integer,
intent(in) :: NAngle
1605 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
1613 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: angle_c
1615 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: part_refl
1618 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: ridge
1624 real,
dimension(1:NAngle) :: angle_i
1626 real,
dimension(1:Nangle) :: En_reflected
1627 integer :: i, j, a, a_r, na
1630 integer :: isc, iec, jsc, jec
1632 integer :: ish, ieh, jsh, jeh
1636 isc = g%isc ; iec = g%iec ; jsc = g%jsc ; jec = g%jec
1637 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1639 twopi = 8.0*atan(1.0)
1640 angle_size = twopi / (
real(nangle))
1645 angle_i(a) = angle_size *
real(a - 1) 1648 angle_c = cs%refl_angle
1649 part_refl = cs%refl_pref
1651 en_reflected(:) = 0.0
1653 do j=jsh,jeh ;
do i=ish,ieh
1656 if (angle_c(i,j) /= cs%nullangle)
then 1657 do a=1,nangle ;
if (en(i,j,a) > 0.0)
then 1658 if (sin(angle_i(a) - angle_c(i,j)) >= 0.0)
then 1660 angle_wall = angle_c(i,j)
1661 elseif (ridge(i,j))
then 1663 angle_wall = angle_c(i,j) + 0.5*twopi
1664 if (angle_wall > twopi)
then 1665 angle_wall = angle_wall - twopi*floor(abs(angle_wall)/twopi)
1666 elseif (angle_wall < 0.0)
then 1667 angle_wall = angle_wall + twopi*ceiling(abs(angle_wall)/twopi)
1671 angle_wall = angle_c(i,j)
1675 if (sin(angle_i(a) - angle_wall) >= 0.0)
then 1676 angle_r = 2.0*angle_wall - angle_i(a)
1677 if (angle_r > twopi)
then 1678 angle_r = angle_r - twopi*floor(abs(angle_r)/twopi)
1679 elseif (angle_r < 0.0)
then 1680 angle_r = angle_r + twopi*ceiling(abs(angle_r)/twopi)
1682 a_r = nint(angle_r/angle_size) + 1
1683 do while (a_r > nangle) ; a_r = a_r - nangle ;
enddo 1685 en_reflected(a_r) = part_refl(i,j)*en(i,j,a)
1686 en(i,j,a) = (1.0-part_refl(i,j))*en(i,j,a)
1691 en(i,j,a) = en(i,j,a) + en_reflected(a)
1692 en_reflected(a) = 0.0
1705 end subroutine reflect
1709 subroutine teleport(En, NAngle, CS, G, LB)
1711 integer,
intent(in) :: NAngle
1713 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
1721 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: angle_c
1723 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: part_refl
1726 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: pref_cell
1728 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: ridge
1732 real,
dimension(1:NAngle) :: angle_i
1733 real,
dimension(1:NAngle) :: cos_angle, sin_angle
1735 character(len=160) :: mesg
1741 integer :: ish, ieh, jsh, jeh
1743 integer :: id_g, jd_g
1745 real :: cos_normal, sin_normal, angle_wall
1750 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1752 twopi = 8.0*atan(1.0)
1753 angle_size = twopi / (
real(nangle))
1758 angle_i(a) = angle_size *
real(a - 1) 1759 cos_angle(a) = cos(angle_i(a)) ; sin_angle(a) = sin(angle_i(a))
1762 angle_c = cs%refl_angle
1763 part_refl = cs%refl_pref
1764 pref_cell = cs%refl_pref_logical
1769 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
1770 if (pref_cell(i,j))
then 1772 if (en(i,j,a) > 0)
then 1774 if (sin(angle_i(a) - angle_c(i,j)) >= 0.0)
then 1775 angle_wall = angle_c(i,j)
1777 elseif (ridge(i,j))
then 1778 angle_wall = angle_c(i,j) + 0.5*twopi
1781 angle_wall = angle_c(i,j)
1784 if (sin(angle_i(a) - angle_wall) >= 0.0)
then 1786 cos_normal = cos(angle_wall + 0.25*twopi)
1787 sin_normal = sin(angle_wall + 0.25*twopi)
1789 ios = int(sign(1.,cos_normal))
1791 jos = int(sign(1.,sin_normal))
1793 if (.not. pref_cell(i+ios,j+jos))
then 1794 en(i,j,a) = en(i,j,a) - en_tele
1795 en(i+ios,j+jos,a) = en(i+ios,j+jos,a) + en_tele
1797 write(mesg,*)
'idg=',id_g,
'jd_g=',jd_g,
'a=',a
1798 call mom_error(fatal,
"teleport: no receptive ocean cell at "//trim(mesg), .true.)
1807 end subroutine teleport
1811 subroutine correct_halo_rotation(En, test, G, NAngle)
1813 real,
dimension(:,:,:,:,:),
intent(inout) :: En
1816 real,
dimension(SZI_(G),SZJ_(G),2), &
1820 integer,
intent(in) :: NAngle
1823 real,
dimension(G%isd:G%ied,NAngle) :: En2d
1824 integer,
dimension(G%isd:G%ied) :: a_shift
1825 integer :: i_first, i_last, a_new
1826 integer :: a, i, j, isd, ied, jsd, jed, m, fr
1827 character(len=160) :: mesg
1828 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1831 i_first = ied+1 ; i_last = isd-1
1834 if (test(i,j,1) /= 1.0)
then 1835 if (i<i_first) i_first = i
1836 if (i>i_last) i_last = i
1838 if (test(i,j,1) == -1.0)
then ; a_shift(i) = nangle/2
1839 elseif (test(i,j,2) == 1.0)
then ; a_shift(i) = -nangle/4
1840 elseif (test(i,j,2) == -1.0)
then ; a_shift(i) = nangle/4
1842 write(mesg,
'("Unrecognized rotation test vector ",2ES9.2," at ",F7.2," E, ",& 1843 &F7.2," N; i,j=",2i4)') &
1844 test(i,j,1), test(i,j,2), g%GeoLonT(i,j), g%GeoLatT(i,j), i, j
1845 call mom_error(fatal, mesg)
1850 if (i_first <= i_last)
then 1852 do m=1,
size(en,5) ;
do fr=1,
size(en,4)
1853 do a=1,nangle ;
do i=i_first,i_last ;
if (a_shift(i) /= 0)
then 1854 a_new = a + a_shift(i)
1855 if (a_new < 1) a_new = a_new + nangle
1856 if (a_new > nangle) a_new = a_new - nangle
1857 en2d(i,a_new) = en(i,j,a,fr,m)
1858 endif ;
enddo ;
enddo 1859 do a=1,nangle ;
do i=i_first,i_last ;
if (a_shift(i) /= 0)
then 1860 en(i,j,a,fr,m) = en2d(i,a)
1861 endif ;
enddo ;
enddo 1865 end subroutine correct_halo_rotation
1868 subroutine ppm_reconstruction_x(h_in, h_l, h_r, G, LB, simple_2nd)
1870 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1871 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_l
1872 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_r
1874 logical,
optional,
intent(in) :: simple_2nd
1878 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1879 real,
parameter :: oneSixth = 1./6.
1880 real :: h_ip1, h_im1
1882 logical :: use_CW84, use_2nd
1883 character(len=256) :: mesg
1884 integer :: i, j, isl, iel, jsl, jel, stencil
1886 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1887 isl = lb%ish-1 ; iel = lb%ieh+1 ; jsl = lb%jsh ; jel = lb%jeh
1890 stencil = 2 ;
if (use_2nd) stencil = 1
1892 if ((isl-stencil < g%isd) .or. (iel+stencil > g%ied))
then 1893 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_x called with a ", & 1894 & "x-halo that needs to be increased by ",i2,".")') &
1895 stencil + max(g%isd-isl,iel-g%ied)
1896 call mom_error(fatal,mesg)
1898 if ((jsl < g%jsd) .or. (jel > g%jed))
then 1899 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_x called with a ", & 1900 & "y-halo that needs to be increased by ",i2,".")') &
1901 max(g%jsd-jsl,jel-g%jed)
1902 call mom_error(fatal,mesg)
1906 do j=jsl,jel ;
do i=isl,iel
1907 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1908 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1909 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) )
1910 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) )
1913 do j=jsl,jel ;
do i=isl-1,iel+1
1914 if ((g%mask2dT(i-1,j) * g%mask2dT(i,j) * g%mask2dT(i+1,j)) == 0.0)
then 1918 slp(i,j) = 0.5 * (h_in(i+1,j) - h_in(i-1,j))
1920 dmx = max(h_in(i+1,j), h_in(i-1,j), h_in(i,j)) - h_in(i,j)
1921 dmn = h_in(i,j) - min(h_in(i+1,j), h_in(i-1,j), h_in(i,j))
1922 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
1927 do j=jsl,jel ;
do i=isl,iel
1932 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1933 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1935 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) ) + onesixth*( slp(i-1,j) - slp(i,j) )
1936 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i+1,j) )
1940 call ppm_limit_pos(h_in, h_l, h_r, 0.0, g, isl, iel, jsl, jel)
1941 end subroutine ppm_reconstruction_x
1944 subroutine ppm_reconstruction_y(h_in, h_l, h_r, G, LB, simple_2nd)
1946 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1947 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_l
1948 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_r
1950 logical,
optional,
intent(in) :: simple_2nd
1954 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1955 real,
parameter :: oneSixth = 1./6.
1956 real :: h_jp1, h_jm1
1959 character(len=256) :: mesg
1960 integer :: i, j, isl, iel, jsl, jel, stencil
1962 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1963 isl = lb%ish ; iel = lb%ieh ; jsl = lb%jsh-1 ; jel = lb%jeh+1
1966 stencil = 2 ;
if (use_2nd) stencil = 1
1968 if ((isl < g%isd) .or. (iel > g%ied))
then 1969 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_y called with a ", & 1970 & "x-halo that needs to be increased by ",i2,".")') &
1971 max(g%isd-isl,iel-g%ied)
1972 call mom_error(fatal,mesg)
1974 if ((jsl-stencil < g%jsd) .or. (jel+stencil > g%jed))
then 1975 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_y called with a ", & 1976 & "y-halo that needs to be increased by ",i2,".")') &
1977 stencil + max(g%jsd-jsl,jel-g%jed)
1978 call mom_error(fatal,mesg)
1982 do j=jsl,jel ;
do i=isl,iel
1983 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
1984 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
1985 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) )
1986 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) )
1989 do j=jsl-1,jel+1 ;
do i=isl,iel
1990 if ((g%mask2dT(i,j-1) * g%mask2dT(i,j) * g%mask2dT(i,j+1)) == 0.0)
then 1994 slp(i,j) = 0.5 * (h_in(i,j+1) - h_in(i,j-1))
1996 dmx = max(h_in(i,j+1), h_in(i,j-1), h_in(i,j)) - h_in(i,j)
1997 dmn = h_in(i,j) - min(h_in(i,j+1), h_in(i,j-1), h_in(i,j))
1998 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
2003 do j=jsl,jel ;
do i=isl,iel
2006 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2007 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2009 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) ) + onesixth*( slp(i,j-1) - slp(i,j) )
2010 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i,j+1) )
2014 call ppm_limit_pos(h_in, h_l, h_r, 0.0, g, isl, iel, jsl, jel)
2015 end subroutine ppm_reconstruction_y
2021 subroutine ppm_limit_pos(h_in, h_L, h_R, h_min, G, iis, iie, jis, jie)
2023 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2024 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2025 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2026 real,
intent(in) :: h_min
2028 integer,
intent(in) :: iis
2029 integer,
intent(in) :: iie
2030 integer,
intent(in) :: jis
2031 integer,
intent(in) :: jie
2033 real :: curv, dh, scale
2034 character(len=256) :: mesg
2037 do j=jis,jie ;
do i=iis,iie
2040 curv = 3.0*(h_l(i,j) + h_r(i,j) - 2.0*h_in(i,j))
2041 if (curv > 0.0)
then 2042 dh = h_r(i,j) - h_l(i,j)
2043 if (abs(dh) < curv)
then 2044 if (h_in(i,j) <= h_min)
then 2045 h_l(i,j) = h_in(i,j) ; h_r(i,j) = h_in(i,j)
2046 elseif (12.0*curv*(h_in(i,j) - h_min) < (curv**2 + 3.0*dh**2))
then 2049 scale = 12.0*curv*(h_in(i,j) - h_min) / (curv**2 + 3.0*dh**2)
2050 h_l(i,j) = h_in(i,j) + scale*(h_l(i,j) - h_in(i,j))
2051 h_r(i,j) = h_in(i,j) + scale*(h_r(i,j) - h_in(i,j))
2056 end subroutine ppm_limit_pos
2101 subroutine internal_tides_init(Time, G, GV, US, param_file, diag, CS)
2102 type(time_type),
target,
intent(in) :: Time
2108 type(
diag_ctrl),
target,
intent(in) :: diag
2114 real,
allocatable :: angles(:)
2115 real,
allocatable,
dimension(:,:) :: h2
2116 real :: kappa_itides, kappa_h2_factor
2119 real,
allocatable :: ridge_temp(:,:)
2122 logical :: use_int_tides, use_temperature
2124 integer :: num_angle, num_freq, num_mode, m, fr
2125 integer :: isd, ied, jsd, jed, a, id_ang, i, j
2128 #include "version_variable.h" 2129 character(len=40) :: mdl =
"MOM_internal_tides" 2130 character(len=16),
dimension(8) :: freq_name
2131 character(len=40) :: var_name
2132 character(len=160) :: var_descript
2133 character(len=200) :: filename
2134 character(len=200) :: refl_angle_file, land_mask_file
2135 character(len=200) :: refl_pref_file, refl_dbl_file
2136 character(len=200) :: dy_Cu_file, dx_Cv_file
2137 character(len=200) :: h2_file
2139 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2141 if (
associated(cs))
then 2142 call mom_error(warning,
"internal_tides_init called "//&
2143 "with an associated control structure.")
2149 use_int_tides = .false.
2150 call read_param(param_file,
"INTERNAL_TIDES", use_int_tides)
2151 cs%do_int_tides = use_int_tides
2152 if (.not.use_int_tides)
return 2154 use_temperature = .true.
2155 call read_param(param_file,
"ENABLE_THERMODYNAMICS", use_temperature)
2156 if (.not.use_temperature)
call mom_error(fatal, &
2157 "register_int_tide_restarts: internal_tides only works with "//&
2158 "ENABLE_THERMODYNAMICS defined.")
2161 num_freq = 1 ; num_angle = 24 ; num_mode = 1
2162 call read_param(param_file,
"INTERNAL_TIDE_FREQS", num_freq)
2163 call read_param(param_file,
"INTERNAL_TIDE_ANGLES", num_angle)
2164 call read_param(param_file,
"INTERNAL_TIDE_MODES", num_mode)
2165 if (.not.((num_freq > 0) .and. (num_angle > 0) .and. (num_mode > 0)))
return 2166 cs%nFreq = num_freq ; cs%nAngle = num_angle ; cs%nMode = num_mode
2169 allocate(cs%En(isd:ied, jsd:jed, num_angle, num_freq, num_mode))
2170 cs%En(:,:,:,:,:) = 0.0
2173 allocate(cs%cp(isd:ied, jsd:jed, num_freq, num_mode))
2174 cs%cp(:,:,:,:) = 0.0
2177 allocate(cs%frequency(num_freq))
2178 call get_param(param_file, mdl,
"FIRST_MODE_PERIOD", period_1, units=
"s", scale=us%s_to_T)
2180 cs%frequency(fr) = (8.0*atan(1.0) * (
real(fr)) / period_1)
2187 call get_param(param_file, mdl,
"INPUTDIR", cs%inputdir, default=
".")
2188 cs%inputdir = slasher(cs%inputdir)
2192 call get_param(param_file, mdl,
"INTERNAL_TIDE_FREQS", num_freq, &
2193 "The number of distinct internal tide frequency bands "//&
2194 "that will be calculated.", default=1)
2195 call get_param(param_file, mdl,
"INTERNAL_TIDE_MODES", num_mode, &
2196 "The number of distinct internal tide modes "//&
2197 "that will be calculated.", default=1)
2198 call get_param(param_file, mdl,
"INTERNAL_TIDE_ANGLES", num_angle, &
2199 "The number of angular resolution bands for the internal "//&
2200 "tide calculations.", default=24)
2202 if (use_int_tides)
then 2203 if ((num_freq <= 0) .and. (num_mode <= 0) .and. (num_angle <= 0))
then 2204 call mom_error(warning,
"Internal tides were enabled, but the number "//&
2205 "of requested frequencies, modes and angles were not all positive.")
2209 if ((num_freq > 0) .and. (num_mode > 0) .and. (num_angle > 0))
then 2210 call mom_error(warning,
"Internal tides were not enabled, even though "//&
2211 "the number of requested frequencies, modes and angles were all "//&
2217 if (cs%NFreq /= num_freq)
call mom_error(fatal,
"Internal_tides_init: "//&
2218 "Inconsistent number of frequencies.")
2219 if (cs%NAngle /= num_angle)
call mom_error(fatal,
"Internal_tides_init: "//&
2220 "Inconsistent number of angles.")
2221 if (cs%NMode /= num_mode)
call mom_error(fatal,
"Internal_tides_init: "//&
2222 "Inconsistent number of modes.")
2223 if (4*(num_angle/4) /= num_angle)
call mom_error(fatal, &
2224 "Internal_tides_init: INTERNAL_TIDE_ANGLES must be a multiple of 4.")
2228 call get_param(param_file, mdl,
"INTERNAL_TIDE_DECAY_RATE", cs%decay_rate, &
2229 "The rate at which internal tide energy is lost to the "//&
2230 "interior ocean internal wave field.", &
2231 units=
"s-1", default=0.0, scale=us%T_to_s)
2232 call get_param(param_file, mdl,
"INTERNAL_TIDE_VOLUME_BASED_CFL", cs%vol_CFL, &
2233 "If true, use the ratio of the open face lengths to the "//&
2234 "tracer cell areas when estimating CFL numbers in the "//&
2235 "internal tide code.", default=.false.)
2236 call get_param(param_file, mdl,
"INTERNAL_TIDE_CORNER_ADVECT", cs%corner_adv, &
2237 "If true, internal tide ray-tracing advection uses a "//&
2238 "corner-advection scheme rather than PPM.", default=.false.)
2239 call get_param(param_file, mdl,
"INTERNAL_TIDE_SIMPLE_2ND_PPM", cs%simple_2nd, &
2240 "If true, CONTINUITY_PPM uses a simple 2nd order "//&
2241 "(arithmetic mean) interpolation of the edge values. "//&
2242 "This may give better PV conservation properties. While "//&
2243 "it formally reduces the accuracy of the continuity "//&
2244 "solver itself in the strongly advective limit, it does "//&
2245 "not reduce the overall order of accuracy of the dynamic "//&
2246 "core.", default=.false.)
2247 call get_param(param_file, mdl,
"INTERNAL_TIDE_UPWIND_1ST", cs%upwind_1st, &
2248 "If true, the internal tide ray-tracing advection uses "//&
2249 "1st-order upwind advection. This scheme is highly "//&
2250 "continuity solver. This scheme is highly "//&
2251 "diffusive but may be useful for debugging.", default=.false.)
2252 call get_param(param_file, mdl,
"INTERNAL_TIDE_BACKGROUND_DRAG", &
2253 cs%apply_background_drag,
"If true, the internal tide "//&
2254 "ray-tracing advection uses a background drag term as a sink.",&
2256 call get_param(param_file, mdl,
"INTERNAL_TIDE_QUAD_DRAG", cs%apply_bottom_drag, &
2257 "If true, the internal tide ray-tracing advection uses "//&
2258 "a quadratic bottom drag term as a sink.", default=.false.)
2259 call get_param(param_file, mdl,
"INTERNAL_TIDE_WAVE_DRAG", cs%apply_wave_drag, &
2260 "If true, apply scattering due to small-scale roughness as a sink.", &
2262 call get_param(param_file, mdl,
"INTERNAL_TIDE_FROUDE_DRAG", cs%apply_Froude_drag, &
2263 "If true, apply wave breaking as a sink.", &
2265 call get_param(param_file, mdl,
"CDRAG", cs%cdrag, &
2266 "CDRAG is the drag coefficient relating the magnitude of "//&
2267 "the velocity field to the bottom stress.", units=
"nondim", &
2269 call get_param(param_file, mdl,
"INTERNAL_TIDE_ENERGIZED_ANGLE", cs%energized_angle, &
2270 "If positive, only one angular band of the internal tides "//&
2271 "gets all of the energy. (This is for debugging.)", default=-1)
2272 call get_param(param_file, mdl,
"USE_PPM_ANGULAR", cs%use_PPMang, &
2273 "If true, use PPM for advection of energy in angular space.", &
2275 call get_param(param_file, mdl,
"GAMMA_ITIDES", cs%q_itides, &
2276 "The fraction of the internal tidal energy that is "//&
2277 "dissipated locally with INT_TIDE_DISSIPATION. "//&
2278 "THIS NAME COULD BE BETTER.", &
2279 units=
"nondim", default=0.3333)
2280 call get_param(param_file, mdl,
"KAPPA_ITIDES", kappa_itides, &
2281 "A topographic wavenumber used with INT_TIDE_DISSIPATION. "//&
2282 "The default is 2pi/10 km, as in St.Laurent et al. 2002.", &
2283 units=
"m-1", default=8.e-4*atan(1.0), scale=us%L_to_m)
2284 call get_param(param_file, mdl,
"KAPPA_H2_FACTOR", kappa_h2_factor, &
2285 "A scaling factor for the roughness amplitude with n"//&
2286 "INT_TIDE_DISSIPATION.", units=
"nondim", default=1.0)
2289 allocate(h2(isd:ied,jsd:jed)) ; h2(:,:) = 0.0
2290 allocate(cs%TKE_itidal_loss_fixed(isd:ied,jsd:jed))
2291 cs%TKE_itidal_loss_fixed = 0.0
2292 allocate(cs%TKE_leak_loss(isd:ied,jsd:jed,num_angle,num_freq,num_mode))
2293 cs%TKE_leak_loss(:,:,:,:,:) = 0.0
2294 allocate(cs%TKE_quad_loss(isd:ied,jsd:jed,num_angle,num_freq,num_mode))
2295 cs%TKE_quad_loss(:,:,:,:,:) = 0.0
2296 allocate(cs%TKE_itidal_loss(isd:ied,jsd:jed,num_angle,num_freq,num_mode))
2297 cs%TKE_itidal_loss(:,:,:,:,:) = 0.0
2298 allocate(cs%TKE_Froude_loss(isd:ied,jsd:jed,num_angle,num_freq,num_mode))
2299 cs%TKE_Froude_loss(:,:,:,:,:) = 0.0
2300 allocate(cs%tot_leak_loss(isd:ied,jsd:jed)) ; cs%tot_leak_loss(:,:) = 0.0
2301 allocate(cs%tot_quad_loss(isd:ied,jsd:jed) ) ; cs%tot_quad_loss(:,:) = 0.0
2302 allocate(cs%tot_itidal_loss(isd:ied,jsd:jed)) ; cs%tot_itidal_loss(:,:) = 0.0
2303 allocate(cs%tot_Froude_loss(isd:ied,jsd:jed)) ; cs%tot_Froude_loss(:,:) = 0.0
2306 call get_param(param_file, mdl,
"H2_FILE", h2_file, &
2307 "The path to the file containing the sub-grid-scale "//&
2308 "topographic roughness amplitude with INT_TIDE_DISSIPATION.", &
2309 fail_if_missing=.true.)
2310 filename = trim(cs%inputdir) // trim(h2_file)
2311 call log_param(param_file, mdl,
"INPUTDIR/H2_FILE", filename)
2312 call mom_read_data(filename,
'h2', h2, g%domain, timelevel=1, scale=us%m_to_Z)
2313 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
2315 h2(i,j) = min(0.01*(g%bathyT(i,j))**2, h2(i,j))
2318 cs%TKE_itidal_loss_fixed(i,j) = 0.5*kappa_h2_factor*gv%Rho0 * us%L_to_Z*kappa_itides * h2(i,j)
2324 call get_param(param_file, mdl,
"REFL_ANGLE_FILE", refl_angle_file, &
2325 "The path to the file containing the local angle of "//&
2326 "the coastline/ridge/shelf with respect to the equator.", &
2327 fail_if_missing=.false., default=
'')
2328 filename = trim(cs%inputdir) // trim(refl_angle_file)
2329 allocate(cs%refl_angle(isd:ied,jsd:jed)) ; cs%refl_angle(:,:) = cs%nullangle
2331 call log_param(param_file, mdl,
"INPUTDIR/REFL_ANGLE_FILE", filename)
2333 g%domain, timelevel=1)
2335 if (trim(refl_angle_file) /=
'' )
call mom_error(fatal, &
2336 "REFL_ANGLE_FILE: "//trim(filename)//
" not found")
2339 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
2340 if (is_nan(cs%refl_angle(i,j))) cs%refl_angle(i,j) = cs%nullangle
2342 call pass_var(cs%refl_angle,g%domain)
2345 call get_param(param_file, mdl,
"REFL_PREF_FILE", refl_pref_file, &
2346 "The path to the file containing the reflection coefficients.", &
2347 fail_if_missing=.false., default=
'')
2348 filename = trim(cs%inputdir) // trim(refl_pref_file)
2349 allocate(cs%refl_pref(isd:ied,jsd:jed)) ; cs%refl_pref(:,:) = 1.0
2351 call log_param(param_file, mdl,
"INPUTDIR/REFL_PREF_FILE", filename)
2352 call mom_read_data(filename,
'refl_pref', cs%refl_pref, g%domain, timelevel=1)
2354 if (trim(refl_pref_file) /=
'' )
call mom_error(fatal, &
2355 "REFL_PREF_FILE: "//trim(filename)//
" not found")
2358 call pass_var(cs%refl_pref,g%domain)
2361 allocate(cs%refl_pref_logical(isd:ied,jsd:jed)) ; cs%refl_pref_logical(:,:) = .false.
2365 if (cs%refl_angle(i,j) /= cs%nullangle .and. &
2366 cs%refl_pref(i,j) < 1.0 .and. cs%refl_pref(i,j) > 0.0)
then 2367 cs%refl_pref_logical(i,j) = .true.
2373 call get_param(param_file, mdl,
"REFL_DBL_FILE", refl_dbl_file, &
2374 "The path to the file containing the double-reflective ridge tags.", &
2375 fail_if_missing=.false., default=
'')
2376 filename = trim(cs%inputdir) // trim(refl_dbl_file)
2377 allocate(ridge_temp(isd:ied,jsd:jed)) ; ridge_temp(:,:) = 0.0
2379 call log_param(param_file, mdl,
"INPUTDIR/REFL_DBL_FILE", filename)
2380 call mom_read_data(filename,
'refl_dbl', ridge_temp, g%domain, timelevel=1)
2382 if (trim(refl_dbl_file) /=
'' )
call mom_error(fatal, &
2383 "REFL_DBL_FILE: "//trim(filename)//
" not found")
2386 allocate(cs%refl_dbl(isd:ied,jsd:jed)) ; cs%refl_dbl(:,:) = .false.
2387 do i=isd,ied;
do j=jsd,jed
2388 if (ridge_temp(i,j) == 1) then; cs%refl_dbl(i,j) = .true.
2389 else ; cs%refl_dbl(i,j) = .false. ;
endif 2427 cs%id_refl_ang = register_diag_field(
'ocean_model',
'refl_angle', diag%axesT1, &
2428 time,
'Local angle of coastline/ridge/shelf with respect to equator',
'rad')
2429 cs%id_refl_pref = register_diag_field(
'ocean_model',
'refl_pref', diag%axesT1, &
2430 time,
'Partial reflection coefficients',
'')
2431 cs%id_dx_Cv = register_diag_field(
'ocean_model',
'dx_Cv', diag%axesT1, &
2432 time,
'North face unblocked width',
'm', conversion=us%L_to_m)
2433 cs%id_dy_Cu = register_diag_field(
'ocean_model',
'dy_Cu', diag%axesT1, &
2434 time,
'East face unblocked width',
'm', conversion=us%L_to_m)
2435 cs%id_land_mask = register_diag_field(
'ocean_model',
'land_mask', diag%axesT1, &
2436 time,
'Land mask',
'logical')
2438 if (cs%id_refl_ang > 0)
call post_data(cs%id_refl_ang, cs%refl_angle, cs%diag)
2439 if (cs%id_refl_pref > 0)
call post_data(cs%id_refl_pref, cs%refl_pref, cs%diag)
2440 if (cs%id_dx_Cv > 0)
call post_data(cs%id_dx_Cv, g%dx_Cv, cs%diag)
2441 if (cs%id_dy_Cu > 0)
call post_data(cs%id_dy_Cu, g%dy_Cu, cs%diag)
2442 if (cs%id_land_mask > 0)
call post_data(cs%id_land_mask, g%mask2dT, cs%diag)
2445 cs%id_tot_En = register_diag_field(
'ocean_model',
'ITide_tot_En', diag%axesT1, &
2446 time,
'Internal tide total energy density', &
2447 'J m-2', conversion=us%RZ3_T3_to_W_m2*us%T_to_s)
2449 cs%id_itide_drag = register_diag_field(
'ocean_model',
'ITide_drag', diag%axesT1, &
2450 time,
'Interior and bottom drag internal tide decay timescale',
's-1', conversion=us%s_to_T)
2452 cs%id_TKE_itidal_input = register_diag_field(
'ocean_model',
'TKE_itidal_input', diag%axesT1, &
2453 time,
'Conversion from barotropic to baroclinic tide, '//&
2454 'a fraction of which goes into rays', &
2455 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2457 cs%id_tot_leak_loss = register_diag_field(
'ocean_model',
'ITide_tot_leak_loss', diag%axesT1, &
2458 time,
'Internal tide energy loss to background drag', &
2459 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2460 cs%id_tot_quad_loss = register_diag_field(
'ocean_model',
'ITide_tot_quad_loss', diag%axesT1, &
2461 time,
'Internal tide energy loss to bottom drag', &
2462 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2463 cs%id_tot_itidal_loss = register_diag_field(
'ocean_model',
'ITide_tot_itidal_loss', diag%axesT1, &
2464 time,
'Internal tide energy loss to wave drag', &
2465 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2466 cs%id_tot_Froude_loss = register_diag_field(
'ocean_model',
'ITide_tot_Froude_loss', diag%axesT1, &
2467 time,
'Internal tide energy loss to wave breaking', &
2468 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2469 cs%id_tot_allprocesses_loss = register_diag_field(
'ocean_model',
'ITide_tot_allprocesses_loss', diag%axesT1, &
2470 time,
'Internal tide energy loss summed over all processes', &
2471 'W m-2', conversion=us%RZ3_T3_to_W_m2)
2473 allocate(cs%id_En_mode(cs%nFreq,cs%nMode)) ; cs%id_En_mode(:,:) = -1
2474 allocate(cs%id_En_ang_mode(cs%nFreq,cs%nMode)) ; cs%id_En_ang_mode(:,:) = -1
2475 allocate(cs%id_itidal_loss_mode(cs%nFreq,cs%nMode)) ; cs%id_itidal_loss_mode(:,:) = -1
2476 allocate(cs%id_allprocesses_loss_mode(cs%nFreq,cs%nMode)) ; cs%id_allprocesses_loss_mode(:,:) = -1
2477 allocate(cs%id_itidal_loss_ang_mode(cs%nFreq,cs%nMode)) ; cs%id_itidal_loss_ang_mode(:,:) = -1
2478 allocate(cs%id_Ub_mode(cs%nFreq,cs%nMode)) ; cs%id_Ub_mode(:,:) = -1
2479 allocate(cs%id_cp_mode(cs%nFreq,cs%nMode)) ; cs%id_cp_mode(:,:) = -1
2481 allocate(angles(cs%NAngle)) ; angles(:) = 0.0
2482 angle_size = (8.0*atan(1.0)) / (
real(num_angle))
2483 do a=1,num_angle ; angles(a) = (
real(a) - 1) * angle_size ; enddo
2485 id_ang = diag_axis_init(
"angle", angles,
"Radians",
"N",
"Angular Orienation of Fluxes")
2486 call define_axes_group(diag, (/ diag%axesT1%handles(1), diag%axesT1%handles(2), id_ang /), axes_ang)
2488 do fr=1,cs%nFreq ;
write(freq_name(fr),
'("freq",i1)') fr ;
enddo 2489 do m=1,cs%nMode ;
do fr=1,cs%nFreq
2491 write(var_name,
'("Itide_En_freq",i1,"_mode",i1)') fr, m
2492 write(var_descript,
'("Internal tide energy density in frequency ",i1," mode ",i1)') fr, m
2493 cs%id_En_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2494 diag%axesT1, time, var_descript,
'J m-2', conversion=us%RZ3_T3_to_W_m2*us%T_to_s)
2495 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2498 write(var_name,
'("Itide_En_ang_freq",i1,"_mode",i1)') fr, m
2499 write(var_descript,
'("Internal tide angular energy density in frequency ",i1," mode ",i1)') fr, m
2500 cs%id_En_ang_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2501 axes_ang, time, var_descript,
'J m-2 band-1', conversion=us%RZ3_T3_to_W_m2*us%T_to_s)
2502 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2506 write(var_name,
'("Itide_wavedrag_loss_freq",i1,"_mode",i1)') fr, m
2507 write(var_descript,
'("Internal tide energy loss due to wave-drag from frequency ",i1," mode ",i1)') fr, m
2508 cs%id_itidal_loss_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2509 diag%axesT1, time, var_descript,
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2510 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2512 write(var_name,
'("Itide_allprocesses_loss_freq",i1,"_mode",i1)') fr, m
2513 write(var_descript,
'("Internal tide energy loss due to all processes from frequency ",i1," mode ",i1)') fr, m
2514 cs%id_allprocesses_loss_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2515 diag%axesT1, time, var_descript,
'W m-2', conversion=us%RZ3_T3_to_W_m2)
2516 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2520 write(var_name,
'("Itide_wavedrag_loss_ang_freq",i1,"_mode",i1)') fr, m
2521 write(var_descript,
'("Internal tide energy loss due to wave-drag from frequency ",i1," mode ",i1)') fr, m
2522 cs%id_itidal_loss_ang_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2523 axes_ang, time, var_descript,
'W m-2 band-1', conversion=us%RZ3_T3_to_W_m2)
2524 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2527 write(var_name,
'("Itide_Ub_freq",i1,"_mode",i1)') fr, m
2528 write(var_descript,
'("Near-bottom horizonal velocity for frequency ",i1," mode ",i1)') fr, m
2529 cs%id_Ub_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2530 diag%axesT1, time, var_descript,
'm s-1', conversion=us%L_T_to_m_s)
2531 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2534 write(var_name,
'("Itide_cp_freq",i1,"_mode",i1)') fr, m
2535 write(var_descript,
'("Horizonal phase velocity for frequency ",i1," mode ",i1)') fr, m
2536 cs%id_cp_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2537 diag%axesT1, time, var_descript,
'm s-1', conversion=us%L_T_to_m_s)
2538 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2543 call wave_structure_init(time, g, param_file, diag, cs%wave_structure_CSp)
2545 end subroutine internal_tides_init
2548 subroutine internal_tides_end(CS)
2552 if (
associated(cs))
then 2553 if (
associated(cs%En))
deallocate(cs%En)
2554 if (
allocated(cs%frequency))
deallocate(cs%frequency)
2555 if (
allocated(cs%id_En_mode))
deallocate(cs%id_En_mode)
2556 if (
allocated(cs%id_Ub_mode))
deallocate(cs%id_Ub_mode)
2557 if (
allocated(cs%id_cp_mode))
deallocate(cs%id_cp_mode)
2561 end subroutine internal_tides_end
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Functions and routines to take area, volume, mass-weighted, layerwise, zonal or meridional means...
Wraps the FMS time manager functions.
This control structure has parameters for the MOM_internal_tides module.
Ocean grid type. See mom_grid for details.
The control structure for the MOM_wave_structure module.
A structure that can be parsed to read and document run-time parameters.
Provides the ocean grid type.
Register fields for restarts.
This module contains I/O framework code.
The MOM6 facility to parse input files for runtime parameters.
An overloaded interface to log the values of various types of parameters.
Make a diagnostic available for averaging or output.
A restart registry and the control structure for restarts.
Describes various unit conversion factors.
A structure with the active energy loop bounds.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Describes the decomposed MOM domain and has routines for communications across PEs.
Subroutines that use the ray-tracing equations to propagate the internal tide energy density...
Routines for error handling and I/O management.
The MOM6 facility for reading and writing restart files, and querying what has been read...
Type for describing a variable, typically a tracer.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Indicate whether a file exists, perhaps with domain decomposition.
An overloaded interface to read various types of parameters.
Set up a group of halo updates.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Provides a transparent vertical ocean grid type and supporting routines.
Vertical structure functions for first baroclinic mode wave speed.
Provides transparent structures with groups of MOM6 variables and supporting routines.
Do a halo update on an array.
Read a data field from a file.
An overloaded interface to read and log the values of various types of parameters.
Provides checksumming functions for debugging.