Skip to content

Process cases and design studies

See the process cases guide for complete saved-case, CLI, design-study, and accountable-copilot workflows.

schema

Versioned, immutable, portable process definitions.

Only registered units and a bounded expression grammar can appear in a case. There are no Python expressions, imports, pickle objects, or executable file references in the format. Arbitrary Python flowsheets remain a separate API.

Classes:

Name Description
Parameter

A scalar operating parameter with SI defaults and optional SI bounds.

FeedDefinition

Compiled feed specifications, retaining explicit branch selection.

ProcessCase

An immutable validated case with a stable content hash.

Functions:

Name Description
identifier

Validate a portable identifier usable in files, metrics, and connections.

sequence

Read a bounded array with a path-aware length error.

parse_parameters

Parse scalar parameter declarations, converting defaults and bounds together.

value_spec

Compile a literal or {"parameter": name} reference into an SI value spec.

resolve_value

Resolve an already validated SI value tree without making traced values concrete.

parse_feeds

Validate feed bases and specifications without running thermodynamics.

validate_feed_values

Check a concrete set of feed conditions before compiling any physical calculation.

Parameter dataclass

Parameter(
    name: str,
    value: float,
    unit: str,
    lower: float | None = None,
    upper: float | None = None,
)

A scalar operating parameter with SI defaults and optional SI bounds.

Methods:

Name Description
check

Reject overrides outside the declared bounds.

Attributes:

Name Type Description
dimension Dimension

Physical dimension of this parameter.

difference bool

Whether the parameter represents a temperature interval.

dimension property

dimension: Dimension

Physical dimension of this parameter.

difference property

difference: bool

Whether the parameter represents a temperature interval.

check

check(value: float, path: str) -> None

Reject overrides outside the declared bounds.

FeedDefinition dataclass

FeedDefinition(
    name: str,
    flow: float | str,
    z: tuple[float | str, ...],
    pressure: float | str,
    temperature: float | str | None,
    enthalpy: float | str | None,
    phase: str | None,
)

Compiled feed specifications, retaining explicit branch selection.

Methods:

Name Description
build

Construct a differentiable stream from operating parameters.

build

build(
    components: tuple[str, ...],
    parameters: dict[str, Any],
    package: Any,
) -> Any

Construct a differentiable stream from operating parameters.

ProcessCase dataclass

ProcessCase(_json: str)

An immutable validated case with a stable content hash.

Construct with :meth:from_dict or :meth:load. to_dict returns a new object, so a caller cannot mutate a compiled case by editing its source map.

Methods:

Name Description
from_dict

Validate an entire process description, including topology and metric dimensions.

load

Read and validate a portable JSON case.

save

Atomically save the case with its explicit input units.

to_dict

Return a detached JSON representation.

with_parameters

Create a new case revision using explicit quantities for parameter updates.

Attributes:

Name Type Description
name str

Portable case name.

case_id str

SHA-256 identity of this exact case revision.

components tuple[str, ...]

Canonical ordered component basis.

parameters dict[str, Parameter]

Fresh parameter declarations in SI.

name property

name: str

Portable case name.

case_id property

case_id: str

SHA-256 identity of this exact case revision.

components property

components: tuple[str, ...]

Canonical ordered component basis.

parameters property

parameters: dict[str, Parameter]

Fresh parameter declarations in SI.

from_dict classmethod

from_dict(value: dict[str, Any]) -> ProcessCase

Validate an entire process description, including topology and metric dimensions.

load classmethod

load(path: str | Path) -> ProcessCase

Read and validate a portable JSON case.

save

save(path: str | Path) -> None

Atomically save the case with its explicit input units.

to_dict

to_dict() -> dict[str, Any]

Return a detached JSON representation.

with_parameters

with_parameters(overrides: dict[str, Any]) -> ProcessCase

Create a new case revision using explicit quantities for parameter updates.

identifier

identifier(value: Any, path: str) -> str

Validate a portable identifier usable in files, metrics, and connections.

sequence

sequence(
    value: Any,
    path: str,
    *,
    minimum: int = 0,
    maximum: int = 1000,
) -> list[Any]

Read a bounded array with a path-aware length error.

parse_parameters

parse_parameters(data: Any) -> dict[str, Parameter]

Parse scalar parameter declarations, converting defaults and bounds together.

value_spec

