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
78 real,
allocatable,
dimension(:,:,:,:,:) :: tke_itidal_loss
80 real,
allocatable,
dimension(:,:) :: tot_leak_loss
82 real,
allocatable,
dimension(:,:) :: tot_quad_loss
84 real,
allocatable,
dimension(:,:) :: tot_itidal_loss
86 real,
allocatable,
dimension(:,:) :: tot_froude_loss
88 real,
allocatable,
dimension(:,:) :: tot_allprocesses_loss
92 type(time_type),
pointer :: time => null()
93 character(len=200) :: inputdir
97 logical :: apply_background_drag
99 logical :: apply_bottom_drag
101 logical :: apply_wave_drag
103 logical :: apply_froude_drag
105 real,
dimension(:,:,:,:,:),
pointer :: en => null()
107 real,
dimension(:,:,:),
pointer :: en_restart => null()
109 real,
allocatable,
dimension(:) :: frequency
118 integer :: id_tot_en = -1, id_tke_itidal_input = -1, id_itide_drag = -1
119 integer :: id_refl_pref = -1, id_refl_ang = -1, id_land_mask = -1
120 integer :: id_dx_cv = -1, id_dy_cu = -1
122 integer :: id_tot_leak_loss = -1, id_tot_quad_loss = -1, id_tot_itidal_loss = -1
123 integer :: id_tot_froude_loss = -1, id_tot_allprocesses_loss = -1
125 integer,
allocatable,
dimension(:,:) :: &
127 id_itidal_loss_mode, &
128 id_allprocesses_loss_mode, &
132 integer,
allocatable,
dimension(:,:) :: &
134 id_itidal_loss_ang_mode
142 integer :: ish, ieh, jsh, jeh
150 subroutine propagate_int_tide(h, tv, cn, TKE_itidal_input, vel_btTide, Nb, dt, &
155 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
159 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: tke_itidal_input
161 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: vel_bttide
163 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: nb
164 real,
intent(in) :: dt
168 real,
dimension(SZI_(G),SZJ_(G),CS%nMode), &
171 real,
dimension(SZI_(G),SZJ_(G),2) :: &
173 real,
dimension(SZI_(G),SZJ_(G),CS%nFreq,CS%nMode) :: &
176 real,
dimension(SZI_(G),SZJB_(G)) :: &
179 real,
dimension(SZI_(G),SZJ_(G)) :: &
181 tot_leak_loss, tot_quad_loss, tot_itidal_loss, tot_froude_loss, tot_allprocesses_loss, &
184 itidal_loss_mode, allprocesses_loss_mode
186 real :: frac_per_sector, f2, i_rho0, i_d_here, freq2, kmag2
187 real :: c_phase, loss_rate, fr2_max
188 real,
parameter :: cn_subro = 1e-100
189 real :: en_new, en_check
190 real :: en_initial, delta_e_check
191 real :: tke_froude_loss_check, tke_froude_loss_tot
192 character(len=160) :: mesg
193 integer :: a, m, fr, i, j, is, ie, js, je, isd, ied, jsd, jed, nangle, nzm
194 integer :: id_g, jd_g
195 type(group_pass_type),
save :: pass_test, pass_en
197 if (.not.
associated(cs))
return
198 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
199 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed ; nangle = cs%NAngle
200 i_rho0 = 1.0 / gv%Rho0
210 if (cs%energized_angle <= 0)
then
211 frac_per_sector = 1.0 / real(cs%nAngle * cs%nMode * cs%nFreq)
212 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
213 f2 = 0.25*us%s_to_T**2*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
214 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2))
215 if (cs%frequency(fr)**2 > f2) &
216 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) + &
217 dt*frac_per_sector*(1-cs%q_itides)*tke_itidal_input(i,j)
218 enddo ;
enddo ;
enddo ;
enddo ;
enddo
219 elseif (cs%energized_angle <= cs%nAngle)
then
220 frac_per_sector = 1.0 / real(cs%nMode * cs%nFreq)
221 a = cs%energized_angle
222 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do j=js,je ;
do i=is,ie
223 f2 = 0.25*us%s_to_T**2*((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) + &
227 dt*frac_per_sector**(1-cs%q_itides)*tke_itidal_input(i,j)
228 enddo ;
enddo ;
enddo ;
enddo
230 call mom_error(warning,
"Internal tide energy is being put into a angular "//&
231 "band that does not exist.")
235 do j=jsd,jed ;
do i=isd,ied ; test(i,j,1) = 1.0 ; test(i,j,2) = 0.0 ;
enddo ;
enddo
236 do m=1,cs%nMode ;
do fr=1,cs%nFreq
239 call create_group_pass(pass_test, test(:,:,1), test(:,:,2), g%domain, stagger=agrid)
240 call start_group_pass(pass_test, g%domain)
243 do m=1,cs%nMode ;
do fr=1,cs%nFreq
244 call refract(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), 0.5*dt, g, us, cs%nAngle, cs%use_PPMang)
248 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
249 do j=js,je ;
do i=is,ie
250 if (cs%En(i,j,a,fr,m)<0.0)
then
251 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
252 write(mesg,*)
'After first refraction: En<0.0 at ig=', id_g,
', jg=', jd_g, &
253 'En=',cs%En(i,j,a,fr,m)
254 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
255 cs%En(i,j,a,fr,m) = 0.0
259 enddo ;
enddo ;
enddo
261 call do_group_pass(pass_en, g%domain)
263 call complete_group_pass(pass_test, g%domain)
266 call correct_halo_rotation(cs%En, test, g, cs%nAngle)
269 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
270 call propagate(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), dt, g, us, cs, cs%NAngle)
274 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
275 do j=js,je ;
do i=is,ie
276 if (cs%En(i,j,a,fr,m)<0.0)
then
277 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
278 if (abs(cs%En(i,j,a,fr,m))>1.0)
then
279 write(mesg,*)
'After propagation: En<0.0 at ig=', id_g,
', jg=', jd_g, &
280 'En=', cs%En(i,j,a,fr,m)
281 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
284 cs%En(i,j,a,fr,m) = 0.0
287 enddo ;
enddo ;
enddo
290 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
291 call refract(cs%En(:,:,:,fr,m), cn(:,:,m), cs%frequency(fr), 0.5*dt, g, us, cs%NAngle, cs%use_PPMang)
295 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
296 do j=js,je ;
do i=is,ie
297 if (cs%En(i,j,a,fr,m)<0.0)
then
298 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
299 write(mesg,*)
'After second refraction: En<0.0 at ig=', id_g,
', jg=', jd_g, &
300 'En=',cs%En(i,j,a,fr,m)
301 call mom_error(warning,
"propagate_int_tide: "//trim(mesg))
302 cs%En(i,j,a,fr,m) = 0.0
306 enddo ;
enddo ;
enddo
309 if (cs%apply_background_drag .or. cs%apply_bottom_drag &
310 .or. cs%apply_wave_drag .or. cs%apply_Froude_drag &
311 .or. (cs%id_tot_En > 0))
then
313 tot_en_mode(:,:,:,:) = 0.0
314 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
315 do j=jsd,jed ;
do i=isd,ied ;
do a=1,cs%nAngle
316 tot_en(i,j) = tot_en(i,j) + cs%En(i,j,a,fr,m)
317 tot_en_mode(i,j,fr,m) = tot_en_mode(i,j,fr,m) + cs%En(i,j,a,fr,m)
318 enddo ;
enddo ;
enddo
323 if (cs%apply_background_drag)
then
324 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=jsd,jed ;
do i=isd,ied
327 cs%TKE_leak_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * cs%decay_rate
328 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) / (1.0 + dt *cs%decay_rate)
329 enddo ;
enddo ;
enddo ;
enddo ;
enddo
332 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
333 do j=js,je ;
do i=is,ie
334 if (cs%En(i,j,a,fr,m)<0.0)
then
335 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
336 write(mesg,*)
'After leak loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
337 'En=',cs%En(i,j,a,fr,m)
338 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
339 cs%En(i,j,a,fr,m) = 0.0
343 enddo ;
enddo ;
enddo
346 if (cs%apply_bottom_drag)
then
347 do j=jsd,jed ;
do i=isd,ied
349 i_d_here = 1.0 / (us%Z_to_m*max(g%bathyT(i,j), 1.0*us%m_to_Z))
350 drag_scale(i,j) = cs%cdrag * sqrt(max(0.0, vel_bttide(i,j)**2 + &
351 tot_en(i,j) * i_rho0 * i_d_here)) * i_d_here
353 do m=1,cs%nMode ;
do fr=1,cs%nFreq ;
do a=1,cs%nAngle ;
do j=jsd,jed ;
do i=isd,ied
356 cs%TKE_quad_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * drag_scale(i,j)
357 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m) / (1.0 + dt *drag_scale(i,j))
358 enddo ;
enddo ;
enddo ;
enddo ;
enddo
361 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
362 do j=js,je ;
do i=is,ie
363 if (cs%En(i,j,a,fr,m)<0.0)
then
364 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
365 write(mesg,*)
'After bottom loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
366 'En=',cs%En(i,j,a,fr,m)
367 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
368 cs%En(i,j,a,fr,m) = 0.0
373 enddo ;
enddo ;
enddo
378 if (cs%apply_wave_drag .or. cs%apply_Froude_drag)
then
379 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
381 call wave_structure(h, tv, g, gv, us, cn(:,:,m), m, cs%frequency(fr), &
382 cs%wave_structure_CSp, tot_en_mode(:,:,fr,m), full_halos=.true.)
384 do j=jsd,jed ;
do i=isd,ied
385 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
386 nzm = cs%wave_structure_CSp%num_intfaces(i,j)
387 ub(i,j,fr,m) = cs%wave_structure_CSp%Uavg_profile(i,j,nzm)
388 umax(i,j,fr,m) = maxval(cs%wave_structure_CSp%Uavg_profile(i,j,1:nzm))
393 if (cs%apply_wave_drag)
then
395 call itidal_lowmode_loss(g, us, cs, nb, ub, cs%En, cs%TKE_itidal_loss_fixed, &
396 cs%TKE_itidal_loss, dt, full_halos=.false.)
399 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
400 do j=js,je ;
do i=is,ie
401 if (cs%En(i,j,a,fr,m)<0.0)
then
402 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
403 write(mesg,*)
'After wave drag loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
404 'En=',cs%En(i,j,a,fr,m)
405 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
406 cs%En(i,j,a,fr,m) = 0.0
410 enddo ;
enddo ;
enddo
413 if (cs%apply_Froude_drag)
then
415 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
416 freq2 = cs%frequency(fr)**2
417 do j=jsd,jed ;
do i=isd,ied
418 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
420 f2 = 0.25*us%s_to_T**2*((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
421 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i,j-1)**2))
422 kmag2 = (freq2 - f2) / (cn(i,j,m)**2 + cn_subro**2)
424 if (kmag2 > 0.0)
then
425 c_phase = sqrt(freq2/kmag2)
426 nzm = cs%wave_structure_CSp%num_intfaces(i,j)
427 fr2_max = (umax(i,j,fr,m)/c_phase)**2
429 if (fr2_max > 1.0)
then
430 en_initial = sum(cs%En(i,j,:,fr,m))
432 loss_rate = (1/fr2_max - 1.0)/dt
435 cs%TKE_Froude_loss(i,j,a,fr,m) = cs%En(i,j,a,fr,m) * abs(loss_rate)
437 en_new = cs%En(i,j,a,fr,m)/fr2_max
438 en_check = cs%En(i,j,a,fr,m) - cs%TKE_Froude_loss(i,j,a,fr,m)*dt
440 cs%En(i,j,a,fr,m) = cs%En(i,j,a,fr,m)/fr2_max
442 if (abs(en_new - en_check) > 1e-10)
then
443 call mom_error(warning,
"MOM_internal_tides: something is wrong with Fr-breaking.", &
445 write(mesg,*)
"En_new=", en_new ,
"En_check=", en_check
446 call mom_error(warning,
"MOM_internal_tides: "//trim(mesg), all_print=.true.)
450 delta_e_check = en_initial - sum(cs%En(i,j,:,fr,m))
451 tke_froude_loss_check = abs(delta_e_check)/dt
452 tke_froude_loss_tot = sum(cs%TKE_Froude_loss(i,j,:,fr,m))
453 if (abs(tke_froude_loss_check - tke_froude_loss_tot) > 1e-10)
then
454 call mom_error(warning,
"MOM_internal_tides: something is wrong with Fr energy update.", &
456 write(mesg,*)
"TKE_Froude_loss_check=", tke_froude_loss_check, &
457 "TKE_Froude_loss_tot=", tke_froude_loss_tot
458 call mom_error(warning,
"MOM_internal_tides: "//trim(mesg), all_print=.true.)
462 cs%cp(i,j,fr,m) = c_phase
467 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle
468 do j=js,je ;
do i=is,ie
469 if (cs%En(i,j,a,fr,m)<0.0)
then
470 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
471 write(mesg,*)
'After Froude loss: En<0.0 at ig=', id_g,
', jg=', jd_g, &
472 'En=',cs%En(i,j,a,fr,m)
473 call mom_error(warning,
"propagate_int_tide: "//trim(mesg), all_print=.true.)
474 cs%En(i,j,a,fr,m) = 0.0
479 enddo ;
enddo ;
enddo
482 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
483 call sum_en(g,cs,cs%En(:,:,:,fr,m),
'prop_int_tide')
487 if (query_averaging_enabled(cs%diag))
then
489 if (cs%id_tot_En > 0)
call post_data(cs%id_tot_En, tot_en, cs%diag)
490 if (cs%id_itide_drag > 0)
call post_data(cs%id_itide_drag, drag_scale, cs%diag)
491 if (cs%id_TKE_itidal_input > 0)
call post_data(cs%id_TKE_itidal_input, &
492 tke_itidal_input, cs%diag)
495 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_En_mode(fr,m) > 0)
then
497 do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
498 tot_en(i,j) = tot_en(i,j) + cs%En(i,j,a,fr,m)
499 enddo ;
enddo ;
enddo
500 call post_data(cs%id_En_mode(fr,m), tot_en, cs%diag)
501 endif ;
enddo ;
enddo
504 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_En_ang_mode(fr,m) > 0)
then
505 call post_data(cs%id_En_ang_mode(fr,m), cs%En(:,:,:,fr,m) , cs%diag)
506 endif ;
enddo ;
enddo
509 tot_leak_loss(:,:) = 0.0
510 tot_quad_loss(:,:) = 0.0
511 tot_itidal_loss(:,:) = 0.0
512 tot_froude_loss(:,:) = 0.0
513 tot_allprocesses_loss(:,:) = 0.0
514 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
515 tot_leak_loss(i,j) = tot_leak_loss(i,j) + cs%TKE_leak_loss(i,j,a,fr,m)
516 tot_quad_loss(i,j) = tot_quad_loss(i,j) + cs%TKE_quad_loss(i,j,a,fr,m)
517 tot_itidal_loss(i,j) = tot_itidal_loss(i,j) + cs%TKE_itidal_loss(i,j,a,fr,m)
518 tot_froude_loss(i,j) = tot_froude_loss(i,j) + cs%TKE_Froude_loss(i,j,a,fr,m)
519 enddo ;
enddo ;
enddo ;
enddo ;
enddo
520 do j=js,je ;
do i=is,ie
521 tot_allprocesses_loss(i,j) = tot_leak_loss(i,j) + tot_quad_loss(i,j) + &
522 tot_itidal_loss(i,j) + tot_froude_loss(i,j)
524 cs%tot_leak_loss = tot_leak_loss
525 cs%tot_quad_loss = tot_quad_loss
526 cs%tot_itidal_loss = tot_itidal_loss
527 cs%tot_Froude_loss = tot_froude_loss
528 cs%tot_allprocesses_loss = tot_allprocesses_loss
529 if (cs%id_tot_leak_loss > 0)
then
530 call post_data(cs%id_tot_leak_loss, tot_leak_loss, cs%diag)
532 if (cs%id_tot_quad_loss > 0)
then
533 call post_data(cs%id_tot_quad_loss, tot_quad_loss, cs%diag)
535 if (cs%id_tot_itidal_loss > 0)
then
536 call post_data(cs%id_tot_itidal_loss, tot_itidal_loss, cs%diag)
538 if (cs%id_tot_Froude_loss > 0)
then
539 call post_data(cs%id_tot_Froude_loss, tot_froude_loss, cs%diag)
541 if (cs%id_tot_allprocesses_loss > 0)
then
542 call post_data(cs%id_tot_allprocesses_loss, tot_allprocesses_loss, cs%diag)
546 do m=1,cs%NMode ;
do fr=1,cs%Nfreq
547 if (cs%id_itidal_loss_mode(fr,m) > 0 .or. cs%id_allprocesses_loss_mode(fr,m) > 0)
then
548 itidal_loss_mode(:,:) = 0.0
549 allprocesses_loss_mode(:,:) = 0.0
550 do a=1,cs%nAngle ;
do j=js,je ;
do i=is,ie
551 itidal_loss_mode(i,j) = itidal_loss_mode(i,j) + cs%TKE_itidal_loss(i,j,a,fr,m)
552 allprocesses_loss_mode(i,j) = allprocesses_loss_mode(i,j) + &
553 cs%TKE_leak_loss(i,j,a,fr,m) + cs%TKE_quad_loss(i,j,a,fr,m) + &
554 cs%TKE_itidal_loss(i,j,a,fr,m) + cs%TKE_Froude_loss(i,j,a,fr,m)
555 enddo ;
enddo ;
enddo
556 call post_data(cs%id_itidal_loss_mode(fr,m), itidal_loss_mode, cs%diag)
557 call post_data(cs%id_allprocesses_loss_mode(fr,m), allprocesses_loss_mode, cs%diag)
558 endif ;
enddo ;
enddo
561 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_itidal_loss_ang_mode(fr,m) > 0)
then
562 call post_data(cs%id_itidal_loss_ang_mode(fr,m), cs%TKE_itidal_loss(:,:,:,fr,m) , cs%diag)
563 endif ;
enddo ;
enddo
566 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_Ub_mode(fr,m) > 0)
then
567 call post_data(cs%id_Ub_mode(fr,m), ub(:,:,fr,m), cs%diag)
568 endif ;
enddo ;
enddo
571 do m=1,cs%NMode ;
do fr=1,cs%Nfreq ;
if (cs%id_cp_mode(fr,m) > 0)
then
572 call post_data(cs%id_cp_mode(fr,m), cs%cp(:,:,fr,m), cs%diag)
573 endif ;
enddo ;
enddo
577 end subroutine propagate_int_tide
580 subroutine sum_en(G, CS, En, label)
584 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle), &
586 character(len=*),
intent(in) :: label
589 real :: En_sum, tmpForSumming, En_sum_diff, En_sum_pdiff
590 character(len=160) :: mesg
596 tmpforsumming = global_area_mean(en(:,:,a),g)*g%areaT_global
597 en_sum = en_sum + tmpforsumming
599 en_sum_diff = en_sum - cs%En_sum
600 if (cs%En_sum /= 0.0)
then
601 en_sum_pdiff= (en_sum_diff/cs%En_sum)*100.0
616 end subroutine sum_en
620 subroutine itidal_lowmode_loss(G, US, CS, Nb, Ub, En, TKE_loss_fixed, TKE_loss, dt, full_halos)
625 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
627 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%nFreq,CS%nMode), &
630 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
631 intent(in) :: TKE_loss_fixed
633 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle,CS%nFreq,CS%nMode), &
635 real,
dimension(G%isd:G%ied,G%jsd:G%jed,CS%NAngle,CS%nFreq,CS%nMode), &
636 intent(out) :: TKE_loss
638 real,
intent(in) :: dt
639 logical,
optional,
intent(in) :: full_halos
642 integer :: j,i,m,fr,a, is, ie, js, je
645 real :: TKE_sum_check
646 real :: frac_per_sector
650 real,
parameter :: En_negl = 1e-30
652 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
654 q_itides = cs%q_itides
656 if (
present(full_halos))
then ;
if (full_halos)
then
657 is = g%isd ; ie = g%ied ; js = g%jsd ; je = g%jed
660 do j=js,je ;
do i=is,ie ;
do m=1,cs%nMode ;
do fr=1,cs%nFreq
665 en_tot = en_tot + en(i,j,a,fr,m)
669 tke_loss_tot = q_itides * us%Z_to_m**2 * tke_loss_fixed(i,j) * nb(i,j) * ub(i,j,fr,m)**2
673 if (en_tot > 0.0)
then
675 frac_per_sector = en(i,j,a,fr,m)/en_tot
676 tke_loss(i,j,a,fr,m) = frac_per_sector*tke_loss_tot
677 loss_rate = tke_loss(i,j,a,fr,m) / (en(i,j,a,fr,m) + en_negl)
678 en(i,j,a,fr,m) = en(i,j,a,fr,m) / (1.0 + dt*loss_rate)
682 tke_loss(i,j,:,fr,m) = 0.0
703 enddo ;
enddo ;
enddo ;
enddo
705 end subroutine itidal_lowmode_loss
711 subroutine get_lowmode_loss(i,j,G,CS,mechanism,TKE_loss_sum)
712 integer,
intent(in) :: i
713 integer,
intent(in) :: j
717 character(len=*),
intent(in) :: mechanism
718 real,
intent(out) :: tke_loss_sum
721 if (mechanism ==
'LeakDrag') tke_loss_sum = cs%tot_leak_loss(i,j)
722 if (mechanism ==
'QuadDrag') tke_loss_sum = cs%tot_quad_loss(i,j)
723 if (mechanism ==
'WaveDrag') tke_loss_sum = cs%tot_itidal_loss(i,j)
724 if (mechanism ==
'Froude') tke_loss_sum = cs%tot_Froude_loss(i,j)
726 end subroutine get_lowmode_loss
729 subroutine refract(En, cn, freq, dt, G, US, NAngle, use_PPMang)
731 integer,
intent(in) :: NAngle
733 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
737 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
739 real,
intent(in) :: freq
740 real,
intent(in) :: dt
742 logical,
intent(in) :: use_PPMang
745 integer,
parameter :: stencil = 2
746 real,
dimension(SZI_(G),1-stencil:NAngle+stencil) :: &
748 real,
dimension(1-stencil:NAngle+stencil) :: &
750 real,
dimension(SZI_(G)) :: &
751 Dk_Dt_Kmag, Dl_Dt_Kmag
752 real,
dimension(SZI_(G),0:nAngle) :: &
754 real,
dimension(SZI_(G),SZJ_(G),1-stencil:NAngle+stencil) :: &
758 real :: df2_dy, df2_dx
762 real :: Angle_size, dt_Angle_size, angle
763 real :: Ifreq, Kmag2, I_Kmag
764 real,
parameter :: cn_subRO = 1e-100
765 integer :: is, ie, js, je, asd, aed, na
768 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; na =
size(en,3)
769 asd = 1-stencil ; aed = nangle+stencil
773 angle_size = (8.0*atan(1.0)) / (real(nangle))
774 dt_angle_size = dt / angle_size
777 angle = (real(a) - 0.5) * angle_size
778 cos_angle(a) = cos(angle) ; sin_angle(a) = sin(angle)
785 do a=1,na ;
do i=is,ie
786 en2d(i,a) = en(i,j,a)
788 do a=asd,0 ;
do i=is,ie
789 en2d(i,a) = en2d(i,a+nangle)
790 en2d(i,nangle+stencil+a) = en2d(i,stencil+a)
795 f2 = 0.25*us%s_to_T**2 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j-1)**2) + &
796 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j)**2))
797 favg = 0.25*us%s_to_T*((g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j-1)) + &
798 (g%CoriolisBu(i,j-1) + g%CoriolisBu(i-1,j)))
799 df2_dx = 0.5*us%s_to_T**2 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i,j-1)**2) - &
800 (g%CoriolisBu(i-1,j)**2 + g%CoriolisBu(i-1,j-1)**2)) * &
802 df_dx = 0.5*us%s_to_T*((g%CoriolisBu(i,j) + g%CoriolisBu(i,j-1)) - &
803 (g%CoriolisBu(i-1,j) + g%CoriolisBu(i-1,j-1))) * &
805 dlncn_dx = 0.5*( g%IdxCu(i,j) * (cn(i+1,j) - cn(i,j)) / &
806 (0.5*(cn(i+1,j) + cn(i,j)) + cn_subro) + &
807 g%IdxCu(i-1,j) * (cn(i,j) - cn(i-1,j)) / &
808 (0.5*(cn(i,j) + cn(i-1,j)) + cn_subro) )
809 df2_dy = 0.5*us%s_to_T**2 * ((g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j)**2) - &
810 (g%CoriolisBu(i,j-1)**2 + g%CoriolisBu(i-1,j-1)**2)) * &
812 df_dy = 0.5*us%s_to_T*((g%CoriolisBu(i,j) + g%CoriolisBu(i-1,j)) - &
813 (g%CoriolisBu(i,j-1) + g%CoriolisBu(i-1,j-1))) * &
815 dlncn_dy = 0.5*( g%IdyCv(i,j) * (cn(i,j+1) - cn(i,j)) / &
816 (0.5*(cn(i,j+1) + cn(i,j)) + cn_subro) + &
817 g%IdyCv(i,j-1) * (cn(i,j) - cn(i,j-1)) / &
818 (0.5*(cn(i,j) + cn(i,j-1)) + cn_subro) )
819 kmag2 = (freq**2 - f2) / (cn(i,j)**2 + cn_subro**2)
820 if (kmag2 > 0.0)
then
821 i_kmag = 1.0 / sqrt(kmag2)
822 dk_dt_kmag(i) = -ifreq * (favg*df_dx + (freq**2 - f2) * dlncn_dx) * i_kmag
823 dl_dt_kmag(i) = -ifreq * (favg*df_dy + (freq**2 - f2) * dlncn_dy) * i_kmag
831 do a=asd,aed ;
do i=is,ie
832 cfl_ang(i,j,a) = (cos_angle(a) * dl_dt_kmag(i) - sin_angle(a) * dk_dt_kmag(i)) * &
834 if (abs(cfl_ang(i,j,a)) > 1.0)
then
835 call mom_error(warning,
"refract: CFL exceeds 1.", .true.)
836 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
841 if (.not.use_ppmang)
then
843 do a=0,na ;
do i=is,ie
844 if (cfl_ang(i,j,a) > 0.0)
then
845 flux_e(i,a) = cfl_ang(i,j,a) * en2d(i,a)
847 flux_e(i,a) = cfl_ang(i,j,a) * en2d(i,a+1)
853 call ppm_angular_advect(en2d(i,:),cfl_ang(i,j,:),flux_e(i,:),nangle,dt,stencil)
858 do a=1,na ;
do i=is,ie
862 en(i,j,a) = en2d(i,a) + (flux_e(i,a-1) - flux_e(i,a))
865 end subroutine refract
869 subroutine ppm_angular_advect(En2d, CFL_ang, Flux_En, NAngle, dt, halo_ang)
870 integer,
intent(in) :: NAngle
872 real,
intent(in) :: dt
873 integer,
intent(in) :: halo_ang
874 real,
dimension(1-halo_ang:NAngle+halo_ang), &
877 real,
dimension(1-halo_ang:NAngle+halo_ang), &
878 intent(in) :: CFL_ang
879 real,
dimension(0:NAngle),
intent(out) :: Flux_En
888 real :: aR, aL, dMx, dMn, Ep, Ec, Em, dA, mA, a6
891 angle_size = (8.0*atan(1.0)) / (real(nangle))
892 i_angle_size = 1 / angle_size
896 u_ang = cfl_ang(a)*angle_size*i_dt
897 if (u_ang >= 0.0)
then
899 ep = en2d(a+1)*i_angle_size
900 ec = en2d(a) *i_angle_size
901 em = en2d(a-1)*i_angle_size
902 al = ( 5.*ec + ( 2.*em - ep ) )/6.
903 al = max( min(ec,em), al) ; al = min( max(ec,em), al)
904 ar = ( 5.*ec + ( 2.*ep - em ) )/6.
905 ar = max( min(ec,ep), ar) ; ar = min( max(ec,ep), ar)
906 da = ar - al ; ma = 0.5*( ar + al )
907 if ((ep-ec)*(ec-em) <= 0.)
then
909 elseif ( da*(ec-ma) > (da*da)/6. )
then
911 elseif ( da*(ec-ma) < - (da*da)/6. )
then
914 a6 = 6.*ec - 3. * (ar + al)
916 flux = u_ang*( ar + 0.5 * cfl_ang(a) * ( ( al - ar ) + a6 * ( 1. - 2./3. * cfl_ang(a) ) ) )
919 flux_en(a) = dt * flux
923 ep = en2d(a+2)*i_angle_size
924 ec = en2d(a+1)*i_angle_size
925 em = en2d(a) *i_angle_size
926 al = ( 5.*ec + ( 2.*em - ep ) )/6.
927 al = max( min(ec,em), al) ; al = min( max(ec,em), al)
928 ar = ( 5.*ec + ( 2.*ep - em ) )/6.
929 ar = max( min(ec,ep), ar) ; ar = min( max(ec,ep), ar)
930 da = ar - al ; ma = 0.5*( ar + al )
931 if ((ep-ec)*(ec-em) <= 0.)
then
933 elseif ( da*(ec-ma) > (da*da)/6. )
then
935 elseif ( da*(ec-ma) < - (da*da)/6. )
then
938 a6 = 6.*ec - 3. * (ar + al)
940 flux = u_ang*( ar + 0.5 * cfl_ang(a) * ( ( al - ar ) + a6 * ( 1. - 2./3. * cfl_ang(a) ) ) )
943 flux_en(a) = dt * flux
947 end subroutine ppm_angular_advect
950 subroutine propagate(En, cn, freq, dt, G, US, CS, NAngle)
952 integer,
intent(in) :: NAngle
954 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
958 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
960 real,
intent(in) :: freq
961 real,
intent(in) :: dt
966 real,
dimension(G%IsdB:G%IedB,G%JsdB:G%JedB) :: &
968 integer,
parameter :: stencil = 2
969 real,
dimension(SZIB_(G),SZJ_(G)) :: &
971 real,
dimension(SZI_(G),SZJB_(G)) :: &
973 real,
dimension(0:NAngle) :: &
975 real,
dimension(NAngle) :: &
976 Cgx_av, Cgy_av, dCgx, dCgy
978 real :: Angle_size, I_Angle_size, angle
980 real,
parameter :: cn_subRO = 1e-100
982 integer :: is, ie, js, je, asd, aed, na
983 integer :: ish, ieh, jsh, jeh
986 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; na =
size(en,3)
987 asd = 1-stencil ; aed = nangle+stencil
1001 jsh = js-1 ; jeh = je+1 ; ish = is-1 ; ieh = ie+1
1003 angle_size = (8.0*atan(1.0)) / real(nangle)
1004 i_angle_size = 1.0 / angle_size
1006 if (cs%corner_adv)
then
1012 do j=jsh-1,jeh ;
do i=ish-1,ieh
1013 f2 = us%s_to_T**2 * g%CoriolisBu(i,j)**2
1014 speed(i,j) = 0.25*(cn(i,j) + cn(i+1,j) + cn(i+1,j+1) + cn(i,j+1)) * &
1015 sqrt(max(freq2 - f2, 0.0)) * ifreq
1019 lb%jsh = js ; lb%jeh = je ; lb%ish = is ; lb%ieh = ie
1020 call propagate_corner_spread(en(:,:,a), a, nangle, speed, dt, g, cs, lb)
1027 angle = (real(a) - 0.5) * angle_size
1028 cos_angle(a) = cos(angle) ; sin_angle(a) = sin(angle)
1032 cgx_av(a) = (sin_angle(a) - sin_angle(a-1)) * i_angle_size
1033 cgy_av(a) = -(cos_angle(a) - cos_angle(a-1)) * i_angle_size
1034 dcgx(a) = sqrt(0.5 + 0.5*(sin_angle(a)*cos_angle(a) - &
1035 sin_angle(a-1)*cos_angle(a-1)) * i_angle_size - &
1037 dcgy(a) = sqrt(0.5 - 0.5*(sin_angle(a)*cos_angle(a) - &
1038 sin_angle(a-1)*cos_angle(a-1)) * i_angle_size - &
1042 do j=jsh,jeh ;
do i=ish-1,ieh
1043 f2 = 0.5*us%s_to_T**2 * (g%CoriolisBu(i,j)**2 + g%CoriolisBu(i,j-1)**2)
1044 speed_x(i,j) = 0.5*(cn(i,j) + cn(i+1,j)) * g%mask2dCu(i,j) * &
1045 sqrt(max(freq2 - f2, 0.0)) * ifreq
1047 do j=jsh-1,jeh ;
do i=ish,ieh
1048 f2 = 0.5*us%s_to_T**2 * (g%CoriolisBu(i,j)**2 + g%CoriolisBu(i-1,j)**2)
1049 speed_y(i,j) = 0.5*(cn(i,j) + cn(i,j+1)) * g%mask2dCv(i,j) * &
1050 sqrt(max(freq2 - f2, 0.0)) * ifreq
1054 lb%jsh = jsh ; lb%jeh = jeh ; lb%ish = ish ; lb%ieh = ieh
1055 call propagate_x(en(:,:,:), speed_x, cgx_av(:), dcgx(:), dt, g, cs%nAngle, cs, lb)
1065 lb%jsh = jsh ; lb%jeh = jeh ; lb%ish = ish ; lb%ieh = ieh
1066 call propagate_y(en(:,:,:), speed_y, cgy_av(:), dcgy(:), dt, g, cs%nAngle, cs, lb)
1072 end subroutine propagate
1077 subroutine propagate_corner_spread(En, energized_wedge, NAngle, speed, dt, G, CS, LB)
1079 real,
dimension(G%isd:G%ied,G%jsd:G%jed), &
1082 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed), &
1085 integer,
intent(in) :: energized_wedge
1086 integer,
intent(in) :: NAngle
1088 real,
intent(in) :: dt
1093 integer :: i, j, k, ish, ieh, jsh, jeh, m
1094 real :: TwoPi, Angle_size
1095 real :: energized_angle
1100 real :: I_Nsubwedges
1101 real :: cos_thetaDT, sin_thetaDT
1102 real :: xNE,xNW,xSW,xSE,yNE,yNW,ySW,ySE
1103 real :: CFL_xNE,CFL_xNW,CFL_xSW,CFL_xSE,CFL_yNE,CFL_yNW,CFL_ySW,CFL_ySE,CFL_max
1104 real :: xN,xS,xE,xW,yN,yS,yE,yW
1107 real :: slopeN,slopeW,slopeS,slopeE, bN,bW,bS,bE
1108 real :: aNE,aN,aNW,aW,aSW,aS,aSE,aE,aC
1111 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: x,y
1112 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: Idx,Idy
1113 real,
dimension(G%IsdB:G%IedB,G%Jsd:G%Jed) :: dx,dy
1114 real,
dimension(2) :: E_new
1117 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1118 twopi = (8.0*atan(1.0))
1119 nsubrays = real(
size(e_new))
1120 i_nsubwedges = 1./(nsubrays - 1)
1122 angle_size = twopi / real(nangle)
1123 energized_angle = angle_size * real(energized_wedge - 1)
1128 idx = g%IdxBu; dx = g%dxBu
1129 idy = g%IdyBu; dy = g%dyBu
1131 do j=jsh,jeh;
do i=ish,ieh
1132 do m=1,int(nsubrays)
1133 theta = energized_angle - 0.5*angle_size + real(m - 1)*angle_size*i_nsubwedges
1134 if (theta < 0.0)
then
1135 theta = theta + twopi
1136 elseif (theta > twopi)
then
1137 theta = theta - twopi
1139 cos_thetadt = cos(theta)*dt
1140 sin_thetadt = sin(theta)*dt
1143 xg = x(i,j); yg = y(i,j)
1144 xne = xg - speed(i,j)*cos_thetadt
1145 yne = yg - speed(i,j)*sin_thetadt
1146 cfl_xne = (xg-xne)*idx(i,j)
1147 cfl_yne = (yg-yne)*idy(i,j)
1149 xg = x(i-1,j); yg = y(i-1,j)
1150 xnw = xg - speed(i-1,j)*cos_thetadt
1151 ynw = yg - speed(i-1,j)*sin_thetadt
1152 cfl_xnw = (xg-xnw)*idx(i-1,j)
1153 cfl_ynw = (yg-ynw)*idy(i-1,j)
1155 xg = x(i-1,j-1); yg = y(i-1,j-1)
1156 xsw = xg - speed(i-1,j-1)*cos_thetadt
1157 ysw = yg - speed(i-1,j-1)*sin_thetadt
1158 cfl_xsw = (xg-xsw)*idx(i-1,j-1)
1159 cfl_ysw = (yg-ysw)*idy(i-1,j-1)
1161 xg = x(i,j-1); yg = y(i,j-1)
1162 xse = xg - speed(i,j-1)*cos_thetadt
1163 yse = yg - speed(i,j-1)*sin_thetadt
1164 cfl_xse = (xg-xse)*idx(i,j-1)
1165 cfl_yse = (yg-yse)*idy(i,j-1)
1167 cfl_max = max(abs(cfl_xne),abs(cfl_xnw),abs(cfl_xsw), &
1168 abs(cfl_xse),abs(cfl_yne),abs(cfl_ynw), &
1169 abs(cfl_ysw),abs(cfl_yse))
1170 if (cfl_max > 1.0)
then
1171 call mom_error(warning,
"propagate_corner_spread: CFL exceeds 1.", .true.)
1175 if (0.0 <= theta .and. theta < 0.25*twopi)
then
1178 elseif (0.25*twopi <= theta .and. theta < 0.5*twopi)
then
1181 elseif (0.5*twopi <= theta .and. theta < 0.75*twopi)
then
1184 elseif (0.75*twopi <= theta .and. theta <= 1.00*twopi)
then
1192 slopen = (yne - ynw)/(xne - xnw)
1193 bn = -slopen*xne + yne
1196 if (xnw == xsw)
then
1199 slopew = (ynw - ysw)/(xnw - xsw)
1200 bw = -slopew*xnw + ynw
1201 xw = (yw - bw)/slopew
1204 slopes = (ysw - yse)/(xsw - xse)
1205 bs = -slopes*xsw + ysw
1208 if (xne == xse)
then
1211 slopee = (yse - yne)/(xse - xne)
1212 be = -slopee*xse + yse
1213 xe = (ye - be)/slopee
1217 ane = 0.0; an = 0.0; anw = 0.0;
1218 aw = 0.0; asw = 0.0; as = 0.0;
1219 ase = 0.0; ae = 0.0; ac = 0.0;
1220 if (0.0 <= theta .and. theta < 0.25*twopi)
then
1221 xcrn = x(i-1,j-1); ycrn = y(i-1,j-1)
1223 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1224 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1225 a3 = (yw - ynw)*(0.5*(xw + xnw))
1226 a4 = (ynw - yn)*(0.5*(xnw + xn))
1227 aw = a1 + a2 + a3 + a4
1229 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1230 a2 = (ys - ysw)*(0.5*(xs + xsw))
1231 a3 = (ysw - yw)*(0.5*(xsw + xw))
1232 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1233 asw = a1 + a2 + a3 + a4
1235 a1 = (ye - yse)*(0.5*(xe + xse))
1236 a2 = (yse - ys)*(0.5*(xse + xs))
1237 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1238 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1239 as = a1 + a2 + a3 + a4
1241 a1 = (yne - ye)*(0.5*(xne + xe))
1242 a2 = (ye - ycrn)*(0.5*(xe + xcrn))
1243 a3 = (ycrn - yn)*(0.5*(xcrn + xn))
1244 a4 = (yn - yne)*(0.5*(xn + xne))
1245 ac = a1 + a2 + a3 + a4
1246 elseif (0.25*twopi <= theta .and. theta < 0.5*twopi)
then
1247 xcrn = x(i,j-1); ycrn = y(i,j-1)
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 as = 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 ase = 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 ae = a1 + a2 + a3 + a4
1267 a1 = (yn - ycrn)*(0.5*(xn + xcrn))
1268 a2 = (ycrn - yw)*(0.5*(xcrn + xw))
1269 a3 = (yw - ynw)*(0.5*(xw + xnw))
1270 a4 = (ynw - yn)*(0.5*(xnw + xn))
1271 ac = a1 + a2 + a3 + a4
1272 elseif (0.5*twopi <= theta .and. theta < 0.75*twopi)
then
1273 xcrn = x(i,j); ycrn = y(i,j)
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 ae = 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 ane = 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 an = a1 + a2 + a3 + a4
1293 a1 = (ycrn - ys)*(0.5*(xcrn + xs))
1294 a2 = (ys - ysw)*(0.5*(xs + xsw))
1295 a3 = (ysw - yw)*(0.5*(xsw + xw))
1296 a4 = (yw - ycrn)*(0.5*(xw + xcrn))
1297 ac = a1 + a2 + a3 + a4
1298 elseif (0.75*twopi <= theta .and. theta <= 1.00*twopi)
then
1299 xcrn = x(i-1,j); ycrn = y(i-1,j)
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 an = 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 anw = 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 aw = a1 + a2 + a3 + a4
1319 a1 = (ye - yse)*(0.5*(xe + xse))
1320 a2 = (yse - ys)*(0.5*(xse + xs))
1321 a3 = (ys - ycrn)*(0.5*(xs + xcrn))
1322 a4 = (ycrn - ye)*(0.5*(xcrn + xe))
1323 ac = a1 + a2 + a3 + a4
1327 a_total = ane + an + anw + aw + asw + as + ase + ae + ac
1328 e_new(m) = (ane*en(i+1,j+1) + an*en(i,j+1) + anw*en(i-1,j+1) + &
1329 aw*en(i-1,j) + asw*en(i-1,j-1) + as*en(i,j-1) + &
1330 ase*en(i+1,j-1) + ae*en(i+1,j) + ac*en(i,j)) / (dx(i,j)*dy(i,j))
1333 en(i,j) = sum(e_new)/nsubrays
1335 end subroutine propagate_corner_spread
1338 subroutine propagate_x(En, speed_x, Cgx_av, dCgx, dt, G, Nangle, CS, LB)
1340 integer,
intent(in) :: NAngle
1342 real,
dimension(G%isd:G%ied,G%jsd:G%jed,Nangle), &
1345 real,
dimension(G%IsdB:G%IedB,G%jsd:G%jed), &
1346 intent(in) :: speed_x
1348 real,
dimension(Nangle),
intent(in) :: Cgx_av
1349 real,
dimension(Nangle),
intent(in) :: dCgx
1351 real,
intent(in) :: dt
1356 real,
dimension(SZI_(G),SZJ_(G)) :: &
1358 real,
dimension(SZIB_(G),SZJ_(G)) :: &
1360 real,
dimension(SZIB_(G)) :: &
1361 cg_p, cg_m, flux1, flux2
1363 real,
dimension(SZI_(G),SZJB_(G),Nangle) :: &
1365 integer :: i, j, k, ish, ieh, jsh, jeh, a
1367 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1370 if (cs%upwind_1st)
then
1371 do j=jsh,jeh ;
do i=ish-1,ieh+1
1372 enl(i,j) = en(i,j,a) ; enr(i,j) = en(i,j,a)
1375 call ppm_reconstruction_x(en(:,:,a), enl, enr, g, lb, simple_2nd=cs%simple_2nd)
1381 cg_p(i) = speed_x(i,j) * (cgx_av(a))
1383 call zonal_flux_en(cg_p, en(:,j,a), enl(:,j), enr(:,j), flux1, &
1384 dt, g, j, ish, ieh, cs%vol_CFL)
1385 do i=ish-1,ieh ; flux_x(i,j) = flux1(i);
enddo
1388 do j=jsh,jeh ;
do i=ish,ieh
1389 fdt_m(i,j,a) = dt*flux_x(i-1,j)
1390 fdt_p(i,j,a) = -dt*flux_x(i,j)
1403 call reflect(fdt_m(:,:,:), nangle, cs, g, lb)
1404 call teleport(fdt_m(:,:,:), nangle, cs, g, lb)
1405 call reflect(fdt_p(:,:,:), nangle, cs, g, lb)
1406 call teleport(fdt_p(:,:,:), nangle, cs, g, lb)
1409 do j=jsh,jeh ;
do i=ish,ieh
1415 en(i,j,:) = en(i,j,:) + g%IareaT(i,j)*(fdt_m(i,j,:) + fdt_p(i,j,:))
1418 end subroutine propagate_x
1421 subroutine propagate_y(En, speed_y, Cgy_av, dCgy, dt, G, Nangle, CS, LB)
1423 integer,
intent(in) :: NAngle
1425 real,
dimension(G%isd:G%ied,G%jsd:G%jed,Nangle), &
1428 real,
dimension(G%isd:G%ied,G%JsdB:G%JedB), &
1429 intent(in) :: speed_y
1431 real,
dimension(Nangle),
intent(in) :: Cgy_av
1432 real,
dimension(Nangle),
intent(in) :: dCgy
1434 real,
intent(in) :: dt
1439 real,
dimension(SZI_(G),SZJ_(G)) :: &
1441 real,
dimension(SZI_(G),SZJB_(G)) :: &
1443 real,
dimension(SZI_(G)) :: &
1444 cg_p, cg_m, flux1, flux2
1446 real,
dimension(SZI_(G),SZJB_(G),Nangle) :: &
1448 character(len=160) :: mesg
1449 integer :: i, j, k, ish, ieh, jsh, jeh, a
1451 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1454 if (cs%upwind_1st)
then
1455 do j=jsh-1,jeh+1 ;
do i=ish,ieh
1456 enl(i,j) = en(i,j,a) ; enr(i,j) = en(i,j,a)
1459 call ppm_reconstruction_y(en(:,:,a), enl, enr, g, lb, simple_2nd=cs%simple_2nd)
1465 cg_p(i) = speed_y(i,j) * (cgy_av(a))
1467 call merid_flux_en(cg_p, en(:,:,a), enl(:,:), enr(:,:), flux1, &
1468 dt, g, j, ish, ieh, cs%vol_CFL)
1469 do i=ish,ieh ; flux_y(i,j) = flux1(i);
enddo
1472 do j=jsh,jeh ;
do i=ish,ieh
1473 fdt_m(i,j,a) = dt*flux_y(i,j-1)
1474 fdt_p(i,j,a) = -dt*flux_y(i,j)
1493 call reflect(fdt_m(:,:,:), nangle, cs, g, lb)
1494 call teleport(fdt_m(:,:,:), nangle, cs, g, lb)
1495 call reflect(fdt_p(:,:,:), nangle, cs, g, lb)
1496 call teleport(fdt_p(:,:,:), nangle, cs, g, lb)
1499 do j=jsh,jeh ;
do i=ish,ieh
1505 en(i,j,:) = en(i,j,:) + g%IareaT(i,j)*(fdt_m(i,j,:) + fdt_p(i,j,:))
1508 end subroutine propagate_y
1511 subroutine zonal_flux_en(u, h, hL, hR, uh, dt, G, j, ish, ieh, vol_CFL)
1513 real,
dimension(SZIB_(G)),
intent(in) :: u
1514 real,
dimension(SZI_(G)),
intent(in) :: h
1516 real,
dimension(SZI_(G)),
intent(in) :: hL
1518 real,
dimension(SZI_(G)),
intent(in) :: hR
1520 real,
dimension(SZIB_(G)),
intent(inout) :: uh
1521 real,
intent(in) :: dt
1522 integer,
intent(in) :: j
1523 integer,
intent(in) :: ish
1524 integer,
intent(in) :: ieh
1525 logical,
intent(in) :: vol_CFL
1535 if (u(i) > 0.0)
then
1536 if (vol_cfl)
then ; cfl = (u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i,j))
1537 else ; cfl = u(i) * dt * g%IdxT(i,j) ;
endif
1538 curv_3 = (hl(i) + hr(i)) - 2.0*h(i)
1539 uh(i) = g%dy_Cu(i,j) * u(i) * &
1540 (hr(i) + cfl * (0.5*(hl(i) - hr(i)) + curv_3*(cfl - 1.5)))
1541 elseif (u(i) < 0.0)
then
1542 if (vol_cfl)
then ; cfl = (-u(i) * dt) * (g%dy_Cu(i,j) * g%IareaT(i+1,j))
1543 else ; cfl = -u(i) * dt * g%IdxT(i+1,j) ;
endif
1544 curv_3 = (hl(i+1) + hr(i+1)) - 2.0*h(i+1)
1545 uh(i) = g%dy_Cu(i,j) * u(i) * &
1546 (hl(i+1) + cfl * (0.5*(hr(i+1)-hl(i+1)) + curv_3*(cfl - 1.5)))
1551 end subroutine zonal_flux_en
1554 subroutine merid_flux_en(v, h, hL, hR, vh, dt, G, J, ish, ieh, vol_CFL)
1556 real,
dimension(SZI_(G)),
intent(in) :: v
1557 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h
1559 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: hL
1561 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: hR
1563 real,
dimension(SZI_(G)),
intent(inout) :: vh
1564 real,
intent(in) :: dt
1565 integer,
intent(in) :: J
1566 integer,
intent(in) :: ish
1567 integer,
intent(in) :: ieh
1568 logical,
intent(in) :: vol_CFL
1578 if (v(i) > 0.0)
then
1579 if (vol_cfl)
then ; cfl = (v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j))
1580 else ; cfl = v(i) * dt * g%IdyT(i,j) ;
endif
1581 curv_3 = hl(i,j) + hr(i,j) - 2.0*h(i,j)
1582 vh(i) = g%dx_Cv(i,j) * v(i) * ( hr(i,j) + cfl * &
1583 (0.5*(hl(i,j) - hr(i,j)) + curv_3*(cfl - 1.5)) )
1584 elseif (v(i) < 0.0)
then
1585 if (vol_cfl)
then ; cfl = (-v(i) * dt) * (g%dx_Cv(i,j) * g%IareaT(i,j+1))
1586 else ; cfl = -v(i) * dt * g%IdyT(i,j+1) ;
endif
1587 curv_3 = hl(i,j+1) + hr(i,j+1) - 2.0*h(i,j+1)
1588 vh(i) = g%dx_Cv(i,j) * v(i) * ( hl(i,j+1) + cfl * &
1589 (0.5*(hr(i,j+1)-hl(i,j+1)) + curv_3*(cfl - 1.5)) )
1594 end subroutine merid_flux_en
1597 subroutine reflect(En, NAngle, CS, G, LB)
1599 integer,
intent(in) :: NAngle
1601 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
1609 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: angle_c
1611 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: part_refl
1614 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: ridge
1620 real,
dimension(1:NAngle) :: angle_i
1622 real,
dimension(1:Nangle) :: En_reflected
1623 integer :: i, j, a, a_r, na
1626 integer :: isc, iec, jsc, jec
1628 integer :: ish, ieh, jsh, jeh
1630 integer :: id_g, jd_g
1633 isc = g%isc ; iec = g%iec ; jsc = g%jsc ; jec = g%jec
1634 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1636 twopi = 8.0*atan(1.0)
1637 angle_size = twopi / (real(nangle))
1642 angle_i(a) = angle_size * real(a - 1)
1645 angle_c = cs%refl_angle
1646 part_refl = cs%refl_pref
1648 en_reflected(:) = 0.0
1657 if (angle_c(i,j) /= cs%nullangle)
then
1659 if (en(i,j,a) > 0.0)
then
1661 if (sin(angle_i(a) - angle_c(i,j)) >= 0.0)
then
1662 angle_wall = angle_c(i,j)
1664 elseif (ridge(i,j))
then
1665 angle_wall = angle_c(i,j) + 0.5*twopi
1666 if (angle_wall > twopi)
then
1667 angle_wall = angle_wall - twopi*floor(abs(angle_wall)/twopi)
1668 elseif (angle_wall < 0.0)
then
1669 angle_wall = angle_wall + twopi*ceiling(abs(angle_wall)/twopi)
1673 angle_wall = angle_c(i,j)
1676 if (sin(angle_i(a) - angle_wall) >= 0.0)
then
1677 angle_r = 2.0*angle_wall - angle_i(a)
1678 if (angle_r > twopi)
then
1679 angle_r = angle_r - twopi*floor(abs(angle_r)/twopi)
1680 elseif (angle_r < 0.0)
then
1681 angle_r = angle_r + twopi*ceiling(abs(angle_r)/twopi)
1683 a_r = nint(angle_r/angle_size) + 1
1684 do while (a_r > nangle) ; a_r = a_r - nangle ;
enddo
1686 en_reflected(a_r) = part_refl(i,j)*en(i,j,a)
1687 en(i,j,a) = (1.0-part_refl(i,j))*en(i,j,a)
1692 en(i,j,:) = en(i,j,:) + en_reflected(:)
1693 en_reflected(:) = 0.0
1707 end subroutine reflect
1711 subroutine teleport(En, NAngle, CS, G, LB)
1713 integer,
intent(in) :: NAngle
1715 real,
dimension(G%isd:G%ied,G%jsd:G%jed,NAngle), &
1723 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: angle_c
1725 real,
dimension(G%isd:G%ied,G%jsd:G%jed) :: part_refl
1728 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: pref_cell
1730 logical,
dimension(G%isd:G%ied,G%jsd:G%jed) :: ridge
1734 real,
dimension(1:NAngle) :: angle_i
1735 real,
dimension(1:NAngle) :: cos_angle, sin_angle
1737 character(len=160) :: mesg
1743 integer :: ish, ieh, jsh, jeh
1745 integer :: id_g, jd_g
1747 real :: cos_normal, sin_normal, angle_wall
1752 ish = lb%ish ; ieh = lb%ieh ; jsh = lb%jsh ; jeh = lb%jeh
1754 twopi = 8.0*atan(1.0)
1755 angle_size = twopi / (real(nangle))
1760 angle_i(a) = angle_size * real(a - 1)
1761 cos_angle(a) = cos(angle_i(a)) ; sin_angle(a) = sin(angle_i(a))
1764 angle_c = cs%refl_angle
1765 part_refl = cs%refl_pref
1766 pref_cell = cs%refl_pref_logical
1771 id_g = i + g%idg_offset ; jd_g = j + g%jdg_offset
1772 if (pref_cell(i,j))
then
1774 if (en(i,j,a) > 0)
then
1776 if (sin(angle_i(a) - angle_c(i,j)) >= 0.0)
then
1777 angle_wall = angle_c(i,j)
1779 elseif (ridge(i,j))
then
1780 angle_wall = angle_c(i,j) + 0.5*twopi
1783 angle_wall = angle_c(i,j)
1786 if (sin(angle_i(a) - angle_wall) >= 0.0)
then
1788 cos_normal = cos(angle_wall + 0.25*twopi)
1789 sin_normal = sin(angle_wall + 0.25*twopi)
1791 ios = int(sign(1.,cos_normal))
1793 jos = int(sign(1.,sin_normal))
1795 if (.not. pref_cell(i+ios,j+jos))
then
1796 en(i,j,a) = en(i,j,a) - en_tele
1797 en(i+ios,j+jos,a) = en(i+ios,j+jos,a) + en_tele
1799 write(mesg,*)
'idg=',id_g,
'jd_g=',jd_g,
'a=',a
1800 call mom_error(fatal,
"teleport: no receptive ocean cell at "//trim(mesg), .true.)
1809 end subroutine teleport
1813 subroutine correct_halo_rotation(En, test, G, NAngle)
1815 real,
dimension(:,:,:,:,:),
intent(inout) :: En
1818 real,
dimension(SZI_(G),SZJ_(G),2), &
1822 integer,
intent(in) :: NAngle
1825 real,
dimension(G%isd:G%ied,NAngle) :: En2d
1826 integer,
dimension(G%isd:G%ied) :: a_shift
1827 integer :: i_first, i_last, a_new
1828 integer :: a, i, j, isd, ied, jsd, jed, m, fr
1829 character(len=160) :: mesg
1830 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1833 i_first = ied+1 ; i_last = isd-1
1836 if (test(i,j,1) /= 1.0)
then
1837 if (i<i_first) i_first = i
1838 if (i>i_last) i_last = i
1840 if (test(i,j,1) == -1.0)
then ; a_shift(i) = nangle/2
1841 elseif (test(i,j,2) == 1.0)
then ; a_shift(i) = -nangle/4
1842 elseif (test(i,j,2) == -1.0)
then ; a_shift(i) = nangle/4
1844 write(mesg,
'("Unrecognized rotation test vector ",2ES9.2," at ",F7.2," E, ",&
1845 &F7.2," N; i,j=",2i4)') &
1846 test(i,j,1), test(i,j,2), g%GeoLonT(i,j), g%GeoLatT(i,j), i, j
1847 call mom_error(fatal, mesg)
1852 if (i_first <= i_last)
then
1854 do m=1,
size(en,5) ;
do fr=1,
size(en,4)
1855 do a=1,nangle ;
do i=i_first,i_last ;
if (a_shift(i) /= 0)
then
1856 a_new = a + a_shift(i)
1857 if (a_new < 1) a_new = a_new + nangle
1858 if (a_new > nangle) a_new = a_new - nangle
1859 en2d(i,a_new) = en(i,j,a,fr,m)
1860 endif ;
enddo ;
enddo
1861 do a=1,nangle ;
do i=i_first,i_last ;
if (a_shift(i) /= 0)
then
1862 en(i,j,a,fr,m) = en2d(i,a)
1863 endif ;
enddo ;
enddo
1867 end subroutine correct_halo_rotation
1870 subroutine ppm_reconstruction_x(h_in, h_l, h_r, G, LB, simple_2nd)
1872 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1873 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_l
1874 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_r
1876 logical,
optional,
intent(in) :: simple_2nd
1880 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1881 real,
parameter :: oneSixth = 1./6.
1882 real :: h_ip1, h_im1
1884 logical :: use_CW84, use_2nd
1885 character(len=256) :: mesg
1886 integer :: i, j, isl, iel, jsl, jel, stencil
1888 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1889 isl = lb%ish-1 ; iel = lb%ieh+1 ; jsl = lb%jsh ; jel = lb%jeh
1892 stencil = 2 ;
if (use_2nd) stencil = 1
1894 if ((isl-stencil < g%isd) .or. (iel+stencil > g%ied))
then
1895 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_x called with a ", &
1896 & "x-halo that needs to be increased by ",i2,".")') &
1897 stencil + max(g%isd-isl,iel-g%ied)
1898 call mom_error(fatal,mesg)
1900 if ((jsl < g%jsd) .or. (jel > g%jed))
then
1901 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_x called with a ", &
1902 & "y-halo that needs to be increased by ",i2,".")') &
1903 max(g%jsd-jsl,jel-g%jed)
1904 call mom_error(fatal,mesg)
1908 do j=jsl,jel ;
do i=isl,iel
1909 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1910 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1911 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) )
1912 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) )
1915 do j=jsl,jel ;
do i=isl-1,iel+1
1916 if ((g%mask2dT(i-1,j) * g%mask2dT(i,j) * g%mask2dT(i+1,j)) == 0.0)
then
1920 slp(i,j) = 0.5 * (h_in(i+1,j) - h_in(i-1,j))
1922 dmx = max(h_in(i+1,j), h_in(i-1,j), h_in(i,j)) - h_in(i,j)
1923 dmn = h_in(i,j) - min(h_in(i+1,j), h_in(i-1,j), h_in(i,j))
1924 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
1929 do j=jsl,jel ;
do i=isl,iel
1934 h_im1 = g%mask2dT(i-1,j) * h_in(i-1,j) + (1.0-g%mask2dT(i-1,j)) * h_in(i,j)
1935 h_ip1 = g%mask2dT(i+1,j) * h_in(i+1,j) + (1.0-g%mask2dT(i+1,j)) * h_in(i,j)
1937 h_l(i,j) = 0.5*( h_im1 + h_in(i,j) ) + onesixth*( slp(i-1,j) - slp(i,j) )
1938 h_r(i,j) = 0.5*( h_ip1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i+1,j) )
1942 call ppm_limit_pos(h_in, h_l, h_r, 0.0, g, isl, iel, jsl, jel)
1943 end subroutine ppm_reconstruction_x
1946 subroutine ppm_reconstruction_y(h_in, h_l, h_r, G, LB, simple_2nd)
1948 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
1949 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_l
1950 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: h_r
1952 logical,
optional,
intent(in) :: simple_2nd
1956 real,
dimension(SZI_(G),SZJ_(G)) :: slp
1957 real,
parameter :: oneSixth = 1./6.
1958 real :: h_jp1, h_jm1
1961 character(len=256) :: mesg
1962 integer :: i, j, isl, iel, jsl, jel, stencil
1964 use_2nd = .false. ;
if (
present(simple_2nd)) use_2nd = simple_2nd
1965 isl = lb%ish ; iel = lb%ieh ; jsl = lb%jsh-1 ; jel = lb%jeh+1
1968 stencil = 2 ;
if (use_2nd) stencil = 1
1970 if ((isl < g%isd) .or. (iel > g%ied))
then
1971 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_y called with a ", &
1972 & "x-halo that needs to be increased by ",i2,".")') &
1973 max(g%isd-isl,iel-g%ied)
1974 call mom_error(fatal,mesg)
1976 if ((jsl-stencil < g%jsd) .or. (jel+stencil > g%jed))
then
1977 write(mesg,
'("In MOM_internal_tides, PPM_reconstruction_y called with a ", &
1978 & "y-halo that needs to be increased by ",i2,".")') &
1979 stencil + max(g%jsd-jsl,jel-g%jed)
1980 call mom_error(fatal,mesg)
1984 do j=jsl,jel ;
do i=isl,iel
1985 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
1986 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
1987 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) )
1988 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) )
1991 do j=jsl-1,jel+1 ;
do i=isl,iel
1992 if ((g%mask2dT(i,j-1) * g%mask2dT(i,j) * g%mask2dT(i,j+1)) == 0.0)
then
1996 slp(i,j) = 0.5 * (h_in(i,j+1) - h_in(i,j-1))
1998 dmx = max(h_in(i,j+1), h_in(i,j-1), h_in(i,j)) - h_in(i,j)
1999 dmn = h_in(i,j) - min(h_in(i,j+1), h_in(i,j-1), h_in(i,j))
2000 slp(i,j) = sign(1.,slp(i,j)) * min(abs(slp(i,j)), 2. * min(dmx, dmn))
2005 do j=jsl,jel ;
do i=isl,iel
2008 h_jm1 = g%mask2dT(i,j-1) * h_in(i,j-1) + (1.0-g%mask2dT(i,j-1)) * h_in(i,j)
2009 h_jp1 = g%mask2dT(i,j+1) * h_in(i,j+1) + (1.0-g%mask2dT(i,j+1)) * h_in(i,j)
2011 h_l(i,j) = 0.5*( h_jm1 + h_in(i,j) ) + onesixth*( slp(i,j-1) - slp(i,j) )
2012 h_r(i,j) = 0.5*( h_jp1 + h_in(i,j) ) + onesixth*( slp(i,j) - slp(i,j+1) )
2016 call ppm_limit_pos(h_in, h_l, h_r, 0.0, g, isl, iel, jsl, jel)
2017 end subroutine ppm_reconstruction_y
2023 subroutine ppm_limit_pos(h_in, h_L, h_R, h_min, G, iis, iie, jis, jie)
2025 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: h_in
2026 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_L
2027 real,
dimension(SZI_(G),SZJ_(G)),
intent(inout) :: h_R
2028 real,
intent(in) :: h_min
2030 integer,
intent(in) :: iis
2031 integer,
intent(in) :: iie
2032 integer,
intent(in) :: jis
2033 integer,
intent(in) :: jie
2035 real :: curv, dh, scale
2036 character(len=256) :: mesg
2039 do j=jis,jie ;
do i=iis,iie
2042 curv = 3.0*(h_l(i,j) + h_r(i,j) - 2.0*h_in(i,j))
2043 if (curv > 0.0)
then
2044 dh = h_r(i,j) - h_l(i,j)
2045 if (abs(dh) < curv)
then
2046 if (h_in(i,j) <= h_min)
then
2047 h_l(i,j) = h_in(i,j) ; h_r(i,j) = h_in(i,j)
2048 elseif (12.0*curv*(h_in(i,j) - h_min) < (curv**2 + 3.0*dh**2))
then
2051 scale = 12.0*curv*(h_in(i,j) - h_min) / (curv**2 + 3.0*dh**2)
2052 h_l(i,j) = h_in(i,j) + scale*(h_l(i,j) - h_in(i,j))
2053 h_r(i,j) = h_in(i,j) + scale*(h_r(i,j) - h_in(i,j))
2058 end subroutine ppm_limit_pos
2103 subroutine internal_tides_init(Time, G, GV, US, param_file, diag, CS)
2104 type(time_type),
target,
intent(in) :: time
2110 type(
diag_ctrl),
target,
intent(in) :: diag
2116 real,
allocatable :: angles(:)
2117 real,
allocatable,
dimension(:,:) :: h2
2118 real :: kappa_itides, kappa_h2_factor
2121 real,
allocatable :: ridge_temp(:,:)
2124 logical :: use_int_tides, use_temperature
2125 integer :: num_angle, num_freq, num_mode, m, fr, period_1
2126 integer :: isd, ied, jsd, jed, a, id_ang, i, j
2129 #include "version_variable.h"
2130 character(len=40) :: mdl =
"MOM_internal_tides"
2131 character(len=16),
dimension(8) :: freq_name
2132 character(len=40) :: var_name
2133 character(len=160) :: var_descript
2134 character(len=200) :: filename
2135 character(len=200) :: refl_angle_file, land_mask_file
2136 character(len=200) :: refl_pref_file, refl_dbl_file
2137 character(len=200) :: dy_cu_file, dx_cv_file
2138 character(len=200) :: h2_file
2140 isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2142 if (
associated(cs))
then
2143 call mom_error(warning,
"internal_tides_init called "//&
2144 "with an associated control structure.")
2150 use_int_tides = .false.
2151 call read_param(param_file,
"INTERNAL_TIDES", use_int_tides)
2152 cs%do_int_tides = use_int_tides
2153 if (.not.use_int_tides)
return
2155 use_temperature = .true.
2156 call read_param(param_file,
"ENABLE_THERMODYNAMICS", use_temperature)
2157 if (.not.use_temperature)
call mom_error(fatal, &
2158 "register_int_tide_restarts: internal_tides only works with "//&
2159 "ENABLE_THERMODYNAMICS defined.")
2162 num_freq = 1 ; num_angle = 24 ; num_mode = 1
2163 call read_param(param_file,
"INTERNAL_TIDE_FREQS", num_freq)
2164 call read_param(param_file,
"INTERNAL_TIDE_ANGLES", num_angle)
2165 call read_param(param_file,
"INTERNAL_TIDE_MODES", num_mode)
2166 if (.not.((num_freq > 0) .and. (num_angle > 0) .and. (num_mode > 0)))
return
2167 cs%nFreq = num_freq ; cs%nAngle = num_angle ; cs%nMode = num_mode
2170 allocate(cs%En(isd:ied, jsd:jed, num_angle, num_freq, num_mode))
2171 cs%En(:,:,:,:,:) = 0.0
2174 allocate(cs%cp(isd:ied, jsd:jed, num_freq, num_mode))
2175 cs%cp(:,:,:,:) = 0.0
2178 allocate(cs%frequency(num_freq))
2179 call read_param(param_file,
"FIRST_MODE_PERIOD", period_1);
2181 cs%frequency(fr) = (8.0*atan(1.0) * (real(fr)) / period_1)
2188 call get_param(param_file, mdl,
"INPUTDIR", cs%inputdir, default=
".")
2189 cs%inputdir = slasher(cs%inputdir)
2193 call get_param(param_file, mdl,
"INTERNAL_TIDE_FREQS", num_freq, &
2194 "The number of distinct internal tide frequency bands "//&
2195 "that will be calculated.", default=1)
2196 call get_param(param_file, mdl,
"INTERNAL_TIDE_MODES", num_mode, &
2197 "The number of distinct internal tide modes "//&
2198 "that will be calculated.", default=1)
2199 call get_param(param_file, mdl,
"INTERNAL_TIDE_ANGLES", num_angle, &
2200 "The number of angular resolution bands for the internal "//&
2201 "tide calculations.", default=24)
2203 if (use_int_tides)
then
2204 if ((num_freq <= 0) .and. (num_mode <= 0) .and. (num_angle <= 0))
then
2205 call mom_error(warning,
"Internal tides were enabled, but the number "//&
2206 "of requested frequencies, modes and angles were not all positive.")
2210 if ((num_freq > 0) .and. (num_mode > 0) .and. (num_angle > 0))
then
2211 call mom_error(warning,
"Internal tides were not enabled, even though "//&
2212 "the number of requested frequencies, modes and angles were all "//&
2218 if (cs%NFreq /= num_freq)
call mom_error(fatal,
"Internal_tides_init: "//&
2219 "Inconsistent number of frequencies.")
2220 if (cs%NAngle /= num_angle)
call mom_error(fatal,
"Internal_tides_init: "//&
2221 "Inconsistent number of angles.")
2222 if (cs%NMode /= num_mode)
call mom_error(fatal,
"Internal_tides_init: "//&
2223 "Inconsistent number of modes.")
2224 if (4*(num_angle/4) /= num_angle)
call mom_error(fatal, &
2225 "Internal_tides_init: INTERNAL_TIDE_ANGLES must be a multiple of 4.")
2229 call get_param(param_file, mdl,
"INTERNAL_TIDE_DECAY_RATE", cs%decay_rate, &
2230 "The rate at which internal tide energy is lost to the "//&
2231 "interior ocean internal wave field.", units=
"s-1", default=0.0)
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))
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*&
2319 kappa_itides * h2(i,j)
2325 call get_param(param_file, mdl,
"REFL_ANGLE_FILE", refl_angle_file, &
2326 "The path to the file containing the local angle of "//&
2327 "the coastline/ridge/shelf with respect to the equator.", &
2328 fail_if_missing=.false.)
2329 filename = trim(cs%inputdir) // trim(refl_angle_file)
2330 call log_param(param_file, mdl,
"INPUTDIR/REFL_ANGLE_FILE", filename)
2331 allocate(cs%refl_angle(isd:ied,jsd:jed)) ; cs%refl_angle(:,:) = cs%nullangle
2333 g%domain, timelevel=1)
2335 do j=g%jsc,g%jec ;
do i=g%isc,g%iec
2336 if (is_nan(cs%refl_angle(i,j))) cs%refl_angle(i,j) = cs%nullangle
2338 call pass_var(cs%refl_angle,g%domain)
2341 call get_param(param_file, mdl,
"REFL_PREF_FILE", refl_pref_file, &
2342 "The path to the file containing the reflection coefficients.", &
2343 fail_if_missing=.false.)
2344 filename = trim(cs%inputdir) // trim(refl_pref_file)
2345 call log_param(param_file, mdl,
"INPUTDIR/REFL_PREF_FILE", filename)
2346 allocate(cs%refl_pref(isd:ied,jsd:jed)) ; cs%refl_pref(:,:) = 1.0
2347 call mom_read_data(filename,
'refl_pref', cs%refl_pref, g%domain, timelevel=1)
2349 call pass_var(cs%refl_pref,g%domain)
2352 allocate(cs%refl_pref_logical(isd:ied,jsd:jed)) ; cs%refl_pref_logical(:,:) = .false.
2356 if (cs%refl_angle(i,j) /= cs%nullangle .and. &
2357 cs%refl_pref(i,j) < 1.0 .and. cs%refl_pref(i,j) > 0.0)
then
2358 cs%refl_pref_logical(i,j) = .true.
2364 call get_param(param_file, mdl,
"REFL_DBL_FILE", refl_dbl_file, &
2365 "The path to the file containing the double-reflective ridge tags.", &
2366 fail_if_missing=.false.)
2367 filename = trim(cs%inputdir) // trim(refl_dbl_file)
2368 call log_param(param_file, mdl,
"INPUTDIR/REFL_DBL_FILE", filename)
2369 allocate(ridge_temp(isd:ied,jsd:jed)) ; ridge_temp(:,:) = 0.0
2370 call mom_read_data(filename,
'refl_dbl', ridge_temp, g%domain, timelevel=1)
2372 allocate(cs%refl_dbl(isd:ied,jsd:jed)) ; cs%refl_dbl(:,:) = .false.
2373 do i=isd,ied;
do j=jsd,jed
2374 if (ridge_temp(i,j) == 1) then; cs%refl_dbl(i,j) = .true.
2375 else ; cs%refl_dbl(i,j) = .false. ;
endif
2415 cs%id_refl_ang = register_diag_field(
'ocean_model',
'refl_angle', diag%axesT1, &
2416 time,
'Local angle of coastline/ridge/shelf with respect to equator',
'rad')
2417 cs%id_refl_pref = register_diag_field(
'ocean_model',
'refl_pref', diag%axesT1, &
2418 time,
'Partial reflection coefficients',
'')
2419 cs%id_dx_Cv = register_diag_field(
'ocean_model',
'dx_Cv', diag%axesT1, &
2420 time,
'North face unblocked width',
'm')
2421 cs%id_dy_Cu = register_diag_field(
'ocean_model',
'dy_Cu', diag%axesT1, &
2422 time,
'East face unblocked width',
'm')
2423 cs%id_land_mask = register_diag_field(
'ocean_model',
'land_mask', diag%axesT1, &
2424 time,
'Land mask',
'logical')
2426 if (cs%id_refl_ang > 0)
call post_data(cs%id_refl_ang, cs%refl_angle, cs%diag)
2427 if (cs%id_refl_pref > 0)
call post_data(cs%id_refl_pref, cs%refl_pref, cs%diag)
2428 if (cs%id_dx_Cv > 0)
call post_data(cs%id_dx_Cv, g%dx_Cv, cs%diag)
2429 if (cs%id_dy_Cu > 0)
call post_data(cs%id_dy_Cu, g%dy_Cu, cs%diag)
2430 if (cs%id_land_mask > 0)
call post_data(cs%id_land_mask, g%mask2dT, cs%diag)
2433 cs%id_tot_En = register_diag_field(
'ocean_model',
'ITide_tot_En', diag%axesT1, &
2434 time,
'Internal tide total energy density',
'J m-2')
2436 cs%id_itide_drag = register_diag_field(
'ocean_model',
'ITide_drag', diag%axesT1, &
2437 time,
'Interior and bottom drag internal tide decay timescale',
's-1')
2439 cs%id_TKE_itidal_input = register_diag_field(
'ocean_model',
'TKE_itidal_input', diag%axesT1, &
2440 time,
'Conversion from barotropic to baroclinic tide, '//&
2441 'a fraction of which goes into rays',
'W m-2')
2443 cs%id_tot_leak_loss = register_diag_field(
'ocean_model',
'ITide_tot_leak_loss', diag%axesT1, &
2444 time,
'Internal tide energy loss to background drag',
'W m-2')
2445 cs%id_tot_quad_loss = register_diag_field(
'ocean_model',
'ITide_tot_quad_loss', diag%axesT1, &
2446 time,
'Internal tide energy loss to bottom drag',
'W m-2')
2447 cs%id_tot_itidal_loss = register_diag_field(
'ocean_model',
'ITide_tot_itidal_loss', diag%axesT1, &
2448 time,
'Internal tide energy loss to wave drag',
'W m-2')
2449 cs%id_tot_Froude_loss = register_diag_field(
'ocean_model',
'ITide_tot_Froude_loss', diag%axesT1, &
2450 time,
'Internal tide energy loss to wave breaking',
'W m-2')
2451 cs%id_tot_allprocesses_loss = register_diag_field(
'ocean_model',
'ITide_tot_allprocesses_loss', diag%axesT1, &
2452 time,
'Internal tide energy loss summed over all processes',
'W m-2')
2454 allocate(cs%id_En_mode(cs%nFreq,cs%nMode)) ; cs%id_En_mode(:,:) = -1
2455 allocate(cs%id_En_ang_mode(cs%nFreq,cs%nMode)) ; cs%id_En_ang_mode(:,:) = -1
2456 allocate(cs%id_itidal_loss_mode(cs%nFreq,cs%nMode)) ; cs%id_itidal_loss_mode(:,:) = -1
2457 allocate(cs%id_allprocesses_loss_mode(cs%nFreq,cs%nMode)) ; cs%id_allprocesses_loss_mode(:,:) = -1
2458 allocate(cs%id_itidal_loss_ang_mode(cs%nFreq,cs%nMode)) ; cs%id_itidal_loss_ang_mode(:,:) = -1
2459 allocate(cs%id_Ub_mode(cs%nFreq,cs%nMode)) ; cs%id_Ub_mode(:,:) = -1
2460 allocate(cs%id_cp_mode(cs%nFreq,cs%nMode)) ; cs%id_cp_mode(:,:) = -1
2462 allocate(angles(cs%NAngle)) ; angles(:) = 0.0
2463 angle_size = (8.0*atan(1.0)) / (real(num_angle))
2464 do a=1,num_angle ; angles(a) = (real(a) - 1) * angle_size ;
enddo
2466 id_ang = diag_axis_init(
"angle", angles,
"Radians",
"N",
"Angular Orienation of Fluxes")
2467 call define_axes_group(diag, (/ diag%axesT1%handles(1), diag%axesT1%handles(2), id_ang /), axes_ang)
2469 do fr=1,cs%nFreq ;
write(freq_name(fr),
'("freq",i1)') fr ;
enddo
2470 do m=1,cs%nMode ;
do fr=1,cs%nFreq
2472 write(var_name,
'("Itide_En_freq",i1,"_mode",i1)') fr, m
2473 write(var_descript,
'("Internal tide energy density in frequency ",i1," mode ",i1)') fr, m
2474 cs%id_En_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2475 diag%axesT1, time, var_descript,
'J m-2')
2476 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2479 write(var_name,
'("Itide_En_ang_freq",i1,"_mode",i1)') fr, m
2480 write(var_descript,
'("Internal tide angular energy density in frequency ",i1," mode ",i1)') fr, m
2481 cs%id_En_ang_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2482 axes_ang, time, var_descript,
'J m-2 band-1')
2483 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2487 write(var_name,
'("Itide_wavedrag_loss_freq",i1,"_mode",i1)') fr, m
2488 write(var_descript,
'("Internal tide energy loss due to wave-drag from frequency ",i1," mode ",i1)') fr, m
2489 cs%id_itidal_loss_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2490 diag%axesT1, time, var_descript,
'W m-2')
2491 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2493 write(var_name,
'("Itide_allprocesses_loss_freq",i1,"_mode",i1)') fr, m
2494 write(var_descript,
'("Internal tide energy loss due to all processes from frequency ",i1," mode ",i1)') fr, m
2495 cs%id_allprocesses_loss_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2496 diag%axesT1, time, var_descript,
'W m-2')
2497 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2501 write(var_name,
'("Itide_wavedrag_loss_ang_freq",i1,"_mode",i1)') fr, m
2502 write(var_descript,
'("Internal tide energy loss due to wave-drag from frequency ",i1," mode ",i1)') fr, m
2503 cs%id_itidal_loss_ang_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2504 axes_ang, time, var_descript,
'W m-2 band-1')
2505 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2508 write(var_name,
'("Itide_Ub_freq",i1,"_mode",i1)') fr, m
2509 write(var_descript,
'("Near-bottom horizonal velocity for frequency ",i1," mode ",i1)') fr, m
2510 cs%id_Ub_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2511 diag%axesT1, time, var_descript,
'm s-1')
2512 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2515 write(var_name,
'("Itide_cp_freq",i1,"_mode",i1)') fr, m
2516 write(var_descript,
'("Horizonal phase velocity for frequency ",i1," mode ",i1)') fr, m
2517 cs%id_cp_mode(fr,m) = register_diag_field(
'ocean_model', var_name, &
2518 diag%axesT1, time, var_descript,
'm s-1')
2519 call mom_mesg(
"Registering "//trim(var_name)//
", Described as: "//var_descript, 5)
2524 call wave_structure_init(time, g, param_file, diag, cs%wave_structure_CSp)
2526 end subroutine internal_tides_init
2529 subroutine internal_tides_end(CS)
2533 if (
associated(cs))
then
2534 if (
associated(cs%En))
deallocate(cs%En)
2535 if (
allocated(cs%frequency))
deallocate(cs%frequency)
2536 if (
allocated(cs%id_En_mode))
deallocate(cs%id_En_mode)
2537 if (
allocated(cs%id_Ub_mode))
deallocate(cs%id_Ub_mode)
2538 if (
allocated(cs%id_cp_mode))
deallocate(cs%id_cp_mode)
2542 end subroutine internal_tides_end