CrocoDash package#

Subpackages#

Submodules#

CrocoDash.case module#

class CrocoDash.case.Case(*, cesmroot: str | Path, caseroot: str | Path, inputdir: str | Path, compset: str, ocn_grid: Grid, ocn_topo: Topo, ocn_vgrid: VGrid, atm_grid_name: str = 'TL319', rof_grid_name: str | None = None, ninst: int = 1, machine: str | None = None, project: str | None = None, override: bool = False, ntasks_ocn: int | None = None, job_queue: str | None = None, job_wallclock_time: str | None = None)#

Bases: object

This class represents a regional MOM6 case within the CESM framework. It is similar to the Experiment class in the regional_mom6 package, but with modifications to work within the CESM framework.

property bgc_in_compset#

Check if BGC is included in the compset.

property cice_in_compset#

Check if CICE is included in the compset.

configure_forcings(date_range: list[str], boundaries: list[str] = ['south', 'north', 'west', 'east'], product_name: str = 'GLORYS', function_name: str = 'get_glorys_data_script_for_cli', function_overrides: dict = None, **kwargs)#

Configure the boundary conditions and tides for the MOM6 case.

Sets up initial and boundary condition forcing data for MOM6 using a specified product and download function. Optionally configures tidal constituents if specified. Supports a large data workflow mode that defers data download and processing to an external script.

Parameters:
  • date_range (list of str) – Start and end dates for the forcing data, formatted as strings. Must contain exactly two elements.

  • boundaries (list of str, optional) – List of open boundaries to process (e.g., [“south”, “north”]). Default is [“south”, “north”, “west”, “east”].

  • product_name (str, optional) – Name of the forcing data product to use. Default is “GLORYS”.

  • function_name (str, optional) – Name of the function to call for downloading the forcing data. Default is “get_glorys_data_script_for_cli”.

  • function_overrides (dict, optional) – Overrides for function_name’s non-required arguments (e.g. {“member”: 3} to select a specific ensemble member for a CESM2-LENS2-style product). Keys must match one of the function’s non-required, defaulted parameters; any other key raises a ValueError. Without this, the function’s own defaults are used, which previously could only be changed by hand-editing config.json between configure_forcings() and process_forcings().

  • product_info (str | Path | dict, optional) – The equivalent MOM6 names to Product Names. Example: xh -> lat time -> valid_time salinity -> salt, as well as any other information required for product parsing The None option assumes the information is in raw_data_access/config under {product_name}.json. Every other option is copied there.

  • kwargs – These are the configuration options (please see accepted arguments in the configuration classes)

Raises:
  • TypeError – If inputs such as date_range, boundaries, or tidal_constituents are not lists of strings.

  • ValueError – If date_range does not have exactly two elements, or if tidal arguments are inconsistently specified. Also raised if an invalid product or function is provided, or if function_overrides contains a key that is not a valid overridable argument of function_name.

  • AssertionError – If the selected data product is not categorized as a forcing product.

Notes

  • Downloads forcing data (or creates a script) for each boundary and the initial condition unless the large data workflow is used.

  • In large data workflow mode, creates a folder structure and config.json file for later manual processing.

  • This method must be called before process_forcings().

See also

process_forcings

Executes the actual boundary, initial condition, and tide setup based on the configuration.

property expt: experiment#
classmethod init_args_check(*, cime, caseroot: str | Path, inputdir: str | Path, ocn_grid: Grid, ocn_topo: Topo, ocn_vgrid: VGrid, compset_lname: str, atm_grid_name: str, rof_grid_name: str | None, ninst: int, machine: str | None, project: str | None, override: bool, ntasks_ocn: int | None = None, job_queue: str | None = None, job_wallclock_time: str | None = None)#

Perform sanity checks on the input arguments to ensure they are valid and consistent.

property name: str#
process_forcings(process_initial_condition=True, process_velocity_tracers=True, **kwargs)#

Process boundary conditions, initial conditions, and other forcings for a MOM6 case. It’s a wrapper around extract_forcings/case_setup/driver.py

This method configures a regional MOM6 case’s ocean state boundaries and initial conditions using previously downloaded data setup in configure_forcings. The method expects configure_forcings() to be called beforehand.

Parameters:
  • process_initial_condition (bool, optional) – Whether to process the initial condition file. Default is True.

  • process_velocity_tracers (bool, optional) – Whether to process velocity and tracer boundary conditions. Default is True. This will be overridden and set to False if the large data workflow in configure_forcings is enabled.

  • kwargs (bool, optional) – Whether to process the other forcings, of the form process_{configurator.name} = False.

Raises:
  • RuntimeError – If configure_forcings() was not called before this method.

  • FileNotFoundError – If required unprocessed files are missing in the expected directories.

Notes

  • This method uses variable name mappings specified in the forcing product configuration.

  • If the large data workflow has been enabled, velocity and tracer OBCs are not processed within this method and must be handled externally.

  • Applies forcing-related namelist and XML updates at the end of the method.