value_spec(
    value: Any,
    dimension: Dimension,
    parameters: dict[str, Parameter],
    path: str,
    *,
    difference: bool = False,
) -> float | str

Compile a literal or {"parameter": name} reference into an SI value spec.

resolve_value

resolve_value(
    value: Any, parameters: dict[str, Any]
) -> Any

Resolve an already validated SI value tree without making traced values concrete.

parse_feeds

parse_feeds(
    data: Any,
    components: tuple[str, ...],
    parameters: dict[str, Parameter],
) -> tuple[FeedDefinition, ...]

Validate feed bases and specifications without running thermodynamics.

validate_feed_values

validate_feed_values(
    feeds: tuple[FeedDefinition, ...],
    parameters: dict[str, float],
) -> None

Check a concrete set of feed conditions before compiling any physical calculation.

runtime

Differentiable execution of portable process cases with retained unit results.

Classes:

Name Description
SolverOptions

Reproducible numerical choices; no solver silently falls back to another backend.

CaseEvaluation

JAX pytree of numerical results in SI, before expensive host acceptance audits.

CaseInitialization

Detached recycle and column seeds for a numerical study evaluation.

CaseRunner

Compile a validated case once, then run, differentiate, or study it.

SolverOptions dataclass

SolverOptions(
    backend: str = "sequential",
    recycle_method: str = "wegstein",
    tolerance: float = 1e-09,
    max_iterations: int = 100,
    specification_iterations: int = 40,
    column_solver: str = "block",
    eo_jacobian: str = "colored",
)

Reproducible numerical choices; no solver silently falls back to another backend.

CaseEvaluation

Bases: NamedTuple

JAX pytree of numerical results in SI, before expensive host acceptance audits.

CaseInitialization

Bases: NamedTuple

Detached recycle and column seeds for a numerical study evaluation.

CaseRunner

CaseRunner(
    case: ProcessCase,
    *,
    options: SolverOptions | None = None,
    policy: AcceptancePolicy = DEFAULT_POLICY,
)

Compile a validated case once, then run, differentiate, or study it.

evaluate accepts SI parameter values and returns a differentiable pytree. It is a numerical kernel, not a physical-acceptance boundary. Use run for an audited, serializable result. Host overrides always require explicit quantities. Design-spec manipulated parameters are solved within their bounds.

Methods:

Name Description
diagnose_structure

Describe process topology and declared numerical structure without solving.

parameter_values

Convert explicit host quantities and validate the entire operating point.

validate_values

Check concrete SI values before a host solve or accepted study point.

prepare

Build EO plans with concrete defaults before tracing; repeated calls are cheap.

initialization

Recover study seeds from an accepted run of this exact case revision.

evaluate

Evaluate in SI with implicit derivatives through recycles and bounded specs.

run

Solve and independently audit a case, retaining failures in a run artifact.

diagnose_structure

diagnose_structure() -> dict[str, Any]

Describe process topology and declared numerical structure without solving.

Registered EO units retain nested column and flash solves. Their global incidence report describes stream connections, not an expanded MESH system. Structural matching doesn't imply accepted process physics.

parameter_values

parameter_values(
    overrides: dict[str, Any] | None = None,
) -> dict[str, Any]

Convert explicit host quantities and validate the entire operating point.

validate_values

validate_values(values: dict[str, Any]) -> None

Check concrete SI values before a host solve or accepted study point.

prepare

prepare() -> None

Build EO plans with concrete defaults before tracing; repeated calls are cheap.

initialization

initialization(run: Any) -> CaseInitialization

Recover study seeds from an accepted run of this exact case revision.

Seeds don't change run: persisted candidates always start cold. Studies record the baseline identity and pass these detached values explicitly to evaluate. No failed trial updates a shared seed.

evaluate

evaluate(
    parameters: dict[str, Any] | None = None,
    *,
    package: Any = None,
    initialization: CaseInitialization | None = None,
) -> CaseEvaluation

Evaluate in SI with implicit derivatives through recycles and bounded specs.

Call prepare before an enclosing JAX transformation for the EO backend. Differentiating with respect to a manipulated parameter's initial guess gives zero; the converged specification determines it.

run

run(
    overrides: dict[str, Any] | None = None,
    *,
    check: bool = False,
) -> Any

Solve and independently audit a case, retaining failures in a run artifact.

results

Independent process acceptance and portable run artifacts.

