From 6face36d817b0d098856ae79b37410b515b94cf1 Mon Sep 17 00:00:00 2001 From: "Phillip J. Wolfram" Date: Thu, 20 Jun 2019 14:53:54 -0600 Subject: [PATCH] Migrates Rayleigh drag from explicit to implicit Previously, Rayleigh drag was implemented explicitly, which meant it was not coupled with vertical mixing. Now, Rayleigh drag is implemented implicitly so that it is directly coupled to implicit vertical mixing. --- src/core_ocean/shared/Makefile | 5 +- src/core_ocean/shared/mpas_ocn_vel_forcing.F | 5 - .../shared/mpas_ocn_vel_forcing_rayleigh.F | 221 ------------------ src/core_ocean/shared/mpas_ocn_vmix.F | 32 ++- 4 files changed, 29 insertions(+), 234 deletions(-) delete mode 100644 src/core_ocean/shared/mpas_ocn_vel_forcing_rayleigh.F diff --git a/src/core_ocean/shared/Makefile b/src/core_ocean/shared/Makefile index 89a9f9efe3..06574027d0 100644 --- a/src/core_ocean/shared/Makefile +++ b/src/core_ocean/shared/Makefile @@ -24,7 +24,6 @@ OBJS = mpas_ocn_init_routines.o \ mpas_ocn_vel_forcing.o \ mpas_ocn_vel_forcing_surface_stress.o \ mpas_ocn_vel_forcing_explicit_bottom_drag.o \ - mpas_ocn_vel_forcing_rayleigh.o \ mpas_ocn_vel_pressure_grad.o \ mpas_ocn_vmix.o \ mpas_ocn_vmix_coefs_const.o \ @@ -103,14 +102,12 @@ mpas_ocn_vel_hmix_leith.o: mpas_ocn_constants.o mpas_ocn_vel_hmix_del4.o: mpas_ocn_constants.o -mpas_ocn_vel_forcing.o: mpas_ocn_vel_forcing_surface_stress.o mpas_ocn_vel_forcing_rayleigh.o mpas_ocn_vel_forcing_explicit_bottom_drag.o mpas_ocn_forcing.o mpas_ocn_constants.o +mpas_ocn_vel_forcing.o: mpas_ocn_vel_forcing_surface_stress.o mpas_ocn_vel_forcing_explicit_bottom_drag.o mpas_ocn_forcing.o mpas_ocn_constants.o mpas_ocn_vel_forcing_surface_stress.o: mpas_ocn_forcing.o mpas_ocn_constants.o mpas_ocn_vel_forcing_explicit_bottom_drag.o: mpas_ocn_constants.o -mpas_ocn_vel_forcing_rayleigh.o: mpas_ocn_constants.o - mpas_ocn_vel_coriolis.o: mpas_ocn_constants.o mpas_ocn_tracer_hmix.o: mpas_ocn_tracer_hmix_del2.o mpas_ocn_tracer_hmix_del4.o mpas_ocn_tracer_hmix_redi.o diff --git a/src/core_ocean/shared/mpas_ocn_vel_forcing.F b/src/core_ocean/shared/mpas_ocn_vel_forcing.F index e9befd1436..c768f2ad3d 100644 --- a/src/core_ocean/shared/mpas_ocn_vel_forcing.F +++ b/src/core_ocean/shared/mpas_ocn_vel_forcing.F @@ -27,7 +27,6 @@ module ocn_vel_forcing use ocn_vel_forcing_surface_stress use ocn_vel_forcing_explicit_bottom_drag - use ocn_vel_forcing_rayleigh implicit none private @@ -143,9 +142,6 @@ subroutine ocn_vel_forcing_tend(meshPool, normalVelocity, surfaceFluxAttenuation err = ior(err, err1) - call ocn_vel_forcing_rayleigh_tend(meshPool, normalVelocity, tend, err1) - err = ior(err, err1) - !-------------------------------------------------------------------- end subroutine ocn_vel_forcing_tend!}}} @@ -181,7 +177,6 @@ subroutine ocn_vel_forcing_init(err)!{{{ call ocn_vel_forcing_surface_stress_init(err1) call ocn_vel_forcing_explicit_bottom_drag_init(err1) - call ocn_vel_forcing_rayleigh_init(err2) err = ior(err1, err2) diff --git a/src/core_ocean/shared/mpas_ocn_vel_forcing_rayleigh.F b/src/core_ocean/shared/mpas_ocn_vel_forcing_rayleigh.F deleted file mode 100644 index 4dbb69d718..0000000000 --- a/src/core_ocean/shared/mpas_ocn_vel_forcing_rayleigh.F +++ /dev/null @@ -1,221 +0,0 @@ -! Copyright (c) 2013, Los Alamos National Security, LLC (LANS) -! and the University Corporation for Atmospheric Research (UCAR). -! -! Unless noted otherwise source code is licensed under the BSD license. -! Additional copyright and license information can be found in the LICENSE file -! distributed with this code, or at http://mpas-dev.github.com/license.html -! -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -! -! ocn_vel_forcing_rayleigh -! -!> \brief MPAS ocean Rayleigh Friction (to be used to smooth "shocks" from cold starts) -!> \author Todd Ringler -!> \date 5 January 2012 -!> \details -!> This module contains the routine for computing -!> tendencies based on linear Rayleigh friction. -! -!----------------------------------------------------------------------- - -module ocn_vel_forcing_rayleigh - - use mpas_derived_types - use mpas_pool_routines - use mpas_timer - use ocn_constants - - implicit none - private - save - - !-------------------------------------------------------------------- - ! - ! Public parameters - ! - !-------------------------------------------------------------------- - - !-------------------------------------------------------------------- - ! - ! Public member functions - ! - !-------------------------------------------------------------------- - - public :: ocn_vel_forcing_rayleigh_tend, & - ocn_vel_forcing_rayleigh_init - - !-------------------------------------------------------------------- - ! - ! Private module variables - ! - !-------------------------------------------------------------------- - - logical :: rayleighFrictionOn, rayleighBottomFrictionOn - real (kind=RKIND) :: rayleighDampingCoef, rayleighBottomDampingCoef - - -!*********************************************************************** - -contains - -!*********************************************************************** -! -! ocn_vel_forcing_rayleigh_tend -! -!> \brief Computes tendency term from Rayleigh friction -!> \author Todd Ringler -!> \date 5 January 2012 -!> \details -!> This routine computes the Rayleigh friction tendency for momentum -!> based on current state. -! -!----------------------------------------------------------------------- - - subroutine ocn_vel_forcing_rayleigh_tend(meshPool, normalVelocity, tend, err)!{{{ - - !----------------------------------------------------------------- - ! - ! input variables - ! - !----------------------------------------------------------------- - - real (kind=RKIND), dimension(:,:), intent(in) :: & - normalVelocity !< Input: velocity - - type (mpas_pool_type), intent(in) :: & - meshPool !< Input: mesh information - - !----------------------------------------------------------------- - ! - ! 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, nEdges - integer, dimension(:), pointer :: nEdgesArray - integer, dimension(:), pointer :: maxLevelEdgeTop - - !----------------------------------------------------------------- - ! - ! call relevant routines for computing tendencies - ! note that the user can choose multiple options and the - ! tendencies will be added together - ! - !----------------------------------------------------------------- - - err = 0 - - if ( .not. (rayleighFrictionOn .or. rayleighBottomFrictionOn)) return - - call mpas_timer_start('vel rayleigh forcing') - - call mpas_pool_get_dimension(meshPool, 'nEdgesArray', nEdgesArray) - call mpas_pool_get_array(meshPool, 'maxLevelEdgeTop', maxLevelEdgeTop) - - nEdges = nEdgesArray( 1 ) - - if ( rayleighFrictionOn ) then - !$omp do schedule(runtime) private(k) - do iEdge = 1, nEdges - do k = 1, maxLevelEdgeTop(iEdge) - - tend(k,iEdge) = tend(k,iEdge) - rayleighDampingCoef * normalVelocity(k,iEdge) - - enddo - enddo - !$omp end do - endif - - if ( rayleighBottomFrictionOn ) then - !$omp do schedule(runtime) private(k) - do iEdge = 1, nEdges - - k = maxLevelEdgeTop(iEdge) - tend(k,iEdge) = tend(k,iEdge) - rayleighDampingCoef * normalVelocity(k,iEdge) - - enddo - !$omp end do - endif - - call mpas_timer_stop('vel rayleigh forcing') - - !-------------------------------------------------------------------- - - end subroutine ocn_vel_forcing_rayleigh_tend!}}} - -!*********************************************************************** -! -! ocn_vel_forcing_rayleigh_init -! -!> \brief Initializes ocean Rayleigh friction -!> \author Todd Ringler -!> \date 5 January 2012 -!> \details -!> This routine initializes quantities related to -!> in the ocean. -! -!----------------------------------------------------------------------- - - subroutine ocn_vel_forcing_rayleigh_init(err)!{{{ - - !-------------------------------------------------------------------- - - !----------------------------------------------------------------- - ! - ! call individual init routines for each parameterization - ! - !----------------------------------------------------------------- - - integer, intent(out) :: err !< Output: error flag - - logical, pointer :: config_Rayleigh_friction, config_Rayleigh_bottom_friction - real (kind=RKIND), pointer :: config_Rayleigh_damping_coeff, config_Rayleigh_bottom_damping_coeff - - err = 0 - - call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_friction', config_Rayleigh_friction) - call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_bottom_friction', config_Rayleigh_bottom_friction) - call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_damping_coeff', config_Rayleigh_damping_coeff) - call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_bottom_damping_coeff', config_Rayleigh_bottom_damping_coeff) - - rayleighDampingCoef = 0.0_RKIND - - if (config_Rayleigh_friction) then - rayleighFrictionOn = .true. - rayleighDampingCoef = config_Rayleigh_damping_coeff - endif - - rayleighBottomDampingCoef = 0.0_RKIND - - if (config_Rayleigh_bottom_friction) then - rayleighBottomFrictionOn = .true. - rayleighBottomDampingCoef = config_Rayleigh_bottom_damping_coeff - endif - - !-------------------------------------------------------------------- - - end subroutine ocn_vel_forcing_rayleigh_init!}}} - -!*********************************************************************** - -end module ocn_vel_forcing_rayleigh - -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -! vim: foldmethod=marker diff --git a/src/core_ocean/shared/mpas_ocn_vmix.F b/src/core_ocean/shared/mpas_ocn_vmix.F index 1bda2fbf55..675b8aaa05 100644 --- a/src/core_ocean/shared/mpas_ocn_vmix.F +++ b/src/core_ocean/shared/mpas_ocn_vmix.F @@ -67,6 +67,7 @@ module ocn_vmix logical :: velVmixOn, tracerVmixOn real (kind=RKIND) :: implicitBottomDragCoef + real (kind=RKIND) :: rayleighDampingCoef, rayleighBottomDampingCoef !*********************************************************************** @@ -271,7 +272,7 @@ subroutine ocn_vel_vmix_tend_implicit(meshPool, dt, kineticEnergyCell, vertViscT nEdges = nEdgesArray( 1 ) allocate(A(nVertLevels),B(nVertLevels),C(nVertLevels),velTemp(nVertLevels)) - A(1)=0 + A(1)=0.0_RKIND !$omp do schedule(runtime) do iEdge = 1, nEdges @@ -304,13 +305,14 @@ subroutine ocn_vel_vmix_tend_implicit(meshPool, dt, kineticEnergyCell, vertViscT ! B is diagonal term B(1) = 1 - C(1) do k = 2, N-1 - B(k) = 1 - A(k) - C(k) + B(k) = 1.0_RKIND - A(k) - C(k) + dt*rayleighDampingCoef enddo ! Apply bottom drag boundary condition on the viscous term ! second line uses sqrt(2.0*kineticEnergyEdge(k,iEdge)) - B(N) = 1 - A(N) + dt*implicitBottomDragCoef & - * sqrt(kineticEnergyCell(k,cell1) + kineticEnergyCell(k,cell2)) / layerThicknessEdge(k,iEdge) + B(N) = 1.0_RKIND - A(N) + dt*implicitBottomDragCoef & + * sqrt(kineticEnergyCell(k,cell1) + kineticEnergyCell(k,cell2)) / layerThicknessEdge(k,iEdge) & + + dt*(rayleighDampingCoef + rayleighBottomDampingCoef) call tridiagonal_solve(A(2:N),B,C(1:N-1),normalVelocity(:,iEdge),velTemp,N) @@ -661,6 +663,8 @@ subroutine ocn_vmix_init(domain, err)!{{{ logical, pointer :: config_disable_vel_vmix, config_disable_tr_vmix logical, pointer :: config_use_implicit_bottom_drag real (kind=RKIND), pointer :: config_implicit_bottom_drag_coeff + logical, pointer :: config_Rayleigh_friction, config_Rayleigh_bottom_friction + real (kind=RKIND), pointer :: config_Rayleigh_damping_coeff, config_Rayleigh_bottom_damping_coeff err = 0 @@ -668,6 +672,26 @@ subroutine ocn_vmix_init(domain, err)!{{{ call mpas_pool_get_config(ocnConfigs, 'config_disable_tr_vmix', config_disable_tr_vmix) call mpas_pool_get_config(ocnConfigs, 'config_use_implicit_bottom_drag', config_use_implicit_bottom_drag) call mpas_pool_get_config(ocnConfigs, 'config_implicit_bottom_drag_coeff', config_implicit_bottom_drag_coeff) + call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_friction', & + config_Rayleigh_friction) + call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_bottom_friction', & + config_Rayleigh_bottom_friction) + call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_damping_coeff', & + config_Rayleigh_damping_coeff) + call mpas_pool_get_config(ocnConfigs, 'config_Rayleigh_bottom_damping_coeff', & + config_Rayleigh_bottom_damping_coeff) + + rayleighDampingCoef = 0.0_RKIND + + if (config_Rayleigh_friction) then + rayleighDampingCoef = config_Rayleigh_damping_coeff + endif + + rayleighBottomDampingCoef = 0.0_RKIND + + if (config_Rayleigh_bottom_friction) then + rayleighBottomDampingCoef = config_Rayleigh_bottom_damping_coeff + endif velVmixOn = .true. tracerVmixOn = .true.