icon4py-standalone-driver 0.2.0rc2__tar.gz

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.
Files changed (21) hide show
  1. icon4py_standalone_driver-0.2.0rc2/PKG-INFO +64 -0
  2. icon4py_standalone_driver-0.2.0rc2/README.md +30 -0
  3. icon4py_standalone_driver-0.2.0rc2/pyproject.toml +92 -0
  4. icon4py_standalone_driver-0.2.0rc2/setup.cfg +4 -0
  5. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/__init__.py +29 -0
  6. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/config.py +43 -0
  7. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/driver_constants.py +28 -0
  8. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/driver_states.py +183 -0
  9. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/driver_utils.py +600 -0
  10. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/main.py +104 -0
  11. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/py.typed +0 -0
  12. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/standalone_driver.py +700 -0
  13. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/testcases/__init__.py +7 -0
  14. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/testcases/initial_condition.py +371 -0
  15. icon4py_standalone_driver-0.2.0rc2/src/icon4py/model/standalone_driver/testcases/utils.py +212 -0
  16. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/PKG-INFO +64 -0
  17. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/SOURCES.txt +19 -0
  18. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/dependency_links.txt +1 -0
  19. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/entry_points.txt +2 -0
  20. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/requires.txt +8 -0
  21. icon4py_standalone_driver-0.2.0rc2/src/icon4py_standalone_driver.egg-info/top_level.txt +1 -0
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.4
2
+ Name: icon4py-standalone_driver
3
+ Version: 0.2.0rc2
4
+ Summary: ICON model driver.
5
+ Author-email: ETH Zurich <gridtools@cscs.ch>
6
+ License: BSD-3 License
7
+ Project-URL: Homepage, https://github.com/C2SM/icon4py
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: BSD License
11
+ Classifier: Operating System :: POSIX
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: Implementation :: CPython
21
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
22
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
23
+ Classifier: Topic :: Scientific/Engineering :: Physics
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ Requires-Dist: icon4py-atmosphere-dycore~=0.2.0rc2
27
+ Requires-Dist: icon4py-atmosphere-diffusion~=0.2.0rc2
28
+ Requires-Dist: icon4py-common~=0.2.0rc2
29
+ Requires-Dist: icon4py-testing~=0.2.0rc2
30
+ Requires-Dist: typer>=0.20.0
31
+ Requires-Dist: devtools>=0.12
32
+ Requires-Dist: gt4py==1.1.10
33
+ Requires-Dist: packaging>=20.0
34
+
35
+ # model driver for Python ICON4Py
36
+
37
+ `main.py` contains a simple python program to run the experimental ICON python port.
38
+
39
+ Currently, it does only diffusion and solve_nonhydro (dry atmosphere with no physics). The configuration for the granules and driver is hardcoded in [standalone_driver.py](src/icon4py/model/standalone_driver/standalone_driver.py). Time step, total integration time, number of substeps, and etc. can be configured there.
40
+
41
+ The code is meant to be changed and enlarged as we port new parts of the model.
42
+
43
+ It runs single node.
44
+
45
+ ## Installation
46
+
47
+ See the general instructions in the [README.md](../../README.md) in the base folder of the repository.
48
+
49
+ ## Usage
50
+
51
+ ```bash
52
+ # set environment variables (optional but convenient)
53
+ export ICON4PY_ROOT=<path to the icon4py clone>
54
+ export GRID_FOLDER=<path to the folder holding grids>
55
+
56
+ # command line arguments:
57
+ icon4py-standalone-driver \
58
+ $ICON4PY_ROOT/configuration_path/ \
59
+ --grid-file-path $GRID_FOLDER/icon_grid_0013_R02B04_R.nc \
60
+ --output-path $ICON4PY_ROOT/output_path \
61
+ --icon4py-backend gtfn_cpu
62
+ ```
63
+
64
+ #### Remarks
@@ -0,0 +1,30 @@
1
+ # model driver for Python ICON4Py
2
+
3
+ `main.py` contains a simple python program to run the experimental ICON python port.
4
+
5
+ Currently, it does only diffusion and solve_nonhydro (dry atmosphere with no physics). The configuration for the granules and driver is hardcoded in [standalone_driver.py](src/icon4py/model/standalone_driver/standalone_driver.py). Time step, total integration time, number of substeps, and etc. can be configured there.
6
+
7
+ The code is meant to be changed and enlarged as we port new parts of the model.
8
+
9
+ It runs single node.
10
+
11
+ ## Installation
12
+
13
+ See the general instructions in the [README.md](../../README.md) in the base folder of the repository.
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ # set environment variables (optional but convenient)
19
+ export ICON4PY_ROOT=<path to the icon4py clone>
20
+ export GRID_FOLDER=<path to the folder holding grids>
21
+
22
+ # command line arguments:
23
+ icon4py-standalone-driver \
24
+ $ICON4PY_ROOT/configuration_path/ \
25
+ --grid-file-path $GRID_FOLDER/icon_grid_0013_R02B04_R.nc \
26
+ --output-path $ICON4PY_ROOT/output_path \
27
+ --icon4py-backend gtfn_cpu
28
+ ```
29
+
30
+ #### Remarks
@@ -0,0 +1,92 @@
1
+ # -- Build system requirements (PEP 518) --
2
+
3
+ [build-system]
4
+ build-backend = "setuptools.build_meta"
5
+ requires = ["setuptools>=61.0", "wheel>=0.40.0"]
6
+
7
+ # -- Standard project description options (PEP 621) --
8
+ [project]
9
+ authors = [{email = "gridtools@cscs.ch", name = "ETH Zurich"}]
10
+ classifiers = [
11
+ 'Development Status :: 3 - Alpha',
12
+ 'Intended Audience :: Science/Research',
13
+ 'License :: OSI Approved :: BSD License',
14
+ 'Operating System :: POSIX',
15
+ 'Programming Language :: Python',
16
+ 'Programming Language :: Python :: 3',
17
+ 'Programming Language :: Python :: 3 :: Only',
18
+ 'Programming Language :: Python :: 3.10',
19
+ 'Programming Language :: Python :: 3.11',
20
+ 'Programming Language :: Python :: 3.12',
21
+ 'Programming Language :: Python :: 3.13',
22
+ 'Programming Language :: Python :: 3.14',
23
+ 'Programming Language :: Python :: Implementation :: CPython',
24
+ 'Topic :: Scientific/Engineering :: Atmospheric Science',
25
+ 'Topic :: Scientific/Engineering :: Mathematics',
26
+ 'Topic :: Scientific/Engineering :: Physics'
27
+ ]
28
+ dependencies = [
29
+ # workspace members
30
+ "icon4py-atmosphere-dycore~=0.2.0rc2",
31
+ "icon4py-atmosphere-diffusion~=0.2.0rc2",
32
+ "icon4py-common~=0.2.0rc2",
33
+ "icon4py-testing~=0.2.0rc2", # TODO(): remove this dependency when driver is fully standalone
34
+ # external dependencies
35
+ "typer>=0.20.0",
36
+ "devtools>=0.12",
37
+ "gt4py==1.1.10",
38
+ "packaging>=20.0"
39
+ ]
40
+ description = "ICON model driver."
41
+ license = {text = "BSD-3 License"}
42
+ name = "icon4py-standalone_driver"
43
+ readme = "README.md"
44
+ requires-python = ">=3.10"
45
+ # managed by bump-my-version:
46
+ version = "0.2.0rc2"
47
+
48
+ [project.scripts]
49
+ icon4py-standalone-driver = "icon4py.model.standalone_driver.main:click" # TODO (Yilu): change the name (remove the standalone) when it becomes the main driver
50
+
51
+ [project.urls]
52
+ Homepage = "https://github.com/C2SM/icon4py"
53
+
54
+ # -- bumpversion --
55
+ [tool.bumpversion]
56
+ allow_dirty = false
57
+ commit = false
58
+ current_version = "0.2.0rc2"
59
+ ignore_missing_version = false
60
+ message = 'Bump icon4py-standalone_driver version: {current_version} → {new_version}'
61
+ parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(?:(?P<pre_l>a|b|rc)(?P<pre_n>\\d+))?"
62
+ serialize = ["{major}.{minor}.{patch}{pre_l}{pre_n}", "{major}.{minor}.{patch}"]
63
+ tag = false
64
+
65
+ [[tool.bumpversion.files]]
66
+ filename = "pyproject.toml"
67
+ replace = '''
68
+ # managed by bump-my-version:
69
+ version = "{new_version}"
70
+ '''
71
+ search = '''
72
+ # managed by bump-my-version:
73
+ version = "{current_version}"
74
+ '''
75
+
76
+ [[tool.bumpversion.files]]
77
+ filename = "src/icon4py/model/standalone_driver/__init__.py"
78
+
79
+ # --ruff --
80
+ [tool.ruff]
81
+ extend = "../../pyproject.toml"
82
+
83
+ [tool.ruff.lint.isort]
84
+ known-first-party = ['icon4py']
85
+ known-third-party = ['gt4py']
86
+
87
+ # -- setuptools --
88
+ [tool.setuptools.package-data]
89
+ '*' = ['*.in', '*.md', '*.rst', '*.txt', 'LICENSE', 'py.typed']
90
+
91
+ [tool.setuptools.packages]
92
+ find = {namespaces = true, where = ['src']}
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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
+ from typing import Final
10
+
11
+ from packaging import version as pkg_version
12
+
13
+
14
+ __all__ = [
15
+ "__author__",
16
+ "__copyright__",
17
+ "__license__",
18
+ "__version__",
19
+ "__version_info__",
20
+ ]
21
+
22
+
23
+ __author__: Final = "ETH Zurich, MeteoSwiss and individual contributors"
24
+ __copyright__: Final = "Copyright (c) 2022-2024 ETH Zurich and MeteoSwiss"
25
+ __license__: Final = "BSD-3-Clause"
26
+
27
+
28
+ __version__: Final = "0.2.0rc2"
29
+ __version_info__: Final = pkg_version.parse(__version__)
@@ -0,0 +1,43 @@
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 dataclasses
10
+ import datetime
11
+ import pathlib
12
+
13
+ from gt4py.next.instrumentation import metrics as gtx_metrics
14
+
15
+ from icon4py.model.common import type_alias as ta
16
+
17
+
18
+ @dataclasses.dataclass
19
+ class ProfilingStats:
20
+ gt4py_metrics_level: int = gtx_metrics.ALL
21
+ gt4py_metrics_output_file: str = "gt4py_metrics.json"
22
+ skip_first_timestep: bool = True
23
+
24
+
25
+ @dataclasses.dataclass(frozen=True)
26
+ class DriverConfig:
27
+ """
28
+ Standalone driver configuration.
29
+
30
+ Default values should correspond to default values in ICON.
31
+ """
32
+
33
+ experiment_name: str
34
+ output_path: pathlib.Path
35
+ profiling_stats: ProfilingStats | None
36
+ dtime: datetime.timedelta = datetime.timedelta(seconds=600.0)
37
+ start_date: datetime.datetime = datetime.datetime(1, 1, 1, 0, 0, 0)
38
+ end_date: datetime.datetime = datetime.datetime(1, 1, 1, 1, 0, 0)
39
+ apply_extra_second_order_divdamp: bool = False
40
+ vertical_cfl_threshold: ta.wpfloat = dataclasses.field(default_factory=lambda: ta.wpfloat(0.85))
41
+ ndyn_substeps: int = 5
42
+ enable_statistics_output: bool = False
43
+ ntracer: int = 0
@@ -0,0 +1,28 @@
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 import type_alias as ta
10
+
11
+
12
+ #: Factor multiplied to the user-defined CFL number to determine the whether to enter watchmode
13
+ CFL_ENTER_WATCHMODE_FACTOR = ta.wpfloat("0.81")
14
+
15
+ #: Threshold factor multiplied to the user-defined CFL number to maintain the number of substeps
16
+ CFL_THRESHOLD_FACTOR = ta.wpfloat("0.9")
17
+
18
+ #: Factor multiplied to the user-defined CFL number to determine the whether to leave watchmode
19
+ CFL_LEAVE_WATCHMODE_FACTOR = ta.wpfloat("0.76")
20
+
21
+ #: Adjustment factor for second order divergence damping
22
+ ADJUST_FACTOR_FOR_SECOND_ORDER_DIVDAMP = ta.wpfloat("0.8")
23
+
24
+ #: Initial period for second order divergence damping
25
+ INITIAL_PERIOD_FOR_SECOND_ORDER_DIVDAMP = ta.wpfloat("1800.0")
26
+
27
+ #: Transition end period for second order divergence damping
28
+ TRANSITION_END_PERIOD_FOR_SECOND_ORDER_DIVDAMP = ta.wpfloat("7200.0")
@@ -0,0 +1,183 @@
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 dataclasses
10
+ import datetime
11
+ import enum
12
+ import functools
13
+ import logging
14
+ import statistics
15
+ from typing import NamedTuple
16
+
17
+ import devtools
18
+
19
+ import icon4py.model.common.utils as common_utils
20
+ from icon4py.model.atmosphere.advection import advection_states
21
+ from icon4py.model.atmosphere.diffusion import diffusion_states
22
+ from icon4py.model.atmosphere.dycore import dycore_states
23
+ from icon4py.model.common import type_alias as ta
24
+ from icon4py.model.common.grid import geometry as grid_geometry
25
+ from icon4py.model.common.interpolation import interpolation_factory
26
+ from icon4py.model.common.metrics import metrics_factory
27
+ from icon4py.model.common.states import (
28
+ diagnostic_state as diagnostics,
29
+ prognostic_state as prognostics,
30
+ )
31
+ from icon4py.model.standalone_driver import config as driver_config
32
+
33
+
34
+ log = logging.getLogger(__name__)
35
+
36
+
37
+ class StaticFieldFactories(NamedTuple):
38
+ """
39
+ Factories of static fields for the driver and components.
40
+
41
+ Attributes:
42
+ geometry_field_source: grid geometry field factory that stores geometrical properties of a grid
43
+ interpolation_field_source: interpolation field factory that stores pre-computed coefficients for interpolation employed in the model
44
+ metrics_field_source: metrics field factory that stores pre-computed coefficients for numerical operations employed in the model
45
+ """
46
+
47
+ geometry_field_source: grid_geometry.GridGeometry
48
+ interpolation_field_source: interpolation_factory.InterpolationFieldsFactory
49
+ metrics_field_source: metrics_factory.MetricsFieldsFactory
50
+
51
+
52
+ class DriverStates(NamedTuple):
53
+ """
54
+ Initialized states for the driver run.
55
+
56
+ Attributes:
57
+ prep_advection_prognostic: Fields collecting data for advection during the solve nonhydro timestep.
58
+ solve_nonhydro_diagnostic: Initial state for solve_nonhydro diagnostic variables.
59
+ diffusion_diagnostic: Initial state for diffusion diagnostic variables.
60
+ prognostics: Initial state for prognostic variables (double buffered).
61
+ diagnostic: Initial state for global diagnostic variables.
62
+ """
63
+
64
+ prep_advection_prognostic: dycore_states.PrepAdvection
65
+ solve_nonhydro_diagnostic: dycore_states.DiagnosticStateNonHydro
66
+ tracer_advection_diagnostic: advection_states.AdvectionDiagnosticState
67
+ prep_tracer_advection_prognostic: advection_states.AdvectionPrepAdvState
68
+ diffusion_diagnostic: diffusion_states.DiffusionDiagnosticState
69
+ prognostics: common_utils.TimeStepPair[prognostics.PrognosticState]
70
+ diagnostic: diagnostics.DiagnosticState
71
+
72
+
73
+ @dataclasses.dataclass
74
+ class ModelTimeVariables:
75
+ """
76
+ This class contains driver's run-time time or date variables.
77
+ It tracks the current simulation date, substepping information, and cfl watch mode.
78
+
79
+ """
80
+
81
+ config: dataclasses.InitVar[driver_config.DriverConfig]
82
+
83
+ n_time_steps: int = dataclasses.field(init=False)
84
+ dtime: datetime.timedelta = dataclasses.field(init=False)
85
+ ndyn_substeps_var: int = dataclasses.field(init=False)
86
+ max_ndyn_substeps: int = dataclasses.field(init=False)
87
+ elapsed_time_in_seconds: ta.wpfloat = dataclasses.field(init=False)
88
+ simulation_date: datetime.datetime = dataclasses.field(init=False)
89
+ is_first_step_in_simulation: bool = dataclasses.field(init=False)
90
+ cfl_watch_mode: bool = dataclasses.field(init=False)
91
+
92
+ def __post_init__(self, config: driver_config.DriverConfig) -> None:
93
+ self.n_time_steps = int((config.end_date - config.start_date) / config.dtime)
94
+ self.dtime = config.dtime
95
+ self.elapsed_time_in_seconds = ta.wpfloat("0.0")
96
+ self.simulation_date = config.start_date
97
+ self.ndyn_substeps_var = config.ndyn_substeps
98
+ self.max_ndyn_substeps = config.ndyn_substeps + 7
99
+ self.is_first_step_in_simulation = True
100
+ self.cfl_watch_mode = False
101
+
102
+ if self.n_time_steps < 0:
103
+ raise ValueError("end_date should be larger than start_date. Please check.")
104
+
105
+ @functools.cached_property
106
+ def dtime_in_seconds(self) -> ta.wpfloat:
107
+ return ta.wpfloat(self.dtime.total_seconds())
108
+
109
+ @property
110
+ def substep_timestep(self) -> ta.wpfloat:
111
+ return ta.wpfloat(self.dtime_in_seconds / self.ndyn_substeps_var)
112
+
113
+ def next_simulation_date(self) -> None:
114
+ self.simulation_date += self.dtime
115
+ self.elapsed_time_in_seconds += self.dtime_in_seconds
116
+
117
+ def update_ndyn_substeps(self, new_ndyn_substeps: int) -> None:
118
+ self.ndyn_substeps_var = new_ndyn_substeps
119
+
120
+ def update_cfl_watch_mode(self, mode: bool) -> None:
121
+ self.cfl_watch_mode = mode
122
+
123
+ def reset(self, config: driver_config.DriverConfig) -> None:
124
+ """
125
+ Re-initialize all time-integration-related runtime values from the given config.
126
+ """
127
+ self.__post_init__(config)
128
+
129
+
130
+ class DriverTimers(enum.Enum):
131
+ SOLVE_NH_FIRST_STEP = "solve_nh_first_step"
132
+ SOLVE_NH = "solve_nh"
133
+ DIFFUSION_FIRST_STEP = "diffusion_first_step"
134
+ DIFFUSION = "diffusion"
135
+
136
+
137
+ @dataclasses.dataclass
138
+ class TimerCollection:
139
+ timer_names: dataclasses.InitVar[list[str]]
140
+ timers: dict[str, devtools.Timer] = dataclasses.field(init=False)
141
+
142
+ def __post_init__(self, timer_names: str | list[str]) -> None:
143
+ self.timers = {}
144
+ self.add_timers(timer_names)
145
+
146
+ def add_timers(self, timer_names: str | list[str]) -> None:
147
+ for timer in timer_names:
148
+ assert timer not in self.timers, f"Timer '{timer}' is already defined."
149
+ self.timers[timer] = devtools.Timer(timer, dp=6, verbose=False)
150
+
151
+ def show_timer_report(
152
+ self,
153
+ ) -> None:
154
+ log.info("===== ICON4Py timer report =====")
155
+ table_titles = (
156
+ f"|{'timer name':^30}|"
157
+ f"{'no. of times called':^23}|"
158
+ f"{'mean time (s)':^23}|"
159
+ f"{'std. deviation (s)':^23}|"
160
+ f"{'min time (s)':^23}|"
161
+ f"{'max time (s)':^23}|"
162
+ )
163
+ log.info(table_titles)
164
+ log.info("-" * len(table_titles))
165
+ for timer_name, timer in self.timers.items():
166
+ times = []
167
+ for r in timer.results:
168
+ if not r.finish:
169
+ r.capture()
170
+ times.append(r.elapsed())
171
+ if len(times) > 0:
172
+ log.info(
173
+ f"|{timer_name:^30}|"
174
+ f"{len(times):^23}|"
175
+ f"{statistics.mean(times):^23.8f}|"
176
+ f"{statistics.stdev(times) if len(times) > 1 else 0:^23.8f}|"
177
+ f"{min(times):^23.8f}|"
178
+ f"{max(times):^23.8f}|"
179
+ )
180
+ else:
181
+ log.info(
182
+ f"|{timer_name:^30}|{'not started':^23}|{'':^23}|{'':^23}|{'':^23}|{'':^23}|"
183
+ )