This subroutine determines the internal wave velocity structure for any mode.
95 type(verticalgrid_type),
intent(in) :: gv
97 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
99 type(thermo_var_ptrs),
intent(in) :: tv
101 real,
dimension(SZI_(G),SZJ_(G)),
intent(in) :: cn
104 integer,
intent(in) :: modenum
105 real,
intent(in) :: freq
106 type(wave_structure_cs),
pointer :: cs
109 real,
dimension(SZI_(G),SZJ_(G)), &
110 optional,
intent(in) :: en
112 logical,
optional,
intent(in) :: full_halos
155 real,
dimension(SZK_(G)+1) :: &
157 pres, t_int, s_int, &
159 real,
dimension(SZK_(G)) :: &
163 real,
dimension(SZK_(G),SZI_(G)) :: &
165 real,
dimension(SZK_(G)) :: &
168 real,
dimension(SZI_(G),SZJ_(G)) :: &
174 real,
dimension(SZI_(G)) :: &
176 h_here, hxt_here, hxs_here, hxr_here
178 real :: i_hnew, drxh_sum
179 real,
parameter :: tol1 = 0.0001, tol2 = 0.001
180 real,
pointer,
dimension(:,:,:) :: t, s
182 real :: rescale, i_rescale
183 integer :: kf(szi_(g))
184 integer,
parameter :: max_itt = 1
185 real,
parameter :: cg_subro = 1e-100
186 real,
parameter :: a_int = 0.5
192 real,
dimension(SZK_(G)+1) :: w_strct, u_strct, w_profile, uavg_profile, z_int, n2
195 real,
dimension(SZK_(G)+1) :: w_strct2, u_strct2
197 real,
dimension(SZK_(G)) :: dz
198 real,
dimension(SZK_(G)+1) :: dwdz_profile
200 real :: int_dwdz2, int_w2, int_n2w2, ke_term, pe_term, w0
202 real,
dimension(SZK_(G)-1) :: lam_z
204 real,
dimension(SZK_(G)-1) :: a_diag, b_diag, c_diag
207 real,
dimension(SZK_(G)-1) :: e_guess
208 real,
dimension(SZK_(G)-1) :: e_itt
211 integer :: i, j, k, k2, itt, is, ie, js, je, nz, nzm, row, ig, jg, ig_stop, jg_stop
213 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
217 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_wave_structure: "// &
218 "Module must be initialized before it is used.")
221 if (
present(full_halos))
then ;
if (full_halos)
then 222 is = g%isd ; ie = g%ied ; js = g%jsd ; je = g%jed
227 s => tv%S ; t => tv%T
228 g_rho0 = gv%g_Earth/gv%Rho0
229 use_eos =
associated(tv%eqn_of_state)
231 h_to_pres = gv%g_Earth * gv%Rho0
233 rescale = 1024.0**4 ; i_rescale = 1.0/rescale
235 min_h_frac = tol1 /
real(nz)
241 do i=is,ie ; htot(i,j) = 0.0 ;
enddo 242 do k=1,nz ;
do i=is,ie ; htot(i,j) = htot(i,j) + h(i,j,k)*h_to_m ;
enddo ;
enddo 245 hmin(i) = htot(i,j)*min_h_frac ; kf(i) = 1 ; h_here(i) = 0.0
246 hxt_here(i) = 0.0 ; hxs_here(i) = 0.0 ; hxr_here(i) = 0.0
249 do k=1,nz ;
do i=is,ie
250 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*h_to_m > hmin(i)))
then 251 hf(kf(i),i) = h_here(i)
252 tf(kf(i),i) = hxt_here(i) / h_here(i)
253 sf(kf(i),i) = hxs_here(i) / h_here(i)
257 h_here(i) = h(i,j,k)*h_to_m
258 hxt_here(i) = (h(i,j,k)*h_to_m)*t(i,j,k)
259 hxs_here(i) = (h(i,j,k)*h_to_m)*s(i,j,k)
261 h_here(i) = h_here(i) + h(i,j,k)*h_to_m
262 hxt_here(i) = hxt_here(i) + (h(i,j,k)*h_to_m)*t(i,j,k)
263 hxs_here(i) = hxs_here(i) + (h(i,j,k)*h_to_m)*s(i,j,k)
266 do i=is,ie ;
if (h_here(i) > 0.0)
then 267 hf(kf(i),i) = h_here(i)
268 tf(kf(i),i) = hxt_here(i) / h_here(i)
269 sf(kf(i),i) = hxs_here(i) / h_here(i)
272 do k=1,nz ;
do i=is,ie
273 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*h_to_m > hmin(i)))
then 274 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
278 h_here(i) = h(i,j,k)*h_to_m
279 hxr_here(i) = (h(i,j,k)*h_to_m)*gv%Rlay(k)
281 h_here(i) = h_here(i) + h(i,j,k)*h_to_m
282 hxr_here(i) = hxr_here(i) + (h(i,j,k)*h_to_m)*gv%Rlay(k)
285 do i=is,ie ;
if (h_here(i) > 0.0)
then 286 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
292 do i=is,ie ;
if(cn(i,j)>0.0)
then 294 ig = i + g%idg_offset ; jg = j + g%jdg_offset
297 if (g%mask2dT(i,j) > 0.5)
then 305 pres(k) = pres(k-1) + h_to_pres*hf(k-1,i)
306 t_int(k) = 0.5*(tf(k,i)+tf(k-1,i))
307 s_int(k) = 0.5*(sf(k,i)+sf(k-1,i))
309 call calculate_density_derivs(t_int, s_int, pres, drho_dt, drho_ds, 2, &
310 kf(i)-1, tv%eqn_of_state)
316 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * &
317 max(0.0,drho_dt(k)*(tf(k,i)-tf(k-1,i)) + &
318 drho_ds(k)*(sf(k,i)-sf(k-1,i)))
323 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * &
324 max(0.0,rf(k,i)-rf(k-1,i))
330 if (drxh_sum >= 0.0)
then 335 hc(1) = hf(1,i) ; tc(1) = tf(1,i) ; sc(1) = sf(1,i)
337 if ((drho_dt(k)*(tf(k,i)-tc(kc)) + drho_ds(k)*(sf(k,i)-sc(kc))) * &
338 (hc(kc) + hf(k,i)) < 2.0 * tol2*drxh_sum)
then 340 i_hnew = 1.0 / (hc(kc) + hf(k,i))
341 tc(kc) = (hc(kc)*tc(kc) + hf(k,i)*tf(k,i)) * i_hnew
342 sc(kc) = (hc(kc)*sc(kc) + hf(k,i)*sf(k,i)) * i_hnew
343 hc(kc) = (hc(kc) + hf(k,i))
348 if ((drho_dt(k2)*(tc(k2)-tc(k2-1)) + drho_ds(k2)*(sc(k2)-sc(k2-1))) * &
349 (hc(k2) + hc(k2-1)) < tol2*drxh_sum)
then 351 i_hnew = 1.0 / (hc(kc) + hc(kc-1))
352 tc(kc-1) = (hc(kc)*tc(kc) + hc(kc-1)*tc(kc-1)) * i_hnew
353 sc(kc-1) = (hc(kc)*sc(kc) + hc(kc-1)*sc(kc-1)) * i_hnew
354 hc(kc-1) = (hc(kc) + hc(kc-1))
361 drho_ds(kc) = drho_ds(k) ; drho_dt(kc) = drho_dt(k)
362 tc(kc) = tf(k,i) ; sc(kc) = sf(k,i) ; hc(kc) = hf(k,i)
367 gprime(k) = g_rho0 * (drho_dt(k)*(tc(k)-tc(k-1)) + &
368 drho_ds(k)*(sc(k)-sc(k-1)))
373 hc(1) = hf(1,i) ; rc(1) = rf(1,i)
375 if ((rf(k,i) - rc(kc)) * (hc(kc) + hf(k,i)) < 2.0*tol2*drxh_sum)
then 377 rc(kc) = (hc(kc)*rc(kc) + hf(k,i)*rf(k,i)) / (hc(kc) + hf(k,i))
378 hc(kc) = (hc(kc) + hf(k,i))
383 if ((rc(k2)-rc(k2-1)) * (hc(k2)+hc(k2-1)) < tol2*drxh_sum)
then 385 rc(kc-1) = (hc(kc)*rc(kc) + hc(kc-1)*rc(kc-1)) / (hc(kc) + hc(kc-1))
386 hc(kc-1) = (hc(kc) + hc(kc-1))
393 rc(kc) = rf(k,i) ; hc(kc) = hf(k,i)
398 gprime(k) = g_rho0 * (rc(k)-rc(k-1))
410 if (kc >= modenum + 1)
then 416 igl(k) = 1.0/(gprime(k)*hc(k)) ; igu(k) = 1.0/(gprime(k)*hc(k-1))
417 z_int(k) = z_int(k-1) + hc(k-1)
418 n2(k) = gprime(k)/(0.5*(hc(k)+hc(k-1)))
421 n2(1) = n2(2) ; n2(kc+1) = n2(kc)
423 z_int(kc+1) = z_int(kc)+hc(kc)
425 if (abs(z_int(kc+1)-htot(i,j)) > 1.e-10)
then 426 call mom_error(warning,
"wave_structure: mismatch in total depths")
428 print *,
"z_int(kc+1)=", z_int(kc+1)
429 print *,
"htot(i,j)=", htot(i,j)
439 lam_z(row) = lam*gprime(k)
440 a_diag(row) = gprime(k)*(-igu(k))
441 b_diag(row) = gprime(k)*(igu(k)+igl(k)) - lam_z(row)
442 c_diag(row) = gprime(k)*(-igl(k))
443 if(isnan(lam_z(row)))
then ; print *,
"Wave_structure: lam_z(row) is NAN" ;
endif 444 if(isnan(a_diag(row)))
then ; print *,
"Wave_structure: a(k) is NAN" ;
endif 445 if(isnan(b_diag(row)))
then ; print *,
"Wave_structure: b(k) is NAN" ;
endif 446 if(isnan(c_diag(row)))
then ; print *,
"Wave_structure: c(k) is NAN" ;
endif 450 lam_z(row) = lam*gprime(k)
452 b_diag(row) = gprime(k)*(igu(k)+igl(k)) - lam_z(row)
453 c_diag(row) = gprime(k)*(-igl(k))
456 lam_z(row) = lam*gprime(k)
457 a_diag(row) = gprime(k)*(-igu(k))
458 b_diag(row) = gprime(k)*(igu(k)+igl(k)) - lam_z(row)
462 e_guess(1:kc-1) = sin(z_int(2:kc)/htot(i,j)*pi)
463 e_guess(1:kc-1) = e_guess(1:kc-1)/sqrt(sum(e_guess(1:kc-1)**2))
467 call tridiag_solver(a_diag(1:kc-1),b_diag(1:kc-1),c_diag(1:kc-1), &
468 -lam_z(1:kc-1),e_guess(1:kc-1),
"TDMA_H",e_itt)
469 e_guess(1:kc-1) = e_itt(1:kc-1)/sqrt(sum(e_itt(1:kc-1)**2))
471 w_strct(2:kc) = e_guess(1:kc-1)
476 ig_stop = 0 ; jg_stop = 0
477 if(isnan(sum(w_strct(1:kc+1))))
then 478 print *,
"Wave_structure: w_strct has a NAN at ig=", ig,
", jg=", jg
479 if(i<g%isc .or. i>g%iec .or. j<g%jsc .or. j>g%jec)
then 480 print *,
"This is occuring at a halo point." 482 ig_stop = ig ; jg_stop = jg
492 w2avg = w2avg + 0.5*(w_strct(k)**2+w_strct(k+1)**2)*dz(k)
494 w2avg = w2avg/htot(i,j)
495 w_strct = w_strct/sqrt(htot(i,j)*w2avg*i_a_int)
499 u_strct(k) = 0.5*((w_strct(k-1) - w_strct(k) )/dz(k-1) + &
500 (w_strct(k) - w_strct(k+1))/dz(k))
502 u_strct(1) = (w_strct(1) - w_strct(2) )/dz(1)
503 u_strct(nzm) = (w_strct(nzm-1)- w_strct(nzm))/dz(nzm-1)
506 f2 = g%CoriolisBu(i,j)**2
509 kmag2 = (freq**2 - f2) / (cn(i,j)**2 + cg_subro**2)
512 int_dwdz2 = 0.0 ; int_w2 = 0.0 ; int_n2w2 = 0.0
513 u_strct2 = u_strct(1:nzm)**2
514 w_strct2 = w_strct(1:nzm)**2
517 int_dwdz2 = int_dwdz2 + 0.5*(u_strct2(k)+u_strct2(k+1))*dz(k)
518 int_w2 = int_w2 + 0.5*(w_strct2(k)+w_strct2(k+1))*dz(k)
519 int_n2w2 = int_n2w2 + 0.5*(w_strct2(k)*n2(k)+w_strct2(k+1)*n2(k+1))*dz(k)
523 if (kmag2 > 0.0)
then 524 ke_term = 0.25*gv%Rho0*( (1+f2/freq**2)/kmag2*int_dwdz2 + int_w2 )
525 pe_term = 0.25*gv%Rho0*( int_n2w2/freq**2 )
526 if (en(i,j) >= 0.0)
then 527 w0 = sqrt( en(i,j)/(ke_term + pe_term) )
529 call mom_error(warning,
"wave_structure: En < 0.0; setting to W0 to 0.0")
530 print *,
"En(i,j)=", en(i,j),
" at ig=", ig,
", jg=", jg
534 w_profile = w0*w_strct
535 dwdz_profile = w0*u_strct
537 uavg_profile = abs(dwdz_profile) * sqrt((1+f2/freq**2)/(2.0*kmag2))
545 cs%w_strct(i,j,1:nzm) = w_strct
546 cs%u_strct(i,j,1:nzm) = u_strct
547 cs%W_profile(i,j,1:nzm) = w_profile
548 cs%Uavg_profile(i,j,1:nzm)= uavg_profile
549 cs%z_depths(i,j,1:nzm) = z_int
550 cs%N2(i,j,1:nzm) = n2
551 cs%num_intfaces(i,j) = nzm
587 cs%w_strct(i,j,1:nzm) = 0.0
588 cs%u_strct(i,j,1:nzm) = 0.0
589 cs%W_profile(i,j,1:nzm) = 0.0
590 cs%Uavg_profile(i,j,1:nzm)= 0.0
591 cs%z_depths(i,j,1:nzm) = 0.0
592 cs%N2(i,j,1:nzm) = 0.0
593 cs%num_intfaces(i,j) = nzm
603 cs%w_strct(i,j,1:nzm) = 0.0
604 cs%u_strct(i,j,1:nzm) = 0.0
605 cs%W_profile(i,j,1:nzm) = 0.0
606 cs%Uavg_profile(i,j,1:nzm)= 0.0
607 cs%z_depths(i,j,1:nzm) = 0.0
608 cs%N2(i,j,1:nzm) = 0.0
609 cs%num_intfaces(i,j) = nzm
Ocean grid type. See mom_grid for details.