diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index b0a281c5..feb203e8 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -4,6 +4,7 @@ on: push: branches: - '**' + - '!joss-paper' jobs: formatting: diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..0d0b2643 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,35 @@ +cff-version: 1.2.0 +preferred-citation: + type: article + authors: + - family-names: "Barnes" + given-names: "Ashley J." + orcid: "https://orcid.org/0000-0003-3165-8676" + - family-names: "Constantinou" + given-names: "Navid C." + orcid: "https://orcid.org/0000-0002-8149-4094" + - family-names: "Gibson" + given-names: "Angus H." + orcid: "https://orcid.org/0000-0001-7577-3604" + - family-names: "Kiss" + given-names: "Andrew E." + orcid: "https://orcid.org/0000-0001-8960-9557" + - family-names: "Chapman" + given-names: "Chris" + orcid: "https://orcid.org/0000-0002-6030-1951" + - family-names: "Reily" + given-names: "John" + orcid: "https://orcid.org/0000-0003-4001-0230" + - family-names: "Bhagtani" + given-names: "Dhruv" + orcid: "https://orcid.org/0000-0002-1222-375X" + - family-names: "Yang" + given-names: "Luwei" + orcid: "https://orcid.org/0000-0001-8570-7424" + title: "regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6" + journal: "Journal of Open Source Software" + doi: "10.21105/joss.06857" + volume: 9 + issue: 100 + start: 6857 + year: 2024 diff --git a/README.md b/README.md index 8349cf53..4afdfdf8 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,14 @@ [![Repo status](https://www.repostatus.org/badges/latest/active.svg?style=flat-square)](https://www.repostatus.org/#active) [![conda forge](https://img.shields.io/conda/vn/conda-forge/regional-mom6.svg)](https://anaconda.org/conda-forge/regional-mom6) [![pypi](https://badge.fury.io/py/regional-mom6.svg)](https://badge.fury.io/py/regional-mom6) -[![status](https://joss.theoj.org/papers/d396435c09aae4c2f4b62cdbc1493c1e/status.svg)](https://joss.theoj.org/papers/d396435c09aae4c2f4b62cdbc1493c1e) [![Documentation Status](https://readthedocs.org/projects/regional-mom6/badge/?version=latest)](https://regional-mom6.readthedocs.io/en/latest/?badge=latest) [![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://mit-license.org) [![codecov](https://codecov.io/gh/COSIMA/regional-mom6/branch/main/graph/badge.svg?token=7OEZ1UZRY4)](https://codecov.io/gh/COSIMA/regional-mom6) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![status](https://joss.theoj.org/papers/d396435c09aae4c2f4b62cdbc1493c1e/status.svg)](https://joss.theoj.org/papers/d396435c09aae4c2f4b62cdbc1493c1e) + Users just need to provide some information about where, when, and how big their domain is and also where raw input forcing files are. The package sorts out all the boring details and creates a set of MOM6-friendly input files along with setup directories ready to go! The idea behind this package is that it should let the user sidestep some of the tricky issues with getting the model to run in the first place. This removes some of the steep learning curve for people new to working with MOM6. Note that the resultant model configuration might still need some tweaking (e.g., fiddling with timestep to avoid CFL-related numerical stability issues or fiddling with bathymetry to deal with very narrow fjords or channels that may exist). @@ -129,3 +130,27 @@ the package using two different sets of input datasets. Please ensure that you can get at least one of these working on your setup with your MOM6 executable before trying to modify the example to suit your domain with your bathymetry, forcing, and boundary conditions. You can download the notebooks [from Github](https://github.com/COSIMA/regional-mom6/tree/main/demos) or by clicking on the download download button, e.g., at the top-right of the [regional Tasmania forced by ERA5 example](https://regional-mom6.readthedocs.io/en/latest/demo_notebooks/reanalysis-forced.html). + +## Citing + +If you use regional-mom6 in research, teaching, or other activities, we would be grateful +if you could mention regional-mom6 and cite our paper in JOSS: + +> Barnes et al., (2024). regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6. _Journal of Open Source Software_, **9(100)**, 6857, doi:[10.21105/joss.06857](https://doi.org/10.21105/joss.06857). + +The bibtex entry for the paper is: + +```bibtex +@article{regional-mom6-JOSS, + doi = {10.21105/joss.06857}, + url = {https://doi.org/10.21105/joss.06857}, + year = {2024}, + publisher = {The Open Journal}, + volume = {9}, + number = {100}, + pages = {6857}, + author = {Ashley J. Barnes and Navid C. Constantinou and Angus H. Gibson and Andrew E. Kiss and Chris Chapman and John Reily and Dhruv Bhagtani and Luwei Yang}, + title = {{regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6}}, + journal = {Journal of Open Source Software} +} +``` diff --git a/docs/index.rst b/docs/index.rst index 954d1681..9e65ebc4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -53,6 +53,15 @@ What you need to get started Browse through the `demos `_. +Citing +------ + +If you use regional-mom6 in research, teaching, or other activities, we would be grateful +if you could mention regional-mom6 and cite our paper in JOSS: + +Barnes et al., (2024). regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6. *Journal of Open Source Software*, **9(100)**, 6857, doi:`10.21105/joss.06857 `_. + + .. _regional-mom6: https://github.com/COSIMA/regional-mom6 .. _Modular Ocean Model version 6: https://github.com/mom-ocean/MOM6 .. _open a pull request: https://github.com/COSIMA/regional-mom6/pulls diff --git a/paper/nested-regional-mom6.ipynb b/paper/nested-regional-mom6.ipynb new file mode 100644 index 00000000..64a82a99 --- /dev/null +++ b/paper/nested-regional-mom6.ipynb @@ -0,0 +1,1503 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "90e1c40c-ddac-4ddb-9a32-55327a4cbd61", + "metadata": {}, + "source": [ + "# MOM6 ANALYSIS - Overview Plot\n", + "The key purpose of this notebook will be to create an overview plot of the Study region.\n", + "I'd like this overview plot to be a simple, clear picture of the nesting approach, as well as baseline picture of the EAC dynamics and flow fields. \n", + "\n", + "**Adjusted for paper** - 29th April 2024\n", + "The steps to reproduce the figure are:\n", + "1. Load in velocity (u/v) data from ACCESS-OM2-01, STHPAC-01, EAC-003 (the latter two being the large and small regional models respectively).\n", + "2. Decide on a depth level for the plot - From memory I chose somewhere around 50m to show the ocean features rather than atmospheric imprint on the surface.\n", + "3. Do some spatial subsetting, regridding and calculate speed from the regridded u/v data fields.\n", + "4. Plot the nested fields. " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "52c55c74-14f4-4000-9256-55ce81f3633f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import cmocean as cm\n", + "import xarray as xr\n", + "import numpy as np\n", + "import glob\n", + "import xesmf" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "69bf0edc-1d6c-4a61-9591-39f45498bd8f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from xgcm import Grid\n", + "\n", + "from dask.distributed import Client\n", + "\n", + "import warnings\n", + "warnings.filterwarnings('ignore')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "799bcdd4-d574-40f5-a97c-1e2750681376", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# import cartopy to plot maps\n", + "import cartopy.crs as ccrs\n", + "import cartopy.feature as feature\n", + "land_50m = feature.NaturalEarthFeature('physical', 'land', '50m', \n", + " edgecolor='black',\n", + " facecolor='gray',\n", + " linewidth=0.2)\n", + "import matplotlib.ticker as mticker\n", + "import cartopy.crs as ccrs" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "23fd3bee-96d8-417f-89f3-569acaaeab60", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Client

\n", + "

Client-b7083cd2-11d4-11ef-b423-00000797fe80

\n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "
Connection method: Cluster objectCluster type: distributed.LocalCluster
\n", + " Dashboard: /proxy/8787/status\n", + "
\n", + "\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "

Cluster Info

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

LocalCluster

\n", + "

f03588b3

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "\n", + " \n", + "
\n", + " Dashboard: /proxy/8787/status\n", + " \n", + " Workers: 7\n", + "
\n", + " Total threads: 28\n", + " \n", + " Total memory: 112.00 GiB\n", + "
Status: runningUsing processes: True
\n", + "\n", + "
\n", + " \n", + "

Scheduler Info

\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Scheduler

\n", + "

Scheduler-76b42360-a6b7-488f-a34c-09fac8d71108

\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + " Comm: tcp://127.0.0.1:42965\n", + " \n", + " Workers: 7\n", + "
\n", + " Dashboard: /proxy/8787/status\n", + " \n", + " Total threads: 28\n", + "
\n", + " Started: Just now\n", + " \n", + " Total memory: 112.00 GiB\n", + "
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "

Workers

\n", + "
\n", + "\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 0

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:46293\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/39793/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:41769\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-55pa8q0c\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 1

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:35849\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/46383/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:41273\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-6ind6mzh\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 2

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:37211\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/44537/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:34573\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-5bc6uav6\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 3

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:40199\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/44305/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:34977\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-pe_ehyil\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 4

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:44425\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/44529/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:40851\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-og8mlj0i\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 5

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:42913\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/41087/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:35617\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-2q_48dp8\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "

Worker: 6

\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + " \n", + "\n", + " \n", + "\n", + "
\n", + " Comm: tcp://127.0.0.1:45869\n", + " \n", + " Total threads: 4\n", + "
\n", + " Dashboard: /proxy/43627/status\n", + " \n", + " Memory: 16.00 GiB\n", + "
\n", + " Nanny: tcp://127.0.0.1:40429\n", + "
\n", + " Local directory: /jobfs/115616104.gadi-pbs/dask-scratch-space/worker-i5ws4t5s\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + " \n", + "\n", + "
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "client = Client()\n", + "client" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4eeff407-e4b0-465e-8404-4612dfc39c6e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# set paths to model output\n", + "## SRM\n", + "eac_003 = '/scratch/v45/jr5971/mom6-setonix/eac_iaf_003/'\n", + "## LRM\n", + "sthpac_01 = '/scratch/v45/jr5971/mom6-setonix/sthpac_iaf_01/'\n", + "## PARENT\n", + "access = '/g/data/ik11/outputs/access-om2-01/01deg_jra55v150_iaf_cycle1/'" + ] + }, + { + "cell_type": "markdown", + "id": "16fb22a2-4281-45c9-bc40-b93071fc71dd", + "metadata": {}, + "source": [ + "### Load OM2 data" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "5c5806e4-4b1c-4885-b6a9-e7eba840a634", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.3.0\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:   (xu_ocean: 3600, yu_ocean: 2700, st_ocean: 75, time: 31)\n",
+       "Coordinates:\n",
+       "  * xu_ocean  (xu_ocean) float64 -279.9 -279.8 -279.7 -279.6 ... 79.8 79.9 80.0\n",
+       "  * yu_ocean  (yu_ocean) float64 -81.09 -81.05 -81.0 -80.96 ... 89.92 89.96 90.0\n",
+       "  * st_ocean  (st_ocean) float64 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n",
+       "  * time      (time) datetime64[ns] 1992-12-01T12:00:00 ... 1992-12-31T12:00:00\n",
+       "Data variables:\n",
+       "    u         (time, st_ocean, yu_ocean, xu_ocean) float32 ...\n",
+       "    v         (time, st_ocean, yu_ocean, xu_ocean) float32 ...\n",
+       "Attributes:\n",
+       "    long_name:      i-current\n",
+       "    units:          m/sec\n",
+       "    valid_range:    [-10.  10.]\n",
+       "    cell_methods:   time: mean\n",
+       "    time_avg_info:  average_T1,average_T2,average_DT\n",
+       "    standard_name:  sea_water_x_velocity
" + ], + "text/plain": [ + "\n", + "Dimensions: (xu_ocean: 3600, yu_ocean: 2700, st_ocean: 75, time: 31)\n", + "Coordinates:\n", + " * xu_ocean (xu_ocean) float64 -279.9 -279.8 -279.7 -279.6 ... 79.8 79.9 80.0\n", + " * yu_ocean (yu_ocean) float64 -81.09 -81.05 -81.0 -80.96 ... 89.92 89.96 90.0\n", + " * st_ocean (st_ocean) float64 0.5413 1.681 2.94 ... 5.511e+03 5.709e+03\n", + " * time (time) datetime64[ns] 1992-12-01T12:00:00 ... 1992-12-31T12:00:00\n", + "Data variables:\n", + " u (time, st_ocean, yu_ocean, xu_ocean) float32 ...\n", + " v (time, st_ocean, yu_ocean, xu_ocean) float32 ...\n", + "Attributes:\n", + " long_name: i-current\n", + " units: m/sec\n", + " valid_range: [-10. 10.]\n", + " cell_methods: time: mean\n", + " time_avg_info: average_T1,average_T2,average_DT\n", + " standard_name: sea_water_x_velocity" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "year_month = '1992_12'\n", + "# access velocities\n", + "om2_u_path = glob.glob(access + f'output*/ocean/*u*{year_month}*.nc')\n", + "om2_v_path = glob.glob(access + f'output*/ocean/*v*{year_month}*.nc')\n", + "om2_u = xr.open_dataset(om2_u_path[0])['u']\n", + "om2_v = xr.open_dataset(om2_v_path[0])['v']\n", + "\n", + "om2_vel = xr.merge([om2_u, om2_v])\n", + "om2_vel" + ] + }, + { + "cell_type": "markdown", + "id": "8005ce16-a3ec-459b-99d1-e73c75fae339", + "metadata": {}, + "source": [ + "### Get MOM6 data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ee965bb3-bf81-4c61-8fa0-d2e4cc53887c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 303 ms, sys: 408 ms, total: 712 ms\n", + "Wall time: 1.42 s\n" + ] + } + ], + "source": [ + "%%time\n", + "year_month = '199212'\n", + "\n", + "# eac vels\n", + "eac_u_path = glob.glob(eac_003 + f'output*/{year_month}*u_3d*nc')[0]\n", + "eac_v_path = glob.glob(eac_003 + f'output*/{year_month}*v_3d*nc')[0]\n", + "eac_u = xr.open_dataset(eac_u_path)['uo']\n", + "eac_v = xr.open_dataset(eac_v_path)['vo']\n", + "\n", + "eac = xr.merge([eac_u, eac_v])\n", + "\n", + "# sthpac vels\n", + "sthpac_u_path = glob.glob(sthpac_01 + f'output*/{year_month}*u_3d.nc')[0]\n", + "sthpac_v_path = glob.glob(sthpac_01 + f'output*/{year_month}*v_3d.nc')[0]\n", + "sthpac_u = xr.open_dataset(sthpac_u_path)['uo']\n", + "sthpac_v = xr.open_dataset(sthpac_v_path)['vo']\n", + "\n", + "sthpac = xr.merge([sthpac_u, sthpac_v])" + ] + }, + { + "cell_type": "markdown", + "id": "ee9b8fc5-6942-4431-8627-16456dc4db6a", + "metadata": {}, + "source": [ + "## Choose spatial and temporal extent\n", + "In order to make the regridding quicker later on, let's choose a temporal extent now. " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "386ff387-3996-4033-a8e2-918a0bddae63", + "metadata": {}, + "outputs": [], + "source": [ + "# Choose depth\n", + "depth_level = 5 # m\n", + "\n", + "om2_2d = om2_vel.sel(st_ocean=depth_level, method='nearest')\n", + "sthpac_2d = sthpac.sel(z_l=depth_level, method='nearest')\n", + "eac_2d = eac.sel(z_l=depth_level, method='nearest')" + ] + }, + { + "cell_type": "markdown", + "id": "6ed464be-291a-46a5-8dd6-ce1675683841", + "metadata": {}, + "source": [ + "### Make Grids Symmetric" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8f3669a5-8ab8-4a9b-a9cc-d316554be74d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bottom left centre points: -217.78 -46.18\n", + "Bottom left CORNER points: -217.8 -46.19\n" + ] + } + ], + "source": [ + "# EAC\n", + "# bottom corner \"centre\" coord\n", + "print('Bottom left centre points: ', np.round(eac.xh.min().values, 2), np.round(eac.yh.min().values,2))\n", + "# bottom left \"corner\" coord...\n", + "print('Bottom left CORNER points: ', np.round(eac.xq.min().values, 2), np.round(eac.yq.min().values,2))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "28d44d42-e721-4d6c-a4ea-0b94ee1c536b", + "metadata": {}, + "outputs": [], + "source": [ + "# CREATE SYMMETRIC DATASETS\n", + "eac_symmetric = eac_2d.isel(xq=slice(1,len(eac.xq)), yq = slice(1,len(eac.yq)))\n", + "sthpac_symmetric = sthpac_2d.isel(xq=slice(1,len(sthpac.xq)), yq=slice(1,len(sthpac.yq)))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f686caf9-5519-466b-a39b-68c90d208fb4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bottom left centre points: -217.78 -46.18\n", + "Bottom left CORNER points: -217.77 -46.17\n" + ] + } + ], + "source": [ + "# EAC\n", + "# bottom corner \"centre\" coord\n", + "print('Bottom left centre points: ', np.round(eac_symmetric.xh.min().values, 2), np.round(eac_symmetric.yh.min().values,2))\n", + "# bottom left \"corner\" coord...\n", + "print('Bottom left CORNER points: ', np.round(eac_symmetric.xq.min().values, 2), np.round(eac_symmetric.yq.min().values,2))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "60da406f-f3f8-4bf6-a93c-f94eed9b751d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\n", + "X Axis (not periodic, boundary=None):\n", + " * center xh --> right\n", + " * right xq --> center\n", + "Y Axis (not periodic, boundary=None):\n", + " * center yh --> right\n", + " * right yq --> center" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get grid cell thickness data\n", + "eac_static = xr.open_dataset(eac_003 + 'output000/19900202.ocean_static.nc')\n", + "sthpac_static = xr.open_dataset(sthpac_01 + 'output000/19900201.ocean_static.nc')\n", + "\n", + "eac_symmetric['dxt'] = eac_static['dxt']\n", + "eac_symmetric['dyt'] = eac_static['dyt']\n", + "sthpac_symmetric['dxt'] = sthpac_static['dxt']\n", + "sthpac_symmetric['dyt'] = sthpac_static['dyt']\n", + "\n", + "\n", + "# Define new aligned grids\n", + "metrics = { \n", + " ('X',) : ['dxt'], # X distances\n", + " ('Y',) : ['dyt'] # Y distances\n", + "}\n", + "coords = {'X' : {'center':'xh', 'right':'xq'},\n", + " 'Y' : {'center':'yh', 'right':'yq'} }\n", + "\n", + "eac_grid = Grid(eac_symmetric, coords=coords, metrics=metrics, periodic=False)\n", + "sthpac_grid = Grid(sthpac_symmetric, coords=coords, metrics=metrics, periodic=False)\n", + "eac_grid" + ] + }, + { + "cell_type": "markdown", + "id": "bbd6db2c-f80b-4a5f-93d8-2f1c0c8d77b7", + "metadata": {}, + "source": [ + "Overwrite the meridional velocities (`vo`) in the symmetric datasets with the new offset points" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "0573deda-48aa-4af9-9e5a-792562107d18", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('time', 'yh', 'xq') ('time', 'z_l', 'yq', 'xh')\n", + "CPU times: user 2.23 s, sys: 3.99 s, total: 6.22 s\n", + "Wall time: 19.8 s\n" + ] + } + ], + "source": [ + "%%time\n", + "eac_symmetric['vo'] = eac_grid.interp(eac_symmetric['vo'], axis=['X','Y'])\n", + "sthpac_symmetric['vo'] = sthpac_grid.interp(sthpac_symmetric['vo'], axis=['X','Y'])\n", + "print(eac_symmetric['vo'].dims, eac['vo'].dims)" + ] + }, + { + "cell_type": "markdown", + "id": "d4ca6caf-687b-450f-acde-9cc3e74368b1", + "metadata": {}, + "source": [ + "### Subset ACCESS spatially" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "bfa64746-de52-4309-bcdb-9f103e7000af", + "metadata": {}, + "outputs": [], + "source": [ + "# subset global to some region just bigger than the sthpac model...\n", + "sthpac_idx = {'W':sthpac.xh.min().values, 'E':sthpac.xh.max().values, \n", + " 'S':sthpac.yh.min().values, 'N':sthpac.yh.max().values}\n", + "eac_idx = {'W':eac.xh.min().values, 'E':eac.xh.max().values,\n", + " 'S':eac.yh.min().values, 'N':eac.yh.max().values}\n", + "om2_subset = om2_2d.sel(xu_ocean=slice(sthpac_idx['W'] - 30, sthpac_idx['E']+50),\n", + " yu_ocean = slice(sthpac_idx['S']-30, sthpac_idx['N']+30))" + ] + }, + { + "cell_type": "markdown", + "id": "56b464c7-289b-46b2-8c5f-22e22f188125", + "metadata": {}, + "source": [ + "# Plotting" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "15de821c-57a4-4658-b270-1bcda5af5265", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from matplotlib import patches\n", + "import cartopy.feature as cfeature\n", + "import matplotlib.lines as mlines\n", + "from matplotlib.ticker import (AutoMinorLocator, MultipleLocator)\n", + "from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "990efb4c-79e1-41fa-a1da-e2b665177373", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.59 s, sys: 3.07 s, total: 4.66 s\n", + "Wall time: 14.9 s\n" + ] + } + ], + "source": [ + "%%time\n", + "sthpac_2d_snap = sthpac_symmetric.load()\n", + "eac_2d_snap = eac_symmetric.load()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "a2b310c3-b5bd-4129-8980-07b5e30e0334", + "metadata": {}, + "outputs": [], + "source": [ + "sthpac_speed = np.sqrt(sthpac_2d_snap['vo']**2 + sthpac_2d_snap['uo']**2).compute()\n", + "eac_speed = np.sqrt(eac_2d_snap['vo']**2 + eac_2d_snap['uo']**2).compute()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "b7fb3364-f408-4de8-bcdb-3d1dcffb0311", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 2.96 s, sys: 447 ms, total: 3.41 s\n", + "Wall time: 9.09 s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Choose single day to calculate speed for all variables. \n", + "day = '1992-12-22'\n", + "om2_2d_snap = om2_subset.sel(time=day)\n", + "sthpac_2d_snap = sthpac_speed.sel(time=day)\n", + "eac_2d_snap = eac_speed.sel(time=day)\n", + "\n", + "# Calculate snapshot of speed\n", + "om2_speed = np.sqrt(om2_2d_snap['v']**2 + om2_2d_snap['u']**2).compute()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4b573ea-8d8a-41e2-8738-95d635feee7d", + "metadata": {}, + "outputs": [], + "source": [ + "fig = plt.figure(figsize=(10, 12))\n", + "ax = plt.axes(projection=ccrs.Robinson(central_longitude=-200))\n", + "\n", + "vmax = 0.65\n", + "\n", + "# Plot access\n", + "h1 = om2_speed.plot(ax=ax,\n", + " vmin=0, vmax=vmax,\n", + " transform=ccrs.PlateCarree(), zorder=0, alpha=1, add_colorbar=False, rasterized=True)\n", + "h2 = sthpac_2d_snap.plot(ax=ax,\n", + " vmin=0, vmax=vmax,\n", + " transform=ccrs.PlateCarree(),\n", + " cmap=cm.cm.ice, add_colorbar=False, rasterized=True)\n", + "h3 = eac_2d_snap.plot(ax=ax,\n", + " vmin=0, vmax=vmax,\n", + " transform=ccrs.PlateCarree(),\n", + " cmap=cm.cm.thermal, add_colorbar=False, rasterized=True)\n", + "\n", + "box1 = patches.Rectangle((sthpac_idx['W'], sthpac_idx['S']), (sthpac_idx['E']-sthpac_idx['W']), \n", + " (sthpac_idx['N']-sthpac_idx['S']), color='w', fill=None, transform=ccrs.PlateCarree(),\n", + " alpha=1, linestyle='dashed', linewidth=3)\n", + "\n", + "box2 = patches.Rectangle((eac_idx['W'], eac_idx['S']), (eac_idx['E']-eac_idx['W']), \n", + " (eac_idx['N']-eac_idx['S']), color='w', fill=None, transform=ccrs.PlateCarree(),\n", + " alpha=1, linestyle='dotted', linewidth=3)\n", + "\n", + "# Add a colorbar axis at the bottom of the graph\n", + "cbar_ax1 = fig.add_axes([0.25, 0.10, 0.5, 0.02])\n", + "cbar_ax2 = fig.add_axes([0.25, 0.06, 0.5, 0.02])\n", + "cbar_ax3 = fig.add_axes([0.25, 0.02, 0.5, 0.02])\n", + "\n", + "# Draw the colorbar\n", + "cbar1=fig.colorbar(h1, shrink=0.45, cax=cbar_ax1, orientation='horizontal', extend='max')\n", + "cbar2=fig.colorbar(h2, shrink=0.45, cax=cbar_ax2, orientation='horizontal', extend='max')\n", + "cbar3=fig.colorbar(h3, shrink=0.45, cax=cbar_ax3, orientation='horizontal', label='ocean surface speed (m/s)', extend='max')\n", + "\n", + "cbar1.ax.set_xticklabels([\"\", \"\", \"\", \"\", \"\", \"\", \"\"])\n", + "cbar2.ax.set_xticklabels([\"\", \"\", \"\", \"\", \"\", \"\", \"\"])\n", + "\n", + "ax.add_patch(box1); ax.add_patch(box2)\n", + "\n", + "ax.add_feature(cfeature.LAND, zorder=0)\n", + "ax.add_feature(cfeature.LAND, zorder=1)\n", + " \n", + "# Set custom ticks on x and y axes\n", + "# ax.set_xticks((120, 140), crs=ccrs.PlateCarree())\n", + "# ax.set_yticks(yticks, crs=ccrs.PlateCarree());\n", + "\n", + "extent = [sthpac_idx['W']-20, sthpac_idx['E']+20, sthpac_idx['S']-5, sthpac_idx['N']+5]\n", + "ax.set_extent(extent, crs=ccrs.PlateCarree())\n", + "ax.coastlines()\n", + "\n", + "ax.set_title(' ', fontsize=18)\n", + "\n", + "# # Add latitude and longitude labels to the ticks\n", + "lon_formatter = LongitudeFormatter(zero_direction_label=False)\n", + "lat_formatter = LatitudeFormatter()\n", + "ax.xaxis.set_major_formatter(lon_formatter)\n", + "ax.yaxis.set_major_formatter(lat_formatter)\n", + "\n", + "ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree(), alpha=0.5, linestyle='--')\n", + "\n", + "fig.savefig('nested-regional-mom6.pdf', bbox_inches='tight')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:analysis3]", + "language": "python", + "name": "conda-env-analysis3-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/paper/nested-regional-mom6.pdf b/paper/nested-regional-mom6.pdf new file mode 100644 index 00000000..3e2ef565 Binary files /dev/null and b/paper/nested-regional-mom6.pdf differ diff --git a/paper/paper.bib b/paper/paper.bib new file mode 100644 index 00000000..22bea666 --- /dev/null +++ b/paper/paper.bib @@ -0,0 +1,299 @@ +@article{Adcroft2019MOM6, + author = {Adcroft, Alistair and Anderson, Whit and Balaji, V. and Blanton, Chris and Bushuk, Mitchell and Dufour, Carolina O. and Dunne, John P. and Griffies, Stephen M. and Hallberg, Robert and Harrison, Matthew J. and Held, Isaac M. and Jansen, Malte F. and John, Jasmin G. and Krasting, John P. and Langenhorst, Amy R. and Legg, Sonya and Liang, Zhi and McHugh, Colleen and Radhakrishnan, Aparna and Reichl, Brandon G. and Rosati, Tony and Samuels, Bonita L. and Shao, Andrew and Stouffer, Ronald and Winton, Michael and Wittenberg, Andrew T. and Xiang, Baoqiang and Zadeh, Niki and Zhang, Rong}, + title = {The {GFDL} global ocean and sea ice model {OM4.0}: {Model} description and simulation features}, + journal = {Journal of Advances in Modeling Earth Systems}, + volume = {11}, + number = {10}, + pages = {3167--3211}, + year = {2019}, + doi = {10.1029/2019MS001726}, +} + +@article{marshall1997finite, + title = {A finite-volume, incompressible {Navier Stokes} model for studies of the ocean on parallel computers}, + author = {Marshall, John and Adcroft, Alistair and Hill, Chris and Perelman, Lev and Heisey, Curt}, + journal = {Journal of Geophysical Research: Oceans}, + volume = {102}, + number = {C3}, + pages = {5753--5766}, + year = {1997}, + doi = {10.1029/96JC02775} +} + +@article{shchepetkin2005regional, + title = {The regional oceanic modeling system ({ROMS}): a split-explicit, free-surface, topography-following-coordinate oceanic model}, + author = {Shchepetkin, Alexander F and McWilliams, James C}, + journal = {Ocean Modelling}, + volume = {9}, + number = {4}, + pages = {347--404}, + year = {2005}, + doi = {10.1016/j.ocemod.2004.08.002} +} + +@misc{xesmf, + author = {Jiawei Zhuang and Raphael Dussin and David Huard and Pascal Bourgault and Anderson Banihirwe and Stephane Raynaud and Brewster Malevich and Martin Schupfner and Filipe and Sam Levang and Charles Gauthier and André Jüling and Mattia Almansi and Richard Scott and RondeauG and Stephan Rasp and Trevor James Smith and Jemma Stachelek and Matthew Plough and Xianxiang Li}, + title = {{xESMF: Universal regridder for geospatial data}}, + year = {2023}, + publisher = {Zenodo}, + journal = {GitHub repository}, + url = {https://github.com/pangeo-data/xESMF}, + doi = {10.5281/zenodo.4294774} +} + +@misc{tasmantides, + author = {Ashley J. Barnes}, + title = {tasman-tides}, + year = {2024}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/ashjbarnes/tasman-tides} +} + +@misc{mitgcmpy, + author = {Kaitlin Naughten and Dani Jones}, + year = {2023}, + title = {{MITgcm\_python}}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/knaughten/mitgcm_python} +} + +@misc{pyroms, + author = {Kate Hedstrom and contributors}, + year = {2023}, + title = {Pyroms}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/ESMG/pyroms} +} + +@misc{gridtools, + author = {James Simkins and Rob Cermak and Kate Hedstrom and Angus Gibson}, + year = {2021}, + title = {{Earth System Modeling Group (ESMG)} gridtools}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/ESMG/gridtools} +} + +@misc{gebco, + author = {{GEBCO Bathymetric Compilation Group 2023}}, + year = {2023}, + title = {The {GEBCO\_2023 Grid} - a continuous terrain model of the global oceans and land}, + publisher = {NERC EDS British Oceanographic Data Centre NOC}, + url = {https://doi.org/10.5285/f98b053b-0cbc-6c23-e053-6c86abc0af7b}, + doi = {10.5285/f98b053b-0cbc-6c23-e053-6c86abc0af7b} + } + +@misc{glorys, + author = {{Copernicus Marine Services}}, + year = {2024}, + title = {Global Ocean Physics Reanalysis}, + publisher = {Mercator Ocean International}, + url = {https://doi.org/10.48670/moi-00021}, + doi = {10.48670/moi-00021} +} + +@article{polton2023reproducible, + author = {Polton, J. and Harle, J. and Holt, J. and Katavouta, A. and Partridge, D. and Jardine, J. and Wakelin, S. and Rulent, J. and Wise, A. and Hutchinson, K. and Byrne, D. and Bruciaferri, D. and O'Dea, E. and De Dominicis, M. and Mathiot, P. and Coward, A. and Yool, A. and Palmi\'eri, J. and Lessin, G. and Mayorga-Adame, C. G. and Le Guennec, V. and Arnold, A. and Rousset, C.}, + title = {Reproducible and relocatable regional ocean modelling: fundamentals and practices}, + journal = {Geoscientific Model Development}, + volume = {16}, + year = {2023}, + number = {5}, + pages = {1481--1510}, + doi = {10.5194/gmd-16-1481-2023} +} + +@misc{era5, + author = {{Copernicus Climate Change Service}}, + year = {2024}, + title = {{ECMWF Reanalysis v5}}, + publisher = {European Centre for Medium-Range Weather Forecasts}, + url = {https://doi.org/10.48670/moi-00021}, + doi = {10.48670/moi-00021} +} + +@article{egusphere-2024-394, + author = {Ross, A. C. and Stock, C. A. and Koul, V. and Delworth, T. L. and Lu, F. and Wittenberg, A. and Alexander, M. A.}, + doi = {10.5194/egusphere-2024-394}, + journal = {EGUsphere}, + pages = {1--40}, + title = {Dynamically downscaled seasonal ocean forecasts for {North American East Coast} ecosystems}, + url = {https://egusphere.copernicus.org/preprints/2024/egusphere-2024-394/}, + volume = {2024}, + year = {2024} +} + +@article{gmd-16-6943-2023, + author = {Ross, A. C. and Stock, C. A. and Adcroft, A. and Curchitser, E. and Hallberg, R. and Harrison, M. J. and Hedstrom, K. and Zadeh, N. and Alexander, M. and Chen, W. and Drenkard, E. J. and du Pontavice, H. and Dussin, R. and Gomez, F. and John, J. G. and Kang, D. and Lavoie, D. and Resplandy, L. and Roobaert, A. and Saba, V. and Shin, S.-I. and Siedlecki, S. and Simkins, J.}, + doi = {10.5194/gmd-16-6943-2023}, + journal = {Geoscientific Model Development}, + number = {23}, + pages = {6943--6985}, + title = {A high-resolution physical--biogeochemical model for marine resource applications in the northwest {Atlantic (MOM6-COBALT-NWA12 v1.0)}}, + url = {https://gmd.copernicus.org/articles/16/6943/2023/}, + volume = {16}, + year = {2023} +} + +@article{arakawa1977computational, + title = {Computational design of the basic dynamical processes of the {UCLA} general circulation model}, + author = {Arakawa, A. and Lamb, V. R.}, + journal = {Methods in Computational Physics: Advances in Research and Applications}, + volume = {17}, + number = {Supplement C}, + pages = {173--265}, + year = {1977}, + doi = {10.1016/B978-0-12-460817-7.50009-4} +} + +@article{griffies2014elements, + title = {Elements of the modular ocean model ({MOM})}, + author = {Griffies, S. M.}, + journal = {GFDL Ocean Group Tech. Rep.}, + volume = {7}, + pages = {47}, + year = {2014}, + url = {https://mom-ocean.github.io/assets/pdfs/MOM5_manual.pdf} +} + +@article{Herzfeld2011, + author = {M. Herzfeld and M. Schmidt and S. M. Griffies and Z. Liang}, + title = {Realistic test cases for limited area ocean modelling}, + journal = {Ocean Modelling}, + volume = {37}, + number = {1}, + pages = {1-34}, + year = {2011}, + doi = {10.1016/j.ocemod.2010.12.008}, +} + +@article{griffies2020ALE, + author = {Griffies, S. M. and Adcroft, A. and Hallberg, R. W.}, + doi = {10.1029/2019MS001954}, + journal = {Journal of Advances in Modeling Earth Systems}, + number = {10}, + pages = {e2019MS001954}, + title = {A primer on the vertical {Lagrangian}-remap method in ocean models based on finite volume generalized vertical coordinates}, + volume = {12}, + year = {2020} +} + +@misc{silvestri2023oceananigansjl, + title = {Oceananigans.jl: {A} model that achieves breakthrough resolution, memory, and energy efficiency in global ocean simulations}, + author = {Simone Silvestri and Gregory L. Wagner and Christopher Hill and Matin Raayai Ardakani and Johannes Blaschke and Jean-Michel Campin and Valentin Churavy and Navid C. Constantinou and Alan Edelman and John Marshall and Ali Ramadhan and Andre Souza and Raffaele Ferrari}, + year = {2023}, + eprint = {2309.06662}, + archivePrefix = {arXiv}, + primaryClass = {physics.ao-ph}, + doi = {10.48550/arXiv.2309.06662} +} + +@incollection{Gula2022ch8, + title = {Chapter 8 -- Submesoscale processes and mixing}, + editor = {Michael Meredith and Alberto {Naveira Garabato}}, + booktitle = {Ocean Mixing}, + publisher = {Elsevier}, + pages = {181-214}, + year = {2022}, + isbn = {978-0-12-821512-8}, + doi = {10.1016/B978-0-12-821512-8.00015-3}, + author = {Jonathan Gula and John Taylor and Andrey Shcherbina and Amala Mahadevan}, +} + +@incollection{deLavergne2022ch3, + title = {Chapter 3 -- The role of mixing in the large-scale ocean circulation}, + editor = {Michael Meredith and Alberto {Naveira Garabato}}, + booktitle = {Ocean Mixing}, + publisher = {Elsevier}, + pages = {35-63}, + year = {2022}, + isbn = {978-0-12-821512-8}, + doi = {10.1016/B978-0-12-821512-8.00010-4}, + author = {Casimir {de Lavergne} and Sjoerd Groeskamp and Jan Zika and Helen L. Johnson}, +} + +@incollection{Melet2022ch2, + title = {Chapter 2 -- The role of ocean mixing in the climate system}, + editor = {Michael Meredith and Alberto {Naveira Garabato}}, + booktitle = {Ocean Mixing}, + publisher = {Elsevier}, + pages = {5-34}, + year = {2022}, + isbn = {978-0-12-821512-8}, + doi = {10.1016/B978-0-12-821512-8.00009-8}, + author = {Angélique V. Melet and Robert Hallberg and David P. Marshall}, +} + + +@article{Orlanski1976, + author = {I. Orlanski}, + doi = {10.1016/0021-9991(76)90023-1}, + journal = {Journal of Computational Physics}, + number = {3}, + pages = {251-269}, + title = {A simple boundary condition for unbounded hyperbolic flows}, + volume = {21}, + year = {1976}, +} + +@book{richardson1922weather, + title = {Weather prediction by numerical processes}, + author = {Richardson, L. F.}, + publisher = {Cambridge University Press}, + address = {London, UK}, + year = {1922}, + doi = {10.1017/CBO9780511618291} +} + +@article{bleck2002gvc, + author = {Rainer Bleck}, + doi = {10.1016/S1463-5003(01)00012-9}, + journal = {Ocean Modelling}, + number = {1}, + pages = {55-88}, + title = {An oceanic general circulation model framed in hybrid isopycnic-{Cartesian} coordinates}, + volume = {4}, + year = {2002} +} + + +@misc{CEFIregional, + author = {Yi-Cheng Teng and Andrew Ross and Theresa Morrison}, + title = {{CEFI-regional-MOM6: Essential tools, XML files, and source codes for collaborators of the Climate, Ecosystems, and Fisheries Initiative (CEFI) to conduct simulations}}, + year = {2023}, + publisher = {GitHub}, + journal = {GitHub repository}, + url = {https://github.com/NOAA-GFDL/CEFI-regional-MOM6} +} + +@article{ACCESS-OM2, + author = {Kiss, A. E. and Hogg, A. McC. and Hannah, N. and Boeira Dias, F. and Brassington, G. B. and Chamberlain, M. A. and Chapman, C. and Dobrohotoff, P. and Domingues, C. M. and Duran, E. R. and England, M. H. and Fiedler, R. and Griffies, S. M. and Heerdegen, A. and Heil, P. and Holmes, R. M. and Klocker, A. and Marsland, S. J. and Morrison, A. K. and Munroe, J. and Nikurashin, M. and Oke, P. R. and Pilo, G. S. and Richet, O. and Savita, A. and Spence, P. and Stewart, K. D. and Ward, M. L. and Wu, F. and Zhang, X.}, + doi = {10.5194/gmd-13-401-2020}, + journal = {Geoscientific Model Development}, + number = {2}, + pages = {401--442}, + title = {{ACCESS-OM2 v1.0}: a global ocean--sea ice model at three resolutions}, + volume = {13}, + year = {2020} +} + +@article{Tsujino2018, + author = {Hiroyuki Tsujino and Shogo Urakawa and Hideyuki Nakano and R. Justin Small and Who M. Kim and Stephen G. Yeager and Gokhan Danabasoglu and Tatsuo Suzuki and Jonathan L. Bamber and Mats Bentsen and Claus W. B{\"o}ning and Alexandra Bozec and Eric P. Chassignet and Enrique Curchitser and Fabio {Boeira Dias} and Paul J. Durack and Stephen M. Griffies and Yayoi Harada and Mehmet Ilicak and Simon A. Josey and Chiaki Kobayashi and Shinya Kobayashi and Yoshiki Komuro and William G. Large and Julien {Le Sommer} and Simon J. Marsland and Simona Masina and Markus Scheinert and Hiroyuki Tomita and Maria Valdivieso and Dai Yamazaki}, + doi = {10.1016/j.ocemod.2018.07.002}, + journal = {Ocean Modelling}, + pages = {79-139}, + title = {{JRA-55} based surface dataset for driving ocean--sea-ice models ({JRA55}-do)}, + volume = {130}, + year = {2018}, +} + +@article{Silvestri2024GPU, + author = {Simone Silvestri and Gregory L. Wagner and Navid C Constantinou and Christopher Hill and Jean-Michel Campin and Andre Nogueira Souza and Siddhartha Bishnu and Valentin Churavy and John C Marshall and Raffaele Ferrari}, + title = {A {GPU}-based ocean dynamical core for routine mesoscale-resolving climate simulations}, + journal = {ESS Open Archive}, + year = {2024}, + doi = {10.22541/essoar.171708158.82342448/v1}, +} diff --git a/paper/paper.md b/paper/paper.md new file mode 100644 index 00000000..b689ad96 --- /dev/null +++ b/paper/paper.md @@ -0,0 +1,132 @@ +--- +title: 'regional-mom6: A Python package for automatic generation of regional configurations for the Modular Ocean Model 6' + +tags: + - Python + - ocean modeling + - regional modeling + - mom6 +authors: + - name: Ashley J. Barnes + orcid: 0000-0003-3165-8676 + affiliation: "1, 2" # (Multiple affiliations must be quoted) + - name: Navid C. Constantinou + orcid: 0000-0002-8149-4094 + affiliation: "1, 2, 3, 4" + - name: Angus H. Gibson + orcid: 0000-0001-7577-3604 + affiliation: 1 + - name: Andrew E. Kiss + orcid: 0000-0001-8960-9557 + affiliation: "1, 2" + - name: Chris Chapman + orcid: 0000-0002-6030-1951 + affiliation: 5 + equal-contrib: true + - name: John Reilly + orcid: 0000-0003-4001-0230 + affiliation: 6 + equal-contrib: true + - name: Dhruv Bhagtani + orcid: 0000-0002-1222-375X + affiliation: "1, 2" + equal-contrib: true + - name: Luwei Yang + orcid: 0000-0001-8570-7424 + affiliation: "1, 2" + equal-contrib: true +affiliations: + - name: Australian National University, Australia + index: 1 + - name: ARC Centre of Excellence for Climate Extremes, Australia + index: 2 + - name: University of Melbourne, Australia + index: 3 + - name: ARC Centre of Excellence for the Weather of the 21st Century, Australia + index: 4 + - name: CSIRO Environment, Hobart, Tasmania, Australia + index: 5 + - name: University of Tasmania, Australia + index: 6 + +date: 8 August 2024 +bibliography: paper.bib +--- + + +# Summary + +`regional-mom6` is a Python package that provides an easy and versatile way to set up regional configurations of the Modular Ocean Model version 6 (MOM6). + +## Regional ocean modeling + +In the ocean, fast and small-scale motions (from ~100m to ~100km varying at time scales of hours to days) play an important role in shaping the large-scale ocean circulation and climate (length scales ~10,000km varying at decadal time scales) [@Melet2022ch2; @deLavergne2022ch3; @Gula2022ch8]. +Despite the increase in computational power and the use of graphical processing units that can bring breakthrough performance and speedup [@Silvestri2024GPU], there are always processes, boundary, or forcing features that are smaller than the model's grid spacing and, thus, remain unresolved in global ocean models. +Regional ocean models can be run at higher resolutions while limiting the required computational resources. + +A regional ocean model simulates the ocean only in a prescribed region, which is a subset of the global ocean. +To do that, we need to apply open boundary conditions at the region's boundaries, that is, we need to impose conditions that mimic the oceanic flow that we are not simulating [@Orlanski1976]. +For example, \autoref{fig:tasman} shows the surface currents from a regional ocean simulation of the Tasman sea that was configured using the `regional-mom6` package. +The boundaries of the domain depicted in \autoref{fig:tasman} are forced with the ocean flow from a global ocean reanalysis product. +Higher-resolution regional ocean models improve the representation of smaller-scale motions, such as tidal beams, mixing, mesoscale and sub-mesoscale circulation, as well as the oceanic response to smaller-scale bathymetric or coastal features (such as headlands, islands, sea-mounts, or submarine canyons) and surface forcing (such as atmospheric fronts and convective storms). +Regional modelling further allows for the "downscaling" of coarse-resolution global ocean or climate models, permitting the representation of the variation in local conditions that might otherwise be contained within only a few (or even a single!) model grid cells in a global model. + +## Modular Ocean Model version 6 + +MOM6 is a widely-used open-source, general circulation ocean--sea ice model, written in Fortran [@Adcroft2019MOM6]. +MOM6 contains several improvements over its predecessor MOM5 [@griffies2014elements], including the implementation of the Arbitrary-Lagrangian-Eulerian vertical coordinates [@bleck2002gvc; @griffies2020ALE], more efficient tracer advection schemes, and state-of-the art parameterizations of sub-grid scale physics. +Pertinent for our discussion, MOM6 provides support for open boundary conditions and thus is becoming popular for regional ocean modeling studies (see, e.g., @gmd-16-6943-2023, @egusphere-2024-394) in addition to global configurations. +However, setting up a regional configuration for MOM6 can be challenging, time consuming, and often involves using several programming languages, a few different tools, and also manually editing/tweaking some input files. +The `regional-mom6` package overcomes these difficulties, automatically generating a regional MOM6 configuration of the user's choice with relatively simple domain geometry, that is, rectangular domains. + +![Snapshot of the ocean surface speed from a two-tier, one-way nested regional ocean configurations of the East Australian Current. The outer regional configuration (dashed region) uses 1/10ᵒ horizontal resolution, 75 vertical levels, and is forced by the output from the global ocean--sea ice model at 1/10ᵒ horizontal resolution (ACCESS-OM2-01; @ACCESS-OM2). The inner regional configuration (dotted region) uses 1/30ᵒ horizontal resolution, 100 vertical levels, and is forced with the outer regional model. All simulations share a common inter-annual atmospheric forcing from 1990 to 2018 provided by the JRA55-do reanalysis [@Tsujino2018].\label{fig:tasman}](nested-regional-mom6.pdf){ width=85% } + +## `regional-mom6` + +The `regional-mom6` package takes as input various datasets that contain the ocean initial condition, the boundary forcing (ocean and atmosphere) for the regional domain, and the seafloor topography. +The input datasets can be on the Arakawa A, B, or C grids [@arakawa1977computational]; the package performs the appropriate interpolation using `xESMF` [@xesmf] under the hood, to put the everything on the C grid required by MOM6. +This base grid for the regional configuration can be constructed in two ways, +either by the user defining a desired resolution and choosing between pre-configured options, +or by the user providing pre-existing horizontal and/or vertical MOM6 grids. +The user can use MOM6's Arbitrary-Lagrangian-Eulerian vertical coordinates, regardless of the native vertical coordinates of the boundary forcing input. +The package automates the re-gridding of all the required forcing input, takes care of all the metadata encoding, generates the regional grid, and ensures that the final input files are in the format expected by MOM6. +Additionally, the tricky case of a regional configuration that includes the 'seam' in the longitude of the raw input data (e.g., a 10ᵒ-wide regional configuration centred at Fiji (178ᵒE) and forced by input with native longitude coordinate in the range 180ᵒW--180ᵒE) is handled automatically, removing the need for any preprocessing of the input data. +This automation allows users to set up a regional MOM6 configuration using only Python and from the convenience of a single Jupyter notebook. +@Herzfeld2011 provide rules of thumb to guide the user in setting regional grid parameters such as the resolution. + +`regional-mom6` is installable via `conda`, it is continuously tested, and comes with extensive documentation including tutorials and examples for setting up regional MOM6 configurations using publicly-available forcing and bathymetry datasets (namely, the GLORYS dataset for ocean boundary forcing [@glorys], the ERA5 reanalysis for atmospheric forcing [@era5], and the GEBCO dataset for seafloor topography [@gebco]). + +With the entire process for setting up a regional configuration streamlined to run within a Jupyter notebook, the package dramatically reduces the barrier-to-entry for first-time users, or those without a strong background in Fortran, experience in compiling and running scripts in terminals, and manipulating netCDF files. +Besides making regional modelling with MOM6 more accessible, our package can automate the generation of multiple experiments (e.g., a series of perturbation experiments), saving time and effort, and improving reproducibility. + +We designed `regional-mom6` with automation of regional configurations in mind. +However, the package's code design and modularity make more complex configurations possible since users can use their own custom-made grids with more complex boundaries and construct the boundary forcing terms one by one. + +# Statement of need + +The learning curve for setting up a regional ocean model can be steep, and it is not obvious for a new user what inputs are required, nor the appropriate format. +In the case of MOM6, there are several tools scattered in Github repositories, for example those collected in Earth System Modeling Group grid tools [@gridtools]. +Also, there exist several regional configuration examples but they are hardcoded for particular domains, specific input files, and work only on specific high-performance computing machines (e.g., @gmd-16-6943-2023). + +Until now there has been no one-stop-shop for users to learn how to get a regional MOM6 configuration up and running. +Users are required to use several tools in several programming languages and then modify -- sometimes by hand -- some of the input metadata to bring everything into the format that MOM6 expects. +Many parts of this process are not documented, requiring users to dig into the MOM6 Fortran source code. +Recently, the Climate, Ecosystems and Fisheries Initiative gathered some tools into a single repository [@CEFIregional] but, at the moment, they are written for specific inputs and computational environment and not installable as a Python package. +Other ocean models have packages to aid in regional configuration setup, for example `Pyroms` [@pyroms] for the Regional Oceanic Modelling System (ROMS; @shchepetkin2005regional) and `MITgcm_python` [@mitgcmpy] for the Massachusetts Institute of Technology General Circulation Model (MITgcm; @marshall1997finite). +With MOM6's growing user base for regional applications, there is a need for a platform that walks users through regional domain configuration from start to finish and, ideally, automates the process on the way. +Other than reducing the barrier-to-entry, automating the regional configuration process renders the workflow much more reproducible; see discussion by @polton2023reproducible. +`regional-mom6` precisely meets these needs. + +By having a shared set of tools that the community can work with and contribute to, this package also facilitates collaboration and knowledge-sharing between different research groups. +Using a shared framework for setting up regional models, it is easier to compare and contrast examples of different experiments and allows for users to gain intuition for generating their chosen domain. + +`regional-mom6` package can also be used for educational purposes, for example as part of course curricula. +With the technically-challenging aspects of setting up a regional configuration now being automated by the `regional-mom6` package, students can set up and run simple MOM6 regional configurations and also change parameters like the model's resolution or the forcing, run again, and see how these parameters affect the ocean flow. + +# Acknowledgements + +We thank the vibrant community of the Consortium for Ocean–Sea Ice Modeling in Australia ([cosima.org.au](https://cosima.org.au)) and also Josué Martínez-Moreno and Callum Shakespeare for useful discussions during the development of this package. +We acknowledge support from the Australian Research Council under DECRA Fellowship DE210100749 (N.C.C.), grant LP200100406 (A.E.K.), and the Center of Excellences for Climate Extremes CE170100023 and for the Weather of the 21st Century CE230100012. +We would also like to acknowledge the code and notes by James Simkins, Andrew Ross, and Rob Cermak, which helped us to troubleshoot and improve the algorithms in our package. Last, we thank the three reviewers and the editor for their efforts and remarks. + +# References diff --git a/paper/paper.pdf b/paper/paper.pdf new file mode 100644 index 00000000..e560f6c5 Binary files /dev/null and b/paper/paper.pdf differ