Example on how to configure a case using mom6-tools

This is a very simple example showing how to read diag_config.yaml, create a case instance, compute a climatology and visualize the results.

Case Information

  • Case:

    • CASEROOT: Path to the root directory of the case: /glade/work/gmarques/cesm.cases/G/g.e30_a03c.GJRAv4.TL319_t232_wgx3_hycom1_N75.2024.079/

    • OCN_DIAG_ROOT: Directory for ocean diagnostics files: ncfiles/

    • SNAME: Identifier or short name of the case: "079"


Average Dates

  • Avg:

    • start_date: Start date for averaging data: '0031-01-01'

    • end_date: End date for averaging data: '0062-01-01'


CESM History File Naming Conventions

  • Fnames:

    • rho2: Format for density files: .mom6.h.rho2.????-??.nc

    • z: Format for depth files: .mom6.h.z.????-??.nc

    • native: Format for native files: .mom6.h.native.????-??.nc

    • sfc: Surface files naming convention: .mom6.h.sfc.????-??.nc

    • static: Static files naming convention: .mom6.h.static.nc

    • geom: Ocean geometry files naming convention: .mom6.h.ocean_geometry.nc


Transport Sections

  • Transports:

    • sections: List of sections where transports are computed, including observational estimates where applicable:

      • ``h.Agulhas_Section``: Uses umo component, range [129.8, 143.6]

      • ``h.Barents_Opening``: Uses vmo component, range [2.0]

      • ``h.Bering_Strait``: Uses vmo component, range [0.7, 1.1]

      • (Additional sections follow similar structure)


Ocean Catalog Path

  • oce_cat: Path to the ocean-related datasets catalog: /glade/u/home/gmarques/libs/oce-catalogs/reference-datasets.yml

[1]:
from mom6_tools.m6toolbox import cime_xmlquery
import yaml, os
import numpy as np
import xarray as xr
import matplotlib
from mom6_tools import m6toolbox
import warnings
warnings.filterwarnings('ignore')
[2]:
# Read in the yaml file
diag_config_yml_path = "diag_config.yml"
diag_config_yml = yaml.load(open(diag_config_yml_path,'r'), Loader=yaml.Loader)
[3]:
caseroot = diag_config_yml['Case']['CASEROOT']
casename = cime_xmlquery(caseroot, 'CASE')
DOUT_S = cime_xmlquery(caseroot, 'DOUT_S')
if DOUT_S:
  OUTDIR = cime_xmlquery(caseroot, 'DOUT_S_ROOT')+'/ocn/hist/'
else:
  OUTDIR = cime_xmlquery(caseroot, 'RUNDIR')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[3], line 2
      1 caseroot = diag_config_yml['Case']['CASEROOT']
----> 2 casename = cime_xmlquery(caseroot, 'CASE')
      3 DOUT_S = cime_xmlquery(caseroot, 'DOUT_S')
      4 if DOUT_S:

File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/mom6_tools/m6toolbox.py:47, in cime_xmlquery(caseroot, varname)
     45 """run CIME's xmlquery for varname in the directory caseroot, return the value"""
     46 try:
---> 47   value = subprocess.check_output(
     48       ["./xmlquery", "-N", "--value", varname],
     49       stderr=subprocess.STDOUT,
     50       cwd=caseroot,
     51   )
     52 except subprocess.CalledProcessError:
     53   value = subprocess.check_output(
     54       ["./xmlquery", "--value", varname], stderr=subprocess.STDOUT, cwd=caseroot
     55   )

File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    418         empty = b''
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    500     kwargs['stdout'] = PIPE
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:
    505         stdout, stderr = process.communicate(input, timeout=timeout)

File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    967         if self.text_mode:
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.
    982     for f in filter(None, (self.stdin, self.stdout, self.stderr)):

File ~/.asdf/installs/python/3.10.20/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1861     if errno_num != 0:
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: '/glade/work/gmarques/cesm.cases/G/g.e30_a07c_cesm.GJRAv4.TL319_t232_wgx3_hycom1_N75.2025.130/'
[4]:
print('Output directory is:', OUTDIR)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 print('Output directory is:', OUTDIR)

NameError: name 'OUTDIR' is not defined
[5]:
print('Casename is:', casename)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 print('Casename is:', casename)

NameError: name 'casename' is not defined
[6]:
# create an empty class object
class args:
  pass

