Input Formats and Validation
Purpose
Use this guide to choose the right input shape and understand where validation fits before targeting begins.
Prerequisites
Start with First Solve with Python if you have not run a packaged sample
case yet. Transport schemas are available from OpenPinch.contracts.input
when an integration needs explicit model validation.
Sample Case
Use basic_pinch.json for first validation checks and
crude_preheat_train_multiperiod.json when you need named operating
periods.
Runnable Workflow
Wrapper-based validation:
from OpenPinch import PinchProblem
problem = PinchProblem("basic_pinch.json")
validation = problem.validation_report()
input_data = problem.validate()
Schema-first validation:
from OpenPinch.contracts.input import TargetInput
source_data = {"streams": [...], "utilities": [...]}
input_data = TargetInput.model_validate(source_data)
Expected Output
Validation returns typed input data or a structured validation report before
the runtime Zone hierarchy is prepared. Input data can be structurally
valid and still produce warnings about unusual thermal assumptions.
Supported Source Shapes
PinchProblem and PinchWorkspace accept:
packaged sample-case names such as
basic_pinch.jsonJSON files
Excel workbooks such as
.xlsx,.xls,.xlsb, and.xlsmCSV directories containing
streams.csvandutilities.csv(streams_csv, utilities_csv)tuplesTargetInputinstancesplain mappings that already match the case-input structure
Canonical Input Fields
Structured process-stream, segment, and temperature-profile mappings reject
unknown fields. Process streams use name and
heat_capacity_flowrate as their canonical field names. Retired spellings
such as stream_name, heat_capacity_flow_rate, and
flow_heat_capacity are invalid inputs and are not migrated.
Variable Heat-Capacity Streams
Structured Python and JSON inputs can describe one physical stream with an
ordered piecewise thermal profile. The prepared problem retains one parent
Stream; its internal child records are used for interval, area, and network
calculations.
Every Value exposed by a prepared parent or child segment is a read-only
view. Change domain state by assigning the stream property, calling
set_value_attr_at_idx(...), or using update_segment(...) and
update_segments(...). These APIs validate a mutable candidate and commit
the complete change transactionally.
Explicit segment input supplies each piece in physical traversal order. Every segment target temperature must equal the next segment supply temperature. OpenPinch preserves this order and rejects gaps, overlaps, reversals, and non-positive segment duties or heat-transfer coefficients.
from OpenPinch import PinchProblem
problem = PinchProblem(
{
"streams": [
{
"zone": "Site",
"name": "Variable CP feed",
"segments": [
{
"t_supply": 180.0,
"t_target": 140.0,
"heat_flow": 60.0,
"htc": 1.5,
},
{
"t_supply": 140.0,
"t_target": 80.0,
"heat_flow": 150.0,
"htc": 0.9,
},
],
}
],
"utilities": [],
},
project_name="Site",
)
A temperature–cumulative-heat profile is an alternative nested input. Its points are authoritative: OpenPinch infers parent endpoints and duty, and validates any duplicated parent values instead of rescaling the profile. Cumulative heat must increase strictly. Temperature plateaus follow the existing minimum sensible-temperature-span convention, while reversals are rejected before linearisation.
stream_input = {
"zone": "Site",
"name": "Calculated profile",
"profile": {
"points": [
{"temperature": 180.0, "cumulative_heat": 0.0},
{"temperature": 140.0, "cumulative_heat": 60.0},
{"temperature": 80.0, "cumulative_heat": 210.0},
],
"linearisation_tolerance": 0.01,
},
}
Nested profiles are supported by Python objects, JSON, and workspace inputs. Flat CSV and Excel stream rows remain unchanged and are never grouped by name or adjacent temperatures.
Segmented Utilities and Prices
Structured utility inputs accept the same mutually exclusive segments or
profile shapes. Explicit segments may each provide a different price.
A segment price overrides the parent utility price; the parent price fills any
missing child price, and the existing utility default applies when neither is
provided. The prepared utility remains one parent stream, whose displayed
price is the duty-weighted effective value.
segmented_steam = {
"name": "Segmented steam",
"type": "Hot",
"price": 40.0,
"segments": [
{
"t_supply": 250.0,
"t_target": 220.0,
"heat_flow": 50.0,
"price": 20.0,
},
{
"t_supply": 220.0,
"t_target": 180.0,
"heat_flow": 100.0,
},
],
}
Here the first segment costs 20 per energy unit and the second inherits 40.
Temperature–heat profile input deliberately accepts one parent/default
price only; use explicit segments when interval prices differ.
Interpretation
Choose the source shape by ownership:
Use packaged sample cases for learning and regression examples.
Use JSON for version-controlled studies.
Use workbooks when the source of truth is spreadsheet-oriented.
Use CSV bundles when streams and utilities originate from separate tabular exports.
Use schema-first Python inputs when another system constructs cases in memory.
Configuration belongs in TargetInput.options and is materialized as a
runtime Configuration object on prepared zones. Use
config_options() to discover supported option keys.
Next Steps
Schemas and Config for typed schema and option details.
Internal Service Layer for the preparation boundary.
Zonal and Total Site Workflows when your input has a zone tree.