Skip to content

Commit 94e2c38

Browse files
committed
Add StokesMOST test to reg_tests/kpp
Added external statements to cvmix_driver.F90 to avoid build issue with intel compiler; also added a seventh test to reg_tests/kpp and modified cvmix_kpp.F90 to fix a segmentation fault in this new test.
1 parent c601b04 commit 94e2c38

File tree

4 files changed

+173
-9
lines changed

4 files changed

+173
-9
lines changed

reg_tests/kpp/input.nl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,13 @@ mix_type = 'kpp'
5252
Cp0 = 3992.0d0
5353
OBL_depth6 = 6000.0d0
5454
/
55+
56+
! Test 7 params
57+
&kpp_col7_nml
58+
ltest7 = .true.
59+
nlev7 = 10
60+
layer_thick7 = 5.0d0
61+
hmix7 = 17.0d0
62+
! Parameter settings to match LMD94 (linear interp, average Nsqr)
63+
interp_type_t7 = "linear"
64+
/

src/cvmix_driver.F90

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ Program cvmix_driver
3636
real(kind=cvmix_r8) :: ocn_depth
3737
character(len=cvmix_strlen) :: mix_type
3838

39+
external cvmix_BL_driver
40+
external cvmix_shear_driver
41+
external cvmix_tidal_driver
42+
external cvmix_ddiff_driver
43+
external cvmix_kpp_driver
44+
3945
namelist/cvmix_nml/mix_type, nlev, max_nlev, ocn_depth
4046

4147
mix_type = 'unset'

src/drivers/cvmix_kpp_drv.F90

Lines changed: 152 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Subroutine cvmix_kpp_driver()
4141
real(cvmix_r8), parameter :: third = cvmix_one / real(3,cvmix_r8)
4242

4343
! CVMix datatypes
44-
type(cvmix_data_type) :: CVmix_vars1, CVmix_vars4, CVmix_vars5
44+
type(cvmix_data_type) :: CVmix_vars1, CVmix_vars4, CVmix_vars5, CVmix_vars7
4545

4646
real(cvmix_r8), dimension(:), allocatable, target :: Mdiff, Tdiff, Sdiff
4747
real(cvmix_r8), dimension(:), allocatable, target :: zt, zw_iface, &
@@ -52,19 +52,23 @@ Subroutine cvmix_kpp_driver()
5252
delta_vel_sqr, &
5353
buoy_freq_iface
5454
real(cvmix_r8), dimension(:,:), allocatable, target :: hor_vel
55+
real(cvmix_r8), dimension(:), allocatable :: ones
5556
real(cvmix_r8), dimension(2) :: ref_vel
5657
real(cvmix_r8), dimension(4) :: shape_coeffs
57-
integer :: i, fid, kt, kw, nlev1, nlev3, nlev4, max_nlev4, OBL_levid4, nlev5
58-
real(cvmix_r8) :: hmix1, hmix5, ri_crit, layer_thick1, layer_thick4, &
59-
layer_thick5, OBL_depth4, OBL_depth5, N, Nsqr
58+
integer :: i, fid, kt, kw, nlev1, nlev3, nlev4, max_nlev4, OBL_levid4, &
59+
nlev5, nlev7
60+
real(cvmix_r8) :: hmix1, hmix5, hmix7, ri_crit, layer_thick1, &
61+
layer_thick4, layer_thick5, layer_thick7, OBL_depth4, &
62+
OBL_depth5, OBL_depth7, N, Nsqr
6063
real(cvmix_r8) :: kOBL_depth, Bslope, Vslope
6164
real(cvmix_r8) :: sigma6, OBL_depth6, surf_buoy_force6, surf_fric_vel6, &
6265
vonkarman6, tao, rho0, grav, alpha, Qnonpen, Cp0, &
6366
w_m6, w_s6, wm6_true, ws6_true
64-
character(len=cvmix_strlen) :: interp_type_t1, interp_type_t4, interp_type_t5
67+
character(len=cvmix_strlen) :: interp_type_t1, interp_type_t4, &
68+
interp_type_t5, interp_type_t7
6569
character(len=cvmix_strlen) :: filename
6670
! True => run specified test
67-
logical :: ltest1, ltest2, ltest3, ltest4, ltest5, ltest6
71+
logical :: ltest1, ltest2, ltest3, ltest4, ltest5, ltest6, ltest7
6872
logical :: lnoDGat1 ! True => G'(1) = 0 (in test 4)
6973