Classes:

Name Description
CaseRun

Immutable audited result with its exact input case and numerical environment.

CaseAcceptanceError

A failed process run; inspect run for all independently graded criteria.

Functions:

Name Description
json_value

Detach arrays into strict JSON; unavailable nonfinite diagnostics become null.

sealed

Create a content-addressed envelope with no timestamp-dependent identity.

verify_artifact

Verify a strict JSON envelope's content integrity, not its external authenticity.

build_run

Audit every unit boundary, the plant boundary, streams, and declared outputs.

render_report

Render only recorded values, keeping qualification and acceptance distinct.

compare_runs

Compare compatible case metrics in SI, recording both acceptance states.

CaseRun dataclass

CaseRun(_json: str)

Immutable audited result with its exact input case and numerical environment.

The hash detects accidental alteration. It isn't a signature or a guarantee that an arbitrary external author actually ran the recorded calculation.

Methods:

Name Description
from_dict

Verify an artifact before making it available to reporting clients.

load

Read a content-verified saved run.

to_dict

Return a detached JSON report.

check

Raise with the failed run attached, preserving its diagnostic evidence.

save

Atomically save the complete strict-JSON result.

markdown

Render a deterministic engineering report with explicit qualification scope.

Attributes:

Name Type Description
run_id str

Identity of the complete result, including numerical and evidence settings.

accepted bool

Whether the recorded numerical, physical, metric, and cost checks passed.

run_id property

run_id: str

Identity of the complete result, including numerical and evidence settings.

accepted property

accepted: bool

Whether the recorded numerical, physical, metric, and cost checks passed.

from_dict classmethod

from_dict(value: dict[str, Any]) -> CaseRun

Verify an artifact before making it available to reporting clients.

load classmethod

load(path: str | Path) -> CaseRun

Read a content-verified saved run.

to_dict

to_dict() -> dict[str, Any]

Return a detached JSON report.

check

check() -> None

Raise with the failed run attached, preserving its diagnostic evidence.

save

save(path: str | Path) -> None

Atomically save the complete strict-JSON result.

markdown

markdown() -> str

Render a deterministic engineering report with explicit qualification scope.

CaseAcceptanceError

CaseAcceptanceError(run: CaseRun)

Bases: RuntimeError

A failed process run; inspect run for all independently graded criteria.

json_value

json_value(value: Any) -> Any

Detach arrays into strict JSON; unavailable nonfinite diagnostics become null.

sealed

sealed(
    kind: str, payload: dict[str, Any]
) -> dict[str, Any]

Create a content-addressed envelope with no timestamp-dependent identity.

verify_artifact

verify_artifact(
    value: Any, kind: str | None = None
) -> dict[str, Any]

Verify a strict JSON envelope's content integrity, not its external authenticity.

build_run

build_run(
    runner: Any,
    evaluation: Any,
    requested: dict[str, Any],
    solver: dict[str, Any],
    policy: dict[str, Any],
) -> CaseRun

Audit every unit boundary, the plant boundary, streams, and declared outputs.

render_report

render_report(run: CaseRun) -> str

Render only recorded values, keeping qualification and acceptance distinct.

compare_runs

compare_runs(
    baseline: CaseRun, candidate: CaseRun
) -> dict[str, Any]

Compare compatible case metrics in SI, recording both acceptance states.

workspace

Atomic, content-addressed case revisions, runs, and studies in a local directory.

Classes:

Name Description
CaseWorkspace

An explicit artifact directory; identifiers never act as arbitrary file paths.

CaseWorkspace

CaseWorkspace(root: str | Path)

An explicit artifact directory; identifiers never act as arbitrary file paths.

Cases are immutable revisions identified by their content, so updates don't overwrite earlier runs or require a mutable global 'current case' pointer. Existing objects are verified before an idempotent save succeeds.

Methods:

Name Description
save_case

Save an immutable case revision and return its ID.

load_case

Load a revision and verify its filename against its content.

save_run

Persist the case revision and its complete audited result.

load_run

Load and verify a stored run.

save_artifact

Save a verified run, study, or comparison envelope atomically.

load_artifact

Read an artifact, checking both envelope and filename identities.

list_cases

List verified case revisions in deterministic identity order.

replay

Recompute a stored run with its case, requested values, and recorded policy.

save_case

save_case(case: ProcessCase) -> str

