API Reference

Application Layer

cli

cli.create_sphinx_skeleton(dest, *, force=False)[source]

Create a conservative Sphinx skeleton for the root-layout TDPy project.

Parameters:
  • dest (str | Path)

  • force (bool)

Return type:

Path

cli.build_parser()[source]

Build the TDPy command-line parser.

Return type:

ArgumentParser

cli.main(argv=None)[source]

Run the command-line interface.

Parameters:

argv (list[str] | None)

Return type:

int

app

class app.TdpyApp(in_dir=None, out_dir=None)[source]

Bases: object

Application service: orchestrates parsing, solving, and output writing.

Parameters:
  • in_dir (Path | None)

  • out_dir (Path | None)

list_inputs()[source]
Return type:

Dict[str, Any]

run(req)[source]
Parameters:

req (RunRequest)

Return type:

RunResult

apis

class apis.RunRequest(in_path, out_path=None, make_plots=False, unit_system='SI', prefer_solver=None, opts=<factory>, overrides=<factory>)[source]

Bases: object

Top-level run request used by the app, CLI, and GUI.

Parameters:
  • in_path (pathlib.Path) – Input file path. TDPy is intentionally file-driven, so this is the only required path.

  • out_path (pathlib.Path | None) – Optional output file path. When omitted, the application layer chooses a default path.

  • make_plots (bool) – Request default plots when the selected solver supports them.

  • unit_system (Literal['SI', 'English', 'Mixed']) – Unit-system hint. "Mixed" means individual fields may include explicit units such as "300 K".

  • prefer_solver (str | None) – Optional solver preference kept for compatibility with older callers.

  • opts (Mapping[str, Any]) – Preferred runtime override mapping used by newer CLI tooling.

  • overrides (Mapping[str, Any]) – Legacy runtime override mapping kept for compatibility.

Notes

This module does not apply overrides directly. The application layer decides how to merge and use them. For minimal surprise, application code should merge overrides first and then opts so that opts wins.

in_path: Path
out_path: Path | None = None
make_plots: bool = False
unit_system: Literal['SI', 'English', 'Mixed'] = 'SI'
prefer_solver: str | None = None
opts: Mapping[str, Any]
overrides: Mapping[str, Any]
class apis.RunResult(ok, solver, in_path, out_path, payload, plots=<factory>, warnings=<factory>, meta=<factory>)[source]

Bases: object

Standardized result envelope returned by the application layer.

Parameters:
  • ok (bool) – Whether the pipeline completed successfully.

  • solver (str) – Solver or backend label used for the run.

  • in_path (pathlib.Path) – Resolved input path.

  • out_path (pathlib.Path | None) – Resolved output path, if output was written.

  • payload (Dict[str, Any]) – JSON-serializable result payload returned by the solver.

  • plots (Dict[str, str]) – Mapping from plot names to generated file paths.

  • warnings (List[str]) – Non-fatal warnings produced during the run.

  • meta (Dict[str, Any]) – Additional metadata such as backend details, timing, or version tags.

ok: bool
solver: str
in_path: Path
out_path: Path | None
payload: Dict[str, Any]
plots: Dict[str, str]
warnings: List[str]
meta: Dict[str, Any]
class apis.ProblemSpec(problem_type, data, schema_version='1.0')[source]

Bases: object

Generic problem specification produced by the design layer.

Parameters:
  • problem_type (str) – Extensible problem type string. Common values include "nozzle_ideal", "thermo_props", "equations", and "optimize".

  • data (Dict[str, Any]) – Problem-specific input mapping after the top-level problem_type has been separated.

  • schema_version (str) – Schema version for the generic envelope.

problem_type: str
data: Dict[str, Any]
schema_version: str = '1.0'
class apis.ThermoPropsRequest(fluid, inputs, outputs, backend='coolprop', basis='mass', units=<factory>, options=<factory>)[source]

Bases: object

Request thermodynamic properties from a selected backend.

Parameters:
  • fluid (str) – Fluid or working-pair identifier.

  • inputs (Mapping[str, Any]) – Mapping of input property names to values.

  • outputs (Sequence[str]) – Requested output property names.

  • backend (Literal['coolprop', 'cantera', 'librh2o', 'nh3h2o', 'auto']) – Backend selector such as "coolprop", "cantera", or "auto".

  • basis (Literal['mass', 'molar']) – Property basis, usually "mass" or "molar".

  • units (Mapping[str, str]) – Optional mapping of property names to unit strings.

  • options (Mapping[str, Any]) – Backend-specific options.

Example

A typical request may use fluid="R134a", inputs such as temperature and pressure, and outputs such as enthalpy, entropy, and density.

fluid: str
inputs: Mapping[str, Any]
outputs: Sequence[str]
backend: Literal['coolprop', 'cantera', 'librh2o', 'nh3h2o', 'auto'] = 'coolprop'
basis: Literal['mass', 'molar'] = 'mass'
units: Mapping[str, str]
options: Mapping[str, Any]
class apis.ThermoPropsResult(fluid, backend, basis, inputs, outputs, units=<factory>, warnings=<factory>, meta=<factory>)[source]

Bases: object

Result of a thermodynamic-property evaluation.

Parameters:
  • fluid (str)

  • backend (str)

  • basis (str)

  • inputs (Dict[str, Any])

  • outputs (Dict[str, Any])

  • units (Dict[str, str])

  • warnings (List[str])

  • meta (Dict[str, Any])

fluid: str
backend: str
basis: str
inputs: Dict[str, Any]
outputs: Dict[str, Any]
units: Dict[str, str]
warnings: List[str]
meta: Dict[str, Any]
class apis.EquationSpec(kind='expr', expr=None, fn=None, args=<factory>, label=None)[source]

Bases: object

Equation specification.

kind=”expr”:
  • expr: expression string representing a constraint (residual == 0)

kind=”residual”:
  • fn: name of a built-in residual provider (string key)

  • args: JSON-friendly kwargs payload for that residual provider

Parameters:
  • kind (Literal['expr', 'residual'])

  • expr (str | None)

  • fn (str | None)

  • args (Dict[str, Any])

  • label (str | None)

expr: str | None = None
fn: str | None = None
kind: Literal['expr', 'residual'] = 'expr'
label: str | None = None
args: Dict[str, Any]
class apis.EquationSystemSpec(vars, equations, params=<factory>, meta=<factory>, backend='auto', method='hybr', tol=1e-09, max_iter=200, max_restarts=2, use_units=False, solve=<factory>)[source]

Bases: object

A full system definition: variables + parameters + equations.

Optional solver configuration:
  • top-level hints: backend/method/tol/max_iter/max_restarts/use_units

  • ALSO stores raw solve block (solve: {…}) if provided by input JSON

Backends are free to ignore hints. The solver layer decides behavior.

Parameters:
  • vars (Dict[str, VarSpec])

  • equations (List[EquationSpec])

  • params (Dict[str, ParamSpec])

  • meta (Dict[str, Any])

  • backend (str)

  • method (str)

  • tol (float)

  • max_iter (int)

  • max_restarts (int)

  • use_units (bool)

  • solve (Dict[str, Any])

backend: str = 'auto'
check_square()[source]

EES-style determinism: number of equations equals number of unknowns.

Return type:

None

max_iter: int = 200
max_restarts: int = 2
method: str = 'hybr'
n_equations()[source]
Return type:

int

n_unknowns()[source]
Return type:

int

params_for_eval()[source]
Return type:

Dict[str, Any]

tol: float = 1e-09
unknown_names()[source]
Return type:

List[str]

use_units: bool = False
validate()[source]
Return type:

None

property variables: List[VarSpec]
vars: Dict[str, VarSpec]
equations: List[EquationSpec]
params: Dict[str, ParamSpec]
meta: Dict[str, Any]
solve: Dict[str, Any]
class apis.VarSpec(name, value=None, guess=None, unit=None, desc=None, lower=None, upper=None, fixed=False, label=None)[source]

Bases: object

Variable specification.

Unknown vs fixed:
  • fixed=True -> known constant inside solve; requires value (guess ignored)

  • fixed=False -> unknown; requires guess (or value-as-guess)

Units:
  • unit is a display hint and also used to interpret numeric guess/bounds.

  • guess/value may be a quantity string (“300 K”) regardless of unit hint.

Parameters:
  • name (str)

  • value (float | None)

  • guess (float | None)

  • unit (str | None)

  • desc (str | None)

  • lower (float | None)

  • upper (float | None)

  • fixed (bool)

  • label (str | None)

bounds()[source]
Return type:

Tuple[float | None, float | None]

desc: str | None = None
fixed: bool = False
guess: float | None = None
guess_value(default=1.0)[source]

Preference: guess -> value -> default.

Parameters:

default (float)

Return type:

float

property kind: str
label: str | None = None
lower: float | None = None
unit: str | None = None
property unknown: bool
upper: float | None = None
value: float | None = None
name: str
class apis.ParamSpec(name, value, unit=None, desc=None, label=None)[source]

Bases: object

Parameter (constant) specification. Value may be float OR non-float (e.g., fluid string).

Parameters:
  • name (str)

  • value (Any)

  • unit (str | None)

  • desc (str | None)

  • label (str | None)

desc: str | None = None
label: str | None = None
unit: str | None = None
name: str
value: Any
exception apis.SpecError[source]

Bases: ValueError

Raised when an equation system spec is malformed.

apis.EquationsProblemSpec

alias of EquationSystemSpec

apis.EquationsSpecError

alias of SpecError

apis.VariableSpec

alias of VarSpec

design

class design.AttrDict[source]

Bases: dict

Dictionary that also supports attribute access.

This is useful because some application code uses getattr(spec, ...) while backend code often expects mapping-like payloads.

design.register(problem_type)[source]
Parameters:

problem_type (str)

class design.EqVar(name, kind, value, guess=None, lower=None, upper=None, units=None, desc=None)[source]

Bases: object

Legacy equation-variable container kept for backward compatibility.

Parameters:
  • name (str)

  • kind (str)

  • value (float | None)

  • guess (float | None)

  • lower (float | None)

  • upper (float | None)

  • units (str | None)

  • desc (str | None)

name: str
kind: str
value: float | None
guess: float | None = None
lower: float | None = None
upper: float | None = None
units: str | None = None
desc: str | None = None
class design.EquationsSolveSpec(equations, variables, params=<factory>, backend='auto', method='hybr', tol=1e-09, max_iter=200, max_restarts=2, meta=<factory>)[source]

Bases: object

Legacy equation-solve container kept for backward compatibility.

Parameters:
  • equations (List[str])

  • variables (List[EqVar])

  • params (Dict[str, Any])

  • backend (str)

  • method (str)

  • tol (float)

  • max_iter (int)

  • max_restarts (int)

  • meta (Dict[str, Any])

equations: List[str]
variables: List[EqVar]
params: Dict[str, Any]
backend: str = 'auto'
method: str = 'hybr'
tol: float = 1e-09
max_iter: int = 200
max_restarts: int = 2
meta: Dict[str, Any]
design.build_nozzle_ideal(data, base_dir)[source]

Build the ideal-gas nozzle profile specification.

Parameters:
  • data (Mapping[str, Any])

  • base_dir (Path)

Return type:

NozzleProfileSpec

design.build_thermo_props(data, base_dir)[source]

Build a normalized thermodynamic-property evaluation spec.

Accepted input forms include a single state with state or given, a batch list under states, and a legacy given plus ask structure. The normalized output has backend, fluid, states, and meta.

Parameters:
  • data (Mapping[str, Any])

  • base_dir (Path)