7074
namelist/kpp_col1_nml/ltest1, nlev1, layer_thick1, interp_type_t1, hmix1, &
@@ -75,6 +79,7 @@ Subroutine cvmix_kpp_driver()
7579
namelist/kpp_col5_nml/ltest5, nlev5, layer_thick5, hmix5, interp_type_t5
7680
namelist/kpp_col6_nml/ltest6, vonkarman6, tao, rho0, grav, alpha, Qnonpen, &
7781
Cp0, OBL_depth6
82+
namelist/kpp_col7_nml/ltest7, nlev7, layer_thick7, hmix7, interp_type_t7
7883

7984
! Read namelists
8085

@@ -117,12 +122,20 @@ Subroutine cvmix_kpp_driver()
117122
Cp0 = real(3992, cvmix_r8)
118123
OBL_depth6 = real(6000, cvmix_r8)
119124

125+
! Defaults for test 7
126+
ltest7 = .false.
127+
nlev7 = 10
128+
layer_thick7 = real(5, cvmix_r8)
129+
hmix7 = real(17, cvmix_r8)
130+
interp_type_t7 = "linear"
131+
120132
read(*, nml=kpp_col1_nml)
121133
read(*, nml=kpp_col2_nml)
122134
read(*, nml=kpp_col3_nml)
123135
read(*, nml=kpp_col4_nml)
124136
read(*, nml=kpp_col5_nml)
125137
read(*, nml=kpp_col6_nml)
138+
read(*, nml=kpp_col7_nml)
126139

127140
! Test 1: user sets up levels via namelist (constant thickness) and specifies
128141
! critical Richardson number as well as depth parameter hmix1. The
@@ -590,6 +603,139 @@ Subroutine cvmix_kpp_driver()
590603

591604
end if ! ltest6
592605

