cape.cfdx.casecntl: Case control module

This module contains templates for interacting with and executing individual cases. Since this is one of the most highly customized modules of the CAPE system, there are few functions here, and the functions that are present are mostly templates.

In general, the case module is used for actually running the CFD solver (and any additional binaries that may be required as part of the run process), and it contains other capabilities for renaming files and determining the settings for a particular casecntl. CAPE saves many settings for the CFD solver and archiving in a file called case.json within each case folder, which allows for the settings of one case to diverge from the other cases in the same run matrix.

Actual functionality is left to individual modules listed below.

  • cape.pycart.case

  • cape.pyfun.case

  • cape.pyover.case

class cape.cfdx.casecntl.CaseRunner(fdir: str | None = None)

Class to handle running of individual CAPE cases

Call:
>>> runner = CaseRunner(fdir=None)
Inputs:
fdir: {None} | str

Optional case folder (by default os.getcwd())

Outputs:
runner: CaseRunner

Controller to run one case of solver

Class attributes:
  • _archivist_cls

  • _dex_cls

  • _logprefix

  • _modname

  • _nstart_max

  • _progname

  • _rc_cls

  • _zombie_files

Attributes:
archive(test: bool = False)

Run the --archive archiving action

Call:
>>> runner.archive(test=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

test: True | {False}

Option to log all actions but not actually copy/delete

Versions:
  • 2024-09-18 @ddalle: v1.0

archive_worker(host: str | None = None)

Archive some files while running

archivist

cape.cfdx.archivist.CaseArchivist | None Archiver instance

assert_not_running()

Check if a case is already running, raise exception if so

Call:
>>> runner.assert_not_running()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2023-06-02 @ddalle: v1.0

  • 2023-06-20 @ddalle: v1.1; instance method

  • 2024-06-16 @ddalle: v2.0; was check_running()

callf(cmdi: list, f: str | None = None, e: str | None = None, i: str | None = None, shell: bool = False) int

Execute a function and save returncode

Call:
>>> ierr = runner.callf(cmdi, f=None, e=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {None} | str

Name of file to write STDOUT

e: {f} | str

Name of file to write STDERR

i: {None} | str

Name of file from which to read STDIN

shell: True | {False}

Option to run subprocess in shell

Outputs:
ierr: int

Return code

Versions:
  • 2024-07-16 @ddalle: v1.0

  • 2024-08-03 @ddalle: v1.1; add log messages

  • 2025-01-22 @ddalle: v1.2; add i option

check_active() bool

Check if a case is actively running CFD executable

Call:
>>> q = runner.check_active()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

Whether case appears to be running

Versions:
  • 2025-03-11 @ddalle: v1.0

check_alt_exit(j: int | None = None) bool

Check for solver-selected exit, e.g. convergence target hit

Call:
>>> q = runner.check_alt_exit(j=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: {None} | int

Phase index

Outputs:
q: bool

True if no listed files have been modified recently

Versions:
  • 2025-08-14 @ddalle: v1.0

check_complete() bool

Check if a case is complete (DONE)

Call:
>>> q = runner.check_complete()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2023-06-20 @ddalle: v1.0

  • 2023-07-08 @ddalle: v1.1; support STOP

check_current_job() bool

Check if being called from the PBS job of this case

Call:
>>> q = runner.check_current_job()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

True if no listed files have been modified recently

Versions:
  • 2025-06-01 @ddalle: v1.0

check_error() bool

Check for other errors; rewrite for each solver

Call:
>>> q = runner.check_error()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

Whether case appears to be an error

Versions:
  • 2023-06-20 @ddalle: v1.0

check_exit(ja: int) bool

Check if a case should exit for any reason

Reasons a case should exit include

  • The case is finished.

  • An alternate exit criteria was found (e.g. resid converged)

  • A CAPE-STOP-PHASE file was found.

  • A CAPE-STOP-ITER file was found.

  • The relevant StartNextPhase option is False.

  • The relevant RestartSamePhase option is False.

Call:
>>> q = runner.check_exit(ja)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ja: int

Phase at beginning of run

Outputs:
q: True | False

Whether case should exit

Versions:
  • 2025-05-26 @ddalle: v1.0

check_mark_error() bool

Check if this case has been marked ERROR in run matrix

Call:
>>> q = runner.check_mark_error()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

Whether case has been marked ERROR or not

Versions:
  • 2025-05-01 @ddalle: v1.0

check_mark_pass() bool

Check if this case has been marked PASS in run matrix

Call:
>>> q = runner.check_mark_pass()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

Whether case has been marked PASS or not

Versions:
  • 2025-05-01 @ddalle: v1.0

check_phase(j: int) bool

Check if phase j has been completed

Call:
>>> q = runner.check_phase(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
q: bool

Whether phase j looks complete

Versions:
  • 2025-04-05 @ddalle: v1.0

  • 2025-08-14 @ddalle: v1.1; check_alt_exit()

check_phase_iters(j: int) bool

Check if phase j has run the appropriate iterations

Call:
>>> q = runner.check_phase_iters(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
q: bool

Whether phase j looks complete

Versions:
  • 2025-04-05 @ddalle: v1.0

check_phase_rerunable(j: int) bool

Check if a phase can be rerun, else it must progress to next

Call:
>>> q = runner.check_phase_rerunable(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
q: bool

Whether phase j can be restarted

Versions:
  • 2025-06-24 @ddalle: v1.0

check_queue() str

Get queue status of current job

Call:
>>> s = runner.check_queue()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
s: str

Job queue status

  • .: not in queue

  • Q: job queued (not running)

  • R: job running

  • H: job held

  • E: job error status

Versions:
  • 2025-05-04 @ddalle: v1.0

check_running() bool

Check if a case is currently running

Call:
>>> q = runner.check_running()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

Whether case appears to be running

Versions:
  • 2023-06-16 @ddalle: v1.0

  • 2025-03-11 @ddalle: v1.1; elimn8 @run_rootdir

check_zombie() bool

Check a case for ZOMBIE status

A running case is declared a zombie if none of the listed files (by default *.out) have been modified in the last 30 minutes. However, a case cannot be a zombie unless it contains a RUNNING file and returns True from CheckRunning().

Call:
>>> q = runner.check_combie()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: bool

True if no listed files have been modified recently

Versions:
  • 2025-06-01 @ddalle: v1.0

checkx_phase(j: int) bool

Apply solver-specific checks for phase j

This generic version always returns True

Call:
>>> q = runner.checkx_phase(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
q: bool

Whether phase j looks complete

Versions:
  • 2025-04-05 @ddalle: v1.0

clean(test: bool = False)

Run the --clean archiving action

Call:
>>> runner.clean(test=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

test: True | {False}

Option to log all actions but not actually copy/delete

Versions:
  • 2024-09-18 @ddalle: v1.0

cntl

cape.cfdx.cntl.Cntl | None Run matrix controller that owns this case

copy_file(src: str, dst: str, f: bool = False)

Copy a file and log results

Call:
>>> runner.copy_file(src, dst, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

src: str

Name of input file, before renaming

dst: str

Name of renamed file

f: True | {False}

Option to overwrite existing dst

Versions:
  • 2024-08-14 @ddalle: v1.0

exec_modfunc(funcspec: dict | str) Any

Call an arbitrary Python function

Call:
>>> v = runner.exec_modfunc(funcspec)
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
v: any

Output of function

Versions:
  • 2025-03-28 @ddalle: v1.0

expand_compids(comp: str | int | list) list

Expand component name to list of component ID numbers

Call:
>>> compids = runner.expand_compids(comp)
Inputs:
comp: str | int | list

Component name, index, or list thereof

Outputs:
compids: list[int]

List of component ID numbers

Versions:
  • 2025-01-30 @ddalle: v1.0

extend_case(m: int = 1, j: int | None = None, nmax: int | None = None) int | None

Extend the case by one execution of final phase

Call:
>>> nnew = runner.extend_case(m=1, nmax=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

m: {1} | int

Number of additional times to execute final phase

j: {None} | int

Phase to extend

nmax: {None} | int

Do not exceed this iteration

Outputs:
nnew: None | int

Number of iters after extension, if changed

Versions:
  • 2024-08-26 @ddalle: v1.0

finalize_files(j: int)

Clean up files after running one cycle of phase j

Call:
>>> runner.finalize_files(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2023-06-20 @ddalle: v1.0 (abstract method)

finalize_stdoutfile(j: int)

Move the {_progname}.out file to run.{j}.{n}

Call:
>>> runner.finalize_stdoutfile(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2025-04-07 @ddalle: v1.0

find_surf_file() FileSearchStatus

Find CFD output file that contains the most recent surface data

Call:
>>> fstat = runner.find_surf_file()
>>> mtch, n = runner.find_surf_file()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
mtch: re.Match | None

Regular expression match instance

n: int

Latest iteration contained in file

Versions:
  • 2025-08-13 @ddalle: v1.0

fork_worker_func(funcspec: str | dict, sleeptime: float | int | None = None)

Fork one process to run a Python function while case runs

Call:
>>> runner.fork_worker_func(funcspec, sleeptime=None)
>>> runner.fork_worker_func(funcname, sleeptime=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

funcname: str

Simple Python command name to execute

funcspec: dict

Python function spec, see UserFuncOpts

sleeptime: {None} | float | int

Time to sleep before restarting shellcmd

Versions:
  • 2025-03-28 @ddalle: v1.0

fork_worker_shell(shellcmd: str, sleeptime: float | int | None = None)

Fork one process to run a shell command while case runs

Call:
>>> runner.fork_worker_shell(shellcmd, sleeptime=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

shellcmd: str

Shell command to run

sleeptime: {None} | float | int

Time to sleep before restarting shellcmd

Versions:
  • 2025-03-28 @ddalle: v1.0

genr8_dex_args_post(typ: str) tuple

Generate tuple of args after comp when reading data cls

This will call the function runner.get_dex_args_post_{typ}() if possible, or runner.get_dex_args_post() as a fall back. If neither function exists, an empty tuple will be returned.

Call:
>>> args = runner.genr8_dex_args_post(typ)
Inputs:
runner: CaseRunner

Controller to run one case of solver

typ: str

DataBook component type

Outputs:
args: tuple

Arguments for _dex_cls instantiation

Versions:
  • 2025-07-24 @ddalle: v1.0

genr8_dex_args_pre(typ: str) tuple

Generate tuple of args before comp when reading data cls

This will call the function runner.get_dex_args_pre_{typ}() if possible, or runner.get_dex_args_pre() as a fall back. If neither function exists, an empty tuple will be returned.

Call:
>>> args = runner.genr8_dex_args_pre(typ)
Inputs:
runner: CaseRunner

Controller to run one case of solver

typ: str

DataBook component type

Outputs:
args: tuple

Arguments for _dex_cls instantiation

Versions:
  • 2025-07-24 @ddalle: v1.0

genr8_resid_args() tuple

Generate list of arguments to case residual class

Call:
>>> args = runner.genr8_resid_args()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
args: tuple

Arguments to CaseResid instantiation

Versions:
  • 2025-08-04 @ddalle: v1.0

genr8_triq_filename(mtch=None, n: int | None = None) str

Find the name of the expected .triq file based on status

Call:
>>> ftriq = runner.genr8_triq_filename(mtch=None, n=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

mtch: {None} | re.Match

Regex match object for surface data file (else call CaseRunner.match_surf_file())

n: {None} | int

Iteration number of surface data (else call CaseRunner.infer_file_niter())

Outputs:
ftriq: str

Name of .triq file expected (or created) by CAPE

Versions:
  • 2025-08-10 @ddalle: v1.0

get_archivist() CaseArchivist

Get or read archivist instance

Call:
>>> a = runner.get_archivist()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
a: CaseArchivist

Archive controller for one case

Versions:
  • 2024-09-13 @ddalle: v1.0

  • 2024-12-09 @ddalle: v1.1; prefer cntl opts over case

get_cape_stdoutfiles() list

Get list of STDOUT files in order they were run

Call:
>>> runfiles = runner.get_cape_stdoutfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
runfiles: list[str]

List of run files, in ascending order

Versions:
  • 2024-08-09 @ddalle: v1.0

  • 2025-03-21 @ddalle: v1.1; use search_regex()

get_case_index() int | None

Get index of a case in the current run matrix

Call:
>>> i = runner.get_case_index()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
i: int | None

Index of case with name frun in run matrix, if present

Versions:
  • 2024-08-15 @ddalle: v1.0

get_case_name() str

Get name of this case according to CAPE run matrix

Call:
>>> casename = runner.get_case_name()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
casename: str

Name of case, using / as path sep

Versions:
  • 2024-08-15 @ddalle: v1.0

get_cntl_rootdir() str

Get name of this case according to CAPE run matrix

Call:
>>> rootdir = runner.get_cntl_rootdir()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
rootdir: str

Absolute path to base of run matrix that runs this case

Versions:
  • 2024-08-26 @ddalle: v1.0

get_cpu_time() float | None

Read most appropriate total CPU usage for current case

Call:
>>> corehrs = runner.get_cpu_time()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
corehrs: None | float

Core hours since last start or None if not running

Versions:
  • 2015-12-22 @ddalle: v1.0 (Cntl.GetCPUTimeBoth)

  • 2016-08-30 @ddalle: v1.1; check for RUNNING

  • 2023-07-09 @ddalle: v2.0; rename, CaseRunner

get_cpu_time_start()

Read total core hours since start of current running phase

Call:
>>> corehrs = runner.get_cpu_time_start()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
corehrs: None | float

Core hours since last start or None if not running

Versions:
  • 2015-08-30 @ddalle: v1.0 (Cntl.GetCPUTimeFromStart)

  • 2023-07-09 @ddalle: v2.0

get_cpu_time_user()

Read total core hours from completed phase cycles

Call:
>>> corehrs = runner.get_cpu_time_user()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
corehrs: None | float

Total core hours used or None if no log file found

Versions:
  • 2015-12-22 @ddalle: v1.0 (Cntl.GetCPUTimeFromFile)

  • 2023-07-09 @ddalle: v2.0

get_databook_opt(comp: str, opt: str)

Retrieve a databook option for a given component

Call:
>>> v = runner.get_databook_opt(comp, opt)
Inputs:
comp: str

Name of component

opt: str

Name of option

Outputs:
v: Any

Value of option opt for component comp

Versions:
  • 2025-01-23 @ddalle: v1.0

get_dex_args_post_triqfm() tuple

Get list of args after comp in CaseTriqFM

Call:
>>> args = runner.get_dex_args_post_triqfm()
>>> ftriq, cntl, i = runner.get_dex_args_post_triqfm()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
args: tuple

Tuple of args

ftriq: str

Name of .triq file with surface solution data

cntl: cape.cfdx.cntl.Cntl

Run matrix controller with definitions for dex comp

i: int

Index of this case in run matrix

Versions:
  • 2025-07-24 @ddalle: v1.0

get_dex_args_post_triqpoint() tuple

Get list of args after comp in CaseTriqPoint

Call:
>>> args = runner.get_dex_args_post_triqpoint()
>>> ftriq, cntl, i = runner.get_dex_args_post_triqpoint()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
args: tuple

Tuple of args

ftriq: str

Name of .triq file with surface solution data

cntl: cape.cfdx.cntl.Cntl

Run matrix controller with definitions for dex comp

i: int

Index of this case in run matrix

Versions:
  • 2025-08-30 @ddalle: v1.0

get_dex_iter(comp: str) int

Get number of iterations available for a DataBook component

Call:
>>> n = runner.get_dex_iter(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iteration count

Versions:
  • 2025-08-07 @ddalle: v1.0

get_dex_iter_fm(comp: str) int

Get number of iterations available for "FM" comps

Call:
>>> n = runner.get_dex_iter_fm()
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iteration count

Versions:
  • 2025-08-07 @ddalle: v1.0

get_dex_iter_lineload(comp: str) int

Get number of iterations for "LineLoad" comp

Call:
>>> n = runner.get_dex_iter_lineload()
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iteration count

Versions:
  • 2025-08-12 @ddalle: v1.0

get_dex_iter_triqfm(comp: str) int

Get number of iterations for "TriqFM" comp

Call:
>>> n = runner.get_dex_iter_triqfm()
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iteration count

Versions:
  • 2025-08-13 @ddalle: v1.0

get_dex_iter_triqpoint(comp: str) int

Get number of iterations for "TriqPoint" comp

Call:
>>> n = runner.get_dex_iter_triqpoint()
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iteration count

Versions:
  • 2025-08-13 @ddalle: v1.0

get_dex_n_orders(nstats: int = 1, nlast: int | None = None, f: bool = False) float

Get current residual order of magnitude drop

Call:
>>> norders = runner.get_dex_n_orders(nstatus=1, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

nstats: {1} | int

Number of iterations over which to average current resid

nlast: {None} | int

Last iteration to use in window

f: True``| { ``False}

Read residual even if one is cached

Outputs:
h: cape.cfdx.casedata.CaseResid

Iterative residual history

Versions:
  • 2055-08-04 @ddalle: v1.0

get_dex_nstats(comp: str) int

Get iters in averaging window for a DataBook component

Call:
>>> n = db.get_nstats(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iterations/timesteps included in averaging window

Versions:
  • 2025-08-12 @ddalle: v1.0

get_dex_nstats_fm(comp: str) int

Get averaging window iters for a "FM" DataBook component

Call:
>>> n = db.get_nstats(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iterations/timesteps included in averaging window

Versions:
  • 2025-08-12 @ddalle: v1.0

get_dex_nstats_lineload(comp: str) int

Get window size for a "LineLoad" DataBook component

Call:
>>> n = db.get_dex_nstats_lineload(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iterations/timesteps included in averaging window

Versions:
  • 2025-08-12 @ddalle: v1.0

get_dex_nstats_triqfm(comp: str) int

Get window size for a "TriqFM" DataBook component

Call:
>>> n = db.get_dex_nstats_triqfm(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iterations/timesteps included in averaging window

Versions:
  • 2025-08-29 @ddalle: v1.0

get_dex_nstats_triqpoint(comp: str) int

Get window size for a "TriqPoint" DataBook component

Call:
>>> n = db.get_dex_nstats_triqpoint(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

Outputs:
n: int

Iterations/timesteps included in averaging window

Versions:
  • 2025-08-29 @ddalle: v1.0

get_dex_opt(comp: str, opt: str, vdef: Any = None) Any

Get general option for a DataBook component

Call:
>>> v = runner.get_dex_opt(comp, opt, vdef=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

opt: str

Name of option to access

vdef: {None} | object

Default value

Outputs:
v: object

DataBook option value

Versions:
  • 2025-07-24 @ddalle: v1.0

get_dex_type(comp: str) str

Get category for a DataBook component

Call:
>>> typ = runner.get_dex_type(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Outputs:
typ: str

DataBook component type

Versions:
  • 2025-07-24 @ddalle: v1.0

get_env_jobid() str

Check to see if we are running inside a PBS/Slurm job

This looks for environment variables to see if this is running inside a batch job. Currently supports slurm and PBS.

Call:
>>> jobid = runner.get_env_jobid()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
jobid: str

Name of current job, 0 if no batch environment

Versions:
  • 2023-12-13 @dvicker: v1.0 (Cntl)

  • 2023-12-18 @ddalle: v1.1; debug

  • 2025-06-01 @ddalle: v1.0; from cntl.Cntl

  • 2025-06-02 @ddalle: v1.1; cache in runner.job

get_funcname(frame: int = 1) str

Get name of calling function, mostly for log messages

Call:
>>> funcname = runner.get_funcname(frame=1)
Inputs:
runner: CaseRunner

Controller to run one case of solver

frame: {1} | int

Depth of function to seek title of

Outputs:
funcname: str

Name of calling function

Versions:
  • 2024-08-16 @ddalle

get_gamma() float

Get freestream ratio of specific heats if possible

Call:
>>> gam = runner.get_gamma()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
gam: float

Freestream ratio of specific heats

Versions:
  • 2025-01-29 @ddalle: v1.0

get_grid_regex() str

Return regular expression for volume grid files

Call:
>>> pat = runner.get_grid_regex()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
pat: str

Regular expression search pattern

Versions:
  • 2025-08-16 @ddalle: v1.0

get_iter(f: bool = True) int

Detect most recent iteration

Call:
>>> n = runner.get_iter(f=True)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {True} | False

Force recalculation of phase

Outputs:
n: int

Iteration number

Versions:
  • 2023-06-20 @ddalle: v1.0

get_iter_active() int

Detect any iterations run since last completed phase run

Call:
>>> n = runner.get_iter_active()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
n: int

Iteration number

Versions:
  • 2025-03-21 @ddalle: v1.0

  • 2025-04-01 @ddalle: v1.1; use getx_iter() for default

get_iter_completed() int

Detect most recent iteration from completed runs

Call:
>>> n = runner.get_iter_completed()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
n: int

Iteration number

Versions:
  • 2025-03-21 @ddalle: v1.0

get_iter_simple(f: bool = True) int

Detect most recent iteration

Call:
>>> n = runner.get_iter_simple(f=True)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {True} | False

Force recalculation of phase

Outputs:
n: int

Iteration number

Versions:
  • 2025-03-21 @ddalle: v1.0

get_job_id() str

Get PBS/Slurm job ID, if any

Call:
>>> job_id = runner.get_job_id()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
job_id: str

Text form of job ID; '' if no job found

Versions:
  • 2023-06-16 @ddalle: v1.0

  • 2023-07-05 @ddalle: v1.1; eliminate j arg

  • 2024-06-10 @ddalle: v2.0; use get_job_ids()

get_job_ids() list

Get list of PBS/Slurm job IDs, if appropriate

Call:
>>> job_id = runner.get_job_id()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
job_ids: list[str]

List of PBS/Slurm job IDs, as text

Versions:
  • 2024-06-10 @ddalle: v1.0

get_last_iter() int

Get min iteration required for a given case

Call:
>>> nmax = runner.get_last_iter()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
nmax: int

Number of iterations

Versions:
  • 2024-06-17 @ddalle: v1.0

  • 2024-07-18 @ddalle: v1.1; better exception handling

get_last_phase() int

Get min phase required for a given case

Call:
>>> jmax = runner.get_last_phase()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
jmax: int

Min phase required for job

Versions:
  • 2024-06-17 @ddalle: v1.0

  • 2024-07-18 @ddalle: v1.1; force reread, handle errors

get_logger() CaseLogger

Get or create logger instance

Call:
>>> logger = runner.get_logger()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
logger: CaseLogger

Logger instance

Versions:
  • 2024-08-16 @ddalle: v1.0

get_mach() float

Get Mach number even if mach is not a run matrix key

This uses cape.cfdx.runmatrix.RunMatrix.GetMach() to combine information from all run matrix keys.

Call:
>>> mach = runner.get_mach()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
mach: float

Mach number

Versions:
  • 2024-12-03 @ddalle: v1.0

  • 2025-01-29 @ddalle: v1.1; attempt read_condition()

get_next_phase(j: int) int | None

Get the number of the phase that follows j

Call:
>>> jnext = runner.get_next_phase(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Current phase number

Outputs:
jnext: int | None

Next phase number, if applicable

Versions:
  • 2024-08-11 @ddalle: v1.0

get_pbs_script(j=None)

Get file name of PBS script

… or Slurm script or execution script

Call:
>>> fpbs = runner.get_pbs_script(j=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: {None} | int

Phase number

Outputs:
fpbs: str

Name of main script to run case

Versions:
  • 2014-12-01 @ddalle: v1.0 (pycart)

  • 2015-10-19 @ddalle: v1.0 (pyfun)

  • 2023-06-18 @ddalle: v1.1; instance method

get_phase(f: bool = True) int

Determine phase number in present case

Call:
>>> j = runner.get_phase(n, f=True)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {True} | False

Force recalculation of phase

Outputs:
j: int

Phase number for next restart

Versions:
  • 2014-10-02 @ddalle: v1.0

  • 2015-10-19 @ddalle: v1.1; FUN3D version

  • 2016-04-14 @ddalle: v1.2; CFDX version

  • 2023-06-16 @ddalle: v2.0; CaseRunner method

get_phase_index(j: int) int | None

Get index of phase in "PhaseSequence"

Call:
>>> k = runner.get_phase_index(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Outputs:
k: None | int

Index of j in PhaseSequence; None if j is not one of the prescribed phases

Versions:
  • 2024-08-11 @ddalle: v1.0

get_phase_iters(j: int) int

Get min iteration required for completion of phase j

Call:
>>> n = runner.get_phase_iters(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase index

Outputs:
n: int

Number of iterations

Versions:
  • 2024-07-18 @ddalle: v1.0

get_phase_n(j: int) int | None

Get last reported iteration run in phase j, if any

Call:
>>> n = runner.get_phase_n(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
n: None | int

Overall iteration reported run for phase j

Versions:
  • 2025-04-05 @ddalle: v1.0

get_phase_next() int

Get phasen number to use for restart

Call:
>>> j = runner.get_phase_next()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
j: int

Phase number for next restart

Versions:
  • 2025-03-30 @ddalle: v1.0

  • 2025-04-05 @ddalle: v2.0; use check_phase()

  • 2025-04-06 @ddalle: v2.1; include get_phase_recent()

get_phase_nreq(j: int) int

Get number of iterations required to be run by phase j

Call:
>>> nreq = runner.get_phase_nreq(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
nreq: int

Min iterations req’d by phase j, from "nIter"

Versions:
  • 2025-04-05 @ddalle: v1.0

get_phase_nrun(j: int) int | None

Get number of iterations reported run by phase j, if any

Call:
>>> nrun = runner.get_phase_nrun(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Outputs:
nrun: None | int

Number of iterations reported run by phase j

Versions:
  • 2025-04-05 @ddalle: v1.0

get_phase_recent() int | None

Get the number of the last phase successfully completed

Call:
>>> j = runner.get_phase_recent()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
j: int

Phase number last completed

Versions:
  • 2025-03-21 @ddalle: v1.0

get_phase_sequence() list

Get list of prescribed phases for a case

Call:
>>> phases = runner.get_phase_sequence()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
phases: int[int]

Min phase required for job

Versions:
  • 2024-07-18 @ddalle: v1.0

get_phase_simple(f: bool = True) int

Determine phase number, only checking output files

Call:
>>> j, jlast = runner.get_phase_simple(f=True)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {True} | False

Force recalculation of phase

Outputs:
j: int

Phase number for current or next restart

jlast: int

Last phase expected

Versions:
  • 2025-03-02 @ddalle: v1.0

get_phase_stdoutfiles(j: int) list

Get list of STDOUT files in order they were run

Call:
>>> runfiles = runner.get_cape_stdoutfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
runfiles: list[str]

List of run files, in ascending order

Versions:
  • 2024-08-09 @ddalle: v1.0

  • 2025-03-21 @ddalle: v1.1; use search_regex()

get_project_rootname(j: int | None = None) str

Read namelist and return project namelist

Call:
>>> rname = runner.get_project_rootname(j=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: {None} | int

Phase number

Outputs:
rname: str

Project rootname

Versions:
  • 2024-11-05 @ddalle: v1.0

get_reportfiles() list

Generate list of report files

Call:
>>> filelist = runner.get_reportfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
filelist: list[str]

List of files to protect

Verions:
  • 2024-09-14 @ddalle: v1.0

get_restart_file(j: int | None = None) str

Get the most recent restart file for phase j

Call:
>>> restartfile = runner.get_restart_file(j=None)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: {None} | int

Phase number

Versions:
  • 2024-11-05 @ddalle: v1.0

get_restart_iter(f=True)

Get number of iteration if case should restart

Call:
>>> nr = runner.get_restart_iter(f=True)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: {True} | False

Force recalculation of phase

Outputs:
nr: int

Restart iteration number

Versions:
  • 2023-06-20 @ddalle: v1.0; cfdx abstract version

get_restartfiles() list

Generate list of restart files

Call:
>>> filelist = runner.get_restartfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
filelist: list[str]

List of files to protect

Verions:
  • 2024-09-14 @ddalle: v1.0

get_returncode() int

Check for other errors; rewrite for each solver

Call:
>>> ierr = runner.get_returncode()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
ierr: int

Return code

Versions:
  • 2023-06-20 @ddalle: v1.0

  • 2024-06-17 @ddalle: v1.1; was check_error()

  • 2024-07-16 @ddalle: v1.2; use self.returncode

get_reynolds() float

Get Reynolds number per grid unit if possible

Call:
>>> rey = runner.get_reynolds()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
rey: float

Reynolds number per grid nuit

Versions:
  • 2025-01-29 @ddalle: v1.0

get_runlog() ndarray

Create a 2D array of CAPE exit phases and iters

Each row of the output is the phase number and iteration at which CAPE exited. The array is sorted by ascending phase then iteration.

Call:
>>> runlog = runner.get_runlog()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
runlog: np.ndarray[int]

2D array of all CAPE exit phase and iteration numbers

Versions:
  • 20254-03-23 @ddalle: v1.0

get_runlog_iter()

Get phase and iteration from most recent CAPE log file name

Call:
>>> phase, iter = runner.get_runlog_iter()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
phase: int

Phase number reported by CAPE

iter: int

Iteration number reported by CAPE

Versions:
  • 2024-03-22 @ddalle: v1.0

get_status() str

Calculate status of current job

Call:
>>> sts = runner.get_status()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
sts: str

One of several possible job statuses

  • DONE: not running and meets finishing criteria

  • PASS: DONE plus marked in run matrix

  • ERROR: marked as failure in run matrix

  • FAIL: local error detected, not marked in matrix

  • RUN: case is currently running

  • INCOMP: case not running and not finished

  • QUEUE: case not running but in the queu

  • PASS*: marked in run matrix but not DONE

  • ZOMBIE: RUNNING but no recently changed files

get_stderr_filename() str

Get standard STDERR file name, e.g. fun3d.err

Call:
>>> fname = runner.get_stderr_filename()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
fname: str

Name of file

Versions:
  • 2025-04-07 @ddalle: v1.0

get_stdout_filename() str

Get standard STDOUT file name, e.g. fun3d.out

Call:
>>> fname = runner.get_stdout_filename()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
fname: str

Name of file

Versions:
  • 2025-04-07 @ddalle: v1.0

get_stop_iter()

Read iteration at which to stop

Call:
>>> nstop = runner.get_stop_iter()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
nstop: int | None

Iteration at which to stop, if any

Versions:
  • 2023-06-20 @ddalle: v1.0

get_surf_regex() str

Get regular expression that all surface output files match

Call:
>>> regex = runner.get_surf_regex()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
regex: str

Regular expression that all surface sol’n files match

Versions:
  • 2025-01-24 @ddalle: v1.0

get_surfgrid_regex() str

Return regular expression for surface grid files

Call:
>>> pat = runner.get_surfgrid_regex()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
pat: str

Regular expression search pattern

Versions:
  • 2025-08-16 @ddalle: v1.0

get_triq_filename() str

Get latest .triq file

Call:
>>> ftriq = runner.get_triq_filename()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
ftriq: str

Name of latest .triq annotated triangulation file

Versions:
  • 2025-01-29 @ddalle: v1.0

get_triq_filename_stem() str

Get the infix for surface .triq files

Call:
>>> stem = runner.get_triq_filename_stem()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
stem: str

File name infix, e.g. "surf" or "tec_boundary"

Versions:
  • 2025-08-11 @ddalle: v1.0

get_user() str

Get user name who is running this case

Call:
>>> user = runner.get_user()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
user: str

Name of specified user or owner of PBS file

Versions:
  • 2025-05-02 @ddalle: v1.0

get_vol_regex() str

Get regular expression that all volume output files match

Call:
>>> regex = runner.get_vol_regex()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
regex: str

Regular expression that all surface sol’n files match

Versions:
  • 2025-08-13 @ddalle: v1.0

get_working_folder() str

Get working folder, . for generic solver

Call:
>>> fdir = runner.get_working_folder()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
fdir: "."

Working folder relative to roo, where next phase is run

Versions:
  • 2024-08-11 @ddalle: v1.0

get_working_folder_() str

Get working folder, but replace '.' with ''

This results in cleaner results with os.path.join().

Call:
>>> fdir = runner.get_working_folder()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
fdir: "" | str

Working folder relative to roo, where next phase is run

Versions:
  • 2024-08-14 @ddalle: v1.0

getx_iter() int

Calculate most recent iteration

Call:
>>> n = runner.getx_iter()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
n: int

Iteration number

Versions:
  • 2023-06-20 @ddalle: v1.0

getx_phase(n: int)

Calculate phase based on present files

The x in the title implies this case might be rewritten for each module.

Call:
>>> j = runner.getx_phase(n)
Inputs:
runner: CaseRunner

Controller to run one case of solver

n: int

Iteration number

Outputs:
j: int

Phase number for next restart

Versions:
  • 2023-06-16 @ddalle: v1.0

  • 2023-07-06 @ddalle: v1.1; PhaseSequence repeats ok

  • 2024-08-12 @ddalle: v1.2; refine file names slightly

getx_restart_iter()

Calculate number of iteration if case should restart

Call:
>>> nr = runner.gets_restart_iter()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
nr: int

Restart iteration number

Versions:
  • 2023-06-20 @ddalle: v1.0; cfdx abstract version

handle_alt_exit(j: int)

Reduce PhaseIters if an early exit was detected

Call:
>>> runner.handle_alt_exit(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number last completed

Versions:
  • 2025-08-15 @ddalle: v1.0

import_cntlmod()

Import appropriate run matrix-level cntl module

Call:
>>> mod = runner.import_cntlmod()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
mod: module

Module imported

Versions:
  • 2024-08-14 @ddalle: v1.0

  • 2024-09-07 @ddalle: v1.1; mod for moving cntl to cfdx

infer_tavg_nstats(n: int | None = None, fname: str | None = None) int

Infer num of iters averaged for output at iteration n

Call:
>>> nstats = runner.infer_tavg_nstats(n)
Inputs:
runner: CaseRunner

Controller to run one case of solver

n: int

Iteration number

Outputs:
nstats: int

Number of iterations averaged in viz file

Versions:
  • 2025-08-10 @ddalle: v1.0

init_post()

Custom initialization hook

Call:
>>> runner.init_post()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2023-06-28 @ddalle: v1.0

init_timer()

Mark a case as RUNNING and initialize a timer

Call:
>>> tic = runner.init_timer()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
tic: datetime.datetime

Time at which case was started

Versions:
  • 2021-10-21 @ddalle: v1.0; from run_fun3d()

  • 2023-06-20 @ddalle: v1.1; instance method, no mark()

j

int | None Current phase number

job

str | None Name of current PBS/Slurm job

jobs

dict Dictionary of job statuses

kill_workers(j: int = 0)

Kill any worker PIDs that may be running after phase

This will wait up to WorkerTimeout seconds after the main solver is no longer active before killing subprocesses.

Call:
>>> runner.kill_workers(j=0)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: {0} | int

Phase number

Versions:
  • 2025-03-07 @ddalle: v1.0

Copy a link and log results

Call:
>>> runner.link_file(src, dst, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

src: str

Name of input file, before renaming

dst: str

Name of renamed file

f: True | {False}

Option to overwrite existing dst

Versions:
  • 2024-08-14 @ddalle: v1.0

log_both(msg: str, title: str | None = None, parent: int = 0)

Write a message to both primary and verbose logs

Call:
>>> runner.log_both(title, msg)
Inputs:
runner: CaseRunner

Controller to run one case of solver

msg: str

Primary content of message

title: {None} | str

Manual title (default is name of calling function)

parent: {0} | int

Extra levels to use for calling function name

Versions:
  • 2024-08-01 @ddalle: v1.0

log_data(data: dict, title: str | None = None, parent: int = 0)

Write dict to verbose log as JSON

Call:
>>> runner.log_data(title, data)
Inputs:
runner: CaseRunner

Controller to run one case of solver

data: dict

Parameters to write to verbose log as JSON

msg: str

Primary content of message

title: {None} | str

Manual title (default is name of calling function)

parent: {0} | int

Extra levels to use for calling function name

Versions:
  • 2024-08-01 @ddalle: v1.0

log_main(msg: str, title: str | None = None, parent: int = 0)

Write a message to primary log

Call:
>>> runner.log_main(msg, title, parent=0)
Inputs:
runner: CaseRunner

Controller to run one case of solver

msg: str

Primary content of message

title: {None} | str

Manual title (default is name of calling function)

parent: {0} | int

Extra levels to use for calling function name

Versions:
  • 2024-08-01 @ddalle: v1.0

log_verbose(msg: str, title: str | None = None, parent: int = 0)

Write a message to verbose log

Call:
>>> runner.log_verbose(title, msg)
Inputs:
runner: CaseRunner

Controller to run one case of solver

msg: str

Primary content of message

title: {None} | str

Manual title (default is name of calling function)

parent: {0} | int

Extra levels to use for calling function name

Versions:
  • 2024-08-01 @ddalle: v1.0

logger

cape.cfdx.logger.CaseLogger Logger instance for this case

mark_active()

Mark a case as active, a subset of RUNNING

Call:
>>> runner.mark_active()
Inputs:
runner: CaseRunner

Conroller to run one case of solver

Versions:
  • 2025-03-11 @ddalle: v1.0

mark_failure(msg: str = 'no details')

Mark the current folder in failure status using FAIL file

Call:
>>> runner.mark_failure(msg="no details")
Inputs:
runner: CaseRunner

Controller to run one case of solver

msg: {"no details"} | str

Error message for output file

Versions:
  • 2023-06-02 @ddalle: v1.0

  • 2023-06-20 @ddalle: v1.1; instance method

mark_inactive()

Delete the ACTIVE file if it exists

Call:
>>> runner.mark_inactive()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2025-03-11 @ddalle: v1.0

mark_running()

Check if cases already running and create RUNNING otherwise

Call:
>>> runner.mark_running()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2023-06-02 @ddalle: v1.0

  • 2023-06-20 @ddalle: v1.1; instance method, no check()

mark_stopped()

Delete the RUNNING file if it exists

Call:
>>> runner.mark_stopped()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2023-06-02 @ddalle: v1.0

  • 2024-08-03 @ddalle: v1.1; add log message

match_grid_file()

Get latest volume grid and regex match instance

Call:
>>> re_match = runner.match_grid_file()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
re_match: re.Match | None

Regular expression groups, if any

Versions:
  • 2025-08-16 @ddalle: v1.0

match_regex(pat: str, workdir: bool = False, regex: bool = True, links: bool = False)

Search for files by regex; return the match info for latest

Call:
>>> mtch = runner.match_regex(pat)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pat: str

File name pattern

links: True | {False}

Option to allow links in output

Outputs:
mtch: re.Match | None

Match object for latest match to pat, if any

Versions:
  • 2025-02-01 @ddalle: v1.0

match_surf_file()

Get latest surface file and regex match instance

Call:
>>> re_match = runner.match_surf_file()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
re_match: re.Match | None

Regular expression groups, if any

Versions:
  • 2025-01-24 @ddalle: v1.0

match_surfgrid_file()

Get latest surface grid and regex match instance

Call:
>>> re_match = runner.match_surfgrid_file()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
re_match: re.Match | None

Regular expression groups, if any

Versions:
  • 2025-08-16 @ddalle: v1.0

match_vol_file()

Get latest volume file and regex match instance

Call:
>>> re_match = runner.match_vol_file()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
re_match: re.Match | None

Regular expression groups, if any

Versions:
  • 2025-01-24 @ddalle: v1.0

mkdir(dirname: str)

Create a folder (if needed); set permissions to match root

Call:
>>> runner.mkdir(dirname)
Inputs:
runner: CaseRunner

Controller to run one case of solver

dirname: str

Name of folder to create and/or modify

Versions:
  • 2025-07-28 @ddalle: v1.0

n

int | None Current iteration number

nr

int Current restart iteration

prep_dex(comp: str)

Perform preprocessing tasks as needed before reading DEx

Call:
>>> db = runner.prep_dex(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-08-12 @ddalle: v1.0

prep_dex_lineload(comp: str)

Prepare surface, run triload, before reading line loads

Call:
>>> db = runner.prep_dex_lineload(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-08-12 @ddalle: v1.0

prep_dex_triqfm(comp: str)

Prepare surface .triq file for TriqFM processing

Call:
>>> db = runner.prep_dex_triqfm(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-08-13 @ddalle: v1.0

prep_dex_triqpoint(comp: str)

Prepare surface .triq file for TriqPoint processing

Call:
>>> db = runner.prep_dex_triqfm(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-08-29 @ddalle: v1.0

prepare_env(j: int)

Set environment vars, alter resource limits (ulimit)

This function relies on the system module resource

Call:
>>> runner.prepare_env(rc, i=0)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

See also:
Versions:
  • 2015-11-10 @ddalle: v1.0 (PrepareEnvironment())

  • 2023-06-02 @ddalle: v1.1; fix logic for appending
    • E.g. "PATH": "+$HOME/bin"

    • This is designed to append to path

  • 2023-06-20 @ddalle: v1.2; instance mthod

prepare_files(j: int)

Prepare files for phase j

Call:
>>> runner.prepare_files(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase index

Versions:
  • 2021-10-21 @ddalle: v1.0 (abstract cfdx method)

prepare_triq() FileStatus

Prepare the surface .triq file and return metadata

Call:
>>> triqstats = runner.prepare_triq()
>>> fname, n = runner.prepare_triq()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
triqstats: FileStatus

Surface .triq file name

triqstats.fname: str

Name of .triq file (created or found)

triqstats.n: int

Iteration number for fname

Versions:
  • 2025-08-11 @ddalle: v1.0

qstat

bool Whether or not to check PBS/Slurm job status

rc

cape.cfdx.options.runctlopts.RunControlOpts RunControl options for this case

read_archive_opts() ArchiveOpts

Read the Archive options for this case

This prefers the parent-folder JSON settings to those found in case.json. If no run matrix JSON settings can be read, the case.json settings will be used.

Call:
>>> opts = runner.read_archive_opts()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
opts: ArchiveOpts

Options interface from case.json

Versions:
  • 2024-08-28 @ddalle: v1.0

  • 2024-12-09 @ddalle: v2.0; prefer top-level JSON

read_case_json() RunControlOpts

Read case.json if not already

Call:
>>> rc = runner.read_case_json()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
rc: RunControlOpts

Options interface from case.json

Versions:
  • 2023-06-15 @ddalle: v1.0

  • 2024-07-18 @ddalle: v2.0; remove f option, use mtime

read_cntl() CntlBase

Read the parent run-matrix control that owns this case

Call:
>>> cntl = runner.read_cntl()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
cntl: Cntl | None

Run matrix control instance

Versions:
  • 2024-08-15 @ddalle: v1.0

  • 2024-08-28 @ddalle: v1.1; can work w/o case.json

read_condition(key: str, f: bool = False)

Read conditions.json if not already

Call:
>>> v = runner.read_condition(key, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

key: str

Name of run matrix key to query

f: True | {False}

Option to force re-read

Outputs:
v: int | float | str

Value of run matrix key key

Versions:
  • 2023-06-16 @ddalle: v1.0

read_conditions(f: bool = False) dict

Read conditions.json if not already

Call:
>>> xi = runner.read_conditions(f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: True | {False}

Option to force re-read

Outputs:
xi: dict

Run matrix conditions for this case

Versions:
  • 2023-06-16 @ddalle: v1.0

read_dex(comp: str) DataKit

Read a data component

Call:
>>> db = runner.read_dex(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-07-24 @ddalle: v1.0

  • 2025-08-12 @ddalle: v1.1; by-element; preprocess

read_dex_by_element(comp: str) DataKit

Read a data component with multiple elements

Call:
>>> db = runner.read_dex_by_element(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

Versions:
  • 2025-08-12 @ddalle: v1.0

read_dex_element(comp: str, compid: str) DataKit

Read one element of a data extracter component

Call:
>>> db = runner.read_dex_element(comp, compid)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read

compid: str

Name of component ID (usually matches comp)

Versions:
  • 2025-07-30 @ddalle: v1.0

read_resid(f: bool = False, meta: bool = False) CaseResid

Read the current residual history

Call:
>>> h = runner.read_resid(f=False, meta=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

f: True``| { ``False}

Read residual even if one is cached

meta: True | {False}

Option to only read first and last iteration

Outputs:
h: cape.cfdx.casedata.CaseResid

Iterative residual history

Versions:
  • 2055-08-04 @ddalle: v1.0

read_start_time()

Read the most recent start time to file

Call:
>>> nProc, tic = runner.read_start_time()
Inputs:
runner: CaseRunner

Controller to run one case of solver

fname: str

Name of file containing CPU usage history

Outputs:
nProc: None | int

Number of cores

tic: None | datetime.datetime

Time at which most recent run was started

Versions:
  • 2016-08-30 @ddalle: v1.0 (stand-alone)

  • 2023-06-17 @ddalle: v2.0; CaseRunner method

read_stop_phase() Tuple[bool, int | None]

Read CAPE-STOP-PHASE file for local stopping criterion

Call:
>>> q, j = runner.read_stop_phase()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
q: True | False

Whether CAPE-STOP-PHASE file exists

j: None | int

Phase at which to stop (every phase if None)

Versions:
  • 2024-05-26 @ddalle: v1.0

read_surfconfig() SurfConfig | None

Read surface configuration map file from best source

Call:
>>> conf = runner.read_surfconfig()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
conf: SurfConfig | None

Surface configuration instance, if possible

Versions:
  • 2025-01-30 @ddalle: v1.0

read_surfconfig_cntl() SurfConfig | None

Read surface configuration map file from run matrix control

Call:
>>> conf = runner.read_surfconfig_cntl()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
conf: SurfConfig | None

Surface configuration instance, if possible

Versions:
  • 2025-01-30 @ddalle: v1.0

read_surfconfig_local() ConfigXML | None

Read surface configuration map file from case folder

Call:
>>> conf = runner.read_surfconfig()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
conf: SurfConfig | None

Surface configuration instance, if possible

Versions:
  • 2025-01-30 @ddalle: v1.0

relpath(fname: str) str

Get path to file relative to case root directory

Call:
>>> frel = runner.relpath(fname)
Inputs:
runner: CaseRunner

Controller to run one case of solver

fname: str

File name, relative to PWD or absolute

Outputs:
frel: str

Path to fname relative to runner.root_dir

Versions:
  • 2024-08-14 @ddalle: v1.0

Delete a link [file if f] if it exists

Call:
>>> runner.remove_link(dst, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

dst: str

Name of link to delete

f: True | {False}

Option to overwrite dst, even if not a link

Versions:
  • 2024-08-14 @ddalle: v1.0

rename_file(src: str, dst: str, f: bool = False)

Rename a file and log results

Call:
>>> runner.rename_file(src, dst, f=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

src: str

Name of input file, before renaming

dst: str

Name of renamed file

f: True | {False}

Option to overwrite existing dst

Versions:
  • 2024-08-13 @ddalle: v1.0

resid

cape.cfdx.casedata.CaseResid Residual history instance

resubmit_case(j0: int)

Resubmit a case as a new job if appropriate

Call:
>>> q = runner.resubmit_case(j0)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j0: int

Index of phase most recently run prior (may differ from current phase)

Outputs:
q: True | False

Whether or not a new job was submitted to queue

Versions:
  • 2022-01-20 @ddalle: v1.0 (cape.pykes.case)

  • 2023-06-02 @ddalle: v1.0

  • 2024-05-25 @ddalle: v1.1; rename options

returncode

int Return code of last system command

run()

Setup and run appropriate solver commands

Call:
>>> ierr = runner.run()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
ierr: int

Return code; 0 for success

Versions:
  • 2014-10-02 @ddalle: v1.0

  • 2021-10-08 @ddalle: v1.1 (run_overflow)

  • 2023-06-21 @ddalle: v2.0; instance method

  • 2024-05-26 @ddalle: v2.1; more exit causes

  • 2025-06-24 @ddalle: v2.2; add rerunable-phase check

run_aflr3(j: int, proj: str, fmt='lb8.ugrid')

Create volume mesh using aflr3

This function looks for several files to determine the most appropriate actions to take:

  • {proj}.i.tri: Triangulation file

  • {proj}.surf: AFLR3 surface file

  • {proj}.aflr3bc: AFLR3 boundary conditions

  • {proj}.xml: Surface component ID mapping file

  • {proj}.{fmt}: Output volume mesh

  • {proj}.FAIL.surf: AFLR3 surface indicating failure

If the volume grid file already exists, this function takes no action. If the surf file does not exist, the function attempts to create it by reading the tri, xml, and aflr3bc files using cape.trifile.Tri. The function then calls cape.bin.aflr3() and finally checks for the FAIL file.

Call:
>>> runner.run_aflr3(j, proj, fmt='lb8.ugrid')
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

proj: str

Project root name

fmt: {"lb8.ugrid"} | str

AFLR3 volume mesh format

Versions:
  • 2016-04-05 @ddalle: v1.0 (CaseAFLR3())

  • 2023-06-02 @ddalle: v1.1; use get_aflr3_run()

  • 2023-06-20 @ddalle: v1.1; instance method

  • 2024-08-22 @ddalle: v1.2; add log messages

run_comp2tri(j: int) int

Run comp2tri to manipulate Cart3D geometries

Call:
>>> ierr = runner.run_comp2tri(j, proj="Components")
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

proj: {'Components'} | str

Project root name

Outputs:
ierr: int

Return code

Versions:
  • 2025-03-01 @ddalle: v1.0

run_intersect(j: int, proj: str = 'Components')

Run intersect to combine surface triangulations

This is a multi-step process in order to preserve all the component IDs of the input triangulations. Normally intersect requires each intersecting component to have a single component ID, and each component must be a water-tight surface.

Cape utilizes two input files, Components.c.tri, which is the original triangulation file with intersections and the original component IDs, and Components.tri, which maps each individual original tri file to a single component. The files involved are tabulated below.

  • Components.tri: Intersecting comps, each w/ single compID

  • Components.c.tri: Original intersecting tris and compIDs

  • Components.o.tri: Output of intersect w/ few compIDs

  • Components.i.tri: Orig compIDs mapped to intersected tris

More specifically, these files are {proj}.i.tri, etc.; the default project name is "Components". This function also calls the Chimera Grid Tools program triged to remove unused nodes from the intersected triangulation and optionally remove small triangles.

Call:
>>> runner.run_intersect(j, proj="Components")
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

proj: {'Components'} | str

Project root name

See also:
Versions:
  • 2015-09-07 @ddalle: v1.0 (CaseIntersect)

  • 2016-04-05 @ddalle: v1.1; generalize to cfdx

  • 2023-06-21 @ddalle: v1.2; update name, instance method

  • 2024-08-22 @ddalle: v1.3; add log messages

run_mixsur_tri(ifile: str, ofile: str) int

Create grid.i.tri using mixsur executable

Call:
>>> ierr = runner.run_mixsur_tri(ifile, ofile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ifile: str

Name of mixsur input file

ofile: str

Name of file for usurp STDOUT

Outputs:
ierr: int

Return code

Versions:
  • 2025-08-13 @ddalle: v1.0

run_more_cases() int

Submit more cases to the queue

Call:
>>> ierr = runner.run_more_cases()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
ierr: int

Return code, 0 if no new cases submitted

Versions:
  • 2023-12-13 @dvicker: v1.0

run_overint_triq(ifile: str, ofile: str) int

Create grid.i.triq using overint executable

Call:
>>> ierr = runner.run_overint_triq(ifile, ofile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ifile: str

Name of usurp input file

ofile: str

Name of file for usurp STDOUT

Outputs:
ierr: int

Return code

Versions:
  • 2025-08-13 @ddalle: v1.0

run_phase(j: int) int

Run one phase using appropriate commands

Call:
>>> ierr = runner.run_phase(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Outputs:
ierr: int

Return code

Versions:
  • 2023-06-05 @ddalle: v1.0 (pyover)

  • 2023-06-14 @ddalle: v1.0

run_phase_main(j: int) int

Run one instance of one phase, including running any hooks

Call:
>>> runner.run_phase_main(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Outputs:
ierr: int

Return code

Versions:
  • 2025-03-28 @ddalle: v1.0

run_post_pyfuncs(j: int)

Run PostPythonFuncs before run_phase()

Call:
>>> v = runner.run_post_pyfuncs(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Outputs:
v: any

Output of function

Versions:
  • 2025-03-28 @ddalle: v1.0

run_post_shell_cmds(j: int)

Run PostShellCmds after successful run_phase() exit

Call:
>>> runner.run_post_shell_cmds(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2023-07-17 @ddalle: v1.0

  • 2024-08-21 @ddalle: v1.1; log messages

run_pre_pyfuncs(j: int)

Run PrePythonFuncs before run_phase()

Call:
>>> v = runner.run_pre_pyfuncs(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Outputs:
v: any

Output of function

Versions:
  • 2025-03-28 @ddalle: v1.0

run_pre_shell_cmds(j: int)

Run PreShellCmds before run_phase()

Call:
>>> runner.run_pre_shell_cmds(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2025-02-28 @aburkhea: v1.0;

run_triload(ifile: str, ofile: str) int

Run the triloadCmd executable

Call:
>>> ierr = runner.run_triload(ifile, ofile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ifile: str

Name of triload input file

ofile: str

Name of file for triload STDOUT

Outputs:
ierr: int

Return code

Versions:
  • 2025-01-22 @ddalle: v1.0

run_usurp_tri(ifile: str, ofile: str) int

Create grid.i.tri using usurp executable

Call:
>>> ierr = runner.run_usurp_tri(ifile, ofile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ifile: str

Name of usurp input file

ofile: str

Name of file for usurp STDOUT

Outputs:
ierr: int

Return code

Versions:
  • 2025-08-13 @ddalle: v1.0

run_usurp_triq(ifile: str, ofile: str) int

Create grid.i.triq using usurp executable

Call:
>>> ierr = runner.run_usurp_triq(ifile, ofile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

ifile: str

Name of usurp input file

ofile: str

Name of file for usurp STDOUT

Outputs:
ierr: int

Return code

Versions:
  • 2025-08-13 @ddalle: v1.0

run_verify(j: int, proj='Components')

Run verify to check triangulation if appropriate

This function checks the validity of triangulation in file "%s.i.tri" % proj. It calls cape.bin.verify().

Call:
>>> runner.run_verify(j, proj='Components', fpre='run')
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

proj: {'Components'} | str

Project root name

Versions:
  • 2015-09-07 @ddalle: v1.0; from run_flowCart()

  • 2016-04-05 @ddalle: v1.1; generalize to cape

  • 2023-06-21 @ddalle: v2.0; instance method

  • 2024-08-22 @ddalle: v2.1; add log messages

run_worker_cmds(j: int)

Run shell commands in parallel while main solver runs

This will fork off one additional process for each entry of WorkerShellCmds, which will repeat every WorkerSleepTime seconds.

Call:
>>> runner.run_worker_cmds(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2025-03-28 @ddalle: v1.0

run_worker_pyfuncs(j: int)

Run Python functions in parallel while main solver runs

This will fork off one additional process for each entry of WorkerPythonFuncs, which will repeat every WorkerSleepTime seconds.

Call:
>>> runner.run_worker_pyfuncs(j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2025-03-28 @ddalle: v1.0

sample_dex(comp: str) DataKit

Sample a DataBook component (e.g. to a specific iteration)

Call:
>>> db = runner.sample_dex(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read and sample

Outputs:
db: DataKit

Sampled DataBook component or raw data

Versions:
  • 2025-08-04 @ddalle: v1.0

  • 2025-08-12 @ddalle: v1.1; sample nStats, XMRP, etc

sample_dex_fm(comp: str) DataKit

Sample a force & moment iterative history

Call:
>>> db = runner.sample_dex_fm(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component to read and sample

Outputs:
db: cape.dkit.rdb.DataKit

Sampled DataBook component or raw data

Versions:
  • 2025-07-29 @ddalle: v1.0

save_reportfiles()

Update list of protected files for generating reports

Call:
>>> runner.save_reportfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2024-09-14 @ddalle: v1.0

save_restartfiles()

Update list of protected files for restarting case

Call:
>>> runner.save_restartfiles()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2024-09-14 @ddalle: v1.0

search(pat: str, workdir: bool = False, regex: bool = False, links: bool = False) list

Search for files by glob and sort them by modification time

Call:
>>> file_list = runner.search(pat, workdir=False, **kw)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pat: str

File name pattern

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat, sorted by mtime

Versions:
  • 2025-01-23 @ddalle: v1.0

  • 2025-02-01 @ddalle: v1.1; use _search()

search_multi(pats: list, workdir: bool = False, regex: bool = False, links: bool = False) list

Search for files by glob and sort them by modification time

Call:
>>> file_list = runner.search_multi(pats)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pats: list[str]

List of file name patterns

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching any pat in pats, sorted by mtime

Versions:
  • 2025-01-23 @ddalle: v1.0

  • 2025-02-01 @ddalle: v1.1; use _search()

search_regex(pat: str, workdir: bool = False, regex: bool = True, links: bool = False) list

Search for files by regex and sort them by modification time

Call:
>>> file_list = runner.search_regex(pat)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pat: str

File name pattern

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat, sorted by mtime

Versions:
  • 2025-02-01 @ddalle: v1.0

search_regex_multi(pats: list, workdir: bool = False, regex: bool = True, links: bool = False) list

Search for files by regex and sort them by modification time

Call:
>>> file_list = runner.search_regex_multi(pats)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pats: list[str]

List of file name patterns

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching any pat in pats, sorted by mtime

Versions:
  • 2025-02-01 @ddalle: v1.0

search_regex_workdir(pat: str, workdir: bool = True, regex: bool = True, links: bool = False) list

Search for files by regex and sort them by modification time

Call:
>>> file_list = runner.search_regex_workdir(pat)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pat: str

File name pattern

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat in working folder, sorted by mtime

Versions:
  • 2025-02-01 @ddalle: v1.0

search_regex_workdir_multi(pats: list, workdir: bool = True, regex: bool = True, links: bool = False) list

Search for files by regex and sort them by modification time

Call:
>>> file_list = runner.search_regex_workdir_multi(pats)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pats: list[str]

List of file name patterns

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat in working folder, sorted by mtime

Versions:
  • 2025-02-01 @ddalle: v1.0

search_workdir(pat: str, workdir: bool = True, regex: bool = False, links: bool = False) list

Search for files by glob and sort them by modification time

Call:
>>> file_list = runner.search_workdir(pat)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pat: str

File name pattern

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat in working folder, sorted by mtime

Versions:
  • 2025-01-23 @ddalle: v1.0

  • 2025-02-01 @ddalle: v1.1; use _search()

search_workdir_multi(pats: list, workdir: bool = True, regex: bool = False, links: bool = False) list

Search for files by glob and sort them by modification time

Call:
>>> file_list = runner.search_workdir_multi(pats)
Inputs:
runner: CaseRunner

Controller to run one case of solver

pats: list[str]

List of file name patterns

links: True | {False}

Option to allow links in output

Outputs:
file_list: list[str]

Files matching pat in working folder, sorted by mtime

Versions:
  • 2025-01-23 @ddalle: v1.0

  • 2025-02-01 @ddalle: v1.1; use _search()

set_phase_iters(n: int, j: int)

Set min iteration required for completion of phase j

Call:
>>> runner.set_phase_iters(n, j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

n: int

Number of iterations

j: int

Phase index

Versions:
  • 2025-08-14 @ddalle: v1.0

set_rlimit(r: int, u: str, j: int = 0, unit: int = 1024)

Set resource limit for one variable

Call:
>>> runner.set_rlimit(r, u, j=0, unit=1024)
Inputs:
runner: CaseRunner

Controller to run one case of solver

r: int

Integer code of particular limit, from resource

u: str

Name of limit to set

j: {0} | int

Phase number

unit: {1024} | int

Multiplier, usually for a kbyte

See also:
  • cape.options.ulimit

Versions:
  • 2016-03-13 @ddalle: v1.0

  • 2021-10-21 @ddalle: v1.1; check if Windows

  • 2023-06-20 @ddalle: v1.2; was SetResourceLimit()

skeleton(test: bool = False)

Run the --skeleton archiving action

Call:
>>> runner.skeleton(test=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

test: True | {False}

Option to log all actions but not actually copy/delete

Versions:
  • 2024-09-18 @ddalle: v1.0

start()

Start or submit initial job

Call:
>>> ierr, job_id = runner.start()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Outputs:
ierr: int

Return code; 0 for success

job_id: None | int

PBS/Slurm job ID number if appropriate

Versions:
  • 2023-06-23 @ddalle: v1.0

stop_case()

Stop a case by deleting PBS job and removing RUNNING file

Call:
>>> runner.stop_case()
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2014-12-27 @ddalle: v1.0 (StopCase())

  • 2023-06-20 @ddalle: v1.1; instance method

  • 2023-07-05 @ddalle: v1.2; use CaseRunner.get_job_id()

tic

float Reference timer

touch_file(fname: str)

Create an empty file if necessary, or update mtime

Call:
>>> runner.touch_file(fname)
Inputs:
runner: CaseRunner

Controller to run one case of solver

fname: str

Name of file to “touch”

Version:
  • 2024-08-14 @ddalle: v1.0

transform_dex(comp: str, db: DataKit)

Apply transformations for a data extraction component

Call:
>>> runner.transform_dex(comp, db)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

db: cape.dkit.rdb.DataKit

Untransformed data extraction

Versions:
  • 2025-08-05 @ddalle: v1.0

transform_dex_fm(comp: str, fm: CaseFM)

Apply transformations for a force & moment data extraction

Call:
>>> runner.transform_dex_fm(comp, fm)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of DataBook component

fm: cape.cfdx.casedata.CasseFM

Untransformed force & moment residual history

Versions:
  • 2025-07-31 @ddalle: v1.0

unarchive(test: bool = False)

Run the --unarchive archiving action

Call:
>>> runner.unarchive(test=False)
Inputs:
runner: CaseRunner

Controller to run one case of solver

test: True | {False}

Option to log all actions but not actually copy/delete

Versions:
  • 2024-09-20 @ddalle: v1.0

validate_dstfile(dst: str)

Check that dst is a valid destination for rename/copy

Checks that dst is inside case folder

Call:
>>> runner.validate_dstfile(dst)
Inputs:
runner: CaseRunner

Controller to run one case of solver

src: str

Name of input file, before renaming

Versions:
  • 2024-08-14 @ddalle: v1.0

validate_srcfile(src: str)

Check that src exists and is a file

Checks that src is a file or a valid link.

Call:
>>> runner.validate_srcfile(src)
Inputs:
runner: CaseRunner

Controller to run one case of solver

src: str

Name of input file, before renaming

Versions:
  • 2024-08-14 @ddalle: v1.0

workers

list[int] List of concurrent worker Process IDs

write_case_json(rc: RunControlOpts)

Write the current settinsg to case.json

Call:
>>> runner.write_case_json(rc)
Inputs:
runner: CaseRunner

Controller to run one case of solver

rc: RunControlOpts

Options interface from case.json

Versions:
  • 2024-08-24 @ddalle: v1.0

write_start_time(j: int)

Write current start time, runner.tic, to file

Call:
>>> runner.write_start_time(tic, j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2015-12-09 @ddalle: v1.0 (pycart)

  • 2015-12-22 @ddalle: v1.0; module function

  • 2023-06-16 @ddalle: v2.0; CaseRunner method

write_triload_input(comp: str, ftriq: str)

Write input file for triloadCmd

Call:
>>> runner.write_triload_input(comp, ftriq)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component

ftriq: str

Name of appropriate .triq file to read from

Versions:
  • 2025-01-29 @ddalle: v1.0

  • 2025-08-12 @ddalle: v1.1; add ftriq as input

write_triload_transformations(comp: str)

Write transformation aspect of triloadCmd input file

Call:
>>> runner.write_triload_transformations(comp)
Inputs:
runner: CaseRunner

Controller to run one case of solver

comp: str

Name of component

Versions:
  • 2025-01-30 @ddalle: v1.0

write_triq(rawdatafile: str, triqfile: str)

Convert CFD data file to .triq format

This enables use with Chimera Grid Tools capabilities and integrates with CAPE’s TriqFM tools.

Call:
>>> runner.write_triq(rawdatafile, triqfile)
Inputs:
runner: CaseRunner

Controller to run one case of solver

Versions:
  • 2025-08-11 @ddalle: v1.0

write_user_time(j: int)

Write time usage since time tic to file

Call:
>>> runner.write_user_time(tic, j)
Inputs:
runner: CaseRunner

Controller to run one case of solver

j: int

Phase number

Versions:
  • 2015-12-09 @ddalle: v1.0 (pycart)

  • 2015-12-22 @ddalle: v1.0; module function

  • 2023-06-16 @ddalle: v2.0; CaseRunner method

xi

dict | None Dictionary of conditions for this case

class cape.cfdx.casecntl.FileSearchStatus(mtch, n)

Class for file search regex and iteration status

Call:
>>> fstat = FileSearchStatus(mtch, n)
Attributes:
mtch: re.Match | None

Regular expression match object for file name

n: int | None

(Inferred) iteration for any file found

mtch

Alias for field number 0

n

Alias for field number 1

class cape.cfdx.casecntl.FileStatus(fname, n)

Class for file name and iteration status

Call:
>>> fstat = FileStatus(fname, n)
Attributes:
fname: str | None

File name

n: int | None

(Inferred) iteration for any file found

fname

Alias for field number 0

n

Alias for field number 1

cape.cfdx.casecntl.GetTriqFile(proj='Components')

Get most recent triq file and its associated iterations

This is a template version with specific implementations for each solver. The cape.cfdx version simply returns the most recent triq file in the folder with no iteration information.

Call:
>>> ftriq, n, i0, i1 = GetTriqFile(proj='Components')
Inputs:
proj: {"Components"} | str

File root name

Outputs:
ftriq: str

Name of most recently modified triq file

n: {None}

Number of iterations included

i0: {None}

First iteration in the averaging

i1: {None}

Last iteration in the averaging

Versions:
  • 2016-12-19 @ddalle: v1.0

class cape.cfdx.casecntl.IterWindow(ia, ib)

Class for beginning and end iter of an averaging window

Call:
>>> window = IterWindow(ia, ib)
Attributes:
ia: int`| ``None`

Iteration at start of window

ib: int | None

Iteration at end of window

ia

Alias for field number 0

ib

Alias for field number 1

cape.cfdx.casecntl.REGEX_RUNFILE = re.compile('run.([0-9][0-9]+).([0-9]+)')

Regular expression for run log files written by CAPE

cape.cfdx.casecntl.StartCase()

Empty template for starting a case

The function is empty but does not raise an error

Call:
>>> cape.casecntl.StartCase()
See also:
  • cape.pycart.casecntl.StartCase()

  • cape.pyfun.casecntl.StartCase()

  • cape.pyover.casecntl.StartCase()

Versions:
  • 2015-09-27 @ddalle: v1.0

  • 2023-06-02 @ddalle: v2.0; empty

cape.cfdx.casecntl.set_rlimit(r: int, ulim: ULimitOpts, u: str, i: int = 0, unit: int = 1024)

Set resource limit for one variable

Call:
>>> set_rlimit(r, ulim, u, i=0, unit=1024)
Inputs:
r: int

Integer code of particular limit, from resource

ulim: ULimitOpts

System resource options interface

u: str

Name of limit to set

i: int

Phase number

unit: int

Multiplier, usually for a kbyte

See also:
  • cape.options.ulimit

Versions:
  • 2016-03-13 @ddalle: v1.0

  • 2021-10-21 @ddalle: v1.1; check if Windows

  • 2023-06-20 @ddalle: v1.2; was SetResourceLimit()