Instructions for setting up and running ISOMIP+ Ocean0 on LANL IC¶
In what follows, replace username
with your user name.
1. SSH tricks¶
A couple of tricks for your laptop if you’re not already using them: Save your SSH connections:
vim ~/.ssh/config
Add the following:
Host *
ControlMaster auto
ControlPath ~/.ssh/connections/%r@%h:%p
ServerAliveInterval 300
Host wtrw
Hostname wtrw.lanl.gov
User username
mkdir ~/.ssh/connections
Alias connections to LANL HPC machines:
vim ~/.bashrc
Add:
alias gr="ssh -t wtrw ssh gr-fe1"
alias ba="ssh -t wtrw ssh ba-fe2"
alias ko="ssh -t wtrw ssh ko-fe"
2. Making sure git is set up nicely¶
2.1 Storing your LANL IC SSH key on GitHub¶
It’s useful to set up GitHub to know your public SSH key from LANL IC if you haven’t already done this. It means you don’t have to type your password for GitHub each time you git fetch, git push, etc.
I believe this is the right link for more details If you haven’t done this already and this gives you trouble, let me know and we can work through it together.
2.2 git settings¶
On IC or on your laptop, make sure you’ve got these settings defined:
git config --global user.name "First Last"
git config --global user.email user@domain.com
git config --global core.editor vim
git config --global push.default nothing
git config --global color.ui true
git config --global core.autocrlf input
git config --global core.whitespace trailing-space
git config --global alias.logg "log --graph --oneline --decorate"
I use git logg
all the time so this last alias is particularly important.
One last config option specific to LANL IC:
git config --global http.proxy http://proxyout.lanl.gov:8080
2.3 git tab completion¶
Download git-completion.bash
cd ~
wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash
Add this to your .bashrc
module load git
source git-completion.bash
3. Forking and Cloning E3SM¶
Make your own fork by clicking “Fork” at the top right:
Go to your new fork (e.g. https://github.com/username/E3SM )
Whenever you ever need to know the link to clone your fork
Click on “Clone or download”
If it says “Clone with HTTPS”, click Use SSH (either works but SSH will use the SSH keys you’ve set up above and you never have to type my Git password.)
Copy the link with the clipboard icon
In a terminal window, log in to a LANL machine (I use Grizzly from here on except where stated):
ssh -t wtrw ssh gr-fe1
Make a directory for the code, e.g.:
mkdir /usr/projects/climate/username
cd /usr/projects/climate/username
mkdir -p e3sm
cd e3sm
Clone the repo:
git clone git@github.com:username/E3SM.git E3SM
cd E3SM
Rename your remote so it’s easier to not confuse it with other forks:
git remote rename origin username/E3SM
Add the main repo:
git remote add E3SM-Project/E3SM git@github.com:E3SM-Project/E3SM.git
Add my fork (you can add other people’s forks in the same way):
git remote add xylar/E3SM git@github.com:xylar/E3SM.git
Get the latest version of all the remotes (pruning anything that has been deleted):
git fetch --all -p
Let’s store some settings you’ll need to load every time you build MPAS. The following are only appropriate for Grizzly and we’ll need a similar file with settings for Badge and any other machines we might use in the future.
vim ../setup_gr.bash
In this file, put:
echo "Setting up grizzly intel environment for building and running MPAS"
module purge
module use /usr/projects/climate/SHARED_CLIMATE/modulefiles/all/
module load git
if [ -f "load_compass_env.sh" ]; then
# this figures out from the local checkout of the compass repo or from
# within a test case which version of the compass environment to load
source load_compass_env.sh
else
# if we're not in a directory with "load_compass_env.sh", load the default
source /usr/projects/climate/SHARED_CLIMATE/anaconda_envs/base/etc/profile.d/conda.sh
# this is the current version, but will need to be updated relatively often
conda activate compass_0.1.8
fi
module load friendly-testing
module load intel/19.0.4 intel-mpi/2019.4 hdf5-parallel/1.8.16 pnetcdf/1.11.2 netcdf-h5parallel/4.7.3 mkl/2019.0.4 scorpio/pio2/1.10.1
export I_MPI_CC=icc
export I_MPI_CXX=icpc
export I_MPI_F77=ifort
export I_MPI_F90=ifort
export USE_PIO2=true
export AUTOCLEAN=true
export HDF5_USE_FILE_LOCKING=FALSE
4. Checking out an E3SM branch and building the model¶
Note: this is a good place to come back to when you need to start over on a new branch.
Add a “worktree”, a copy of the repo that we can point to a different branch.
We will work with the main branch, master
:
cd /usr/projects/climate/username/e3sm/E3SM
Let’s make sure we have the latest version of all the branches on all of the remotes
git fetch --all -p
Okay, now we’re ready to make a new folder to work from.
git worktree add ../ocean/my_branch -b ocean/my_branch
cd ../ocean/my_branch
Take a look at which branch were on:
git logg
We start off on E3SM-Project/E3SM/master
. If you want to point to a different branch,
you need to do a hard reset to put yourself there. Here’s an example:
git reset --hard xylar/E3SM/ocean/fancy_new_branch
git logg
Now source the file with modules and settings for building MPAS on grizzly:
source /usr/projects/climate/username/e3sm/setup_gr.bash
If all goes well, you should see comapss_py3.7
as part of your command prompt and you should be read to build MPAS.
make ifort
Take a coffee break, this will take some time. …
5. Setting up a test case¶
Okay you’re back and refreshed? Let’s set up a test case.
You also need to clone the compass repo and check out the legacy
branch:
git clone git@github.com:MPAS-Dev/compass.git
cd compass
git checkout legacy
git submodule update --init --recursive
COMPASS (COnfiguration of Model for Prediction Across Scales Setups – yes, a little tortured) is a set of python
scripts we use to set up and run our test cases. To build test cases, you need to tell COMPASS where to find a few
thing on Grizzly. Open a file config.ocean
and put the following in it:
# This file is the ocean core's configuration file. It is specific to the ocean
# core, and a specific machine. Each machine will configure this file
# differently, but it can be used to point on version of the testing
# infrastructure at a different version of the model.
# The namelists section defines paths to template namelists that will be used
# to generate specific namelists. Typically these will point to the forward and
# init namelists in the default_inputs directory after a successful build of
# the ocean model.
[namelists]
forward = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean/namelist.ocean.forward
init = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean/namelist.ocean.init
# The streams section defines paths to template streams files that will be used
# to generate specific streams files. Typically these will point to the forward and
# init streams files in the default_inputs directory after a successful build of
# the ocean model.
[streams]
forward = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean/streams.ocean.forward
init = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean/streams.ocean.init
# The executables section defines paths to required executables. These
# executables are provided for use by specific test cases.
# Full paths should be provided in order to access the executables from
# anywhere on the machine.
[executables]
model = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean/ocean_model
# The paths section describes paths that are used within the ocean core test
# cases.
[paths]
# The mesh_database and the initial_condition_database are locations where
# meshes / initial conditions might be found on a specific machine. They can be
# the same directory, or different directory. Additionally, if they are empty
# some test cases might download data into them, which will then be reused if
# the test case is run again later.
mpas_model = /usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean
mesh_database = /usr/projects/regionalclimate/COMMON_MPAS/ocean/grids/mesh_database
initial_condition_database = /usr/projects/regionalclimate/COMMON_MPAS/ocean/grids/initial_condition_database
bathymetry_database = /usr/projects/regionalclimate/COMMON_MPAS/ocean/grids/bathymetry_database
In theory, you can point to default namelists, streams files and executables for other branches than the one you’re currently on but that’s very rarely (if ever) going to be useful to you so you’ll just have to bear with all these redundant references to
/usr/projects/climate/username/e3sm/E3SM/components/mpas-ocean
If you want to set up a worktree for a different branch, the config.ocean
looks the same except that you would need to replace the above path with the
one for your new worktree.
List the available test cases:
./list_testcases.py
At present, there are 140 of them! Let’s look at only the ISOMIP+ ones
(core: ocean
, configuration: isomip_plus
):
./list_testcases.py -o ocean -c isomip_plus
There are 2 resolutions (2 km and 5 km) and 3 test cases at each resolution (Ocean0, 1 and 2). For now, we’re going to focus on Ocean0, which has boundary conditions and ocean properties consistent with a (very) warm continental shelf. This one spins up to a quasi-steady state in about 2 years (compared to several decades for the other 2, which are purposefully designed as transient experiments) so it’s a good starting point. We’ll use the 2 km version because the domain is only 80 km wide, so 5 km is really quite coarse. Plus, this is the “standard” resolution for ISOMIP+.
Set up the test case as follows:
./setup_testcase.py -o ocean -c isomip_plus -r 2km -t Ocean0 -f config.ocean -m runtime_definitions/srun.xml --work_dir /lustre/scratch4/turquoise/username/isomip_plus_Ocean0
6. Running the test case¶
We’ll do a short test run (1 month) to make sure everything is working, rather than jumping into a 2-year simulation.
cd /lustre/scratch4/turquoise/username/isomip_plus_Ocean0/ocean/isomip_plus/2km/Ocean0/
salloc --nodes=1 --time=0:20:00 --account=e3sm
source /usr/projects/climate/username/e3sm/setup_gr.bash
./run_test.py
If you don’t have access to the e3sm
account, ask one of the COSIM team for
help to get access. Somewhere on the HPC website, there is a way to ask for
access, but they may just be able to add you directly.
7. Running a full 2-year Ocean0 simulation¶
For this one, you should use a job script.
cd /lustre/scratch4/turquoise/username/isomip_plus_Ocean0/ocean/isomip_plus/2km/Ocean0/forward
vim job_script.bash
Put this in the job script:
#!/bin/bash
#SBATCH --nodes=4
#SBATCH --time=4:00:00
#SBATCH --account=e3sm
#SBATCH --job-name=Ocean0
#SBATCH --output=Ocean0.o%j
#SBATCH --error=Ocean0.e%j
#SBATCH --qos=interactive
# exit if there are any errors
set -e
source /usr/projects/climate/username/e3sm/setup_gr.bash
months_per_job=24
end_date="0003-01-01_00:00:00"
for month in `seq 0 $months_per_job`
do
./check_progress.py -f namelist.ocean -e $end_date
./run.py
./setup_restart.py -f namelist.ocean
done
Submit the job:
sbatch job_script.bash
Once it’s running, monitor the progress with:
tail log.ocean.0000.out
This writes a message for each time step (if all is going well).
The simulation runs one month at a time and then does some adjustment in a python script to make sure sea level doesn’t get out of control (there’s a lot of melting going on so we have to have a compensating level of “evaporation” at the domain boundary). It also will check to see if we’ve already reached year 2 and won’t run again if so.
Some basic output is available in:
analysis_members/globalStats.0001-01-01_00.00.00.nc
To see the mean melt flux and how time is progressing there, do:
ncdump -v xtime,landIceFreshwaterFluxAvg analysis_members/globalStats.0001-01-01_00.00.00.nc | tail -n 50
Keep in mind that the units are kg m^{-2} s^{-1}
, not m/yr, so not the most
intuitive output. There is a viz
package in the isomip_plus
directory
that gets linked in each test case. You can also look at output in paraview.
8. Visualization¶
8.1 Running the default viz¶
Viz should be light enough weight that you can run it on the login node but you could get an interactive job if you prefer. It produces images, rather than anything interactive, so no need for x-windows or anything like that.
There should be a link to viz
in the forward
output directory. This is
a link to a python package (you can tell because it contains a __init__.py
(which is empty) and a __main__.py
, which is the main script for
visualization. To start with, we’ll run the default viz. If you don’t
already have the compass conda environment loaded, do:
source /usr/projects/climate/SHARED_CLIMATE/anaconda_envs/base/etc/profile.d/conda.sh
conda activate compass_0.1.8
Then, run:
python -m viz
This will run the main()
function in __main__.py
. You could optionally set
the input directory and the experiment number but the defaults are the current
directory and Ocean0
, respectively, so there’s no need in this case.
This will take maybe 10 or 15 minutes (most of it on the overturning
streamfunction). You should see something like:
barotropic streamfunction: 100% |##############################| Time: 0:00:15
compute and caching transport on MPAS grid:
[########################################] | 100% Completed | 7.2s
interpolating tansport on z-level grid: 100% |#################| Time: 0:10:13
caching transport on z-level grid:
[########################################] | 100% Completed | 2.2s
compute and caching vertical transport sum on z-level grid:
[########################################] | 100% Completed | 2.4s
bin overturning streamfunction: 100% |#########################| Time: 0:02:03
plotting barotropic streamfunction: 100% |#####################| Time: 0:00:08
plotting overturning streamfunction: 100% |####################| Time: 0:00:05
plotting melt rate: 100% |#####################################| Time: 0:00:07
plotting heat flux from ocean to ice-ocean interface: 100% |###| Time: 0:00:07
plotting heat flux into ice at ice-ocean interface: 100% |#####| Time: 0:00:07
plotting thermal driving: 100% |###############################| Time: 0:00:07
plotting haline driving: 100% |################################| Time: 0:00:07
plotting friction velocity: 100% |#############################| Time: 0:00:08
plotting top temperature: 100% |###############################| Time: 0:00:09
plotting bot temperature: 100% |###############################| Time: 0:00:08
plotting temperature section: 100% |###########################| Time: 0:00:05
plotting top salinity: 100% |##################################| Time: 0:00:08
plotting bot salinity: 100% |##################################| Time: 0:00:08
plotting salinity section: 100% |##############################| Time: 0:00:05
plotting top potential density: 100% |#########################| Time: 0:00:10
plotting bot potential density: 100% |#########################| Time: 0:00:08
plotting potential density section: 100% |#####################| Time: 0:00:05
running ffmpeg -y -r 30 -i ./plots/botPotRho/botPotRho_%04d.png -b:v 32000k -r 30 ./movies/botPotRho.mp4
running ffmpeg -y -r 30 -i ./plots/botSalinity/botSalinity_%04d.png -b:v 32000k -r 30 ./movies/botSalinity.mp4
running ffmpeg -y -r 30 -i ./plots/botTemp/botTemp_%04d.png -b:v 32000k -r 30 ./movies/botTemp.mp4
running ffmpeg -y -r 30 -i ./plots/bsf/bsf_%04d.png -b:v 32000k -r 30 ./movies/bsf.mp4
running ffmpeg -y -r 30 -i ./plots/frictionVelocity/frictionVelocity_%04d.png -b:v 32000k -r 30 ./movies/frictionVelocity.mp4
running ffmpeg -y -r 30 -i ./plots/halineDriving/halineDriving_%04d.png -b:v 32000k -r 30 ./movies/halineDriving.mp4
running ffmpeg -y -r 30 -i ./plots/iceHeatFlux/iceHeatFlux_%04d.png -b:v 32000k -r 30 ./movies/iceHeatFlux.mp4
running ffmpeg -y -r 30 -i ./plots/meltRate/meltRate_%04d.png -b:v 32000k -r 30 ./movies/meltRate.mp4
running ffmpeg -y -r 30 -i ./plots/oceanHeatFlux/oceanHeatFlux_%04d.png -b:v 32000k -r 30 ./movies/oceanHeatFlux.mp4
running ffmpeg -y -r 30 -i ./plots/osf/osf_%04d.png -b:v 32000k -r 30 ./movies/osf.mp4
running ffmpeg -y -r 30 -i ./plots/sectionPotRho/sectionPotRho_%04d.png -b:v 32000k -r 30 ./movies/sectionPotRho.mp4
running ffmpeg -y -r 30 -i ./plots/sectionSalinity/sectionSalinity_%04d.png -b:v 32000k -r 30 ./movies/sectionSalinity.mp4
running ffmpeg -y -r 30 -i ./plots/sectionTemp/sectionTemp_%04d.png -b:v 32000k -r 30 ./movies/sectionTemp.mp4
running ffmpeg -y -r 30 -i ./plots/thermalDriving/thermalDriving_%04d.png -b:v 32000k -r 30 ./movies/thermalDriving.mp4
running ffmpeg -y -r 30 -i ./plots/topPotRho/topPotRho_%04d.png -b:v 32000k -r 30 ./movies/topPotRho.mp4
running ffmpeg -y -r 30 -i ./plots/topSalinity/topSalinity_%04d.png -b:v 32000k -r 30 ./movies/topSalinity.mp4
running ffmpeg -y -r 30 -i ./plots/topTemp/topTemp_%04d.png -b:v 32000k -r 30 ./movies/topTemp.mp4
The more intresting results should be a series of movies in movies
and 4
time series plots in plots
(mean melt rate, total melt flux, mean thermal
driving and mean friction velocity) and the same plots in
timeSeriesBelow300m
, but this time averaged only over the deepest part of
the ice shelf (where much of the action is).
You’ll likely need to scp or rsync them to your laptop to view them. Let me know if it’s not clear what these are.
8.2 Doing your own viz¶
A starting point for doing your own viz is to make a local copy of
__main__.py
to edit:
cp viz/__main__.py myviz.py
vim myviz.py
You could, for example, take out the slow streamfunction stuff if you don’t need that (it was added because I required it as standard output in MISOMIP).
The script imports the following
from viz.streamfunction import compute_barotropic_streamfunction, \
compute_overturning_streamfunction
These are functions for computing the stream functions and writing them to NetCDF files.
from viz.plot import MoviePlotter, TimeSeriesPlotter
These can be used to create “plotter” object that can then produce either time-series plots or a series of image for making movies.
from viz.misomip import compute_misomip_interp_coeffs, interp_misomip
These are used to write out MISOMIP standard output on a regular grid.
You can look at streamfunction.py
, plot.py
and misomip.py
to learn
a bit more about what these do. There’s a bit of commenting, particularly for
the “public” functions that don’t start with an underscore.
Maybe simplify it down to eliminate the streamfunction and MISOMIP stuff, and don’t worry about the plots averaged over the deeper part of the ice draft (none of this is probably all that relevant to you):
#!/usr/bin/env python
import xarray
import argparse
from viz.plot import MoviePlotter, TimeSeriesPlotter
def main():
parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-f", "--folder", dest="folder",
help="Folder for plots", default='.')
parser.add_argument("-e", "--expt", dest="expt",
help="Experiment number (0, 1 or 2)", default=0)
args = parser.parse_args()
folder = args.folder
expt = args.expt
dsMesh = xarray.open_dataset('{}/init.nc'.format(folder))
ds = xarray.open_mfdataset('{}/timeSeriesStatsMonthly*.nc'.format(folder),
concat_dim='Time')
tsPlotter = TimeSeriesPlotter(inFolder=folder,
outFolder='{}/plots'.format(folder),
expt=expt)
tsPlotter.plot_melt_time_series()
mPlotter = MoviePlotter(inFolder=folder,
outFolder='{}/plots'.format(folder),
expt=expt)
mPlotter.plot_melt_rates()
mPlotter.plot_ice_shelf_boundary_variables()
mPlotter.plot_temperature()
mPlotter.plot_salinity()
mPlotter.plot_potential_density()
mPlotter.images_to_movies(outFolder='{}/movies'.format(folder),
framesPerSecond=30, extension='mp4')
if __name__ == '__main__':
main()
I’ve set things up to plot some of the more common fields by default. The following plot either time series or movies of some common fields related to the ice-ocean interface – melt rates, thermal driving, friction velocity, etc.
tsPlotter.plot_melt_time_series()
...
mPlotter.plot_melt_rates()
mPlotter.plot_ice_shelf_boundary_variables()
These functions plot 3D fields at the top of the ocean (either the ice draft or the sea surace), the sea floor and in a transect through the middle of the domain:
mPlotter.plot_temperature()
mPlotter.plot_salinity()
mPlotter.plot_potential_density()
You could also add your own custom fields as long as they’re available in the
timeSeriesStatsMonthly*.nc
files. Here are a couple of examples:
Here are a couple of examples:
# plot a time series of SST
areaCell = tsPlotter.dsMesh.areaCell
temperature = tsPlotter.ds.timeMonthly_avg_activeTracers_temperature
sst = temperature.isel(nVertLevels=0)
meanSST = (sst*areaCell).sum(dim='nCells')/areaCell.sum(dim='nCells')
tsPlotter.plot_time_series(meanSST, 'mean sea-surface temperature',
prefix='meanSST', units='deg C')
...
# plot the x and y components of velocity at top, bottom and transect
da = mPlotter.ds.timeMonthly_avg_velocityX
mPlotter.plot_3d_field_top_bot_section(
da, nameInTitle='x velocity', prefix='Vx', units='m/s',
vmin=-0.2, vmax=0.2)
da = mPlotter.ds.timeMonthly_avg_velocityY
mPlotter.plot_3d_field_top_bot_section(
da, nameInTitle='y velocity', prefix='Vy', units='m/s',
vmin=-0.2, vmax=0.2)
Make sure any new plots with the movie plotter happen before movies are made
(mPlotter.images_to_movies()
) so they get included in the movies.
The data sets (ds
) and data arrays (da
) come from xarray
, which is a
really handy package for working with NetCDF-style files in memory in python.
It’s a lot smarter about named dimensions than numpy
and a lot more easy
to manipulate than default python NetCDF4
data sets. But there’s a bit of a
learning curve involving a lot of Googling the documentation and StackOverflow.
Hopefully that’s a start…