See also

configure_forcings

Must be called before this method to set up the environment.

property runoff_in_compset#

Check if runoff is included in the compset.

validate_case()#
property ww3_in_compset#

Check if WW3 is included in the compset.

CrocoDash.case_state module#

case_state.py — Serialization policy and I/O for the CrocoDash case state file.

The case state is written to _crocodash_state.json inside the case root at the end of Case.__init__. This module owns:

  • the schema version used to gate compatibility checks;

  • which Case.__init__ arguments are excluded from the state snapshot (INIT_ARGS_EXCLUDE);

  • which state-file keys are derived (i.e. cannot be passed straight back to Case.__init__) and therefore need explicit handling when reconstructing a case from the file (DERIVED_KEYS);

  • the write, read, and check_version functions.

Keeping both INIT_ARGS_EXCLUDE and DERIVED_KEYS here makes the serialisation contract visible and co-located: when the state schema changes, this is the single file to update.

CrocoDash.case_state.check_version(state, state_path)#

Raise ValueError if state’s schema_version is incompatible with SCHEMA_VERSION.

Only MAJOR.MINOR must match; a higher PATCH is acceptable. Logs a warning (rather than raising) when schema_version is absent entirely (pre-versioning cases).

CrocoDash.case_state.read(caseroot)#

Read _crocodash_state.json, validate the schema version, and return the state dict.

CrocoDash.case_state.write(caseroot, state)#

Write state to _crocodash_state.json, injecting schema_version as the first key.

CrocoDash.cli module#

exception CrocoDash.cli.CrocoDashCliError#

Bases: Exception

A deliberate, user-facing CLI error.

main() prints this cleanly and exits(1) instead of showing a traceback. Only raise this for conditions a user can act on (e.g. “run this other command first”) – never to blanket-catch unexpected bugs, which should keep their real traceback.

CrocoDash.cli.main()#

CrocoDash.grid module#

CrocoDash.grid_creator module#

CrocoDash.logging module#

This module (logging) contains logging functions that are used across the CrocoDash package.

CrocoDash.logging.setup_logger(name)#

This function sets up a logger format for the package. It attaches logger output to stdout (if a handler doesn’t already exist) and formats it in a pretty way!

Parameters:

name (str) – The name of the logger.

Returns:

The logger

Return type:

logging.Logger

CrocoDash.recipe module#

recipe.py — Creating a Case directly from a YAML config dict or file.

Built on top of case.py, which handles the actual case creation through API calls, This module adds the layer for creating a case from a yaml file, which is a convenient way to create a case without having to write a script. The YAML file can be generated from an existing case using the case_to_yaml function, which reads the case’s state files and reconstructs a config dict suitable for passing to create_case_from_yaml.

CrocoDash.recipe.build_grid(grid_cfg)#

Build a Grid from a config dict. Uses supergrid_path for file-based grids.

CrocoDash.recipe.build_topo(topo_cfg, grid)#

Build a Topo from a config dict. Dispatches on topo.source.type.

CrocoDash.recipe.build_vgrid(vgrid_cfg, topo)#

Build a VGrid from a config dict. If depth is omitted, uses topo.max_depth.

CrocoDash.recipe.case_to_yaml(caseroot)#

Reconstruct a YAML config dict from an existing case’s state files.

Reads _crocodash_state.json (written by Case.__init__) and, if present, extract_forcings/config.json (written by Case.configure_forcings). Returns a dict suitable for passing to create_case_from_yaml or writing to a YAML file with yaml.dump().

CrocoDash.recipe.create_case_from_yaml(config, override=False, configure_only=False)#

Run the full case creation workflow from a config dict.

Builds Grid, Topo, and VGrid objects, creates the CESM case, then calls configure_forcings and process_forcings. A forcings section is required. Returns the Case.

Parameters:

configure_only (bool) – If True, skip process_forcings. Useful when you only need the case configured (e.g. to diff against a reference case) without running the expensive forcing extraction step.

CrocoDash.recipe.generate_configure_forcing_args(forcing_config, remove_configs=None)#

Convert a config.json forcing_config dict into configure_forcings kwargs.

CrocoDash.recipe.load_config(path)#

Read a YAML case config file, validate its structure, and return the config dict.

CrocoDash.recipe.validate_config_structure(config)#

Fast pre-flight structural checks on a config dict before any expensive work.

CrocoDash.shareable module#

shareable — case portability across user boundaries.

Built on top of recipe.py, which handles programmatic case creation from YAML. This module adds the layer for sharing a configured case with another user:

Person A (sender)
CaseBundle(caseroot)
→ identifies what makes the case non-standard beyond a plain CrocoDash setup

(SourceMods, xmlchanges, extra XML files, user_nl tweaks)

→ bundle(output_dir) packages everything into a portable folder

Person B (recipient)
ForkBundle(bundle_dir)

→ guides the user through updating paths, machine, compset, and forcings → recreates the case via recipe.py → applies the captured non-standard CESM state

