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, &