Calls subroutines in this file that are needed to refract, propagate, and dissipate energy density of the internal tide.
154 type(ocean_grid_type),
intent(inout) :: g
155 type(verticalgrid_type),
intent(in) :: gv
156 type(unit_scale_type),
intent(in) :: us
157 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
159 type(thermo_var_ptrs),
intent(in) :: tv
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
168 type(int_tide_cs),
pointer :: cs
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
247 call create_group_pass(pass_en, cs%En(:,:,:,fr,m), g%domain)
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