The bundle folder is the artifact that crosses the user boundary. duplicate_case() is a convenience for copying a case within the same user context.

class CrocoDash.shareable.BundleDifferences(xml_files_missing_in_new: list = <factory>, user_nl_missing_params: dict = <factory>, source_mods_missing_files: list = <factory>, xmlchanges_missing: list = <factory>)#

Bases: object

Non-standard CESM state in a case beyond what recipe.py would produce.

source_mods_missing_files: list#
user_nl_missing_params: dict#
xml_files_missing_in_new: list#
xmlchanges_missing: list#
class CrocoDash.shareable.CaseBundle(caseroot)#

Bases: object

Sender-side entry point for sharing a CrocoDash case.

Reads a live case and identifies everything that makes it non-standard beyond what recipe.py would produce by default: extra XML files, user_nl tweaks, SourceMods, and xmlchanges. Packages all of it into a portable bundle folder that can be handed off to another user.

Typical usage:

bundle = CaseBundle(caseroot)
bundle.identify_non_standard_case_info(cesmroot, machine, project)
bundle_path = bundle.bundle(output_dir)
# hand bundle_path to the recipient
bundle(output_folder_location, machine=None, project=None)#

Package this case into a portable bundle folder.

Runs identify_non_standard_case_info() automatically if not already called. The bundle contains the full recipe YAML, the non-standard diff, all ocnice input files, user_nl files, replay.sh, and any SourceMods or extra XML files.

diff(other_case)#

Return a BundleDifferences of what this case has that other_case does not.

duplicate_case(new_caseroot, new_inputdir, bundle_dir=None)#
get_user_nl_value(component, param)#
identify_non_standard_case_info(cesmroot, machine, project_number)#

Diff this case against a freshly created reference case to find what’s non-standard.

Uses recipe.py to spin up a temporary reference case with the same grid, topo, vgrid, and forcing configuration (configure_only=True, so forcings are not processed). Anything in this case that the reference case lacks is captured in self.non_standard_case_info as a BundleDifferences. Called automatically by bundle() if not already run.

class CrocoDash.shareable.ForkBundle(bundle_location)#

Bases: object

Recipient-side entry point for creating a case from a bundle.

Takes a bundle folder produced by CaseBundle and recreates the case for a new user or environment. Guides the recipient through updating destination paths, machine, and optionally the compset and forcing configuration interactively. Uses recipe.py to rebuild the case from the (possibly modified) YAML, then applies any non-standard CESM state that was captured at bundle time.

Typical usage:

fork = ForkBundle(bundle_dir)
case = fork.fork(
    cesmroot="/path/to/cesm",
    machine="derecho",
    project_number="PROJ123",
    new_caseroot="/path/to/new_case",
    new_inputdir="/path/to/new_inputdir",
)
apply_copy_plan()#
fork(cesmroot, machine, project_number, new_caseroot, new_inputdir, plan=None)#

Recreate the bundled case for a new user or environment.

Guides the recipient through an interactive YAML review — prompting for destination paths, machine, project, and optionally compset and forcing date range. Offers $EDITOR for deeper changes (e.g. swapping the compset or adjusting forcing kwargs). After confirmation, creates the case via recipe.py and applies the non-standard CESM state captured at bundle time.

Parameters:
  • cesmroot (str or Path) – CESM root on the recipient’s machine.

  • machine (str) – Machine name for the new case.

  • project_number (str) – Project/account number for the new case.

  • new_caseroot (str or Path) – Destination path for the new case root.

  • new_inputdir (str or Path) – Destination path for the new input directory.

  • plan (dict, optional) – Which non-standard CESM state to transfer, keyed by "xml_files", "user_nl", "source_mods", "xmlchanges". When omitted the recipient is asked interactively for each category.

CrocoDash.shareable.apply_xmlchanges_to_case(old_caseroot, xmlchangeparams)#
CrocoDash.shareable.ask_string(prompt: str, default='') str#
CrocoDash.shareable.ask_yes_no(prompt: str, default=True) bool#
CrocoDash.shareable.copy_source_mods_from_case(old_caseroot, new_caseroot, short_filepaths)#
CrocoDash.shareable.copy_user_nl_params_from_case(old_caseroot, usernlparams)#
CrocoDash.shareable.copy_xml_files_from_case(old_caseroot, new_caseroot, filenames)#
CrocoDash.shareable.duplicate_case(caseroot, new_caseroot, new_inputdir, bundle_dir=None)#

Copy a CrocoDash case to a new location within the same user context.

Reads machine, project, and cesmroot from the original case’s _crocodash_state.json, identifies any non-standard CESM state, recreates the case via recipe.py, and transfers the non-standard state to the new location. Pass bundle_dir to also save a portable bundle as a side effect.

CrocoDash.topo module#

CrocoDash.topo_editor module#

CrocoDash.vgrid module#

CrocoDash.vgrid_creator module#

Module contents#