Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support wetting-and-drying with RK4 and subglacial thin film #119

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions components/mpas-ocean/src/Registry.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,10 @@
description="If true, use take into account the ssh gradient across previously flux-limited edges in the wetting and drying algorithm"
possible_values=".true. or .false."
/>
<nml_option name="config_land_ice_overburden_height" type="real" default_value="0.0" units="m"
description="The amount of pressure overburden allowed in grounded regions. If ice must float at level of critical thickness, set equal to -1 * critical thickness"
possible_values="Any real"
/>
</nml_record>
<nml_record name="ocean_constants">
<nml_option name="config_density0" type="real" default_value="1026.0" units="kg m^-3"
Expand Down
41 changes: 40 additions & 1 deletion components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ module ocn_diagnostics
!
!--------------------------------------------------------------------

logical :: landIcePressureInitialized
integer :: ke_cell_flag, ke_vertex_flag
real (kind=RKIND) :: fCoef
real (kind=RKIND) :: landIceTopDragCoeff
Expand Down Expand Up @@ -2552,6 +2553,7 @@ subroutine ocn_diagnostic_solve_surface_pressure(forcingPool, &

integer :: iCell ! cell loop index

real (kind=RKIND) :: h_crit, ssh_crit, landIcePressureMax
real (kind=RKIND), dimension(:), pointer :: &
frazilSurfacePressure, &! frazil ice pressure from forcing
landIcePressure ! land ice pressure
Expand All @@ -2567,6 +2569,12 @@ subroutine ocn_diagnostic_solve_surface_pressure(forcingPool, &
call mpas_pool_get_array(forcingPool, 'landIcePressure', &
landIcePressure)

! First initialize landIcePressure unchanged, then modify in grounded regions
if (landIcePressureOn .and. .not. landIcePressureInitialized) then
landIcePressureApplied(:) = landIcePressure(:)
landIcePressureInitialized = .true.
endif

! Compute pressure for generalized coordinates.
! Pressure at top surface may be due to atmospheric pressure,
! sea ice, frazil ice or the weight of an ice shelf
Expand Down Expand Up @@ -2610,6 +2618,31 @@ subroutine ocn_diagnostic_solve_surface_pressure(forcingPool, &
! Add land ice pressure if needed

if (landIcePressureOn) then
#ifdef MPAS_OPENACC
!$acc parallel loop &
!$acc present(surfacePressure)
!! need this eventually, but there is currently
!! an issue, probably with the re-retrieval of pointer
!!acc present(surfacePressure, landIcePressure)
#else
!$omp parallel
!$omp do schedule(runtime) private(h_crit, ssh_crit, landIcePressureMax)
#endif
do iCell = 1, nCellsAll
! the maximum pressure is the one that results in ssh at the critical
! thickness (gravity is positive), but we also allow some amount of overburden
! because rho may deviate significantly from rho_sw
h_crit = config_drying_min_cell_height * (maxLevelCell(iCell) - minLevelCell(iCell) + 1)
ssh_crit = bottomDepth(iCell) - h_crit + config_land_ice_overburden_height
landIcePressureMax = gravity * rho_sw * ssh_crit
landIcePressureApplied(iCell) = &
min(landIcePressureMax, landIcePressure(iCell))
end do
#ifndef M_OPENACC
!$omp end do
!$omp end parallel
#endif

#ifdef MPAS_OPENACC
!$acc parallel loop &
!$acc present(surfacePressure)
Expand All @@ -2621,7 +2654,7 @@ subroutine ocn_diagnostic_solve_surface_pressure(forcingPool, &
#endif
do iCell = 1, nCellsAll
surfacePressure(iCell) = surfacePressure(iCell) &
+ landIcePressure(iCell)
+ landIcePressureApplied(iCell)
end do
#ifndef MPAS_OPENACC
!$omp end do
Expand Down Expand Up @@ -4749,6 +4782,12 @@ subroutine ocn_diagnostics_init(domain, err)!{{{
call mpas_log_write("config_sgr_flux_vertical_location not one of 'bottom', 'uniform', 'top'.", MPAS_LOG_CRIT)
end if

if (config_do_restart) then
landIcePressureInitialized = .true.
else
landIcePressureInitialized = .false.
endif

end subroutine ocn_diagnostics_init!}}}

!***********************************************************************
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ module ocn_diagnostics_variables
real (kind=RKIND), dimension(:), pointer :: surfaceBuoyancyForcing
real (kind=RKIND), dimension(:), pointer :: surfaceFrictionVelocity
real (kind=RKIND), dimension(:), pointer :: surfacePressure
real (kind=RKIND), dimension(:), pointer :: landIcePressureApplied

real (kind=RKIND), dimension(:,:), pointer :: &
transportVelocityX, transportVelocityY, transportVelocityZ, transportVelocityZonal, &
Expand Down Expand Up @@ -707,6 +708,8 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e
call mpas_pool_get_array(diagnosticsPool, 'dThreshMLD', dThreshMLD)
call mpas_pool_get_array(diagnosticsPool, 'surfacePressure', &
surfacePressure)
call mpas_pool_get_array(diagnosticsPool, 'landIcePressureApplied', &
landIcePressureApplied)

! Semi-implicit Array Pointer retrievals
if (trim(config_time_integrator) == 'split_implicit') then
Expand Down Expand Up @@ -957,6 +960,7 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e
!$acc thermExpCoeff, &
!$acc sfcFlxAttCoeff, &
!$acc surfacePressure, &
!$acc landIcePressureApplied, &
!$acc potentialDensity, &
!$acc displacedDensity, &
!$acc boundaryLayerDepth, &
Expand Down Expand Up @@ -1217,6 +1221,7 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{
!$acc thermExpCoeff, &
!$acc sfcFlxAttCoeff, &
!$acc surfacePressure, &
!$acc landIcePressureApplied, &
!$acc potentialDensity, &
!$acc displacedDensity, &
!$acc boundaryLayerDepth, &
Expand Down Expand Up @@ -1420,6 +1425,7 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{
thermExpCoeff, &
sfcFlxAttCoeff, &
surfacePressure, &
landIcePressureApplied, &
potentialDensity, &
displacedDensity, &
boundaryLayerDepth, &
Expand Down
178 changes: 164 additions & 14 deletions components/mpas-ocean/src/shared/mpas_ocn_wetting_drying.F
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module ocn_wetting_drying
use ocn_mesh
use ocn_subgrid
use ocn_vel_pressure_grad
use ocn_surface_land_ice_fluxes

implicit none
private
Expand Down Expand Up @@ -67,6 +68,121 @@ module ocn_wetting_drying

contains

subroutine ocn_compute_land_ice_ssh_floatation(landIcePressure, ssh_floatation, &
err)
!-----------------------------------------------------------------
!
! input variables
!
!-----------------------------------------------------------------
real (kind=RKIND), dimension(:), intent(in) :: landIcePressure

!-----------------------------------------------------------------
!
! input/output variables
!
!-----------------------------------------------------------------
real (kind=RKIND), dimension(:), intent(inout) :: ssh_floatation

!-----------------------------------------------------------------
!
! output variables
!
!-----------------------------------------------------------------

integer, intent(out) :: err !< Output: error flag

!-----------------------------------------------------------------
!
! local variables
!
!-----------------------------------------------------------------
integer :: iCell

err = 0

if ( .not. landIcePressureOn ) return

!$omp parallel
!$omp do schedule(runtime)
do iCell = 1, nCellsAll

! the depth at which floatation occurs with full land ice pressure
! (may be below the bathymetry) (gravity is positive)
ssh_floatation(iCell) = - landIcePressure(iCell) / (gravity * rho_sw)

end do
!$omp end do
!$omp end parallel

end subroutine ocn_compute_land_ice_ssh_floatation

subroutine ocn_compute_land_ice_ssh_adjustment(landIcePressure, landIceMask, &
ssh_land_ice_adjustment, err)
!-----------------------------------------------------------------
!
! input variables
!
!-----------------------------------------------------------------
integer, dimension(:), intent(in) :: landIceMask
real (kind=RKIND), dimension(:), intent(in) :: landIcePressure

!-----------------------------------------------------------------
!
! input/output variables
!
!-----------------------------------------------------------------
real (kind=RKIND), dimension(:), intent(inout) :: ssh_land_ice_adjustment

!-----------------------------------------------------------------
!
! output variables
!
!-----------------------------------------------------------------

integer, intent(out) :: err !< Output: error flag

!-----------------------------------------------------------------
!
! local variables
!
!-----------------------------------------------------------------
integer :: iCell
real (kind=RKIND), dimension(:), allocatable :: landIcePressureMax, rho_mean, ssh_floatation
real (kind=RKIND) :: dPressure, ssh_crit, hCrit

err = 0

if ( .not. config_zero_drying_velocity ) return
if ( .not. landIcePressureOn ) return

allocate(rho_mean(nCellsAll))
allocate(landIcePressureMax(nCellsAll))
allocate(ssh_floatation(nCellsAll))
rho_mean(:) = rho_sw
landIcePressureMax(:) = 0.0_RKIND
ssh_floatation(:) = 0.0_RKIND

call ocn_compute_land_ice_ssh_floatation(landIcePressure, ssh_floatation, err)

!$omp parallel
!$omp do schedule(runtime) private(dPressure, ssh_crit, hCrit)
do iCell = 1, nCellsAll
hCrit = config_drying_min_cell_height * (maxLevelCell(iCell) - minLevelCell(iCell) + 1)
ssh_crit = hCrit - bottomDepth(iCell)

! the ssh equivalent by which we adjusted landIcePressure to ensure
! floatation at roughly the point at which the wetting-and-drying
! is active (ssh_crit)
! we need to multiply by landIceMask here for the cases where ssh_crit > 0
ssh_land_ice_adjustment(iCell) = landIceMask(iCell) * &
min(ssh_floatation(iCell) - ssh_crit, 0.0_RKIND)
end do
!$omp end do
!$omp end parallel

end subroutine ocn_compute_land_ice_ssh_adjustment

!***********************************************************************
!
! routine ocn_wetting_drying_verify
Expand Down Expand Up @@ -237,26 +353,32 @@ subroutine ocn_prevent_drying_rk4(domain, block, dt, rkSubstepWeight, config_zer
!-----------------------------------------------------------------


type (mpas_pool_type), pointer :: tendPool
type (mpas_pool_type), pointer :: statePool
type (mpas_pool_type), pointer :: provisStatePool
real (kind=RKIND), dimension(:, :), pointer :: layerThicknessCur
real (kind=RKIND), dimension(:, :), pointer :: layerThicknessProvis
real (kind=RKIND), dimension(:, :), pointer :: normalVelocity
type (mpas_pool_type), pointer :: tendPool
type (mpas_pool_type), pointer :: statePool
type (mpas_pool_type), pointer :: provisStatePool
type (mpas_pool_type), pointer :: forcingPool
real (kind=RKIND), dimension(:), pointer :: landIcePressure, landIceDraft
integer, dimension(:), pointer :: landIceMask
real (kind=RKIND), dimension(:, :), pointer :: layerThicknessCur
real (kind=RKIND), dimension(:, :), pointer :: layerThicknessProvis
real (kind=RKIND), dimension(:, :), pointer :: normalVelocity

integer :: iEdge, k
integer :: iEdge, k

err = 0
err = 0

call mpas_pool_get_subpool(block % structs, 'tend', tendPool)
call mpas_pool_get_subpool(block % structs, 'state', statePool)
call mpas_pool_get_subpool(block % structs, 'provis_state', provisStatePool)
call mpas_pool_get_subpool(block % structs, 'forcing', forcingPool)

call mpas_pool_get_array(statePool, 'normalVelocity', normalVelocity, 1)
! use thickness at n because constraint is h_n + dt*T_h > h_min
call mpas_pool_get_array(statePool, 'layerThickness', layerThicknessCur, 1)
call mpas_pool_get_array(provisStatePool, 'layerThickness', layerThicknessProvis, 1)

call mpas_pool_get_array(forcingPool, 'landIceMask', landIceMask)
call mpas_pool_get_array(forcingPool, 'landIceDraft', landIceDraft)
call mpas_pool_get_array(forcingPool, 'landIcePressure', landIcePressure)

!$omp parallel
!$omp do schedule(runtime)
Expand All @@ -269,8 +391,10 @@ subroutine ocn_prevent_drying_rk4(domain, block, dt, rkSubstepWeight, config_zer
! ensure cells stay wet by selectively damping cells with a damping tendency to make
! sure tendency doesn't dry cells

call ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, &
normalTransportVelocity, rkSubstepWeight, wettingVelocityFactor, err)
call ocn_wetting_drying_wettingVelocity( &
domain, layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, &
normalTransportVelocity, rkSubstepWeight, &
landIceMask, landIcePressure, landIceDraft, wettingVelocityFactor, err)

! prevent drying from happening with selective wettingVelocityFactor
if (config_zero_drying_velocity) then
Expand Down Expand Up @@ -309,7 +433,8 @@ end subroutine ocn_prevent_drying_rk4 !}}}
!-----------------------------------------------------------------------

subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, &
normalVelocity, dt, wettingVelocityFactor, err)!{{{
normalVelocity, dt, landIceMask, landIcePressure, landIceDraft, &
wettingVelocityFactor, err)!{{{

!-----------------------------------------------------------------
!
Expand All @@ -332,6 +457,11 @@ subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerT
real (kind=RKIND), intent(in) :: &
dt !< Input: time step

integer, dimension(:), intent(in) :: landIceMask

real (kind=RKIND), dimension(:), intent(in) :: &
landIcePressure, landIceDraft

!-----------------------------------------------------------------
!
! input/output variables
Expand Down Expand Up @@ -367,10 +497,14 @@ subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerT

character (len=100) :: log_string

integer:: cellDummy(2), cellCur, CellNei
integer:: cellDummy(2), cellCur, CellNei, nVertLevelsCell
real (kind=RKIND) :: sshCur, sshNei
real (kind=RKIND), dimension(:), pointer :: sshCell
real (kind=RKIND), dimension(:, :), pointer :: layerThicknessCell
real (kind=RKIND), dimension(:), allocatable :: sshLandIceAdjustment
!< amount by which to adjust ssh related to
!< the initial adjustment of land ice pressure
!< effects on ssh


err = 0
Expand Down Expand Up @@ -409,6 +543,22 @@ subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerT
end do

layerThicknessCell(k, iCell) = min(layerThicknessProvis(k, iCell), layerThicknessCur(k, iCell)) + dt * divOutFlux
end do
end do
!$omp end do
!$omp end parallel

allocate(sshLandIceAdjustment(nCellsAll))
sshLandIceAdjustment(:) = 0.0_RKIND
call ocn_compute_land_ice_ssh_adjustment(landIcePressure, landIceMask, sshLandIceAdjustment, err)

!$omp parallel
!$omp do schedule(runtime) private(k, nVertLevelsCell)
do iCell = 1, nCellsAll
nVertLevelsCell = maxLevelCell(iCell) - minLevelCell(iCell) + 1
do k = minLevelCell(iCell), maxLevelCell(iCell)
layerThicknessCell(k, iCell) = layerThicknessCell(k, iCell) + &
sshLandIceAdjustment(iCell) / nVertLevelsCell
if ( .not. config_use_ssh_gradient_wetting_drying ) then
call ocn_wetting_velocity_factor_on_cell_edges( &
wettingVelocityFactor, layerThicknessCell(k, iCell), normalVelocity, iCell, k)
Expand Down Expand Up @@ -458,7 +608,7 @@ subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerT
do k = minLevelCell(iCell), maxLevelCell(iCell)
columnThickness = columnThickness + layerThicknessCell(k, iCell)
enddo
sshCell(iCell) = columnThickness - bottomDepth(iCell)
sshCell(iCell) = columnThickness - bottomDepth(iCell) - sshLandIceAdjustment(iCell)
enddo
!$omp end do
!$omp end parallel
Expand Down