{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Vertical regridding and remapping of CMIP6 ocean data in the cloud\n", "## C Spencer Jones, Julius Busecke, Takaya Uchida and Ryan Abernathey" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Introduction\n", "\n", "Many ocean and climate models output ocean variables (like velocity, temperature, oxygen concentration etc.) in depth space. Property transport in the ocean generally follows isopycnals, but isopycnals often move up and down in depth space. A small difference in the vertical location of isopycnals between experiments can cause a large apparent difference in ocean properties when the experiments are compared in depth space. As a result, it is often useful to compare ocean variables in density space. \n", "\n", "This work compares two algorithms for plotting ocean properties in density coordinates, one written in FORTRAN with a python wrapper ([xlayers](https://github.com/cspencerjones/xlayers)), and one written in xarray ([xarrayutils](https://github.com/jbusecke/xarrayutils)). Both algorithms conserve total salt content in the vertical, and both algorithms are easily parallelizable to enable plotting large datasets in density coordinates. As shown here, xlayers is a faster algorithm, but on some machines it requires more setup due to its reliance on a FORTRAN compiler.\n", "\n", "Here, we apply these algorithms to plot salinity in density space in one of the Coupled Model Intercomparison Project Phase 6 (CMIP-6) models. We compare the salinity as a function of density in two future greenhouse-gas scenarios. In general, areas with net precipitation today are getting fresher and areas with net evaporation today are getting saltier ([Durack and Wijffels, 2010](https://doi.org/10.1175/2010JCLI3377.1)). In climate models with a 1% per year CO$_2$ increase, areas with net precipitation today experience increasing precipitation, and areas with net evaporation today experience a further reduction in precipitation in higher greenhouse-gas scenarios ([Vallis et al. 2015](https://doi.org/10.1002/qj.2456)). Here we compare two different greenhouse gas scenarios in the Shared Socioeconomic Pathways experiments. By plotting salinity in density space, we visualize how changes in salinity at the surface propagate along isopycnals to influence salinity concentrations in the ocean interior. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Loading CMIP-6 data\n", "We choose to load temperature and salinity data from the [ACCESS-ESM1-5 model](https://doi.org/10.22499/2.6301.004), but this calculation can be performed on almost any CMIP-6 model currently available through [Google's public datasets program](https://cloud.google.com/blog/products/data-analytics/new-climate-model-data-now-google-public-datasets). " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#Load the packages needed\n", "import numpy as np\n", "import pandas as pd\n", "import xarray as xr\n", "import xesmf as xe\n", "import cartopy\n", "import cartopy.crs as ccrs\n", "import zarr\n", "import gcsfs\n", "import matplotlib.pyplot as plt\n", "import time\n", "import warnings\n", "\n", "# suppress warnings to improve readability\n", "warnings.filterwarnings('ignore')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array(['gs://cmip6/ScenarioMIP/CSIRO/ACCESS-ESM1-5/ssp126/r1i1p1f1/Omon/so/gn/',\n", " 'gs://cmip6/ScenarioMIP/CSIRO/ACCESS-ESM1-5/ssp126/r1i1p1f1/Omon/thetao/gn/',\n", " 'gs://cmip6/ScenarioMIP/CSIRO/ACCESS-ESM1-5/ssp585/r1i1p1f1/Omon/so/gn/',\n", " 'gs://cmip6/ScenarioMIP/CSIRO/ACCESS-ESM1-5/ssp585/r1i1p1f1/Omon/thetao/gn/'],\n", " dtype=object)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Access the catalog of available CMIP-6 data\n", "df = pd.read_csv('https://storage.googleapis.com/cmip6/cmip6-zarr-consolidated-stores.csv')\n", "# Connect to google cloud storage (this only needs to be created once)\n", "gcs = gcsfs.GCSFileSystem(token='anon')\n", "\n", "# Write a query to find temperature (thetao) and salinity (so) in the ACCESS model\n", "df_sub = df.query(\"source_id == 'ACCESS-ESM1-5' and member_id=='r1i1p1f1' and table_id=='Omon' \\\n", " and (experiment_id=='ssp126' or experiment_id=='ssp585') \\\n", " and (variable_id=='thetao' or variable_id=='so')\")\n", "google_cloud_stores = df_sub.zstore.values\n", "google_cloud_stores" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We choose to compare properties for two future greenhouse gas scenarios, sometimes called [Shared Soceioeconomic Pathways](https://doi.org/10.1016/j.gloenvcha.2016.05.009). The first is a lower-emissions scenario, SSP1-2.6, and the second is a higher-emissions scenario, SSP5-8.5. The following code accesses the specific zarr stores that contain temperature and salinity data for these two pathways and sets up pointers to this data. " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<xarray.Dataset>\n", "Dimensions: (bnds: 2, experiment_id: 2, i: 360, j: 300, lev: 50, time: 1032, vertices: 4)\n", "Coordinates:\n", " vertices_longitude (j, i, vertices) float64 80.0 81.0 81.0 ... 80.0 80.0\n", " time_bnds (time, bnds) datetime64[ns] 2015-01-01 ... 2101-01-01\n", " lev_bnds (lev, bnds) float64 0.0 10.0 10.0 ... 5.665e+03 6e+03\n", " longitude (j, i) float64 80.5 81.5 82.5 83.5 ... 79.96 79.97 79.99\n", " vertices_latitude (j, i, vertices) float64 -78.0 -78.0 ... 65.0 65.42\n", " latitude (j, i) float64 -77.88 -77.88 -77.88 ... 65.63 65.21\n", " * j (j) int32 0 1 2 3 4 5 6 ... 293 294 295 296 297 298 299\n", " * i (i) int32 0 1 2 3 4 5 6 ... 353 354 355 356 357 358 359\n", " * time (time) datetime64[ns] 2015-01-16T12:00:00 ... 2100-12-16T12:00:00\n", " * lev (lev) float64 5.0 15.0 25.0 ... 5.499e+03 5.831e+03\n", " * experiment_id (experiment_id) object 'ssp126' 'ssp585'\n", "Dimensions without coordinates: bnds, vertices\n", "Data variables:\n", " so (experiment_id, time, lev, j, i) float32 dask.array<chunksize=(1, 6, 50, 300, 360), meta=np.ndarray>\n", " thetao (experiment_id, time, lev, j, i) float32 dask.array<chunksize=(1, 5, 50, 300, 360), meta=np.ndarray>" ], "text/plain": [ "
<xarray.Dataset>\n", "Dimensions: (bnds: 2, experiment_id: 2, i: 360, j: 300, lev: 50, time: 1032, vertices: 4)\n", "Coordinates:\n", " vertices_longitude (j, i, vertices) float64 80.0 81.0 81.0 ... 80.0 80.0\n", " time_bnds (time, bnds) datetime64[ns] 2015-01-01 ... 2101-01-01\n", " lev_bnds (lev, bnds) float64 0.0 10.0 10.0 ... 5.665e+03 6e+03\n", " longitude (j, i) float64 80.5 81.5 82.5 83.5 ... 79.96 79.97 79.99\n", " vertices_latitude (j, i, vertices) float64 -78.0 -78.0 ... 65.0 65.42\n", " latitude (j, i) float64 -77.88 -77.88 -77.88 ... 65.63 65.21\n", " * j (j) int32 0 1 2 3 4 5 6 ... 293 294 295 296 297 298 299\n", " * i (i) int32 0 1 2 3 4 5 6 ... 353 354 355 356 357 358 359\n", " * time (time) datetime64[ns] 2015-01-16T12:00:00 ... 2100-12-16T12:00:00\n", " * lev (lev) float64 5.0 15.0 25.0 ... 5.499e+03 5.831e+03\n", " * experiment_id (experiment_id) object 'ssp126' 'ssp585'\n", "Dimensions without coordinates: bnds, vertices\n", "Data variables:\n", " so (experiment_id, time, lev, j, i) float32 dask.array<chunksize=(1, 6, 50, 300, 360), meta=np.ndarray>\n", " thetao (experiment_id, time, lev, j, i) float32 dask.array<chunksize=(1, 5, 50, 300, 360), meta=np.ndarray>\n", " dens (experiment_id, time, lev, j, i) float64 dask.array<chunksize=(1, 5, 50, 300, 360), meta=np.ndarray>" ], "text/plain": [ "