Return type:

Mapping[str, Any]

design.build_equations(data, base_dir)[source]

Build a stable equation-system mapping.

The returned mapping is compatible with equations.spec.system_from_mapping. It accepts the established CLI/app shape with solver options, params or constants, a variables mapping or list, and equations supplied inline or through equations_file.

The builder intentionally does not add a top-level solve key. Nested solve information, when present, is copied into meta for user-interface and debugging purposes.

Parameters:
  • data (Mapping[str, Any])

  • base_dir (Path)

Return type:

Mapping[str, Any]

design.build_optimize(data, base_dir)[source]

Build an optimization specification mapping.

The optimization builder accepts objective and sense fields, inline or file-based constraints, optional design-variable declarations, and the same equation-style variables/constants fields used by build_equations.

The returned mapping is routed by the equations facade to the optimizer backend when problem_type is "optimize" or when objective and constraint keys are present.

Parameters:
  • data (Mapping[str, Any])

  • base_dir (Path)

Return type:

Mapping[str, Any]

design.build_problem(mapping, in_path)[source]

Normalize an input mapping into a ProblemSpec.

The input mapping must include problem_type. All remaining keys are copied into ProblemSpec.data.

Parameters:
  • mapping (Mapping[str, Any])

  • in_path (Path)

Return type:

ProblemSpec

design.build_spec(problem, base_dir)[source]

Build the solver-specific specification for a ProblemSpec.

Parameters:
Return type:

Any

core

core.area_mach(M, k)[source]

Return A/A* as a function of Mach number for a perfect gas.

Parameters:
  • M (float)

  • k (float)

Return type:

float

core.mach_from_area_ratio(r, k, branch)[source]

Invert area-Mach relation for A/A* = r.

Parameters:
  • r (float)

  • k (float)

  • branch (Literal['sub', 'sup'])

Return type:

float

core.static_from_stag(T0, P0, M, k, R)[source]
Parameters:
  • T0 (float)

  • P0 (float)

  • M (float)

  • k (float)

  • R (float)

Return type:

Dict[str, float]

core.choked_mass_flow(Astar, T0, P0, k, R)[source]
Parameters:
  • Astar (float)

  • T0 (float)

  • P0 (float)

  • k (float)

  • R (float)

Return type:

float

class core.NozzleProfileSpec(k: 'float', R: 'float', T0_K: 'float', P0_Pa: 'float', x_mm: 'List[float]', D_mm: 'List[float]', branch_after_throat: 'Branch' = 'sup')[source]

Bases: object

Parameters:
  • k (float)

  • R (float)

  • T0_K (float)

  • P0_Pa (float)

  • x_mm (List[float])

  • D_mm (List[float])

  • branch_after_throat (Literal['sub', 'sup'])

k: float
R: float
T0_K: float
P0_Pa: float
x_mm: List[float]
D_mm: List[float]
branch_after_throat: Literal['sub', 'sup'] = 'sup'
class core.Solver[source]

Bases: object

name: str = 'solver-base'
solve(spec)[source]
Parameters:

spec (Any)

Return type:

Dict[str, Any]

class core.NozzleIdealGasSolver[source]

Bases: Solver

name: str = 'nozzle-ideal-gas'
solve(spec)[source]
Parameters:

spec (NozzleProfileSpec)

Return type:

Dict[str, Any]

in_out

in_out.package_dir()[source]

Return the directory containing this module.

Return type:

Path

in_out.in_dir()[source]

Return the default input directory.

Return type:

Path

in_out.out_dir()[source]

Return the default output directory.

Return type:

Path

in_out.load_text_kv(path)[source]

Parse an EES-style key-value text file.

Supported line forms include key = value and key: value. Blank lines and comment-only lines are skipped.

Values are coerced on a best-effort basis into booleans, None, integers, floats, JSON objects or arrays, comma-separated lists, or raw strings.

Examples

The following input lines are accepted:

key = value
key2: value2
list = 1, 2, 3
Parameters:

path (str | Path)

Return type:

Dict[str, Any]

in_out.load_problem(path)[source]

Load a problem mapping from JSON, YAML, or TXT.

The returned object is always a plain dictionary suitable for build_problem or build_spec. JSON and YAML roots must be mappings. TXT files are parsed with load_text_kv.

Parameters:

path (str | Path)

Return type:

Dict[str, Any]

in_out.save_json(data, path)[source]

Save a mapping as formatted JSON and return the output path.

Parameters:
  • data (Mapping[str, Any])

  • path (str | Path)

Return type:

Path

in_out.save_yaml(data, path)[source]

Save a mapping as YAML and return the output path.

PyYAML must be installed to use this helper.

Parameters:
  • data (Mapping[str, Any])

  • path (str | Path)

Return type:

Path

in_out.load_geometry_csv(path)[source]

Return x_mm and D_mm arrays from a geometry CSV file.

The CSV file must include headers named x_mm and D_mm. The function name is kept for backward compatibility with the existing nozzle solver.

Parameters:

path (str | Path)

Return type:

Tuple[List[float], List[float]]

in_out.save_table_csv(path, rows, *, fieldnames=None)[source]

Save a sequence of row mappings to a CSV file.

If fieldnames is not provided, the column names are inferred from the first row. Values are written through csv.DictWriter.

Parameters:
  • path (str | Path)

  • rows (Sequence[Mapping[str, Any]])

  • fieldnames (Sequence[str] | None)

Return type:

Path

in_out.save_plotly_html(fig, path)[source]

Save a Plotly figure as HTML and return the string path.

Plotly must be installed and the caller must pass an object that implements write_html.

Parameters:
  • fig (Any)

  • path (str | Path)

Return type:

str

units

exception units.UnitError[source]

Bases: ValueError

Raised when units are unknown or incompatible.

class units.UnitDef(dim, factor, offset=0.0, canonical=None)[source]

Bases: object

Linear mapping to a dimension’s base unit:

base = value * factor + offset

For most units offset = 0. Temperatures are handled via offsets (C, F, R).

Parameters:
  • dim (str)

  • factor (float)

  • offset (float)

  • canonical (str | None)

canonical: str | None = None
offset: float = 0.0
dim: str
factor: float
class units.UnitRegistry[source]

Bases: object

Registry of unit definitions.

Each unit belongs to a dimension group; conversions are only allowed within the same dimension group.

add(unit, dim, factor, offset=0.0, canonical=None)[source]
Parameters:
  • unit (str)

  • dim (str)

  • factor (float)

  • offset (float)

  • canonical (str | None)

Return type:

None

convert(value, from_unit, to_unit)[source]
Parameters:
  • value (float)

  • from_unit (str)

  • to_unit (str)

Return type:

float

dim(unit)[source]
Parameters:

unit (str)

Return type:

str

from_base(base_value, to_unit)[source]
Parameters:
  • base_value (float)

  • to_unit (str)

Return type:

float

get(unit)[source]
Parameters:

unit (str)

Return type:

UnitDef

has(unit)[source]
Parameters:

unit (str)

Return type:

bool

list_units(dim=None)[source]
Parameters:

dim (str | None)

Return type:

Dict[str, UnitDef]

to_base(value, from_unit)[source]
Parameters:
  • value (float)

  • from_unit (str)

Return type:

float

class units.Quantity(value: 'float', unit: 'str', registry: 'UnitRegistry')[source]

Bases: object

Parameters:
as_dict()[source]
Return type:

Dict[str, Any]

base_value()[source]
Return type:

float

property dim: str
to(unit)[source]
Parameters:

unit (str)

Return type:

Quantity

value: float
unit: str
registry: UnitRegistry
units.default_registry()[source]

Create the default registry covering common thermo / fluids units.

Base units by dimension:

temperature -> K pressure -> Pa length -> m area -> m2 volume -> m3 mass -> kg time -> s velocity -> m/s energy -> J power -> W spec_energy -> J/kg spec_entropy -> J/(kg*K) density -> kg/m3 mass_flow -> kg/s volumetric_flow -> m3/s

Return type:

UnitRegistry

units.parse_quantity(text, *, default_unit=None, to_unit=None, registry=<units.core.UnitRegistry object>)[source]

Parse a numeric string with optional unit.

Examples

  • “101.3 kPa”

  • “5bar”

  • “300[K]”

  • “-10 C”

  • “70 kJ/kg”

  • “1.2e5 Pa”

Behavior:
  • If no unit is provided:
    • if default_unit is given: uses it

    • else: returns unit=”” (no unit)

  • If to_unit is provided: converts to that unit (requires a known from-unit).

Parameters:
  • text (str)

  • default_unit (str | None)

  • to_unit (str | None)

  • registry (UnitRegistry)

Return type:

Quantity

units.convert(value, from_unit, to_unit)[source]

Convert a scalar using DEFAULT_REGISTRY.

This is the convenience function most of the rest of TDPy expects.

Parameters:
  • value (float)

  • from_unit (str)

  • to_unit (str)

Return type:

float

units.convert_value(value, from_unit, to_unit, registry)[source]

Convenience wrapper for an explicit registry.

Parameters:
  • value (float)

  • from_unit (str)

  • to_unit (str)

  • registry (UnitRegistry)

Return type:

float

utils

utils.ensure_dir(path)[source]

Ensure a directory exists.

If path looks like a file path (has a suffix), create its parent directory. Otherwise, create the directory itself.

Parameters:

path (str | Path)

Return type:

None

utils.setup_logger(name='tdpy', level=20)[source]

Deterministic logger setup.

  • Avoids duplicate handlers even if called repeatedly

  • Default INFO; can be overridden via env TDPY_LOG_LEVEL (e.g. DEBUG, INFO, WARNING, 10, 20)

Parameters:
  • name (str)

  • level (int)

Return type:

Logger

utils.json_default(obj)[source]

Default handler for json.dumps.

Supports:
  • dataclasses

  • pathlib.Path

  • simple iterables (set/tuple) -> list

Parameters:

obj (Any)

Return type:

Any

utils.json_dumps(data, *, indent=2)[source]

Convenience wrapper for consistent JSON output.

Parameters:
  • data (Any)

  • indent (int)

Return type:

str

utils.timed(fn)[source]

Decorator to time function calls and log elapsed seconds (DEBUG level).

Parameters:

fn (Callable[[...], T])

Return type:

Callable[[…], T]

utils.with_error_context(context)[source]

Decorator factory: wraps exceptions with extra context.

Keeps the original exception as __cause__ so tracebacks stay useful.

Parameters:

context (str)

Return type:

Callable[[Callable[[…], T]], Callable[[…], T]]

utils.env_path(*parts, default=None)[source]

Read env var like TDPY_FOO_BAR for parts (“foo”,”bar”). Returns string or default.

Parameters:
  • parts (str)

  • default (str | None)

Return type:

str | None

utils.deep_update(dst, src)[source]

Recursively merge src into dst (in-place) and return dst. Dicts merge deeply, other types overwrite.

Parameters:
  • dst (MutableMapping[str, Any])

  • src (Mapping[str, Any])

Return type:

MutableMapping[str, Any]

utils.dotted_get(mapping, path, default=None)[source]

Get mapping[“a”][“b”][“c”] using path “a.b.c”.

Parameters:
  • mapping (Mapping[str, Any])

  • path (str)

  • default (Any)

Return type:

Any

utils.dotted_set(mapping, path, value)[source]

Set mapping[“a”][“b”][“c”] = value using path “a.b.c”. Creates intermediate dicts as needed.

Parameters:
  • mapping (MutableMapping[str, Any])

  • path (str)

  • value (Any)

Return type:

None

