Oceananigans.jl and ClimaOcean.jl

Warning:

This is compicated code and many packages are involved. At this early stage of model evolution bugs are expected and there is a community of "watchers" and experts fixing problems. See for example ClimaOcean.jl issue #327 or CUDA.jl issue #4036. Thus at this stage familiarizing with the type of julia code which is involved and the output plots where available has value. Later running the code without error by paying attention to the versions of julia and some packages will become important. Participating in the effort to fix bugs is a big step which some readers will want to take. Detecting bugs by attempting new applications is very worthwhile, but first the robustness of the existing examples needs to be ensured.
(These comments were written in mid Juanuary 2025.)

(The following documentation in this section was written in mid December 2024.)

There is extensive documentation for the package Oceananigans with many links here.

Oceanigans Examples:

These examples are given to explore the way in which the Oceananigans package can be used to examine local properties of sea water. Below in the section "ClimaOcean Examples" more global examples will be provided once they have been verified.

These examples use the graphics package CairoMakie. To run them on a GPU some adjustments need to be made. For example the CUDA package must be used and instead of CairoMakie, the closely related GLMakie. The final example is for the reader to experiment interactively with a simple Julia function readme_example(arch, time, npts) to compare the performance of the CPU and GPU, if its available. It is taken from the Oceananigans.jl README.md documentation.

Hints for running the examples: We make no assumptions regarding special environments for running Julia. Our method of considering the examples is to first download the example code into a local directory or folder. Then run Julia in a command window with this local directory with whatever command line flags the user desires, including none. Open the example code in an editor, such as Notepad++, and then drag and drop into Julia blocks of code, such as those between begin and end in the "Adjusted version" of the example. Output will appear either on the screen such as plots or in the local directory.

Hints for obtaining help: Many Julia and Oceanigans methods (and their functions) amd structures appear in the examples. To get the extensive online help which is available, first ensure that "using Oceananigans, ClimaOcean" is invoked. In addition, if the GPU is being investigated then "using CUDA" should be invoked. Then Julia's normal help environment can be entered with a question mark on an othwise empty line. Then type the name of the symbol for which help is sought. A list of names is given on this page below. The descriptions and options are often many and might be bewildering at first. In the examples only a small number of options are explored.

