
Versatile Ocean Simulation in Pure Python¶
Veros, the versatile ocean simulator, aims to be the swiss army knife of ocean modeling. It is a full-fledged GCM that supports anything between highly idealized configurations and realistic set-ups. Thanks to its interplay with Bohrium, Veros runs efficiently on your laptop, gaming PC (with experimental GPU support through OpenCL & CUDA), and small cluster. In short, we want to enable ocean modelling with a clear focus on simplicity, usability, and adaptability.
If you want to learn more about the background and capabilities of Veros, you should check out A short introduction to Veros. If you are already convinced, you can jump right into action, and learn how to get started instead!
A short introduction to Veros¶
The vision¶
Veros is an adaptation of pyOM2 (v2.1.0), developed by Carsten Eden (Institut für Meereskunde, Hamburg University). In contrast to pyOM2, however, this implementation does not rely on a Fortran backend for computations - everything runs in pure Python, down to the last parameterization. We believe that using this approach it is possible to create an open source ocean model that is:
Easy to access: Python modules are simple to install, and projects like Anaconda are doing a great job in creating platform-independent environments.
Easy to use: Anyone with some experience can use their favorite Python tools to set up, control, and post-process Veros.
Easy to verify: Python code tends to be concise and easy to read, even for people with little practical programming experience. This enables a wide range of people to spot errors in our code, solidifying it in the process.
Easy to modify: Due to the popularity of Python, its dynamic code structure, and OOP-capabilities, Veros can be extended and modified with minimal effort.
However, using Python over a compiled language like Fortran usually comes at a high computational cost. We try to overcome this gap for large models by providing an interface to Bohrium, a framework that acts as a high-performance replacement for NumPy. Bohrium takes care of all parallelism in the background for us, so we can concentrate on writing a nice, readable ocean model.
In case you are curious about how Veros is currently stacking up against pyOM2 in terms of performance, you should check out our benchmarks.
Features¶
Note
This section provides a quick overview of the capabilities and limitations of Veros. For a comprehensive description of the physics and numerics behind Veros, please refer to the documentation of pyOM2. You can also obtain a copy of the PDF documentation here
.
The model domain¶
The numerical solution is calculated using finite differences on an Arakawa C-grid, which is staggered in every dimension. Tracers (like temperature and salinity) are calculated at different positions than zonal, meridional, and vertical fluxes (like the velocities u, v, and w). The following figure shows the relative positions of the so-called T, U, V, and ζ grid points (W not shown):
The structure of the Arakawa C-grid.¶
Veros supports both Cartesian and pseudo-spherical (i.e., including additional metric terms) coordinate systems. Islands or holes in the domain are fully supported by the streamfunction solver. Zonal boundaries can either be cyclic or regraded as walls (with free-slip boundary conditions).
Available parameterizations¶
At its core, Veros currently offers the following solvers, numerical schemes, parameterizations, and closures:
- Surface pressure:
a high-performance streamfunction solver via an iterative Poisson solver
- Equation of state:
the full 48-term TEOS equation of state
various linear and nonlinear model equations from [Vallis2006]
- Friction:
harmonic or biharmonic lateral friction
linear or quadratic bottom friction
interior Rayleigh friction
explicit or fully implicit harmonic vertical friction
- Advection:
a classical second-order central difference scheme
a second-order scheme with a superbee flux-limiter
- Diffusion:
harmonic or biharmonic lateral diffusion
explicit or implicit harmonic vertical diffusion
- Isoneutral mixing:
lateral mixing of tracers along neutral surfaces following [Griffies1998] (optional)
- Internal wave breaking:
IDEMIX as in [OlbersEden2013] (optional)
- EKE model (eddy kinetic energy):
meso-scale eddy mixing closure after [Gent1995], either with constant coefficients or calculated using the prognostic EKE closure by [EdenGreatbatch2008] (optional)
- TKE model (turbulent kinetic energy):
prognostic TKE model for vertical mixing as introduced in [Gaspar1990] (optional)
Diagnostics¶
Diagnostics are responsible for handling all model output, runtime checks of the solution, and restart file handling. They are implemented in a modular fashion, so additional diagnostics can be implemented easily. Already implemented diagnostics handle snapshot output, time-averaging of variables, monitoring of energy fluxes, and calculation of the overturning streamfunction.
For more information, see Diagnostics.
Pre-configured model setups¶
Veros supports a wide range of model configurations. Several setups are already implemented that highlight some of the capabilities of Veros, and that serve as a basis for users to set up their own configuration: Setup gallery.
Current limitations¶
Veros is still in early development. There are several open issues that we would like to fix later on:
- Physics:
Veros does not yet implement any of the more recent pyOM2.2 features such as the ROSSMIX parameterization, IDEMIX v3.0, open boundary conditions, or cyclic meridional boundaries. It neither implements all of pyOM2.1’s features - missing are e.g. the non-hydrostatic solver, IDEMIX v2.0, and the surface pressure solver.
Since the grid is required to be rectilinear, there is currently no natural way to handle the singularity at the North Pole. The northern and southern boundaries of the domain are thus always “walls”.
There is currently no ice sheet model in Veros. Some realistic setups employ a simple ice mask that cut off atmospheric forcing for water that gets too cold instead.
- Technical issues:
For the time being, Veros’ dynamical core is still more or less a direct port of PyOM2. This means that numerics and physics are still tightly coupled, which makes for a far from optimal user experience. In a future version of Veros, we would like to introduce additional abstraction to make the core routines a lot more readable than they are now.
References¶
- EdenGreatbatch2008
Eden, Carsten, and Richard J. Greatbatch. “Towards a mesoscale eddy closure.” Ocean Modelling 20.3 (2008): 223-239.
- OlbersEden2013
Olbers, Dirk, and Carsten Eden. “A global model for the diapycnal diffusivity induced by internal gravity waves.” Journal of Physical Oceanography 43.8 (2013): 1759-1779.
- Gent1995
Gent, Peter R., et al. “Parameterizing eddy-induced tracer transports in ocean circulation models.” Journal of Physical Oceanography 25.4 (1995): 463-474.
- Griffies1998
Griffies, Stephen M. “The Gent–McWilliams skew flux.” Journal of Physical Oceanography 28.5 (1998): 831-841.
- Vallis2006
Vallis, Geoffrey K. “Atmospheric and oceanic fluid dynamics: fundamentals and large-scale circulation.” Cambridge University Press, 2006.
- Gaspar1990
Gaspar, Philippe, Yves Grégoris, and Jean‐Michel Lefevre. “A simple eddy kinetic energy model for simulations of the oceanic vertical mixing: Tests at station Papa and Long‐Term Upper Ocean Study site.” Journal of Geophysical Research: Oceans 95.C9 (1990): 16179-16193.
Getting started¶
Installation¶
Using pip (multi-platform)¶
Note
You should only install Veros via pip if you want to get going as quickly as possible, and do not plan to access or modify the Veros source code. The prefered way to install Veros is through Anaconda (see below).
If you already have Python installed, the quickest way to get a working Veros installation is to run:
$ pip install veros --user
and optionally:
$ pip install bohrium --user
to use Veros with Bohrium (Linux and OSX only).
Using Anaconda (multi-platform, recommended)¶
Download and install Anaconda. Make sure to grab the 64-bit version of the Python interpreter.
Clone the Veros repository:
$ git clone https://github.com/team-ocean/veros.git
Create a new conda environment for Veros, and install all relevant dependencies, by running
$ conda env create -f environment-unix.yml
on Linux and OSX, or
$ conda env create -f environment-windows.yml
on Windows.
To use Veros, just activate your new conda environment! This can be done through either conda activate veros, source activate veros, or activate veros, depending on your platform and Anaconda installation.
On bare metal (Ubuntu / Debian)¶
Install some dependencies:
$ sudo apt-get install git python3-dev python3-pip libhdf5-dev
Clone our repository:
$ git clone https://github.com/team-ocean/veros.git
Install Veros (preferably in a virtual environment) via:
$ pip3 install -e ./veros --user
Optionally, install Bohrium via:
$ pip3 install bohrium --user
Setting up a model¶
To run Veros, you need to set up a model - i.e., specify which settings and model domain you want to use. This is done by subclassing the Veros setup base class
in a setup script that is written in Python. You should have a look at the pre-implemented model setups in the repository’s setup
folder, or use the veros copy-setup command to copy one into your current folder. A good place to start is the ACC model
:
$ veros copy-setup acc
By working through the existing models, you should quickly be able to figure out how to write your own simulation. Just keep in mind this general advice:
You can (and should) use any (external) Python tools you want in your model setup. Before implementing a certain functionality, you should check whether it is already provided by a common library. Especially the SciPy module family provides countless implementations of common scientific functions (and SciPy is installed along with Veros).
If you decorate your methods with
@veros_method
, the variablenp
inside that function will point to the currently used backend (i.e., NumPy or Bohrium). Thus, if you want your setup to be able to dynamically switch between backends, you should write your methods like this:from veros import Veros, veros_method class MyVerosSetup(Veros): ... @veros_method def my_function(self): arr = np.array([1,2,3,4]) # "np" uses either NumPy or Bohrium
If you are curious about the general procedure in which a model is set up and ran, you should read the source code of
veros.VerosSetup
(especially thesetup()
andrun()
methods). This is also the best way to find out about the order in which methods and routines are called.Out of all functions that need to be implemented by your subclass of
veros.VerosSetup
, the only one that is called in every time step isset_forcing()
(at the beginning of each iteration). This implies that, to achieve optimal performance, you should consider moving calculations that are constant in time to other functions.
If you want to learn more about setting up advanced configurations, you should check out our tutorial that walks you through the creation of a realistic configuration with an idealized Atlantic.
Running Veros¶
After adapting your setup script, you are ready to run your first simulation. It is advisable to include something like:
@veros.tools.cli
def run(*args, **kwargs):
simulation = MyVerosSetup()
simulation.setup()
simulation.run()
if __name__ == "__main__":
run()
in your setup file, so you can run it as a script:
$ python my_setup.py
However, you are not required to do so, and you are welcome to write include your simulation class into other Python files and call it dynamically or interactively (e.g. in an IPython session).
All Veros setups decorated with veros.tools.cli()
accept additional options via the command line when called as a script or as arguments to their __init__()
function when called from another Python module. You can check the available commands through
$ python my_setup.py --help
Reading Veros output¶
All output is handled by the available diagnostics. The most basic diagnostic, snapshot, writes some model variables to netCDF files in regular intervals (and puts them into your current working directory).
NetCDF is a binary format that is widely adopted in the geophysical modeling community. There are various packages for reading, visualizing and processing netCDF files (such as ncview and ferret), and bindings for many programming languages (such as C, Fortran, MATLAB, and Python).
In fact, after installing Veros, you will already have installed the netCDF bindings for Python, so reading data from an output file and plotting it is as easy as:
import matplotlib.pyplot as plt
import h5netcdf
with h5netcdf.File("veros.snapshot.nc", "r") as datafile:
# read variable "u" and save it to a NumPy array
u = datafile.variables["u"][...]
# plot surface velocity at the last time step included in the file
plt.imshow(u[-1, -1, ...])
plt.show()
For further reference refer to the netcdf4-python documentation.
Using Bohrium¶
Warning
While Bohrium yields significant speed-ups for large to very large setups, the overhead introduced by Bohrium often leads to (sometimes considerably) slower execution for problems below a certain threshold size (see also Which backend should I choose to run my model (NumPy / Bohrium)?). You are thus advised to test carefully whether Bohrium is beneficial in your particular use case.
For large simulations, it is often beneficial to use the Bohrium backend for computations. When using Bohrium, all number crunching will make full use of your available architecture, i.e., computations are executed in parallel on all of your CPU cores, or even GPU when using BH_STACK=opencl
or BH_STACK=cuda
. You may switch between NumPy and Bohrium with a simple command line switch:
$ python my_setup.py -b bohrium
or, when running inside another Python module: (must be done before initializing you setup):
from veros import runtime_settings as rs
rs.backend = "bohrium"
Re-starting from a previous run¶
Restart data (in HDF5 format) is written at the end of each simulation or after a regular time interval if the setting restart_frequency is set to a finite value. To use this restart file as initial conditions for another simulation, you will have to point restart_input_filename of the new simulation to the corresponding restart file. This can (as all settings) also be given via command line:
$ python my_setup.py -s restart_input_filename /path/to/restart_file.h5
Running Veros on multiple processes via MPI¶
Note
This assumes that you are familiar with running applications through MPI, and is most useful on large architectures like a compute cluster. For smaller architectures, it is usually easier to stick to Bohrium.
Running Veros through MPI requires some addititonal dependencies:
A recent MPI implementation, such as OpenMPI or MPICH
mpi4py
that is linked to the correct MPI libraryA parallel-enabled version of the HDF5 library
h5py
built against this parallel version of HDF5For optimal performance, PETSc and
petsc4py
, linked to the rest of the stack
After you have installed everything, you can start Veros on multiple processes like so::
$ mpirun -n 4 python my_setup.py -n 2 2
In this case, Veros would run on 4 processes, each process computing one-quarter of the domain. The arguments of the -n flag specify the number of chunks in x and y-direction, respectively.
You can combine MPI and Bohrium like so::
$ OMP_NUM_THREADS=2 mpirun -n 2 python my_setup.py -n 2 1 -b bohrium
This starts 2 independent processes, each being parallelized by Bohrium using 2 threads (hybrid run).
See also
For more information, see Running Veros on a cluster.
Enhancing Veros¶
Veros was written with extensibility in mind. If you already know some Python and have worked with NumPy, you are pretty much ready to write your own extension. The model code is located in the veros
subfolder, while all of the numerical routines are located in veros/core
.
We believe that the best way to learn how Veros works is to read its source code. Starting from the Veros base class
, you should be able to work your way through the flow of the program, and figure out where to add your modifications. If you installed Veros through pip -e or setup.py develop, all changes you make will immediately be reflected when running the code.
In case you want to add additional output capabilities or compute additional quantities without changing the main solution of the simulation, you should consider adding a custom diagnostic.
A convenient way to implement your modifications is to create your own fork of Veros on GitHub, and submit a pull request if you think your modifications could be useful for the Veros community.
See also
More information is available in our developer guide.
Creating an advanced model setup¶
Note
This guide is still work in progress.
This is a step-by-step guide that illustrates how even complicated setups can be created with relative ease (thanks to the tools provided by the scientific Python community). As an example, we will re-create the wave propagation setup, which is a global ocean model with an idealized Atlantic.