Save an immutable case revision and return its ID.

load_case

load_case(case_id: str) -> ProcessCase

Load a revision and verify its filename against its content.

save_run

save_run(run: CaseRun) -> str

Persist the case revision and its complete audited result.

load_run

load_run(run_id: str) -> CaseRun

Load and verify a stored run.

save_artifact

save_artifact(artifact: dict[str, Any]) -> str

Save a verified run, study, or comparison envelope atomically.

load_artifact

load_artifact(artifact_id: str) -> dict[str, Any]

Read an artifact, checking both envelope and filename identities.

list_cases

list_cases() -> list[dict[str, str]]

List verified case revisions in deterministic identity order.

replay

replay(run_id: str) -> CaseRun

Recompute a stored run with its case, requested values, and recorded policy.

studies

Reproducible parameter sweeps, checked sensitivities, and constrained design studies.

Classes:

Name Description
StudyResult

A study manifest and the complete audited runs it references.

Functions:

Name Description
sweep

Run a deterministic Cartesian sweep of explicit parameter quantities.

sensitivities

Compare implicit JAX derivatives with centered differences of accepted runs.

optimize

Solve a bounded local constrained design using SLSQP and exact JAX derivatives.

StudyResult dataclass

StudyResult(
    artifact: dict[str, Any], runs: tuple[CaseRun, ...]
)

A study manifest and the complete audited runs it references.

save writes runs first, then the manifest, so a published manifest never references an unwritten run. Failed points remain first-class study records.

Methods:

Name Description
save

Persist all dependent runs and then the manifest.

Attributes:

Name Type Description
study_id str

Content identity of the study manifest.

accepted bool

Whether the study's explicit acceptance criteria passed.

study_id property

study_id: str

Content identity of the study manifest.

accepted property

accepted: bool

Whether the study's explicit acceptance criteria passed.

save

save(workspace: CaseWorkspace) -> str

Persist all dependent runs and then the manifest.

sweep

sweep(
    runner: CaseRunner,
    grid: dict[str, list[Any]],
    *,
    workspace: CaseWorkspace | None = None,
    max_points: int = 100,
) -> StudyResult

Run a deterministic Cartesian sweep of explicit parameter quantities.

Invalid point inputs and failed physical solves are retained, never silently omitted from averages or presented as successful operating points.

sensitivities

sensitivities(
    runner: CaseRunner,
    parameters: list[str],
    metrics: list[str],
    *,
    overrides: dict[str, Any] | None = None,
    relative_step: float = 0.0001,
    relative_tolerance: float = 0.002,
    release_caches: bool = False,
    derivative_mode: str = "auto",
    derivative_batch_size: int = 1,
    workspace: CaseWorkspace | None = None,
    recorder: PerformanceRecorder | None = None,
) -> StudyResult

Compare implicit JAX derivatives with centered differences of accepted runs.

Both differences stay within declared bounds. Phase-regime changes, nonfinite derivatives, failed perturbed runs, and boundary points are reported as unverified, with no extrapolated gradient claim. This checks a local derivative; it doesn't establish uncertainty or a global response. An optional recorder observes derivative phases without changing the study's identity or acceptance criteria.

optimize

optimize(
    runner: CaseRunner,
    variables: list[str],
    objective: str,
    *,
    sense: str = "min",
    constraints: list[dict[str, Any]] | None = None,
    overrides: dict[str, Any] | None = None,
    max_iterations: int = 100,
    release_caches: bool = False,
    derivative_mode: str = "auto",
    derivative_batch_size: int = 1,
    workspace: CaseWorkspace | None = None,
    recorder: PerformanceRecorder | None = None,
) -> StudyResult

Solve a bounded local constrained design using SLSQP and exact JAX derivatives.

Variables use their declared bounds. Trial points get numerical checks; baseline and final points additionally receive independent physical audits. Success requires optimizer termination, feasibility, finite derivatives, and accepted final physics. A failed final candidate is retained, never promoted. Screening economics and local optimization don't imply a global optimum. An optional recorder measures each local linearization and Jacobian application without adding timing fields to the study artifact.

profiling

Explicit performance observations tied to audited process runs.

Timings live in a separate artifact, so profiling doesn't add nondeterministic fields to ordinary case/run identities. Compilation and execution are separated only where a caller explicitly lowers and compiles a JAX kernel. A modular plant's first evaluation includes its individual units' compilation work.