utils.coerce_scalar(text)[source]

Coerce a string into bool/int/float if it looks like one; otherwise return the original string.

Parameters:

text (str)

Return type:

Any

utils.parse_overrides(pairs)[source]
Parse CLI-style overrides:

[“a.b=3”, “foo=true”, “bar.baz=1e-6”]

Returns a nested dict suitable for deep_update().

Parameters:

pairs (Iterable[str])

Return type:

Dict[str, Any]

utils.require_package(import_name, pip_name=None)[source]

Raise a clear ImportError for optional dependencies.

Parameters:
  • import_name (str)

  • pip_name (str | None)

Return type:

None

utils.now_iso()[source]

UTC-ish timestamp string; good enough for meta fields.

Return type:

str

utils.clamp(x, lo=None, hi=None)[source]
Parameters:
  • x (float)

  • lo (float | None)

  • hi (float | None)

Return type:

float

main

main.main(argv=None)[source]
Parameters:

argv (list[str] | None)

Return type:

int

Equations Package

equations.api

exception equations.api.BackendUnavailableError[source]

Bases: RuntimeError

Raised when a requested backend isn’t installed/available.

equations.api.EquationSystem

alias of EquationSystemSpec

equations.api.Param

alias of ParamSpec

equations.api.Solution

alias of Any

equations.api.Var

alias of VarSpec

equations.api.solve(system, *, backend=None, method=None, tol=None, max_iter=None, max_restarts=None, use_units=None)[source]

Convenience alias that routes equation systems and optimization problems.

Parameters:
  • system (EquationSystemSpec | Mapping[str, Any])

  • backend (Literal['auto', 'gekko', 'scipy'] | None)

  • method (str | None)

  • tol (float | None)

  • max_iter (int | None)

  • max_restarts (int | None)

  • use_units (bool | None)

Return type:

Any

equations.api.solve_optimize(problem, *, backend=None, method=None, tol=None, max_iter=None, max_restarts=None, use_units=None)[source]

Solve an optimization problem produced by interpreter/build_spec.py.

Expected mapping keys (build_spec output):
  • problem_type: “optimize”

  • objective: “<expr>”

  • sense: “min”|”max”

  • constraints: [“<eq/residual>”, …] (residual==0 constraints)

  • variables: […], constants: {…}, solve: {…}

Backend notes:
  • Current optimizer implementation is SciPy-based (scipy.optimize.minimize).

  • GEKKO optimization is not wired here (yet).

Parameters:
  • problem (Mapping[str, Any])

  • backend (Literal['auto', 'gekko', 'scipy'] | None)

  • method (str | None)

  • tol (float | None)

  • max_iter (int | None)

  • max_restarts (int | None)

  • use_units (bool | None)

Return type:

Any

equations.api.solve_system(system, *, backend=None, method=None, tol=None, max_iter=None, max_restarts=None, use_units=None)[source]

Solve an EES-ish nonlinear equation system.

Accepts:
  • EquationSystemSpec, OR

  • a JSON/YAML mapping compatible with spec.system_from_mapping()

Override semantics:
  • If an API kwarg is None, we fall back to spec.solve / spec fields / defaults.

  • If provided, the API kwarg overrides spec/solve-block.

Parameters:
  • system (EquationSystemSpec | Mapping[str, Any])

  • backend (Literal['auto', 'gekko', 'scipy'] | None)

  • method (str | None)

  • tol (float | None)

  • max_iter (int | None)

  • max_restarts (int | None)

  • use_units (bool | None)

Return type:

Any

equations.solver

class equations.solver.SolveResult(ok: 'bool', backend: 'str', method: 'str', message: 'str', nfev: 'int', variables: 'Dict[str, Any]', residuals: 'List[float]', residual_norm: 'float', meta: 'Dict[str, Any]')[source]

Bases: object

Parameters:
  • ok (bool)

  • backend (str)

  • method (str)

  • message (str)

  • nfev (int)

  • variables (Dict[str, Any])

  • residuals (List[float])

  • residual_norm (float)

  • meta (Dict[str, Any])

ok: bool
backend: str
method: str
message: str
nfev: int
variables: Dict[str, Any]
residuals: List[float]
residual_norm: float
meta: Dict[str, Any]
equations.solver.solve_system(spec, *, backend='auto', method='hybr', tol=1e-09, max_iter=200, max_restarts=2)[source]

Solve a nonlinear equation system.

Notes: - Enforces EES-style “square system”: n_equations == n_unknowns. - Uses safe_eval for equation parsing and evaluation.

Parameters:
  • spec (Any)

  • backend (str)

  • method (str)

  • tol (float)

  • max_iter (int)

  • max_restarts (int)

Return type:

SolveResult

equations.optimizer

equations.optimizer.solve_optimize(problem, *, backend=None, method=None, tol=None, max_iter=None)[source]

Solve an optimization problem.

Parameters are passed through by equations/api.py, but this function also reads defaults from the problem mapping itself.

Expected keys in problem (duck-typed; see equations/api.py solve_optimize):
  • objective: str

  • sense: “min” | “max”

  • constraints: list[str] # treated as equality residuals == 0

  • variables: list[var-like] # each has name/kind/value/guess/lower/upper

  • params: dict[str, Any] # numeric constants, symbols, and property callables

  • tol, max_iter, method (optional)

Returns:

SolveResult (same shape as equations/solver.py).

Parameters:
  • problem (Mapping[str, Any])

  • backend (str | None)

  • method (str | None)

  • tol (float | None)

  • max_iter (int | None)

Return type:

SolveResult

equations.safe_eval

class equations.safe_eval.CompiledExpr(raw, residual, code, names)[source]

Bases: object

Compiled expression metadata and code object.

Parameters:
  • raw (str) – Original user expression string. This may include an equals sign when compiled through compile_residual.

  • residual (str) – Normalized residual expression string. For plain expressions, this is the expression itself.

  • code (Any) – Compiled Python code object ready for restricted evaluation.

  • names (List[str]) – Referenced identifiers after excluding safe functions, safe constants, and injected extras.

raw: str
residual: str
code: Any
names: List[str]
exception equations.safe_eval.ParseError[source]

Bases: ValueError

Raised when an equation or expression cannot be parsed or evaluated.

exception equations.safe_eval.UnsafeExpressionError[source]

Bases: ValueError

Raised when an expression contains unsupported or unsafe syntax.

equations.safe_eval.compile_expression(expr, *, extra_funcs=None, extra_consts=None)[source]

Compile a plain arithmetic expression without equation normalization.

Parameters:
  • expr (str)

  • extra_funcs (Mapping[str, Callable[[...], Any]] | None)

  • extra_consts (Mapping[str, Any] | None)

Return type:

CompiledExpr

equations.safe_eval.compile_residual(eq, *, extra_funcs=None, extra_consts=None)[source]

Compile an equation into a residual expression.

If eq has no equals sign, it is treated as an existing residual expression.

Parameters:
  • eq (str)

  • extra_funcs (Mapping[str, Callable[[...], Any]] | None)

  • extra_consts (Mapping[str, Any] | None)

Return type:

CompiledExpr

equations.safe_eval.eval_compiled(c, *, values=None, params=None, extra_funcs=None, extra_consts=None)[source]

Evaluate a compiled expression safely and coerce the result to float.

Parameters:
  • c (CompiledExpr)

  • values (Mapping[str, Any] | None)

  • params (Mapping[str, Any] | None)

  • extra_funcs (Mapping[str, Callable[[...], Any]] | None)

  • extra_consts (Mapping[str, Any] | None)

Return type:

float

equations.safe_eval.eval_expression(expr, *, values=None, params=None, extra_funcs=None, extra_consts=None)[source]

Compile and evaluate a plain expression.

Parameters:
  • expr (str)

  • values (Mapping[str, Any] | None)

  • params (Mapping[str, Any] | None)

  • extra_funcs (Mapping[str, Callable[[...], Any]] | None)

  • extra_consts (Mapping[str, Any] | None)

Return type:

float

equations.safe_eval.is_identifier(name)[source]

Return whether name is a simple Python-style identifier.

The accepted pattern is an ASCII-style identifier beginning with a letter or underscore and followed by letters, digits, or underscores.

Parameters:

name (str)

Return type:

bool

equations.safe_eval.normalize_equation_to_residual(eq)[source]

Convert an equation into a residual expression.

Examples

"P2 = P1 + dp" becomes "(P2) - (P1 + dp)".

"a == b" becomes "(a) - (b)".

"f(x)" is returned as "f(x)" and interpreted as an existing residual expression.

Parameters:

eq (str)

Return type:

str

equations.safe_eval.preprocess_expr(s)[source]

Apply minimal EES-style preprocessing to an expression.

The preprocessing performs these transformations:

  • ^ becomes **.

  • Unicode minus becomes -.

  • Unicode multiplication symbols become *.

  • Unicode division becomes /.

  • Leading and trailing whitespace are stripped.

Parameters:

s (str)

Return type:

str

equations.safe_eval.split_assignment(eq)[source]

Detect a simple assignment expression.

The accepted shape is lhs = rhs where lhs is a plain identifier. If the expression is not a simple assignment, (None, None) is returned.

Parameters:

eq (str)

Return type:

Tuple[str | None, str | None]

equations.spec

exception equations.spec.SpecError[source]

Bases: ValueError

Raised when an equation system spec is malformed.

class equations.spec.VarSpec(name, value=None, guess=None, unit=None, desc=None, lower=None, upper=None, fixed=False, label=None)[source]

Bases: object

Variable specification.

Unknown vs fixed:
  • fixed=True -> known constant inside solve; requires value (guess ignored)

  • fixed=False -> unknown; requires guess (or value-as-guess)

Units:
  • unit is a display hint and also used to interpret numeric guess/bounds.

  • guess/value may be a quantity string (“300 K”) regardless of unit hint.

Parameters:
  • name (str)

  • value (float | None)

  • guess (float | None)

  • unit (str | None)

  • desc (str | None)

  • lower (float | None)

  • upper (float | None)

  • fixed (bool)

  • label (str | None)

name: str
value: float | None = None
guess: float | None = None
unit: str | None = None
desc: str | None = None
lower: float | None = None
upper: float | None = None
fixed: bool = False
label: str | None = None
property unknown: bool
property kind: str
bounds()[source]
Return type:

Tuple[float | None, float | None]

guess_value(default=1.0)[source]

Preference: guess -> value -> default.

Parameters:

default (float)

Return type:

float

class equations.spec.ParamSpec(name, value, unit=None, desc=None, label=None)[source]

Bases: object

Parameter (constant) specification. Value may be float OR non-float (e.g., fluid string).

Parameters:
  • name (str)

  • value (Any)

  • unit (str | None)

  • desc (str | None)

  • label (str | None)

name: str
value: Any
unit: str | None = None
desc: str | None = None
label: str | None = None
class equations.spec.EquationSpec(kind='expr', expr=None, fn=None, args=<factory>, label=None)[source]

Bases: object

Equation specification.

kind=”expr”:
  • expr: expression string representing a constraint (residual == 0)

kind=”residual”:
  • fn: name of a built-in residual provider (string key)

  • args: JSON-friendly kwargs payload for that residual provider

Parameters:
  • kind (Literal['expr', 'residual'])

  • expr (str | None)

  • fn (str | None)

  • args (Dict[str, Any])

  • label (str | None)

kind: Literal['expr', 'residual'] = 'expr'
expr: str | None = None
fn: str | None = None
args: Dict[str, Any]
label: str | None = None
class equations.spec.EquationSystemSpec(vars, equations, params=<factory>, meta=<factory>, backend='auto', method='hybr', tol=1e-09, max_iter=200, max_restarts=2, use_units=False, solve=<factory>)[source]

