Subsystems: Reusable Component Groups¶
Subsystems are an easy way to add frequently used component groups such as a drum with evaporator or a preheater with desuperheater to your system. In this section you will learn how to create a subsystem and implement it in your work. The subsystems are highly customizable and thus a very powerful tool, if you require using specific component groups frequently. We provide an example, of how to create a simple subsystem and use it in a simulation.
Custom subsystems¶
Create a .py file in your working-directory. This file contains the
class definition of your subsystem and at minimum one method:
create_network: Method to create the network of your subsystem.
On top of that you need to add methods to define the available interfaces of
your subsystem to the remaining network through specifying the number of inlets
and outlets in the __init__ method of your class as seen in the code
example below.
All other functionalities are inherited by the parent class of the
subsystem object.
Example¶
Create the subsystem¶
We create a subsystem for the usage of a waste heat steam generator. The subsystem is built up of a superheater, an evaporator, a drum and an economizer as seen in the figure below.
Figure: Topology of the waste heat steam generator¶
Figure: Topology of the waste heat steam generator¶
Create a file, e.g. mysubsystems.py and add the following lines:
Imports of the necessary classes from tespy.
Class definition of the subsystem (inheriting from subsystem class).
Methods for component and connection creation. Both, components and connections, are stored in a dictionary for easy access by their respective label.
>>> from tespy.components import Subsystem, HeatExchanger, Drum
>>> from tespy.connections import Connection
>>> class WasteHeatSteamGenerator(Subsystem):
... """Class documentation"""
... def __init__(self, label):
... self.num_in = 2
... self.num_out = 2
... super().__init__(label)
...
... def create_network(self):
... """Define the subsystem's connections."""
... eco = HeatExchanger('economizer')
... eva = HeatExchanger('evaporator')
... sup = HeatExchanger('superheater')
... drum = Drum('drum')
...
... inlet_eco = Connection(self.inlet, 'out2', eco, 'in2', label='1')
... eco_dr = Connection(eco, 'out2', drum, 'in1', label='2')
... dr_eva = Connection(drum, 'out1', eva, 'in2', label='3')
... eva_dr = Connection(eva, 'out2', drum, 'in2', label='4')
... dr_sup = Connection(drum, 'out2', sup, 'in2', label='5')
... sup_outlet = Connection(sup, 'out2', self.outlet, 'in2', label='6')
...
... self.add_conns(inlet_eco, eco_dr, dr_eva, eva_dr, dr_sup, sup_outlet)
...
... inlet_sup = Connection(self.inlet, 'out1', sup, 'in1', label='11')
... sup_eva = Connection(sup, 'out1', eva, 'in1', label='12')
... eva_eco = Connection(eva, 'out1', eco, 'in1', label='13')
... eco_outlet = Connection(eco, 'out1', self.outlet, 'in1', label='14')
...
... self.add_conns(inlet_sup, sup_eva, eva_eco, eco_outlet)
Make use of your subsystem¶
We create a network and use the subsystem we just created along with the different tespy classes required.
>>> from tespy.networks import Network
>>> from tespy.components import Source, Sink
>>> from tespy.connections import Connection
>>> import numpy as np
>>> # %% network definition
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(temperature="degC", pressure="bar")
>>> # %% component definition
>>> feed_water = Source('feed water inlet')
>>> steam = Sink('live steam outlet')
>>> waste_heat = Source('waste heat inlet')
>>> chimney = Sink('waste heat chimney')
>>> sg = WasteHeatSteamGenerator('waste heat steam generator')
>>> # %% connection definition
>>> fw_sg = Connection(feed_water, 'out1', sg, 'in2')
>>> sg_ls = Connection(sg, 'out2', steam, 'in1')
>>> fg_sg = Connection(waste_heat, 'out1', sg, 'in1')
>>> sg_ch = Connection(sg, 'out1', chimney, 'in1')
>>> nw.add_conns(fw_sg, sg_ls, fg_sg, sg_ch)
>>> nw.add_subsystems(sg)
>>> # %% connection parameters
>>> fw_sg.set_attr(fluid={'water': 1}, T=25, m0=15)
>>> fg_sg.set_attr(fluid={'air': 1}, T=650, m=100)
>>> sg_ls.set_attr(p=130, T=600, design=['T'])
>>> sg_ch.set_attr(p=1)
>>> sg.get_conn('4').set_attr(x=0.6)
>>> # %% component parameters
>>> sg.get_comp('economizer').set_attr(
... pr1=0.999, pr2=0.97, design=['pr1', 'pr2'],
... offdesign=['zeta1', 'zeta2', 'kA_char']
... )
>>> sg.get_comp('evaporator').set_attr(
... pr1=0.999, ttd_l=20, design=['pr1', 'ttd_l'],
... offdesign=['zeta1', 'kA_char']
... )
>>> sg.get_comp('superheater').set_attr(
... pr1=0.999, pr2=0.99, design=['pr1', 'pr2'],
... offdesign=['zeta1', 'zeta2', 'kA_char']
... )
>>> sg.get_conn('2').set_attr(td_bubble=5, design=['td_bubble'])
>>> # %% solve
>>> # solve design case
>>> nw.solve('design')
>>> nw.assert_convergence()
>>> nw.save('tmp.json')
>>> # offdesign test
>>> nw.solve('offdesign', design_path='tmp.json')
>>> nw.assert_convergence()