The resulting stream function after about 1 year of integration.¶
The vision¶
The purpose of this model is to examine wave propagation along the eastern boundary of the North Atlantic. Since it is difficult to track propagating waves along ragged geometry or through uneven forcing fields, we will idealize the representation of the North Atlantic; and as the presence of the Pacific in the model is crucial to achieve a realistic ocean circulation, we want to use a global model.
This leaves us with the following requirements for the final wave propagation model:
A global model with a resolution of around 2 degrees and meridional stretching.
Convert the eastern boundary of the Atlantic to a straight line, so analytically derived wave properties hold.
A refined grid resolution at the eastern boundary of the Atlantic.
Zonally averaged forcings in the Atlantic.
A somehow interpolated initial state for cells that have been converted from land to ocean in the North Atlantic.
Options for shelf and continental slope.
A multiplier setting for the Southern Ocean wind stress.
Model skeleton¶
Instead of starting from scratch, we can use the global one degree model as a template, which looks like this:
#!/usr/bin/env python
import os
import h5netcdf
from veros import VerosSetup, tools, veros_method, time
from veros.variables import Variable, allocate
BASE_PATH = os.path.dirname(os.path.realpath(__file__))
DATA_FILES = tools.get_assets('global_1deg', os.path.join(BASE_PATH, 'assets.yml'))
class GlobalOneDegreeSetup(VerosSetup):
"""Global 1 degree model with 115 vertical levels.
`Adapted from pyOM2 <https://wiki.zmaw.de/ifm/TO/pyOM2/1x1%20global%20model>`_.
"""
@veros_method
def set_parameter(self, vs):
"""
set main parameters
"""
vs.nx = 360
vs.ny = 160
vs.nz = 115
vs.dt_mom = 1800.0
vs.dt_tracer = 1800.0
vs.runlen = 0.
vs.coord_degree = True
vs.enable_cyclic_x = True
vs.congr_epsilon = 1e-10
vs.congr_max_iterations = 10000
vs.enable_hor_friction = True
vs.A_h = 5e4
vs.enable_hor_friction_cos_scaling = True
vs.hor_friction_cosPower = 1
vs.enable_tempsalt_sources = True
vs.enable_implicit_vert_friction = True
vs.eq_of_state_type = 5
# isoneutral
vs.enable_neutral_diffusion = True
vs.K_iso_0 = 1000.0
vs.K_iso_steep = 50.0
vs.iso_dslope = 0.005
vs.iso_slopec = 0.005
vs.enable_skew_diffusion = True
# tke
vs.enable_tke = True
vs.c_k = 0.1
vs.c_eps = 0.7
vs.alpha_tke = 30.0
vs.mxl_min = 1e-8
vs.tke_mxl_choice = 2
vs.kappaM_min = 2e-4
vs.kappaH_min = 2e-5
vs.enable_kappaH_profile = True
vs.enable_tke_superbee_advection = True
# eke
vs.enable_eke = True
vs.eke_k_max = 1e4
vs.eke_c_k = 0.4
vs.eke_c_eps = 0.5
vs.eke_cross = 2.
vs.eke_crhin = 1.0
vs.eke_lmin = 100.0
vs.enable_eke_superbee_advection = True
vs.enable_eke_isopycnal_diffusion = True
# idemix
vs.enable_idemix = False
vs.enable_eke_diss_surfbot = True
vs.eke_diss_surfbot_frac = 0.2
vs.enable_idemix_superbee_advection = True
vs.enable_idemix_hor_diffusion = True
# custom variables
vs.nmonths = 12
vs.variables.update(
t_star=Variable('t_star', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
s_star=Variable('s_star', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
qnec=Variable('qnec', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
qnet=Variable('qnet', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
qsol=Variable('qsol', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
divpen_shortwave=Variable('divpen_shortwave', ('zt',), '', '', time_dependent=False),
taux=Variable('taux', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
tauy=Variable('tauy', ('xt', 'yt', 'nmonths'), '', '', time_dependent=False),
)
@veros_method
def _read_forcing(self, vs, var):
with h5netcdf.File(DATA_FILES['forcing'], 'r') as infile:
var = infile.variables[var]
return np.array(var, dtype=str(var.dtype)).T
@veros_method
def set_grid(self, vs):
dz_data = self._read_forcing(vs, 'dz')
vs.dzt[...] = dz_data[::-1]
vs.dxt[...] = 1.0
vs.dyt[...] = 1.0
vs.y_origin = -79.
vs.x_origin = 91.
@veros_method
def set_coriolis(self, vs):
vs.coriolis_t[...] = 2 * vs.omega * np.sin(vs.yt[np.newaxis, :] / 180. * vs.pi)
@veros_method(dist_safe=False, local_variables=['kbot'])
def set_topography(self, vs):
bathymetry_data = self._read_forcing(vs, 'bathymetry')
salt_data = self._read_forcing(vs, 'salinity')[:, :, ::-1]
mask_salt = salt_data == 0.
vs.kbot[2:-2, 2:-2] = 1 + np.sum(mask_salt.astype(np.int), axis=2)
mask_bathy = bathymetry_data == 0
vs.kbot[2:-2, 2:-2][mask_bathy] = 0
vs.kbot[vs.kbot >= vs.nz] = 0
# close some channels
i, j = np.indices((vs.nx, vs.ny))
mask_channel = (i >= 207) & (i < 214) & (j < 5) # i = 208,214; j = 1,5
vs.kbot[2:-2, 2:-2][mask_channel] = 0
# Aleutian islands
mask_channel = (i == 104) & (j == 134) # i = 105; j = 135
vs.kbot[2:-2, 2:-2][mask_channel] = 0
# Engl channel
mask_channel = (i >= 269) & (i < 271) & (j == 130) # i = 270,271; j = 131
vs.kbot[2:-2, 2:-2][mask_channel] = 0
@veros_method(dist_safe=False, local_variables=[
't_star', 's_star', 'qnec', 'qnet', 'qsol', 'divpen_shortwave', 'taux', 'tauy',
'temp', 'salt', 'forc_iw_bottom', 'forc_iw_surface', 'kbot', 'maskT', 'maskW',
'zw', 'dzt'
])
def set_initial_conditions(self, vs):
rpart_shortwave = 0.58
efold1_shortwave = 0.35
efold2_shortwave = 23.0
# initial conditions
temp_data = self._read_forcing(vs, 'temperature')
vs.temp[2:-2, 2:-2, :, 0] = temp_data[..., ::-1] * vs.maskT[2:-2, 2:-2, :]
vs.temp[2:-2, 2:-2, :, 1] = temp_data[..., ::-1] * vs.maskT[2:-2, 2:-2, :]
salt_data = self._read_forcing(vs, 'salinity')
vs.salt[2:-2, 2:-2, :, 0] = salt_data[..., ::-1] * vs.maskT[2:-2, 2:-2, :]
vs.salt[2:-2, 2:-2, :, 1] = salt_data[..., ::-1] * vs.maskT[2:-2, 2:-2, :]
# wind stress on MIT grid
vs.taux[2:-2, 2:-2, :] = self._read_forcing(vs, 'tau_x')
vs.tauy[2:-2, 2:-2, :] = self._read_forcing(vs, 'tau_y')
qnec_data = self._read_forcing(vs, 'dqdt')
vs.qnec[2:-2, 2:-2, :] = qnec_data * vs.maskT[2:-2, 2:-2, -1, np.newaxis]
qsol_data = self._read_forcing(vs, 'swf')
vs.qsol[2:-2, 2:-2, :] = -qsol_data * vs.maskT[2:-2, 2:-2, -1, np.newaxis]
# SST and SSS
sst_data = self._read_forcing(vs, 'sst')
vs.t_star[2:-2, 2:-2, :] = sst_data * vs.maskT[2:-2, 2:-2, -1, np.newaxis]
sss_data = self._read_forcing(vs, 'sss')
vs.s_star[2:-2, 2:-2, :] = sss_data * vs.maskT[2:-2, 2:-2, -1, np.newaxis]
if vs.enable_idemix:
tidal_energy_data = self._read_forcing(vs, 'tidal_energy')
mask = np.maximum(0, vs.kbot[2:-2, 2:-2] - 1)[:, :, np.newaxis] == np.arange(vs.nz)[np.newaxis, np.newaxis, :]
tidal_energy_data[:, :] *= vs.maskW[2:-2, 2:-2, :][mask].reshape(vs.nx, vs.ny) / vs.rho_0
vs.forc_iw_bottom[2:-2, 2:-2] = tidal_energy_data
wind_energy_data = self._read_forcing(vs, 'wind_energy')
wind_energy_data[:, :] *= vs.maskW[2:-2, 2:-2, -1] / vs.rho_0 * 0.2
vs.forc_iw_surface[2:-2, 2:-2] = wind_energy_data
"""
Initialize penetration profile for solar radiation and store divergence in divpen
note that pen is set to 0.0 at the surface instead of 1.0 to compensate for the
shortwave part of the total surface flux
"""
swarg1 = vs.zw / efold1_shortwave
swarg2 = vs.zw / efold2_shortwave
pen = rpart_shortwave * np.exp(swarg1) + (1.0 - rpart_shortwave) * np.exp(swarg2)
pen[-1] = 0.
vs.divpen_shortwave = allocate(vs, ('zt',))
vs.divpen_shortwave[1:] = (pen[1:] - pen[:-1]) / vs.dzt[1:]
vs.divpen_shortwave[0] = pen[0] / vs.dzt[0]
@veros_method
def set_forcing(self, vs):
t_rest = 30. * 86400.
cp_0 = 3991.86795711963 # J/kg /K
year_in_seconds = time.convert_time(1., 'years', 'seconds')
(n1, f1), (n2, f2) = tools.get_periodic_interval(vs.time, year_in_seconds,
year_in_seconds / 12., 12)
# linearly interpolate wind stress and shift from MITgcm U/V grid to this grid
vs.surface_taux[:-1, :] = f1 * vs.taux[1:, :, n1] + f2 * vs.taux[1:, :, n2]
vs.surface_tauy[:, :-1] = f1 * vs.tauy[:, 1:, n1] + f2 * vs.tauy[:, 1:, n2]
if vs.enable_tke:
vs.forc_tke_surface[1:-1, 1:-1] = np.sqrt((0.5 * (vs.surface_taux[1:-1, 1:-1] \
+ vs.surface_taux[:-2, 1:-1]) / vs.rho_0) ** 2
+ (0.5 * (vs.surface_tauy[1:-1, 1:-1] \
+ vs.surface_tauy[1:-1, :-2]) / vs.rho_0) ** 2) ** (3. / 2.)
# W/m^2 K kg/J m^3/kg = K m/s
t_star_cur = f1 * vs.t_star[..., n1] + f2 * vs.t_star[..., n2]
vs.qqnec = f1 * vs.qnec[..., n1] + f2 * vs.qnec[..., n2]
vs.qqnet = f1 * vs.qnet[..., n1] + f2 * vs.qnet[..., n2]
vs.forc_temp_surface[...] = (vs.qqnet + vs.qqnec * (t_star_cur - vs.temp[..., -1, vs.tau])) \
* vs.maskT[..., -1] / cp_0 / vs.rho_0
s_star_cur = f1 * vs.s_star[..., n1] + f2 * vs.s_star[..., n2]
vs.forc_salt_surface[...] = 1. / t_rest * \
(s_star_cur - vs.salt[..., -1, vs.tau]) * vs.maskT[..., -1] * vs.dzt[-1]
# apply simple ice mask
mask1 = vs.temp[:, :, -1, vs.tau] * vs.maskT[:, :, -1] <= -1.8
mask2 = vs.forc_temp_surface <= 0
ice = ~(mask1 & mask2)
vs.forc_temp_surface *= ice
vs.forc_salt_surface *= ice
# solar radiation
if vs.enable_tempsalt_sources:
vs.temp_source[..., :] = (f1 * vs.qsol[..., n1, None] + f2 * vs.qsol[..., n2, None]) \
* vs.divpen_shortwave[None, None, :] * ice[..., None] \
* vs.maskT[..., :] / cp_0 / vs.rho_0
@veros_method
def set_diagnostics(self, vs):
average_vars = ['surface_taux', 'surface_tauy', 'forc_temp_surface', 'forc_salt_surface',
'psi', 'temp', 'salt', 'u', 'v', 'w', 'Nsqr', 'Hd', 'rho',
'K_diss_v', 'P_diss_v', 'P_diss_nonlin', 'P_diss_iso', 'kappaH']
if vs.enable_skew_diffusion:
average_vars += ['B1_gm', 'B2_gm']
if vs.enable_TEM_friction:
average_vars += ['kappa_gm', 'K_diss_gm']
if vs.enable_tke:
average_vars += ['tke', 'Prandtlnumber', 'mxl', 'tke_diss',
'forc_tke_surface', 'tke_surf_corr']
if vs.enable_idemix:
average_vars += ['E_iw', 'forc_iw_surface', 'forc_iw_bottom', 'iw_diss',
'c0', 'v0']
if vs.enable_eke:
average_vars += ['eke', 'K_gm', 'L_rossby', 'L_rhines']
vs.diagnostics['averages'].output_variables = average_vars
vs.diagnostics['cfl_monitor'].output_frequency = 86400.0
vs.diagnostics['snapshot'].output_frequency = 365 * 86400 / 24.
vs.diagnostics['overturning'].output_frequency = 365 * 86400
vs.diagnostics['overturning'].sampling_frequency = 365 * 86400 / 24.
vs.diagnostics['energy'].output_frequency = 365 * 86400
vs.diagnostics['energy'].sampling_frequency = 365 * 86400 / 24.
vs.diagnostics['averages'].output_frequency = 365 * 86400
vs.diagnostics['averages'].sampling_frequency = 365 * 86400 / 24.
@veros_method
def after_timestep(self, vs):
pass
@tools.cli
def run(*args, **kwargs):
simulation = GlobalOneDegreeSetup(*args, **kwargs)
simulation.setup()
simulation.run()
if __name__ == '__main__':
run()
The biggest changes in the new wave propagation setup will be located in the
set_grid()
set_topography()
and set_initial_conditions()
methods to accommodate for the new geometry and the interpolation of initial
conditions to the modified grid, so we can concentrate on implementing those
first.
Step 1: Setup grid¶
Warning
When using a non-uniform grid,
Step 2: Create idealized topography¶
Usually, to create an idealized topography, one would simply hand-craft some input and forcing files that reflect the desired changes. However, since we want our setup to have flexible resolution, we will have to write an algorithm that creates these input files for any given number of grid cells. One convenient way to achieve this is by creating some high-resolution masks representing the target topography by hand, and then interpolate these masks to the desired resolution.
Create a mask image¶
Before we can start, we need to download a high-resolution topography dataset. There are many freely available topographical data sets on the internet; one of them is ETOPO5 (with a resolution of 5 arc-minutes), which we will be using throughout this tutorial. To create a mask image from the topography file, you can use the command line tool veros create-mask, e.g. like
$ veros create-mask ETOPO5_Ice_g_gmt4.nc
This creates a one-to-one representation of the topography file as a PNG image. However, in the case of the 5 arc-minute topography, the resulting image includes a lot of small islands and complicated coastlines that might cause problems when being interpolated to a numerical grid with a much lower resolution. To address this, the create-mask script accepts a scale argument. When given, a Gaussian filter with standard deviation scale (in grid cells) is applied to the resulting image, smoothing out small features. The command
$ veros create-mask ETOPO5_Ice_g_gmt4 --scale 3 3
results in the following mask:

Smoothed topography mask¶
which looks good enough to serve as a basis for horizontal resolutions of around one degree.
Modify the mask¶
We can now proceed to mold this realistic version of the global topography into the desired idealized shape. You can use any image editor you have available; one possibility is the free software GIMP. Inside the editor, we can use the pencil tools to create a modified version of the topography mask:

Idealized topography mask¶
In this modified version, I have
replaced the eastern boundary of the North Atlantic by a meridional line;
removed all lakes and inland seas;
thickened Central America (to prevent North and South America to become disconnected due to interpolation artifacts); and
removed the Arctic Ocean and Hudson Bay.
Now that our topography mask is finished, we can go ahead and implement it in the Veros setup!
Import to Veros¶
To read the mask in PNG format, we are going to use the Python Imaging Library (PIL).
Step 3: Interpolate forcings & initial conditions¶

Mask to identify grid cells in the North Atlantic¶
Step 4: Set up diagnostics & final touches¶
Making changes in Veros¶
Code conventions¶
When contributing to Veros, please adhere to the following general guidelines:
Your first guide should be the surrounding Veros code. Look around, and be consistent with your modifications.
Unless you have a very good reason not to do so, please stick to the PEP8 style guide throughout your code. One exception we make in Veros is in regard to the maximum line length - since numerical operations can take up quite a lot of horizontal space, you may use longer lines if it increases readability.
Please follow the PEP8 naming conventions, and use meaningful, telling names for your variables, functions, and classes. The variable name
stretching_factor
is infinitely more meaningful thank
. This is especially important for settings and generic helper functions.“Private” helper functions that are not meant to be called from outside the current source file should be prefixed with an underscore (
_
).Use double quotes (
"
) for all strings longer than a single character.Document your functions using Google-style docstrings. This is especially important if you are implementing a user-facing API (such as a diagnostic, a setup, or tools that are meant to be called from setups).
Distributed memory support¶
By default, all core routines should support distributed execution via MPI.
In this case, every processor only operates on a chunk of the total data.
By using veros.variables.allocate()
, you can make sure that allocated data always has the right shape.
Since none of the processes have access to the global data, you need to take special care during reductions (e.g. sum
) and accumulations (e.g. cumsum
) along horizontal dimensions.
Use functions from veros.distributed
(e.g. veros.distributed.global_max()
) where appropriate.
The dist_safe keyword¶
If you are not comfortable writing code that is safe for distributed execution, you can use the dist_safe
keyword to veros.decorators.veros_method()
::
@veros_method(dist_safe=False, local_variables=["temp"])
def my_function(vs):
# this function is now guaranteed to be executed on the main process
# since temp is declared as a local variable, we have access to all of the data
vs.temp[2:-2, 2:-2] = np.max(vs.temp)
# this would throw an error, since salt is not in local_variables
# vs.salt[...] = 0
# after execution, the updated contents of vs.temp are scattered to all processes,
# and distributed execution continues
When encountering a veros_method
that is marked as not safe for distributed execution (dist_safe=False
), Veros gathers all relevant data from the worker processes,
copies it to the main process, and executes the function there.
This ensures that you can write your code exactly as in the non-distributed case (but it comes with a performance penalty, of course).
Running tests and benchmarks¶
If you want to make sure that your changes did not break anything, you can run our test suite that compares the results of each subroutine to pyOM2. To do that, you will need to compile the Python interface of pyOM2 on your machine, and then point the testing suite to the library location, e.g. through:
$ pytest -v . --pyom2-lib /path/to/pyOM2/py_src/pyOM_code.so
from the main folder of the Veros repository.
If you deliberately introduced breaking changes, you can disable them during testing by prefixing them with:
if not vs.pyom_compatibility_mode:
# your changes
Automated benchmarks are provided in a similar fashion. The benchmarks run some dummy problems with varying problem sizes and all available computational backends: numpy
, bohrium-openmp
, bohrium-opencl
, bohrium-cuda
, fortran
(pyOM2), and fortran-mpi
(parallel pyOM2). For options and further information run:
$ python run_benchmarks.py --help
from the test
folder. Timings are written in YAML format.
Performance tweaks¶
If your changes to Veros turn out to have a negative effect on the runtime of the model, there several ways to investigate and solve performance problems:
Run your model with the
-v debug
option to get additional debugging output (such as timings for each time step, and a timing summary after the run has finished).Run your model with the
-p
option to profile Veros with pyinstrument. You may have to run pip install pyinstrument before being able to do so. After completion of the run, a fileprofile.html
will be written that can be opened with a web browser and contains timings for the entire call stack.You should try and avoid explicit loops over arrays at all cost (even more so when using Bohrium). You should always try to work on the whole array at once.
When using Bohrium, it is sometimes beneficial to copy an array to NumPy before passing it to an external module or performing an operation that cannot be vectorized efficiently. Just don’t forget to copy it back to Bohrium after you are finished, e.g. like so:
from veros import runtime_settings as rs if rs.backend == "bohrium": u_np = vs.u.copy2numpy() else: u_np = vs.u vs.u[...] = np.asarray(external_function(u_np))
If you are still having trouble, don’t hesitate to ask for help (e.g. on GitHub).
Running Veros on a cluster¶
This tutorial walks you through some of the most common challenges that are specific to large, shared architectures like clusters and supercomputers. In case you are still having trouble setting up or running Veros on a large architecture after reading it, you should first contact the administrator of your cluster. Otherwise, you should of course feel free to open an issue.
Installation¶
Probably the easiest way to install Veros on a cluster is to, once again, use Anaconda. Since it is mostly platform independent and does not require elevated permissions, Anaconda is the perfect way to try out Veros without too much hassle.
If you are an administrator and want to make Veros accessible to multiple users on your cluster, we recommend that you do not install Veros system-wide, since it severely limits the possibilities of the users: First of all, they won’t be able to install additional Python modules they might want to use for post-processing or development. And second of all, the source code (and playing with it) is supposed to be a critical part of the Veros experience. Instead, you could e.g. use virtualenv to create a lightweight Python environment for every user that they can freely manage.
Usage¶
If you want to run Veros on a shared computing architecture, there are several issues that require special handling:
Preventing timeouts: In cloud computing, it is common that scheduling constraints limit the maximum execution time of a given process. Processes that exceed this time are killed. To prevent that long-running processes have to be restarted manually after each timeout, one usually makes use of a resubmit mechanism: The long-running process is split into chunks that each finish before a timeout is triggered, with subsequent runs starting from the restart files that the previous process has written.
Allocation of resources: Most applications use MPI to distribute work across processors; however, this is not supported by Bohrium. We therefore need to make sure that just one single process on a single node is started for our simulation (Bohrium will then divide the workload among different threads using OpenMP).
To solve these issues, the scheduling manager needs to be told exactly how it should run our model, which is usually being done by writing a batch script that prepares the environment and states which resources to request. The exact set-up of such a script will vary depending on the scheduling manager running on your cluster, and how exactly you chose to install Veros and Bohrium. One possible way to write such a batch script for the scheduling manager SLURM is presented here:
#!/bin/bash -l
#
#SBATCH -p mycluster
#SBATCH -A myaccount
#SBATCH --job-name=veros_mysetup
#SBATCH --nodes=2
#SBATCH --ntasks=16
#SBATCH --cpus-per-task=4
#SBATCH --exclusive
#SBATCH --mail-type=ALL
#SBATCH --mail-user=your@email.xyz
# load module dependencies
module load bohrium
# only needed if not found automatically
export BH_CONFIG=/path/to/bohrium/config.ini
# if needed, you can modify the internal Bohrium compiler flags
export BH_OPENMP_COMPILER_FLG="-x c -fPIC -shared -std=gnu99 -O3 -Werror -fopenmp"
# set number of threads to cpus-per-task
export OMP_NUM_THREADS=4
# adapt srun command to your available scheduler / MPI implementation
veros resubmit -i my_run -n 8 -l 7776000 \
-c "srun --mpi=pmi2 -- python my_setup.py -b bohrium -v debug -n 4 4" \
--callback "sbatch veros_batch.sh"
which is saved as veros_batch.sh
in the model setup folder and called using sbatch
.
This script makes use of the veros resubmit command and its --callback
option to create a script that automatically re-runs itself in a new process after each successful run (see also Command line tools). Upon execution, a job is created on one node, using 16 processors in one process, that runs the Veros setup located in my_setup.py
a total of eight times for 90 days (7776000 seconds) each, with identifier my_run
. Note that the --callback "sbatch veros_batch.sh"
part of the command is needed to actually create a new job after every run, to prevent the script from being killed after a timeout.
Setup gallery¶
This page gives an overview of the available model setups. To copy the setup file and additional input files (if applicable) to the current working directory, you can make use of the veros copy-setup command.
Example:
$ veros copy-setup acc
Idealized configurations¶
ACC channel model¶
-
class
veros.setup.acc.
ACCSetup
(state=None, override=None, plugins=None)[source]¶ Bases:
veros.veros.VerosSetup
A model using spherical coordinates with a partially closed domain representing the Atlantic and ACC.
Wind forcing over the channel part and buoyancy relaxation drive a large-scale meridional overturning circulation.
- This setup demonstrates:
setting up an idealized geometry
updating surface forcings
basic usage of diagnostics
ACC sector model¶
-
class
veros.setup.acc_sector.
ACCSectorSetup
(state=None, override=None, plugins=None)[source]¶ Bases:
veros.veros.VerosSetup
A model using spherical coordinates with a partially closed domain representing the narrow sector of Atlantic and ACC.
The bathymetry of the model is idealized to a flat-bottom (with depth of 4000 m) over the majority of the domain, except a half depth appended within the confines of the circumpolar channel at the inflow and outflow regions. The horizontal grid has resolution of \(2 \times 2\) degrees, and the vertical one has 40 levels.
Wind forcing over the sector part and buoyancy relaxation drive a large-scale meridional overturning circulation.
- This setup demonstrates:
setting up an idealized geometry after (Munday et al., 2013).
modifing surface forcings over selected regions of the domain
sensitivity of circumpolar transport and meridional overturning to changes in Southern Ocean wind stress and buoyancy anomalies
basic usage of diagnostics
Realistic configurations¶
Global flexible resolution setup¶
Wave propagation study¶
Global four-degree model¶
-
class
veros.setup.global_4deg.
GlobalFourDegreeSetup
(state=None, override=None, plugins=None)[source]¶ Bases:
veros.veros.VerosSetup
Global 4 degree model with 15 vertical levels.
- This setup demonstrates:
setting up a realistic model
reading input data from external files
implementing surface forcings
applying a simple ice mask
Global one-degree model¶
North Atlantic regional model¶
-
class
veros.setup.north_atlantic.
NorthAtlanticSetup
(state=None, override=None, plugins=None)[source]¶ Bases:
veros.veros.VerosSetup
A regional model of the North Atlantic, inspired by Smith et al., 2000.
Forcing and initial conditions are taken from the FLAME PyOM2 setup. Bathymetry data from ETOPO1 (resolution of 1 arcmin).
Boundary forcings are implemented via sponge layers in the Greenland Sea, by the Strait of Gibraltar, and in the South Atlantic. This setup runs with arbitrary resolution; upon changing the number of grid cells, all forcing files will be interpolated to the new grid. Default resolution corresponds roughly to \(0.5 \times 0.25\) degrees.
Available model settings¶
The following list of available settings is automatically created from the file settings.py
in the Veros main folder.
They are available as attributes of all instances of the Veros state class
, e.g.:
>>> simulation = MyVerosSetup()
>>> vs = simulation.state
>>> print(vs.eq_of_state_type)
1
-
VerosState.identifier = UNNAMED
Identifier of the current simulation
-
VerosState.nx = 0
Grid points in zonal (x) direction
-
VerosState.ny = 0
Grid points in meridional (y,j) direction
-
VerosState.nz = 0
Grid points in vertical (z,k) direction
-
VerosState.dt_mom = 0.0
Time step in seconds for momentum
-
VerosState.dt_tracer = 0.0
Time step for tracers, can be larger than dt_mom
-
VerosState.runlen = 0.0
Length of simulation in seconds
-
VerosState.AB_eps = 0.1
Deviation from Adam-Bashforth weighting
-
VerosState.coord_degree = False
either spherical (True) or cartesian (False) coordinates
-
VerosState.enable_cyclic_x = False
enable cyclic boundary conditions
-
VerosState.eq_of_state_type = 1
equation of state: 1: linear, 3: nonlinear with comp., 5: TEOS
-
VerosState.enable_implicit_vert_friction = False
enable implicit vertical friction
-
VerosState.enable_explicit_vert_friction = False
enable explicit vertical friction
-
VerosState.enable_hor_friction = False
enable horizontal friction
-
VerosState.enable_hor_diffusion = False
enable horizontal diffusion
-
VerosState.enable_biharmonic_friction = False
enable biharmonic horizontal friction
-
VerosState.enable_biharmonic_mixing = False
enable biharmonic horizontal mixing
-
VerosState.enable_hor_friction_cos_scaling = False
scaling of hor. viscosity with cos(latitude)**cosPower
-
VerosState.enable_ray_friction = False
enable Rayleigh damping
-
VerosState.enable_bottom_friction = False
enable bottom friction
-
VerosState.enable_bottom_friction_var = False
enable bottom friction with lateral variations
-
VerosState.enable_quadratic_bottom_friction = False
enable quadratic bottom friction
-
VerosState.enable_tempsalt_sources = False
enable restoring zones, etc
-
VerosState.enable_momentum_sources = False
enable restoring zones, etc
-
VerosState.enable_superbee_advection = False
enable advection scheme with implicit mixing
-
VerosState.enable_conserve_energy = True
exchange energy consistently
-
VerosState.enable_store_bottom_friction_tke = False
transfer dissipated energy by bottom/rayleig fric. to TKE, else transfer to internal waves
-
VerosState.enable_store_cabbeling_heat = False
transfer non-linear mixing terms to potential enthalpy, else transfer to TKE and EKE
-
VerosState.enable_noslip_lateral = False
enable lateral no-slip boundary conditions in harmonic- and biharmonic friction.
-
VerosState.congr_epsilon = 1e-12
convergence criteria for Poisson solver
-
VerosState.congr_max_iterations = 1000
maximum number of Poisson solver iterations
-
VerosState.A_h = 0.0
lateral viscosity in m^2/s
-
VerosState.K_h = 0.0
lateral diffusivity in m^2/s
-
VerosState.r_ray = 0.0
Rayleigh damping coefficient in 1/s
-
VerosState.r_bot = 0.0
bottom friction coefficient in 1/s
-
VerosState.r_quad_bot = 0.0
qudratic bottom friction coefficient
-
VerosState.hor_friction_cosPower = 3
-
VerosState.A_hbi = 0.0
lateral biharmonic viscosity in m^4/s
-
VerosState.K_hbi = 0.0
lateral biharmonic diffusivity in m^4/s
-
VerosState.kappaH_0 = 0.0
-
VerosState.kappaM_0 = 0.0
fixed values for vertical viscosity/diffusivity which are set for no TKE model
-
VerosState.enable_neutral_diffusion = False
enable isopycnal mixing
-
VerosState.enable_skew_diffusion = False
enable skew diffusion approach for eddy-driven velocities
-
VerosState.enable_TEM_friction = False
TEM approach for eddy-driven velocities
-
VerosState.K_iso_0 = 0.0
constant for isopycnal diffusivity in m^2/s
-
VerosState.K_iso_steep = 0.0
lateral diffusivity for steep slopes in m^2/s
-
VerosState.K_gm_0 = 0.0
fixed value for K_gm which is set for no EKE model
-
VerosState.iso_dslope = 0.0008
parameters controlling max allowed isopycnal slopes
-
VerosState.iso_slopec = 0.001
parameters controlling max allowed isopycnal slopes
-
VerosState.enable_idemix = False
-
VerosState.tau_v = 172800.0
time scale for vertical symmetrisation
-
VerosState.tau_h = 1296000.0
time scale for horizontal symmetrisation
-
VerosState.gamma = 1.57
-
VerosState.jstar = 5.0
spectral bandwidth in modes
-
VerosState.mu0 = 0.3333333333333333
dissipation parameter
-
VerosState.enable_idemix_hor_diffusion = False
-
VerosState.enable_eke_diss_bottom = False
-
VerosState.enable_eke_diss_surfbot = False
-
VerosState.eke_diss_surfbot_frac = 1.0
fraction which goes into bottom
-
VerosState.enable_idemix_superbee_advection = False
-
VerosState.enable_idemix_upwind_advection = False
-
VerosState.enable_tke = False
-
VerosState.c_k = 0.1
-
VerosState.c_eps = 0.7
-
VerosState.alpha_tke = 1.0
-
VerosState.mxl_min = 1e-12
-
VerosState.kappaM_min = 0.0
-
VerosState.kappaM_max = 100.0
-
VerosState.tke_mxl_choice = 1
-
VerosState.enable_tke_superbee_advection = False
-
VerosState.enable_tke_upwind_advection = False
-
VerosState.enable_tke_hor_diffusion = False
-
VerosState.K_h_tke = 2000.0
lateral diffusivity for tke
-
VerosState.enable_eke = False
-
VerosState.eke_lmin = 100.0
minimal length scale in m
-
VerosState.eke_c_k = 1.0
-
VerosState.eke_cross = 1.0
Parameter for EKE model
-
VerosState.eke_crhin = 1.0
Parameter for EKE model
-
VerosState.eke_c_eps = 1.0
Parameter for EKE model
-
VerosState.eke_k_max = 10000.0
maximum of K_gm
-
VerosState.alpha_eke = 1.0
factor vertical friction
-
VerosState.enable_eke_superbee_advection = False
-
VerosState.enable_eke_upwind_advection = False
-
VerosState.enable_eke_isopycnal_diffusion = False
use K_gm also for isopycnal diffusivity
-
VerosState.enable_eke_leewave_dissipation = False
-
VerosState.c_lee0 = 1.0
-
VerosState.eke_Ri0 = 200.0
-
VerosState.eke_Ri1 = 50.0
-
VerosState.eke_int_diss0 = 5.787037037037037e-07
-
VerosState.kappa_EKE0 = 0.1
-
VerosState.eke_r_bot = 0.0
bottom friction coefficient
-
VerosState.eke_hrms_k0_min = 0.0
min value for bottom roughness parameter
-
VerosState.kappaH_min = 0.0
minimum value for vertical diffusivity
-
VerosState.enable_kappaH_profile = False
Compute vertical profile of diffusivity after Bryan and Lewis (1979) in TKE routine
-
VerosState.enable_Prandtl_tke = True
Compute Prandtl number from stratification levels in TKE routine
-
VerosState.Prandtl_tke0 = 10.0
Constant Prandtl number when stratification is neglected for kappaH computation in TKE routine
-
VerosState.use_io_threads = False
Start extra threads for disk writes
-
VerosState.io_timeout = 20
Timeout in seconds while waiting for IO locks to be released
-
VerosState.enable_netcdf_zlib_compression = True
Use netCDF4’s native zlib interface, which leads to smaller output files (but carries some computational overhead).
-
VerosState.enable_hdf5_gzip_compression = True
Use h5py’s native gzip interface, which leads to smaller restart files (but carries some computational overhead).
-
VerosState.restart_input_filename =
File name of restart input. If not given, no restart data will be read.
-
VerosState.restart_output_filename = {identifier}_{itt:0>4d}.restart.h5
File name of restart output. May contain Python format syntax that is substituted with Veros attributes.
-
VerosState.restart_frequency = 0
Frequency (in seconds) to write restart data
-
VerosState.force_overwrite = False
Overwrite existing output files
-
VerosState.pyom_compatibility_mode = False
Force compatibility to pyOM2 (even reproducing bugs and other quirks). For testing purposes only.
-
VerosState.diskless_mode = False
Suppress all output to disk. Mainly used for testing purposes.
-
VerosState.default_float_type = float64
Default type to use for floating point arrays (e.g.
float32
orfloat64
).
Model variables¶
The variable meta-data (i.e., all instances of veros.variables.Variable
)
are available in a dictionary as the attribute Veros.variables
. The actual
data arrays are added directly as attributes to Veros
. The following code
snippet (as commonly used in the Diagnostics) illustrates this behavior:
var_meta = {key: val for key, val in vs.variables.items() if val.time_dependent and val.output}
var_data = {key: getattr(veros, key) for key in var_meta.keys()}
In this case, var_meta
is a dictionary containing all metadata for variables that
are time dependent and should be added to the output, while var_data
is a dictionary
with the same keys containing the corresponding data arrays.
Variable class¶
Available variables¶
There are two kinds of variables in Veros. Main variables are always present in a
simulation, while conditional variables are only available if their respective
condition is True
at the time of variable allocation.
- Attributes:
- : Time-dependent: Included in snapshot output by default: Written to restart files by default
Main variables¶
-
VerosState.
cost
¶ - Units
1
- Dimensions
yt
- Type
- Attributes
Metric factor for spherical coordinates
-
VerosState.
cosu
¶ - Units
1
- Dimensions
yu
- Type
- Attributes
Metric factor for spherical coordinates
-
VerosState.
tantr
¶ - Units
1
- Dimensions
yt
- Type
- Attributes
Metric factor for spherical coordinates
-
VerosState.
coriolis_t
¶ - Units
1/s
- Dimensions
xt, yt
- Type
- Attributes
Coriolis frequency at T grid point
-
VerosState.
coriolis_h
¶ - Units
1/s
- Dimensions
xt, yt
- Type
- Attributes
Horizontal Coriolis frequency at T grid point
-
VerosState.
kbot
¶ - Units
- Dimensions
xt, yt
- Type
- Attributes
Index of the deepest grid cell (counting from 1, 0 means all land)
-
VerosState.
hur
¶ - Units
m
- Dimensions
xu, yt
- Type
- Attributes
Total depth of the water column (masked)
-
VerosState.
hvr
¶ - Units
m
- Dimensions
xt, yu
- Type
- Attributes
Total depth of the water column (masked)
-
VerosState.
beta
¶ - Units
1/(ms)
- Dimensions
xt, yt
- Type
- Attributes
Change of Coriolis frequency with latitude
-
VerosState.
maskT
¶ - Units
- Dimensions
xt, yt, zt
- Type
int8
- Attributes
Mask in physical space for tracer points
-
VerosState.
maskU
¶ - Units
- Dimensions
xu, yt, zt
- Type
int8
- Attributes
Mask in physical space for U points
-
VerosState.
maskV
¶ - Units
- Dimensions
xt, yu, zt
- Type
int8
- Attributes
Mask in physical space for V points
-
VerosState.
maskW
¶ - Units
- Dimensions
xt, yt, zw
- Type
int8
- Attributes
Mask in physical space for W points
-
VerosState.
maskZ
¶ - Units
- Dimensions
xu, yu, zt
- Type
int8
- Attributes
Mask in physical space for Zeta points
-
VerosState.
rho
¶ - Units
kg/m^3
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
In-situ density anomaly, relative to the surface mean value of 1024 kg/m^3
-
VerosState.
prho
¶ - Units
kg/m^3
- Dimensions
xt, yt, zt
- Type
- Attributes
Potential density anomaly, relative to the surface mean value of 1024 kg/m^3 (identical to in-situ density anomaly for equation of state type 1, 2, and 4)
-
VerosState.
int_drhodT
¶ - Units
?
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Partial derivative of dynamic enthalpy by temperature
-
VerosState.
int_drhodS
¶ - Units
?
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Partial derivative of dynamic enthalpy by salinity
-
VerosState.
Nsqr
¶ - Units
1/s^2
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
Square of stability frequency
-
VerosState.
Hd
¶ - Units
m^2/s^2
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Dynamic enthalpy
-
VerosState.
dHd
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Change of dynamic enthalpy due to advection
-
VerosState.
temp
¶ - Units
deg C
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Conservative temperature
-
VerosState.
dtemp
¶ - Units
deg C/s
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Conservative temperature tendency
-
VerosState.
dsalt
¶ - Units
g/(kg s)
- Dimensions
xt, yt, zt, timesteps
- Type
- Attributes
Salinity tendency
-
VerosState.
dtemp_vmix
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of temperature due to vertical mixing
-
VerosState.
dtemp_hmix
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of temperature due to horizontal mixing
-
VerosState.
dsalt_vmix
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of salinity due to vertical mixing
-
VerosState.
dsalt_hmix
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of salinity due to horizontal mixing
-
VerosState.
dtemp_iso
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of temperature due to isopycnal mixing plus skew mixing
-
VerosState.
dsalt_iso
¶ - Units
deg C/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Change of salinity due to isopycnal mixing plus skew mixing
-
VerosState.
forc_temp_surface
¶ - Units
m K/s
- Dimensions
xt, yt
- Type
- Attributes
Surface temperature flux
-
VerosState.
forc_salt_surface
¶ - Units
m g/s kg
- Dimensions
xt, yt
- Type
- Attributes
Surface salinity flux
-
VerosState.
du
¶ - Units
m/s
- Dimensions
xu, yt, zt, timesteps
- Type
- Attributes
Zonal velocity tendency
-
VerosState.
dv
¶ - Units
m/s
- Dimensions
xt, yu, zt, timesteps
- Type
- Attributes
Meridional velocity tendency
-
VerosState.
du_cor
¶ - Units
m/s^2
- Dimensions
xu, yt, zt
- Type
- Attributes
Change of u due to Coriolis force
-
VerosState.
dv_cor
¶ - Units
m/s^2
- Dimensions
xt, yu, zt
- Type
- Attributes
Change of v due to Coriolis force
-
VerosState.
du_mix
¶ - Units
m/s^2
- Dimensions
xu, yt, zt
- Type
- Attributes
Change of u due to implicit vertical mixing
-
VerosState.
dv_mix
¶ - Units
m/s^2
- Dimensions
xt, yu, zt
- Type
- Attributes
Change of v due to implicit vertical mixing
-
VerosState.
du_adv
¶ - Units
m/s^2
- Dimensions
xu, yt, zt
- Type
- Attributes
Change of u due to advection
-
VerosState.
dv_adv
¶ - Units
m/s^2
- Dimensions
xt, yu, zt
- Type
- Attributes
Change of v due to advection
-
VerosState.
surface_taux
¶ - Units
N/s^2
- Dimensions
xu, yt
- Type
- Attributes
Zonal surface wind stress
-
VerosState.
surface_tauy
¶ - Units
N/s^2
- Dimensions
xt, yu
- Type
- Attributes
Meridional surface wind stress
-
VerosState.
forc_rho_surface
¶ - Units
?
- Dimensions
xt, yt
- Type
- Attributes
Surface potential density flux
-
VerosState.
psi
¶ - Units
m^3/s
- Dimensions
xu, yu, timesteps
- Type
- Attributes
Barotropic streamfunction
-
VerosState.
dpsi
¶ - Units
m^3/s^2
- Dimensions
xu, yu, timesteps
- Type
- Attributes
Streamfunction tendency
-
VerosState.
dpsin
¶ - Units
?
- Dimensions
isle, timesteps
- Type
- Attributes
Boundary streamfunction factor
-
VerosState.
line_dir_south_mask
¶ - Units
- Dimensions
xt, yt, isle
- Type
- Attributes
Line integral mask
-
VerosState.
line_dir_north_mask
¶ - Units
- Dimensions
xt, yt, isle
- Type
- Attributes
Line integral mask
-
VerosState.
line_dir_east_mask
¶ - Units
- Dimensions
xt, yt, isle
- Type
- Attributes
Line integral mask
-
VerosState.
line_dir_west_mask
¶ - Units
- Dimensions
xt, yt, isle
- Type
- Attributes
Line integral mask
-
VerosState.
K_gm
¶ - Units
m^2/s
- Dimensions
xt, yt, zw
- Type
- Attributes
GM diffusivity, either constant or from EKE model
-
VerosState.
K_iso
¶ - Units
m^2/s
- Dimensions
xt, yt, zw
- Type
- Attributes
Along-isopycnal diffusivity
-
VerosState.
K_diss_v
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Kinetic energy dissipation by vertical, rayleigh and bottom friction
-
VerosState.
K_diss_bot
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Mean energy dissipation by bottom and rayleigh friction
-
VerosState.
K_diss_h
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Kinetic energy dissipation by horizontal friction
-
VerosState.
K_diss_gm
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Mean energy dissipation by GM (TRM formalism only)
-
VerosState.
P_diss_v
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by vertical diffusion
-
VerosState.
P_diss_nonlin
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by nonlinear equation of state
-
VerosState.
P_diss_iso
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by isopycnal mixing
-
VerosState.
P_diss_skew
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by GM (w/o TRM)
-
VerosState.
P_diss_hmix
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by horizontal mixing
-
VerosState.
P_diss_adv
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by advection
-
VerosState.
P_diss_comp
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by compression
-
VerosState.
P_diss_sources
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Potential energy dissipation by external sources (e.g. restoring zones)
-
VerosState.
u_wgrid
¶ - Units
m/s
- Dimensions
xt, yt, zw
- Type
- Attributes
Zonal velocity interpolated to W grid points
-
VerosState.
v_wgrid
¶ - Units
m/s
- Dimensions
xt, yt, zw
- Type
- Attributes
Meridional velocity interpolated to W grid points
Conditional variables¶
coord_degree¶
-
VerosState.
xt
¶ - Units
degrees_east
- Dimensions
xt
- Type
- Attributes
Zonal (x) coordinate of T-grid point
-
VerosState.
xu
¶ - Units
degrees_east
- Dimensions
xu
- Type
- Attributes
Zonal (x) coordinate of U-grid point
-
VerosState.
yt
¶ - Units
degrees_north
- Dimensions
yt
- Type
- Attributes
Meridional (y) coordinate of T-grid point
not coord_degree¶
-
VerosState.
xt
- Units
km
- Dimensions
xt
- Type
- Attributes
Zonal (x) coordinate of T-grid point
-
VerosState.
xu
- Units
km
- Dimensions
xu
- Type
- Attributes
Zonal (x) coordinate of U-grid point
-
VerosState.
yt
- Units
km
- Dimensions
yt
- Type
- Attributes
Meridional (y) coordinate of T-grid point
-
VerosState.
yu
- Units
km
- Dimensions
yu
- Type
- Attributes
Meridional (y) coordinate of U-grid point
enable_tempsalt_sources¶
-
VerosState.
temp_source
¶ - Units
K/s
- Dimensions
xt, yt, zt
- Type
- Attributes
Non-conservative source of temperature
enable_momentum_sources¶
-
VerosState.
u_source
¶ - Units
m/s^2 (?)
- Dimensions
xu, yt, zt
- Type
- Attributes
Non-conservative source of zonal velocity
enable_neutral_diffusion¶
-
VerosState.
K_11
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_13
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_22
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_23
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_31
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_32
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
-
VerosState.
K_33
¶ - Units
?
- Dimensions
xt, yt, zt
- Type
- Attributes
Isopycnal mixing tensor component
enable_skew_diffusion¶
-
VerosState.
B1_gm
¶ - Units
m^2/s
- Dimensions
xt, yu, zt
- Type
- Attributes
Zonal component of GM streamfunction
enable_bottom_friction_var¶
-
VerosState.
r_bot_var_u
¶ - Units
?
- Dimensions
xu, yt
- Type
- Attributes
Zonal bottom friction coefficient
enable_TEM_friction¶
enable_tke¶
-
VerosState.
tke
¶ - Units
m^2/s^2
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
Turbulent kinetic energy
-
VerosState.
dtke
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
Turbulent kinetic energy tendency
enable_eke¶
-
VerosState.
eke
¶ - Units
m^2/s^2
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
meso-scale energy
-
VerosState.
deke
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
meso-scale energy tendency
-
VerosState.
eke_diss_iw
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Dissipation of EKE to internal waves
-
VerosState.
eke_diss_tke
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Dissipation of EKE to TKE
enable_eke_leewave_dissipation¶
-
VerosState.
c_lee
¶ - Units
1/s
- Dimensions
xt, yt
- Type
- Attributes
Lee wave dissipation coefficient
enable_idemix¶
-
VerosState.
E_iw
¶ - Units
m^2/s^2
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
Internal wave energy
-
VerosState.
dE_iw
¶ - Units
m^2/s^2
- Dimensions
xt, yt, zw, timesteps
- Type
- Attributes
Internal wave energy tendency
-
VerosState.
c0
¶ - Units
m/s
- Dimensions
xt, yt, zw
- Type
- Attributes
Vertical internal wave group velocity
-
VerosState.
v0
¶ - Units
m/s
- Dimensions
xt, yt, zw
- Type
- Attributes
Horizontal internal wave group velocity
-
VerosState.
iw_diss
¶ - Units
m^2/s^3
- Dimensions
xt, yt, zw
- Type
- Attributes
Internal wave dissipation
-
VerosState.
forc_iw_surface
¶ - Units
m^3/s^3
- Dimensions
xt, yt
- Type
- Attributes
Internal wave surface forcing
Diagnostics¶
Diagnostics are separate objects (instances of subclasses of VerosDiagnostic
)
responsible for handling I/O, restart mechanics, and monitoring of the numerical
solution. All available diagnostics are instantiated and added to a dictionary
attribute VerosState.diagnostics
(with a key determined by their name attribute).
Options for diagnostics may be set during the VerosSetup.set_diagnostics()
method:
class MyModelSetup(VerosSetup):
...
def set_diagnostics(self, vs):
vs.diagnostics['averages'].output_variables = ['psi','u','v']
vs.diagnostics['averages'].sampling_frequency = 3600.
vs.diagnostics['snapshot'].output_variables += ['du']
Base class¶
This class implements some common logic for all diagnostics. This makes it easy to write your own diagnostics: Just derive from this class, and implement the virtual functions.
-
class
veros.diagnostics.diagnostic.
VerosDiagnostic
(vs)[source]¶ Bases:
object
Base class for diagnostics. Provides an interface and wrappers for common I/O.
Any diagnostic needs to implement the five interface methods and set some attributes.
-
name
= None¶ Name that identifies the current diagnostic
-
initialize
(vs)¶ Called at the end of setup. Use this to process user settings and handle setup.
-
diagnose
(vs)¶ Called with frequency
sampling_frequency
.
-
output
(vs)¶ Called with frequency
output_frequency
.
-
write_restart
(vs)¶ Responsible for writing restart files.
-
read_restart
(vs)¶ Responsible for reading restart files.
-
Available diagnostics¶
Currently, the following diagnostics are implemented and added to
VerosState.diagnostics
:
Snapshot¶
-
class
veros.diagnostics.snapshot.
Snapshot
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Writes snapshots of the current solution. Also reads and writes the main restart data required for restarting a Veros simulation.
-
output_path
= '{identifier}.snapshot.nc'¶ File to write to. May contain format strings that are replaced with Veros attributes.
-
name
= 'snapshot'¶
-
output_frequency
= None¶ Frequency (in seconds) in which output is written.
-
output_variables
= None¶ Variables to be written to output. Defaults to all Veros variables that have the attribute
output
.
-
restart_variables
= None¶ Variables to be written to restart. Defaults to all Veros variables that have the attribute
write_to_restart
.
-
Averages¶
-
class
veros.diagnostics.averages.
Averages
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Time average output diagnostic.
All registered variables are summed up when
diagnose()
is called, and averaged and output upon callingoutput()
.-
name
= 'averages'¶
-
output_path
= '{identifier}.averages.nc'¶ File to write to. May contain format strings that are replaced with Veros attributes.
-
output_variables
= None¶ Iterable containing all variables to be averaged. Changes have no effect after
initialize
has been called.
-
output_frequency
= None¶ Frequency (in seconds) in which output is written.
-
sampling_frequency
= None¶ Frequency (in seconds) in which variables are accumulated.
-
CFL monitor¶
-
class
veros.diagnostics.cfl_monitor.
CFLMonitor
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Diagnostic monitoring the maximum CFL number of the solution to detect instabilities.
Writes output to stdout (no binary output).
-
name
= 'cfl_monitor'¶
-
Tracer monitor¶
-
class
veros.diagnostics.tracer_monitor.
TracerMonitor
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Diagnostic monitoring global tracer contents / fluxes.
Writes output to stdout (no binary output).
-
name
= 'tracer_monitor'¶
-
output_frequency
= None¶ Frequency (in seconds) in which output is written.
-
Energy¶
-
class
veros.diagnostics.energy.
Energy
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Diagnose globally averaged energy cycle. Also averages energy in time.
-
name
= 'energy'¶
-
output_path
= '{identifier}.energy.nc'¶ File to write to. May contain format strings that are replaced with Veros attributes.
-
output_frequency
= None¶ Frequency (in seconds) in which output is written.
-
sampling_frequency
= None¶ Frequency (in seconds) in which variables are accumulated.
-
Overturning¶
-
class
veros.diagnostics.overturning.
Overturning
(vs)[source]¶ Bases:
veros.diagnostics.diagnostic.VerosDiagnostic
Isopycnal overturning diagnostic. Computes and writes vertical streamfunctions (zonally averaged).
-
name
= 'overturning'¶
-
output_path
= '{identifier}.overturning.nc'¶ File to write to. May contain format strings that are replaced with Veros attributes.
-
output_frequency
= None¶ Frequency (in seconds) in which output is written.
-
sampling_frequency
= None¶ Frequency (in seconds) in which variables are accumulated.
-
p_ref
= 2000.0¶ Reference pressure for isopycnals
-
Command line tools¶
After installing Veros, you can call these scripts from the command line from any location on your system.
veros¶
This is a wrapper script that provides easy access to all Veros command line tools.
Usage: veros [OPTIONS] COMMAND [ARGS]...
Veros command-line tools
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
copy-setup Copy a standard setup to another directory.
create-mask Creates a mask image from a given netCDF file
resubmit Re-run a Veros setup several times
veros-create-mask¶
Usage: veros create-mask [OPTIONS] INFILE
Creates a mask image from a given netCDF file
Options:
-v, --variable TEXT Variable holding topography data (default: z)
-o, --outfile TEXT Output filename (default: topography.png)
-s, --scale INTEGER... Standard deviation in grid cells for Gaussian
smoother (default: disable smoother)
--help Show this message and exit.
veros-copy-setup¶
Usage: veros copy-setup [OPTIONS] SETUP
Copy a standard setup to another directory.
Available setups:
acc, acc_sector, global_1deg, global_4deg, global_flexible,
north_atlantic, wave_propagation
Example:
$ veros copy-setup global_4deg --to ~/veros-setups/4deg-lowfric
Further directories containing setup templates can be added to this
command via the VEROS_SETUP_DIR environment variable.
Options:
--to PATH Target directory, must not exist (default: copy to current
working directory)
--help Show this message and exit.
veros-resubmit¶
Usage: veros resubmit [OPTIONS]
Performs several runs of Veros back to back, using the previous run as
restart input.
Intended to be used with scheduling systems (e.g. SLURM or PBS).
Options:
-i, --identifier TEXT Base identifier of the simulation [required]
-n, --num-runs INTEGER Total number of runs to execute [required]
-l, --length-per-run FLOAT Length (in seconds) of each run [required]
-c, --veros-cmd COMMAND The command that is used to call veros (quoted)
[required]
--callback CMD Command to call after each run has finished
(quoted, default: call self)
--help Show this message and exit.
Python API¶
Veros setup class¶
-
class
veros.
VerosSetup
(state=None, override=None, plugins=None)[source]¶ Bases:
object
Main class for Veros, used for building a model and running it.
Note
This class is meant to be subclassed. Subclasses need to implement the methods
set_parameter()
,set_topography()
,set_grid()
,set_coriolis()
,set_initial_conditions()
,set_forcing()
, andset_diagnostics()
.- Parameters
backend (
bool
, optional) – Backend to use for array operations. Possible values arenumpy
andbohrium
. Defaults toNone
, which tries to read the backend from the command line (set via a flag-b
/--backend
), and usesnumpy
if no command line argument is given.loglevel (one of {debug, info, warning, error, critical}, optional) – Verbosity of the model. Tries to read value from command line if not given (
-v
/--loglevel
). Defaults toinfo
.
Example
>>> import matplotlib.pyplot as plt >>> from veros import VerosSetup >>> >>> class MyModel(VerosSetup): >>> ... >>> >>> simulation = MyModel(backend='bohrium') >>> simulation.run() >>> plt.imshow(simulation.state.psi[..., 0]) >>> plt.show()
-
set_parameter
(vs)[source]¶ To be implemented by subclass.
First function to be called during setup. Use this to modify the model settings.
Example
>>> def set_parameter(self, vs): >>> vs.nx, vs.ny, vs.nz = (360, 120, 50) >>> vs.coord_degree = True >>> vs.enable_cyclic = True
-
set_initial_conditions
(vs)[source]¶ To be implemented by subclass.
May be used to set initial conditions.
Example
>>> @veros_method >>> def set_initial_conditions(self, vs): >>> vs.u[:, :, :, vs.tau] = np.random.rand(vs.u.shape[:-1])
-
set_grid
(vs)[source]¶ To be implemented by subclass.
Has to set the grid spacings
dxt
,dyt
, anddzt
, along with the coordinates of the grid origin,x_origin
andy_origin
.Example
>>> @veros_method >>> def set_grid(self, vs): >>> vs.x_origin, vs.y_origin = 0, 0 >>> vs.dxt[...] = [0.1, 0.05, 0.025, 0.025, 0.05, 0.1] >>> vs.dyt[...] = 1. >>> vs.dzt[...] = [10, 10, 20, 50, 100, 200]
-
set_coriolis
(vs)[source]¶ To be implemented by subclass.
Has to set the Coriolis parameter
coriolis_t
at T grid cells.Example
>>> @veros_method >>> def set_coriolis(self, vs): >>> vs.coriolis_t[:, :] = 2 * vs.omega * np.sin(vs.yt[np.newaxis, :] / 180. * vs.pi)
-
set_topography
(vs)[source]¶ To be implemented by subclass.
Must specify the model topography by setting
kbot
.Example
>>> @veros_method >>> def set_topography(self, vs): >>> vs.kbot[:, :] = 10 >>> # add a rectangular island somewhere inside the domain >>> vs.kbot[10:20, 10:20] = 0
-
set_forcing
(vs)[source]¶ To be implemented by subclass.
Called before every time step to update the external forcing, e.g. through
forc_temp_surface
,forc_salt_surface
,surface_taux
,surface_tauy
,forc_tke_surface
,temp_source
, orsalt_source
. Use this method to implement time-dependent forcing.Example
>>> @veros_method >>> def set_forcing(self, vs): >>> current_month = (vs.time / (31 * 24 * 60 * 60)) % 12 >>> vs.surface_taux[:, :] = vs._windstress_data[:, :, current_month]
-
set_diagnostics
(vs)[source]¶ To be implemented by subclass.
Called before setting up the diagnostics. Use this method e.g. to mark additional variables for output.
Example
>>> @veros_method >>> def set_diagnostics(self, vs): >>> vs.diagnostics['snapshot'].output_vars += ['drho', 'dsalt', 'dtemp']
-
after_timestep
(vs)[source]¶ Called at the end of each time step. Can be used to define custom, setup-specific events.
-
run
(show_progress_bar=None)[source]¶ Main routine of the simulation.
Note
Make sure to call
setup()
prior to this function.- Parameters
show_progress_bar (
bool
, optional) – Whether to show fancy progress bar via tqdm. By default, only show if stdout is a terminal and Veros is running on a single process.
Veros state class¶
veros_method decorator¶
-
veros.
veros_method
(function=None, **kwargs)[source]¶ Decorator that injects the current backend as variable
np
into the wrapped function.Note
This decorator should be applied to all functions that make use of the computational backend (even when subclassing
veros.Veros
). The first argument to the decorated function must be a Veros instance.Example
>>> from veros import Veros, veros_method >>> >>> class MyModel(Veros): >>> @veros_method >>> def set_topography(self): >>> self.kbot[...] = np.random.randint(0, self.nz, size=self.kbot.shape)
Runtime settings & state¶
Tools & utilities¶
Assets¶
-
veros.tools.assets.
get_assets
(asset_id, asset_file)[source]¶ Handles automatic download and verification of external assets (such as forcing files).
By default, assets are stored in
$HOME/.veros/assets
(can be overwritten by settingVEROS_ASSET_DIR
environment variable to the desired location).- Parameters
- Returns
A
dict
mapping identifier of each asset to file name on disk.
Example
>>> get_assets('mysetup', 'assets.yml') { "forcing": "/home/user/.veros/assets/mysetup/mysetup_forcing.h5", "initial_conditions": "/home/user/.veros/assets/mysetup/initial.h5" }
In this case,
assets.yml
contains:forcing: url: https://mywebsite.com/veros_assets/mysetup_forcing.h5 md5: ef3be0a58782771c8ee5a6d0206b87f6 initial_conditions: url: https://mywebsite.com/veros_assets/initial.h5 md5: d1b4e0e199d7a5883cf7c88d3d6bcb28
CLI¶
-
veros.tools.cli.
cli
(run)[source]¶ Decorator that wraps the decorated function with the Veros setup command line interface.
Example
>>> @veros.tools.cli.cli() >>> def run_setup(override): ... sim = MyVerosSetup(override=override) ... sim.run() ... >>> if __name__ == '__main__': ... run_setup()
This script then automatically supports settings to be specified from the command line:
$ python my_setup.py --help Usage: my_setup.py [OPTIONS] Options: -b, --backend [numpy|bohrium] Backend to use for computations (default: numpy) -v, --loglevel [trace|debug|info|warning|error|critical] Log level used for output (default: info) -s, --override SETTING VALUE Override default setting, may be specified multiple times -p, --profile-mode Write a performance profile for debugging (default: false) -n, --num-proc INTEGER... Number of processes in x and y dimension (requires execution via mpirun) --help Show this message and exit.
Setup tools¶
-
veros.tools.setup.
interpolate
(coords, var, interp_coords, missing_value=None, fill=True, kind='linear')[source]¶ Interpolate globally defined data to a different (regular) grid.
- Parameters
coords – Tuple of coordinate arrays for each dimension.
var (
ndarray
of dim (nx1, …, nxd)) – Variable data to interpolate.interp_coords – Tuple of coordinate arrays to interpolate to.
missing_value (optional) – Value denoting cells of missing data in
var
. Is replaced by NaN before interpolating. Defaults to None, which means no replacement is taking place.fill (bool, optional) – Whether NaN values should be replaced by the nearest finite value after interpolating. Defaults to
True
.kind (str, optional) – Order of interpolation. Supported are nearest and linear (default).
- Returns
ndarray
containing the interpolated values on the grid spanned byinterp_coords
.
-
veros.tools.setup.
fill_holes
(data)[source]¶ A simple inpainting function that replaces NaN values in data with the nearest finite value.
-
veros.tools.setup.
get_periodic_interval
(current_time, cycle_length, rec_spacing, n_rec)[source]¶ Used for linear interpolation between periodic time intervals.
One common application is the interpolation of external forcings that are defined at discrete times (e.g. one value per month of a standard year) to the current time step.
- Parameters
- Returns
Indices and weights for the interpolated record array.
- Return type
tuple
containing (n1, f1), (n2, f2)
Example
The following interpolates a record array
data
containing 12 monthly values to the current time step:>>> year_in_seconds = 60. * 60. * 24. * 365. >>> current_time = 60. * 60. * 24. * 45. # mid-february >>> print(data.shape) (360, 180, 12) >>> (n1, f1), (n2, f2) = get_periodic_interval(current_time, year_in_seconds, year_in_seconds / 12, 12) >>> data_at_current_time = f1 * data[..., n1] + f2 * data[..., n2]
-
veros.tools.setup.
make_cyclic
(longitude, array=None, wrap=360.0)[source]¶ Create a cyclic version of a longitude array and (optionally) another array.
- Parameters
longitude (ndarray) – Longitude array of shape (nlon, …).
array (ndarray) – Another array that is to be made cyclic of shape (nlon, …).
wrap (float) – Wrapping value, defaults to 360 (degrees).
- Returns
Tuple containing (cyclic_longitudes, cyclic_array) if array is given, otherwise just the ndarray cyclic_longitudes of shape (2 * nlon, …).
-
veros.tools.setup.
get_coastline_distance
(coords, coast_mask, spherical=False, radius=None, num_candidates=None, n_jobs=-1)[source]¶ Calculate the (approximate) distance of each water cell from the nearest coastline.
- Parameters
coords (tuple of ndarrays) – Tuple containing x and y (longitude and latitude) coordinate arrays of shape (nx, ny).
coast_mask (ndarray) – Boolean mask indicating whether a cell is a land cell (must be same shape as coordinate arrays).
spherical (bool) – Use spherical instead of Cartesian coordinates. When this is True, cyclical boundary conditions are used, and the resulting distances are only approximate. Cells are pre-sorted by Euclidean lon-lat distance, and great circle distances are calculated for the first num_candidates elements. Defaults to False.
radius (float) – Radius of spherical coordinate system. Must be given when spherical is True.
num_candidates (int) – Number of candidates to calculate great circle distances for for each water cell. The higher this value, the more accurate the returned distances become when spherical is True. Defaults to the square root of the number of coastal cells.
n_jobs (int) – Number of parallel jobs to determine nearest neighbors (defaults to -1, which uses all available threads).
- Returns
ndarray
of shape (nx, ny) indicating the distance to the nearest land cell (0 if cell is land).
Example
The following returns coastal distances of all T cells for a spherical Veros setup.
>>> coords = np.meshgrid(self.xt[2:-2], self.yt[2:-2], indexing='ij') >>> dist = tools.get_coastline_distance(coords, self.kbot > 0, spherical=True, radius=self.radius)
-
veros.tools.setup.
get_uniform_grid_steps
(total_length, stepsize)[source]¶ Get uniform grid step sizes in an interval.
- Parameters
- Returns
ndarray
of grid steps
Example
>>> uniform_steps = uniform_grid_setup(6., 0.25) >>> uniform_steps [ 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25 ]
-
veros.tools.setup.
get_stretched_grid_steps
(n_cells, total_length, minimum_stepsize, stretching_factor=2.5, two_sided_grid=False, refine_towards='upper')[source]¶ Computes stretched grid steps for regional and global domains with either one or two-sided stretching using a hyperbolic tangent stretching function.
- Parameters
n_cells (int) – Number of grid points.
total_length (float) – Length of the grid interval to be covered (sum of the resulting grid steps).
minimum_stepsize (float) – Grid step size on the lower end of the interval.
stretching_factor (float, optional) – Coefficient of the tanh stretching function. The higher this value, the more abrupt the step sizes change.
two_sided_grid (bool, optional) – If set to True, the resulting grid will be symmetrical around the center. Defaults to False.
refine_towards ('upper' or 'lower', optional) – The side of the interval that is to be refined. Defaults to ‘upper’.
- Returns
ndarray
of shape (n_cells) containing grid steps.
Examples
>>> dyt = get_stretched_grid_steps(14, 180, 5) >>> dyt [ 5.10517337 5.22522948 5.47813251 5.99673813 7.00386752 8.76808565 11.36450896 14.34977676 16.94620006 18.71041819 19.71754758 20.2361532 20.48905624 20.60911234] >>> dyt.sum() 180.0
>>> dyt = get_stretched_grid_steps(14, 180, 5, stretching_factor=4.) >>> dyt [ 5.00526979 5.01802837 5.06155549 5.20877528 5.69251688 7.14225176 10.51307232 15.20121339 18.57203395 20.02176884 20.50551044 20.65273022 20.69625734 20.70901593] >>> dyt.sum() 180.0
-
veros.tools.setup.
get_vinokur_grid_steps
(n_cells, total_length, lower_stepsize, upper_stepsize=None, two_sided_grid=False, refine_towards='upper')[source]¶ Computes stretched grid steps for regional and global domains with either one or two-sided stretching using Vinokur stretching.
This stretching function minimizes discretization errors on finite difference grids.
- Parameters
n_cells (int) – Number of grid points.
total_length (float) – Length of the grid interval to be covered (sum of the resulting grid steps).
lower_stepsize (float) – Grid step size on the lower end of the interval.
upper_stepsize (float or
None
, optional) – Grid step size on the upper end of the interval. If not given, the one-sided version of the algorithm is used (that enforces zero curvature on the upper end).two_sided_grid (bool, optional) – If set to True, the resulting grid will be symmetrical around the center. Defaults to False.
refine_towards ('upper' or 'lower', optional) – The side of the interval that is to be refined. Defaults to ‘upper’.
- Returns
ndarray
of shape (n_cells) containing grid steps.
- Reference:
Vinokur, Marcel, On One-Dimensional Stretching Functions for Finite-Difference Calculations, Journal of Computational Physics. 50, 215, 1983.
Examples
>>> dyt = get_vinokur_grid_steps(14, 180, 5, two_sided_grid=True) >>> dyt [ 18.2451554 17.23915939 15.43744632 13.17358802 10.78720589 8.53852027 6.57892471 6.57892471 8.53852027 10.78720589 13.17358802 15.43744632 17.23915939 18.2451554 ] >>> dyt.sum() 180.
>>> dyt = get_vinokur_grid_steps(14, 180, 5, upper_stepsize=10) >>> dyt [ 5.9818365 7.3645667 8.92544833 10.61326984 12.33841985 13.97292695 15.36197306 16.3485688 16.80714121 16.67536919 15.97141714 14.78881918 13.27136448 11.57887877 ] >>> dyt.sum() 180.
Numerical operators¶
Distributed communication primitives¶
How to use plug-ins¶
A plug-in is an optional extension for Veros that you can use to enable additional physics, outputs, or diagnostics.
Note
Plug-ins do not necessarily meet the same quality standards as the Veros core, and not all plug-ins are directly affiliated with Veros or the Veros developers. You should carefully check whether a given plug-in fits your needs.
As a first step, install the plug-in you want to use, e.g. veros-bgc
via
$ pip install veros-bgc
You can then immediately use any custom setups included in the plug-in:
$ veros copy-setup bgc_global_4deg
To use a plug-in in a Veros setup, all you need to do is to import it and add it to the __veros_plugins__
attribute of your setup class:
import veros_bgc
class MySetup(VerosSetup):
__veros_plugins__ = (veros_bgc,)
# - rest of the setup definition -
This step is probably not necessary if you use a setup that was shipped with the plug-in, but in doubt you should double-check that the plug-in is activated properly.
See also
For more information, refer to the documentation of the plug-in in question. You can find some suggestions in the contents of this section.
How to write a Veros plug-in¶
Writing a plug-in for Veros is relatively simple.
A plug-in can be any Python package that accepts a VerosState
object.
The plug-in is then free to modify the model state in any way it pleases.
The only requirement for the plug-in to be usable in Veros setups is that it declares a special object in its top __init__.py
file:
__VEROS_INTERFACE__ = dict(
name='my-plugin',
setup_entrypoint=my_setup_function,
run_entrypoint=my_main_function
)
The functions passed in setup_entrypoint
and run_entrypoint
are then called by Veros during model set-up and after each time step, respectively, with the model state as the sole argument.
An example for these functions could be:
from veros import veros_method
@veros_method
def my_setup_function(vs):
pass
@veros_method
def my_main_function(vs):
# apply simple ice mask
mask = np.logical_and(vs.temp[:, :, -1, vs.tau] * vs.maskT[:, :, -1] < -1.8,
vs.forc_temp_surface < 0.)
vs.forc_temp_surface[mask] = 0.0
vs.forc_salt_surface[mask] = 0.0
In this case, the setup function does nothing, while the main function sets temperature and salinity forcing to 0 where the surface temperature is smaller than -1.8 degrees (a very crude sea ice model).
Custom settings, variables, and diagnostics¶
In real-world applications, you probably want to use custom settings, variables, and/or diagnostics in your plug-in.
You can specify those as additional arguments to __VEROS_INTERFACE__
:
__VEROS_INTERFACE__ = dict(
name='my-plugin',
setup_entrypoint=my_setup_function,
run_entrypoint=my_main_function,
settings=my_settings,
variables=my_variables,
conditional_variables=my_conditional_variables,
diagnostics=[MyDiagnostic]
)
In this case, my_settings
is a dict
mapping the name of the setting to a Setting
object:
from collections import OrderedDict # to preserve order
from veros.settings import Setting
my_settings = OrderedDict([
('enable_my_plugin', Setting(False, bool, 'Enable my plugin')),
('temperature_cutoff', Setting(-1.8, float, 'Cut-off surface temperature')),
])
Similarly, for variables and conditional variables:
from collections import OrderedDict # to preserve order
from veros.variables import Variable, T_GRID
my_variables = OrderedDict([
('my_variable', Variable('Description', T_GRID, 'unit', 'Long description')),
])
my_conditional_variables = OrderedDict([
('enable_my_plugin', # condition
OrderedDict([
('my_conditional_variable', Variable(
'description', T_GRID, 'unit', 'Long description'
)),
])),
])
The so-defined settings and variables are then available as attributes of the Veros state object, as usual:
@veros_method
def my_function(vs):
if vs.enable_my_plugin:
vs.my_variable[...] = 0.
See also
For more inspiration on how to specify settings and variables, have a look at the built-in settings.py
and variables.py
files.
Diagnostics are defined similarly, but they have to be a subclass of VerosDiagnostic
.
Shipping custom model setups¶
You can use a special entrypoint in the setup.py
file of your plug-in to inform the Veros command-line interface of your custom setups:
from setuptools import setup
setup(
name='my-plugin',
packages='my_plugin',
entry_points={
'veros.setup_dirs': [
'my_plugin = my_plugin.setup'
]
}
)
This assumes, that your custom setups are located in the folder my_plugin/setup
.
Then, veros copy-setup will automatically find your custom setups if the plug-in is installed:
$ veros copy-setup --help
Usage: veros copy-setup [OPTIONS] SETUP
Copy a standard setup to another directory.
Available setups:
acc, acc_sector, eady, global_1deg, global_4deg,
global_flexible, my_setup, north_atlantic, wave_propagation
Example:
$ veros copy-setup global_4deg --to ~/veros-setups/4deg-lowfric
Further directories containing setup templates can be added to this
command via the VEROS_SETUP_DIR environment variable.
Options:
--to PATH Target directory, must not exist (default: copy to current
working directory)
--help Show this message and exit.
In this case, the custom setup is located in the folder my_plugin/setup/my_setup
, and thus shows up as my_setup
.
Frequently asked questions¶
Which backend should I choose to run my model (NumPy / Bohrium)?¶
Because in its current state Bohrium carries some computational overhead, this mostly depends on your problem size and the architecture you want to use. As a rule of thumb, switching from NumPy to Bohrium is beneficial if your set-up contains at least 1,000,000 elements (total number of elements in a 3-dimensional array, i.e., \(n_x n_y n_z\)). You can also use our benchmarks for general orientation.
Benchmarks¶
Note
The following benchmarks are for general orientation only. Benchmark results are highly platform dependent; your mileage may vary.
Veros compared to PyOM2¶
The following figurew present some benchmarks that compare the performance of Veros and pyOM 2.1 depending on the problem size:
Veros runtime estimates on the DC3 cluster¶
The following figure presents estimates of Veros runtime required for 1 year prediction on CPU and GPU nodes of the DC3 cluster. The estimates were done for ACC, Wave propagation and Global cases with different spatial and temporal resolution.
For more details on the cases configuration see the setup gallery.
Runtime estimates on a cluster node with 32 CPU cores (Bh CPU) and on a cluster node with 24 CPU cores and an NVidia Tesla P100 GPU (Bh GPU).¶
Publications¶
Papers¶
Häfner, D., Jacobsen, R. L., Eden, C., Kristensen, M. R. B., Jochum, M., Nuterman, R., and Vinter, B.: Veros v0.1 – a fast and versatile ocean simulator in pure Python, Geosci. Model Dev., 11, 3299-3312, https://doi.org/10.5194/gmd-11-3299-2018, 2018.
Talks¶
Veros — A High-Performance Ocean Simulator Written in Pure Python. A talk held at the 98th Annual Meeting of the American Meteorological Society (AMS). Abstract and slides available.
A Fast Versatile Ocean Simulator (Veros) in Pure Python. A talk held at the European Geosciences Union General Assembly 2018, Vienna, Austria. Abstract
Contact¶
If you want to report a bug in Veros, have a technical inquiry, or want to ask for a missing feature, please use our issue tracker on GitHub.
In case you have general questions about Veros, please contact the maintainer of the Veros repository.