Bases: object

A full system definition: variables + parameters + equations.

Optional solver configuration:
  • top-level hints: backend/method/tol/max_iter/max_restarts/use_units

  • ALSO stores raw solve block (solve: {…}) if provided by input JSON

Backends are free to ignore hints. The solver layer decides behavior.

Parameters:
  • vars (Dict[str, VarSpec])

  • equations (List[EquationSpec])

  • params (Dict[str, ParamSpec])

  • meta (Dict[str, Any])

  • backend (str)

  • method (str)

  • tol (float)

  • max_iter (int)

  • max_restarts (int)

  • use_units (bool)

  • solve (Dict[str, Any])

vars: Dict[str, VarSpec]
equations: List[EquationSpec]
params: Dict[str, ParamSpec]
meta: Dict[str, Any]
backend: str = 'auto'
method: str = 'hybr'
tol: float = 1e-09
max_iter: int = 200
max_restarts: int = 2
use_units: bool = False
solve: Dict[str, Any]
property variables: List[VarSpec]
params_for_eval()[source]
Return type:

Dict[str, Any]

n_equations()[source]
Return type:

int

unknown_names()[source]
Return type:

List[str]

n_unknowns()[source]
Return type:

int

validate()[source]
Return type:

None

check_square()[source]

EES-style determinism: number of equations equals number of unknowns.

Return type:

None

equations.spec.system_from_mapping(m)[source]

Construct an EquationSystemSpec from a JSON/YAML mapping.

Robustness upgrades: - accepts variables as mapping OR list[{name,…}] - accepts equations as list OR single string - merges params + constants (constants wins) - tolerates shorthand scalar variable entries: {“x”: 1.0} - supports solve-block overrides under “solve”: {…} - validates problem_type if present

Parameters:

m (Mapping[str, Any])

Return type:

EquationSystemSpec

Interpreter Package

interpreter.cli

interpreter.cli.main(argv=None)[source]
Parameters:

argv (list[str] | None)

Return type:

int

interpreter.api

interpreter.api.interpret_text(text, *, cfg=None)[source]

Interpret raw user text into a TDPy-ready JSON spec.

This is the main API for the interpreter package:

text -> parse_text() -> build_from_parsed() -> InterpretResult(spec=JSON-ready dict)

Parameters:
Return type:

InterpretResult

interpreter.api.interpret_file(path, *, cfg=None, encoding='utf-8')[source]

Interpret a .txt file into a TDPy JSON spec.

  • If cfg.title is not provided, defaults to file stem.

  • Preserves cfg values by creating a shallow updated InterpretConfig.

Parameters:
Return type:

InterpretResult

interpreter.api.write_spec_json(res, outfile, *, indent=2, sort_keys=False)[source]

Write only the JSON spec portion of InterpretResult to disk.

This intentionally writes only res.spec and not warnings/errors/meta.

Parameters:
Return type:

None

interpreter.api.write_full_result_json(res, outfile, *, indent=2, sort_keys=False)[source]

Write the full interpreter result to disk (spec + diagnostics).

Useful for debugging interpreter behavior, regression tests, and UI integration.

Parameters:
Return type:

None

interpreter.build_spec

interpreter.build_spec.build_from_parsed(parsed, *, cfg)[source]
Parameters:
Return type:

InterpretResult

interpreter.intent

class interpreter.intent.IntentDraft(title, equations, constants_expr, constants_val, guesses, report, solve_overrides, warnings, reserved_words=<factory>, func_names=<factory>)[source]

Bases: object

Optional richer structure for future one-shot text interpretation.

The current interpreter path uses build_spec.py as the main builder. This dataclass is retained as a stable intermediate shape for future extensions and for callers that may already import it.

Parameters:
  • title (str | None)

  • equations (List[str])

  • constants_expr (Dict[str, str])

  • constants_val (Dict[str, float])

  • guesses (Dict[str, float])

  • report (List[str])

  • solve_overrides (Dict[str, Any])

  • warnings (List[str])

  • reserved_words (Set[str])

  • func_names (Set[str])

title: str | None
equations: List[str]
constants_expr: Dict[str, str]
constants_val: Dict[str, float]
guesses: Dict[str, float]
report: List[str]
solve_overrides: Dict[str, Any]
warnings: List[str]
reserved_words: Set[str]
func_names: Set[str]
interpreter.intent.parse_guess_line(line, *, enable_units=True)[source]

Parse a human-friendly guess line.

Supported forms include "? x = 1.2", "guess: x = 1.2", "init x = 1.2", "x ?= 1.2", and "x = 1.2" when the right-hand side is numeric or a parseable quantity.

Returns:

(name, value) when parsing succeeds; otherwise None.

Return type:

tuple[str, float] | None

Parameters:
  • line (str)

  • enable_units (bool)

interpreter.intent.parse_constant_assignment(line)[source]

Parse a constant assignment and return the name and RHS expression.

Accepted forms include "g = 9.81" and "A := pi*r^2". The right-hand side is returned after solver-safe preprocessing.

The function does not decide whether the right-hand side is numeric or symbolic. That decision is made by the builder layer.

Parameters:

line (str)

Return type:

Tuple[str, str] | None

interpreter.intent.looks_like_equation(line)[source]

Return whether a line should stay in the equation stream.

Empty lines, comment-only lines, report directives, and solve directives return False. Other lines return True.

Optimizer directives such as maximize:, bounds:, and design_vars: are allowed through the equation stream so build_spec.py can peel them off and construct optimization specs.

Parameters:

line (str)

Return type:

bool

interpreter.intent.normalize_equation(line)[source]

Normalize common user syntax for solver consumption.

Parameters:

line (str)

Return type:

str

interpreter.intent.extract_names_fallback(expr)[source]

Extract likely variable names from an expression.

The extractor strips comments and quoted string literals before scanning. It filters built-in constants, reserved directive words, known function names, and dunder-style names.

Parameters:

expr (str)

Return type:

Set[str]

interpreter.intent.resolve_constants(constants_expr, *, enable_units=True)[source]

Resolve numeric constants with a multi-pass strategy.

Resolution order is:

  1. Direct numeric or unit-aware parsing.

  2. Safe numeric evaluation using constants that have already been resolved.

  3. Preservation of unresolved expressions for the caller.

Returns:

Resolved numeric constants, unresolved expression constants, and warning messages.

Return type:

tuple[dict[str, float], dict[str, str], list[str]]

Parameters:
  • constants_expr (Mapping[str, str])

  • enable_units (bool)

interpreter.models

class interpreter.models.InterpretConfig(title=None, backend='auto', method='hybr', tol=1e-06, max_iter=50, max_restarts=2, keep_assignments_as_equations=False, allow_residual_lines=True, infer_report='unknowns', default_guess=1.0, enable_units=True, strict_warnings=False)[source]

Bases: object

Controls interpreter heuristics and the emitted ‘solve’ block defaults.

Notes

  • keep_assignments_as_equations=False means we try to pull trivial constant assignments like “x = 3.0” into constants when RHS is numeric-only.

  • allow_residual_lines=True means a line like “x+y-3” is treated as “x+y-3 = 0” (primarily in equations/default mode).

  • infer_report governs the auto-report selection when the user doesn’t provide an explicit report list.

Parameters:
  • title (str | None)

  • backend (str)

  • method (str)

  • tol (float)

  • max_iter (int)

  • max_restarts (int)

  • keep_assignments_as_equations (bool)

  • allow_residual_lines (bool)

  • infer_report (str)

  • default_guess (float)

  • enable_units (bool)

  • strict_warnings (bool)

title: str | None = None
backend: str = 'auto'
method: str = 'hybr'
tol: float = 1e-06
max_iter: int = 50
max_restarts: int = 2
keep_assignments_as_equations: bool = False
allow_residual_lines: bool = True
infer_report: str = 'unknowns'
default_guess: float = 1.0
enable_units: bool = True
strict_warnings: bool = False
class interpreter.models.InterpretResult(ok, spec, warnings=<factory>, errors=<factory>, meta=<factory>)[source]

Bases: object

Result of interpretation (text -> JSON-ready spec).

  • ok: True when no fatal errors were found

  • spec: JSON-ready dictionary suitable for cli run

  • warnings/errors: human-readable diagnostics

  • meta: stable machine-readable summary (counts, unresolved constants, etc.)

Parameters:
  • ok (bool)

  • spec (Dict[str, Any])

  • warnings (List[str])

  • errors (List[str])

  • meta (Dict[str, Any])

ok: bool
spec: Dict[str, Any]
warnings: List[str]
errors: List[str]
meta: Dict[str, Any]
class interpreter.models.ParsedInput(title=None, equation_lines=<factory>, given_lines=<factory>, guess_lines=<factory>, report_names=<factory>, solve_overrides=<factory>, ignored_lines=<factory>)[source]

Bases: object

Output of the text parser stage.

This intentionally stays close to the user’s raw intent: - equation_lines: raw “equation-ish” lines (including residual lines) - given_lines: raw constant assignments (or candidate givens) - guess_lines: raw guess statements - report_names: raw report variable names extracted by parser - solve_overrides: raw solve overrides extracted by parser - ignored_lines: anything we didn’t classify; kept for diagnostics/telemetry

Parameters:
  • title (str | None)

  • equation_lines (List[str])

  • given_lines (List[str])

  • guess_lines (List[str])

  • report_names (List[str])

  • solve_overrides (Dict[str, Any])

  • ignored_lines (List[str])

title: str | None = None
equation_lines: List[str]
given_lines: List[str]
guess_lines: List[str]
report_names: List[str]
solve_overrides: Dict[str, Any]
ignored_lines: List[str]
add_ignored(line)[source]
Parameters:

line (str)

Return type:

None

interpreter.numeric_eval

interpreter.numeric_eval.default_numeric_funcs()[source]

Return the default numeric-only function allowlist.

The returned functions perform numeric work only. They do not perform file I/O, imports, attribute access, or backend calls.

Return type:

Dict[str, Any]

class interpreter.numeric_eval.NumericEvalContext(expr, where='numeric expression')[source]

Bases: object

Context attached to a numeric evaluation error.

Parameters:
  • expr (str)

  • where (str)

expr: str
where: str = 'numeric expression'
exception interpreter.numeric_eval.NumericEvalError(message, *, ctx=None)[source]

Bases: ValueError

Error raised when a numeric expression cannot be safely evaluated.

Parameters:
interpreter.numeric_eval.safe_eval_numeric(expr, *, names, funcs=None)[source]

Evaluate a numeric expression with an AST whitelist.

Allowed syntax includes numeric literals, resolved names supplied through names, the operators +, -, *, /, **, %, unary signs, parentheses, and calls to whitelisted numeric functions.

Disallowed syntax includes attribute access, indexing, comprehensions, lambdas, assignments, comparisons, boolean operations, conditional expressions, calls to non-whitelisted functions, and starred arguments.

Parameters:
  • expr (str) – Expression text to evaluate.

  • names (Mapping[str, float]) – Mapping of previously resolved numeric constants.

  • funcs (Mapping[str, Any] | None) – Optional extra numeric-safe functions.

Returns:

Evaluated numeric value.

Return type:

float

interpreter.numeric_eval.try_parse_float_or_quantity(s, *, enable_units=True)[source]

Try to parse text as a float or a unit-aware quantity.

The parser first accepts plain finite floats and scientific notation. When enable_units is true, it then tries the optional TDPy units layer.

