16 implicit none ;
private 18 #include <MOM_memory.h> 20 public wave_speed, wave_speeds, wave_speed_init, wave_speed_set_param
29 logical :: use_ebt_mode = .false.
33 logical :: better_cg1_est = .false.
35 real :: mono_n2_column_fraction = 0.
39 real :: mono_n2_depth = -1.
43 real :: min_speed2 = 0.
44 real :: wave_speed_tol = 0.001
48 logical :: remap_answers_2018 = .true.
57 subroutine wave_speed(h, tv, G, GV, US, cg1, CS, full_halos, use_ebt_mode, mono_N2_column_fraction, &
58 mono_N2_depth, modal_structure, better_speed_est, min_speed, wave_speed_tol)
62 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
65 real,
dimension(SZI_(G),SZJ_(G)),
intent(out) :: cg1
67 logical,
optional,
intent(in) :: full_halos
69 logical,
optional,
intent(in) :: use_ebt_mode
71 real,
optional,
intent(in) :: mono_N2_column_fraction
74 real,
optional,
intent(in) :: mono_N2_depth
77 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)), &
78 optional,
intent(out) :: modal_structure
79 logical,
optional,
intent(in) :: better_speed_est
81 real,
optional,
intent(in) :: min_speed
83 real,
optional,
intent(in) :: wave_speed_tol
87 real,
dimension(SZK_(G)+1) :: &
96 real,
dimension(SZK_(G)) :: &
99 real,
dimension(SZK_(G),SZI_(G)) :: &
104 real,
dimension(SZK_(G)) :: &
111 real :: det, ddet, detKm1, detKm2, ddetKm1, ddetKm2
117 real,
dimension(SZI_(G)) :: &
128 real,
pointer,
dimension(:,:,:) :: T => null(), s => null()
138 real :: rescale, I_rescale
139 integer :: kf(szi_(g))
140 integer,
parameter :: max_itt = 10
141 real :: lam_it(max_itt), det_it(max_itt), ddet_it(max_itt)
143 logical :: better_est
146 integer :: i, j, k, k2, itt, is, ie, js, je, nz
150 logical :: l_use_ebt_mode, calc_modal_structure
151 real :: l_mono_N2_column_fraction, l_mono_N2_depth
152 real :: mode_struct(szk_(g)), ms_min, ms_max, ms_sq
154 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
156 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_wave_speed: "// &
157 "Module must be initialized before it is used.")
158 if (
present(full_halos))
then ;
if (full_halos)
then 159 is = g%isd ; ie = g%ied ; js = g%jsd ; je = g%jed
162 l2_to_z2 = us%L_to_Z**2
164 l_use_ebt_mode = cs%use_ebt_mode
165 if (
present(use_ebt_mode)) l_use_ebt_mode = use_ebt_mode
166 l_mono_n2_column_fraction = cs%mono_N2_column_fraction
167 if (
present(mono_n2_column_fraction)) l_mono_n2_column_fraction = mono_n2_column_fraction
168 l_mono_n2_depth = cs%mono_N2_depth
169 if (
present(mono_n2_depth)) l_mono_n2_depth = mono_n2_depth
170 calc_modal_structure = l_use_ebt_mode
171 if (
present(modal_structure)) calc_modal_structure = .true.
172 if (calc_modal_structure)
then 173 do k=1,nz;
do j=js,je;
do i=is,ie
174 modal_structure(i,j,k) = 0.0
175 enddo ;
enddo ;
enddo 178 s => tv%S ; t => tv%T
179 g_rho0 = gv%g_Earth / gv%Rho0
181 z_to_pres = gv%Z_to_H * (gv%H_to_RZ * gv%g_Earth)
182 use_eos =
associated(tv%eqn_of_state)
184 better_est = cs%better_cg1_est ;
if (
present(better_speed_est)) better_est = better_speed_est
187 tol_solve = cs%wave_speed_tol ;
if (
present(wave_speed_tol)) tol_solve = wave_speed_tol
188 tol_hfrac = 0.1*tol_solve ; tol_merge = tol_solve /
real(nz)
190 tol_solve = 0.001 ; tol_hfrac = 0.0001 ; tol_merge = 0.001
200 cg1_min2 = cs%min_speed2 ;
if (
present(min_speed)) cg1_min2 = min_speed**2
201 rescale = 1024.0**4 ; i_rescale = 1.0/rescale
202 c2_scale = us%m_s_to_L_T**2 / 4096.0**2
204 min_h_frac = tol_hfrac /
real(nz)
221 do i=is,ie ; htot(i) = 0.0 ;
enddo 222 do k=1,nz ;
do i=is,ie ; htot(i) = htot(i) + h(i,j,k)*gv%H_to_Z ;
enddo ;
enddo 225 hmin(i) = htot(i)*min_h_frac ; kf(i) = 1 ; h_here(i) = 0.0
226 hxt_here(i) = 0.0 ; hxs_here(i) = 0.0 ; hxr_here(i) = 0.0
229 do k=1,nz ;
do i=is,ie
230 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*gv%H_to_Z > hmin(i)))
then 231 hf(kf(i),i) = h_here(i)
232 tf(kf(i),i) = hxt_here(i) / h_here(i)
233 sf(kf(i),i) = hxs_here(i) / h_here(i)
237 h_here(i) = h(i,j,k)*gv%H_to_Z
238 hxt_here(i) = (h(i,j,k)*gv%H_to_Z)*t(i,j,k)
239 hxs_here(i) = (h(i,j,k)*gv%H_to_Z)*s(i,j,k)
241 h_here(i) = h_here(i) + h(i,j,k)*gv%H_to_Z
242 hxt_here(i) = hxt_here(i) + (h(i,j,k)*gv%H_to_Z)*t(i,j,k)
243 hxs_here(i) = hxs_here(i) + (h(i,j,k)*gv%H_to_Z)*s(i,j,k)
246 do i=is,ie ;
if (h_here(i) > 0.0)
then 247 hf(kf(i),i) = h_here(i)
248 tf(kf(i),i) = hxt_here(i) / h_here(i)
249 sf(kf(i),i) = hxs_here(i) / h_here(i)
252 do k=1,nz ;
do i=is,ie
253 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*gv%H_to_Z > hmin(i)))
then 254 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
258 h_here(i) = h(i,j,k)*gv%H_to_Z
259 hxr_here(i) = (h(i,j,k)*gv%H_to_Z)*gv%Rlay(k)
261 h_here(i) = h_here(i) + h(i,j,k)*gv%H_to_Z
262 hxr_here(i) = hxr_here(i) + (h(i,j,k)*gv%H_to_Z)*gv%Rlay(k)
265 do i=is,ie ;
if (h_here(i) > 0.0)
then 266 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
271 do i=is,ie ;
if (g%mask2dT(i,j) > 0.5)
then 273 pres(1) = 0.0 ; h_top(1) = 0.0
275 pres(k) = pres(k-1) + z_to_pres*hf(k-1,i)
276 t_int(k) = 0.5*(tf(k,i)+tf(k-1,i))
277 s_int(k) = 0.5*(sf(k,i)+sf(k-1,i))
278 h_top(k) = h_top(k-1) + hf(k-1,i)
281 tv%eqn_of_state, (/2,kf(i)/) )
290 if (h_top(kf(i)) > 0.0)
then 291 i_htot = 1.0 / (h_top(kf(i)) + hf(kf(i),i))
294 h_bot(k) = h_bot(k+1) + hf(k,i)
295 drxh_sum = drxh_sum + ((h_top(k) * h_bot(k)) * i_htot) * &
296 max(0.0, drho_dt(k)*(tf(k,i)-tf(k-1,i)) + drho_ds(k)*(sf(k,i)-sf(k-1,i)))
304 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * &
305 max(0.0, drho_dt(k)*(tf(k,i)-tf(k-1,i)) + drho_ds(k)*(sf(k,i)-sf(k-1,i)))
312 do k=2,kf(i) ; h_top(k) = h_top(k-1) + hf(k-1,i) ;
enddo 313 if (h_top(kf(i)) > 0.0)
then 314 i_htot = 1.0 / (h_top(kf(i)) + hf(kf(i),i))
317 h_bot(k) = h_bot(k+1) + hf(k,i)
318 drxh_sum = drxh_sum + ((h_top(k) * h_bot(k)) * i_htot) * max(0.0,rf(k,i)-rf(k-1,i))
323 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * max(0.0,rf(k,i)-rf(k-1,i))
330 if (g_rho0 * drxh_sum <= cg1_min2)
then 332 if (
present(modal_structure)) modal_structure(i,j,:) = 0.
339 hc(1) = hf(1,i) ; tc(1) = tf(1,i) ; sc(1) = sf(1,i)
342 merge = ((drho_dt(k)*(tf(k,i)-tc(kc)) + drho_ds(k)*(sf(k,i)-sc(kc))) * &
343 ((hc(kc) * hf(k,i))*i_htot) < 2.0 * tol_merge*drxh_sum)
345 merge = ((drho_dt(k)*(tf(k,i)-tc(kc)) + drho_ds(k)*(sf(k,i)-sc(kc))) * &
346 (hc(kc) + hf(k,i)) < 2.0 * tol_merge*drxh_sum)
350 i_hnew = 1.0 / (hc(kc) + hf(k,i))
351 tc(kc) = (hc(kc)*tc(kc) + hf(k,i)*tf(k,i)) * i_hnew
352 sc(kc) = (hc(kc)*sc(kc) + hf(k,i)*sf(k,i)) * i_hnew
353 hc(kc) = (hc(kc) + hf(k,i))
359 merge = ((drho_dt(k2)*(tc(k2)-tc(k2-1)) + drho_ds(k2)*(sc(k2)-sc(k2-1))) * &
360 ((hc(k2) * hc(k2-1))*i_htot) < tol_merge*drxh_sum)
362 merge = ((drho_dt(k2)*(tc(k2)-tc(k2-1)) + drho_ds(k2)*(sc(k2)-sc(k2-1))) * &
363 (hc(k2) + hc(k2-1)) < tol_merge*drxh_sum)
367 i_hnew = 1.0 / (hc(kc) + hc(kc-1))
368 tc(kc-1) = (hc(kc)*tc(kc) + hc(kc-1)*tc(kc-1)) * i_hnew
369 sc(kc-1) = (hc(kc)*sc(kc) + hc(kc-1)*sc(kc-1)) * i_hnew
370 hc(kc-1) = (hc(kc) + hc(kc-1))
377 drho_ds(kc) = drho_ds(k) ; drho_dt(kc) = drho_dt(k)
378 tc(kc) = tf(k,i) ; sc(kc) = sf(k,i) ; hc(kc) = hf(k,i)
383 gprime(k) = g_rho0 * (drho_dt(k)*(tc(k)-tc(k-1)) + drho_ds(k)*(sc(k)-sc(k-1)))
388 hc(1) = hf(1,i) ; rc(1) = rf(1,i)
391 merge = ((rf(k,i) - rc(kc)) * ((hc(kc) * hf(k,i))*i_htot) < 2.0*tol_merge*drxh_sum)
393 merge = ((rf(k,i) - rc(kc)) * (hc(kc) + hf(k,i)) < 2.0*tol_merge*drxh_sum)
397 rc(kc) = (hc(kc)*rc(kc) + hf(k,i)*rf(k,i)) / (hc(kc) + hf(k,i))
398 hc(kc) = (hc(kc) + hf(k,i))
404 merge = ((rc(k2)-rc(k2-1)) * ((hc(k2) * hc(k2-1))*i_htot) < tol_merge*drxh_sum)
406 merge = ((rc(k2)-rc(k2-1)) * (hc(k2)+hc(k2-1)) < tol_merge*drxh_sum)
410 rc(kc-1) = (hc(kc)*rc(kc) + hc(kc-1)*rc(kc-1)) / (hc(kc) + hc(kc-1))
411 hc(kc-1) = (hc(kc) + hc(kc-1))
418 rc(kc) = rf(k,i) ; hc(kc) = hf(k,i)
423 gprime(k) = g_rho0 * (rc(k)-rc(k-1))
433 h_top(1) = 0.0 ; h_bot(kc+1) = 0.0
434 do k=2,kc+1 ; h_top(k) = h_top(k-1) + hc(k-1) ;
enddo 435 do k=kc,2,-1 ; h_bot(k) = h_bot(k+1) + hc(k) ;
enddo 436 i_htot = 0.0 ;
if (h_top(kc+1) > 0.0) i_htot = 1.0 / h_top(kc+1)
439 if (l_use_ebt_mode)
then 442 n2min = l2_to_z2*gprime(2)/hc(1)
444 hw = 0.5*(hc(k-1)+hc(k))
446 if (l_mono_n2_column_fraction>0. .or. l_mono_n2_depth>=0.)
then 447 if ( ((g%bathyT(i,j)-sum_hc < l_mono_n2_column_fraction*g%bathyT(i,j)) .or. &
448 ((l_mono_n2_depth >= 0.) .and. (sum_hc > l_mono_n2_depth))) .and. &
449 (l2_to_z2*gp > n2min*hw) )
then 452 gp = us%Z_to_L**2 * (n2min*hw)
454 n2min = l2_to_z2 * gp/hw
457 igu(k) = 1.0/(gp*hc(k))
458 igl(k-1) = 1.0/(gp*hc(k-1))
459 sum_hc = sum_hc + hc(k)
462 speed2_tot = speed2_tot + 2.0 * gprime(k)*((h_top(k) * h_bot(k)) * i_htot)
464 speed2_tot = speed2_tot + gprime(k)*(hc(k-1)+hc(k))*0.707
471 igl(k) = 1.0/(gprime(k)*hc(k)) ; igu(k) = 1.0/(gprime(k)*hc(k-1))
473 speed2_tot = speed2_tot + gprime(k)*((h_top(k) * h_bot(k)) * i_htot)
475 speed2_tot = speed2_tot + gprime(k)*(hc(k-1)+hc(k))
480 if (calc_modal_structure)
then 482 mode_struct(1:kc) = 1.
486 if (calc_modal_structure)
then 487 lam0 = 0.5 / speed2_tot ; lam = lam0
489 lam0 = 1.0 / speed2_tot ; lam = lam0
494 if (l_use_ebt_mode)
then 503 call tridiag_det(igu, igl, 1, kc, lam, det, ddet, row_scale=c2_scale)
514 call tridiag_det(igu, igl, 2, kc, lam, det, ddet, row_scale=c2_scale)
517 det_it(itt) = det ; ddet_it(itt) = ddet
519 if ((ddet >= 0.0) .or. (-det > -0.5*lam*ddet))
then 530 if (calc_modal_structure)
then 531 call tdma6(kc, igu, igl, lam, mode_struct)
532 ms_min = mode_struct(1)
533 ms_max = mode_struct(1)
534 ms_sq = mode_struct(1)**2
536 ms_min = min(ms_min, mode_struct(k))
537 ms_max = max(ms_max, mode_struct(k))
538 ms_sq = ms_sq + mode_struct(k)**2
540 if (ms_min<0. .and. ms_max>0.)
then 541 lam = 0.5 * ( lam - dlam )
543 mode_struct(1:kc) = abs(mode_struct(1:kc)) / sqrt( ms_sq )
545 mode_struct(1:kc) = mode_struct(1:kc) / sqrt( ms_sq )
549 if (abs(dlam) < tol_solve*lam)
exit 553 if (lam > 0.0) cg1(i,j) = 1.0 / sqrt(lam)
555 if (
present(modal_structure))
then 556 if (mode_struct(1)/=0.)
then 557 mode_struct(1:kc) = mode_struct(1:kc) / mode_struct(1)
564 hc_h(k) = gv%Z_to_H * hc(k)
566 if (cs%remap_answers_2018)
then 567 call remapping_core_h(cs%remapping_CS, kc, hc_h(:), mode_struct, &
568 nz, h(i,j,:), modal_structure(i,j,:), &
569 1.0e-30*gv%m_to_H, 1.0e-10*gv%m_to_H)
571 call remapping_core_h(cs%remapping_CS, kc, hc_h(:), mode_struct, &
572 nz, h(i,j,:), modal_structure(i,j,:), &
573 gv%H_subroundoff, gv%H_subroundoff)
578 if (
present(modal_structure)) modal_structure(i,j,:) = 0.
583 if (
present(modal_structure)) modal_structure(i,j,:) = 0.
587 end subroutine wave_speed
592 subroutine tdma6(n, a, c, lam, y)
593 integer,
intent(in) :: n
594 real,
dimension(:),
intent(in) :: a
595 real,
dimension(:),
intent(in) :: c
596 real,
intent(in) :: lam
597 real,
dimension(:),
intent(inout) :: y
607 beta(1) = (a(1)+c(1)) - lambda
608 if (beta(1)==0.)
then 610 lambda = (1. + 1.e-5) * lambda
611 beta(1) = (a(1)+c(1)) - lambda
613 i_beta(1) = 1. / beta(1)
616 beta(k) = ( (a(k)+c(k)) - lambda ) - a(k) * c(k-1) * i_beta(k-1)
618 if (beta(k)==0.)
then 620 lambda = (1. + 1.e-5) * lambda
621 i_beta(1) = 1. / ( (a(1)+c(1)) - lambda )
623 i_beta(m) = 1. / ( ( (a(m)+c(m)) - lambda ) - a(m) * c(m-1) * i_beta(m-1) )
624 yy(m) = y(m) + a(m) * yy(m-1) * i_beta(m-1)
627 i_beta(k) = 1. / beta(k)
629 yy(k) = y(k) + a(k) * yy(k-1) * i_beta(k-1)
632 y(n) = yy(n) * i_beta(n)
634 y(k) = ( yy(k) + c(k) * y(k+1) ) * i_beta(k)
640 subroutine wave_speeds(h, tv, G, GV, US, nmodes, cn, CS, full_halos, better_speed_est, &
641 min_speed, wave_speed_tol)
645 real,
dimension(SZI_(G),SZJ_(G),SZK_(G)),
intent(in) :: h
647 integer,
intent(in) :: nmodes
648 real,
dimension(G%isd:G%ied,G%jsd:G%jed,nmodes),
intent(out) :: cn
650 logical,
optional,
intent(in) :: full_halos
652 logical,
optional,
intent(in) :: better_speed_est
654 real,
optional,
intent(in) :: min_speed
656 real,
optional,
intent(in) :: wave_speed_tol
660 real,
dimension(SZK_(G)+1) :: &
669 real,
dimension(SZK_(G),SZI_(G)) :: &
674 real,
dimension(SZK_(G)) :: &
695 real :: ddet_l,ddet_r
696 real :: det_sub,ddet_sub
699 real,
dimension(nmodes) :: &
702 integer :: nrootsfound
704 real,
dimension(SZI_(G)) :: &
713 real,
parameter :: reduct_factor = 0.5
717 real,
pointer,
dimension(:,:,:) :: T => null(), s => null()
725 integer :: kf(szi_(g))
726 integer,
parameter :: max_itt = 10
728 logical :: better_est
731 integer,
parameter :: sub_it_max = 4
734 logical :: sub_rootfound
736 integer :: sub, sub_it
737 integer :: i, j, k, k2, itt, is, ie, js, je, nz, row, iint, m, ig, jg
739 is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
741 if (
present(cs))
then 742 if (.not.
associated(cs))
call mom_error(fatal,
"MOM_wave_speed: "// &
743 "Module must be initialized before it is used.")
746 if (
present(full_halos))
then ;
if (full_halos)
then 747 is = g%isd ; ie = g%ied ; js = g%jsd ; je = g%jed
750 s => tv%S ; t => tv%T
751 g_rho0 = gv%g_Earth / gv%Rho0
753 z_to_pres = gv%Z_to_H * (gv%H_to_RZ * gv%g_Earth)
754 use_eos =
associated(tv%eqn_of_state)
755 c1_thresh = 0.01*us%m_s_to_L_T
756 c2_scale = us%m_s_to_L_T**2 / 4096.0**2
758 better_est = .false. ;
if (
present(cs)) better_est = cs%better_cg1_est
759 if (
present(better_speed_est)) better_est = better_speed_est
761 tol_solve = 0.001 ;
if (
present(cs)) tol_solve = cs%wave_speed_tol
762 if (
present(wave_speed_tol)) tol_solve = wave_speed_tol
763 tol_hfrac = 0.1*tol_solve ; tol_merge = tol_solve /
real(nz)
765 tol_solve = 0.001 ; tol_hfrac = 0.0001 ; tol_merge = 0.001
767 cg1_min2 = 0.0 ;
if (
present(cs)) cg1_min2 = cs%min_speed2
768 if (
present(min_speed)) cg1_min2 = min_speed**2
774 min_h_frac = tol_hfrac /
real(nz)
782 do i=is,ie ; htot(i) = 0.0 ;
enddo 783 do k=1,nz ;
do i=is,ie ; htot(i) = htot(i) + h(i,j,k)*gv%H_to_Z ;
enddo ;
enddo 786 hmin(i) = htot(i)*min_h_frac ; kf(i) = 1 ; h_here(i) = 0.0
787 hxt_here(i) = 0.0 ; hxs_here(i) = 0.0 ; hxr_here(i) = 0.0
790 do k=1,nz ;
do i=is,ie
791 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*gv%H_to_Z > hmin(i)))
then 792 hf(kf(i),i) = h_here(i)
793 tf(kf(i),i) = hxt_here(i) / h_here(i)
794 sf(kf(i),i) = hxs_here(i) / h_here(i)
798 h_here(i) = h(i,j,k)*gv%H_to_Z
799 hxt_here(i) = (h(i,j,k)*gv%H_to_Z)*t(i,j,k)
800 hxs_here(i) = (h(i,j,k)*gv%H_to_Z)*s(i,j,k)
802 h_here(i) = h_here(i) + h(i,j,k)*gv%H_to_Z
803 hxt_here(i) = hxt_here(i) + (h(i,j,k)*gv%H_to_Z)*t(i,j,k)
804 hxs_here(i) = hxs_here(i) + (h(i,j,k)*gv%H_to_Z)*s(i,j,k)
807 do i=is,ie ;
if (h_here(i) > 0.0)
then 808 hf(kf(i),i) = h_here(i)
809 tf(kf(i),i) = hxt_here(i) / h_here(i)
810 sf(kf(i),i) = hxs_here(i) / h_here(i)
813 do k=1,nz ;
do i=is,ie
814 if ((h_here(i) > hmin(i)) .and. (h(i,j,k)*gv%H_to_Z > hmin(i)))
then 815 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
819 h_here(i) = h(i,j,k)*gv%H_to_Z
820 hxr_here(i) = (h(i,j,k)*gv%H_to_Z)*gv%Rlay(k)
822 h_here(i) = h_here(i) + h(i,j,k)*gv%H_to_Z
823 hxr_here(i) = hxr_here(i) + (h(i,j,k)*gv%H_to_Z)*gv%Rlay(k)
826 do i=is,ie ;
if (h_here(i) > 0.0)
then 827 hf(kf(i),i) = h_here(i) ; rf(kf(i),i) = hxr_here(i) / h_here(i)
833 if (g%mask2dT(i,j) > 0.5)
then 835 pres(1) = 0.0 ; h_top(1) = 0.0
837 pres(k) = pres(k-1) + z_to_pres*hf(k-1,i)
838 t_int(k) = 0.5*(tf(k,i)+tf(k-1,i))
839 s_int(k) = 0.5*(sf(k,i)+sf(k-1,i))
840 h_top(k) = h_top(k-1) + hf(k-1,i)
843 tv%eqn_of_state, (/2,kf(i)/) )
852 if (h_top(kf(i)) > 0.0)
then 853 i_htot = 1.0 / (h_top(kf(i)) + hf(kf(i),i))
856 h_bot(k) = h_bot(k+1) + hf(k,i)
857 drxh_sum = drxh_sum + ((h_top(k) * h_bot(k)) * i_htot) * &
858 max(0.0, drho_dt(k)*(tf(k,i)-tf(k-1,i)) + drho_ds(k)*(sf(k,i)-sf(k-1,i)))
866 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * &
867 max(0.0, drho_dt(k)*(tf(k,i)-tf(k-1,i)) + drho_ds(k)*(sf(k,i)-sf(k-1,i)))
874 do k=2,kf(i) ; h_top(k) = h_top(k-1) + hf(k-1,i) ;
enddo 875 if (h_top(kf(i)) > 0.0)
then 876 i_htot = 1.0 / (h_top(kf(i)) + hf(kf(i),i))
879 h_bot(k) = h_bot(k+1) + hf(k,i)
880 drxh_sum = drxh_sum + ((h_top(k) * h_bot(k)) * i_htot) * max(0.0,rf(k,i)-rf(k-1,i))
885 drxh_sum = drxh_sum + 0.5*(hf(k-1,i)+hf(k,i)) * max(0.0,rf(k,i)-rf(k-1,i))
892 if (g_rho0 * drxh_sum > cg1_min2)
then 898 hc(1) = hf(1,i) ; tc(1) = tf(1,i) ; sc(1) = sf(1,i)
901 merge = ((drho_dt(k)*(tf(k,i)-tc(kc)) + drho_ds(k)*(sf(k,i)-sc(kc))) * &
902 ((hc(kc) * hf(k,i))*i_htot) < 2.0 * tol_merge*drxh_sum)
904 merge = ((drho_dt(k)*(tf(k,i)-tc(kc)) + drho_ds(k)*(sf(k,i)-sc(kc))) * &
905 (hc(kc) + hf(k,i)) < 2.0 * tol_merge*drxh_sum)
909 i_hnew = 1.0 / (hc(kc) + hf(k,i))
910 tc(kc) = (hc(kc)*tc(kc) + hf(k,i)*tf(k,i)) * i_hnew
911 sc(kc) = (hc(kc)*sc(kc) + hf(k,i)*sf(k,i)) * i_hnew
912 hc(kc) = (hc(kc) + hf(k,i))
918 merge = ((drho_dt(k2)*(tc(k2)-tc(k2-1)) + drho_ds(k2)*(sc(k2)-sc(k2-1))) * &
919 ((hc(k2) * hc(k2-1))*i_htot) < tol_merge*drxh_sum)
921 merge = ((drho_dt(k2)*(tc(k2)-tc(k2-1)) + drho_ds(k2)*(sc(k2)-sc(k2-1))) * &
922 (hc(k2) + hc(k2-1)) < tol_merge*drxh_sum)
926 i_hnew = 1.0 / (hc(kc) + hc(kc-1))
927 tc(kc-1) = (hc(kc)*tc(kc) + hc(kc-1)*tc(kc-1)) * i_hnew
928 sc(kc-1) = (hc(kc)*sc(kc) + hc(kc-1)*sc(kc-1)) * i_hnew
929 hc(kc-1) = (hc(kc) + hc(kc-1))
936 drho_ds(kc) = drho_ds(k) ; drho_dt(kc) = drho_dt(k)
937 tc(kc) = tf(k,i) ; sc(kc) = sf(k,i) ; hc(kc) = hf(k,i)
942 gprime(k) = g_rho0 * (drho_dt(k)*(tc(k)-tc(k-1)) + drho_ds(k)*(sc(k)-sc(k-1)))
947 hc(1) = hf(1,i) ; rc(1) = rf(1,i)
950 merge = ((rf(k,i) - rc(kc)) * ((hc(kc) * hf(k,i))*i_htot) < 2.0 * tol_merge*drxh_sum)
952 merge = ((rf(k,i) - rc(kc)) * (hc(kc) + hf(k,i)) < 2.0*tol_merge*drxh_sum)
956 rc(kc) = (hc(kc)*rc(kc) + hf(k,i)*rf(k,i)) / (hc(kc) + hf(k,i))
957 hc(kc) = (hc(kc) + hf(k,i))
963 merge = ((rc(k2)-rc(k2-1)) * ((hc(k2) * hc(k2-1))*i_htot) < tol_merge*drxh_sum)
965 merge = ((rc(k2)-rc(k2-1)) * (hc(k2)+hc(k2-1)) < tol_merge*drxh_sum)
969 rc(kc-1) = (hc(kc)*rc(kc) + hc(kc-1)*rc(kc-1)) / (hc(kc) + hc(kc-1))
970 hc(kc-1) = (hc(kc) + hc(kc-1))
977 rc(kc) = rf(k,i) ; hc(kc) = hf(k,i)
982 gprime(k) = g_rho0 * (rc(k)-rc(k-1))
995 h_top(1) = 0.0 ; h_bot(kc+1) = 0.0
996 do k=2,kc+1 ; h_top(k) = h_top(k-1) + hc(k-1) ;
enddo 997 do k=kc,2,-1 ; h_bot(k) = h_bot(k+1) + hc(k) ;
enddo 998 i_htot = 0.0 ;
if (h_top(kc+1) > 0.0) i_htot = 1.0 / h_top(kc+1)
1004 igl(k) = 1.0/(gprime(k)*hc(k)) ; igu(k) = 1.0/(gprime(k)*hc(k-1))
1005 if (better_est)
then 1006 speed2_tot = speed2_tot + gprime(k)*((h_top(k) * h_bot(k)) * i_htot)
1008 speed2_tot = speed2_tot + gprime(k)*(hc(k-1)+hc(k))
1013 lam_1 = 1.0 / speed2_tot
1018 call tridiag_det(igu, igl, 2, kc, lam_1, det, ddet, row_scale=c2_scale)
1022 if ((ddet >= 0.0) .or. (-det > -0.5*lam_1*ddet))
then 1029 lam_1 = lam_1 + dlam
1032 if (abs(dlam) < tol_solve*lam_1)
exit 1035 if (lam_1 > 0.0) cn(i,j,1) = 1.0 / sqrt(lam_1)
1039 if (nmodes>1 .and. kc>=nmodes+1 .and. cn(i,j,1)>c1_thresh)
then 1042 lammin = lam_1*(1.0 + tol_solve)
1044 speed2_min = (reduct_factor*cn(i,j,1)/
real(nmodes))**2
1045 lammax = 1.0 / speed2_min
1049 numint = nint((lammax - lammin)/laminc)
1055 call tridiag_det(igu, igl, 2, kc, lammin, det_l, ddet_l, row_scale=c2_scale)
1058 xr = lammin + laminc * iint
1060 call tridiag_det(igu, igl, 2, kc, xr, det_r, ddet_r, row_scale=c2_scale)
1061 if (det_l*det_r < 0.0)
then 1062 if (det_l*ddet_l < 0.0)
then 1063 nrootsfound = nrootsfound + 1
1064 xbl(nrootsfound) = xl
1065 xbr(nrootsfound) = xr
1074 sub_rootfound = .false.
1075 do sub_it=1,sub_it_max
1079 xl_sub = xl + laminc/(nsub)*sub
1080 call tridiag_det(igu, igl, 2, kc, xl_sub, det_sub, ddet_sub, &
1082 if (det_sub*det_r < 0.0)
then 1083 if (det_sub*ddet_sub < 0.0)
then 1084 sub_rootfound = .true.
1085 nrootsfound = nrootsfound + 1
1086 xbl(nrootsfound) = xl_sub
1087 xbr(nrootsfound) = xr
1092 if (sub_rootfound)
exit 1095 if (sub_it == sub_it_max)
then 1096 call mom_error(warning,
"wave_speed: root not found "// &
1097 " after sub_it_max subdivisions of original"// &
1104 if (nrootsfound >= nmodes-1)
then 1107 elseif (iint == numint)
then 1123 call tridiag_det(igu, igl, 2, kc, lam_n, det, ddet, row_scale=c2_scale)
1126 lam_n = lam_n + dlam
1127 if (abs(dlam) < tol_solve*lam_1)
exit 1130 if (lam_n > 0.0) cn(i,j,m+1) = 1.0 / sqrt(lam_n)
1139 end subroutine wave_speeds
1145 subroutine tridiag_det(a, c, ks, ke, lam, det, ddet, row_scale)
1146 real,
dimension(:),
intent(in) :: a
1147 real,
dimension(:),
intent(in) :: c
1148 integer,
intent(in) :: ks
1149 integer,
intent(in) :: ke
1150 real,
intent(in) :: lam
1151 real,
intent(out):: det
1152 real,
intent(out):: ddet
1153 real,
optional,
intent(in) :: row_scale
1156 real :: detKm1, detKm2
1157 real :: ddetKm1, ddetKm2
1158 real,
parameter :: rescale = 1024.0**4
1163 i_rescale = 1.0 / rescale
1164 rscl = 1.0 ;
if (
present(row_scale)) rscl = row_scale
1166 detkm1 = 1.0 ; ddetkm1 = 0.0
1167 det = (a(ks)+c(ks)) - lam ; ddet = -1.0
1170 detkm2 = row_scale*detkm1 ; ddetkm2 = row_scale*ddetkm1
1171 detkm1 = row_scale*det ; ddetkm1 = row_scale*ddet
1173 det = ((a(k)+c(k))-lam)*detkm1 - (a(k)*c(k-1))*detkm2
1174 ddet = ((a(k)+c(k))-lam)*ddetkm1 - (a(k)*c(k-1))*ddetkm2 - detkm1
1177 if (abs(det) > rescale)
then 1178 det = i_rescale*det ; detkm1 = i_rescale*detkm1
1179 ddet = i_rescale*ddet ; ddetkm1 = i_rescale*ddetkm1
1180 elseif (abs(det) < i_rescale)
then 1181 det = rescale*det ; detkm1 = rescale*detkm1
1182 ddet = rescale*ddet ; ddetkm1 = rescale*ddetkm1
1186 end subroutine tridiag_det
1189 subroutine wave_speed_init(CS, use_ebt_mode, mono_N2_column_fraction, mono_N2_depth, remap_answers_2018, &
1190 better_speed_est, min_speed, wave_speed_tol)
1192 logical,
optional,
intent(in) :: use_ebt_mode
1194 real,
optional,
intent(in) :: mono_N2_column_fraction
1197 real,
optional,
intent(in) :: mono_N2_depth
1200 logical,
optional,
intent(in) :: remap_answers_2018
1203 logical,
optional,
intent(in) :: better_speed_est
1205 real,
optional,
intent(in) :: min_speed
1207 real,
optional,
intent(in) :: wave_speed_tol
1211 # include "version_variable.h" 1212 character(len=40) :: mdl =
"MOM_wave_speed" 1214 if (
associated(cs))
then 1215 call mom_error(warning,
"wave_speed_init called with an "// &
1216 "associated control structure.")
1218 else ;
allocate(cs) ;
endif 1223 call wave_speed_set_param(cs, use_ebt_mode=use_ebt_mode, mono_n2_column_fraction=mono_n2_column_fraction, &
1224 better_speed_est=better_speed_est, min_speed=min_speed, wave_speed_tol=wave_speed_tol)
1226 call initialize_remapping(cs%remapping_CS,
'PLM', boundary_extrapolation=.false., &
1227 answers_2018=cs%remap_answers_2018)
1229 end subroutine wave_speed_init
1232 subroutine wave_speed_set_param(CS, use_ebt_mode, mono_N2_column_fraction, mono_N2_depth, remap_answers_2018, &
1233 better_speed_est, min_speed, wave_speed_tol)
1235 logical,
optional,
intent(in) :: use_ebt_mode
1237 real,
optional,
intent(in) :: mono_N2_column_fraction
1240 real,
optional,
intent(in) :: mono_N2_depth
1243 logical,
optional,
intent(in) :: remap_answers_2018
1246 logical,
optional,
intent(in) :: better_speed_est
1248 real,
optional,
intent(in) :: min_speed
1250 real,
optional,
intent(in) :: wave_speed_tol
1253 if (.not.
associated(cs))
call mom_error(fatal, &
1254 "wave_speed_set_param called with an associated control structure.")
1256 if (
present(use_ebt_mode)) cs%use_ebt_mode = use_ebt_mode
1257 if (
present(mono_n2_column_fraction)) cs%mono_N2_column_fraction = mono_n2_column_fraction
1258 if (
present(mono_n2_depth)) cs%mono_N2_depth = mono_n2_depth
1259 if (
present(remap_answers_2018)) cs%remap_answers_2018 = remap_answers_2018
1260 if (
present(better_speed_est)) cs%better_cg1_est = better_speed_est
1261 if (
present(min_speed)) cs%min_speed2 = min_speed**2
1262 if (
present(wave_speed_tol)) cs%wave_speed_tol = wave_speed_tol
1264 end subroutine wave_speed_set_param
Control structure for MOM_wave_speed.
Ocean grid type. See mom_grid for details.
Calculates density of sea water from T, S and P.
Provides the ocean grid type.
Provides column-wise vertical remapping functions.
Routines for calculating baroclinic wave speeds.
The MOM6 facility to parse input files for runtime parameters.
Container for remapping parameters.
Make a diagnostic available for averaging or output.
Describes various unit conversion factors.
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Routines for error handling and I/O management.
Calculate the derivatives of density with temperature and salinity from T, S, and P...
Provides subroutines for quantities specific to the equation of state.
An overloaded interface to log version information about modules.
Describes the vertical ocean grid, including unit conversion factors.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Provides a transparent vertical ocean grid type and supporting routines.
Provides transparent structures with groups of MOM6 variables and supporting routines.