The examples in this section are taken from the Oceananigans.jl github file system.

  1. One Dimensional Diffusion:

    This simple example of one dimensional diffusion illustrates the way in which Oceanigans applications are normally structured. First the package environment, then the grid, model, initial condition, visualizing the model data with CairoMakie, running the simulation, and finally making a movie of the resulting flow. Roughly speaking, this progression is exhibited in each example.

    Code and documentation links:

  2. Two Dimensional Turbulence

    In this example, we initialize a random velocity field and observe its turbulent decay in a two-dimensional domain. This example demonstrates how to run a model with no tracers and no buoyancy model. and how to use computed `Field`s to generate output.

    Code and documentation links:

  3. Baroclinic Adjustment

    In this example, we simulate the evolution and the passage to equlibrium of a baroclinically unstable front.

    Code and documentation links:

  4. Internal Wave

    In this example, we initialize an internal wave packet in two-dimensions and watch it propagate. This example illustrates how to set up a two-dimensional model, set initial conditions, and how to use the structure BackgroundField.

    Code and documentation links:

  5. Tilted Bottom Boundary Layer

    This example simulates a two-dimensional oceanic bottom boundary layer in a domain that's tilted with respect to gravity. We simulate the perturbation away from a constant along-slope (y-direction) velocity constant density stratification. This perturbation develops into a turbulent bottom boundary layer due to momentum loss at the bottom boundary modeled with a quadratic drag law.

    The example illustrates the effects of changing the direction of gravitational acceleration in the buoyancy model and changing the axis of rotation for Coriolis forces.

    Code and documentation links:

  6. Shallow Water Bickley Jet

    This is an example of an unstable Bickley jet in a Shallow Water model.

    It uses Oceananigans.jl's ShallowWaterModel to simulate the evolution of an unstable, geostrophically balanced, Bickley jet The example is periodic in x with flat bathymetry and uses the conservative formulation of the shallow water equations. The initial conditions superpose the Bickley jet with small-amplitude perturbations. See ["The nonlinear evolution of barotropically unstable jets," J. Phys. Oceanogr. (2003)](https://doi.org/10.1175/1520-0485(2003)033<2173:TNEOBU>2.0.CO;2) for more details on this problem.

    The mass transport (uh, vh) is the prognostic momentum variable in the conservative formulation of the shallow water equations, where (u, v) are the horizontal velocity components and ``h`` is the layer height.

  7. Internal Tide

    In this example we show how an internal tide is generated from a barotropic tidal flow flowing back and forth over a sea bottom mount.

    Code and documentation links:

  8. Convecting Plankton

    This is an example modelling plankton mixing and blooming.

    We simulate the mixing of phytoplankton by convection that decreases in time and eventually shuts off, thereby precipitating a phytoplankton bloom. A similar scenario was simulated by [Taylor and Ferrari (2011)](https://aslopubs.onlinelibrary.wiley.com/doi/abs/10.4319/lo.2011.56.6.2293), providing evidence that the ["critical turbulence hypothesis"](https://en.wikipedia.org/wiki/Critical_depth#Critical_Turbulence_Hypothesis) explains the explosive bloom of oceanic phytoplankton observed in spring.

    The phytoplankton in our model are advected, diffuse, grow, and die according to

    t P + (v · ∇) P - κ ∇²P = (μ₀ e(z / λ) - m) P
    where v is the turbulent velocity field, κ is an isotropic diffusivity, μ₀ is the phytoplankton growth rate at the surface, λ is the scale over which sunlight attenuates away from the surface, and m is the mortality rate of phytoplankton due to viruses and grazing by zooplankton. We use Oceananigans' Forcing abstraction to implement the phytoplankton dynamics described by the right side of the phytoplankton equation above.

    The example demonstrates how to:

    Code and documentation links:

  9. Ocean Wind Mixing And Convection

    This example simulates mixing by three-dimensional turbulence in an ocean surface boundary layer driven by atmospheric winds and convection. It demonstrates how to:

    Code and documentation links:

  10. Horizontal Convection

    In this example a non-uniform buoyancy is imposed on top of an initially resting fluid. It demonstrates how to:

    Code and documentation links:

  11. Langmuir Turbulence

    This example implements a Langmuir turbulence simulation reported in section 4 of [Wagner et al., "Near-inertial waves and turbulence driven by the growth of swell", Journal of Physical Oceanography (2021)](https://journals.ametsoc.org/view/journals/phoc/51/5/JPO-D-20-0178.1.xml)

    The example demonstrates how to:

    Code and documentation links:

  12. Kelvin Helmholtz Instability

    This example models the classical Kelvin-Helmholtz instability for two fluids, one on top of the other, moving in different directions in the (x,z) plane.

    Code and documentation links:

  13. Testing the GPU

    This simple example is of a Julia function readme_example(arch, time, npts) to compare the performance of the readers CPU and GPU. The first argument should be either CPU() or GPU(), the second the stop time, and the third the number of grid points in the x and y directions. Note that a comment has been made that for the GPU to perform better than the CPU there must be at least 10 million grid points, for example npts=104.

    Code link: An adjusted version of the original example Julia code is linked here.

The package ClimaOcean.jl

ClimaOcean is a package under development with a first example given here and more to come later. It supports the development of global as well as local climate models , based on bathymetry (heights and depths) from NASAs ECCO2 data set, the Japanese 55 year reanalysis JRA55-do data set, and the Julia packages Oceananigans.jl and CairoMakie.jl or GLMakie.jl. Most examples have been adaptedto be adapted to run on GPUs with little change other than a significant improvement in run wall-time.

To see an explanation of the differences between Oceanigans and ClimaOcean, click here and scroll down below the Installation instructions.

Users need to be aware that this package, ClimaOcean, is in a state of evolution, and the latest version ClimaOcean#main is normally more robust than earlier versions.

ClimaOcean Examples:

The first set of examples should be run to check whether the users connections to data are working. Facilities for Windows operating systems downloading to Julia are currently under development. To obtain ECCO data credentials with NASA are required. More information is given with the example "Inspect ECCO Data". The Preliminary Examples can be run on a CPU or GPU. The final set Global Ocean Modelling must be run on a GPU or GPUs.

The examples are in the github folder linked here. Note that some examples from github may be removed and/or replaced. Hence, we have included copies of the examples used to produce given outputs with the heading "Possibly adjusted example code".

Preparatory steps before attempting to run these examples in Julia for the first time

  1. Make a directory with path, P say. in your filesystem with full access and change to that directory.

  2. Using a suitable shell (for example the Windows Power Shell or Linux Bash shell) clone the ClimaOcean.jl package:
    shell> git clone https://github.com/CliMA/ClimaOcean.jl.git

  3. Signup with NASA and obtain ECCO credentials. See src/DataWrangling/ECCO in the ClimaOcean.jl code file system.

  4. In ~/.julia make a directory config and a file startup.jl in that directory with the lines
    ENV["ECCO_USERNAME"]="your NASA username"
    ENV["ECCO_PASSWORD"]="your ECCO password as given by NASA"
    If config/startup.jl already exists add the lines to the file.

  5. In the cloned system make a directory src/myexamples . If you are running the examples in this section on your own computer then you should first download the code into myexamples. Suppose the example is example.jl

  6. Ensure the ClimaOcean.jl is the most recent by following the instructions in the documentation:
    julia> using Pkg; Pkg.add(url="https://github.com/CliMA/ClimaOcean.jl.git, rev="main"); Pkg.instantiate()

    Change to the myexamples directory and then run julia> julia --project example.jl . The output should appear in your myexamples directory.

You may need to repeat some of these sets. For example if ClimaOcean is updated or if your ECCO credentials expire.

If there are difficulties downloading data onto a Windows file system

There should not be such problems, but the user may need to do this. If so knowing that the data for ClimaOcean is stored in ~/.julia/scratchspaces/[made up subdirectory for ClimaOcean]/[subdirectory] where subdirectory is for example Bathymetry, ECCO, JRA55 etc. A suitable function is urlread given in the file Windows_downloader.jl linked here.. This download needs to be performed only once, or maybe when the data is updated.

To find the filenames and url's for the datafiles you may need to explore the source code for ClimaOcean.jl. Some of these are given in Windows_downloader.jl . Preliminary Examples:

Generate Atmosphere Dataset:

Outline: This code uses the ClimaOcean function JRA55_field_time_series to download data for 55 years for specific humidity, temperature and sea level pressure to provide an atmosphere for ocean modelling.

The JRA55 dataset which includes 55 years of measured data for the listed variables with values for the whole earth:

For details, see the article by K. D. Stewart et al. entited "JRA55-do-based repeat year forcing datasets for driving ocean-sea-ice models" Ocean Modelling, 2020 accessible here.

Original example code has been removed or moved.

Possibly adjusted example code: generate_atmos_dataset.jl

Output: There is no output to the screen. The dataset is written to the file atmospheric_state.jld2 in the users current directory.

Generate Bathymetry:

Outline: This code shows how we can configure an imersed boundary grid with realistic bathymetry for the Mediterranean sea. It uses the Oceananigans package for the LatitudeLongitudeGrid and the Field functions of ClimaOcean to download and regrid the bathymetry. Its uses the graphics package CairoMakie, which gives publication quality graphics, to visualase the output.
The bathymetry data is from NASAs ET0P01 dataset which is downloaded by the Oceananigans function regrid_bathymetry. The first download obtains the data from the NASA file system. This is stored in a subdirectory of .julia/scratchspaces for ClimaOcean data files, data which is then used on subsequent times. Note that it is a large file, about 0.5 Gbytes.

Original example code: generate_bathymetry.jl

Possibly adjusted example code: generate_bathymetry.jl

Output plot: different_bottom_heights.png
The output plot has 3 components, giving values for the depths called h_rough, h_smooth and h_one_basin. h_rough is plotted from the original data depths, h_smooth a result of 40 interpolation passes and h_one_basin the result of including at most one water volume inclosed completely by land. Spot the differences!

Generate surface fluxes:

Outline: This code computes and plots surface fluxes from a prescribed ocean and atmosphere. It uses ClimaOcean's uses formulae to estimate the surface exchange of momentum, heat, and water vapor between the atmosphere and the ocean.
It demonstrates the turbulent surface flux calculations performed in ClimaOcean using ECCO2 data for the ocean and JRA55 data for the atmosphere.

We need the ClimaOcean DataWrangling modules: ECCO2 and JRA55. We also need Oceananigans for the ImmersedBoundaryGrid and Field utilities, and CairoMakie to plot.

Important note: you will need ECCO credentials and a NASA login account. See here for instructions.

Original example code: generate_surface_fluxes.jl

Possibly adjusted example code: generate_surface_fluxes.jl

Output plots: ecco_continents.png
This plot demonstrate the effect of using a imersed boundary mask.
fluxes.png
This plot has 5 components: the sensible heat flux, the latent heat flux, the zonal (x-direction) wind stress on the ocean, the meridional wind stress (y-direction), and teh water vapour flux.

Inspect JRA55 data:

Outline: This code downloads if necessary the JRA55 data for downwelling_shortwave_radiation, and relative humidity using the ClimaOcean function JRA55_field_time_series. Plotting is done using the graphics package GLMakie so that there is mouse control to rotate to globe and reposition the view point in the case of the snapshot inspect_JRA55_data.png. To do this the user needs to first run the code as far as the line display(fig), reposition the vew point using the mouse, and then make the movie JRA55_data.mp4. Note that this movie takes quite a long time to gather the needed data, but the result is worth waiting for!

Code: inspect_JRA55_data.jl

Possibly adjusted example code: inspect_JRA55_data.jl

Output plots:
inspect_JRA55_data.png
A snapshot of the data from day 0 in 1993.

JRA55_data.mp4
A movie with a standard orthographic projection.

JRA55_data_9_7.mp4
A movie with the viewpoint over the south pole.

To obtain output for pairs of variables other than downwelling_shortwave_radiation and relative humidity, the reader needs to edit the code inspect_JRA55_data.jl and change the range for each variables which appears in the plotting sections.

Inspect ECCO data:

Outline: This code provides a first look at ECCO data. Note that credentials are required to obtain this from NASA. See here for instructions.

ClimaOcean can download and utilize data from the ECCO state estimate, which stands for "Estimating the Circulation and Climate of the Ocean".

The example code shows how to download three-dimensional temperature and salinity fields from the ECCO data repository, and makes a short animation to showcase the content of the fields.

The package Oceananigans is used for Field utilities, CairoMakie for plotting, Printf for formatted labeling, and ClimaOcean to actually download and construct the ECCO fields.

Original code has been removed or moved.

Possibly adjusted example code: inspect_ecco_data.jl

Output:
ECCO_continents.png

ECCO_temperature_salinity.mp4

Global Ocean Modelling:

Single Column Simulation:

Outline: This code performs a single-column ocean simulation with forcing provided by the JRA55 re-analysis. The evolution of an ocean water column forced by an atmosphere derived from the JRA55 re-analysis is simulated over a month commencing 1 October 1992.
The simulated column is located at ocean station Papa at (144.9ᵒ W and 50.1ᵒ N). For background information about this NOAA weather station click here.

Code: single_column_os_papa_simulation.jl

Possibly adjusted example code: single_column_os_papa_simulation.jl

Output:
single_column_profiles.mp4
This gives a single plot with many component sub-plots. These include the time evolution in the column of wind stress, heat flux, water velocities, surface temperature, freshwater volumn flux, and surface salinity.

Example of a near global ocean simulation from the documentation:

Outline: This code performs a near global ocean simulation using the code from the initial ClimaOcean.jl documentation following the heading "A core abstraction: ClimaOcean.OceanSeaIceModel". This can be found here. The code is rewritten without the comments (which are strongly recommended to be consulted and studied). It should be run on a GPU.

Possibly adjusted example code: ClimaOceanDoc.jl

Plot output: doc_example_surface_speed.png
This output is less detailed that the plot in the github documentation for ClimaOcean.jl. for a reason yet to be determined. It is either a bug or the result of running the code with different input settings.

Near Global Ocean Simulation:

Outline: This code sets up and runs a near-global ocean simulation using the packages Oceananigans.jl and ClimaOcean.jl. It covers latitudes from 75°S to 75°N with a horizontal resolution of 1/4 degree and 40 vertical levels and should be run on a GPU. The simulation's results are visualized with the CairoMakie.jl package.

The initial setup with package imports:

First the required Julia packages for visualization (CairoMakie), ocean modeling (Oceananigans, ClimaOcean), and handling dates and times (CFTime, Dates) are imported via the "using" statements. These packages provide the foundational tools for setting up the simulation environment, including grid setup, physical processes modeling, and data visualization. It should be run on a GPU.

Code: near_global_ocean_simulation.jl

Possibly adjusted example code: near_global_ocean_simulation.jl

Output:
snapshot_near_global.png

near_global_ocean_surface.mp4
The output video has three components giving the ocean surface speed, temperature and turbulent kinetic energy.

Some Oceanigans and ClimaOcean methods and structures

  1. Grids

  2. Models

  3. Simulations

  4. Numerical Solvers

  5. Turbulence Closures

  6. Boundary Conditions