PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
remove_narrow_tongues.cc
Go to the documentation of this file.
1/* Copyright (C) 2016, 2017, 2018, 2019, 2020, 2022, 2023, 2025 PISM Authors
2 *
3 * This file is part of PISM.
4 *
5 * PISM is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with PISM; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "pism/frontretreat/util/remove_narrow_tongues.hh"
21
22#include "pism/util/Grid.hh"
23#include "pism/geometry/Geometry.hh"
24
25namespace pism {
26
27// Apply a function to all data members of Box<int> and return results.
28template <typename IN, typename OUT>
29stencils::Box<OUT> apply(const stencils::Box<IN> &input, OUT (*f)(IN)) {
30 return { f(input.c), f(input.n), f(input.nw), f(input.w), f(input.sw),
31 f(input.s), f(input.se), f(input.e), f(input.ne) };
32}
33
34/** Remove tips of one-cell-wide ice tongues ("noses")..
35 *
36 * The center icy cell in ice tongues like this one (and equivalent)
37 *
38 * @code
39 O O ?
40 X X O
41 O O ?
42 @endcode
43 *
44 * where "O" is ice-free and "?" is any mask value, are removed.
45 * Ice tongues like this one
46 *
47 * @code
48 # O ?
49 X X O
50 # O ?
51 @endcode
52 * where one or two of the "#" cells are ice-filled, are not removed.
53 *
54 * See the code for the precise rule, which uses `ice_free_ocean()` for the "O"
55 * cells if the center cell has grounded ice, and uses `ice_free()` if the
56 * center cell has floating ice.
57 *
58 * @note We use `geometry.cell_type` (and not `ice_thickness`) to make decisions. This
59 * means that we can update `ice_thickness` in place without introducing a dependence on
60 * the grid traversal order.
61 *
62 * @param[in,out] mask cell type mask
63 * @param[in,out] ice_thickness modeled ice thickness
64 *
65 * @return 0 on success
66 */
67void remove_narrow_tongues(const Geometry &geometry,
68 array::Scalar &ice_thickness) {
69
70 const auto &mask = geometry.cell_type;
71 const auto &bed = geometry.bed_elevation;
72 const auto &sea_level = geometry.sea_level_elevation;
73
74 auto grid = mask.grid();
75
76 array::AccessScope list{&mask, &bed, &sea_level, &ice_thickness};
77
78 for (auto p : grid->points()) {
79 const int i = p.i(), j = p.j();
80 if (mask.ice_free(i, j) or
81 (mask.grounded_ice(i, j) and bed(i, j) >= sea_level(i, j))) {
82 continue;
83 }
84
85 // Note: i,j cannot be ice-free (see the if-block above), so it is either grounded ice
86 // or floating ice.
87 //
88 // If (i,j) is grounded ice then we will remove it if it has
89 // exclusively ice-free ocean neighbors.
90 //
91 // If (i,j) is floating then we will remove it if its neighbors are
92 // ice-free, whether ice-free ocean or ice-free ground.
93 auto ice_free =
94 apply(mask.box_int(i, j), mask.grounded_ice(i, j) ? mask::ice_free_ocean : mask::ice_free);
95
96 if ((not ice_free.w and
97 ice_free.nw and
98 ice_free.sw and
99 ice_free.n and
100 ice_free.s and
101 ice_free.e) or
102 (not ice_free.n and
103 ice_free.nw and
104 ice_free.ne and
105 ice_free.w and
106 ice_free.e and
107 ice_free.s) or
108 (not ice_free.e and
109 ice_free.ne and
110 ice_free.se and
111 ice_free.w and
112 ice_free.s and
113 ice_free.n) or
114 (not ice_free.s and
115 ice_free.sw and
116 ice_free.se and
117 ice_free.w and
118 ice_free.e and
119 ice_free.n)) {
120 ice_thickness(i, j) = 0.0;
121 }
122 }
123}
124
125} // end of namespace pism
array::Scalar1 sea_level_elevation
Definition Geometry.hh:48
array::CellType2 cell_type
Definition Geometry.hh:55
array::Scalar2 bed_elevation
Definition Geometry.hh:47
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
bool ice_free_ocean(int M)
Definition Mask.hh:61
bool ice_free(int M)
Ice-free cell (grounded or ocean).
Definition Mask.hh:58
stencils::Box< OUT > apply(const stencils::Box< IN > &input, OUT(*f)(IN))
void remove_narrow_tongues(const Geometry &geometry, array::Scalar &ice_thickness)