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.2.2 (10.11.2026)¶
New Features¶
The specific cost of a stream entering the plant can now be given for each exergy form, e.g.
"<stream>_c_CH". A form without its own value takes"<stream>_c"[33] (closes #76).The cost of the loss streams is charged to the product streams in proportion to their net exergy (Bejan et al., Example 8.1) [2]. A stream subtracted in
E_P, such as the feedwater of a boiler, is paired with the product stream it turns into downstream. Where that is not possible, the gross exergy is used as before and a warning names the stream.The cost of the exergy destruction of the whole plant, \(c_\mathrm{F,tot}\,\dot{E}_\mathrm{D,tot}\), is part of
system_costsand of the JSON export.A cost correlation used outside its range gives a warning that names the correlation, the size and the bound the cost is extrapolated from.
Bug Fixes¶
The chemical exergy of a gas mixture from which water condenses at the ambient state was too high, since the exergy of the gas phase was not weighted with its molar fraction. The flue gases of the CCPP and CGAM examples had a chemical exergy that was 5 to 7 % too high. The exergy destruction of the combustion chamber was therefore too low and the exergy loss of the stack too high. The overall exergetic efficiency does not change (closes #63). The flue gas of the JSON example stored the old value, which is updated as well.
In the Ahrendts library, the chemical exergy of liquid and gaseous methanol was swapped and deuterium had the value of oxygen. Deuterium has no value now.
A pure substance gets the chemical exergy of its reference phase, e.g. liquid for methanol and ethanol. Before, it got the value of the gas, except for water.
A pure substance without a value in the library gets a chemical exergy of 0 and a warning that says so. A mixture with such a substance raises a
ValueErrorthat names it. Before, a library entry without a value, such as krypton, raised aTypeErrorin a mixture. A stream without a composition, e.g. an EBSILON binary mixture, also gets 0 and a warning that names it.The docstrings of
calc_chemical_exergy()andadd_chemical_exergy()give the units of the ambient state in K and Pa and of the result in J/kg.The fuel cost of a mixer or a deaerator was wrong. With split physical exergy it did not contain the thermal exergy of its fuel streams. Without the split the exergy left in the outlet was valued at the cost of the outlet instead of the inlet, so the fuel cost depended on the investment cost of the component [33]. Their c_F, c_P, C_D, r and f were wrong. Stream costs were not affected (closes #64).
A dissipative heat exchanger or valve passed the full cost of an exergy form to an outlet without exergy of that form, e.g. the mechanical exergy of a stream leaving at the ambient pressure. This cost now stays in the cost difference of the dissipative component, which is charged to the other components. The valve treats the chemical exergy in the same way. In the heat pump example the costs of all components change, the cost of the product does not (closes #65).
The share of the cost of dissipative components that is charged to a component is now shown in the new column Z_diss of the component results and in the JSON export, read directly from the cost matrix. It is part of the cost balance of the component and thus of its c_P and r [33]. It is not part of f, which compares the investment of the component with the cost of its exergy destruction [2], nor of C_D+Z, since C_D+Z of the dissipative component already contains it. A stream that enters a dissipative component no longer relieves its source component of this cost in the cost matrix (closes #66).
With split physical exergy, the exergy balance of the combustion chamber took the increase of physical exergy as product, its cost balance the increase of thermal exergy. Both now take the increase of thermal exergy as product and the decrease of chemical and mechanical exergy as fuel [33], summed over all inlets and outlets. The exergetic efficiency of the combustion chamber changes slightly, its exergy destruction does not (closes #67).
An ambient state passed to
from_aspenorfrom_ebsilonreached the components but not the exergies of the streams. Aspen now runs the model again at the passed state. EBSILON computes the physical exergy at it if it differs from the measuring points of the model.from_jsonraises aValueErrorif the passed state differs from the one the exergies in the file were computed at (closes #68).The conversion of mass into molar fractions dropped species unknown to CoolProp without a warning. It now raises a
ValueErrorthat names them. The EBSILON parser maps its composition parameters and its pure fluids to CoolProp names, e.g. ETH to Ethane, and no longer writes parameters that are no mass fractions, such as the liquid share of water L_H2O (closes #69).When a stream had no exergy of one form, e.g. no mechanical exergy at the ambient pressure, the auxiliary cost equations of most components set a cost rate equal to a specific cost or fixed the cost of an inlet, which made the cost matrix singular. Such a stream now carries no cost of that form [33]. A branch without mass flow no longer divides by zero (closes #71).
In a closed cycle with chemical exergy the cost of the chemical exergy of the working fluid was undetermined, so the cost matrix was singular or ill-conditioned. The cycle closer now sets it to zero. If a stream enters the cycle from outside, e.g. make-up water, its cost carries through the cycle instead (closes #72).
The auxiliary cost equations of the combustion chamber used only its first two inlets. They now use all inlets, an inlet without chemical exergy no longer makes the cost matrix singular, and a missing chemical exergy raises a clear error. An ash outlet is now taken into account: the ash is heated with the gas, so the increase of its physical exergy is product, while its chemical exergy is subtracted from the fuel. Its chemical exergy keeps the specific cost of the fuel, and the increase of its physical exergy costs as much per unit as that of the gas [33]. The Aspen parser gives every stream of an RStoic block its own connector, so a second outlet no longer replaces the combustion gas, and it warns if an RStoic block has a heat duty but no heat stream (closes #73).
A simple heat exchanger releasing heat above the ambient temperature had a negative product cost with split physical exergy and left out the investment cost without the split. Its product cost is now the cost of the heat. Below the ambient temperature its fuel multiplied two mass flows (closes #74).
A collecting header with parallel branches counted every inlet, including its main inlet, as often as there are branches in the exergy balance, but only once in the cost balance. The mixer and the splitter now count a stream of a parabolic trough as often as the trough’s
num_branchesand every other stream once (closes #75).With split physical exergy, the exergy balance of a mixer or a deaerator used the physical exergy, while its cost balance already used the thermal exergy and put the decrease of mechanical exergy into the fuel. Both now do the latter [33]. Inlets of different composition put the decrease of their chemical exergy into the fuel as well, so the exergy destroyed by mixing is part of the exergy destruction. With the outlet exactly at the ambient temperature, the exergy that still leaves at the outlet is no longer counted as destruction, and the mixer no longer gives an exergy destruction of NaN there. An inlet now belongs to the fuel or the product by the sign of the change of its specific exergy, as SPECO requires [33], and no longer by its temperature, so steams of different pressures no longer give a negative product. The cost of the fuel follows the same streams and forms, also without the split and with the outlet at the ambient temperature. The vent of a deaerator and further outlets of a mixer are part of the balance and leave at the specific cost of the main outlet. In the examples, fuel and product of the deaerator and the mixer of the CCPP change by less than 0.01 kW.
A simple heat exchanger taking in heat above the ambient temperature counted its investment cost in the cost of its fuel, so that r was close to zero. The cost of its fuel is now the cost of the heat.
A simple heat exchanger without a heat stream wrote one auxiliary cost equation too many when it released heat, which made the cost matrix fail. It now leaves the outlet to its cost balance, and it warns that the heat then has no cost.
A simple heat exchanger cooling a stream across the ambient temperature without split physical exergy could have a negative exergy destruction. Without the split it now uses the physical exergy only, as chosen: the heat carries the net change of physical exergy, and a warning explains that the warm and the cold exergy cannot be told apart. Without the split, a simple heat exchanger with a pressure drop warns that the exergy lost by the pressure drop is counted in the exergy of the heat, not as exergy destruction.
A dissipative heat exchanger gave the auxiliary fluid, such as the cooling water, the specific cost it entered with, so it left with more cost than it brought. The auxiliary fluid now leaves without cost, so its cost is part of the cost of the dissipative component, while the main working fluid keeps its specific cost [33]. The auxiliary fluid is found from the plant: it is the side whose outlet reaches a loss stream of
E_Lthrough splitters, mixers and dissipative components only, on every branch. Where that does not decide, a stream that gains exergy is taken as the auxiliary fluid. A heat exchanger whose product reachesE_Lthis way, e.g. cooling water that joins other waste water in a mixer before it is discharged, is now dissipative as well, and not only when the product outlet itself is listed inE_L[2]. The cost of the fuel of a dissipative heat exchanger contains every cost its streams leave behind, the chemical cost of the auxiliary fluid included, so that its C_D + Z is its cost difference. In the heat pump example the air leaving the evaporator now has no cost. The cost of the product does not change, the costs of the components change by less than 0.5 %.A simple heat exchanger heating a stream from below to above the ambient temperature with split physical exergy had a negative exergy destruction. Its product is now the thermal exergy of the outlet, and the cold exergy of the inlet is destroyed, as when a stream is cooled across the ambient temperature [2].
A turbine whose outlet leaves slightly warmer than its inlet, such as a hydraulic turbine, and a compressor or pump with inlet and outlet exactly at the ambient temperature had no fuel and product. They now keep their definition. The cost part of the turbine uses the same outlet as its exergy part, and turbomachines no longer fail when their fuel or product cannot be defined.
The steam generator looked for its heat only among its inlets and took the drain from outlet 2, while the EBSILON parser maps the heat to connector 2 and the drain to outlet 3. It now finds the heat by its kind and the drain as the material outlet besides the two steam outlets, and a missing drain is allowed.
The exergy balance of a flash tank used only the thermal exergy with split physical exergy, so its exergy destruction could be negative, while its cost balance used all exergy forms. Both now take the thermal exergy of the inlet as fuel and that of the outlets as product, and the decrease of mechanical and chemical exergy as fuel. A storage now counts the chemical exergy in its exergy balance, as it did in its cost balance.
A valve below the ambient temperature whose liquid warms on throttling had a negative product. It is now dissipative [33].
A heat exchanger with a stream at a third connector, such as a cascaded drain mapped from EBSILON, left that stream out of its balance. It now raises an error that names the connector.
With split physical exergy, the parabolic trough wrote its fuel, which includes the decrease of mechanical exergy of the fluid, onto the solar heat connection. The connection now carries the solar exergy only.
The relative cost difference r of a component without a product was shown as infinite. It is now NaN. The exergoeconomic factor of a generator or motor without exergy destruction and investment was 0 instead of NaN, several components divided by zero for r and f, and the motor swapped fuel and product in its exergy balance but not in its costs. These are corrected.
A turbine expanding to or below the ambient temperature with split physical exergy wrote no auxiliary cost equations, so the cost matrix was singular. The mechanical exergy now keeps its specific cost, and the thermal exergy of the outlet costs as much per unit as the power [33].
flows_from_rolescounted the exergy of a heat stream in the direction of the heat. Below the ambient temperature the exergy flows against the heat [2], so such a heat stream is now reversed, with a warning.The cost of the exergy loss charged to the products left out loss streams listed as
outputsofE_L, so a priced one, such as purchased cooling water, broke the cost balance of the plant. The loss cost is now the net value [33].check_cost_balance()called afterrun()no longer shows the loss share of a power or heat product as a residual.A stream listed in
E_F,E_PorE_Lwithout an exergy value made the totals NaN. It now raises an error that names it. A heat exchanger in a temperature configuration without fuel and product and a parabolic trough below the ambient temperature now give their exergy destruction from the balance instead of NaN.A simple heat exchanger taking in heat below the ambient temperature with split physical exergy counted the pressure drop against its product. The pressure drop is now fuel and destroyed, as for a heat exchanger below the ambient temperature [2].
The cost of a heat stream followed the direction of the heat. Below the ambient temperature the exergy of heat flows against the heat [2], and its cost now does too, with a warning. Heat taken in by a stream below the ambient temperature, as in an evaporator that cools a room, is the product of the simple heat exchanger, which prices it, so it needs no cost. Heat given off by a stream below the ambient temperature or by a stream cooled across it, as in a chiller, brings the cold exergy and needs a cost like any fuel entering the plant. These cases used to give a negative fuel cost or a singular cost matrix. Without split physical exergy, a stream heated across the ambient temperature now uses the net change of physical exergy as well.
The Aspen parser wrote the work stream of a compressor as leaving it, and the electric power of the motor that drives it as leaving the motor. A pump got a second electric inlet next to its own work stream. Power now flows from the grid through the motor into the compressor or pump, and the work stream of a pump is the electric inlet of its motor. The exergoeconomic analysis of the Aspen CCPP model solves.
A second call of
analyse()kept the dissipative behaviour inferred from the first one and the rows of the earlier cost matrix. Compressor and pump now give the exergy destruction from the exergy balance when the outlet is colder than the inlet. A heat exchanger warns if its hot side enters colder than its cold side. The check of the overall exergy balance no longer skips a component whose exergy destruction is NaN.
Other Changes¶
The examples were run again with all three simulators. Their stored results, the validation notebooks and the results of the exergoeconomic examples in the documentation are up to date. The documentation of the heat pump exergoeconomic example now shows the results with split physical exergy, as its script computes them. The deviations between the simulators do not change.
The table of the number of cost equations of the CGAM example in the documentation was out of date and is corrected.
EconomicAnalysis.first_year_om_costs()is renamed tobase_year_om_costs(), since it returns the cost at the start of the first year in money of the base year. The old name still works with aDeprecationWarning.The docstrings of the pump and of the heat exchanger without split physical exergy now match the code.
v0.2.1 (04.11.2026)¶
New Features¶
ExerPy checks the input of an analysis before it starts, first its structure and then the ranges of its values. This covers JSON files read with
from_jsonand the models parsed from TESPy, EBSILON and Aspen. The problems of each step are reported together, each with its place in the file, e.g.$.connections['1'].m. The format is described in JSON format, andjson_schema()returns it as a JSON Schema (#48).A value in the input can carry its unit, e.g.
"T": 15.0, "T_unit": "degC". ExerPy converts it to SI with pint before the analysis, and a value without a unit is taken as SI. An unknown unit or a unit of the wrong kind is an error that names its place in the file (closes #48).Every export writes the unit of each value.
export_to_json()takesunitsto write values in other units, andexerpy.units.convert()converts a value between any two units.The costs of the exergoeconomic analysis can carry a unit as well, e.g.
"10_c_unit": "EUR / MWh"in the cost dictionary orc_unitinfuel_costs. The newexport_to_json()saves the costs of the streams, the components and the plant, each with its unit.The Aspen parser splits the physical exergy into its thermal and mechanical part with
split_physical_exergy=True, as the EBSILON parser does. For each stream, it adds a property analysis at the ambient temperature and the stream’s pressure to the model in memory and runs the simulation once. The model file stays unchanged.With the split, the EBSILON and Aspen parsers check that the property data of the split reproduce the enthalpy and entropy of each stream, and warn if they do not.
API Changes¶
from_json,from_tespy,from_ebsilonandfrom_aspencheck the input by default. Every material stream needsm,T,p,hande_PH, so an older hand-written file may need more values than before. Passvalidate=Falseto skip the check.ExerPy depends on
msgspecandpint.The TESPy parser writes the values in the units of the network, together with these units. Dimensionless values are written with the unit
dimensionlessinstead of-.export_to_json()no longer writes the internal cost values that an exergoeconomic analysis adds to the streams.export_to_json()writes the costs instead.exerpy.functions.convert_to_SIandexerpy.functions.fluid_property_dataare removed. The EBSILON and Aspen parsers convert their values withexerpy.units.convert_to_SI(), which uses pint and also reads the unit spellings of the simulators, e.g.CorkJ/kg-K. The SI unit of each value is listed inexerpy.units.SI_UNITS.
Bug Fixes¶
The EBSILON parser no longer lists the gaseous and liquid parts of the water,
H2OGandH2OL, next to the totalH2O. The mass fractions of a stream now add up to one. The results do not change.Molar flows given in
kmol/minorkmol/hby EBSILON or Aspen were converted with a factor that was wrong by 10⁶. An enthalpy, entropy or exergy per mole is now an error instead of being read as a value per kg. The examples are not affected.The EBSILON parser raises an error when the calculation of a model fails, instead of parsing the results of an earlier calculation that the model still holds. Every message of the solver is logged with its error code and object, also when it has no description (closes #53).
A heat exchanger is treated as dissipative only when the outlet listed in
E_Lcarries its product, such as the cooling water of a condenser. A fuel-side outlet inE_L, such as the flue gas of an economizer going to the stack, no longer makes it dissipative. The economizers of the CCPP and CGAM examples have an exergetic efficiency again, and the cost results of the CGAM exergoeconomic example change accordingly (closes #55).The EBSILON parser split the physical exergy with other property data than the model: the IAPWS-IF97 steam table, the FDBR gas table and no real gas correction. It now uses the fluid data of each stream. With a real gas correction in the model, e_T of methane at the ambient temperature was -4.4 kJ/kg instead of 0.
The Aspen parser recognizes a multiplier block on work streams as a generator or a motor from the sign of the power entering it, which a turbine produces and a compressor or pump consumes. It no longer asks for a block with the factor 1, which stopped scripts without a terminal, such as the CGAM example (closes #61).
tabulatewas missing from the dependencies, so the result tables failed in a fresh installation. The CI now also imports ExerPy with its dependencies only (closes #43).
Other Changes¶
The examples split the physical exergy with all three simulators. The gases of the CCPP and CGAM models are real gases in Aspen Plus (REFPROP) and EBSILON (Lee-Kesler-Plöcker correction), as in TESPy.
The tests compare the exergy destruction of each component and the exergetic efficiency of the example plants with the results based on EBSILON.
tests/test_simulators.pyruns the EBSILON and Aspen parsers on the example models ifEXERPY_SIMULATOR_TESTS=1.ExerPy is tested on Python 3.11 to 3.15, and the package metadata lists these versions. The GitHub Actions use their current versions (closes #50).
The default heat transfer coefficients were checked against the sources.
The examples were run again with all three simulators. Their validation notebooks compare the exergy destruction of each component and the exergetic efficiency of the plant with the results based on EBSILON (closes #44).
The motor of the Aspen heat pump example has the efficiency of 0.985, as in the other models.
The tests of the TESPy examples run in a temporary folder and no longer overwrite the example results in the repository (closes #49).
Contributors¶
v0.2.0 (22.10.2026)¶
New Features¶
The purchased equipment cost of a component may be estimated with a cost correlation of OpenPyTEA [8]. The new module
exerpy.costinglists the correlations that cost a class of component, suggests one per class, reads the size from the model, converts it into the units of the correlation and says how it relates to the range the correlation was fitted over. For a size outside the range, the cost is extrapolated from the nearest bound with a scaling exponent, or the component is split into parallel units. The costs are in US dollars of the year of the correlation and are converted with the annual exchange rates of the European Central Bank; the cost index of OpenPyTEA is read at runtime as well. ExerPy itself ships no cost correlation and no cost index. OpenPyTEA is an optional dependency,pip install exerpy[costs].sizes()returns every size the model determines for a component, in SI units: the power, the mass flow, the volume flow at the inlet and the pressure ratio of a turbomachine, the power of a motor or a generator, and the heat flow, the heat transfer capacity, the logarithmic mean temperature difference and the area of a heat exchanger, and the heat flow and the live steam mass flow of a steam generator.size()returns one of them. A user-defined cost equation takes the ones it needs, andestimate()takes the one that has the dimension of the units of the chosen correlation, a power or a heat flow, an area, a volume flow or a mass flow, so the volume flow of a fan is converted into ACFM without a hand calculation.The area of a heat exchanger follows from its sections: the exchanger is cut at every phase change of either stream, and every section takes its own overall heat transfer coefficient \(U\). The coefficients are given per section, or taken from a new data file of published values: for each comparable cell (the exchanger type and construction and the fluid group and phase of each stream), the median of its values with their range, their number and their sources. A section without a comparable cell asks for its coefficient instead of borrowing one from another fluid, and a default that rests on fewer than three independent sources is reported. See Component Sizing.
The purchased equipment cost of a component may be scaled from the cost of a reference component of the same type and a different size, with the six-tenths rule or a user-defined exponent, and escalated from the year of the reference with the plant cost index. The size is given, or
size_bynames the size the reference refers to and that size is read from the model. See Scaling the cost of a reference component.boundary_streams()lists the streams that cross the system boundary, with their direction, andflows_from_roles()builds the fuel, product and loss definitions from the role of each of them,"F","P"or"L".from_dict()reads the cost assumptions from a dictionary with the structure of the filefrom_json()reads.A reference year before the first or after the last entry of the plant cost index is bridged with the nominal escalation rate, forward or backward, with a warning saying so;
escalation_factor()returns the factor for a year.A
SimpleHeatExchangertakes the temperature of the source of the heat it takes in asT_hot, or of the consumer of the heat it gives off asT_cold. The heat is then valued at that temperature, as the fuel or the product of the component, and the loss of the heat transfer counts as its exergy destruction. Without them, the heat is valued at the exergy change of the stream, as before. See Heat from or to outside the model.A new example obtains the purchased equipment costs of the heat pump in four ways (known costs, scaled costs of reference components, user-defined cost equations and the correlations of OpenPyTEA), carries each to the cost rates of the components and combines them. See Purchased Equipment Costs from Four Sources.
Bug Fixes¶
The TESPy parser exports the vapour quality of a stream of one fluid, which the sections of a heat exchanger need to place a saturated end.
The EBSILON parser exported the heat transfer capacity
kAof a heat exchanger in the unit of the model, which may be kW/K; it now converts it into W/K.The specific volume of a stream was taken from the
vof a TESPy export, which is its volume flow, so a mixture was placed as a gas or a liquid by its volume flow rather than by its specific volume.The sections of a heat exchanger are the same for TESPy, EBSILON and Aspen Plus models. The Aspen parser exports the volume flow and the vapour mass fraction of a stream; a stream whose export has no volume flow takes the phase of its fluid group; the gaseous water EBSILON lists a second time (
H2OG) no longer hides a flue gas or air; and a stream that is saturated at both ends no longer needs the enthalpy reference of CoolProp.
Documentation¶
The documentation is regrouped into Get Started, Methods, Examples, Project and Reference, and the examples are sorted into exergy, economic and exergoeconomic analysis, each with an overview page. A table of the five steps of the workflow, from the exergy analysis to the exergoeconomic one, links the methods and the examples.
A new page, Component Sizing, explains which sizes a cost function takes, how the area of a heat exchanger is found and where the heat transfer coefficients come from, with a generated table of every value and its sources.
The economic analysis page lists where the purchased equipment costs come from and names the symbol of every quantity it introduces.
Every example ends with its complete code, read from the script itself, and every example of the economic and the exergoeconomic analysis shows the flowsheet of its plant.
The example of the economic analysis of the heat pump stands on its own and carries a purchased equipment cost through every step to its cost rate. The example results are described as what they are, the outcome of placeholder costs, with a guide to reading them.
The CGAM example no longer compares its results with those of Kelly (2008): her stream data do not follow the model of the CGAM problem, so the two are not comparable.
OpenPyTEA and every source of the heat transfer coefficients are cited.
The exergoeconomic analysis page explains how the equation system is built and solved, what changes with the split of the physical exergy and what each error message points to. The exergy analysis page explains how the heat exchanged with the outside of the model is valued, and the API overview covers all five steps of the workflow.
API Changes¶
The TESPy interface,
exerpy[tespy], requires TESPy 0.11.3 or newer.OpenPyTEA 3.1.0 or newer is required for the cost estimates, through the new extra
exerpy[costs].A purchased equipment cost given to
EconomicAnalysismay be a dictionary describing a scaled cost instead of a number.The years of
EconomicAnalysisare renamed:cost_year, the year whose price level a cost from a source is given in, is nowreference_year, and the formerreference_year, the year every cost is carried to, is nowbase_year. The attributereference_PECis nowbase_PEC, andestimate()returns the year of the correlation asreference_year. The same keys apply in the filesfrom_json()reads.
Other Changes¶
A continuous integration check fails when a file contains a cost correlation or a table of a plant cost index, so that none enters the repository.
Contributors¶
Sergio Tomasinelli (@sertomas)