diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml
index 2a21e22f40d2..00d926278fbc 100644
--- a/components/mpas-ocean/src/Registry.xml
+++ b/components/mpas-ocean/src/Registry.xml
@@ -2008,6 +2008,7 @@
+
diff --git a/components/mpas-ocean/src/shared/Makefile b/components/mpas-ocean/src/shared/Makefile
index d378b68624bb..27c3db10fee1 100644
--- a/components/mpas-ocean/src/shared/Makefile
+++ b/components/mpas-ocean/src/shared/Makefile
@@ -157,7 +157,7 @@ mpas_ocn_tracer_short_wave_absorption_variable.o: mpas_ocn_constants.o mpas_ocn_
mpas_ocn_tracer_short_wave_absorption_jerlov.o: mpas_ocn_constants.o mpas_ocn_config.o
-mpas_ocn_vmix.o: mpas_ocn_vmix_cvmix.o mpas_ocn_vmix_coefs_redi.o mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_diagnostics_variables.o mpas_ocn_vmix_gotm.o
+mpas_ocn_vmix.o: mpas_ocn_vmix_cvmix.o mpas_ocn_vmix_coefs_redi.o mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_diagnostics_variables.o mpas_ocn_vmix_gotm.o mpas_ocn_diagnostics.o
mpas_ocn_vmix_cvmix.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_diagnostics_variables.o mpas_ocn_mesh.o mpas_ocn_stokes_drift.o
diff --git a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F
index 0334667f2f10..691bfe70b589 100644
--- a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F
+++ b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F
@@ -64,7 +64,7 @@ module ocn_diagnostics
ocn_fuperp, &
ocn_filter_btr_mode_tend_vel, &
ocn_reconstruct_eddy_vectors, &
- ocn_compute_kpp_input_fields, &
+ ocn_compute_mixing_input_fields, &
ocn_validate_state, &
ocn_build_log_filename, &
ocn_diagnostics_init
@@ -3319,12 +3319,12 @@ end subroutine ocn_filter_btr_mode_tend_vel!}}}
!***********************************************************************
!
-! routine ocn_compute_KPP_input_fields
+! routine ocn_compute_mixing_input_fields
!
!> \brief
-!> Compute fields necessary to drive the CVMix KPP module
-!> \author Todd Ringler
-!> \date 20 August 2013
+!> Compute fields necessary to drive the CVMix KPP and gotm modules
+!> \author Todd Ringler, Luke Van Roekel
+!> \date 11 July 2024
!> \details
!> CVMix/KPP requires the following fields as intent(in):
!> surfaceBuoyancyForcing
@@ -3333,7 +3333,7 @@ end subroutine ocn_filter_btr_mode_tend_vel!}}}
!
!-----------------------------------------------------------------------
- subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
+ subroutine ocn_compute_mixing_input_fields(statePool, forcingPool, &
meshPool, timeLevelIn)!{{{
!-----------------------------------------------------------------
@@ -3385,8 +3385,7 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
evapTemperatureFlux, &
icebergTemperatureFlux, &
seaIceTemperatureFlux, &
- surfaceStress, &
- surfaceStressMagnitude
+ sfcStressMag
real (kind=RKIND), dimension(:,:), pointer :: &
layerThickness, &! layer thickness
@@ -3419,7 +3418,7 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
!-----------------------------------------------------------------
! Begin code
- call mpas_timer_start('KPP input fields')
+ call mpas_timer_start('Mixing input fields')
if (present(timeLevelIn)) then
timeLevel = timeLevelIn
@@ -3469,18 +3468,8 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
surfaceThicknessFluxSubglacialRunoff)
call mpas_pool_get_array(forcingPool, 'penetrativeTemperatureFlux', &
penetrativeTemperatureFlux)
- call mpas_pool_get_array(forcingPool, 'surfaceStress', &
- surfaceStress)
call mpas_pool_get_array(forcingPool, 'surfaceStressMagnitude', &
- surfaceStressMagnitude)
- call mpas_pool_get_array(forcingPool, 'rainTemperatureFlux', &
- rainTemperatureFlux)
- call mpas_pool_get_array(forcingPool, 'evapTemperatureFlux', &
- evapTemperatureFlux)
- call mpas_pool_get_array(forcingPool, 'seaIceTemperatureFlux', &
- seaIceTemperatureFlux)
- call mpas_pool_get_array(forcingPool, 'icebergTemperatureFlux', &
- icebergTemperatureFlux)
+ sfcStressMag)
! allocate scratch space displaced density computation
ncells = nCellsAll
@@ -3594,17 +3583,8 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
activeTracersSurfaceFlux(indexTempFlux,iCell) &
+ penetrativeTemperatureFlux(iCell) &
- penetrativeTemperatureFluxOBL(iCell) &
- - fracAbsorbed* (rainTemperatureFlux(iCell) + &
- evapTemperatureFlux(iCell) + &
- seaIceTemperatureFlux(iCell) + &
- icebergTemperatureFlux(iCell)) &
- - fracAbsorbedRunoff* &
- activeTracersSurfaceFluxRunoff(indexTempFlux,iCell)
- if (trim(config_subglacial_runoff_mode) == 'data') then
- nonLocalSurfaceTracerFlux(indexTempFlux, iCell) = nonLocalSurfaceTracerFlux(indexTempFlux, iCell) &
- - fracAbsorbedSubglacialRunoff* &
- activeTracersSurfaceFluxSubglacialRunoff(indexTempFlux,iCell)
- end if
+ - fracAbsorbed*surfaceThicknessFlux(iCell) * &
+ activeTracers(indexTempFlux,kmin,iCell)
nonLocalSurfaceTracerFlux(indexSaltFlux,iCell) = &
activeTracersSurfaceFlux(indexSaltFlux,iCell) &
@@ -3630,21 +3610,8 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
surfaceBuoyancyForcing(iCell) = surfaceBuoyancyForcing(iCell)* &
gravity
- ! compute magnitude of surface stress
- sumSurfaceStressSquared = 0.0_RKIND
- do i = 1, nEdgesOnCell(iCell)
- iEdge = edgesOnCell(i, iCell)
- sumSurfaceStressSquared = sumSurfaceStressSquared &
- + edgeAreaFractionOfCell(i,iCell)* &
- surfaceStress(iEdge)**2
- enddo
-
- ! NOTE that the factor of 2 is from averaging dot products
- ! to cell centers on a C-grid
- surfaceStressMagnitude(iCell) = &
- sqrt(2.0_RKIND * sumSurfaceStressSquared)
surfaceFrictionVelocity(iCell) = &
- sqrt(surfaceStressMagnitude(iCell) / rho_sw)
+ sqrt(sfcStressMag(iCell) / rho_sw)
enddo
!$omp end do
@@ -3655,11 +3622,11 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, &
salineContractionCoeff, &
densitySurfaceDisplaced)
- call mpas_timer_stop('KPP input fields')
+ call mpas_timer_stop('Mixing input fields')
!-------------------------------------------------------------------
- end subroutine ocn_compute_KPP_input_fields!}}}
+ end subroutine ocn_compute_mixing_input_fields!}}}
!***********************************************************************
!
diff --git a/components/mpas-ocean/src/shared/mpas_ocn_tendency.F b/components/mpas-ocean/src/shared/mpas_ocn_tendency.F
index 182fca7dbb96..c4f1c55eba63 100644
--- a/components/mpas-ocean/src/shared/mpas_ocn_tendency.F
+++ b/components/mpas-ocean/src/shared/mpas_ocn_tendency.F
@@ -1317,12 +1317,9 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, &
!
! Compute tracer tendency due to non-local flux computed in KPP
!
- if (config_use_cvmix_kpp .or. config_use_gotm) then
- call ocn_compute_KPP_input_fields(statePool, forcingPool,&
- meshPool, timeLevel)
-
- if (.not. config_cvmix_kpp_nonlocal_with_implicit_mix) then
+ if (config_use_cvmix_kpp) then
call mpas_timer_start("non-local flux from KPP")
+ if (.not. config_cvmix_kpp_nonlocal_with_implicit_mix) then
if (computeBudgets) then
!$omp parallel
!$omp do schedule(runtime) private(k,n)
@@ -1365,8 +1362,8 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, &
!$omp end do
!$omp end parallel
endif ! compute budgets
- call mpas_timer_stop("non-local flux from KPP")
end if ! not non-local with implicit mix
+ call mpas_timer_stop("non-local flux from KPP")
end if ! KPP
! Compute tracer tendency due to production/destruction of
diff --git a/components/mpas-ocean/src/shared/mpas_ocn_vmix.F b/components/mpas-ocean/src/shared/mpas_ocn_vmix.F
index 68ef9d82a6bf..cabdf86ba112 100644
--- a/components/mpas-ocean/src/shared/mpas_ocn_vmix.F
+++ b/components/mpas-ocean/src/shared/mpas_ocn_vmix.F
@@ -27,6 +27,7 @@ module ocn_vmix
use mpas_timer
use ocn_mesh
+ use ocn_diagnostics
use mpas_constants
use ocn_constants
use ocn_config
@@ -202,6 +203,11 @@ subroutine ocn_vmix_coefs(meshPool, statePool, forcingPool, scratchPool, err, ti
!$omp end parallel
#endif
+ if(config_use_cvmix_kpp .or. config_use_gotm) then
+ call ocn_compute_mixing_input_fields(statePool, forcingPool,&
+ meshPool, timeLevel)
+ end if
+
#ifdef MPAS_OPENACC
!$acc update host(vertViscTopOfEdge, vertDiffTopOfCell)
#endif
diff --git a/components/mpas-ocean/src/shared/mpas_ocn_vmix_cvmix.F b/components/mpas-ocean/src/shared/mpas_ocn_vmix_cvmix.F
index 87fb36f2145f..fce760487e3b 100644
--- a/components/mpas-ocean/src/shared/mpas_ocn_vmix_cvmix.F
+++ b/components/mpas-ocean/src/shared/mpas_ocn_vmix_cvmix.F
@@ -64,7 +64,7 @@ module ocn_vmix_cvmix
type(cvmix_shear_params_type) :: cvmix_shear_params
type(cvmix_tidal_params_type) :: cvmix_tidal_params
- logical :: cvmixOn, cvmixConvectionOn, cvmixKPPOn
+ logical :: lnonzero_surf_nonlocal, cvmixOn, cvmixConvectionOn, cvmixKPPOn
real (kind=RKIND) :: backgroundVisc, backgroundDiff
integer :: cvmixBackgroundChoice ! user choice of cvmix background scheme
@@ -1042,19 +1042,22 @@ subroutine ocn_vmix_cvmix_init(domain,err)!{{{
! initialize KPP boundary layer scheme
!
if (config_use_cvmix_kpp) then
- if(config_cvmix_kpp_matching.eq."MatchBoth") then
- call mpas_log_write( &
- "Use of option MatchBoth is discouraged, use SimpleShapes instead", &
- MPAS_LOG_WARN)
- elseif(.not. config_cvmix_kpp_matching.eq."SimpleShapes") then
+ if(.not. config_cvmix_kpp_matching.eq."SimpleShapes" .and. &
+ .not. config_cvmix_kpp_matching.eq."MatchBoth" .and. &
+ .not. config_cvmix_kpp_matching.eq."ParabolicNonLocal") then
call mpas_log_write( &
"Unknown value for config_cvmix_kpp_matching., supported values are:" // &
- " SimpleShapes or MatchBoth", &
+ " SimpleShapes or MatchBoth or ParabolicNonLocal", &
MPAS_LOG_CRIT)
err = 1
return
endif
+ lnonzero_surf_nonlocal = .false.
+ if(config_cvmix_kpp_matching .eq."ParabolicNonLocal") then
+ lnonzero_surf_nonlocal = .true.
+ end if
+
if (trim(config_cvmix_kpp_langmuir_mixing_opt) .ne. "NONE" .and. &
trim(config_cvmix_kpp_langmuir_mixing_opt) .ne. "LWF16" .and. &
trim(config_cvmix_kpp_langmuir_mixing_opt) .ne. "RWHGK16") then
@@ -1081,13 +1084,15 @@ subroutine ocn_vmix_cvmix_init(domain,err)!{{{
call cvmix_init_kpp ( &
ri_crit = config_cvmix_kpp_criticalBulkRichardsonNumber, &
interp_type = config_cvmix_kpp_interpolationOMLType, &
- interp_type2 = config_cvmix_kpp_interpolationOMLType, &
+ interp_type2 = 'LMD94', &
lEkman = config_cvmix_kpp_EkmanOBL, &
lMonOb = config_cvmix_kpp_MonObOBL, &
MatchTechnique = config_cvmix_kpp_matching, &
surf_layer_ext = config_cvmix_kpp_surface_layer_extent, &
langmuir_mixing_str = config_cvmix_kpp_langmuir_mixing_opt, &
langmuir_entrainment_str = config_cvmix_kpp_langmuir_entrainment_opt, &
+ lnoDGat1 = .true., &
+ lnonzero_surf_nonlocal = lnonzero_surf_nonlocal, &
lenhanced_diff = config_cvmix_kpp_use_enhanced_diff)
endif