From 34eeea443562c133901ac20494b9c123f8630add Mon Sep 17 00:00:00 2001 From: MiKyung Lee <58964324+mlee03@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:28:00 -0500 Subject: [PATCH] Read in ak, bk coefficients (#36) * initial changes to read in ak bk * read ak/bk * add xfail * remove input dir * further changes to unit tests * finish up test * add history * commit uncommited files * fix test comment * add input to top * read in data * read in netcdf file in eta mod * remove txt file * test * modify test and fix generate.py * remove emacs backup file * driver tests pass * fix helper.py * fix fv3core tests * fix physics test * fix grid tests * nullcommconfig * cleanup input * remove driver input * remove top level input * fix circular import problems * modify eta_file readin for test_restart_serial * comment out 91 test * rm safety checks * revert diagnostics.py * restore driver.py * revert initialization.py * restore state.py * restore analytic_init.py * restore init_utils.py and analytic_init.py * restore c_sw.py * d2a2c_vect.py * restore fv3core/stensils * restore translate_fvdynamics * restore physics/stencils * restore stencils * remove circular dependency * use pytest parametrize * cleanup generation.py * fstrinngs * add eta_file to MetricTerm init * remove eta_file argument in new_from_metric_terms and geos_wrapper * use pytest parametrize for the xfail tests * use pytest parametrize for the xfail tests * fix geos_wrapper and grid * fix tests * fstring * add test comments * fix util/HISTORY.md * fix comments * remove __init__.py from tests/main/grid * add jupyter notebooks to generate eta files * generate ak,bk,ptop on metricterm init * fix tests * exploit np.all in eta mod * remove tests/main/grid/input * update ci * test * remove input * edit ci yaml * remove push --------- Co-authored-by: mlee03 --- .github/workflows/main_unit_tests.yml | 4 + CONTRIBUTORS.md | 1 + driver/examples/configs/baroclinic_c12.yaml | 5 + .../configs/baroclinic_c12_write_restart.yaml | 5 + driver/pace/driver/grid.py | 2 + .../notebooks/generate_eta_file_netcdf.ipynb | 148 +++ .../notebooks/generate_eta_file_xarray.ipynb | 140 +++ fv3core/pace/fv3core/wrappers/geos_wrapper.py | 4 +- tests/main/driver/test_restart_fortran.py | 4 +- tests/main/driver/test_restart_serial.py | 5 +- tests/main/fv3core/test_cartesian_grid.py | 3 +- tests/main/fv3core/test_dycore_call.py | 2 + tests/main/fv3core/test_init_from_geos.py | 3 + tests/main/grid/test_eta.py | 110 +++ tests/main/physics/test_integration.py | 1 + tests/main/test_grid_init.py | 5 +- util/HISTORY.md | 2 + util/pace/util/grid/eta.py | 841 +----------------- util/pace/util/grid/generation.py | 49 +- 19 files changed, 484 insertions(+), 850 deletions(-) create mode 100644 examples/notebooks/generate_eta_file_netcdf.ipynb create mode 100644 examples/notebooks/generate_eta_file_xarray.ipynb create mode 100755 tests/main/grid/test_eta.py diff --git a/.github/workflows/main_unit_tests.yml b/.github/workflows/main_unit_tests.yml index 5800baa65..b8a1289b9 100644 --- a/.github/workflows/main_unit_tests.yml +++ b/.github/workflows/main_unit_tests.yml @@ -22,6 +22,10 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements_dev.txt + - name: Clone datafiles + run: | + mkdir -p tests/main/input && cd tests/main/input + git clone -b store_files https://github.com/mlee03/pace.git tmp && mv tmp/*.nc . && rm -rf tmp - name: Run all main tests run: | pytest -x tests/main diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 0ca00ff5b..7030919a5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,6 +11,7 @@ List format (alphabetical order): Surname, Name. Employer/Affiliation * Fuhrer, Oliver. Allen Institute for AI. * George, Rhea. Allen Institute for AI. * Harris, Lucas. GFDL. +* Lee, Mi Kyung. GFDL. * Kung, Chris. NASA. * McGibbon, Jeremy. Allen Institute for AI. * Niedermayr, Yannick. ETH. diff --git a/driver/examples/configs/baroclinic_c12.yaml b/driver/examples/configs/baroclinic_c12.yaml index 1785f9abf..2b0a2e3f6 100644 --- a/driver/examples/configs/baroclinic_c12.yaml +++ b/driver/examples/configs/baroclinic_c12.yaml @@ -94,3 +94,8 @@ physics_config: hydrostatic: false nwat: 6 do_qa: true + +grid_config: + type: generated + config: + eta_file: 'tests/main/input/eta79.nc' diff --git a/driver/examples/configs/baroclinic_c12_write_restart.yaml b/driver/examples/configs/baroclinic_c12_write_restart.yaml index 55e5b2b10..7bca30327 100644 --- a/driver/examples/configs/baroclinic_c12_write_restart.yaml +++ b/driver/examples/configs/baroclinic_c12_write_restart.yaml @@ -92,3 +92,8 @@ physics_config: hydrostatic: false nwat: 6 do_qa: true + +grid_config: + type: generated + config: + eta_file: "tests/main/input/eta79.nc" diff --git a/driver/pace/driver/grid.py b/driver/pace/driver/grid.py index 1cf59d073..d4e07d004 100644 --- a/driver/pace/driver/grid.py +++ b/driver/pace/driver/grid.py @@ -99,6 +99,7 @@ class GeneratedGridConfig(GridInitializer): dx_const: Optional[float] = 1000.0 dy_const: Optional[float] = 1000.0 deglat: Optional[float] = 15.0 + eta_file: str = "None" def get_grid( self, @@ -112,6 +113,7 @@ def get_grid( dx_const=self.dx_const, dy_const=self.dy_const, deglat=self.deglat, + eta_file=self.eta_file, ) if self.stretch_factor != 1: # do horizontal grid transformation _transform_horizontal_grid( diff --git a/examples/notebooks/generate_eta_file_netcdf.ipynb b/examples/notebooks/generate_eta_file_netcdf.ipynb new file mode 100644 index 000000000..bf9623c79 --- /dev/null +++ b/examples/notebooks/generate_eta_file_netcdf.ipynb @@ -0,0 +1,148 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "2c056479", + "metadata": { + "lines_to_next_cell": 0 + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c96fbff", + "metadata": {}, + "outputs": [], + "source": [ + "import netCDF4 as nc\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6827b1b5", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "This notebook uses the python netCDF4 module\n", + "to create an eta_file containg\n", + "ak and bk coefficients for km=79\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45d4a704", + "metadata": {}, + "outputs": [], + "source": [ + "#create a Dataset instance\n", + "coefficients = nc.Dataset(\"eta79.nc\", \"w\", format=\"NETCDF4\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b964a014", + "metadata": {}, + "outputs": [], + "source": [ + "#Set dimensionsion\n", + "km = coefficients.createDimension(\"km\", 80)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d51c395f", + "metadata": {}, + "outputs": [], + "source": [ + "#Create ak and bk variables\n", + "ak = coefficients.createVariable(\"ak\", np.float64, (\"km\"))\n", + "bk = coefficients.createVariable(\"bk\", np.float64, (\"km\"))\n", + "ak.units=\"\"\n", + "bk.units=\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6723352e", + "metadata": {}, + "outputs": [], + "source": [ + "#Assign and write out values of ak\n", + "ak[:] = np.array(\n", + " [ 3.000000e+02, 6.467159e+02, 1.045222e+03, 1.469188e+03, 1.897829e+03,\n", + " 2.325385e+03, 2.754396e+03, 3.191294e+03, 3.648332e+03, 4.135675e+03,\n", + " 4.668282e+03, 5.247940e+03, 5.876271e+03, 6.554716e+03, 7.284521e+03,\n", + " 8.066738e+03, 8.902188e+03, 9.791482e+03, 1.073499e+04, 1.162625e+04,\n", + " 1.237212e+04, 1.299041e+04, 1.349629e+04, 1.390277e+04, 1.422098e+04,\n", + " 1.446058e+04, 1.462993e+04, 1.473633e+04, 1.478617e+04, 1.478511e+04,\n", + " 1.473812e+04, 1.464966e+04, 1.452370e+04, 1.436382e+04, 1.417324e+04,\n", + " 1.395491e+04, 1.371148e+04, 1.344540e+04, 1.315890e+04, 1.285407e+04,\n", + " 1.253280e+04, 1.219685e+04, 1.184788e+04, 1.148739e+04, 1.111682e+04,\n", + " 1.073748e+04, 1.035062e+04, 9.957395e+03, 9.558875e+03, 9.156069e+03,\n", + " 8.749922e+03, 8.341315e+03, 7.931065e+03, 7.519942e+03, 7.108648e+03,\n", + " 6.698281e+03, 6.290007e+03, 5.884984e+03, 5.484372e+03, 5.089319e+03,\n", + " 4.700960e+03, 4.320421e+03, 3.948807e+03, 3.587201e+03, 3.236666e+03,\n", + " 2.898237e+03, 2.572912e+03, 2.261667e+03, 1.965424e+03, 1.685079e+03,\n", + " 1.421479e+03, 1.175419e+03, 9.476516e+02, 7.388688e+02, 5.497130e+02,\n", + " 3.807626e+02, 2.325417e+02, 1.054810e+02, -8.381903e-04, 0.000000e+00] )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "195c9ef5", + "metadata": {}, + "outputs": [], + "source": [ + "#Assign and write out values of bk \n", + "bk[:] = np.array(\n", + " [ 0., 0., 0., 0., 0., 0.,\n", + " 0., 0., 0., 0., 0., 0.,\n", + " 0., 0., 0., 0., 0., 0.,\n", + " 0., 0.00106595, 0.00412866, 0.00900663, 0.01554263, 0.02359921,\n", + " 0.03305481, 0.0438012, 0.05574095, 0.06878554, 0.08285347, 0.09786981,\n", + " 0.1137643, 0.130471, 0.1479275, 0.1660746, 0.1848558, 0.2042166,\n", + " 0.2241053, 0.2444716, 0.2652672, 0.286445, 0.3079604, 0.3297701,\n", + " 0.351832, 0.3741062, 0.3965532, 0.4191364, 0.4418194, 0.4645682,\n", + " 0.48735, 0.5101338, 0.5328897, 0.5555894, 0.5782067, 0.6007158,\n", + " 0.6230936, 0.6452944, 0.6672683, 0.6889648, 0.7103333, 0.7313231,\n", + " 0.7518838, 0.7719651, 0.7915173, 0.8104913, 0.828839, 0.846513,\n", + " 0.8634676, 0.8796583, 0.8950421, 0.9095779, 0.9232264, 0.9359506,\n", + " 0.9477157, 0.9584892, 0.9682413, 0.9769447, 0.9845753, 0.9911126,\n", + " 0.9965372, 1. ] )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0f3bd9d", + "metadata": {}, + "outputs": [], + "source": [ + "#Close netcdf file\n", + "coefficients.close()" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "executable": "/usr/bin/env python3", + "main_language": "python", + "notebook_metadata_filter": "-all" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/notebooks/generate_eta_file_xarray.ipynb b/examples/notebooks/generate_eta_file_xarray.ipynb new file mode 100644 index 000000000..a47b09e62 --- /dev/null +++ b/examples/notebooks/generate_eta_file_xarray.ipynb @@ -0,0 +1,140 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "6dc5fe4c", + "metadata": { + "lines_to_next_cell": 0 + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81be9a15", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import xarray as xr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c74c6c07", + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "This notebook uses the python xarray module\n", + "to create an eta_file containg\n", + "ak and bk coefficients for km=79\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f72c5d5b", + "metadata": {}, + "outputs": [], + "source": [ + "#Assign ak data\n", + "ak=np.array(\n", + " [ 3.000000e+02, 6.467159e+02, 1.045222e+03, 1.469188e+03, 1.897829e+03,\n", + " 2.325385e+03, 2.754396e+03, 3.191294e+03, 3.648332e+03, 4.135675e+03,\n", + " 4.668282e+03, 5.247940e+03, 5.876271e+03, 6.554716e+03, 7.284521e+03,\n", + " 8.066738e+03, 8.902188e+03, 9.791482e+03, 1.073499e+04, 1.162625e+04,\n", + " 1.237212e+04, 1.299041e+04, 1.349629e+04, 1.390277e+04, 1.422098e+04,\n", + " 1.446058e+04, 1.462993e+04, 1.473633e+04, 1.478617e+04, 1.478511e+04,\n", + " 1.473812e+04, 1.464966e+04, 1.452370e+04, 1.436382e+04, 1.417324e+04,\n", + " 1.395491e+04, 1.371148e+04, 1.344540e+04, 1.315890e+04, 1.285407e+04,\n", + " 1.253280e+04, 1.219685e+04, 1.184788e+04, 1.148739e+04, 1.111682e+04,\n", + " 1.073748e+04, 1.035062e+04, 9.957395e+03, 9.558875e+03, 9.156069e+03,\n", + " 8.749922e+03, 8.341315e+03, 7.931065e+03, 7.519942e+03, 7.108648e+03,\n", + " 6.698281e+03, 6.290007e+03, 5.884984e+03, 5.484372e+03, 5.089319e+03,\n", + " 4.700960e+03, 4.320421e+03, 3.948807e+03, 3.587201e+03, 3.236666e+03,\n", + " 2.898237e+03, 2.572912e+03, 2.261667e+03, 1.965424e+03, 1.685079e+03,\n", + " 1.421479e+03, 1.175419e+03, 9.476516e+02, 7.388688e+02, 5.497130e+02,\n", + " 3.807626e+02, 2.325417e+02, 1.054810e+02, -8.381903e-04, 0.000000e+00] )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5b85c7e", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [ + "#Assign bk data\n", + "bk=np.array(\n", + " [ 0., 0., 0., 0., 0., 0.,\n", + " 0., 0., 0., 0., 0., 0.,\n", + " 0., 0., 0., 0., 0., 0.,\n", + " 0., 0.00106595, 0.00412866, 0.00900663, 0.01554263, 0.02359921,\n", + " 0.03305481, 0.0438012, 0.05574095, 0.06878554, 0.08285347, 0.09786981,\n", + " 0.1137643, 0.130471, 0.1479275, 0.1660746, 0.1848558, 0.2042166,\n", + " 0.2241053, 0.2444716, 0.2652672, 0.286445, 0.3079604, 0.3297701,\n", + " 0.351832, 0.3741062, 0.3965532, 0.4191364, 0.4418194, 0.4645682,\n", + " 0.48735, 0.5101338, 0.5328897, 0.5555894, 0.5782067, 0.6007158,\n", + " 0.6230936, 0.6452944, 0.6672683, 0.6889648, 0.7103333, 0.7313231,\n", + " 0.7518838, 0.7719651, 0.7915173, 0.8104913, 0.828839, 0.846513,\n", + " 0.8634676, 0.8796583, 0.8950421, 0.9095779, 0.9232264, 0.9359506,\n", + " 0.9477157, 0.9584892, 0.9682413, 0.9769447, 0.9845753, 0.9911126,\n", + " 0.9965372, 1. ] )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5450f7f", + "metadata": {}, + "outputs": [], + "source": [ + "#Create a Dataset instance\n", + "coefficients = xr.Dataset(\n", + " { \"ak\": ([\"km1\"], ak),\n", + " \"bk\": ([\"km1\"], bk) \n", + " })" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a0e5487", + "metadata": {}, + "outputs": [], + "source": [ + "#Set attributes for each variable\n", + "coefficients[\"ak\"].attrs[\"units\"]=\"\"\n", + "coefficients[\"bk\"].attrs[\"units\"]=\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "612b0134", + "metadata": {}, + "outputs": [], + "source": [ + "#Write netcdf file\n", + "coefficients.to_netcdf(\"eta79.nc\")" + ] + } + ], + "metadata": { + "jupytext": { + "cell_metadata_filter": "-all", + "executable": "/usr/bin/env python3", + "main_language": "python", + "notebook_metadata_filter": "-all" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/fv3core/pace/fv3core/wrappers/geos_wrapper.py b/fv3core/pace/fv3core/wrappers/geos_wrapper.py index e1d1defe3..9f8347f30 100644 --- a/fv3core/pace/fv3core/wrappers/geos_wrapper.py +++ b/fv3core/pace/fv3core/wrappers/geos_wrapper.py @@ -124,7 +124,9 @@ def __init__( # set up the metric terms and grid data metric_terms = pace.util.grid.MetricTerms( - quantity_factory=quantity_factory, communicator=self.communicator + quantity_factory=quantity_factory, + communicator=self.communicator, + eta_file=namelist["grid_config"]["config"]["eta_file"], ) grid_data = pace.util.grid.GridData.new_from_metric_terms(metric_terms) diff --git a/tests/main/driver/test_restart_fortran.py b/tests/main/driver/test_restart_fortran.py index 5dc70d0a6..d1accdaa2 100644 --- a/tests/main/driver/test_restart_fortran.py +++ b/tests/main/driver/test_restart_fortran.py @@ -47,7 +47,9 @@ def test_state_from_fortran_restart(): damping_coefficients, driver_grid_data, grid_data, - ) = pace.driver.GeneratedGridConfig(restart_path=restart_dir).get_grid( + ) = pace.driver.GeneratedGridConfig( + restart_path=restart_dir, eta_file=restart_dir + "/fv_core.res.nc" + ).get_grid( quantity_factory, null_communicator ) diff --git a/tests/main/driver/test_restart_serial.py b/tests/main/driver/test_restart_serial.py index 3e62b8639..51ce615a9 100644 --- a/tests/main/driver/test_restart_serial.py +++ b/tests/main/driver/test_restart_serial.py @@ -66,11 +66,14 @@ def test_restart_save_to_disk(): sizer=sizer, backend=backend ) + eta_file = driver_config.grid_config.config.eta_file ( damping_coefficients, driver_grid_data, grid_data, - ) = pace.driver.GeneratedGridConfig().get_grid(quantity_factory, communicator) + ) = pace.driver.GeneratedGridConfig(eta_file=eta_file).get_grid( + quantity_factory, communicator + ) init = AnalyticInit() driver_state = init.get_driver_state( quantity_factory=quantity_factory, diff --git a/tests/main/fv3core/test_cartesian_grid.py b/tests/main/fv3core/test_cartesian_grid.py index db2ebe2d4..986f4eaf8 100644 --- a/tests/main/fv3core/test_cartesian_grid.py +++ b/tests/main/fv3core/test_cartesian_grid.py @@ -8,7 +8,7 @@ @pytest.mark.parametrize("npx", [8]) @pytest.mark.parametrize("npy", [8]) -@pytest.mark.parametrize("npz", [1]) +@pytest.mark.parametrize("npz", [79]) @pytest.mark.parametrize("dx_const", [1e2, 1e3]) @pytest.mark.parametrize("dy_const", [2e2, 3e3]) @pytest.mark.parametrize("deglat", [0.0, 15.0]) @@ -35,6 +35,7 @@ def test_cartesian_grid_generation( dx_const=dx_const, dy_const=dy_const, deglat=deglat, + eta_file="tests/main/input/eta79.nc", ) assert np.all(grid_generator.lat_agrid.data == deglat * PI / 180.0) assert np.all(grid_generator.lon_agrid.data == 0.0) diff --git a/tests/main/fv3core/test_dycore_call.py b/tests/main/fv3core/test_dycore_call.py index 02ffe1e42..4fd7a4719 100644 --- a/tests/main/fv3core/test_dycore_call.py +++ b/tests/main/fv3core/test_dycore_call.py @@ -97,9 +97,11 @@ def setup_dycore() -> ( quantity_factory = pace.util.QuantityFactory.from_backend( sizer=sizer, backend=backend ) + eta_file = "tests/main/input/eta79.nc" metric_terms = MetricTerms( quantity_factory=quantity_factory, communicator=communicator, + eta_file=eta_file, ) grid_data = GridData.new_from_metric_terms(metric_terms) diff --git a/tests/main/fv3core/test_init_from_geos.py b/tests/main/fv3core/test_init_from_geos.py index 16efe9e9d..7e03caf08 100644 --- a/tests/main/fv3core/test_init_from_geos.py +++ b/tests/main/fv3core/test_init_from_geos.py @@ -74,6 +74,9 @@ def test_geos_wrapper(): "fv_sg_adj": 0, "n_sponge": 48, }, + "grid_config": { + "config": {"eta_file": "tests/main/input/eta91.nc"}, + }, } namelist = f90nml.namelist.Namelist(namelist_dict) diff --git a/tests/main/grid/test_eta.py b/tests/main/grid/test_eta.py new file mode 100755 index 000000000..b34e52aa9 --- /dev/null +++ b/tests/main/grid/test_eta.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import os + +import numpy as np +import pytest +import xarray as xr +import yaml + +import pace.driver + + +""" +This test checks to ensure that ak and bk +values are read-in and stored properly. +In addition, this test checks to ensure that +the function set_hybrid_pressure_coefficients +fail as expected if the computed eta values +vary non-mononitically and if the eta_file +is not provided. +""" + + +def set_answers(eta_file): + + """ + Read in the expected values of ak and bk + arrays from the input eta NetCDF files. + """ + + data = xr.open_dataset(eta_file) + return data["ak"].values, data["bk"].values + + +@pytest.mark.parametrize("km", [79, 91]) +def test_set_hybrid_pressure_coefficients_correct(km): + + """This test checks to see that the ak and bk arrays + are read-in correctly and are stored as + expected. Both values of km=79 and km=91 are + tested and both tests are expected to pass + with the stored ak and bk values agreeing with the + values read-in directly from the NetCDF file. + """ + + dirname = os.path.dirname(os.path.abspath(__file__)) + config_file = os.path.join( + dirname, "../../../driver/examples/configs/baroclinic_c12.yaml" + ) + + with open(config_file, "r") as f: + yaml_config = yaml.safe_load(f) + + yaml_config["nz"] = km + yaml_config["grid_config"]["config"]["eta_file"] = f"tests/main/input/eta{km}.nc" + + driver_config = pace.driver.DriverConfig.from_dict(yaml_config) + driver_config.comm_config = pace.driver.NullCommConfig(rank=0, total_ranks=6) + driver = pace.driver.Driver(config=driver_config) + + p_results = driver.state.grid_data.p.data + ak_results = driver.state.grid_data.ak.data + bk_results = driver.state.grid_data.bk.data + ak_answers, bk_answers = set_answers(f"tests/main/input/eta{km}.nc") + + if ak_answers.size != ak_results.size: + raise ValueError("Unexpected size of bk") + if bk_answers.size != bk_results.size: + raise ValueError("Unexpected size of ak") + + if not np.array_equal(ak_answers, ak_results): + raise ValueError("Unexpected value of ak") + if not np.array_equal(bk_answers, bk_results): + raise ValueError("Unexpected value of bk") + + driver.safety_checker.clear_all_checks() + + +@pytest.mark.parametrize( + "cfile", + [ + "file_is_not_here", + "tests/main/grid/input/eta_not_mono.nc", + ], +) +@pytest.mark.xfail +def test_set_hybrid_pressure_coefficients_fail(cfile): + + """This test checks to see that the program + fails when (1) the eta_file is not specified in the yaml + configuration file; and (2), the computed eta values + increase non-monotonically. For the latter test, the eta_file + is specified in test_config_not_mono.yaml file and + the ak and bk values in the eta_file have been changed nonsensically + to result in erronenous eta values. + """ + + dirname = os.path.dirname(os.path.abspath(__file__)) + config_file = os.path.join( + dirname, "../../../driver/examples/configs/baroclinic_c12.yaml" + ) + + with open(config_file, "r") as f: + yaml_config = yaml.safe_load(f) + + yaml_config["grid_config"]["config"]["eta_file"] = cfile + + driver_config = pace.driver.DriverConfig.from_dict(yaml_config) + driver_config.comm_config = pace.driver.NullCommConfig(rank=0, total_ranks=6) + driver = pace.driver.Driver(config=driver_config) diff --git a/tests/main/physics/test_integration.py b/tests/main/physics/test_integration.py index a55d9f988..8d86f80be 100644 --- a/tests/main/physics/test_integration.py +++ b/tests/main/physics/test_integration.py @@ -64,6 +64,7 @@ def setup_physics(): metric_terms = pace.util.grid.MetricTerms( quantity_factory=quantity_factory, communicator=communicator, + eta_file="tests/main/input/eta79.nc", ) grid_data = pace.util.grid.GridData.new_from_metric_terms(metric_terms) physics = pace.physics.Physics( diff --git a/tests/main/test_grid_init.py b/tests/main/test_grid_init.py index 4c0e5e2b1..55e00e81d 100644 --- a/tests/main/test_grid_init.py +++ b/tests/main/test_grid_init.py @@ -32,18 +32,21 @@ def test_grid_init_not_decomposition_dependent(rank: int): mpi_54rank test suite. It tests only variables that are not dependent on halo updates for their values in the compute domain. """ - nx_tile, ny_tile, nz = 48, 48, 5 + nx_tile, ny_tile, nz = 48, 48, 79 + eta_file = "tests/main/input/eta79.nc" metric_terms_1by1 = MetricTerms( quantity_factory=get_quantity_factory( layout=(1, 1), nx_tile=nx_tile, ny_tile=ny_tile, nz=nz ), communicator=get_cube_comm(rank=0, layout=(1, 1)), + eta_file=eta_file, ) metric_terms_3by3 = MetricTerms( quantity_factory=get_quantity_factory( layout=(3, 3), nx_tile=nx_tile, ny_tile=ny_tile, nz=nz ), communicator=get_cube_comm(rank=rank, layout=(3, 3)), + eta_file=eta_file, ) partitioner = pace.util.TilePartitioner(layout=(3, 3)) assert allclose(metric_terms_1by1.grid, metric_terms_3by3.grid, partitioner, rank) diff --git a/util/HISTORY.md b/util/HISTORY.md index 62ada765d..972d71670 100644 --- a/util/HISTORY.md +++ b/util/HISTORY.md @@ -13,6 +13,8 @@ latest - Added `dx_const`, `dy_const`, and `deglat` to grid generation code for doubly-periodic grids - Added f32 support to halo exchange data transformation - Use one single logger, from logging.py +- Removed hard-coded values of `ak` and `bk` arrays and added in the feature to read in `ak` and `bk` values + from a NetCDF file to compute the `eta` and `eta_v` values. v0.10.0 ------- diff --git a/util/pace/util/grid/eta.py b/util/pace/util/grid/eta.py index dc37aaa25..52fe3552c 100644 --- a/util/pace/util/grid/eta.py +++ b/util/pace/util/grid/eta.py @@ -1,6 +1,8 @@ +import os from dataclasses import dataclass import numpy as np +import xarray as xr @dataclass @@ -21,7 +23,9 @@ class HybridPressureCoefficients: bk: np.ndarray -def set_hybrid_pressure_coefficients(km: int) -> HybridPressureCoefficients: +def set_hybrid_pressure_coefficients( + km: int, eta_file: str +) -> HybridPressureCoefficients: """ Sets the coefficients describing the hybrid pressure coordinates. @@ -35,820 +39,30 @@ def set_hybrid_pressure_coefficients(km: int) -> HybridPressureCoefficients: Returns: a HybridPressureCoefficients dataclass """ - if km == 79: - ak = np.array( - [ - 300, - 646.7159, - 1045.222, - 1469.188, - 1897.829, - 2325.385, - 2754.396, - 3191.294, - 3648.332, - 4135.675, - 4668.282, - 5247.94, - 5876.271, - 6554.716, - 7284.521, - 8066.738, - 8902.188, - 9791.482, - 10734.99, - 11626.25, - 12372.12, - 12990.41, - 13496.29, - 13902.77, - 14220.98, - 14460.58, - 14629.93, - 14736.33, - 14786.17, - 14785.11, - 14738.12, - 14649.66, - 14523.7, - 14363.82, - 14173.24, - 13954.91, - 13711.48, - 13445.4, - 13158.9, - 12854.07, - 12532.8, - 12196.85, - 11847.88, - 11487.39, - 11116.82, - 10737.48, - 10350.62, - 9957.395, - 9558.875, - 9156.069, - 8749.922, - 8341.315, - 7931.065, - 7519.942, - 7108.648, - 6698.281, - 6290.007, - 5884.984, - 5484.372, - 5089.319, - 4700.96, - 4320.421, - 3948.807, - 3587.201, - 3236.666, - 2898.237, - 2572.912, - 2261.667, - 1965.424, - 1685.079, - 1421.479, - 1175.419, - 947.6516, - 738.8688, - 549.713, - 380.7626, - 232.5417, - 105.481, - -0.0008381903, - 0, - ] - ) - bk = np.array( - [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0.001065947, - 0.004128662, - 0.009006631, - 0.01554263, - 0.02359921, - 0.03305481, - 0.0438012, - 0.05574095, - 0.06878554, - 0.08285347, - 0.09786981, - 0.1137643, - 0.130471, - 0.1479275, - 0.1660746, - 0.1848558, - 0.2042166, - 0.2241053, - 0.2444716, - 0.2652672, - 0.286445, - 0.3079604, - 0.3297701, - 0.351832, - 0.3741062, - 0.3965532, - 0.4191364, - 0.4418194, - 0.4645682, - 0.48735, - 0.5101338, - 0.5328897, - 0.5555894, - 0.5782067, - 0.6007158, - 0.6230936, - 0.6452944, - 0.6672683, - 0.6889648, - 0.7103333, - 0.7313231, - 0.7518838, - 0.7719651, - 0.7915173, - 0.8104913, - 0.828839, - 0.846513, - 0.8634676, - 0.8796583, - 0.8950421, - 0.9095779, - 0.9232264, - 0.9359506, - 0.9477157, - 0.9584892, - 0.9682413, - 0.9769447, - 0.9845753, - 0.9911126, - 0.9965372, - 1, - ] - ) - elif km == 91: - ak = np.array( - [ - 1.00000000, - 1.75000000, - 2.75000000, - 4.09999990, - 5.98951054, - 8.62932968, - 12.2572632, - 17.1510906, - 23.6545467, - 32.1627693, - 43.1310921, - 57.1100426, - 74.6595764, - 96.4470978, - 123.169769, - 155.601318, - 194.594009, - 241.047531, - 295.873840, - 360.046967, - 434.604828, - 520.628723, - 619.154846, - 731.296021, - 858.240906, - 1001.06561, - 1160.92859, - 1339.03992, - 1536.50012, - 1754.48938, - 1994.17834, - 2256.67407, - 2543.17139, - 2854.76392, - 3192.58569, - 3557.75366, - 3951.35107, - 4374.28662, - 4827.11084, - 5310.22168, - 5823.87793, - 6369.04248, - 6948.75244, - 7566.91992, - 8226.34277, - 8931.20996, - 9684.46191, - 10482.2725, - 11318.2793, - 12184.0771, - 13065.5674, - 13953.2207, - 14830.7285, - 15687.2617, - 16508.0645, - 17281.0996, - 17994.2988, - 18636.3223, - 19196.1797, - 19664.0723, - 20030.1914, - 20285.3691, - 20421.5254, - 20430.0684, - 20302.8730, - 20032.3711, - 19611.0664, - 19031.3848, - 18286.6426, - 17377.7930, - 16322.4639, - 15144.4033, - 13872.5674, - 12540.4785, - 11183.4170, - 9835.32715, - 8526.30664, - 7282.24512, - 6123.26074, - 5063.50684, - 4111.24902, - 3270.00122, - 2539.22729, - 1915.30762, - 1392.44995, - 963.134766, - 620.599365, - 357.989502, - 169.421387, - 51.0314941, - 2.48413086, - 0.00000000, - ] - ) + if eta_file == "None": + raise ValueError("eta file not specified") + if not os.path.isfile(eta_file): + raise ValueError("file " + eta_file + " does not exist") - bk = np.array( - [ - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 3.50123992e-06, - 2.81484008e-05, - 9.38666999e-05, - 2.28561999e-04, - 5.12343016e-04, - 1.04712998e-03, - 1.95625005e-03, - 3.42317997e-03, - 5.58632007e-03, - 8.65428988e-03, - 1.27844000e-02, - 1.81719996e-02, - 2.49934997e-02, - 3.34198996e-02, - 4.36249003e-02, - 5.57769015e-02, - 7.00351968e-02, - 8.65636021e-02, - 0.105520003, - 0.127051994, - 0.151319996, - 0.178477004, - 0.208675995, - 0.242069006, - 0.278813988, - 0.319043010, - 0.362558991, - 0.408596009, - 0.456384987, - 0.505111992, - 0.553902984, - 0.601903021, - 0.648333013, - 0.692534983, - 0.733981013, - 0.772292018, - 0.807236016, - 0.838724971, - 0.866774976, - 0.891497016, - 0.913065016, - 0.931702971, - 0.947658002, - 0.961175978, - 0.972495019, - 0.981844008, - 0.989410996, - 0.995342016, - 1.00000000, - ] - ) + # read file into ak, bk arrays + data = xr.open_dataset(eta_file) + ak = data["ak"].values + bk = data["bk"].values - elif km == 72: - ak = np.array( - [ - 1.00000000, - 2.00000024, - 3.27000046, - 4.75850105, - 6.60000134, - 8.93450165, - 11.9703016, - 15.9495029, - 21.1349030, - 27.8526058, - 36.5041084, - 47.5806084, - 61.6779099, - 79.5134125, - 101.944023, - 130.051025, - 165.079025, - 208.497040, - 262.021057, - 327.643066, - 407.657104, - 504.680115, - 621.680115, - 761.984192, - 929.294189, - 1127.69019, - 1364.34021, - 1645.71033, - 1979.16040, - 2373.04053, - 2836.78052, - 3381.00073, - 4017.54102, - 4764.39111, - 5638.79102, - 6660.34131, - 7851.23145, - 9236.57227, - 10866.3018, - 12783.7031, - 15039.3027, - 17693.0039, - 20119.2012, - 21686.5020, - 22436.3008, - 22389.8008, - 21877.5977, - 21214.9980, - 20325.8984, - 19309.6953, - 18161.8965, - 16960.8965, - 15625.9961, - 14290.9951, - 12869.5938, - 11895.8623, - 10918.1709, - 9936.52148, - 8909.99219, - 7883.42188, - 7062.19824, - 6436.26367, - 5805.32129, - 5169.61084, - 4533.90088, - 3898.20093, - 3257.08081, - 2609.20068, - 1961.31055, - 1313.48035, - 659.375244, - 4.80482578, - 0.00000000, - ] - ) + # check size of ak and bk array is km+1 + if ak.size - 1 != km: + raise ValueError(f"size of ak array is not equal to km={km}") + if bk.size - 1 != km: + raise ValueError(f"size of bk array is not equal to km={km}") - bk = np.array( - [ - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 8.17541324e-09, - 6.96002459e-03, - 2.80100405e-02, - 6.37200624e-02, - 0.113602079, - 0.156224087, - 0.200350106, - 0.246741116, - 0.294403106, - 0.343381137, - 0.392891139, - 0.443740189, - 0.494590193, - 0.546304166, - 0.581041515, - 0.615818441, - 0.650634944, - 0.685899913, - 0.721165955, - 0.749378204, - 0.770637512, - 0.791946948, - 0.813303947, - 0.834660947, - 0.856018007, - 0.877429008, - 0.898908019, - 0.920387030, - 0.941865027, - 0.963406026, - 0.984951973, - 1.00000000, - ] - ) + # check that the eta values computed from ak and bk are monotonically increasing + eta, etav = check_eta(ak, bk) - elif km == 137: - ak = np.array( - [ - 1.00000000, - 1.82500005, - 3.00000000, - 4.63000011, - 6.82797718, - 9.74696636, - 13.6054239, - 18.6089306, - 24.9857178, - 32.9857101, - 42.8792419, - 54.9554634, - 69.5205765, - 86.8958817, - 107.415741, - 131.425507, - 159.279404, - 191.338562, - 227.968948, - 269.539581, - 316.420746, - 368.982361, - 427.592499, - 492.616028, - 564.413452, - 643.339905, - 729.744141, - 823.967834, - 926.344910, - 1037.20117, - 1156.85364, - 1285.61035, - 1423.77014, - 1571.62292, - 1729.44897, - 1897.51929, - 2076.09595, - 2265.43164, - 2465.77051, - 2677.34814, - 2900.39136, - 3135.11938, - 3381.74365, - 3640.46826, - 3911.49048, - 4194.93066, - 4490.81738, - 4799.14941, - 5119.89502, - 5452.99072, - 5798.34473, - 6156.07422, - 6526.94678, - 6911.87061, - 7311.86914, - 7727.41211, - 8159.35400, - 8608.52539, - 9076.40039, - 9562.68262, - 10065.9785, - 10584.6318, - 11116.6621, - 11660.0674, - 12211.5479, - 12766.8730, - 13324.6689, - 13881.3311, - 14432.1396, - 14975.6152, - 15508.2568, - 16026.1152, - 16527.3223, - 17008.7891, - 17467.6133, - 17901.6211, - 18308.4336, - 18685.7188, - 19031.2891, - 19343.5117, - 19620.0430, - 19859.3906, - 20059.9316, - 20219.6641, - 20337.8633, - 20412.3086, - 20442.0781, - 20425.7188, - 20361.8164, - 20249.5117, - 20087.0859, - 19874.0254, - 19608.5723, - 19290.2266, - 18917.4609, - 18489.7070, - 18006.9258, - 17471.8398, - 16888.6875, - 16262.0469, - 15596.6953, - 14898.4531, - 14173.3242, - 13427.7695, - 12668.2578, - 11901.3398, - 11133.3047, - 10370.1758, - 9617.51562, - 8880.45312, - 8163.37500, - 7470.34375, - 6804.42188, - 6168.53125, - 5564.38281, - 4993.79688, - 4457.37500, - 3955.96094, - 3489.23438, - 3057.26562, - 2659.14062, - 2294.24219, - 1961.50000, - 1659.47656, - 1387.54688, - 1143.25000, - 926.507812, - 734.992188, - 568.062500, - 424.414062, - 302.476562, - 202.484375, - 122.101562, - 62.7812500, - 22.8359375, - 3.75781298, - 0.00000000, - 0.00000000, - ] - ) - - bk = np.array( - [ - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 0.00000000, - 7.00000010e-06, - 2.40000008e-05, - 5.90000018e-05, - 1.12000002e-04, - 1.99000002e-04, - 3.39999999e-04, - 5.61999972e-04, - 8.90000025e-04, - 1.35300006e-03, - 1.99200003e-03, - 2.85700010e-03, - 3.97100020e-03, - 5.37799997e-03, - 7.13300006e-03, - 9.26099997e-03, - 1.18060000e-02, - 1.48160001e-02, - 1.83179993e-02, - 2.23549996e-02, - 2.69639995e-02, - 3.21759991e-02, - 3.80260013e-02, - 4.45480011e-02, - 5.17730005e-02, - 5.97280003e-02, - 6.84479997e-02, - 7.79580027e-02, - 8.82859975e-02, - 9.94620025e-02, - 0.111505002, - 0.124448001, - 0.138312995, - 0.153125003, - 0.168909997, - 0.185689002, - 0.203491002, - 0.222332999, - 0.242244005, - 0.263242006, - 0.285353988, - 0.308598012, - 0.332938999, - 0.358253986, - 0.384362996, - 0.411125004, - 0.438391000, - 0.466003001, - 0.493800014, - 0.521619022, - 0.549301028, - 0.576691985, - 0.603648007, - 0.630035996, - 0.655736029, - 0.680643022, - 0.704668999, - 0.727738976, - 0.749796987, - 0.770798028, - 0.790717006, - 0.809535980, - 0.827256024, - 0.843881011, - 0.859431982, - 0.873929024, - 0.887408018, - 0.899900019, - 0.911448002, - 0.922096014, - 0.931881011, - 0.940859973, - 0.949064016, - 0.956550002, - 0.963352025, - 0.969512999, - 0.975077987, - 0.980072021, - 0.984542012, - 0.988499999, - 0.991984010, - 0.995002985, - 0.997630000, - 1.00000000, - ] - ) - - else: - raise NotImplementedError( - "Only grids with 72, 79, 91 or 137 vertical levels" - "have been implemented so far" - ) + if not np.all(eta[:-1] <= eta[1:]): + raise ValueError("ETA values are not monotonically increasing") + if not np.all(etav[:-1] <= etav[1:]): + raise ValueError("ETAV values are not monotonically increasing") if 0.0 in bk: ks = 0 if km == 91 else np.where(bk == 0)[0][-1] @@ -857,4 +71,11 @@ def set_hybrid_pressure_coefficients(km: int) -> HybridPressureCoefficients: raise ValueError("bk must contain at least one 0.") pressure_data = HybridPressureCoefficients(ks, ptop, ak, bk) + return pressure_data + + +def check_eta(ak, bk): + from pace.fv3core.initialization.init_utils import compute_eta + + return compute_eta(ak, bk) diff --git a/util/pace/util/grid/generation.py b/util/pace/util/grid/generation.py index e61afe2d4..6181661fc 100644 --- a/util/pace/util/grid/generation.py +++ b/util/pace/util/grid/generation.py @@ -17,8 +17,8 @@ ) from pace.util import X_DIM, X_INTERFACE_DIM, Y_DIM, Y_INTERFACE_DIM, Z_INTERFACE_DIM from pace.util.constants import N_HALO_DEFAULT, PI, RADIUS +from pace.util.grid import eta -from .eta import set_hybrid_pressure_coefficients from .geometry import ( calc_unit_vector_south, calc_unit_vector_west, @@ -225,6 +225,7 @@ def __init__( dx_const: float = 1000.0, dy_const: float = 1000.0, deglat: float = 15.0, + eta_file: str = "None", ): self._grid_type = grid_type self._dx_const = dx_const @@ -282,10 +283,12 @@ def __init__( self._dy_center = None self._area = None self._area_c = None - self._ks = None - self._ak = None - self._bk = None - self._ptop = None + ( + self._ks, + self._ptop, + self._ak, + self._bk, + ) = self._set_hybrid_pressure_coefficients(eta_file) self._ec1 = None self._ec2 = None self._ew1 = None @@ -426,6 +429,7 @@ def from_tile_sizing( dx_const: float = 1000.0, dy_const: float = 1000.0, deglat: float = 15.0, + eta_file: str = "None", ) -> "MetricTerms": sizer = util.SubtileGridSizer.from_tile_params( nx_tile=npx - 1, @@ -447,6 +451,7 @@ def from_tile_sizing( dx_const=dx_const, dy_const=dy_const, deglat=deglat, + eta_file=eta_file, ) @property @@ -586,13 +591,6 @@ def ks(self) -> util.Quantity: """ number of levels where the vertical coordinate is purely pressure-based """ - if self._ks is None: - ( - self._ks, - self._ptop, - self._ak, - self._bk, - ) = self._set_hybrid_pressure_coefficients() return self._ks @property @@ -601,13 +599,6 @@ def ak(self) -> util.Quantity: the ak coefficient used to calculate the pressure at a given k-level: pk = ak + (bk * ps) """ - if self._ak is None: - ( - self._ks, - self._ptop, - self._ak, - self._bk, - ) = self._set_hybrid_pressure_coefficients() return self._ak @property @@ -616,13 +607,6 @@ def bk(self) -> util.Quantity: the bk coefficient used to calculate the pressure at a given k-level: pk = ak + (bk * ps) """ - if self._bk is None: - ( - self._ks, - self._ptop, - self._ak, - self._bk, - ) = self._set_hybrid_pressure_coefficients() return self._bk @property @@ -630,13 +614,6 @@ def ptop(self) -> util.Quantity: """ the pressure of the top of atmosphere level """ - if self._ptop is None: - ( - self._ks, - self._ptop, - self._ak, - self._bk, - ) = self._set_hybrid_pressure_coefficients() return self._ptop @property @@ -2128,7 +2105,7 @@ def _compute_area_c_cartesian(self): area_cgrid_64.data[:, :] = self._dx_const * self._dy_const return quantity_cast_to_model_float(self.quantity_factory, area_cgrid_64) - def _set_hybrid_pressure_coefficients(self): + def _set_hybrid_pressure_coefficients(self, eta_file): ks = self.quantity_factory.zeros( [], "", @@ -2149,7 +2126,9 @@ def _set_hybrid_pressure_coefficients(self): "", dtype=Float, ) - pressure_coefficients = set_hybrid_pressure_coefficients(self._npz) + pressure_coefficients = eta.set_hybrid_pressure_coefficients( + self._npz, eta_file + ) ks = pressure_coefficients.ks ptop = pressure_coefficients.ptop ak.data[:] = asarray(pressure_coefficients.ak, type(ak.data))