Introduction to used libraries#

This section will give a short introduction into the packages used for the course.

CoolProp in 5 Minutes#

CoolProp [1] is an open source package for the calculation of thermodynamic properties of many pure, pseudo-pure (e.g. air) and mixtures. The online documentation contains all relevant information on the scope of the software and its usage for further read. In this course CoolProp is mainly accessed at the High Level API, specifically the PropsSI function.

The PropsSI function can be imported as follows:

from CoolProp.CoolProp import PropsSI as PSI

To access non-trivial[1] properties of a fluid at a defined state, we have to provide

  • the output property

  • the first input property,

  • the second input property and

  • the name of the fluid.

Note

All values returned by the function are given in SI unit systems.

For example, to get the enthalpy of water at a pressure of 10 bar and a temperature of 250 °C, PropsSI is called in the following way:

PSI("H", "P", 10 * 1e5, "T", 250 + 273.15, "water")
2943122.4215286043

We will be working with entropy S, enthalpy H, temperature T, pressure P and vapor mass fraction Q in this course. All possible input variables are listed here.

PSI("S", "P", 10 * 1e5, "T", 250 + 273.15, "water")  # entropy
6926.482858129736
PSI("T", "P", 10 * 1e5, "Q", 0, "water")  # saturation temperature
453.02800788167605
PSI("P", "T", 250 + 273.15, "Q", 0, "water")  # saturation pressure
3976174.9306515492
PSI("H", "P", 10 * 1e5, "Q", 0, "water")  # enthalpy of saturated liquid
762515.0697660876
PSI("H", "P", 10 * 1e5, "Q", 1, "water")  # enthalpy of saturated gas
2777108.6040473124

It is also possible to call PropsSI on vectors calculating many states in a single function call. To do this, we need to pass a numpy.array to the function. For example calulate the enthalpy of water at a give pressure but variable temperature.

Tip

Find helpful links on the usage of numpy in the last section of this chapter.

import numpy as np


temperature_range = np.arange(50, 251) + 273.15  # temperature range from 50 to 250 degrees

enthalpy_range = PSI("H", "P", 10 * 1e5, "T", temperature_range, "water")  # at 10 bar

TESPy in 5 Minutes#

TESPy [2] is an open-source framework for the simulation of component based thermodynamic conversion processes. With the software you can used predefined components such as a pump, compressor, heat exhcanger, turbine or valve (and many more) to build thermodynamic systems. The system is set up by connecting the components in a generic way and then specifying respective process and component parameters.

The software then performs a steady state simulation of your system by creating and solving a system of equations in the so called equation oriented (EO) approach (see [3] for more information). The system represents the individual topology and compoent and process specifications provided by you. TESPy accomplishes this by solving for

  • mass flow,

  • pressure and

  • enthalpy

of every connections between two components[2]. After solving a model, missing component and process parameters - for example: efficiencies, temperatures, pressure losses - are determined based on these information. The EO approach lets the modeler choose, which parameters are inputs and which parameters are results: For instance, a compressor efficiency can be an input and the system variables are solved to meet that constraint, or it can be a result of other inputs.

Modeling a Compressor#

TESPy consists of three main building blocks:

  • class Network as container of the simulation

  • class Component (children of them: Compressor, Valve, …), in which thermodynamic conversion processes take place

  • class Connection, which define the topology of the Network by connecting the individual components

We are modeling a compressor, which compresses fully saturated steam to a higher pressure level. The Fig. 11 shows the abstract representation of the component. The table below summarizes the process parameters we are going to apply in our example.

../_images/Compressor.svg

Fig. 1 Compressor model.#

parameter description

model location

model parameter

value

unit

saturated gas state

in

x

100

%

temperature

T

10

°C

mass flow

m

0.1

kg/s

efficiency

compressor

eta_s

80

%

pressure ratio

pr

3

-

from tespy.networks import Network
from tespy.components import Source, Sink, Compressor
from tespy.connections import Connection


nwk = Network(fluids=["R290"], p_unit="bar", T_unit="C")

so = Source("source")
cp = Compressor("compressor")
si = Sink("sink")

c1 = Connection(so, "out1", cp, "in1", label="1")
c2 = Connection(cp, "out1", si, "in1", label="2")

nwk.add_conns(c1, c2)

To make a simulation it is now necessary to specify relevant component and process parameters. We start with the values as provided in Table 1.

c1.set_attr(fluid={"R290": 1}, T=10, x=1, m=0.1)

cp.set_attr(eta_s=0.8, pr=3)

nwk.solve("design")
 iter  | residual   | progress   | massflow   | pressure   | enthalpy   | fluid      |            
