Skip to content

Commit 4941445

Browse files
Adjust calving scheme to handle narrow fjords
This makes two adjustments: 1. When deciding if an edge should experience calving, include neighbors above sea level instead of just open ocean neighbors. This ensures fjord walls don’t “block” the calving expected at a cell based on its calvingVelocity 2. Adjust the scale_edge_length function to zero edges that are oriented in the opposite direction of the velocity. Previously orientation was ignored but this is now necessary to avoid calving at edges that have neighbors above sea level (item 1) facing the opposite direction as the velocity. # Please enter the commit message for your changes. Lines starting
1 parent a9947f2 commit 4941445

File tree

1 file changed

+34
-23
lines changed

1 file changed

+34
-23
lines changed

components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,6 @@ subroutine eigencalving(domain, err)
13781378
real (kind=RKIND), dimension(:), pointer :: eigencalvingParameter
13791379
real (kind=RKIND), dimension(:), pointer :: calvingVelocity
13801380
real (kind=RKIND), dimension(:), pointer :: eMax, eMin
1381-
real (kind=RKIND), dimension(:), pointer :: angleEdge
13821381
real (kind=RKIND), dimension(:), pointer :: thickness
13831382
real (kind=RKIND), dimension(:), pointer :: calvingThickness
13841383
real (kind=RKIND), pointer :: calvingCFLdt
@@ -1429,7 +1428,6 @@ subroutine eigencalving(domain, err)
14291428
14301429
! get fields
14311430
call mpas_pool_get_array(meshPool, 'deltat', deltat)
1432-
call mpas_pool_get_array(meshPool, 'angleEdge', angleEdge)
14331431
call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
14341432
call mpas_pool_get_array(geometryPool, 'calvingFrontMask', calvingFrontMask)
14351433
call mpas_pool_get_array(geometryPool, 'eigencalvingParameter', eigencalvingParameter)
@@ -1602,7 +1600,6 @@ subroutine specified_calving_velocity(domain, err)
16021600
character (len=StrKIND), pointer :: config_calving_specified_source
16031601
real (kind=RKIND), dimension(:), pointer :: calvingVelocity
16041602
real (kind=RKIND), dimension(:), pointer :: calvingVelocityData
1605-
real (kind=RKIND), dimension(:), pointer :: angleEdge
16061603
real (kind=RKIND), dimension(:), pointer :: thickness
16071604
real (kind=RKIND), dimension(:), pointer :: calvingThickness
16081605
real (kind=RKIND), pointer :: calvingCFLdt
@@ -1643,7 +1640,6 @@ subroutine specified_calving_velocity(domain, err)
16431640
16441641
! get fields
16451642
call mpas_pool_get_array(meshPool, 'deltat', deltat)
1646-
call mpas_pool_get_array(meshPool, 'angleEdge', angleEdge)
16471643
call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
16481644
call mpas_pool_get_array(geometryPool, 'calvingFrontMask', calvingFrontMask)
16491645
call mpas_pool_get_array(geometryPool, 'calvingVelocity', calvingVelocity)
@@ -2495,7 +2491,7 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
24952491
real (kind=RKIND), pointer :: config_calving_error_threshold
24962492
logical, pointer :: config_distribute_unablatedVolumeDynCell
24972493
real (kind=RKIND), dimension(:), pointer :: dvEdge, dcEdge
2498-
real (kind=RKIND), dimension(:), pointer :: angleEdge
2494+
real (kind=RKIND), dimension(:), pointer :: xCell, yCell, xEdge, yEdge
24992495
real (kind=RKIND), dimension(:), pointer :: calvingVelocity, faceMeltSpeed
25002496
real (kind=RKIND), dimension(:), pointer :: areaCell
25012497
real (kind=RKIND), dimension(:,:), pointer :: uReconstructX
@@ -2536,7 +2532,10 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
25362532
call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge)
25372533
call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge)
25382534
call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge)
2539-
call mpas_pool_get_array(meshPool, 'angleEdge', angleEdge)
2535+
call mpas_pool_get_array(meshPool, 'xCell', xCell)
2536+
call mpas_pool_get_array(meshPool, 'yCell', yCell)
2537+
call mpas_pool_get_array(meshPool, 'xEdge', xEdge)
2538+
call mpas_pool_get_array(meshPool, 'yEdge', yEdge)
25402539
call mpas_pool_get_dimension(meshPool, 'nEdges', nEdges)
25412540
call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve)
25422541
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
@@ -2850,10 +2849,9 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
28502849
do iNeighbor = 1, nEdgesOnCell(iCell)
28512850
iEdge = edgesOnCell(iNeighbor, iCell)
28522851
jCell = cellsOnCell(iNeighbor, iCell)
2853-
if (li_mask_is_margin(edgeMask(iEdge)) .and. & !< edge is a margin
2854-
.not. li_mask_is_ice(cellMask(jCell)) .and. bedTopography(jCell) < config_sea_level & ! ensure margin is w/ocn
2855-
) then
2856-
edgeLengthScaling = scale_edge_length(angleEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
2852+
if (li_mask_is_margin(edgeMask(iEdge)) .or. &
2853+
(li_mask_is_ice(cellMask(jCell)) .and. bedTopography(jCell) > config_sea_level)) then
2854+
edgeLengthScaling = scale_edge_length(xCell(iCell), yCell(iCell), xEdge(iEdge), yEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
28572855
requiredAblationVolumeNonDynEdge(iEdge) = ablationVelocity(iCell) * &
28582856
edgeLengthScaling * dvEdge(iEdge) * thicknessForAblation(iCell) * deltat
28592857
requiredAblationVolumeNonDynCell(iCell) = requiredAblationVolumeNonDynCell(iCell) + &
@@ -2913,9 +2911,10 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
29132911
.and. li_mask_is_margin(cellMask(iCell)) ) then ! that is at the edge of the ice
29142912
do iNeighbor = 1, nEdgesOnCell(iCell)
29152913
jCell = cellsOnCell(iNeighbor, iCell)
2916-
if ((.not. li_mask_is_ice(cellMask(jCell))) .and. (bedTopography(jCell) < config_sea_level)) then
2914+
if ((.not. li_mask_is_ice(cellMask(jCell))) .and. (bedTopography(jCell) < config_sea_level) .or. &
2915+
(bedTopography(jCell) > config_sea_level) ) then
29172916
iEdge = edgesOnCell(iNeighbor, iCell)
2918-
edgeLengthScaling = scale_edge_length(angleEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
2917+
edgeLengthScaling = scale_edge_length(xCell(iCell), yCell(iCell), xEdge(iEdge), yEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
29192918
requiredAblationVolumeDynEdge(iEdge) = ablationVelocity(iCell) * &
29202919
edgeLengthScaling * dvEdge(iEdge) * thicknessForAblation(iCell) * deltat
29212920
endif
@@ -2939,7 +2938,7 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
29392938
do iNeighbor = 1, nEdgesOnCell(iCell)
29402939
iEdge = edgesOnCell(iNeighbor, iCell)
29412940
if (li_mask_is_dynamic_ice(edgeMask(iEdge))) then
2942-
edgeLengthScaling = scale_edge_length(angleEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
2941+
edgeLengthScaling = scale_edge_length(xCell(iCell), yCell(iCell), xEdge(iEdge), yEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
29432942
ablateLengthEdge = edgeLengthScaling * dvEdge(iEdge)
29442943
ablateLengthCell = ablateLengthCell + ablateLengthEdge
29452944
endif
@@ -2951,7 +2950,7 @@ subroutine li_apply_front_ablation_velocity(meshPool, geometryPool, velocityPool
29512950
iEdge = edgesOnCell(iNeighbor, iCell)
29522951
jCell = cellsOnCell(iNeighbor, iCell)
29532952
if (li_mask_is_dynamic_ice(edgeMask(iEdge))) then
2954-
edgeLengthScaling = scale_edge_length(angleEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
2953+
edgeLengthScaling = scale_edge_length(xCell(iCell), yCell(iCell), xEdge(iEdge), yEdge(iEdge), uvelForAblation(iCell), vvelForAblation(iCell))
29552954
ablateLengthEdge = edgeLengthScaling * dvEdge(iEdge)
29562955
if (requiredAblationVolumeDynEdge(iEdge) > 0.0_RKIND) then
29572956
call mpas_log_write("Unexpectedly found a dynamic edge that already has calving assigned to it." // &
@@ -3178,18 +3177,30 @@ end subroutine li_apply_front_ablation_velocity
31783177

31793178
! Helper function for subroutine li_apply_front_ablation_velocity
31803179
! Calculates the amount to scale an edge length based on the orientation of the edge with the surface velocity
3181-
function scale_edge_length(angleEdgeHere, u, v)
3182-
real(kind=RKIND), intent(in) :: angleEdgeHere
3183-
real(kind=RKIND), intent(in) :: u
3184-
real(kind=RKIND), intent(in) :: v
3180+
function scale_edge_length(xc, yc, xe, ye, vx, vy)
3181+
real(kind=RKIND), intent(in) :: xc, yc ! x,y coords of cell center
3182+
real(kind=RKIND), intent(in) :: xe, ye ! x,y coords of edge neighboring cell
3183+
real(kind=RKIND), intent(in) :: vx, vy ! x,y components of velocity vector
31853184
real(kind=RKIND) :: scale_edge_length
31863185

3187-
real(kind=RKIND) :: mag
3186+
real(kind=RKIND) :: ux, uy, umag, vmag
3187+
3188+
! Calculate vector pointing from cell center to edge
3189+
ux = xe - xc
3190+
uy = ye - yc
3191+
umag = sqrt(ux**2 + uy**2)
3192+
3193+
! avoid divide by zero
3194+
if (umag == 0.0_RKIND) umag = 1.0_RKIND
3195+
vmag = sqrt(vx**2 + vy**2)
3196+
if (vmag == 0.0_RKIND) vmag = 1.0_RKIND
3197+
3198+
! dot product of unit vectors
3199+
scale_edge_length = (ux / umag) * (vx / vmag) + (uy / umag) * (vy / vmag)
3200+
! set scale to 0 where vectors are not pointing the same way
3201+
! (i.e. where vector to edge points away from flow direction)
3202+
scale_edge_length = max(0.0, scale_edge_length)
31883203

3189-
mag = sqrt(u**2 + v**2)
3190-
if (mag == 0.0_RKIND) mag = 1.0_RKIND
3191-
scale_edge_length = abs(u/mag * cos(angleEdgeHere) + v/mag * sin(angleEdgeHere)) ! dot product of unit vectors
3192-
!scale_edge_length = abs(cos(angleEdgeHere - atan2(v, u)))
31933204
end function scale_edge_length
31943205

31953206

0 commit comments

Comments
 (0)