args.static = casename+diag_config_yml['Fnames']['static']
args.native = casename+diag_config_yml['Fnames']['native']
args.geom =   casename+diag_config_yml['Fnames']['geom']
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 5
      2 class args:
      3   pass
----> 5 args.static = casename+diag_config_yml['Fnames']['static']
      6 args.native = casename+diag_config_yml['Fnames']['native']
      7 args.geom =   casename+diag_config_yml['Fnames']['geom']

NameError: name 'casename' is not defined
[7]:
# Load the grid
from mom6_tools.MOM6grid import MOM6grid

geom_file = OUTDIR+'/'+args.geom
if os.path.exists(geom_file):
  grd = MOM6grid(OUTDIR+'/'+args.static, geom_file, xrformat=True)
else:
  grd = MOM6grid(OUTDIR+'/'+args.static, xrformat=True)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[7], line 4
      1 # Load the grid
      2 from mom6_tools.MOM6grid import MOM6grid
----> 4 geom_file = OUTDIR+'/'+args.geom
      5 if os.path.exists(geom_file):
      6   grd = MOM6grid(OUTDIR+'/'+args.static, geom_file, xrformat=True)

NameError: name 'OUTDIR' is not defined
[8]:
# request 6 Dask workers as PBS batch jobs
# (drop cluster_class to run them on this node instead)
from mom6_tools.jobqueue import get_cluster

parallel, cluster, client = get_cluster(6, cluster_class='PBSCluster')
client
Starting a dask cluster: PBSCluster

Requesting 6 workers...

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[8], line 5
      1 # request 6 Dask workers as PBS batch jobs
      2 # (drop cluster_class to run them on this node instead)
      3 from mom6_tools.jobqueue import get_cluster
----> 5 parallel, cluster, client = get_cluster(6, cluster_class='PBSCluster')
      6 client

File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/mom6_tools/jobqueue.py:300, in get_cluster(nw, cluster_class, args, config, **kwargs)
    297 print('Requesting {} workers... \n'.format(nw))
    298 if is_jobqueue_cluster:
    299   # dask.config.set({'distributed.dashboard.link': '/proxy/{port}/status'})
--> 300   cluster = cluster_class(**kwargs)
    301   cluster.scale(nw)
    302 else:

File ~/checkouts/readthedocs.org/user_builds/mom6-tools/envs/latest/lib/python3.10/site-packages/dask_jobqueue/core.py:656, in JobQueueCluster.__init__(self, n_workers, job_cls, loop, security, shared_temp_directory, silence_logs, name, asynchronous, dashboard_address, host, scheduler_options, scheduler_cls, interface, protocol, config_name, **job_kwargs)
    653 self._job_kwargs = job_kwargs
    655 worker = {"cls": self.job_cls, "options": self._job_kwargs}
--> 656 if "processes" in self._job_kwargs and self._job_kwargs["processes"] > 1:
    657     worker["group"] = [
    658         "-" + str(i) for i in range(self._job_kwargs["processes"])
    659     ]
    661 self._dummy_job  # trigger property to ensure that the job is valid

TypeError: '>' not supported between instances of 'NoneType' and 'int'
[9]:
%time ds = xr.open_mfdataset(OUTDIR+'/'+casename+'.mom6.h.sfc.000?-??.nc', \
         parallel=True, data_vars='minimal', chunks={'time': 12},\
         coords='minimal', compat='override')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
File <timed exec>:1

NameError: name 'OUTDIR' is not defined
[10]:
ds
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 1
----> 1 ds

NameError: name 'ds' is not defined
[11]:
%matplotlib inline
# Plot mean SST
from mom6_tools.m6plot import xyplot

area = np.ma.masked_where(grd.wet == 0, np.ma.masked_invalid(grd.areacello))

dummy1 = np.ma.masked_where(grd.wet == 0, ds.tos.mean('time'))

xyplot(dummy1, grd.geolon, grd.geolat, area , suptitle='Mean SST', clim=(-2,32))
Basemap module not found. Some regional plots may not function properly
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[11], line 5
      2 # Plot mean SST
      3 from mom6_tools.m6plot import xyplot
----> 5 area = np.ma.masked_where(grd.wet == 0, np.ma.masked_invalid(grd.areacello))
      7 dummy1 = np.ma.masked_where(grd.wet == 0, ds.tos.mean('time'))
      9 xyplot(dummy1, grd.geolon, grd.geolat, area , suptitle='Mean SST', clim=(-2,32))

NameError: name 'grd' is not defined
[ ]: