What’s New¶
Notable new features and improvements of the current release series. The changelogs of the earlier series are linked at the bottom of this page.
v0.11.2 - Rankine’s Renaissance (September, 3, 2026)¶
New Features¶
The EN 12900 fitting and efficiency map generation for the
PolynomialCompressorsupport non-rectangular data:nancells in datasheet tables are excluded from the fits. The methodsfit_EN12900_points()andgenerate_eta_polys_from_points()accept flattened arrays of data points directly (PR #1056).
Bug Fixes¶
The starting value generation split the total mass balance of combustion components arbitrarily, since the stoichiometry and the energy balance cannot enter the presolve on a guessed fluid composition. The
CombustionChamberand its subclasses now contribute an approximate air to fuel proportion - based on the oxygen supply and demand of the inlets and onlamb, where it is specified - to the flow presolve, which leads to more reasonable initial guesses for the individual mass flows (PR #1058).
Other Changes¶
Three new example models are available in the Model Library (PR #1059):
A water-to-water heat pump with an internal heat exchanger and EN 12900 compressor maps, including the offdesign evaluation of its part load behavior.
A supercritical CO2 recompression cycle, a 100 MW Brayton cycle validated against published data.
A combined cycle power plant of 300 MW with district heating extraction.
The documentation has been restructured into the main sections “Get started”, “Explore”, “Build”, “Project” and “Reference”. The former advanced features, integration and knowledge center pages are now split into the how-to guides, extend and integrate sections and the complete simulation models moved from the tutorials to the Model Library (PR #1059).
The new publications page lists the works using or citing tespy. If your work is missing, please open an issue or a pull request (PR #1059).
Contributors¶
Francesco Witte (@fwitte)
v0.11.1 - Rankine’s Renaissance (August, 16, 2026)¶
New Features¶
New
UserDefinedVariableclass: a standalone solver variable that is not attached to any connection or component. It is referenced from the function and dependents of aUserDefinedEquation, which closes the degree of freedom the variable adds. See the user defined variables section for an example (PR #1034).The
SectionedHeatExchangerreports the required hot-side heat transfer areaarea_hotas a result, in casearea_ratio,R_condand the alpha values of all phases occurring in the solution are set (PR #1035).Presolving logs every determination: which specification (or previously presolved value) eliminates which variables, both as solver debug messages and as a structured record.
Network.get_presolve_logreturns the records in order of occurrence, with the originating specifications of each determination resolved transitively (PR #1040).New
NTUHeatExchangercomponent: the heat transfer coefficientUAis linked to the heat transferred through the effectiveness-NTU relation of a specifiableflow_arrangement(counterflow, parallelflow, crossflow with any mixing combination and shell and tube with an arbitrary number of shell passes).eps,NTUand the capacity rate ratioC_rare reported as results (PR #1045).The specifications of a network can be saved, cleared and restored with the new methods
save_specifications(),clear_specifications()andrestore_specifications(). This allows switching between different parametrizations of a topologically unchanged network (PR #1047).The cycle diagram handling of the
ModelTemplateclass can be customized now (PR #1046):The new
create_diagram()method is a public hook for diagram creation. Override it to adjust e.g. the isoline ranges to the operating envelope of your model.Pre-configured diagrams can be registered per fluid with
register_diagram()or passed directly to the plotting methods via the newdiagramkeyword, which is especially useful in interactive sessions.Fluids not supported by fluprodia (mixtures, incompressibles or fluids outside the default isoline range) no longer raise an error in the plotting methods. Instead a warning is logged and the plot falls back to showing the state points only. An is raised if
strict=Trueis passed to the respective method.
The
deltaof aRefcan be specified aspint.Quantityas well (PR #1051).Connections, components and their data containers provide readable
reprandprintoutput now, which can be controlled globally withtespy.set_display_mode:"compact"(default)"extensive""none"
See the general configuration section for an example (PR #1052).
A
Networkcan be converted into aSubsystemwith the newfrom_network()method. The boundary components of the Network instance, e.g.SourceandSink, are automatically by the SubsystemInterface to allow embedding the subsystem into another network. Thekeepparameter controls which state is carried into the subsystem instance (PR #1021):full parametrization (
"specifications", default),starting values only (
"starting_values")nothing (
"nothing")
Bug Fixes¶
The enthalpy to temperature inversion of the
IncompressibleFluidWrapperreturned wrong temperatures for (nearly) constant heat capacity data. The quadratic formula is now evaluated in its numerically stable form.The section result arrays of the
ParallelFlowHeatExchanger(T_hot_sections,T_cold_sections,Q_sections,lmtd_per_section) paired the temperature profiles in counterflow orientation. Both profiles now run from the common inlet end (maximum temperature difference at zero heat transferred) to the common outlet end, aligned on the cumulative heat axis of the parallel flow configuration (PR #1043).After solving and a difference in results between the specified input and the calculated property, the component results tables were not updated while the connection results tables were. Both now report the state of the latest solve (PR #1051).
The
deltaof a referenced property specification was reinterpreted in the current default units at every solve. Changing the default units between two solves silently changed its value (PR #1051).
Other Changes¶
Changing the default units through
set_defaults()after a network has been solved is now well defined and warns about its consequences:Values specified as plain numbers and results are converted from their SI value to the updated default units from the next solve on.
New plain number specifications are interpreted in the new default units.
Values specified as
pint.Quantitykeep their unit.
Previously, already converted values silently kept their old unit while re-specified values picked up the new one, mixing unit systems within a single network (PR #1051).
Support for importing networks exported with tespy v0.8 or earlier through
from_json()has been removed. The same applies to design and initialisation state files written with tespy v0.9 or earlier. To migrate such files, load and re-save them with an intermediate tespy version, e.g. v0.10.0 (PR #1021).The determination error and debug messages on the problem reduction report the number of directly specified variables, so the difference between the original and the reduced problem size becomes traceable (PR #1034).
Adding a connection or component, which is already part of a different network, now raises an error. To use the same model in a second network, create an independent copy of it, e.g. with
export()andfrom_json()(PR #1021).The postprocessing overhead per solve has been reduced (PR #1051):
Unit strings are parsed into pint objects only once per unit and registry instead of once per converted value.
The results DataFrames are built lazily on first access of
Network.results.
Documentation¶
New advanced tutorial on a CO2 transcritical booster refrigeration system of the kind used in supermarkets. The model is implemented on top of the
ModelTemplateclass and demonstrates log(p)-h and QT diagram plotting, a sensitivity analysis of the gas cooler pressure and the optimization of the COP with pymoo. See the tutorial for details.
Contributors¶
Francesco Witte (@fwitte)
Francesco D’Ettorre (@dk-teknologisk-FDE)
Hannes Schneider (@HaSchneider)
v0.11.0 - Rankine’s Renaissance (July, 27, 2026)¶
The solver was restructured from the ground up for this release. The new solver section in the documentation describes the full solution process. This page lists the changes relevant for updating existing models and custom components.
API Changes¶
Everything deprecated with a
FutureWarningin this release will be removed or changed in version 0.12; each warning names its replacement.The solver state of the
Networkclass has moved to the newProblemclass. A fresh instance is created with every call ofsolve()and remains accessible through the new read-onlyNetwork.problemproperty afterwards. Accessing solver attributes directly on the network, e.g.variables_dict,residual,jacobian,increment,residual_history,lin_dep,iter,max_iter, is deprecated and raises aFutureWarning, useNetwork.problem.<name>instead. The public inspection API, e.g.print_residuals(), and thestatusandconvergedattributes are unaffected.The convergence check operates on scaled residuals now: every residual is related to the response of its equation, every increment to the magnitude of its variable, which makes the acceptance independent of the physical scale of the plant.
residual_historyand the residual column of the iteration information display the largest scaled residual instead of the norm of the raw residual vector,print_residuals()shows both. See the solving section.The starting value generation was reworked, see the starting values section for the new process. Custom components may need updates in the hooks that contribute starting value information:
initialise_sourceandinitialise_targetare only consulted as a last fallback for a generic pressure value anymore. Their enthalpy branches are never called; starting enthalpies are generated by the automatic machinery instead.Components can override
_initial_affine_edges()(approximate pressure and enthalpy relations between the ports, used to propagate known values through the network),_initial_temperature_edges()(approximate temperature relations, reconciled into one starting temperature per connection) andinitial_state()(expected phase at a port, turned into saturation pressure anchors and phase consistent enthalpies). The base class defaults cover components with a single inlet and a single outlet.
The dependency declarations of equations are load-bearing for the new block decomposition: an incomplete declaration of a custom equation can render the problem structurally singular for block-wise solving. The error message points to
nw.solve(mode, block_solve=False)for that case.The
power_connector_locationparameter ofSimpleHeatExchanger(and its subclasses) has been removed. It was deprecated and without effect. Loading a network export containing removed component parameters does not fail anymore: unknown parameters are skipped with a warning, so files from older versions stay loadable.
New Features¶
The equation system is solved block-wise by default: a Dulmage-Mendelsohn decomposition brings it into block lower triangular form and the blocks are solved in precedence order. Failures escalate in stages up to the simultaneous solution of the full system from its initial state, which reproduces the behavior of previous versions exactly - the block phase can therefore never degrade robustness. The simultaneous solution can be enforced with
nw.solve(mode, block_solve=False). Networks with variable fluid composition are always solved simultaneously for now, block-wise solving for them is planned for a future release. See the decomposition and solving sections.Under- and over-determination errors and structural singularities name the specific equations and variables of the defective part of the model, interactively available through
print_structural_analysis().The solution process can be staged:
presolve()prepares the problem and stops before solving, so variables can be inspected and modified,solve_continue()then runs the solver. Withnw.solve(mode, pause_on_block_failure=True)the solver pauses at the first failing block (status20) for interactive debugging of that exact state. See the section on interacting with the solver.Starting values can be provided as temperature and vapor quality guesses now, e.g.
conn.set_attr(T0=75, x0=0.5): the temperature guess anchors the starting temperature estimation and both are converted into enthalpy and saturation pressure starting values. The guesses override values of a previous solution and are consumed by a successful solve (#622).New inspection methods report the mathematical structure of the problem: the variable space reduction and the provenance of presolved values (
print_presolved_variables()), the block decomposition (print_blocks(),print_incidence_matrix()withblock_order=True) and the state of a failed block (print_block_jacobian(),print_block_states()). See the problem reduction section.
Bug Fixes¶
The residual of the \(\zeta/D^4\) pressure loss equation saturated with vanishing derivatives when the pressure difference approached zero or the mass flow diverged. It is now formulated in terms of the pressure difference, which keeps gradient information exactly where the equation was most violated and removes the special case branch for zero mass flow.
Enthalpy starting values inside the two phase dome could fail with a linear dependency when a temperature equation sat on the residual plateau of the two phase region. The all-zero jacobian row recovery and its bracketing search handle these plateaus now, e.g. the SEGS model converges without its previous two stage initialization.
Exporting a network before solving it serialized plain numeric specifications with the global default units instead of the network’s default units, e.g. a temperature of 200 set under
°Cdefaults was exported as200 kelvinand misread on import. Solved networks were not affected.set_attr()now actually emits itsFutureWarning: the deprecation notice existed but was never raised.Solver runs are bit-exact reproducible now. Two defects injected run to run varying floating point noise into the Jacobian: the numeric derivatives restored the perturbed value by arithmetic (leaving one ulp sized residues that depended on the evaluation order) and the evaluation order itself followed the per process iteration order of sets. Marginal models could converge in one run and fail in the next; results and iteration counts are now identical across repeated runs.
The postprocessing limit checks are noise aware now: a parameter value beyond its declared bound by less than a relative tolerance - related to the magnitude of the parameter itself or of a declared reference parameter, e.g. the thermal input for the heat dissipation of a combustion chamber - is snapped onto the bound instead of being reported. Converged solutions are no longer flagged with
status = 1for numerical noise on exact bounds.Value ranges (
m_range,p_range,h_range) are exported in the network’s default units now. Files exported with earlier versions hold raw SI magnitudes, which are reinterpreted in the default units on load - check or re-export old files carrying range specifications.
Other Changes¶
The solver detects when the residual alternates between two values and activates the oscillation damping automatically. The
oscillation_dampingparameter ofsolve()remains available to activate it from the first iteration. See the convergence stability section.Convergence acceptance was modified. A solution is only accepted in an iteration in which no convergence heuristic modified any value, replacing the fixed
min_iterfloor. The default ofmin_iterdropped from 4 to 2 and warm started solves, e.g. in offdesign parameter sweeps, typically finish in two iterations.Debug logging was reworked throughout preprocessing and solving: it reports the fluid domains, the design/offdesign switch, the problem reduction and the block decomposition, and console output is no longer doubled when console logging is enabled.
The construction of the mathematical problem moved from the network to
Problem.buildand the affine elimination graph is a persistentStructureGraphinstance, available asNetwork.problem.structure_graph. The private network methods_build_graph,_find_cycles_in_graph,_raise_error_if_cycleand_find_linear_dependent_variableshave been removed.
Contributors¶
Francesco Witte (@fwitte)