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.