Returns:

Parsed finite value, or None when the text cannot be interpreted as a numeric value.

Return type:

float | None

Parameters:
  • s (str)

  • enable_units (bool)

interpreter.parse

interpreter.parse.parse_text(text)[source]

Parse human-friendly equation text into ParsedInput.

The parser is designed for clean and chaotic human input.

Key behavior

Directives are recognized anywhere, even inside an equations section. For example, report: P_2, m_p is not treated as an equation.

Optimizer directives such as objective:, minimize:, maximize:, design_vars:, bounds:, and constraints: are intentionally preserved as raw equation lines so build_spec.py can interpret them.

In equations mode, lines such as P_atm = 100000 are inferred as given constants when the right-hand side is numeric-only.

Guess lines can be marked with prefixes such as ?, guess, or init.

returns:

Lightweight parser output that keeps raw lines for downstream interpretation.

rtype:

ParsedInput

Parameters:

text (str)

Return type:

ParsedInput

Thermo Props Package

thermo_props.api

thermo_props.api.state(*, fluid=None, outputs=('T', 'P', 'Q', 'Hmass', 'Smass', 'Umass', 'Dmass', 'Cpmass', 'Cvmass', 'A', 'V', 'L', 'Prandtl'), include_phase=True, **spec)[source]

Build a thermodynamic state from two independent properties.

Parameters:
  • fluid (str | None) – Fluid identifier. This may also be supplied in spec.

  • outputs (Sequence[str]) – Requested output property keys.

  • include_phase (bool) – Whether to request a phase string when supported by the backend.

  • **spec (Any) – State-definition keys. The mapping must contain exactly two independent thermodynamic inputs after metadata keys are ignored.

Return type:

ThermoState

Examples

state(fluid="R134a", T_C=-10, x=1.0)

state(fluid="HEOS::Air", T=300.0, P_bar=1.01325)

Notes

Accepted input keys include EES-style names such as T, P, h, s, u, rho, v, x, and Q, plus unit-suffixed keys such as T_C, P_bar, h_kJkg, s_kJkgK, rho_kgm3, and v_m3kg.

thermo_props.api.props(*, fluid=None, outputs=('T', 'P', 'Q', 'Hmass', 'Smass', 'Umass', 'Dmass', 'Cpmass', 'Cvmass', 'A', 'V', 'L', 'Prandtl'), include_phase=True, **spec)[source]

Return a property dictionary in SI units for a thermodynamic state.

Parameters:
  • fluid (str | None)

  • outputs (Sequence[str])

  • include_phase (bool)

  • spec (Any)

Return type:

dict[str, float]

thermo_props.api.prop(out, *, fluid=None, include_phase=False, **spec)[source]

Return one property in SI units for a thermodynamic state.

Parameters:
  • out (str) – Requested output property key.

  • fluid (str | None) – Fluid identifier. This may also be supplied in spec.

  • include_phase (bool) – Whether to include phase evaluation while constructing the state.

  • **spec (Any) – State-definition keys.

Return type:

float

Examples

prop("P", fluid="R134a", T_C=35, x=0.0)

prop("Hmass", fluid="HEOS::Air", T=300, P=101325)

thermo_props.api.run(spec)[source]

Evaluate one or more thermodynamic-property states.

This is the app-oriented entry point used by problem_type = "thermo_props" inputs.

Preferred input shape

The current design layer emits a mapping with these keys:

  • backend: backend label, typically "coolprop".

  • fluid: root-level fluid identifier.

  • states: list of state mappings.

  • meta: optional metadata mapping.

Each state may use given for state inputs and ask for requested output keys.

Backward-compatible shapes

The function also accepts older shapes:

  • {"fluid": "...", "state": {...}, "outputs": [...]}

  • {"fluid": "...", "states": [...], "outputs": [...]}

  • {"fluid": "...", "given": {...}, "ask": [...]}

  • {"fluid": "...", "T": ..., "P": ..., "outputs": [...]}

returns:

JSON-serializable result payload.

rtype:

dict[str, Any]

Parameters:

spec (Any)

Return type:

dict[str, Any]

thermo_props.api.eval_states(spec)

Evaluate one or more thermodynamic-property states.

This is the app-oriented entry point used by problem_type = "thermo_props" inputs.

Preferred input shape

The current design layer emits a mapping with these keys:

  • backend: backend label, typically "coolprop".

  • fluid: root-level fluid identifier.

  • states: list of state mappings.

  • meta: optional metadata mapping.

Each state may use given for state inputs and ask for requested output keys.

Backward-compatible shapes

The function also accepts older shapes:

  • {"fluid": "...", "state": {...}, "outputs": [...]}

  • {"fluid": "...", "states": [...], "outputs": [...]}

  • {"fluid": "...", "given": {...}, "ask": [...]}

  • {"fluid": "...", "T": ..., "P": ..., "outputs": [...]}

returns:

JSON-serializable result payload.

rtype:

dict[str, Any]

Parameters:

spec (Any)

Return type:

dict[str, Any]

thermo_props.api.state_to_dict(st)[source]

Return a JSON-friendly representation of a ThermoState.

Values are in SI units using CoolProp-native keys, except derived outputs such as v in cubic meters per kilogram.

Parameters:

st (ThermoState)

Return type:

dict[str, Any]

thermo_props.api.saturation_curve_Ts(fluid, *, n=200, T_min_K=None, T_max_K=None)[source]

Return saturation-dome curves for a pure fluid in T-s space.

Output keys are T_K, sL_JkgK for saturated liquid entropy, and sV_JkgK for saturated vapor entropy.

The helper uses CoolProp saturation evaluation through (T, Q) calls. Fluids without a saturation curve, or mixtures that do not support this evaluation path, may raise CoolPropCallError.

Parameters:
  • fluid (str)

  • n (int)

  • T_min_K (float | None)

  • T_max_K (float | None)

Return type:

dict[str, list[float]]

thermo_props.api.isobars_Ts(fluid, pressures_Pa, *, nT=80, T_min_K=None, T_max_K=None)[source]

Generate T-s isobars for Plotly-style overlays.

Parameters:
  • fluid (str) – Fluid identifier.

  • pressures_Pa (Sequence[float]) – Iterable of pressure values in pascals.

  • nT (int) – Number of temperature samples per isobar.

  • T_min_K (float | None) – Optional lower temperature bound in kelvin.

  • T_max_K (float | None) – Optional upper temperature bound in kelvin.

Returns:

Trace-like dictionaries with keys P_Pa, T_K, and s_JkgK.

Return type:

list[dict[str, Any]]

thermo_props.core

class thermo_props.core.Props(default_outputs=('T', 'P', 'Q', 'Hmass', 'Smass', 'Umass', 'Dmass', 'Cpmass', 'Cvmass', 'A', 'V', 'L', 'Prandtl'), *, include_phase=True)[source]

Bases: object

Convenience thermo property service (CoolProp-backed).

This class delegates “state building” to state.py to avoid duplicating normalization/unit-conversion logic.

Typical use:

props = Props() st = props.state(“R134a”, {“T_C”: -10, “x”: 1.0}) print(st.h) # J/kg print(st.props[“Hmass”]) # same print(props.get(“cp”, “R134a”, {“T_C”: -10, “x”: 1.0}))

Notes: - inputs must specify exactly TWO independent thermodynamic_properties (state.py enforces this). - Larger sets of equations belong in equations.

Parameters:
  • default_outputs (Sequence[str])

  • include_phase (bool)

state(fluid, inputs, *, outputs=None, include_phase=None)[source]

Build a ThermoState from a mapping containing exactly two independent inputs.

inputs may contain unit-suffixed keys such as:
  • T_C, T_K

  • P_bar, P_kPa, P_MPa, P_atm

  • h_kJkg, s_kJkgK, u_kJkg

  • rho_kgm3, v_m3kg

  • x or Q (quality)

Parameters:
  • fluid (str)

  • inputs (Mapping[str, Any])

  • outputs (Sequence[str] | None)

  • include_phase (bool | None)

Return type:

ThermoState

state_from_pair(fluid, in1, v1, in2, v2, *, outputs=None, include_phase=None)[source]

Build a ThermoState from two CoolProp-native inputs (already SI).

Example

props.state_from_pair(“R134a”, “T”, 263.15, “Q”, 1.0)

