icon4py-bindings 0.2.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- icon4py/bindings/__init__.py +29 -0
- icon4py/bindings/all_bindings.py +68 -0
- icon4py/bindings/common.py +325 -0
- icon4py/bindings/config.py +13 -0
- icon4py/bindings/debug_utils.py +129 -0
- icon4py/bindings/diffusion_wrapper.py +308 -0
- icon4py/bindings/dycore_wrapper.py +445 -0
- icon4py/bindings/grid_wrapper.py +244 -0
- icon4py/bindings/icon4py_export.py +122 -0
- icon4py/bindings/muphys_wrapper.py +97 -0
- icon4py/bindings/viztracer_plugin.py +89 -0
- icon4py_bindings-0.2.0rc2.dist-info/METADATA +43 -0
- icon4py_bindings-0.2.0rc2.dist-info/RECORD +15 -0
- icon4py_bindings-0.2.0rc2.dist-info/WHEEL +5 -0
- icon4py_bindings-0.2.0rc2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# ICON4Py - ICON inspired code in Python and GT4Py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2022-2024, ETH Zurich and MeteoSwiss
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Please, refer to the LICENSE file in the root directory.
|
|
7
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
8
|
+
|
|
9
|
+
"""Package metadata: version, authors, license and copyright."""
|
|
10
|
+
|
|
11
|
+
from typing import Final
|
|
12
|
+
|
|
13
|
+
from packaging import version as pkg_version
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"__author__",
|
|
18
|
+
"__copyright__",
|
|
19
|
+
"__license__",
|
|
20
|
+
"__version__",
|
|
21
|
+
"__version_info__",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
__author__: Final = "ETH Zurich, MeteoSwiss and individual contributors"
|
|
25
|
+
__copyright__: Final = "Copyright (c) 2022-2024 ETH Zurich and MeteoSwiss"
|
|
26
|
+
__license__: Final = "BSD-3-Clause"
|
|
27
|
+
|
|
28
|
+
__version__: Final = "0.2.0rc2"
|
|
29
|
+
__version_info__: Final = pkg_version.parse(__version__)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# ICON4Py - ICON inspired code in Python and GT4Py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2022-2024, ETH Zurich and MeteoSwiss
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Please, refer to the LICENSE file in the root directory.
|
|
7
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
8
|
+
|
|
9
|
+
"""CLI entrypoint that generates the combined icon4py Fortran/C bindings.
|
|
10
|
+
|
|
11
|
+
Run as ``python -m icon4py.bindings.all_bindings --output-f90 X --output-c Y``.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import pathlib
|
|
17
|
+
|
|
18
|
+
import click
|
|
19
|
+
|
|
20
|
+
from icon4py.bindings import diffusion_wrapper, dycore_wrapper, grid_wrapper
|
|
21
|
+
from icon4py.tools import py2fgen
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
FUNCTIONS = [
|
|
25
|
+
diffusion_wrapper.diffusion_init,
|
|
26
|
+
diffusion_wrapper.diffusion_run,
|
|
27
|
+
grid_wrapper.grid_init,
|
|
28
|
+
dycore_wrapper.solve_nh_init,
|
|
29
|
+
dycore_wrapper.solve_nh_run,
|
|
30
|
+
]
|
|
31
|
+
LIBRARY_NAME = "icon4py_bindings"
|
|
32
|
+
|
|
33
|
+
_FILE_PATH = click.Path(dir_okay=False, resolve_path=True, path_type=pathlib.Path)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@click.command(name="all_bindings")
|
|
37
|
+
@click.option(
|
|
38
|
+
"--output-f90",
|
|
39
|
+
type=_FILE_PATH,
|
|
40
|
+
default=None,
|
|
41
|
+
help="Path for the generated Fortran interface (.f90).",
|
|
42
|
+
)
|
|
43
|
+
@click.option(
|
|
44
|
+
"--output-c",
|
|
45
|
+
type=_FILE_PATH,
|
|
46
|
+
default=None,
|
|
47
|
+
help="Path for the generated CFFI C source (.c). The .h header is written alongside.",
|
|
48
|
+
)
|
|
49
|
+
def main(output_f90: pathlib.Path | None, output_c: pathlib.Path | None) -> None:
|
|
50
|
+
"""Generate the icon4py Fortran/C binding sources at user-chosen paths."""
|
|
51
|
+
if output_f90 is None and output_c is None:
|
|
52
|
+
raise click.UsageError("specify --output-f90 and/or --output-c")
|
|
53
|
+
|
|
54
|
+
plugin = py2fgen.get_cffi_description(FUNCTIONS, LIBRARY_NAME)
|
|
55
|
+
h_basename = output_c.with_suffix(".h").name if output_c is not None else f"{LIBRARY_NAME}.h"
|
|
56
|
+
sources = py2fgen.render(plugin, h_basename=h_basename)
|
|
57
|
+
|
|
58
|
+
# write_if_changed avoids touching mtimes (and triggering downstream
|
|
59
|
+
# rebuilds) when the rendered content matches what is already on disk.
|
|
60
|
+
if output_f90 is not None:
|
|
61
|
+
py2fgen.write_if_changed(sources.f90, output_f90)
|
|
62
|
+
if output_c is not None:
|
|
63
|
+
py2fgen.write_if_changed(sources.c, output_c)
|
|
64
|
+
py2fgen.write_if_changed(sources.h, output_c.with_suffix(".h"))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if __name__ == "__main__":
|
|
68
|
+
main()
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# ICON4Py - ICON inspired code in Python and GT4Py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2022-2024, ETH Zurich and MeteoSwiss
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Please, refer to the LICENSE file in the root directory.
|
|
7
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
import functools
|
|
11
|
+
import logging
|
|
12
|
+
from collections.abc import Callable, Iterable
|
|
13
|
+
from types import ModuleType
|
|
14
|
+
from typing import TYPE_CHECKING, Annotated, Final, TypeAlias
|
|
15
|
+
|
|
16
|
+
import gt4py.next as gtx
|
|
17
|
+
import gt4py.next.typing as gtx_typing
|
|
18
|
+
import numpy as np
|
|
19
|
+
from gt4py import eve
|
|
20
|
+
from gt4py._core import definitions as gt4py_definitions
|
|
21
|
+
from gt4py.next.type_system import type_specifications as ts
|
|
22
|
+
|
|
23
|
+
from icon4py.model.common import dimension as dims, model_backends
|
|
24
|
+
from icon4py.model.common.decomposition import definitions, mpi_decomposition
|
|
25
|
+
from icon4py.model.common.grid import base, horizontal as h_grid, icon
|
|
26
|
+
from icon4py.model.common.utils import data_allocation as data_alloc
|
|
27
|
+
from icon4py.model.common.utils.data_allocation import adjust_fortran_indices
|
|
28
|
+
from icon4py.tools import py2fgen
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
xp: Final = np
|
|
33
|
+
else:
|
|
34
|
+
try:
|
|
35
|
+
import cupy as cp
|
|
36
|
+
|
|
37
|
+
xp = cp
|
|
38
|
+
except ImportError:
|
|
39
|
+
cp = None
|
|
40
|
+
xp = np
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
NDArray: TypeAlias = np.ndarray | xp.ndarray
|
|
44
|
+
|
|
45
|
+
# TODO(havogt): import needed to register MultNodeRun in get_process_properties, does the pattern make sense?
|
|
46
|
+
assert hasattr(mpi_decomposition, "get_multinode_properties")
|
|
47
|
+
|
|
48
|
+
log = logging.getLogger(__name__)
|
|
49
|
+
|
|
50
|
+
Int32Array1D: TypeAlias = Annotated[
|
|
51
|
+
data_alloc.NDArray,
|
|
52
|
+
py2fgen.ArrayParamDescriptor(
|
|
53
|
+
rank=1,
|
|
54
|
+
dtype=ts.ScalarKind.INT32,
|
|
55
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
56
|
+
is_optional=False,
|
|
57
|
+
),
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
OptionalInt32Array1D: TypeAlias = Annotated[
|
|
61
|
+
data_alloc.NDArray | None,
|
|
62
|
+
py2fgen.ArrayParamDescriptor(
|
|
63
|
+
rank=1,
|
|
64
|
+
dtype=ts.ScalarKind.INT32,
|
|
65
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
66
|
+
is_optional=True,
|
|
67
|
+
),
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
OptionalInt32Array2D: TypeAlias = Annotated[
|
|
71
|
+
data_alloc.NDArray | None,
|
|
72
|
+
py2fgen.ArrayParamDescriptor(
|
|
73
|
+
rank=2,
|
|
74
|
+
dtype=ts.ScalarKind.INT32,
|
|
75
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
76
|
+
is_optional=True,
|
|
77
|
+
),
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
Float64Array1D: TypeAlias = Annotated[
|
|
81
|
+
data_alloc.NDArray,
|
|
82
|
+
py2fgen.ArrayParamDescriptor(
|
|
83
|
+
rank=1,
|
|
84
|
+
dtype=ts.ScalarKind.FLOAT64,
|
|
85
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
86
|
+
is_optional=False,
|
|
87
|
+
),
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
Float64Array2D: TypeAlias = Annotated[
|
|
91
|
+
data_alloc.NDArray,
|
|
92
|
+
py2fgen.ArrayParamDescriptor(
|
|
93
|
+
rank=2,
|
|
94
|
+
dtype=ts.ScalarKind.FLOAT64,
|
|
95
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
96
|
+
is_optional=False,
|
|
97
|
+
),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
Float64Array3D: TypeAlias = Annotated[
|
|
101
|
+
data_alloc.NDArray,
|
|
102
|
+
py2fgen.ArrayParamDescriptor(
|
|
103
|
+
rank=3,
|
|
104
|
+
dtype=ts.ScalarKind.FLOAT64,
|
|
105
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
106
|
+
is_optional=False,
|
|
107
|
+
),
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
OptionalFloat64Array1D: TypeAlias = Annotated[
|
|
111
|
+
data_alloc.NDArray | None,
|
|
112
|
+
py2fgen.ArrayParamDescriptor(
|
|
113
|
+
rank=1,
|
|
114
|
+
dtype=ts.ScalarKind.FLOAT64,
|
|
115
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
116
|
+
is_optional=True,
|
|
117
|
+
),
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
OptionalFloat64Array2D: TypeAlias = Annotated[
|
|
121
|
+
data_alloc.NDArray,
|
|
122
|
+
py2fgen.ArrayParamDescriptor(
|
|
123
|
+
rank=2,
|
|
124
|
+
dtype=ts.ScalarKind.FLOAT64,
|
|
125
|
+
memory_space=py2fgen.MemorySpace.MAYBE_DEVICE,
|
|
126
|
+
is_optional=True,
|
|
127
|
+
),
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class BackendIntEnum(eve.IntEnum):
|
|
132
|
+
DEFAULT = 0
|
|
133
|
+
DACE = 1
|
|
134
|
+
GTFN = 2
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def select_backend(
|
|
138
|
+
selector: BackendIntEnum, on_gpu: bool
|
|
139
|
+
) -> gtx_typing.Backend | model_backends.BackendDescriptor:
|
|
140
|
+
backend_descriptor: model_backends.BackendDescriptor = {}
|
|
141
|
+
backend_descriptor["device"] = model_backends.GPU if on_gpu else model_backends.CPU
|
|
142
|
+
if selector == BackendIntEnum.DEFAULT:
|
|
143
|
+
return backend_descriptor
|
|
144
|
+
if selector == BackendIntEnum.DACE:
|
|
145
|
+
backend_descriptor["backend_factory"] = model_backends.make_custom_dace_backend
|
|
146
|
+
return backend_descriptor
|
|
147
|
+
if selector == BackendIntEnum.GTFN:
|
|
148
|
+
backend_descriptor["backend_factory"] = model_backends.make_custom_gtfn_backend
|
|
149
|
+
return backend_descriptor
|
|
150
|
+
|
|
151
|
+
raise ValueError(f"Invalid backend selector: {selector}")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def cached_dummy_field_factory(
|
|
155
|
+
allocator: gtx_typing.Allocator | None,
|
|
156
|
+
) -> Callable[[str, gtx.Domain, gt4py_definitions.DType], gtx.Field]:
|
|
157
|
+
# curried to exclude non-hashable backend from cache
|
|
158
|
+
@functools.lru_cache(maxsize=20)
|
|
159
|
+
def impl(_name: str, domain: gtx.Domain, dtype: gt4py_definitions.DType) -> gtx.Field:
|
|
160
|
+
# _name is used to differentiate between different dummy fields
|
|
161
|
+
return gtx.zeros(domain, dtype=dtype, allocator=allocator)
|
|
162
|
+
|
|
163
|
+
return impl
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def shrink_to_dimension(
|
|
167
|
+
sizes: dict[gtx.Dimension, int], tables: dict[gtx.FieldOffset, NDArray]
|
|
168
|
+
) -> dict[gtx.FieldOffset, NDArray]:
|
|
169
|
+
"""Shrink the neighbor tables from nproma size to the actual size of the grid."""
|
|
170
|
+
return {k: v[: sizes[k.target[0]]] for k, v in tables.items()}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def add_origin(xp: ModuleType, table: NDArray) -> NDArray:
|
|
174
|
+
return xp.column_stack((xp.arange(table.shape[0], dtype=xp.int32), table))
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def get_nproma(tables: Iterable[NDArray]) -> int:
|
|
178
|
+
tables = list(tables)
|
|
179
|
+
nproma = tables[0].shape[0]
|
|
180
|
+
if not all(table.shape[0] == nproma for table in tables):
|
|
181
|
+
raise ValueError("All connectivity tables must have the same number of rows (nproma).")
|
|
182
|
+
return nproma
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def construct_icon_grid(
|
|
186
|
+
cell_starts: np.ndarray,
|
|
187
|
+
cell_ends: np.ndarray,
|
|
188
|
+
vertex_starts: np.ndarray,
|
|
189
|
+
vertex_ends: np.ndarray,
|
|
190
|
+
edge_starts: np.ndarray,
|
|
191
|
+
edge_ends: np.ndarray,
|
|
192
|
+
c2e: NDArray,
|
|
193
|
+
e2c: NDArray,
|
|
194
|
+
c2e2c: NDArray,
|
|
195
|
+
e2c2e: NDArray,
|
|
196
|
+
e2v: NDArray,
|
|
197
|
+
v2e: NDArray,
|
|
198
|
+
v2c: NDArray,
|
|
199
|
+
e2c2v: NDArray,
|
|
200
|
+
c2v: NDArray,
|
|
201
|
+
grid_id: str,
|
|
202
|
+
num_vertices: int,
|
|
203
|
+
num_cells: int,
|
|
204
|
+
num_edges: int,
|
|
205
|
+
vertical_size: int,
|
|
206
|
+
limited_area: bool,
|
|
207
|
+
distributed: bool,
|
|
208
|
+
allocator: gtx_typing.Allocator | None,
|
|
209
|
+
) -> icon.IconGrid:
|
|
210
|
+
log.debug("Constructing ICON Grid in Python...")
|
|
211
|
+
log.debug("num_cells:%s", num_cells)
|
|
212
|
+
log.debug("num_edges:%s", num_edges)
|
|
213
|
+
log.debug("num_vertices:%s", num_vertices)
|
|
214
|
+
log.debug("num_levels:%s", vertical_size)
|
|
215
|
+
|
|
216
|
+
log.debug("Offsetting Fortran connectivitity arrays by 1")
|
|
217
|
+
|
|
218
|
+
xp = data_alloc.import_array_ns(allocator)
|
|
219
|
+
start_indices = {
|
|
220
|
+
# TODO(halungge): ICON Fortran has 0 values in these arrays in some places possibly where they don't use them.
|
|
221
|
+
# We should investigate where we access these values.
|
|
222
|
+
dims.CellDim: np.maximum(0, adjust_fortran_indices(cell_starts)),
|
|
223
|
+
dims.EdgeDim: np.maximum(0, adjust_fortran_indices(edge_starts)),
|
|
224
|
+
dims.VertexDim: np.maximum(0, adjust_fortran_indices(vertex_starts)),
|
|
225
|
+
}
|
|
226
|
+
end_indices = {dims.CellDim: cell_ends, dims.EdgeDim: edge_ends, dims.VertexDim: vertex_ends}
|
|
227
|
+
|
|
228
|
+
c2e = adjust_fortran_indices(c2e)
|
|
229
|
+
c2v = adjust_fortran_indices(c2v)
|
|
230
|
+
v2c = adjust_fortran_indices(v2c)
|
|
231
|
+
e2v = adjust_fortran_indices(e2v)[
|
|
232
|
+
:, 0:2
|
|
233
|
+
] # slicing required for e2v as input data is actually e2c2v
|
|
234
|
+
c2e2c = adjust_fortran_indices(c2e2c)
|
|
235
|
+
v2e = adjust_fortran_indices(v2e)
|
|
236
|
+
e2c2v = adjust_fortran_indices(e2c2v)
|
|
237
|
+
e2c = adjust_fortran_indices(e2c)
|
|
238
|
+
e2c2e = adjust_fortran_indices(e2c2e)
|
|
239
|
+
|
|
240
|
+
# stacked arrays
|
|
241
|
+
c2e2c0 = add_origin(xp, c2e2c)
|
|
242
|
+
e2c2e0 = add_origin(xp, e2c2e)
|
|
243
|
+
|
|
244
|
+
config = base.GridConfig(
|
|
245
|
+
horizontal_config=base.HorizontalGridSize(
|
|
246
|
+
num_vertices=num_vertices,
|
|
247
|
+
num_cells=num_cells,
|
|
248
|
+
num_edges=num_edges,
|
|
249
|
+
),
|
|
250
|
+
vertical_size=vertical_size,
|
|
251
|
+
limited_area=limited_area,
|
|
252
|
+
distributed=distributed,
|
|
253
|
+
keep_skip_values=False,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
neighbor_tables = {
|
|
257
|
+
dims.C2E: c2e,
|
|
258
|
+
dims.C2V: c2v,
|
|
259
|
+
dims.E2C: e2c,
|
|
260
|
+
dims.E2C2E: e2c2e,
|
|
261
|
+
dims.C2E2C: c2e2c,
|
|
262
|
+
dims.C2E2CO: c2e2c0,
|
|
263
|
+
dims.E2C2EO: e2c2e0,
|
|
264
|
+
dims.V2E: v2e,
|
|
265
|
+
dims.E2V: e2v,
|
|
266
|
+
dims.E2C2V: e2c2v,
|
|
267
|
+
dims.V2C: v2c,
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
neighbor_tables = shrink_to_dimension(
|
|
271
|
+
sizes={dims.EdgeDim: num_edges, dims.VertexDim: num_vertices, dims.CellDim: num_cells},
|
|
272
|
+
tables=neighbor_tables,
|
|
273
|
+
)
|
|
274
|
+
domain_bounds_constructor = functools.partial(
|
|
275
|
+
h_grid.get_start_end_idx_from_icon_arrays,
|
|
276
|
+
start_indices=start_indices,
|
|
277
|
+
end_indices=end_indices,
|
|
278
|
+
)
|
|
279
|
+
start_index, end_index = icon.get_start_and_end_index(domain_bounds_constructor)
|
|
280
|
+
|
|
281
|
+
return icon.icon_grid(
|
|
282
|
+
id_=grid_id,
|
|
283
|
+
allocator=allocator,
|
|
284
|
+
config=config,
|
|
285
|
+
neighbor_tables=neighbor_tables,
|
|
286
|
+
start_index=start_index,
|
|
287
|
+
end_index=end_index,
|
|
288
|
+
grid_params=icon.GridParams(),
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def construct_decomposition(
|
|
293
|
+
c_glb_index: np.ndarray,
|
|
294
|
+
e_glb_index: np.ndarray,
|
|
295
|
+
v_glb_index: np.ndarray,
|
|
296
|
+
c_owner_mask: np.ndarray,
|
|
297
|
+
e_owner_mask: np.ndarray,
|
|
298
|
+
v_owner_mask: np.ndarray,
|
|
299
|
+
num_cells: int,
|
|
300
|
+
num_edges: int,
|
|
301
|
+
num_vertices: int,
|
|
302
|
+
comm_id: int,
|
|
303
|
+
) -> tuple[
|
|
304
|
+
definitions.ProcessProperties, definitions.DecompositionInfo, definitions.ExchangeRuntime
|
|
305
|
+
]:
|
|
306
|
+
log.debug("Offsetting Fortran connectivitity arrays by 1")
|
|
307
|
+
c_glb_index = adjust_fortran_indices(c_glb_index)
|
|
308
|
+
e_glb_index = adjust_fortran_indices(e_glb_index)
|
|
309
|
+
v_glb_index = adjust_fortran_indices(v_glb_index)
|
|
310
|
+
|
|
311
|
+
c_owner_mask = c_owner_mask[:num_cells]
|
|
312
|
+
e_owner_mask = e_owner_mask[:num_edges]
|
|
313
|
+
v_owner_mask = v_owner_mask[:num_vertices]
|
|
314
|
+
|
|
315
|
+
decomposition_info = (
|
|
316
|
+
definitions.DecompositionInfo()
|
|
317
|
+
# TODO (halungge): last argument is called `decomp_domain` in icon, it is not needed in the granules should we pass it nevertheless?
|
|
318
|
+
.set_dimension(dims.CellDim, c_glb_index, c_owner_mask, None)
|
|
319
|
+
.set_dimension(dims.EdgeDim, e_glb_index, e_owner_mask, None)
|
|
320
|
+
.set_dimension(dims.VertexDim, v_glb_index, v_owner_mask, None)
|
|
321
|
+
)
|
|
322
|
+
process_props = definitions.get_process_properties(definitions.MultiNodeRun(), comm_id)
|
|
323
|
+
exchange = definitions.create_exchange(process_props, decomposition_info)
|
|
324
|
+
|
|
325
|
+
return process_props, decomposition_info, exchange
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# ICON4Py - ICON inspired code in Python and GT4Py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2022-2024, ETH Zurich and MeteoSwiss
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Please, refer to the LICENSE file in the root directory.
|
|
7
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
8
|
+
|
|
9
|
+
from icon4py.model.common.utils import env
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
WAIT_FOR_COMPILATION: bool = env.flag_to_bool("ICON4PY_WAIT_FOR_COMPILATION", False)
|
|
13
|
+
"""Wait in granule initialization until jit compilation is complete."""
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# ICON4Py - ICON inspired code in Python and GT4Py
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2022-2024, ETH Zurich and MeteoSwiss
|
|
4
|
+
# All rights reserved.
|
|
5
|
+
#
|
|
6
|
+
# Please, refer to the LICENSE file in the root directory.
|
|
7
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from gt4py.next import common as gtx_common
|
|
12
|
+
|
|
13
|
+
from icon4py.model.common import dimension as dims
|
|
14
|
+
from icon4py.model.common.decomposition import definitions
|
|
15
|
+
from icon4py.model.common.grid import horizontal as h_grid, icon
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def print_grid_decomp_info(
|
|
22
|
+
icon_grid: icon.IconGrid,
|
|
23
|
+
process_props: definitions.ProcessProperties,
|
|
24
|
+
decomposition_info: definitions.DecompositionInfo,
|
|
25
|
+
num_cells: int,
|
|
26
|
+
num_edges: int,
|
|
27
|
+
num_verts: int,
|
|
28
|
+
) -> None:
|
|
29
|
+
logger.info(
|
|
30
|
+
"icon_grid:cell_start for rank %s is.... %s",
|
|
31
|
+
process_props.rank,
|
|
32
|
+
"\n".join(
|
|
33
|
+
[
|
|
34
|
+
f"{k!s} - {icon_grid.start_index(k)}"
|
|
35
|
+
for k in h_grid.get_domains_for_dim(dims.CellDim)
|
|
36
|
+
]
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
logger.info(
|
|
40
|
+
"icon_grid:cell_end for rank %s is.... %s",
|
|
41
|
+
process_props.rank,
|
|
42
|
+
"\n".join(
|
|
43
|
+
[f"{k!s} - {icon_grid.end_index(k)}" for k in h_grid.get_domains_for_dim(dims.CellDim)]
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
logger.info(
|
|
47
|
+
"icon_grid:vert_start for rank %s is.... %s",
|
|
48
|
+
process_props.rank,
|
|
49
|
+
"\n".join(
|
|
50
|
+
[
|
|
51
|
+
f"{k!s} - {icon_grid.start_index(k)}"
|
|
52
|
+
for k in h_grid.get_domains_for_dim(dims.VertexDim)
|
|
53
|
+
]
|
|
54
|
+
),
|
|
55
|
+
)
|
|
56
|
+
logger.info(
|
|
57
|
+
"icon_grid:vert_end for rank %s is.... %s",
|
|
58
|
+
process_props.rank,
|
|
59
|
+
"\n".join(
|
|
60
|
+
[
|
|
61
|
+
f"{k!s} - {icon_grid.end_index(k)}"
|
|
62
|
+
for k in h_grid.get_domains_for_dim(dims.VertexDim)
|
|
63
|
+
]
|
|
64
|
+
),
|
|
65
|
+
)
|
|
66
|
+
logger.info(
|
|
67
|
+
"icon_grid:edge_start for rank %s is.... %s",
|
|
68
|
+
process_props.rank,
|
|
69
|
+
"\n".join(
|
|
70
|
+
[
|
|
71
|
+
f"{k!s} - {icon_grid.start_index(k)}"
|
|
72
|
+
for k in h_grid.get_domains_for_dim(dims.EdgeDim)
|
|
73
|
+
]
|
|
74
|
+
),
|
|
75
|
+
)
|
|
76
|
+
logger.info(
|
|
77
|
+
"icon_grid:edge_end for rank %s is.... %s",
|
|
78
|
+
process_props.rank,
|
|
79
|
+
"\n".join(
|
|
80
|
+
[f"{k!s} - {icon_grid.end_index(k)}" for k in h_grid.get_domains_for_dim(dims.EdgeDim)]
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
for offset, connectivity in icon_grid.connectivities.items():
|
|
85
|
+
if gtx_common.is_neighbor_table(connectivity):
|
|
86
|
+
logger.debug(
|
|
87
|
+
f"icon_grid:{offset} for rank {process_props.rank} is.... {connectivity.asnumpy()}"
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
logger.info(
|
|
91
|
+
"c_glb_index for rank %s is.... %s",
|
|
92
|
+
process_props.rank,
|
|
93
|
+
decomposition_info.global_index(dims.CellDim)[0:num_cells],
|
|
94
|
+
)
|
|
95
|
+
logger.info(
|
|
96
|
+
"e_glb_index for rank %s is.... %s",
|
|
97
|
+
process_props.rank,
|
|
98
|
+
decomposition_info.global_index(dims.EdgeDim)[0:num_edges],
|
|
99
|
+
)
|
|
100
|
+
logger.info(
|
|
101
|
+
"v_glb_index for rank %s is.... %s",
|
|
102
|
+
process_props.rank,
|
|
103
|
+
decomposition_info.global_index(dims.VertexDim)[0:num_verts],
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
logger.info(
|
|
107
|
+
"c_owner_mask for rank %s is.... %s",
|
|
108
|
+
process_props.rank,
|
|
109
|
+
decomposition_info.owner_mask(dims.CellDim)[0:num_cells],
|
|
110
|
+
)
|
|
111
|
+
logger.info(
|
|
112
|
+
"e_owner_mask for rank %s is.... %s",
|
|
113
|
+
process_props.rank,
|
|
114
|
+
decomposition_info.owner_mask(dims.EdgeDim)[0:num_edges],
|
|
115
|
+
)
|
|
116
|
+
logger.info(
|
|
117
|
+
"v_owner_mask for rank %s is.... %s",
|
|
118
|
+
process_props.rank,
|
|
119
|
+
decomposition_info.owner_mask(dims.VertexDim)[0:num_verts],
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
logger.info(
|
|
123
|
+
f"local cells = {decomposition_info.global_index(dims.CellDim, definitions.DecompositionInfo.EntryType.ALL).shape} "
|
|
124
|
+
f"local edges = {decomposition_info.global_index(dims.EdgeDim, definitions.DecompositionInfo.EntryType.ALL).shape} "
|
|
125
|
+
f"local vertices = {decomposition_info.global_index(dims.VertexDim, definitions.DecompositionInfo.EntryType.ALL).shape}"
|
|
126
|
+
)
|
|
127
|
+
logger.info(
|
|
128
|
+
f"rank={process_props.rank}/{process_props.comm_size}: GHEX context setup: from {process_props.comm_name} with {process_props.comm_size} nodes"
|
|
129
|
+
)
|