Classes:

Name Description
PerformanceRecorder

Synchronize timed operations and optionally checkpoint phase observations.

Functions:

Name Description
peak_rss_bytes

Return process-lifetime peak resident bytes, or None where unavailable.

profile

Measure an audited case and optional reusable implicit metric derivatives.

PerformanceRecorder

PerformanceRecorder(checkpoint: str | Path | None = None)

Synchronize timed operations and optionally checkpoint phase observations.

Checkpoints describe in-progress or failed work; they aren't accepted run artifacts. A killed subprocess can leave its last completed phase on disk. Use a fresh process and an explicitly isolated persistent cache for a cold benchmark. This recorder never clears process-global caches on its own.

Methods:

Name Description
snapshot

Return an unsealed observation, including any completed phases.

measure

Time one operation through device completion and retain failures.

compiled_kernel

Measure tracing/lowering, compilation, first execution, and warm execution.

snapshot

snapshot(status: str = 'running') -> dict[str, Any]

Return an unsealed observation, including any completed phases.

measure

measure(
    name: str,
    operation: Callable[[], Any],
    *,
    ready: Callable[[Any], Any] | None = None,
) -> Any

Time one operation through device completion and retain failures.

compiled_kernel

compiled_kernel(
    name: str,
    function: Callable[..., Any],
    args: tuple[Any, ...],
    *,
    repeats: int = 2,
) -> Any

Measure tracing/lowering, compilation, first execution, and warm execution.

Call in a fresh process to characterize cold compilation. Persistent cache hits can reduce the compile phase and must be recorded by the benchmark caller. The returned value is the final synchronized result.

peak_rss_bytes

peak_rss_bytes() -> int | None

Return process-lifetime peak resident bytes, or None where unavailable.

This includes compilation and native allocations. It is a high-water mark for this process, not an allocation counter or a per-phase memory delta.

profile

profile(
    runner: CaseRunner,
    *,
    overrides: dict[str, Any] | None = None,
    parameters: list[str] | None = None,
    metrics: list[str] | None = None,
    derivative_mode: str = "auto",
    derivative_batch_size: int = 1,
    warm_repeats: int = 2,
    workspace: CaseWorkspace | None = None,
    recorder: PerformanceRecorder | None = None,
) -> StudyResult

Measure an audited case and optional reusable implicit metric derivatives.

First calls may include compilation; this API makes no cold-cache claim. Derivative observations require an accepted baseline and finite converged numerical evaluations. They aren't finite-difference verification; use sensitivities for that independent check. Failed physics remains failed regardless of speed. Peak RSS includes every prior allocation in the process.

examples

Executable, exportable process examples using the portable case vocabulary.

Functions:

Name Description
example_case

Construct a built-in case that can be exported and reopened as plain JSON.

ethanol_train_case

An NRTL ethanol-water column with feed/bottoms heat recovery.

heater_bank_case

Independent energy-balanced heaters for many-variable derivative studies.

reactive_case

Illustrative butane isomerization with real-fluid reaction and energy closure.

example_case

example_case(name: str = 'heater') -> ProcessCase

Construct a built-in case that can be exported and reopened as plain JSON.

Economic prices and CEPCI are illustrative declared assumptions, not live market data. The depropanizer reproduces the existing rigorous plant test's 95% propane purity and 98% recovery with feed/bottoms heat recovery.

ethanol_train_case

ethanol_train_case(n_stages: int = 12) -> ProcessCase

An NRTL ethanol-water column with feed/bottoms heat recovery.

Uses the curated parameter case from the existing numerical plant test. This performance example makes no new measured qualification claim.

heater_bank_case

heater_bank_case(count: int = 24) -> ProcessCase

Independent energy-balanced heaters for many-variable derivative studies.

Each heater has its own fresh feed, outlet, and bounded temperature. Total heat and annual cost depend on every variable, so a reverse derivative measures the cost of increasing the parameter count without adding an artificial optimization objective.

reactive_case

reactive_case(*, separation: bool = False) -> ProcessCase

Illustrative butane isomerization with real-fluid reaction and energy closure.

The kinetic coefficient and equipment sizes are design demonstrations, not measured catalyst data. Detailed balance derives the reverse activity rate from the component formation data. The separation variant reacts in liquid stage volumes; the vapor variant closes a component-selective recycle.