diff --git a/src/shared/cvmix_kinds_and_types.F90 b/src/shared/cvmix_kinds_and_types.F90 index 86bceab07..6b71165df 100644 --- a/src/shared/cvmix_kinds_and_types.F90 +++ b/src/shared/cvmix_kinds_and_types.F90 @@ -36,8 +36,9 @@ module cvmix_kinds_and_types ! Kind Types: ! The cvmix package uses double precision for floating point computations. - integer, parameter, public :: cvmix_r8 = selected_real_kind(15, 307), & - cvmix_strlen = 256 + integer, parameter, public :: cvmix_r8 = selected_real_kind(15, 307), & + cvmix_log_kind = kind(.true.), & + cvmix_strlen = 256 ! Parameters to allow CVMix to store integers instead of strings integer, parameter, public :: CVMIX_OVERWRITE_OLD_VAL = 1 @@ -82,12 +83,10 @@ module cvmix_kinds_and_types ! units: m^2 s^-3 ! latitude of column real(cvmix_r8) :: lat - ! units: can be degrees or radians (there are no internal - ! computations based on this term) + ! units: degrees ! longitude of column real(cvmix_r8) :: lon - ! units: can be degrees or radians (there are no internal - ! computations based on this term) + ! units: degrees ! Coriolis parameter real(cvmix_r8) :: Coriolis ! units: s^-1 @@ -134,6 +133,17 @@ module cvmix_kinds_and_types real(cvmix_r8), dimension(:), pointer :: VertDep_iface => NULL() ! units: unitless + ! A time-dependent coefficient needed for Schmittner 2014 + real(cvmix_r8), dimension(:), pointer :: SchmittnerCoeff => NULL() + + ! A time-invariant coefficient needed in Schmittner tidal mixing + real(cvmix_r8), dimension(:), pointer :: SchmittnerSouthernOcean => NULL() + + ! Another time-invariant coefficient needed in Schmittner tidal mixing + real(cvmix_r8), dimension(:,:), pointer :: exp_hab_zetar => NULL() + + + ! For KPP, need to store non-local transport term real(cvmix_r8), dimension(:), pointer :: kpp_Tnonlocal_iface => NULL() real(cvmix_r8), dimension(:), pointer :: kpp_Snonlocal_iface => NULL() diff --git a/src/shared/cvmix_put_get.F90 b/src/shared/cvmix_put_get.F90 index bc643c607..7e1681d77 100644 --- a/src/shared/cvmix_put_get.F90 +++ b/src/shared/cvmix_put_get.F90 @@ -37,6 +37,7 @@ module cvmix_put_get module procedure cvmix_put_int module procedure cvmix_put_real module procedure cvmix_put_real_1D + module procedure cvmix_put_real_2D module procedure cvmix_put_global_params_int module procedure cvmix_put_global_params_real end interface cvmix_put @@ -157,9 +158,9 @@ subroutine cvmix_put_real(CVmix_vars, varname, val, nlev_in) CVmix_vars%SurfaceFriction = val case ("SurfaceBuoyancyForcing") CVmix_vars%SurfaceBuoyancyForcing = val - case ("lat") + case ("Latitude") CVmix_vars%lat = val - case ("lon") + case ("Longitude") CVmix_vars%lon = val case ("Coriolis") CVmix_vars%Coriolis = val @@ -278,7 +279,7 @@ subroutine cvmix_put_real(CVmix_vars, varname, val, nlev_in) CVmix_vars%VertDep_iface(:) = val case default - print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put!" + print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put_real!" stop 1 end select @@ -432,9 +433,19 @@ subroutine cvmix_put_real_1D(CVmix_vars, varname, val, nlev_in) allocate(CVmix_vars%Vy_cntr(nlev)) end if CVmix_vars%Vy_cntr(:) = val + case ("SchmittnerSouthernOcean") + if (.not.associated(CVmix_vars%SchmittnerSouthernOcean)) then + allocate(CVmix_vars%SchmittnerSouthernOcean(CVmix_vars%max_nlev+1)) + end if + CVmix_vars%SchmittnerSouthernOcean(:) = val + case ("SchmittnerCoeff") + if (.not.associated(CVmix_vars%SchmittnerCoeff)) then + allocate(CVmix_vars%SchmittnerCoeff(CVmix_vars%max_nlev+1)) + end if + CVmix_vars%SchmittnerCoeff(:) = val case default - print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put!" + print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put_real_1D!" stop 1 end select @@ -445,6 +456,65 @@ end subroutine cvmix_put_real_1D !BOP +! !IROUTINE: cvmix_put_real_2D +! !INTERFACE: + + subroutine cvmix_put_real_2D(CVmix_vars, varname, val, nlev_in) + +! !DESCRIPTION: +! Write an array of real values into a cvmix\_data\_type variable. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + character(len=*), intent(in) :: varname + real(cvmix_r8), dimension(:,:), intent(in) :: val + integer, optional, intent(in) :: nlev_in + +! !OUTPUT PARAMETERS: + type(cvmix_data_type), intent(inout) :: CVmix_vars +!EOP +!BOC + + ! Local variables + integer :: nlev + + if (present(nlev_in)) then + nlev = nlev_in + else + nlev = CVmix_vars%max_nlev + end if + + if (nlev.eq.-1) then + print*, "ERROR: you must specify the number of levels before ", & + "you can pack data into a cvmix_data_type!" + print*, "You tried to set ", trim(varname) + stop 1 + end if + + select case (trim(cvmix_att_name(varname))) + case ("exp_hab_zetar") + if (.not.associated(CVmix_vars%exp_hab_zetar)) then + allocate(CVmix_vars%exp_hab_zetar(CVmix_vars%nlev+1,CVmix_vars%nlev+1)) + end if + CVmix_vars%exp_hab_zetar = val + + + case default + print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put_real_2D!" + stop 1 + + end select + +!EOC + + end subroutine cvmix_put_real_2D + +!BOP + ! !IROUTINE: cvmix_put_global_params_int ! !INTERFACE: @@ -472,7 +542,7 @@ subroutine cvmix_put_global_params_int(CVmix_params, varname, val) CVmix_params%max_nlev = val case default - print*, "ERROR: ", trim(varname), " not a valid choice!" + print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put_global_params_int!" stop 1 end select @@ -515,7 +585,7 @@ subroutine cvmix_put_global_params_real(CVmix_params, varname, val) case ('g','Gravity') CVmix_params%Gravity = val case default - print*, "ERROR: ", trim(varname), " not a valid choice!" + print*, "ERROR: ", trim(varname), " not a valid choice for cvmix_put_global_params_real!" stop 1 end select diff --git a/src/shared/cvmix_tidal.F90 b/src/shared/cvmix_tidal.F90 index 4a901065e..5f1925441 100644 --- a/src/shared/cvmix_tidal.F90 +++ b/src/shared/cvmix_tidal.F90 @@ -23,7 +23,9 @@ module cvmix_tidal ! !USES: use cvmix_kinds_and_types, only : cvmix_r8, & + cvmix_log_kind, & cvmix_zero, & + cvmix_one, & cvmix_data_type, & cvmix_strlen, & cvmix_global_params_type, & @@ -44,15 +46,21 @@ module cvmix_tidal ! !PUBLIC MEMBER FUNCTIONS: public :: cvmix_init_tidal - public :: cvmix_compute_vert_dep public :: cvmix_coeffs_tidal + public :: cvmix_coeffs_tidal_schmittner public :: cvmix_compute_Simmons_invariant + public :: cvmix_compute_Schmittner_invariant + public :: cvmix_compute_SchmittnerCoeff + public :: cvmix_compute_socn_tidal_invariant + public :: cvmix_compute_vert_dep + public :: cvmix_compute_vert_dep_Schmittner public :: cvmix_put_tidal public :: cvmix_get_tidal_real public :: cvmix_get_tidal_str interface cvmix_coeffs_tidal module procedure cvmix_coeffs_tidal_low +! module procedure cvmix_coeffs_tidal_schmittner module procedure cvmix_coeffs_tidal_wrap end interface cvmix_coeffs_tidal @@ -61,8 +69,24 @@ module cvmix_tidal module procedure cvmix_compute_Simmons_invariant_wrap end interface cvmix_compute_Simmons_invariant + interface cvmix_compute_Schmittner_invariant + module procedure cvmix_compute_Schmittner_invariant_low + module procedure cvmix_compute_Schmittner_invariant_wrap + end interface cvmix_compute_Schmittner_invariant + + interface cvmix_compute_SchmittnerCoeff + module procedure cvmix_compute_SchmittnerCoeff_low + module procedure cvmix_compute_SchmittnerCoeff_wrap + end interface cvmix_compute_SchmittnerCoeff + + interface cvmix_compute_socn_tidal_invariant + module procedure cvmix_compute_socn_tidal_invariant_low + module procedure cvmix_compute_socn_tidal_invariant_wrap + end interface cvmix_compute_socn_tidal_invariant + interface cvmix_put_tidal module procedure cvmix_put_tidal_int + module procedure cvmix_put_tidal_logical module procedure cvmix_put_tidal_real module procedure cvmix_put_tidal_str end interface cvmix_put_tidal @@ -86,6 +110,10 @@ module cvmix_tidal ! vertical deposition function) real(cvmix_r8) :: vertical_decay_scale ! units: m + ! vertical_decay_scaleR is zetar in Schmittner method (used to compute the + ! vertical deposition function) + real(cvmix_r8) :: vertical_decay_scaleR ! units: m + ! depth_cutoff is depth of the shallowest column where tidal mixing is ! computed (like all depths, positive => below the surface) real(cvmix_r8) :: depth_cutoff ! units: m @@ -96,6 +124,9 @@ module cvmix_tidal ! Flag for what to do with old values of CVmix_vars%[MTS]diff integer :: handle_old_vals + ! Flag for controlling application of Schmittner Southern-Ocean mods + logical(cvmix_log_kind) :: ltidal_Schmittner_socn + ! Note: need to include some logic to avoid excessive memory use end type cvmix_tidal_params_type !EOP @@ -111,28 +142,31 @@ module cvmix_tidal subroutine cvmix_init_tidal(CVmix_tidal_params_user, mix_scheme, efficiency,& vertical_decay_scale, max_coefficient, & - local_mixing_frac, depth_cutoff, old_vals) + local_mixing_frac, depth_cutoff, & + ltidal_Schmittner_socn, old_vals) ! !DESCRIPTION: ! Initialization routine for tidal mixing. There is currently just one ! supported schemes - set \verb|mix_scheme = 'simmons'| to use the Simmons ! mixing scheme. +! - set \verb|mix_scheme = 'schmittner'| to use the Schmittner +! mixing scheme. ! ! !USES: ! Only those used by entire module. ! !INPUT PARAMETERS: - character(len=*), optional, intent(in) :: mix_scheme, old_vals - real(cvmix_r8), optional, intent(in) :: efficiency - real(cvmix_r8), optional, intent(in) :: vertical_decay_scale - real(cvmix_r8), optional, intent(in) :: max_coefficient - real(cvmix_r8), optional, intent(in) :: local_mixing_frac - real(cvmix_r8), optional, intent(in) :: depth_cutoff + character(len=*), optional, intent(in) :: mix_scheme, old_vals + real(cvmix_r8), optional, intent(in) :: efficiency + real(cvmix_r8), optional, intent(in) :: vertical_decay_scale + real(cvmix_r8), optional, intent(in) :: max_coefficient + real(cvmix_r8), optional, intent(in) :: local_mixing_frac + real(cvmix_r8), optional, intent(in) :: depth_cutoff + logical(cvmix_log_kind), optional, intent(in) :: ltidal_Schmittner_socn ! !OUTPUT PARAMETERS: type(cvmix_tidal_params_type), optional, target, intent(inout) :: & CVmix_tidal_params_user - !EOP !BOC @@ -194,6 +228,49 @@ subroutine cvmix_init_tidal(CVmix_tidal_params_user, mix_scheme, efficiency,& CVmix_tidal_params_user) end if + if (present(ltidal_Schmittner_socn)) then + call cvmix_put_tidal("ltidal_Schmittner_socn", ltidal_Schmittner_socn, & + CVmix_tidal_params_user) + else + ! Default: do not apply Schmittner Southern Ocean mods + call cvmix_put_tidal("ltidal_Schmittner_socn", .false., CVmix_tidal_params_user) + end if + + case ('schmittner','Schmittner') + ! Unitless parameters + if (present(efficiency)) then + call cvmix_put_tidal("efficiency", efficiency, & + CVmix_tidal_params_user) + else + call cvmix_put_tidal("efficiency", 0.2_cvmix_r8, & + CVmix_tidal_params_user) + end if + + ! Parameters with units + if (present(vertical_decay_scale)) then + call cvmix_put_tidal("vertical_decay_scaleR", cvmix_one/vertical_decay_scale, & + CVmix_tidal_params_user) + else + call cvmix_put_tidal("vertical_decay_scaleR", cvmix_one/500.0_cvmix_r8, & + CVmix_tidal_params_user) + end if + + if (present(max_coefficient)) then + call cvmix_put_tidal("max_coefficient", max_coefficient, & + CVmix_tidal_params_user) + else + call cvmix_put_tidal("max_coefficient", 50e-4_cvmix_r8, & + CVmix_tidal_params_user) + end if + + if (present(ltidal_Schmittner_socn)) then + call cvmix_put_tidal("ltidal_Schmittner_socn", ltidal_Schmittner_socn, & + CVmix_tidal_params_user) + else + ! Default: do not apply Schmittner Southern Ocean mods + call cvmix_put_tidal("ltidal_Schmittner_socn", .false., CVmix_tidal_params_user) + end if + case DEFAULT print*, "ERROR: ", trim(mix_scheme), " is not a valid choice for ", & "tidal mixing." @@ -231,7 +308,8 @@ end subroutine cvmix_init_tidal ! !IROUTINE: cvmix_coeffs_tidal_wrap ! !INTERFACE: - subroutine cvmix_coeffs_tidal_wrap(CVmix_vars, CVmix_params, & + subroutine cvmix_coeffs_tidal_wrap(CVmix_vars, & + CVmix_params, & CVmix_tidal_params_user) ! !DESCRIPTION: @@ -266,15 +344,33 @@ subroutine cvmix_coeffs_tidal_wrap(CVmix_vars, CVmix_params, & nlev = CVmix_vars%nlev max_nlev = CVmix_vars%max_nlev - call cvmix_coeffs_tidal(new_Mdiff, new_Tdiff, & - CVmix_vars%SqrBuoyancyFreq_iface, & - CVmix_vars%OceanDepth, CVmix_vars%SimmonsCoeff, & - CVmix_vars%VertDep_iface, nlev, max_nlev, & - CVMix_params, CVmix_tidal_params_user) - call cvmix_update_wrap(CVmix_tidal_params_in%handle_old_vals, max_nlev, & - Mdiff_out = CVmix_vars%Mdiff_iface, & - Tdiff_out = CVmix_vars%Tdiff_iface, & - new_Mdiff = new_Mdiff, & + select case (trim(CVmix_tidal_params_in%mix_scheme)) + case ('simmons','Simmons') + call cvmix_coeffs_tidal_low & + (new_Mdiff, new_Tdiff, & + CVmix_vars%SqrBuoyancyFreq_iface, & + CVmix_vars%OceanDepth, & + CVmix_vars%SimmonsCoeff, & + CVmix_vars%VertDep_iface, nlev, max_nlev, & + CVMix_params, & + CVmix_vars%SchmittnerSouthernOcean, & + CVmix_tidal_params_user) + case ('schmittner','Schmittner') + call cvmix_coeffs_tidal_schmittner & + (new_Mdiff, new_Tdiff, & + CVmix_vars%SqrBuoyancyFreq_iface, & + CVmix_vars%OceanDepth, & + CVmix_vars%VertDep_iface, nlev, max_nlev, & + CVmix_vars%SchmittnerCoeff, & + CVmix_vars%SchmittnerSouthernOcean, & + CVMix_params, & + CVmix_tidal_params_user) + + end select + call cvmix_update_wrap(CVmix_tidal_params_in%handle_old_vals, max_nlev, & + Mdiff_out = CVmix_vars%Mdiff_iface, & + Tdiff_out = CVmix_vars%Tdiff_iface, & + new_Mdiff = new_Mdiff, & new_Tdiff = new_Tdiff) !EOC @@ -288,7 +384,9 @@ end subroutine cvmix_coeffs_tidal_wrap subroutine cvmix_coeffs_tidal_low(Mdiff_out, Tdiff_out, Nsqr, OceanDepth, & SimmonsCoeff, vert_dep, nlev, max_nlev, & - CVmix_params, CVmix_tidal_params_user) + CVmix_params, & + SchmittnerSouthernOcean, & + CVmix_tidal_params_user) ! !DESCRIPTION: ! Computes vertical diffusion coefficients for tidal mixing @@ -302,11 +400,13 @@ subroutine cvmix_coeffs_tidal_low(Mdiff_out, Tdiff_out, Nsqr, OceanDepth, & ! !INPUT PARAMETERS: type(cvmix_tidal_params_type), target, optional, intent(in) :: & CVmix_tidal_params_user - integer, intent(in) :: nlev, max_nlev type(cvmix_global_params_type), intent(in) :: CVmix_params + integer, intent(in) :: nlev, max_nlev + real(cvmix_r8), dimension(max_nlev+1), intent(in) :: Nsqr, vert_dep real(cvmix_r8), intent(in) :: OceanDepth real(cvmix_r8), intent(in) :: SimmonsCoeff - real(cvmix_r8), dimension(max_nlev+1), intent(in) :: Nsqr, vert_dep + real(cvmix_r8), dimension(max_nlev+1), intent(in), & + optional :: SchmittnerSouthernOcean ! !INPUT/OUTPUT PARAMETERS: real(cvmix_r8), dimension(max_nlev+1), intent(inout) :: Mdiff_out @@ -317,6 +417,7 @@ subroutine cvmix_coeffs_tidal_low(Mdiff_out, Tdiff_out, Nsqr, OceanDepth, & ! Local variables integer :: k + real(cvmix_r8), dimension(max_nlev+1) :: SchmittnerSouthernOceanLocal type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params @@ -326,15 +427,29 @@ subroutine cvmix_coeffs_tidal_low(Mdiff_out, Tdiff_out, Nsqr, OceanDepth, & CVmix_tidal_params => CVmix_tidal_params_saved end if + if (present(SchmittnerSouthernOcean)) then + SchmittnerSouthernOceanLocal = SchmittnerSouthernOcean + else + SchmittnerSouthernOceanLocal = cvmix_zero + end if + select case (trim(CVmix_tidal_params%mix_scheme)) case ('simmons','Simmons') Tdiff_out = cvmix_zero if (OceanDepth.ge.CVmix_tidal_params%depth_cutoff) then do k=1, nlev+1 + !*** compute tidal diffusion if (Nsqr(k).gt.cvmix_zero) & Tdiff_out(k) = SimmonsCoeff*vert_dep(k)/Nsqr(k) + + !*** apply Scmittner Southern Ocean modification + if (CVmix_tidal_params%ltidal_Schmittner_socn .and. k<=nlev)& + Tdiff_out(k) = max(Tdiff_out(k),SchmittnerSouthernOcean(k)) + + !*** apply tidal diffusion cap if (Tdiff_out(k).gt.CVmix_tidal_params%max_coefficient) & Tdiff_out(k) = CVmix_tidal_params%max_coefficient + end do end if @@ -352,9 +467,92 @@ end subroutine cvmix_coeffs_tidal_low !BOP -! !IROUTINE: cvmix_compute_vert_dep +! !IROUTINE: cvmix_coeffs_tidal_schmittner ! !INTERFACE: + subroutine cvmix_coeffs_tidal_schmittner & + (Mdiff_out, Tdiff_out, Nsqr, OceanDepth, & + vert_dep, nlev, max_nlev, & + SchmittnerCoeff, & + SchmittnerSouthernOcean, & + CVmix_params, & + CVmix_tidal_params_user) + +! !DESCRIPTION: +! Computes vertical diffusion coefficients for tidal mixing +! parameterizations. +!\\ +!\\ +! +! !USES: +! only those used by entire module. + +! !INPUT PARAMETERS: + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + integer, intent(in) :: nlev, max_nlev + type(cvmix_global_params_type), intent(in) :: CVmix_params + real(cvmix_r8), intent(in) :: OceanDepth + real(cvmix_r8), dimension(max_nlev+1), intent(in) :: Nsqr, vert_dep + real(cvmix_r8), dimension(max_nlev+1), intent(in) :: SchmittnerSouthernOcean + real(cvmix_r8), dimension(max_nlev+1), intent(in) :: SchmittnerCoeff + +! !INPUT/OUTPUT PARAMETERS: + real(cvmix_r8), dimension(max_nlev+1), intent(inout) :: Mdiff_out + real(cvmix_r8), dimension(max_nlev+1), intent(inout) :: Tdiff_out + +!EOP +!BOC + + ! Local variables + integer :: k + + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + select case (trim(CVmix_tidal_params%mix_scheme)) + + case ('schmittner','Schmittner') + Tdiff_out = cvmix_zero + if (OceanDepth.ge.CVmix_tidal_params%depth_cutoff) then + do k=1, nlev+1 + !*** compute tidal diffusion + if (Nsqr(k).gt.cvmix_zero) & + Tdiff_out(k) = SchmittnerCoeff(k)/Nsqr(k) + + !*** apply Scmittner Southern Ocean modification + if (CVmix_tidal_params%ltidal_Schmittner_socn .and. k<=nlev)& + Tdiff_out(k) = max(Tdiff_out(k),SchmittnerSouthernOcean(k)) + + !*** apply tidal diffusion cap + if (Tdiff_out(k).gt.CVmix_tidal_params%max_coefficient) & + Tdiff_out(k) = CVmix_tidal_params%max_coefficient + + end do + + end if + + case DEFAULT + ! Note: this error should be caught in cvmix_init_tidal + print*, "ERROR: invalid choice for type of tidal mixing." + stop 1 + + end select + Mdiff_out = CVmix_params%Prandtl*Tdiff_out + +!EOC + + end subroutine cvmix_coeffs_tidal_schmittner + +!BOP + !IROUTINE: cvmix_compute_vert_dep + !INTERFACE: + function cvmix_compute_vert_dep(zw, zt, nlev, CVmix_tidal_params) ! !DESCRIPTION: @@ -406,7 +604,50 @@ function cvmix_compute_vert_dep(zw, zt, nlev, CVmix_tidal_params) end function cvmix_compute_vert_dep !BOP + !IROUTINE: cvmix_compute_vert_dep_Schmittner + !INTERFACE: + + function cvmix_compute_vert_dep_Schmittner(zw, nlev, CVmix_tidal_params) + +! !DESCRIPTION: +! Computes the vertical deposition function needed for Schmittner 2014 tidal +! mixing. +!\\ +!\\ +! +! !USES: +! only those used by entire module. + +! !INPUT PARAMETERS: + type(cvmix_tidal_params_type), intent(in) :: CVmix_tidal_params + integer, intent(in) :: nlev + real(cvmix_r8), dimension(nlev+1), intent(in) :: zw + +! !OUTPUT PARAMETERS: + real(cvmix_r8), dimension(nlev+1) :: cvmix_compute_vert_dep_Schmittner + +!EOP +!BOC + ! Local variables + real(cvmix_r8) :: zetar + integer :: k + + zetar = CVmix_tidal_params%vertical_decay_scaleR + + ! Compute Schmittner-method vertical decay profile + cvmix_compute_vert_dep_Schmittner(1) = cvmix_zero + do k=2,nlev+1 + cvmix_compute_vert_dep_Schmittner(k) = zetar/(cvmix_one-exp(zetar*zw(k))) +! cvmix_compute_vert_dep_Schmittner(k) = zetar/(cvmix_one-exp(zetar*zw(k+1))) +! cvmix_compute_vert_dep_Schmittner(k) = zetar/(cvmix_one-exp(zetar*zw(k-1))) + end do + +!EOC + + end function cvmix_compute_vert_dep_Schmittner + +!BOP ! !IROUTINE: cvmix_compute_Simmons_invariant_wrap ! !INTERFACE: @@ -509,6 +750,329 @@ subroutine cvmix_compute_Simmons_invariant_low(nlev, energy_flux, rho, & end subroutine cvmix_compute_Simmons_invariant_low +!BOP +! !IROUTINE: cvmix_compute_Schmittner_invariant_wrap +! !INTERFACE: + + subroutine cvmix_compute_Schmittner_invariant_wrap(CVmix_vars, & + CVmix_params,& + CVmix_tidal_params_user) + +! !DESCRIPTION: +! Compute the time-invariant portion of the tidal mixing coefficient using +! the Schmittner 2014 scheme. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + type(cvmix_global_params_type), intent(in) :: CVmix_params + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + +! !INPUT/OUTPUT PARAMETERS: + type(cvmix_data_type), intent(inout) :: CVmix_vars + +!EOP + + ! local variables + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + call cvmix_put(CVmix_vars, 'VertDep', cvmix_zero) + + call cvmix_compute_Schmittner_invariant_low(CVmix_vars%nlev, & + CVmix_vars%VertDep_iface, & + CVmix_tidal_params%efficiency, & + CVmix_params%FreshWaterDensity, & + CVmix_vars%exp_hab_zetar, & + CVmix_vars%zw_iface, & + CVMix_tidal_params_user) + +!EOC + + end subroutine cvmix_compute_Schmittner_invariant_wrap + +!BOP +! !IROUTINE: cvmix_compute_Schmittner_invariant_low +! !INTERFACE: + + subroutine cvmix_compute_Schmittner_invariant_low(nlev, VertDep, efficiency, rho, & + exp_hab_zetar, zw, & + CVmix_tidal_params_user) + +! !DESCRIPTION: +! Compute the time-invariant portion of the tidal mixing coefficient using +! the Schmittner 2014 scheme. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + integer, intent(in) :: nlev + real(cvmix_r8), intent(in) :: efficiency + real(cvmix_r8), intent(in) :: rho + real(cvmix_r8), dimension(:), intent(in) :: zw + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + +! !OUTPUT PARAMETERS: + real(cvmix_r8), dimension(1:nlev+1), intent(inout) :: VertDep + real(cvmix_r8), dimension(2:nlev+1,2:nlev+1), intent(inout) :: exp_hab_zetar + +!EOP + + ! local variables + real(cvmix_r8) :: hab ! height above bottom + real(cvmix_r8) :: term + real(cvmix_r8) :: zetar + integer :: k,k1 ! indices + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + term = efficiency/rho + zetar = CVmix_tidal_params%vertical_decay_scaleR + + VertDep = cvmix_compute_vert_dep_Schmittner(zw(1:nlev+1), nlev,& + CVmix_tidal_params) + + do k=2,nlev + do k1=k+1,nlev+1 + hab= zw(k1)-zw(k) + exp_hab_zetar(k,k1)=term*exp(hab*zetar)*VertDep(k1) + enddo + enddo + +!BOC + +!EOC + + end subroutine cvmix_compute_Schmittner_invariant_low + +!BOP +! !IROUTINE: cvmix_compute_SchmittnerCoeff_wrap +! !INTERFACE: + + subroutine cvmix_compute_SchmittnerCoeff_wrap(CVmix_vars, CVmix_params, nlev, & + energy_flux, CVmix_tidal_params_user) + +! !DESCRIPTION: +! Compute the full time-dependent tidal mixing coefficient using +! the Schmittner 2014 scheme. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + integer, intent(in) :: nlev + type(cvmix_global_params_type), intent(in) :: CVmix_params + real(cvmix_r8), dimension(2:nlev+1), intent(in) :: energy_flux + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + +! !INPUT/OUTPUT PARAMETERS: + type(cvmix_data_type), intent(inout) :: CVmix_vars + +!EOP + + ! local variables + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + call cvmix_compute_SchmittnerCoeff_low(CVmix_vars%nlev, & + energy_flux, & + CVmix_params%FreshWaterDensity, & + CVmix_vars%SchmittnerCoeff, & + CVmix_vars%exp_hab_zetar, & + CVMix_tidal_params_user) + +!EOC + + end subroutine cvmix_compute_SchmittnerCoeff_wrap + +!BOP +! !IROUTINE: cvmix_compute_SchmittnerCoeff_low +! !INTERFACE: + + subroutine cvmix_compute_SchmittnerCoeff_low(nlev, energy_flux, rho, & + SchmittnerCoeff, & + exp_hab_zetar, & + CVmix_tidal_params_user) + +! !DESCRIPTION: +! Compute the time-dependent portion of the tidal mixing coefficient using +! the Schmittner 2014 scheme. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + integer, intent(in) :: nlev + real(cvmix_r8), intent(in) :: rho + real(cvmix_r8), dimension(2:nlev+1,2:nlev+1), intent(in) :: exp_hab_zetar + real(cvmix_r8), dimension(2:nlev+1), intent(in) :: energy_flux + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + +! !OUTPUT PARAMETERS: + real(cvmix_r8), dimension(:), intent(out) :: SchmittnerCoeff + +!EOP + + ! local variables + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + integer :: k,k1 + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + SchmittnerCoeff(:) = cvmix_zero + + do k=2,nlev + do k1=k+1,nlev+1 + !note... need to put energy_flux onto interface level + SchmittnerCoeff(k) = & + SchmittnerCoeff(k) + energy_flux(k1)*exp_hab_zetar(k,k1) + enddo + enddo + +!BOC + +!EOC + + end subroutine cvmix_compute_SchmittnerCoeff_low + +!BOP +! !IROUTINE: cvmix_compute_socn_tidal_invariant_wrap +! !INTERFACE: + + subroutine cvmix_compute_socn_tidal_invariant_wrap(CVmix_vars, & + CVmix_params, & + CVmix_tidal_params_user) + +! !DESCRIPTION: +! Compute the time-invariant Schmittner Southern-Ocean tidal mixing terms +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + type(cvmix_global_params_type), intent(in) :: CVmix_params + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + +! !INPUT/OUTPUT PARAMETERS: + type(cvmix_data_type), intent(inout) :: CVmix_vars + +!EOP + + ! local variables + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + if (CVmix_tidal_params%ltidal_Schmittner_socn) & + call cvmix_compute_socn_tidal_invariant_low(CVmix_vars%nlev, & + CVmix_vars%lat, & + CVmix_vars%lon, & + CVmix_vars%zw_iface, & + cvmix_vars%SchmittnerSouthernOcean,& + CVMix_tidal_params_user ) + +!EOC + + end subroutine cvmix_compute_socn_tidal_invariant_wrap + +!BOP + +! !IROUTINE: cvmix_compute_socn_tidal_invariant_low +! !INTERFACE: + + subroutine cvmix_compute_socn_tidal_invariant_low(nlev, & + lat, & + lon, & + zw, & + SchmittnerSouthernOcean, & + CVmix_tidal_params_user ) + +! !DESCRIPTION: +! Compute the time-invariant Schmittner Southern-Ocean tidal mixing terms +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + integer, intent(in) :: nlev + real(cvmix_r8), intent(in) :: lat + real(cvmix_r8), intent(in) :: lon + real(cvmix_r8), dimension(:), intent(in) :: zw + type(cvmix_tidal_params_type), target, optional, intent(in) :: & + CVmix_tidal_params_user + + !OUTPUT PARAMETERS: + real(cvmix_r8),dimension(:),intent(inout) :: SchmittnerSouthernOcean + +!EOP + + ! local variables + integer :: k + real(cvmix_r8) :: SchmittnerTanhLat + real(cvmix_r8) :: SchmittnerTanhZw + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params + +!BOC + + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params => CVmix_tidal_params_user + else + CVmix_tidal_params => CVmix_tidal_params_saved + end if + + SchmittnerTanhLat = 0.5_cvmix_r8*(cvmix_one-tanh((lat+40.0_cvmix_r8)/8.0_cvmix_r8)) + + do k=1, nlev+1 + SchmittnerTanhZw = tanh((-zw(k)-500._cvmix_r8)/100.0_cvmix_r8)*1.0e-4_cvmix_r8 + SchmittnerSouthernOcean(k) = SchmittnerTanhLat*SchmittnerTanhZw + end do + +!EOC + + end subroutine cvmix_compute_socn_tidal_invariant_low + !BOP ! !IROUTINE: cvmix_put_tidal_int @@ -554,6 +1118,49 @@ subroutine cvmix_put_tidal_int(varname, val, CVmix_tidal_params_user) end subroutine cvmix_put_tidal_int +! !IROUTINE: cvmix_put_tidal_logical +! !INTERFACE: + + subroutine cvmix_put_tidal_logical(varname, val, CVmix_tidal_params_user) + +! !DESCRIPTION: +! Write a logical value into a cvmix\_tidal\_params\_type variable. +!\\ +!\\ + +! !USES: +! Only those used by entire module. + +! !INPUT PARAMETERS: + character(len=*), intent(in) :: varname + logical(cvmix_log_kind),intent(in) :: val + +! !OUTPUT PARAMETERS: + type(cvmix_tidal_params_type), optional, target, intent(inout) :: & + CVmix_tidal_params_user + +!EOP +!BOC + + type(cvmix_tidal_params_type), pointer :: CVmix_tidal_params_out + + CVmix_tidal_params_out => CVmix_tidal_params_saved + if (present(CVmix_tidal_params_user)) then + CVmix_tidal_params_out => CVmix_tidal_params_user + end if + + select case (trim(varname)) + case ('ltidal_Schmittner_socn') + CVmix_tidal_params_out%ltidal_Schmittner_socn = val + case DEFAULT + print*, "ERROR: ", trim(varname), " is not a boolean variable!" + stop 1 + end select + +!EOC + + end subroutine cvmix_put_tidal_logical + !BOP ! !IROUTINE: cvmix_put_tidal_real @@ -593,6 +1200,8 @@ subroutine cvmix_put_tidal_real(varname, val, CVmix_tidal_params_user) CVmix_tidal_params_out%efficiency = val case ('vertical_decay_scale') CVmix_tidal_params_out%vertical_decay_scale = val + case ('vertical_decay_scaleR') + CVmix_tidal_params_out%vertical_decay_scaleR = val case ('max_coefficient') CVmix_tidal_params_out%max_coefficient = val case ('local_mixing_frac') diff --git a/src/shared/cvmix_utils.F90 b/src/shared/cvmix_utils.F90 index f791f0107..c119fa528 100644 --- a/src/shared/cvmix_utils.F90 +++ b/src/shared/cvmix_utils.F90 @@ -145,9 +145,9 @@ function cvmix_att_name(varname) case ("surf_buoy", "SurfaceBuoyancy", "SurfaceBuoyancyForcing") cvmix_att_name = "SurfaceBuoyancyForcing" case ("lat", "latitude", "Latitude") - cvmix_att_name = "lat" + cvmix_att_name = "Latitude" case ("lon", "longitude", "Longitude") - cvmix_att_name = "lon" + cvmix_att_name = "Longitude" case ("coriolis", "Coriolis", "CoriolisFreq", "CoriolisFrequency") cvmix_att_name = "Coriolis" case ("kOBL_depth", "BoundaryLayerDepthIndex") @@ -158,6 +158,10 @@ function cvmix_att_name(varname) cvmix_att_name = "LangmuirEnhancementFactor" case ("SurfaceStokesDrift", "stokes_drift") cvmix_att_name = "SurfaceStokesDrift" + case ("ltidal_Schmittner_socn") + cvmix_att_name = "UseSchmittnerSouthernOceanMods" + case ("ltidal_max") + cvmix_att_name = "ApplyTidalMixingCap" ! Variables on level interfaces case ("zw", "zw_iface") @@ -218,6 +222,12 @@ function cvmix_att_name(varname) cvmix_att_name = "Vy_cntr" case ("SimmonsCoeff", "TidalCoeff") cvmix_att_name = "SimmonsCoeff" + case ("SchmittnerCoeff") + cvmix_att_name = "SchmittnerCoeff" + case ("SchmittnerSouthernOcean") + cvmix_att_name = "SchmittnerSouthernOcean" + case ("exp_hab_zetar") + cvmix_att_name = "exp_hab_zetar" case ("VertDep", "VertDep_iface", "vert_dep") cvmix_att_name = "VertDep_iface" case DEFAULT