606+
! Test 7: Test 5, but lStokesMOST = .true.
607+
if (ltest7) then
608+
print*, ""
609+
print*, "Test 7: Computing Bulk Richardson number (with StokesMOST)"
610+
print*, "----------"
611+
612+
! using linear interpolation, averaging Nsqr, and setting Cv = 1.5 to
613+
! match LMD result
614+
call cvmix_init_kpp(Cv = 1.5_cvmix_r8, interp_type=interp_type_t7, &
615+
lStokesMOST=.true., lMonOb=.true.)
616+
617+
! Set up vertical levels (centers and interfaces) and compute bulk
618+
! Richardson number
619+
allocate(zt(nlev7), zw_iface(nlev7+1))
620+
do kw=1,nlev7+1
621+
zw_iface(kw) = -layer_thick7*real(kw-1, cvmix_r8)
622+
end do
623+
do kt=1,nlev7
624+
zt(kt) = 0.5_cvmix_r8 * (zw_iface(kt)+zw_iface(kt+1))
625+
end do
626+
627+
! Compute Br-B(d), |Vr-V(d)|^2, and Vt^2
628+
allocate(buoyancy(nlev7), delta_vel_sqr(nlev7), hor_vel(nlev7,2), &
629+
shear_sqr(nlev7), w_s(nlev7), Ri_bulk(nlev7), Ri_bulk2(nlev7), &
630+
buoy_freq_iface(nlev7+1))
631+
632+
ref_vel(1) = 0.1_cvmix_r8
633+
ref_vel(2) = cvmix_zero
634+
N = 0.01_cvmix_r8
635+
Nsqr = N*N
636+
Bslope = -Nsqr
637+
Vslope = -0.1_cvmix_r8 / (real(nlev7,cvmix_r8)*layer_thick7-hmix7)
638+
do kt=1,nlev7
639+
if ((zt(kt).ge.-hmix7).or.(kt.eq.1)) then
640+
buoyancy(kt) = Nsqr
641+
hor_vel(kt,1) = 0.1_cvmix_r8
642+
buoy_freq_iface(kt) = cvmix_zero
643+
else
644+
if (zw_iface(kt).ge.-hmix7) then
645+
! derivatives of buoyancy and horizontal velocity component are
646+
! discontinuous in this layer (no change -> non-zero linear change)
647+
! so we compute area-average of analytic function over layer
648+
buoyancy(kt) = Bslope*(-zw_iface(kt+1)-real(hmix7,cvmix_r8))**2 / &
649+
(real(2,cvmix_r8)*layer_thick7) + Nsqr
650+
hor_vel(kt,1) = Vslope*(-zw_iface(kt+1)-real(hmix7,cvmix_r8))**2 / &
651+
(real(2,cvmix_r8)*layer_thick7) + 0.1_cvmix_r8
652+
else
653+
buoyancy(kt) = Nsqr+Bslope*(-zt(kt)-real(hmix7,cvmix_r8))
654+
hor_vel(kt,1) = 0.1_cvmix_r8 + Vslope * &
655+
(-zt(kt)-real(hmix7,cvmix_r8))
656+
end if
657+
buoy_freq_iface(kt) = sqrt(-(buoyancy(kt)-buoyancy(kt-1)) / &
658+
layer_thick7)
659+
end if
660+
! Compute w_s with zeta=0 per LMD page 393
661+
! => w_s = von Karman * surf_fric_vel = 0.4*0.01 = 4e-3
662+
call cvmix_kpp_compute_turbulent_scales(cvmix_zero, -zt(kt), &
663+
buoyancy(1), 0.01_cvmix_r8, &
664+
w_s=w_s(kt))
665+
hor_vel(kt,2) = cvmix_zero
666+
delta_vel_sqr(kt) = (ref_vel(1)-hor_vel(kt,1))**2 + &
667+
(ref_vel(2)-hor_vel(kt,2))**2
668+
end do
669+
buoy_freq_iface(nlev7+1) = N
670+
! MNL: test both uses of compute_bulk_Richardson
671+
Ri_bulk = cvmix_kpp_compute_bulk_Richardson(zt, (buoyancy(1)-buoyancy), &
672+
delta_vel_sqr, &
673+
Nsqr_iface = buoy_freq_iface**2, &
674+
ws_cntr = w_s)
675+
676+
shear_sqr = cvmix_kpp_compute_unresolved_shear(zt, w_s, &
677+
Nsqr_iface = buoy_freq_iface**2)
678+
! Note that Vt_shear_sqr is the fourth argument in compute_bulk_Richardson
679+
! so it does not need to declared explicitly (even though it is optional)
680+
Ri_bulk2 = cvmix_kpp_compute_bulk_Richardson(zt, (buoyancy(1)-buoyancy), &
681+
delta_vel_sqr, shear_sqr)
682+
allocate(ones(nlev7))
683+
ones(:) = cvmix_one
684+
call cvmix_kpp_compute_OBL_depth(Ri_bulk, zw_iface, OBL_depth7, &
685+
kOBL_depth, zt, surf_fric=cvmix_one, &
686+
surf_buoy=ones, Xi=ones)
687+
deallocate(ones)
688+
do kt=1,nlev7
689+
if (abs(Ri_bulk(kt)-Ri_bulk2(kt)).gt.1e-12_cvmix_r8) then
690+
print*, "WARNING: two Ri_bulk computations did not match!"
691+
print*, zt(kt), Ri_bulk(kt), Ri_bulk2(kt)
692+
else
693+
print*, zt(kt), Ri_bulk(kt)
694+
end if
695+
end do
696+
print*, "OBL has depth of ", OBL_depth7
697+
#ifdef _NETCDF
698+
print*, "Done! Data is stored in test7.nc, run plot_bulk_Rich.ncl ", &
699+
"to see output."
700+
#else
701+
print*, "Done! Data is stored in test7.out, run plot_bulk_Rich.ncl ", &
702+
"to see output."
703+
#endif
704+
705+
CVmix_vars7%nlev = nlev7
706+
CVmix_vars7%BoundaryLayerDepth = OBL_depth7
707+
CVmix_vars7%zt_cntr => zt
708+
CVmix_vars7%BulkRichardson_cntr => Ri_bulk
709+
CVmix_vars7%Vx_cntr => hor_vel(:,1)
710+
#ifdef _NETCDF
711+
call cvmix_io_open(fid, "test7.nc", "nc")
712+
#else
713+
call cvmix_io_open(fid, "test7.out", "ascii")
714+
#endif
715+
call cvmix_output_write(fid, CVmix_vars7, (/"zt ", &
716+
"Ri_bulk ", &
717+
"Vx ", &
718+
"buoyancy"/), buoyancy)
719+
#ifdef _NETCDF
720+
call cvmix_output_write_att(fid, "OBL_depth", &
721+
CVmix_vars7%BoundaryLayerDepth)
722+
call cvmix_output_write_att(fid, "longname", "ocean height (cell center)",&
723+
"zt")
724+
call cvmix_output_write_att(fid, "units", "m", "zt")
725+
call cvmix_output_write_att(fid, "longname", "horizontal velocity", "U")
726+
call cvmix_output_write_att(fid, "units", "m/s", "U")
727+
call cvmix_output_write_att(fid, "units", "m/s^2", "buoyancy")
728+
call cvmix_output_write_att(fid, "longname", "Bulk Richardson number", &
729+
"BulkRichardson")
730+
call cvmix_output_write_att(fid, "units", "unitless", "BulkRichardson")
731+
#endif
732+
call cvmix_io_close(fid)
733+
734+
deallocate(zt, zw_iface)
735+
deallocate(buoyancy, delta_vel_sqr, hor_vel, shear_sqr, w_s, Ri_bulk, &
736+
Ri_bulk2, buoy_freq_iface)
737+
end if ! ltest7
738+
593739
!EOC
594740

