Download model/legacy/orographies.py from OneScience-Group/NeuralGCM: direct link, hf CLI and curl.
- Browser
- Download file 5.01 kB
-
https://huggingface.co/OneScience-Group/NeuralGCM/resolve/main/model/legacy/orographies.py
- Command line
-
hf download hf://OneScience-Group/NeuralGCM/model/legacy/orographies.py
-
curl -L -o orographies.py https://huggingface.co/OneScience-Group/NeuralGCM/resolve/main/model/legacy/orographies.py
5.01 kB
| # Copyright 2024 Google LLC | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # https://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """Modules responsible for orography processing and initialization.""" | |
| from typing import Any, Callable, Mapping, Optional, Sequence | |
| from dinosaur import coordinate_systems | |
| from dinosaur import primitive_equations | |
| from dinosaur import scales | |
| from dinosaur import typing | |
| from dinosaur import xarray_utils | |
| import gin | |
| import haiku as hk | |
| import jax.numpy as jnp | |
| import numpy as np | |
| units = scales.units | |
| OrographyModule = Callable[..., typing.Array] | |
| FilterModule = Callable[..., typing.PyTreeFilterFn] | |
| class ClippedOrography(hk.Module): | |
| """Module that initializes orography by converting to modal and clipping.""" | |
| def __init__( | |
| self, | |
| coords: coordinate_systems.CoordinateSystem, | |
| dt: float, | |
| physics_specs: Any, | |
| aux_features: typing.AuxFeatures, | |
| wavenumbers_to_clip: int = 1, | |
| name: Optional[str] = None, | |
| ): | |
| del dt, physics_specs | |
| super().__init__(name=name) | |
| self.coords = coords | |
| self.wavenumbers_to_clip = wavenumbers_to_clip | |
| self.nodal_orography = aux_features.get( | |
| xarray_utils.OROGRAPHY, np.zeros(coords.horizontal.nodal_shape)) | |
| def __call__(self) -> typing.Array: | |
| """Returns orography converted to modal representation with clipping.""" | |
| return primitive_equations.truncated_modal_orography( | |
| self.nodal_orography, self.coords, self.wavenumbers_to_clip) | |
| class FilteredCustomOrography(hk.Module): | |
| """Module that initializes orography from external data.""" | |
| def __init__( | |
| self, | |
| coords: coordinate_systems.CoordinateSystem, | |
| dt: float, | |
| physics_specs: Any, | |
| aux_features: typing.AuxFeatures, | |
| orography_data_path: str, | |
| filter_modules: Sequence[FilterModule] = tuple(), | |
| renaming_dict: Optional[Mapping[str, str]] = None, | |
| name: Optional[str] = None, | |
| ): | |
| super().__init__(name=name) | |
| ds = xarray_utils.ds_from_path_or_aux(orography_data_path, aux_features) | |
| if renaming_dict is not None: | |
| ds = ds.rename(renaming_dict) | |
| nodal_orography = xarray_utils.nodal_orography_from_ds(ds) | |
| # TODO(dkochkov) Insist on having units specified in variable attrs. | |
| self.nodal_orography = physics_specs.nondimensionalize( | |
| nodal_orography * units.meter) # pyrefly: ignore[unsupported-operation] | |
| self.coords = coords | |
| # Note: here we explicitly use linear truncation to preserve full signal. | |
| # Smoothing is then achieved by interpolation to self.coords and filtering. | |
| self.input_coords = xarray_utils.coordinate_system_from_dataset( | |
| ds, truncation=xarray_utils.LINEAR, spmd_mesh=coords.spmd_mesh, | |
| spherical_harmonics_impl=self.coords.horizontal.spherical_harmonics_impl | |
| ) | |
| self.filter_fns = [ | |
| module(coords, dt, physics_specs, aux_features) | |
| for module in filter_modules] | |
| def __call__(self) -> typing.Array: | |
| """Returns orography converted to modal representation with filtering.""" | |
| return primitive_equations.filtered_modal_orography( | |
| self.nodal_orography, self.coords, self.input_coords, self.filter_fns) | |
| class LearnedOrography(hk.Module): | |
| """Module that uses learned parameters to correct orography.""" | |
| def __init__( | |
| self, | |
| coords: coordinate_systems.CoordinateSystem, | |
| dt: float, | |
| physics_specs: Any, | |
| aux_features: typing.AuxFeatures, | |
| base_orography_module: OrographyModule, | |
| correction_scale: float, | |
| name: Optional[str] = None, | |
| ): | |
| super().__init__(name=name) | |
| self.coords = coords | |
| self.base_orography_fn = base_orography_module( | |
| coords, dt, physics_specs, aux_features) | |
| self.scale = correction_scale | |
| # coords.horizontal.modal_shape can change based upon the required amount of | |
| # padding for a particular implementation of spherical harmonics, but the | |
| # mask should always have the same number of non-zero elements in the same | |
| # order. | |
| self.correction = hk.get_parameter( | |
| 'orography', (coords.horizontal.mask.sum(),), jnp.float32, | |
| init=hk.initializers.Constant(0.0)) | |
| def __call__(self) -> typing.Array: | |
| """Returns orography in modal representation.""" | |
| mask = self.coords.horizontal.mask | |
| correction_2d = jnp.zeros(self.coords.horizontal.modal_shape) | |
| correction_2d = correction_2d.at[mask].set(self.correction) | |
| return self.base_orography_fn() + correction_2d * self.scale # pytype: disable=not-callable # jax-ndarray | |