-------+------------+------------+------------+------------+------------+------------+
 1     | 3.82e+05   | 50 %       | 1.45e+00   | 1.03e+06   | 7.37e+04   | 0.00e+00   |            
 2     | 3.26e+05   | 50 %       | 8.33e-17   | 7.44e+05   | 4.20e+05   | 0.00e+00   |            
 3     | 4.50e+03   | 50 %       | 0.00e+00   | 1.18e+05   | 4.14e+03   | 0.00e+00   |            
 4     | 6.32e+01   | 51 %       | 0.00e+00   | 1.09e+03   | 8.01e+01   | 0.00e+00   |            
 5     | 5.29e-03   | 52 %       | 0.00e+00   | 9.42e-02   | 1.20e-02   | 0.00e+00   |            
 6     | 1.85e-06   | 53 %       | 0.00e+00   | 9.55e-02   | 2.41e-03   | 0.00e+00   |            
Total iterations: 6, Calculation time: 0.02 s, Iterations per second: 277.73

We can have a look at some results. An overview is provided by the print_results method of the Network.

nwk.print_results()
##### RESULTS (Compressor) #####
+------------+----------+----------+----------+--------+
|            |        P |    eta_s |       pr |   igva |
|------------+----------+----------+----------+--------|
| compressor | 6.37e+03 | 8.00e-01 | 3.00e+00 |    nan |
+------------+----------+----------+----------+--------+
##### RESULTS (Connection) #####
+----+-----------+-----------+-----------+-----------+
|    |         m |         p |         h |         T |
|----+-----------+-----------+-----------+-----------|
|  1 | 1.000e-01 | 6.366e+00 | 5.857e+05 | 1.000e+01 |
|  2 | 1.000e-01 | 1.910e+01 | 6.494e+05 | 6.476e+01 |
+----+-----------+-----------+-----------+-----------+

Since TESPy is working with an equation oriented solver, we can now change things up. For example, instead of providing the efficiency of the compressor, we could provide an outlet temperature. Given that temperature, the efficiency of the compressor will be a result of the calculation.

Note

With the equation oriented structure the user is not constraint in the inputs. As long as the network is well determined, the solver be able to find a result. One downside of the equation oriented approach is that the a initial guess for all variables is required. Bad starting values often lead to the solver being unable to find a solution. For more information please have a look at the TESPy documentation. Here in detail information and best practices are provided for this topic.

cp.set_attr(eta_s=None)  # unset the isentropic efficiency
c2.set_attr(T=70)
nwk.set_attr(iterinfo=False)
nwk.solve("design")
nwk.print_results()
##### RESULTS (Compressor) #####
+------------+----------+----------+----------+--------+
|            |        P |    eta_s |       pr |   igva |
|------------+----------+----------+----------+--------|
| compressor | 7.64e+03 | 6.67e-01 | 3.00e+00 |    nan |
+------------+----------+----------+----------+--------+
##### RESULTS (Connection) #####
+----+-----------+-----------+-----------+-----------+
|    |         m |         p |         h |         T |
|----+-----------+-----------+-----------+-----------|
|  1 | 1.000e-01 | 6.366e+00 | 5.857e+05 | 1.000e+01 |
|  2 | 1.000e-01 | 1.910e+01 | 6.621e+05 | 7.000e+01 |
+----+-----------+-----------+-----------+-----------+

For example, we can make an invalid parameter specification by setting the mass flow at the inlet and at the outlet of the compressor. This overdetermines the system of equations and will result in an error when trying to solve.

c2.set_attr(T=None, m=0.1)
nwk.solve("design")
Singularity in jacobian matrix, calculation aborted! Make sure your network does not have any linear dependencies in the parametrisation. Other reasons might be
-> given temperature with given pressure in two phase region, try setting enthalpy instead or provide accurate starting value for pressure.
-> given logarithmic temperature differences or kA-values for heat exchangers, 
-> support better starting values.
-> bad starting value for fuel mass flow of combustion chamber, provide small (near to zero, but not zero) starting value.

Learn more#

TESPy relies on CoolProp to provide fluid property data for a large range of different fluids [1]. The online documentation of TESPy provides a large variety of examples and tutorials to learn to use the software as well as extensive background information and code documentation:

Data handling and visualization#

The following Python packages are used within the course:

  • NumPy is a mathematical computation package, e.g. for vectorized function calls.

  • pandas is a package building on NumPy with focus on data science.

  • matplotlib is a library with a lot of methods for scientific data visualization.

We do not provide a tutorial here, there are many examples and tutorials available through the respective online documentation as well as resources provided by the community, e.g. Data Science for Energy System Modeling.