Parameters:
  • fluid (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • outputs (Sequence[str] | None)

  • include_phase (bool | None)

Return type:

ThermoState

get(out_key, fluid, inputs, *, default=None)[source]

Get one property from a two-input mapping.

out_key can be:
  • EES-ish: h, s, u, rho, v, cp, cv, a, mu, k, Pr, x

  • or stored key: Hmass, Smass, Umass, Dmass, Cpmass, Cvmass, A, V, L, Prandtl, T, P, Q

Parameters:
  • out_key (str)

  • fluid (str)

  • inputs (Mapping[str, Any])

  • default (float | None)

Return type:

float | None

get_many(out_keys, fluid, inputs, *, default=None)[source]

Get multiple thermodynamic_properties from a two-input mapping. Returns dict keyed by the ORIGINAL requested keys.

Parameters:
  • out_keys (Iterable[str])

  • fluid (str)

  • inputs (Mapping[str, Any])

  • default (float | None)

Return type:

Dict[str, float | None]

get_si_from_pair(out, fluid, in1, v1, in2, v2)[source]

Fast path: one property from two SI inputs using CoolProp-native tokens.

Example

props.get_si_from_pair(“Hmass”, “R134a”, “T”, 263.15, “Q”, 1.0)

Parameters:
  • out (str)

  • fluid (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

float

thermo_props.core.State

alias of ThermoState

class thermo_props.core.ThermoState(fluid, in1, v1, in2, v2, props, phase=None)[source]

Bases: object

A thermodynamic state evaluated by CoolProp.

props contains CoolProp-native keys in SI units, plus derived:
  • “v” : specific volume (m^3/kg)

  • “gamma” : Cp/Cv (if available)

  • “R_eff” : Cp - Cv (diagnostic; not constant for real fluids)

Parameters:
  • fluid (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • props (dict[str, float])

  • phase (str | None)

property P: float
property T: float
get(key, default=None)[source]
Parameters:
  • key (str)

  • default (float | None)

Return type:

float | None

property h: float
phase: str | None = None
property rho: float
property s: float
property v: float
fluid: str
in1: str
v1: float
in2: str
v2: float
props: dict[str, float]
exception thermo_props.core.CoolPropCallError[source]

Bases: RuntimeError

Raised when a CoolProp (or compatible shim) call fails; message includes full call context.

exception thermo_props.core.CoolPropNotInstalled[source]

Bases: ImportError

Raised when CoolProp cannot be imported.

thermo_props.core.coolprop_available()[source]

Return True if PropsSI/PhaseSI are importable.

Return type:

bool

thermo_props.state

class thermo_props.state.ThermoState(fluid, in1, v1, in2, v2, props, phase=None)[source]

Bases: object

A thermodynamic state evaluated by CoolProp.

props contains CoolProp-native keys in SI units, plus derived:
  • “v” : specific volume (m^3/kg)

  • “gamma” : Cp/Cv (if available)

  • “R_eff” : Cp - Cv (diagnostic; not constant for real fluids)

Parameters:
  • fluid (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • props (dict[str, float])

  • phase (str | None)

fluid: str
in1: str
v1: float
in2: str
v2: float
props: dict[str, float]
phase: str | None = None
get(key, default=None)[source]
Parameters:
  • key (str)

  • default (float | None)

Return type:

float | None

property T: float
property P: float
property h: float
property s: float
property rho: float
property v: float
thermo_props.state.state_from_mapping(mapping, *, fluid=None, outputs=('T', 'P', 'Q', 'Hmass', 'Smass', 'Umass', 'Dmass', 'Cpmass', 'Cvmass', 'A', 'V', 'L', 'Prandtl'), include_phase=True)[source]

Build a state from a mapping that contains exactly two independent thermodynamic_properties.

Accepts keys like:
  • {“T_C”: -10, “x”: 1.0}

  • {“P_bar”: 10, “h_kJkg”: 240}

  • {“T”: 300, “P”: 101325}

  • {“rho_kgm3”: 12.3, “T_K”: 280}

  • {“v_m3kg”: 0.0012, “P_bar”: 10} # specific volume

You may supply fluid= or include “fluid” in the mapping.

Parameters:
  • mapping (Mapping[str, Any])

  • fluid (str | None)

  • outputs (Sequence[str])

  • include_phase (bool)

Return type:

ThermoState

thermo_props.state.state_from_pair(fluid, in1, v1, in2, v2, outputs=('T', 'P', 'Q', 'Hmass', 'Smass', 'Umass', 'Dmass', 'Cpmass', 'Cvmass', 'A', 'V', 'L', 'Prandtl'), include_phase=True)[source]

Build a state from two independent thermodynamic_properties (already in SI units / CoolProp keys).

Example

state_from_pair(“R134a”, “T”, 273.15, “Q”, 1.0) state_from_pair(“HEOS::Air”, “T”, 300.0, “P”, 101325.0)

Parameters:
  • fluid (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • outputs (Sequence[str])

  • include_phase (bool)

Return type:

ThermoState

thermo_props.state.prop_from_state(fluid, out, in1, v1, in2, v2)[source]

Tiny helper for solvers that want one property without building a full ThermoState.

Note: - out may be a CoolProp key (e.g., “Hmass”) or a common alias (“h”,”s”,”rho”,…). - Derived outputs (“v”,”gamma”,”R_eff”) are not supported here; use state_from_pair().

Parameters:
  • fluid (str)

  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

float

thermo_props.coolprop_backend

exception thermo_props.coolprop_backend.CoolPropNotInstalled[source]

Bases: ImportError

Raised when CoolProp cannot be imported.

exception thermo_props.coolprop_backend.CoolPropCallError[source]

Bases: RuntimeError

Raised when a CoolProp (or compatible shim) call fails; message includes full call context.

exception thermo_props.coolprop_backend.CanteraNotInstalled[source]

Bases: ImportError

Raised when Cantera backend cannot be imported.

exception thermo_props.coolprop_backend.CanteraCallError[source]

Bases: RuntimeError

Raised when a Cantera (or compatible shim) call fails; message includes full call context.

thermo_props.coolprop_backend.coolprop_available()[source]

Return True if PropsSI/PhaseSI are importable.

Return type:

bool

thermo_props.coolprop_backend.haprops_available()[source]

Return True if HAPropsSI is importable.

Return type:

bool

thermo_props.coolprop_backend.ha_props_available()[source]

Back-compat alias.

Return type:

bool

thermo_props.coolprop_backend.abstractstate_available()[source]

Return True if CoolProp AbstractState helpers are importable.

Return type:

bool

thermo_props.coolprop_backend.cantera_available()[source]

Return True if tdpy Cantera backend is importable and reports availability.

Return type:

bool

thermo_props.coolprop_backend.coolprop_version()[source]

Return CoolProp version string if available, else None.

Return type:

str | None

thermo_props.coolprop_backend.global_param_string(name)[source]

Wrapper for CoolProp.get_global_param_string.

Parameters:

name (str)

Return type:

str

thermo_props.coolprop_backend.ctprops_si(out, in1, v1, in2, v2, fluid)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.coolprop_backend.ctprops_multi(outputs, in1, v1, in2, v2, fluid)[source]
Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

dict[str, float]

thermo_props.coolprop_backend.batch_ctprops(calls)[source]
Parameters:

calls (Iterable[CTCall])

Return type:

list[float]

thermo_props.coolprop_backend.ctprops_cache_info()[source]
Return type:

dict[str, Any]

thermo_props.coolprop_backend.clear_ctprops_caches()[source]
Return type:

None

thermo_props.coolprop_backend.props_si(out, in1, v1, in2, v2, fluid)[source]

CoolProp PropsSI wrapper with: - alias normalization - strict float conversion - optional NH3H2O native hook (explicit aliases only)

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.coolprop_backend.props_multi(outputs, in1, v1, in2, v2, fluid)[source]
Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

dict[str, float]

thermo_props.coolprop_backend.phase_si(in1, v1, in2, v2, fluid)[source]

CoolProp PhaseSI wrapper with optional NH3H2O hook.

Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

str

thermo_props.coolprop_backend.batch_props(calls)[source]
Parameters:

calls (Iterable[CPCall])

Return type:

list[float]

thermo_props.coolprop_backend.as_props_si(out, in1, v1, in2, v2, fluid)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.coolprop_backend.as_props_multi(outputs, in1, v1, in2, v2, fluid)[source]
Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

dict[str, float]

thermo_props.coolprop_backend.batch_as_props(calls)[source]
Parameters:

calls (Iterable[ASCall])

Return type:

list[float]

thermo_props.coolprop_backend.FugacitySI(in1, v1, in2, v2, fluid, i=0)[source]
Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

  • i (int)

Return type:

float

thermo_props.coolprop_backend.FugacityCoeffSI(in1, v1, in2, v2, fluid, i=0)[source]
Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

  • i (int)

Return type:

float

thermo_props.coolprop_backend.LnFugacityCoeffSI(in1, v1, in2, v2, fluid, i=0)[source]
Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

  • i (int)

Return type:

float

thermo_props.coolprop_backend.ChemicalPotentialSI(in1, v1, in2, v2, fluid, i=0)[source]
Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

  • i (int)

Return type:

float

thermo_props.coolprop_backend.haprops_si(out, in1, v1, in2, v2, in3, v3)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

Return type:

float

thermo_props.coolprop_backend.haprops_multi(outputs, in1, v1, in2, v2, in3, v3)[source]
Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

Return type:

dict[str, float]

thermo_props.coolprop_backend.batch_haprops(calls)[source]
Parameters:

calls (Iterable[HACall])

Return type:

list[float]

thermo_props.coolprop_backend.ha_props_si(out, in1, v1, in2, v2, in3, v3)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

Return type:

float

thermo_props.coolprop_backend.ha_props_multi(outputs, in1, v1, in2, v2, in3, v3)[source]
Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

Return type:

dict[str, float]

thermo_props.coolprop_backend.batch_ha_props(calls)[source]
Parameters:

calls (Iterable[HACall])

Return type:

list[float]

thermo_props.coolprop_backend.PropsSI(out, in1, v1, in2, v2, fluid)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.coolprop_backend.PhaseSI(in1, v1, in2, v2, fluid)[source]
Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

str

thermo_props.coolprop_backend.HAPropsSI(out, in1, v1, in2, v2, in3, v3)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

Return type:

float

thermo_props.coolprop_backend.ASPropsSI(out, in1, v1, in2, v2, fluid)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.coolprop_backend.CTPropsSI(out, in1, v1, in2, v2, fluid)[source]
Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

class thermo_props.coolprop_backend.CPCall(out: 'str', in1: 'str', v1: 'float', in2: 'str', v2: 'float', fluid: 'str')[source]

Bases: object

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

out: str
in1: str
v1: float
in2: str
v2: float
fluid: str
class thermo_props.coolprop_backend.HACall(out: 'str', in1: 'str', v1: 'float', in2: 'str', v2: 'float', in3: 'str', v3: 'float')[source]

Bases: object

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

out: str
in1: str
v1: float
in2: str
v2: float
in3: str
v3: float
class thermo_props.coolprop_backend.ASCall(out: 'str', in1: 'str', v1: 'float', in2: 'str', v2: 'float', fluid: 'str')[source]

Bases: object

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

out: str
in1: str
v1: float
in2: str
v2: float
fluid: str
class thermo_props.coolprop_backend.CTCall(out: 'str', in1: 'str', v1: 'float', in2: 'str', v2: 'float', fluid: 'str')[source]

Bases: object

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

out: str
in1: str
v1: float
in2: str
v2: float
fluid: str

thermo_props.cantera_backend

exception thermo_props.cantera_backend.CanteraNotInstalled[source]

Bases: ImportError

Raised when Cantera cannot be imported.

exception thermo_props.cantera_backend.CanteraCallError[source]

Bases: RuntimeError

Raised when a Cantera (CTPropsSI) call fails; message includes call context.

thermo_props.cantera_backend.cantera_available()[source]
Return type:

bool

thermo_props.cantera_backend.cantera_version()[source]
Return type:

str | None

thermo_props.cantera_backend.ctprops_cache_info()[source]

Return cache stats (useful for debugging performance).

Return type:

dict[str, Any]

thermo_props.cantera_backend.clear_ctprops_caches()[source]

Clear all internal LRU caches.

Return type:

None

thermo_props.cantera_backend.ctprops_si(out, in1, v1, in2, v2, fluid)[source]

Cantera-backed property lookup with a CoolProp-like signature (memoized).

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

thermo_props.cantera_backend.ctprops_multi(outputs, in1, v1, in2, v2, fluid)[source]

Compute multiple CT outputs for the same state (state set once).

Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

dict[str, float]

thermo_props.cantera_backend.batch_ctprops(calls)[source]

Execute a batch of CTPropsSI calls (memoized per call).

Parameters:

calls (Iterable[CTCall])

Return type:

list[float]

thermo_props.cantera_backend.CTPropsSI(out, in1, v1, in2, v2, fluid)[source]

Alias shim so input files can call CTPropsSI the same way they call PropsSI.

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

Return type:

float

class thermo_props.cantera_backend.CTCall(out, in1, v1, in2, v2, fluid)[source]

Bases: object

A single Cantera CTPropsSI call signature (same shape as PropsSI).

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • fluid (str)

out: str
in1: str
v1: float
in2: str
v2: float
fluid: str

thermo_props.librh2o_ashrae_backend

exception thermo_props.librh2o_ashrae_backend.LiBrH2OCallError[source]

Bases: RuntimeError

Raised when an ASHRAE LiBr–H2O property call fails; message includes full call context.

exception thermo_props.librh2o_ashrae_backend.LiBrH2ODomainError[source]

Bases: ValueError

Raised when inputs are outside the intended correlation domain.

thermo_props.librh2o_ashrae_backend.h_LiBrH2O(T, x, *, warn_extrapolation=False)[source]

Solution enthalpy h(T,x) [J/kg_solution] using ASHRAE-style polynomial.

Parameters:
  • T (float)

  • x (float)

  • warn_extrapolation (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.P_eq_LiBrH2O(T, x, *, warn_extrapolation=False)[source]

Equilibrium vapor pressure over LiBr solution P_eq(T,x) [Pa].

Parameters:
  • T (float)

  • x (float)

  • warn_extrapolation (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.x_LiBrH2O(T, P, *, x_lo=0.4, x_hi=0.75, tol=1e-10, warn_extrapolation=False)[source]

Solve x such that P_eq(T,x) = P.

Parameters:
  • T (float)

  • P (float)

  • x_lo (float)

  • x_hi (float)

  • tol (float)

  • warn_extrapolation (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.T_from_Px(P, x, *, T_lo=288.15, T_hi=438.15, tol=1e-08, warn_extrapolation=False)[source]

Solve T such that P_eq(T,x)=P.

Parameters:
  • P (float)

  • x (float)

  • T_lo (float)

  • T_hi (float)

  • tol (float)

  • warn_extrapolation (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.T_from_hx(h_target, x, *, T_lo=288.15, T_hi=438.15, tol=1e-08, warn_extrapolation=False)[source]

Solve T such that h(T,x)=h_target.

Parameters:
  • h_target (float)

  • x (float)

  • T_lo (float)

  • T_hi (float)

  • tol (float)

  • warn_extrapolation (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.rho_LiBrH2O(T, x, *, prefer_coolprop=True)[source]

Density ρ(T,x) [kg/m^3].

Parameters:
  • T (float)

  • x (float)

  • prefer_coolprop (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.cp_LiBrH2O(T, x, *, prefer_coolprop=True)[source]

Specific heat cp(T,x) [J/kg/K].

Parameters:
  • T (float)

  • x (float)

  • prefer_coolprop (bool)

Return type:

float

thermo_props.librh2o_ashrae_backend.librh2o_available()[source]

This backend is pure-python; always available.

Return type:

bool

thermo_props.librh2o_ashrae_backend.librh2o_props_si(out, in1, v1, in2, v2)[source]

PropsSI-like wrapper for LiBr–H2O properties.

Supported pairs: - (T, X) -> outputs: P, H, D, C - (T, P) -> output: X - (P, X) -> output: T - (H, X) -> output: T

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

float

thermo_props.librh2o_ashrae_backend.librh2o_props_multi(outputs, in1, v1, in2, v2)[source]

Compute multiple outputs for the same LiBr–H2O state.

Parameters:
  • outputs (Sequence[str])

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

dict[str, float]

thermo_props.librh2o_ashrae_backend.batch_librh2o_props(calls)[source]

Execute a batch of LiBr–H2O PropsSI-like calls.

Parameters:

calls (Iterable[LiBrCall])

Return type:

list[float]

class thermo_props.librh2o_ashrae_backend.LiBrCall(out: 'str', in1: 'str', v1: 'float', in2: 'str', v2: 'float')[source]

Bases: object

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

out: str
in1: str
v1: float
in2: str
v2: float
thermo_props.librh2o_ashrae_backend.x_LiBrH2O_from_TP(T, P, **kwargs)[source]

Back-compat alias for x_LiBrH2O(T, P, …).

Parameters:
  • T (float)

  • P (float)

  • kwargs (float)

Return type:

float

thermo_props.librh2o_ashrae_backend.T_LiBrH2O_from_Px(P, x, **kwargs)[source]

Back-compat alias for T_from_Px(P, x, …).

Parameters:
  • P (float)

  • x (float)

  • kwargs (float)

Return type:

float

thermo_props.librh2o_ashrae_backend.T_LiBrH2O_from_hx(h_target, x, **kwargs)[source]

Back-compat alias for T_from_hx(h_target, x, …).

Parameters:
  • h_target (float)

  • x (float)

  • kwargs (float)

Return type:

float

thermo_props.librh2o_ashrae_backend.LiBrPropsSI(out, in1, v1, in2, v2)[source]

Back-compat CoolProp-style alias.

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

float

thermo_props.librh2o_ashrae_backend.LiBrH2OPropsSI(out, in1, v1, in2, v2)[source]

Back-compat CoolProp-style alias.

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

Return type:

float

thermo_props.nh3h2o_backend

NH3-H2O property backend for TDPy.

This module wraps the native ammonia-water implementation used for Ibrahim and Klein style NH3-H2O property work. It provides TPX state evaluation, scalar property calls, batch helpers, EES-style shims, and CoolProp-style shims.

Inputs are temperature in kelvin, pressure in pascals, NH3 mass fraction, and an optional EES quality flag for supported TXQ calls. Outputs are plain Python floats or dictionaries suitable for JSON serialization.

thermo_props.nh3h2o_backend.supports(fluid)[source]

Return whether a fluid string should dispatch to this backend.

Parameters:

fluid (str)

Return type:

bool

exception thermo_props.nh3h2o_backend.NH3H2ONotInstalled[source]

Bases: ImportError

Raised when the native ammonia-water implementation cannot be imported.

exception thermo_props.nh3h2o_backend.NH3H2OCallError[source]

Bases: RuntimeError

Raised when an NH3-H2O property call fails with context.

thermo_props.nh3h2o_backend.nh3h2o_available()[source]

Return whether ammonia_water.props_tpx is importable.

Return type:

bool

thermo_props.nh3h2o_backend.state_tpx(T_K, P_Pa, X, *, strict=True)[source]

Return the full NH3-H2O state dictionary for T, P, and X.

When strict is true, failures or an ok value of zero raise NH3H2OCallError. When strict is false, the underlying result dictionary is returned for caller-side inspection.

Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

dict[str, Any]

thermo_props.nh3h2o_backend.prop_tpx(out, T_K, P_Pa, X, *, strict=True)[source]

Return one float-valued NH3-H2O property at T, P, and X.

Parameters:
  • out (str)

  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.props_multi_tpx(outputs, T_K, P_Pa, X, *, strict=True)[source]

Return several float-valued NH3-H2O properties for one TPX state.

The returned dictionary keeps the output keys exactly as requested by the caller.

Parameters:
  • outputs (Sequence[str])

  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

dict[str, float]

thermo_props.nh3h2o_backend.phase_tpx(T_K, P_Pa, X, *, strict=True)[source]

Return the phase string reported by the NH3-H2O model.

The value is intended for reporting and diagnostics, not as a scalar equation solver residual.

Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

str

thermo_props.nh3h2o_backend.ok_tpx(T_K, P_Pa, X)[source]

Return a quick success flag using strict=False internally.

Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

Return type:

bool

thermo_props.nh3h2o_backend.batch_prop_tpx(calls)[source]

Execute a batch of NH3-H2O property calls and return floats.

Parameters:

calls (Iterable[NH3H2OCall])

Return type:

list[float]

thermo_props.nh3h2o_backend.batch_state_tpx(states)[source]

Return full state dictionaries for several TPX states.

Each item may be a (T_K, P_Pa, X) tuple or a mapping with equivalent keys.

Parameters:

states (Iterable[tuple[float, float, float] | Mapping[str, Any]])

Return type:

list[dict[str, Any]]

thermo_props.nh3h2o_backend.h_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.s_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.u_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.v_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.rho_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.q_tpx(T_K, P_Pa, X, *, strict=True)[source]
Parameters:
  • T_K (float)

  • P_Pa (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.NH3H2OPropsSI(out, *args, strict=True)[source]

Return one NH3-H2O property using an EES-style scalar signature.

The function accepts key-value input pairs. It supports TPX inputs for the usual state calls and TXQ inputs for EES-style surface-tension calls.

Parameters:
  • out (Any)

  • args (Any)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.nh3h2o_props_si(out, *args, strict=True)

Return one NH3-H2O property using an EES-style scalar signature.

The function accepts key-value input pairs. It supports TPX inputs for the usual state calls and TXQ inputs for EES-style surface-tension calls.

Parameters:
  • out (Any)

  • args (Any)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.NH3H2O(out, in1, v1, in2, v2, in3, v3, *, strict=True)[source]

Return one NH3-H2O property using a CoolProp-like TPX signature.

The three input key-value pairs are order agnostic but must resolve to T, P, and X. TXQ calls are intentionally handled by NH3H2OPropsSI.

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.NH3H2O_STATE(in1, v1, in2, v2, in3, v3, *, strict=True)[source]

Return the full state dictionary using a CoolProp-like TPX signature.

Parameters:
  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

  • strict (bool)

Return type:

dict[str, Any]

thermo_props.nh3h2o_backend.NH3H2O_TPX(out, T, P, X, *, strict=True)[source]

Return one property from direct T, P, and X inputs.

Parameters:
  • out (str)

  • T (float)

  • P (float)

  • X (float)

  • strict (bool)

Return type:

float

thermo_props.nh3h2o_backend.NH3H2O_STATE_TPX(T, P, X, *, strict=True)[source]

Return the full state dictionary from direct T, P, and X inputs.

Parameters:
  • T (float)

  • P (float)

  • X (float)

  • strict (bool)

Return type:

dict[str, Any]

class thermo_props.nh3h2o_backend.NH3H2OCall(out, in1, v1, in2, v2, in3, v3, strict=True)[source]

Bases: object

Container for one NH3-H2O CoolProp-style property call.

The object stores one output key, three input key-value pairs, and a strict error-handling flag. The input keys are expected to resolve to T, P, and X.

Parameters:
  • out (str)

  • in1 (str)

  • v1 (float)

  • in2 (str)

  • v2 (float)

  • in3 (str)

  • v3 (float)

  • strict (bool)

out: str
in1: str
v1: float
in2: str
v2: float
in3: str
v3: float
strict: bool = True

thermo_props.ammonia_water

Ammonia-water property model based on Ibrahim and Klein.

This module implements thermodynamic properties for NH3-H2O mixtures using a reduced Gibbs formulation and an excess Gibbs model.

Primary goals

The implementation provides an EES-like state call through props_tpx and returns enthalpy, entropy, internal energy, specific volume, density, and the EES-style quality flag. It also includes guardrails that avoid non-physical negative or non-finite volume and density values in successful states.

Units

Inputs use kelvin, pascals, and NH3 mass fraction. Internal calculations use reduced temperature and pressure. Outputs use SI units, with convenience kilojoule-per-kilogram fields also included.

VLE approach

The vapor-liquid equilibrium helper uses a Gibbs-consistent K-form based on liquid activity coefficients from the excess Gibbs model. The model skips VLE classification when the vapor equation of state is not applicable and falls back to single-phase liquid behavior to avoid false vapor or two-phase flags.

class thermo_props.ammonia_water.PureCoeffs(A1: 'float', A2: 'float', A3: 'float', A4: 'float', B1: 'float', B2: 'float', B3: 'float', C1: 'float', C2: 'float', C3: 'float', C4: 'float', D1: 'float', D2: 'float', D3: 'float', hr0_L: 'float', hr0_g: 'float', sr0_L: 'float', sr0_g: 'float', Tr0: 'float', Pr0: 'float', M: 'float')[source]

Bases: object

Parameters:
  • A1 (float)

  • A2 (float)

  • A3 (float)

  • A4 (float)

  • B1 (float)

  • B2 (float)

  • B3 (float)

  • C1 (float)

  • C2 (float)

  • C3 (float)

  • C4 (float)

  • D1 (float)

  • D2 (float)

  • D3 (float)

  • hr0_L (float)

  • hr0_g (float)

  • sr0_L (float)

  • sr0_g (float)

  • Tr0 (float)

  • Pr0 (float)

  • M (float)

A1: float
A2: float
A3: float
A4: float
B1: float
B2: float
B3: float
C1: float
C2: float
C3: float
C4: float
D1: float
D2: float
D3: float
hr0_L: float
hr0_g: float
sr0_L: float
sr0_g: float
Tr0: float
Pr0: float
M: float
thermo_props.ammonia_water.x_from_w(w_nh3)[source]

Convert NH3 mass fraction to mole fraction.

Parameters:

w_nh3 (float)

Return type:

float

thermo_props.ammonia_water.w_from_x(x_nh3)[source]

Convert NH3 mole fraction to mass fraction.

Parameters:

x_nh3 (float)

Return type:

float

thermo_props.ammonia_water.M_mix_from_x(x_nh3)[source]

Return mixture molar mass in kilograms per mole from mole fraction.

Parameters:

x_nh3 (float)

Return type:

float

thermo_props.ammonia_water.pure_props(comp, phase, T, P, *, validate_volume=True)[source]

Return pure-component thermodynamic properties at temperature and pressure.

The phase argument must be "L" for liquid or "g" for vapor. The returned dictionary includes molar Gibbs energy, enthalpy, entropy, and volume, plus mass-basis enthalpy, entropy, internal energy, specific volume, and density.

Parameters:
  • comp (Literal['NH3', 'H2O'])

  • phase (Literal['L', 'g'])

  • T (float)

  • P (float)

  • validate_volume (bool)

Return type:

Dict[str, float]

thermo_props.ammonia_water.excess_reduced(x, Tr, Pr)[source]

Return reduced excess Gibbs energy and derivatives.

The returned tuple contains the reduced excess Gibbs energy, its derivative with respect to reduced temperature, and its derivative with respect to reduced pressure.

Parameters:
  • x (float)

  • Tr (float)

  • Pr (float)

Return type:

Tuple[float, float, float]

thermo_props.ammonia_water.excess_props(x, T, P)[source]

Return excess liquid thermodynamic properties.

The calculation uses the reduced excess Gibbs energy and its derivatives to compute molar excess Gibbs energy, enthalpy, entropy, and volume, along with mass-basis diagnostic values.

Parameters:
  • x (float)

  • T (float)

  • P (float)

Return type:

Dict[str, float]

thermo_props.ammonia_water.activity_ln_gamma(x, T, P)[source]

Return activity-coefficient logarithms for the binary mixture.

The values are derived from the excess Gibbs model and returned as ln(gamma_NH3) and ln(gamma_H2O).

Parameters:
  • x (float)

  • T (float)

  • P (float)

Return type:

Tuple[float, float]

thermo_props.ammonia_water.activity_coeffs(x, T, P)[source]

Return activity coefficients from the excess Gibbs model.

Parameters:
  • x (float)

  • T (float)

  • P (float)

Return type:

Tuple[float, float]

thermo_props.ammonia_water.mix_liquid_props(T, P, x_nh3)[source]

Return liquid NH3-H2O solution properties.

The composition argument is the NH3 mole fraction. Returned values include phase, mole and mass composition, mass-basis thermodynamic properties, and kilojoule-per-kilogram convenience fields.

Parameters:
  • T (float)

  • P (float)

  • x_nh3 (float)

Return type:

Dict[str, float]

thermo_props.ammonia_water.mix_vapor_props(T, P, y_nh3)[source]

Return vapor NH3-H2O mixture properties.

The composition argument is the NH3 vapor mole fraction. The mixture treatment uses ideal mixing of the pure-vapor real-gas correlations.

Parameters:
  • T (float)

  • P (float)

  • y_nh3 (float)

Return type:

Dict[str, float]

thermo_props.ammonia_water.props_tpx(T_K, P_Pa, X, strict=True)[source]

Return an EES-like NH3-H2O state for temperature, pressure, and mass fraction.

Parameters:
  • T_K (float) – Temperature in kelvin.

  • P_Pa (float) – Pressure in pascals.

  • X (float) – NH3 mass fraction.

  • strict (bool) – When true, invalid states raise. When false, invalid states return a result payload with ok set to zero and non-finite property fields.

Returns:

State payload containing thermodynamic properties, composition diagnostics, and convenience unit conversions.

Return type:

dict[str, float]

Notes

The quality flag follows the EES convention. The implementation avoids VLE classification when the vapor equation of state is not applicable at the specified state.

GUI Modules

gui_core_dpg

class gui_core_dpg.AppState(repo_root: 'Path', in_root: 'Path', out_root: 'Path', ui_font_default: 'int | None' = None, ui_font_macos: 'int | None' = None, ui_font_labview: 'int | None' = None, mono_font: 'int | None' = None, eqn_loaded_problem: 'Dict[str, Any] | None' = None, eqn_guess_widgets: 'Dict[str, Dict[str, str]] | None' = None, eqn_last_out_file: 'str' = '', props_last_out_file: 'str' = '')[source]

Bases: object

Parameters:
  • repo_root (Path)

  • in_root (Path)

  • out_root (Path)

  • ui_font_default (int | None)

  • ui_font_macos (int | None)

  • ui_font_labview (int | None)

  • mono_font (int | None)

  • eqn_loaded_problem (Dict[str, Any] | None)

  • eqn_guess_widgets (Dict[str, Dict[str, str]] | None)

  • eqn_last_out_file (str)

  • props_last_out_file (str)

repo_root: Path
in_root: Path
out_root: Path
ui_font_default: int | None = None
ui_font_macos: int | None = None
ui_font_labview: int | None = None
mono_font: int | None = None
eqn_loaded_problem: Dict[str, Any] | None = None
eqn_guess_widgets: Dict[str, Dict[str, str]] | None = None
eqn_last_out_file: str = ''
props_last_out_file: str = ''
gui_core_dpg.t(prefix, name)[source]
Parameters:
  • prefix (str)

  • name (str)

Return type:

str

gui_core_dpg.enqueue_task(q, fn)[source]
Parameters:
  • q (SimpleQueue[Callable[[], None]])

  • fn (Callable[[], None])

Return type:

None

gui_core_dpg.drain_tasks(q, *, max_tasks=50)[source]
Parameters:
  • q (SimpleQueue[Callable[[], None]])

  • max_tasks (int)

Return type:

None

class gui_core_dpg.ThemeSpec(label: 'str', key: 'str', theme_id: 'int', font_id: 'int | None')[source]

Bases: object

Parameters:
  • label (str)

  • key (str)

  • theme_id (int)

  • font_id (int | None)

label: str
key: str
theme_id: int
font_id: int | None
gui_core_dpg.main()[source]
Return type:

int

gui_log_dpg

class gui_log_dpg.LogPanel(tag_level: 'str' = '##log_level', tag_box: 'str' = '##log_box', tag_status: 'str' = '##log_status', tag_clear_btn: 'str' = '##log_clear_btn', default_level: 'str' = 'INFO', max_chars: 'int' = 250000)[source]

Bases: object

Parameters:
  • tag_level (str)

  • tag_box (str)

  • tag_status (str)

  • tag_clear_btn (str)

  • default_level (str)

  • max_chars (int)

tag_level: str = '##log_level'
tag_box: str = '##log_box'
tag_status: str = '##log_status'
tag_clear_btn: str = '##log_clear_btn'
default_level: str = 'INFO'
max_chars: int = 250000
build(parent=None, *, height=240, mono_font=None)[source]
Parameters:
  • parent (object | None)

  • height (int)

  • mono_font (int | None)

Return type:

None

clear()[source]
Return type:

None

debug(msg)[source]
Parameters:

msg (str)

Return type:

None

info(msg)[source]
Parameters:

msg (str)

Return type:

None

warn(msg)[source]
Parameters:

msg (str)

Return type:

None

error(msg)[source]
Parameters:

msg (str)

Return type:

None

set_status(msg)[source]
Parameters:

msg (str)

Return type:

None

drain(*, max_lines=200)[source]
Parameters:

max_lines (int)

Return type:

None

gui_utils_dpg

class gui_utils_dpg.CmdResult(returncode, stdout, stderr)[source]

Bases: object

Result returned by the asynchronous command runner.

Parameters:
  • returncode (int)

  • stdout (str)

  • stderr (str)

returncode: int
stdout: str
stderr: str
gui_utils_dpg.ensure_dir(p)[source]

Ensure a directory exists and return the normalized path.

When p looks like a file path because it has a suffix, the parent directory is created. Otherwise, p itself is created.

Parameters:

p (str | Path)

Return type:

Path

gui_utils_dpg.extract_dpg_file_dialog_path(app_data)[source]

Normalize Dear PyGui file-dialog payloads across versions.

Different Dear PyGui versions return selected file paths under slightly different keys. This helper checks the known shapes and returns a string path when one is available.

Parameters:

app_data (Any)

Return type:

str

gui_utils_dpg.find_repo_root(start=None)[source]

Find the TDPy repository root.

The search walks upward from a few likely starting locations and looks for files that strongly indicate the project root: __init__.py, cli.py, and app.py. If discovery is ambiguous, the directory containing this module is returned as the safest fallback.

Parameters:

start (str | Path | None)

Return type:

Path

gui_utils_dpg.in_dir(repo_root)[source]

Return the resolved default input directory for a repository root.

Parameters:

repo_root (Path)

Return type:

Path

gui_utils_dpg.is_inside(child, parent)[source]

Return whether child is located inside parent.

Parameters:
  • child (Path)

  • parent (Path)

Return type:

bool

gui_utils_dpg.last_nonempty_line(text)[source]

Return the last non-empty line in a text block.

Parameters:

text (str)

Return type:

str

gui_utils_dpg.load_json(path)[source]

Load a JSON object from a file.

Parameters:

path (Path)

Return type:

Dict[str, Any]

gui_utils_dpg.load_text(path)[source]

Load text from a file using UTF-8 with replacement for bad bytes.

Parameters:

path (Path)

Return type:

str

gui_utils_dpg.open_path(path)[source]

Open a file or folder with the operating-system default handler.

Parameters:

path (str | PathLike[str] | Path)

Return type:

bool

gui_utils_dpg.out_dir(repo_root)[source]

Return the resolved default output directory for a repository root.

Parameters:

repo_root (Path)

Return type:

Path

gui_utils_dpg.preview_cmd(cmd, *, prefix='runroot')[source]

Build a compact command preview string for the GUI.

Parameters:
  • cmd (Sequence[str])

  • prefix (str)

Return type:

str

gui_utils_dpg.rel_to_in(path, repo_root)[source]

Return a CLI-friendly path relative to in when possible.

Parameters:
  • path (Path)

  • repo_root (Path)

Return type:

str

gui_utils_dpg.resolve_input_pattern(path, *, prefer_exts=('.txt', '.json'))[source]

Resolve a GUI input path or glob pattern to a concrete file.

Supported examples include absolute files, wildcard paths, and bare stems. For wildcard matches, preferred extensions are selected first.

Examples

The following inputs are supported:

/path/to/foo.*
/path/to/*.txt
/path/to/foo
Parameters:
  • path (str | Path)

  • prefer_exts (Tuple[str, ...])

Return type:

Path | None

gui_utils_dpg.run_cmd_async(cmd, *, cwd=None, env=None, timeout=None, on_line=None, on_done=None)[source]

Run a command in a background thread.

Parameters:
  • cmd (Sequence[str]) – Command and arguments.

  • cwd (Path | None) – Optional working directory.

  • env (Mapping[str, str] | None) – Optional environment mapping.

  • timeout (float | None) – Optional timeout in seconds.

  • on_line (Callable[[str], None] | None) – Callback invoked for each captured stdout or stderr line. Stderr lines are prefixed with "STDERR: ".

  • on_done (Callable[[CmdResult], None] | None) – Callback invoked once with CmdResult.

Returns:

The started daemon thread.

Return type:

threading.Thread

gui_utils_dpg.save_json(path, payload, *, indent=2)[source]

Save a mapping as formatted JSON.

Parameters:
  • path (Path)

  • payload (Mapping[str, Any])

  • indent (int)

Return type:

None

gui_utils_dpg.save_text(path, text)[source]

Save text to a file using UTF-8 and create parent directories.

Parameters:
  • path (Path)

  • text (str)

Return type:

None

gui_utils_dpg.unique_path(base)[source]

Generate a non-existing path by appending a numeric suffix.

The suffix is inserted before the file extension. For example, result.json may become result_1.json.

Parameters:

base (Path)

Return type:

Path