diff --git a/components/mpas-albany-landice/src/Registry_subglacial_hydro.xml b/components/mpas-albany-landice/src/Registry_subglacial_hydro.xml
index 024f23a9bb49..3fa1358d0a3f 100644
--- a/components/mpas-albany-landice/src/Registry_subglacial_hydro.xml
+++ b/components/mpas-albany-landice/src/Registry_subglacial_hydro.xml
@@ -78,8 +78,8 @@
possible_values="positive real number"
/>
-
@@ -112,6 +112,10 @@
description="width of sheet beneath/around channel that contributes to melt within the channel"
possible_values="positive real number"
/>
+
+
diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F
index bf9616b4339b..d36077750a83 100644
--- a/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F
+++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F
@@ -396,18 +396,6 @@ subroutine li_SGH_solve(domain, err)
block => block % next
end do
-
- ! =============
- ! =============
- ! =============
- ! subcycle hydro model until master dt is reached
- ! =============
- ! =============
- ! =============
- timecycling: do while (timeLeft > 0.0_RKIND)
- numSubCycles = numSubCycles + 1
-
-
! =============
! Calculate time-varying forcing, as needed
! =============
@@ -436,10 +424,6 @@ subroutine li_SGH_solve(domain, err)
err = ior(err, 1)
endif
- ! SHMIP forcing will override basalMeltInput.
- call shmip_timevarying_forcing(block, err_tmp)
- err = ior(err, err_tmp)
-
block => block % next
end do
@@ -453,6 +437,29 @@ subroutine li_SGH_solve(domain, err)
endif
+
+ ! =============
+ ! =============
+ ! =============
+ ! subcycle hydro model until master dt is reached
+ ! =============
+ ! =============
+ ! =============
+ timecycling: do while (timeLeft > 0.0_RKIND)
+ numSubCycles = numSubCycles + 1
+
+
+ ! apply shmip forcing if needed
+ block => domain % blocklist
+ do while (associated(block))
+ ! SHMIP forcing will override basalMeltInput from above
+ call shmip_timevarying_forcing(block, err_tmp)
+ err = ior(err, err_tmp)
+
+ block => block % next
+ end do
+
+
! =============
! Update till water layer thickness
! =============
@@ -482,6 +489,7 @@ subroutine li_SGH_solve(domain, err)
! =============
! Calculate edge quantities and advective fluxes
! =============
+ call mpas_timer_start("calc edge quantities")
block => domain % blocklist
do while (associated(block))
@@ -518,12 +526,14 @@ subroutine li_SGH_solve(domain, err)
block => block % next
end do
+ call mpas_timer_stop("calc edge quantities")
! =============
! Update Channel fields
! =============
if (config_SGH_chnl_active) then
+ call mpas_timer_start("update channel")
block => domain % blocklist
do while (associated(block))
@@ -539,13 +549,16 @@ subroutine li_SGH_solve(domain, err)
call mpas_dmpar_field_halo_exch(domain, 'channelMelt')
call mpas_dmpar_field_halo_exch(domain, 'channelPressureFreeze')
call mpas_timer_stop("halo updates")
+ call mpas_timer_stop("update channel")
endif
! =============
! Calculate adaptive time step
! =============
+ call mpas_timer_start("calc SGH dt")
call check_timestep(domain, timeLeft, numSubCycles, err_tmp)
+ call mpas_timer_stop("calc SGH dt")
err = ior(err, err_tmp)
if (err > 0) then
exit timecycling
@@ -555,6 +568,7 @@ subroutine li_SGH_solve(domain, err)
! =============
! Compute flux divergence
! =============
+ call mpas_timer_start("compute flux div")
block => domain % blocklist
do while (associated(block))
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
@@ -591,12 +605,14 @@ subroutine li_SGH_solve(domain, err)
call mpas_timer_start("halo updates")
call mpas_dmpar_field_halo_exch(domain, 'divergence')
call mpas_timer_stop("halo updates")
+ call mpas_timer_stop("compute flux div")
! =============
! Update channel area now that we have time step
! =============
if (config_SGH_chnl_active) then
+ call mpas_timer_start("evolve channel")
block => domain % blocklist
do while (associated(block))
@@ -611,11 +627,13 @@ subroutine li_SGH_solve(domain, err)
call mpas_dmpar_field_halo_exch(domain, 'channelMeltInputCell')
call mpas_dmpar_field_halo_exch(domain, 'channelArea')
call mpas_timer_stop("halo updates")
+ call mpas_timer_stop("evolve channel")
endif
! =============
! Calculate total grounding line discharges
! =============
+ call mpas_timer_start("calc SGH GL flux")
block => domain % blocklist
do while (associated(block))
@@ -624,10 +642,12 @@ subroutine li_SGH_solve(domain, err)
block => block % next
end do
+ call mpas_timer_stop("calc SGH GL flux")
! =============
! Update water layer thickness
! =============
+ call mpas_timer_start("update water layer thickness")
block => domain % blocklist
do while (associated(block))
call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool)
@@ -660,6 +680,7 @@ subroutine li_SGH_solve(domain, err)
block => block % next
end do
+ call mpas_timer_stop("update water layer thickness")
! =============
! Calculate pressure field
@@ -679,6 +700,7 @@ subroutine li_SGH_solve(domain, err)
! ordering choice is only needed to support channels. Without it, runs with
! channels would use an out of date waterThickness in the hydropotential and
! do not restart correctly due to the order of operations mismatch.
+ call mpas_timer_start("calc pressure")
block => domain % blocklist
do while (associated(block))
@@ -709,6 +731,7 @@ subroutine li_SGH_solve(domain, err)
block => block % next
end do
+ call mpas_timer_stop("calc pressure")
deltatSGHaccumulated = deltatSGHaccumulated + deltatSGH
@@ -879,6 +902,7 @@ subroutine calc_edge_quantities(block, err)
real (kind=RKIND), pointer :: bedRoughMax
real (kind=RKIND) :: conduc_coeff_wtd
character (len=StrKIND), pointer :: config_SGH_tangent_slope_calculation
+ logical, pointer :: config_SGH_allow_terrestrial_outflow
real (kind=RKIND), pointer :: config_sea_level
real (kind=RKIND), pointer :: rhoo
integer, pointer :: nEdges
@@ -909,6 +933,7 @@ subroutine calc_edge_quantities(block, err)
call mpas_pool_get_config(liConfigs, 'config_SGH_conduc_coeff_drowned', conduc_coeff_drowned)
call mpas_pool_get_config(liConfigs, 'config_SGH_bed_roughness_max', bedRoughMax)
call mpas_pool_get_config(liConfigs, 'config_SGH_tangent_slope_calculation', config_SGH_tangent_slope_calculation)
+ call mpas_pool_get_config(liConfigs, 'config_SGH_allow_terrestrial_outflow', config_SGH_allow_terrestrial_outflow)
call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level)
call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhoo)
@@ -972,19 +997,35 @@ subroutine calc_edge_quantities(block, err)
! This one-sided implementation also creates outflowing conditions at terrestrial boundary
do iEdge = 1, nEdges
if (hydroTerrestrialMarginMask(iEdge) == 1) then
- cell1 = cellsOnEdge(1, iEdge)
- cell2 = cellsOnEdge(2, iEdge)
- if (li_mask_is_grounded_ice(cellMask(cell1))) then ! cell2 is the icefree cell - replace phi there with cell1 Phig
-
- hydropotentialBaseSlopeNormal(iEdge) = - waterPressure(cell1) / dcEdge(iEdge)
- hydropotentialSlopeNormal(iEdge) = - (rho_water * gravity * waterThickness(cell1) + waterPressure(cell1)) / dcEdge(iEdge)
-
- else ! cell1 is the icefree cell - replace phi there with cell2 Phig
-
- hydropotentialBaseSlopeNormal(iEdge) = waterPressure(cell2) / dcEdge(iEdge)
- hydropotentialSlopeNormal(iEdge) = (rho_water * gravity * waterThickness(cell2) + waterPressure(cell2)) / dcEdge(iEdge)
-
- endif ! which cell is icefree
+ if (config_SGH_allow_terrestrial_outflow) then
+ cell1 = cellsOnEdge(1, iEdge)
+ cell2 = cellsOnEdge(2, iEdge)
+ if (li_mask_is_grounded_ice(cellMask(cell1))) then ! cell2 is the icefree cell - replace phi there with cell1 Phig
+ if (bedTopography(cell2) < bedTopography(cell1)) then
+ hydropotentialBaseSlopeNormal(iEdge) = - waterPressure(cell1) / dcEdge(iEdge)
+ hydropotentialSlopeNormal(iEdge) = - (rho_water * gravity * waterThickness(cell1) + waterPressure(cell1)) / dcEdge(iEdge)
+ else
+ ! If bare ground elevation is higher than elevation beneath the ice, no flux
+ hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND
+ hydropotentialSlopeNormal(iEdge) = 0.0_RKIND
+ waterPressureSlopeNormal(iEdge) = 0.0_RKIND
+ endif
+ else ! cell1 is the icefree cell - replace phi there with cell2 Phig
+ if (bedTopography(cell1) < bedTopography(cell2)) then
+ hydropotentialBaseSlopeNormal(iEdge) = waterPressure(cell2) / dcEdge(iEdge)
+ hydropotentialSlopeNormal(iEdge) = (rho_water * gravity * waterThickness(cell2) + waterPressure(cell2)) / dcEdge(iEdge)
+ else
+ ! If bare ground elevation is higher than elevation beneath the ice, no flux
+ hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND
+ hydropotentialSlopeNormal(iEdge) = 0.0_RKIND
+ waterPressureSlopeNormal(iEdge) = 0.0_RKIND
+ endif
+ endif ! which cell is icefree
+ else ! if disallow terrestrial outflow
+ hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND
+ hydropotentialSlopeNormal(iEdge) = 0.0_RKIND
+ waterPressureSlopeNormal(iEdge) = 0.0_RKIND
+ endif ! if allow terrestrial outflow
endif ! if edge of grounded ice
end do
@@ -1844,7 +1885,9 @@ subroutine update_channel(block, err)
real (kind=RKIND), pointer :: creep_coeff
real (kind=RKIND), pointer :: rhoi
real (kind=RKIND), pointer :: config_SGH_incipient_channel_width
+ real (kind=RKIND), pointer :: bedRoughMax
logical, pointer :: config_SGH_include_pressure_melt
+ real (kind=RKIND), pointer :: config_SGH_chnl_area_shutoff
real (kind=RKIND), dimension(:), pointer :: channelArea
real (kind=RKIND), dimension(:), pointer :: channelMelt
real (kind=RKIND), dimension(:), pointer :: channelPressureFreeze
@@ -1862,6 +1905,7 @@ subroutine update_channel(block, err)
real (kind=RKIND), dimension(:), pointer :: effectivePressureSGH
real (kind=RKIND), dimension(:), pointer :: channelDiffusivity
real (kind=RKIND), dimension(:), pointer :: waterThicknessEdgeUpwind
+ real (kind=RKIND), dimension(:), pointer :: waterThickness
integer, dimension(:), pointer :: waterFluxMask
integer, dimension(:), pointer :: hydroMarineMarginMask
integer, dimension(:), pointer :: edgeMask
@@ -1885,6 +1929,8 @@ subroutine update_channel(block, err)
call mpas_pool_get_config(liConfigs, 'config_SGH_chnl_creep_coefficient', creep_coeff)
call mpas_pool_get_config(liConfigs, 'config_SGH_incipient_channel_width', config_SGH_incipient_channel_width)
call mpas_pool_get_config(liConfigs, 'config_SGH_include_pressure_melt', config_SGH_include_pressure_melt)
+ call mpas_pool_get_config(liConfigs, 'config_SGH_bed_roughness_max', bedRoughMax)
+ call mpas_pool_get_config(liConfigs, 'config_SGH_chnl_area_shutoff', config_SGH_chnl_area_shutoff)
call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels)
call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve)
call mpas_pool_get_array(hydroPool, 'channelArea', channelArea)
@@ -1908,6 +1954,7 @@ subroutine update_channel(block, err)
call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask)
call mpas_pool_get_array(hydroPool, 'channelDiffusivity', channelDiffusivity)
call mpas_pool_get_array(hydroPool, 'waterThicknessEdgeUpwind', waterThicknessEdgeUpwind)
+ call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
! Calculate terms needed for opening (melt) rate
@@ -1949,6 +1996,12 @@ subroutine update_channel(block, err)
channelMelt = (abs(channelDischarge * hydropotentialSlopeNormal) & ! channel dissipation
+ abs(waterFlux * hydropotentialSlopeNormal * config_SGH_incipient_channel_width) & !some sheet dissipation
) / latent_heat_ice
+ ! disable channel melting above area limit
+ do iEdge = 1, nEdgesSolve
+ if (channelArea(iEdge) > config_SGH_chnl_area_shutoff) then
+ channelMelt = 0.0_RKIND
+ endif
+ enddo
channelPressureFreeze = -1.0_RKIND * iceMeltingPointPressureDependence * cp_freshwater * rho_water * &
(channelDischarge + waterFlux * config_SGH_incipient_channel_width) &
* waterPressureSlopeNormal / latent_heat_ice