595741
End Subroutine cvmix_kpp_driver

src/shared/cvmix_kpp.F90

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,7 +1576,7 @@ subroutine cvmix_kpp_compute_OBL_depth_low(Ri_bulk, zw_iface, OBL_depth, &
15761576
! Local variables
15771577
real(kind=cvmix_r8), dimension(:), pointer :: depth
15781578
real(kind=cvmix_r8), dimension(4) :: coeffs
1579-
real(kind=cvmix_r8) :: Ekman, MoninObukhov, OBL_Limit
1579+
real(kind=cvmix_r8) :: Ekman, MoninObukhov, OBL_Limit, numer, denom
15801580
integer :: nlev, k, kRi
15811581
logical :: lstable
15821582

@@ -1671,9 +1671,11 @@ subroutine cvmix_kpp_compute_OBL_depth_low(Ri_bulk, zw_iface, OBL_depth, &
16711671
if (CVmix_kpp_params_in%lMonOb ) then
16721672
if ( present(Xi) .and. present(surf_buoy) ) then
16731673
MoninObukhov = OBL_limit
1674+
numer = surf_fric**3
1675+
denom = surf_buoy(k+1) * (cvmix_one-Xi(k+1))
16741676
do k = 0, kRi-1
1675-
if (surf_buoy(k+1) .gt. cvmix_zero) MoninObukhov = &
1676-
surf_fric**3 / (surf_buoy(k+1) * (cvmix_one-Xi(k+1)))
1677+
if ( denom*OBL_limit .gt. numer ) MoninObukhov = &
1678+
numer / denom
16771679
if ( MoninObukhov .lt. abs(zt_cntr(k+1)) ) &
16781680
exit
16791681
end do

0 commit comments

Comments
 (0)