{ "cells": [ { "cell_type": "markdown", "id": "afc21996-cdfc-44ec-80b3-a3ce06e0ea53", "metadata": {}, "source": [ "# A primer on calculating rotational and divergent wind components" ] }, { "cell_type": "markdown", "id": "13e339f8-85fd-4447-be9e-1288f9842630", "metadata": {}, "source": [ "
\n", "\n", "You can install it using `conda` (in the correct environment):\n", "```bash\n", "!conda install -c conda-forge windspharm --yes\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "id": "8099bd00-173b-42a5-ab75-127f0163fd30", "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "import iris\n", "from aeolus.calc import wind_rot_div\n", "from aeolus.core import AtmoSim\n", "from aeolus.model import um" ] }, { "cell_type": "markdown", "id": "b561091d-dc93-41da-92ca-c4f790ab221b", "metadata": {}, "source": [ "## Loading data" ] }, { "cell_type": "code", "execution_count": 2, "id": "6ec023bc-ab8c-4132-84a8-e5a2da6b0324", "metadata": {}, "outputs": [], "source": [ "sample_file = (\n", " Path.cwd().parent / \"tests\" / \"data\" / \"test_data\" / \"netcdf\" / \"ch111_ctrl_mean_u_v_w.nc\"\n", ")" ] }, { "cell_type": "code", "execution_count": 3, "id": "8b31262c-96a6-4c02-8d3d-1bcec7a8facd", "metadata": {}, "outputs": [], "source": [ "inp_data = iris.load(sample_file)" ] }, { "cell_type": "code", "execution_count": 4, "id": "33e20240-a2c6-4422-b4c9-0b9c0a942d61", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0: upward_air_velocity / (m s-1) (level_height: 39; latitude: 90; longitude: 144)\n", "1: x_wind / (m s-1) (level_height: 39; latitude: 90; longitude: 144)\n", "2: y_wind / (m s-1) (level_height: 39; latitude: 90; longitude: 144)\n" ] } ], "source": [ "print(inp_data)" ] }, { "cell_type": "markdown", "id": "d86b08ef-85d3-450f-8942-e2e1df27d4f6", "metadata": {}, "source": [ "**Note** that the x- and y-wind components are already [horizontally interpolated](https://scitools-iris.readthedocs.io/en/latest/userguide/interpolation_and_regridding.html#regridding) to the same grid." ] }, { "cell_type": "markdown", "id": "fee0ce47-909b-4769-8037-505a113bfc60", "metadata": {}, "source": [ "The `inp_data` cube list can be then used to instantiate an `AtmoSim` object, using a planet configuration with relevant constants (see \"Physical constants\" example for more info)." ] }, { "cell_type": "code", "execution_count": 5, "id": "68f9d81f-2cdf-46ca-a097-13020cb1315f", "metadata": {}, "outputs": [], "source": [ "my_run = AtmoSim(\n", " cubes=inp_data,\n", " name=\"t1e\",\n", " description=\"Time-mean output from a UM simulation of the THAI Hab 1 case.\",\n", " planet=\"trap1e\", # this reads constants from a JSON file\n", ")" ] }, { "cell_type": "markdown", "id": "72dc6426-bc80-4bfc-b09b-32dbc64826b0", "metadata": {}, "source": [ "## Applying Helmoltz decomposition" ] }, { "cell_type": "markdown", "id": "2dfa07f2-e884-4473-8f77-3404af0ee608", "metadata": {}, "source": [ "For convenience, let's select a single level in the vertical. This is optional - the rot/div decomposition can be performed on an N-dimensional cubes, as long as they have longitude and latitude dimensions." ] }, { "cell_type": "code", "execution_count": 6, "id": "b9a99c44-8bc1-4b29-b714-b37b4b1ab476", "metadata": {}, "outputs": [], "source": [ "u_at_8km = my_run.u.extract(iris.Constraint(**{um.z: 8000}))\n", "v_at_8km = my_run.v.extract(iris.Constraint(**{um.z: 8000}))" ] }, { "cell_type": "markdown", "id": "9179549c-a7bb-4f19-825c-7ae3834cd21f", "metadata": {}, "source": [ "Check that the data is indeed roughly at 8000 m height." ] }, { "cell_type": "code", "execution_count": 7, "id": "8312e689-32e5-40cf-a5ca-3ef19ff238f3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "DimCoord : level_height / (m)\n", " points: [7988.824]\n", " bounds: [[7438.572, 8579.836]]\n", " shape: (1,) bounds(1, 2)\n", " dtype: float64\n", " long_name: 'level_height'\n", " var_name: 'level_height'\n", " attributes:\n", " positive 'up'\n" ] } ], "source": [ "print(u_at_8km.coord(um.z))" ] }, { "cell_type": "markdown", "id": "7e5f82c9-40eb-4bb5-94b3-6fdce4708f1c", "metadata": {}, "source": [ "We can then apply the rot/div decomposition. The planet's radius will be taken from the cubes' metadata. Alternatively, it can be supplied by passing a `ConstContainer` as the `const` optional argument to the `wind_rot_div()` function." ] }, { "cell_type": "code", "execution_count": 8, "id": "8856e340-3f37-488c-95e2-a202fabc2a78", "metadata": {}, "outputs": [], "source": [ "rot_div_cubes = wind_rot_div(u_at_8km, v_at_8km)" ] }, { "cell_type": "code", "execution_count": 9, "id": "2143b7c2-4250-4391-8944-5cf83836b4c2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'u_total':