diff --git a/src/core_ocean/Registry.xml b/src/core_ocean/Registry.xml
index b182b7ac8a..ab8ff8be34 100644
--- a/src/core_ocean/Registry.xml
+++ b/src/core_ocean/Registry.xml
@@ -943,6 +943,10 @@
description="Dimensionless bottom drag coefficient, $c_{drag}$."
possible_values="any positive real, typically 1.0e-3"
/>
+
+
+
+
+
+
@@ -1958,6 +1976,15 @@
+
+
+
+
@@ -2850,6 +2877,10 @@
+
\brief MPAS ocean topographic wave drag
+!> \author Nairita Pal
+!> \date Oct 2020
+!> \details
+!> This module contains the routine for computing
+!> tendencies from topographic wave drag.
+!
+!-----------------------------------------------------------------------
+
+module ocn_vel_forcing_topographic_wave_drag
+
+ use mpas_derived_types
+ use mpas_pool_routines
+ use mpas_timer
+
+ use ocn_constants
+ use ocn_mesh
+ use ocn_diagnostics_variables
+ use ocn_forcing
+
+ implicit none
+ private
+ save
+
+ !--------------------------------------------------------------------
+ !
+ ! Public parameters
+ !
+ !--------------------------------------------------------------------
+
+ !--------------------------------------------------------------------
+ !
+ ! Public member functions
+ !
+ !--------------------------------------------------------------------
+
+ public :: ocn_vel_forcing_topographic_wave_drag_tend, &
+ ocn_vel_forcing_topographic_wave_drag_init
+
+ !--------------------------------------------------------------------
+ !
+ ! Private module variables
+ !
+ !--------------------------------------------------------------------
+
+ logical :: topographicWaveDragOn
+ real (kind=RKIND) :: topographicWaveDragCoeff
+
+!***********************************************************************
+
+contains
+
+!***********************************************************************
+!
+! routine ocn_vel_forcing_topographic_wave_drag_tend
+!
+!> \brief Computes tendency term from topographic wave drag
+!> \author Nairita Pal
+!> \date 15 Oct 2020
+!> \details
+!> This routine computes the topographic wave drag tendency for momentum
+!> based on current state.
+!
+!-----------------------------------------------------------------------
+
+ subroutine ocn_vel_forcing_topographic_wave_drag_tend(normalVelocity, & !{{{
+ tend, err)
+
+ !-----------------------------------------------------------------
+ !
+ ! input variables
+ !
+ !-----------------------------------------------------------------
+
+ real (kind=RKIND), dimension(:,:), intent(in) :: &
+ normalVelocity !< Input: velocity
+
+ !-----------------------------------------------------------------
+ !
+ ! input/output variables
+ !
+ !-----------------------------------------------------------------
+
+ real (kind=RKIND), dimension(:,:), intent(inout) :: &
+ tend !< Input/Output: velocity tendency
+
+ !-----------------------------------------------------------------
+ !
+ ! output variables
+ !
+ !-----------------------------------------------------------------
+
+ integer, intent(out) :: err !< Output: error flag
+
+ !-----------------------------------------------------------------
+ !
+ ! local variables
+ !
+ !-----------------------------------------------------------------
+
+ integer :: iEdge, k
+
+ err = 0
+ if ( .not. topographicWaveDragOn ) return
+
+ call mpas_timer_start('vel topographic wave drag')
+
+ !$omp do schedule(runtime) private(k)
+ do iEdge = 1, nEdgesOwned
+ k = maxLevelEdgeTop(iEdge)
+ ! topographic wave drag term:
+ ! du/dt = ... 1/rinv * u
+ ! rinv is the e-folding time use in HyCOM. Here
+ ! topographic_wave_drag = 1/rinv
+ if (k>0) then
+ tend(k,iEdge) = tend(k,iEdge) - topographicWaveDragCoeff &
+ * topographic_wave_drag(iEdge) * normalVelocity(k,iEdge)
+ endif
+ enddo
+ !$omp end do
+
+ call mpas_timer_stop('vel topographic wave drag')
+
+ !--------------------------------------------------------------------
+
+ end subroutine ocn_vel_forcing_topographic_wave_drag_tend!}}}
+
+!***********************************************************************
+!
+! routine ocn_vel_forcing_topographic_wave_drag_init
+!
+!> \brief Initializes ocean topographic wave drag forcing
+!> \author Nairita Pal
+!> \date Oct 2020
+!> \details
+!> This routine initializes quantities related to topographic wave drag
+!> in the ocean.
+!
+!-----------------------------------------------------------------------
+
+ subroutine ocn_vel_forcing_topographic_wave_drag_init(err)!{{{
+
+ !--------------------------------------------------------------------
+
+ !-----------------------------------------------------------------
+ !
+ ! call individual init routines for each parameterization
+ !
+ !-----------------------------------------------------------------
+
+ integer, intent(out) :: err !< Output: error flag
+
+ logical, pointer :: config_disable_vel_topographic_wave_drag
+ logical, pointer :: config_use_topographic_wave_drag
+ real (kind=RKIND), pointer :: config_topographic_wave_drag_coeff
+
+ err = 0
+
+ call mpas_pool_get_config(ocnConfigs, 'config_use_topographic_wave_drag', config_use_topographic_wave_drag)
+ call mpas_pool_get_config(ocnConfigs, 'config_topographic_wave_drag_coeff', config_topographic_wave_drag_coeff)
+ call mpas_pool_get_config(ocnConfigs, 'config_disable_vel_topographic_wave_drag', config_disable_vel_topographic_wave_drag)
+
+ topographicWaveDragCoeff = 0.0_RKIND
+
+ if (config_use_topographic_wave_drag) then
+ topographicWaveDragOn = .true.
+ topographicWaveDragCoeff = config_topographic_wave_drag_coeff
+ endif
+
+ if (config_disable_vel_topographic_wave_drag) topographicWaveDragOn = .false.
+
+ !--------------------------------------------------------------------
+
+ end subroutine ocn_vel_forcing_topographic_wave_drag_init!}}}
+
+!***********************************************************************
+
+end module ocn_vel_forcing_topographic_wave_drag
+
+!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+! vim: foldmethod=marker
diff --git a/src/core_ocean/shared/mpas_ocn_vel_tidal_potential.F b/src/core_ocean/shared/mpas_ocn_vel_tidal_potential.F
index 57362b26e8..f3d07ebd50 100644
--- a/src/core_ocean/shared/mpas_ocn_vel_tidal_potential.F
+++ b/src/core_ocean/shared/mpas_ocn_vel_tidal_potential.F
@@ -307,7 +307,9 @@ subroutine ocn_vel_tidal_potential_init(domain,err)!{{{
type (block_type), pointer :: block_ptr
type (mpas_pool_type), pointer :: forcingPool
type (mpas_pool_type), pointer :: meshPool
+ integer, pointer :: nCells
integer, pointer :: nTidalPotentialConstituents
+ real (kind=RKIND), dimension(:), pointer :: latCell
! End preamble
!-----------------------------------------------------------------
@@ -332,9 +334,17 @@ subroutine ocn_vel_tidal_potential_init(domain,err)!{{{
!*** eventually replace with allocated module private vars
block_ptr => domain % blocklist
+
call mpas_pool_get_subpool(block_ptr%structs, 'forcing', &
forcingPool)
+ call mpas_pool_get_subpool(block_ptr%structs, 'mesh', &
+ meshPool)
+
+ call mpas_pool_get_dimension(block_ptr % dimensions, 'nCells', nCells)
+
+ call mpas_pool_get_array(meshPool, 'latCell', latCell)
+
call mpas_pool_get_array(forcingPool, 'tidalPotentialEta', &
tidalPotEta)
@@ -369,7 +379,7 @@ subroutine ocn_vel_tidal_potential_init(domain,err)!{{{
call mpas_set_time(refTime, &
dateTimeString=config_tidal_potential_reference_time)
- do iCell = 1,nCellsAll
+ do iCell = 1,nCells
tidalPotEta(iCell) = 0.0_RKIND
end do
@@ -428,7 +438,7 @@ subroutine ocn_vel_tidal_potential_init(domain,err)!{{{
tidalConstituentType, &
err)
- do iCell = 1,nCellsAll
+ do iCell = 1,nCells
lat = latCell(iCell)
latitudeFunction(iCell,1) = 3.0_RKIND*sin(lat)**2 -1.0_RKIND
latitudeFunction(iCell,2) = sin(2.0_RKIND*lat)
diff --git a/src/core_ocean/shared/mpas_ocn_vmix.F b/src/core_ocean/shared/mpas_ocn_vmix.F
index 375d97ed52..01e1de81a8 100644
--- a/src/core_ocean/shared/mpas_ocn_vmix.F
+++ b/src/core_ocean/shared/mpas_ocn_vmix.F
@@ -821,7 +821,16 @@ subroutine ocn_vel_vmix_tend_implicit_spatially_variable_mannings(meshPool, forc
end do
! average cell-based implicit bottom drag to edges and convert Mannings n to Cd
- if (config_use_vegetation_drag .AND. config_use_vegetation_manning_equation) then
+ if (config_use_implicit_bottom_roughness) then
+ ! NCOM's formula for bottom drag coefficient
+ ! The original formula is cb(i,j) = max(cbmin, (vonk/log(0.5*depth(i,j)/z0))**2 ))
+ ! where vonk=0.16, z0=0.001, bracketed between [0.0025, 0.1]
+ ! The constant below is 250 = 0.5*0.5/z0 with the extra 0.5 from
+ ! averaging the two bottomDepth cells.
+ implicitCd = max(0.0025_RKIND, &
+ min(0.1_RKIND, &
+ 0.16_RKIND/log(250.0_RKIND*(bottomDepth(cell1)+bottomDepth(cell2)))**2 ))
+ elseif (config_use_vegetation_drag .AND. config_use_vegetation_manning_equation) then
implicitCd = gravity*(0.5_RKIND*(vegetationManning(cell1) + vegetationManning(cell2)))**2.0 * &
(0.5_RKIND * (ssh(cell1) + ssh(cell2) + bottomDepth(cell1) + bottomDepth(cell2)))**(-1.0_RKIND/3.0_RKIND)
else
@@ -1137,7 +1146,8 @@ subroutine ocn_vmix_implicit(dt, meshPool, statePool, forcingPool, scratchPool,
if (config_use_implicit_bottom_drag_variable) then
call ocn_vel_vmix_tend_implicit_spatially_variable(meshPool, bottomDrag, dt, kineticEnergyCell, &
vertViscTopOfEdge, layerThickness, layerThickEdge, normalVelocity, err)
- else if (config_use_implicit_bottom_drag_variable_mannings) then
+ else if (config_use_implicit_bottom_drag_variable_mannings.or. &
+ config_use_implicit_bottom_roughness) then
! update bottomDrag via Cd=g*n^2*h^(-1/3)
call ocn_vel_vmix_tend_implicit_spatially_variable_mannings(meshPool, forcingPool, bottomDrag, &
dt, kineticEnergyCell, &