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 |
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. |
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. |
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. |
from_dict
classmethod
¶
from_dict(value: dict[str, Any]) -> ProcessCase
Validate an entire process description, including topology and metric dimensions.
with_parameters
¶
with_parameters(overrides: dict[str, Any]) -> ProcessCase
Create a new case revision using explicit quantities for parameter updates.
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
¶
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 an already validated SI value tree without making traced values concrete.
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
¶
CaseInitialization
¶
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
¶
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
¶
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
¶
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.
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 |
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
¶
Verify an artifact before making it available to reporting clients.
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
¶
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 only recorded values, keeping qualification and acceptance distinct.
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
¶
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. |
load_case
¶
load_case(case_id: str) -> ProcessCase
Load a revision and verify its filename against its content.
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.
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
¶
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. |
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
¶
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
¶
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.