Drum blowdown #448
-
Hi, community. By any chance, do you know if it's possible to indicate a blowdown connection to a drum? When I try to derive a connection between the drum and the evaporator (a splitter, to send some saturated liquid to waste), the library crashes (for a good reason: I imagine there is some error in the drum cycle closer, as the inflow to the evaporator is somehow different from the outflow from the evaporator, because the aforementioned blowdown derivation). Any help with this issue would be highly appreciated. PS: There is a way to design the circuit otherwise, deriving the blowdown before the drum, providing you stipulate some saturated steam to heat the economizer outlet to saturation and then returning it to the drum, but it is a little bit more complicated. There's need for an additional loop. |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 8 replies
-
Hi and thanks for asking. Can you post a flow sheet? Just a drum with blow down, nothing more? If you like, we can have a meeting and look at this together, and see how to implement something on top of what is currently available:). Best |
Beta Was this translation helpful? Give feedback.
-
Hi, F. I've seen that how the flows go have been understood perfectly. If anyone else is reading: This need arises because in a steam power plant, where the cycle is not entirely closed (seals are not perfect), solids carried by the makeup water end up in the drum, not being able to travel with the saturated steam (at least, in great extent). As concentration rises, causing several and serious operational problems, it's quite usual to continuously purge the drum. In a mechanical-compressed refrigeration cycle (like the one in the documentation) such need is not present, as it is a fully closed cycle and leakage is minimal. Counting with the ability to model the blowdown flows enables further studies of energy efficiency, by taking some heat from the waste flow before it's discarded. I'll check the branch and the editable version. I'm glad to contribute (though quite a small one) to this community. Thanks for the answer, and the time of developing. |
Beta Was this translation helpful? Give feedback.
-
Hi, sorry for being a pain. I've updated tespy, and tried to run several files. It seems to be sth not working entirely right with the component: Traceback (most recent call last): File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\spyder_kernels\py3compat.py:356 in compat_exec File c:\users\barral pablo\desktop\untitled2.py:40 File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\networks\network.py:1937 in solve File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\networks\network.py:872 in initialise File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\networks\network.py:1336 in init_design File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\components\nodes\drum.py:200 in preprocess File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\components\component.py:345 in preprocess File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\tespy\components\nodes\drum.py:179 in get_mandatory_constraints UnboundLocalError: cannot access local variable 'num_mass_eq' where it is not associated with a value This arises when trying to run the test (I've copied the code): from tespy.components import Drum
from tespy.components import SimpleHeatExchanger
from tespy.components import Sink
from tespy.components import Source
from tespy.components import Splitter
from tespy.connections import Connection
from tespy.networks import Network
nw = Network(T_unit="C", p_unit="bar")
dr = Drum("drum")
so = Source("liquid")
si = Sink("vapor")
c1 = Connection(so, "out1", dr, "in1", label="1")
c2 = Connection(dr, "out2", si, "in1", label="2")
nw.add_conns(c1, c2)
c1.set_attr(fluid={"R290": 1}, m=10, Td_bp=-10, T=50)
sp = Splitter("blowdown splitter")
si = Sink("blowdown sink")
eva = SimpleHeatExchanger("evaporator")
dr = nw.get_comp("drum")
c3 = Connection(dr, "out1", sp, "in1", label="3")
c4 = Connection(sp, "out1", si, "in1", label="4")
c5 = Connection(sp, "out2", eva, "in1", label="5")
c6 = Connection(eva, "out1", dr, "in2", label="6")
c6.set_attr(x=0.7, m=15)
nw.add_conns(c3, c4, c5, c6)
nw.solve("design") The same thing happens when from tespy.networks import Network
from tespy.components import Source, Sink, Splitter, Drum, SimpleHeatExchanger
from tespy.connections import Connection
nw = Network()
water = Source("Water")
drum = Drum("Drum")
splitter = Splitter("Blow down splitter")
evaporator = SimpleHeatExchanger("Evaporator")
blow_down = Sink("Blow down outlet")
steam = Sink("Saturated steam outlet")
c1 = Connection(water, "out1", drum, "in1", label="1")
c2 = Connection(drum, "out1", splitter, "in1", label="2")
c3 = Connection(splitter, "out1", blow_down, "in1", label="3")
c4 = Connection(splitter, "out2", evaporator, "in1", label="4")
c5 = Connection(evaporator, "out1", drum, "in2", label="5")
c6 = Connection(drum, "out2", steam, "in1", label="6")
nw.add_conns(c1, c2, c3, c4, c5, c6)
c1.set_attr(fluid={"water": 1}, p=100e5, Td_bp=-10, m=5)
c4.set_attr(m=10)
c4.set_attr(x=7)
nw.solve("design") Line 179 is def get_mandatory_constraints(self):
if self.inl[1].m == self.outl[0].m:
num_mass_eq = 0
return {
'mass_flow_constraints': {
'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv,
'constant_deriv': True, 'latex': self.mass_flow_func_doc,
'num_eq': num_mass_eq},
'energy_balance_constraints': {
'func': self.energy_balance_func,
'deriv': self.energy_balance_deriv,
'constant_deriv': False, 'latex': I'm sorry for posting. If I had the knowledge, I'd try to fix it myself! Regards :) |
Beta Was this translation helpful? Give feedback.
-
The working example is: # -*- coding: utf-8 -*-
"""
Created on Tue Nov 14 11:14:50 2023
@author: pmbarral
"""
# Application notes:
from tespy.networks import Network
from tespy.connections import Connection
from tespy.components import (CycleCloser, SimpleHeatExchanger, Pump, Splitter, Valve, Sink, Source, Merge, Drum)
my_plant = Network()
my_plant.set_attr(T_unit='C',p_unit='bar', h_unit='kJ / kg', m_unit='t / h', s_unit='kJ / kgK', iterinfo=False)
# Components
cc = CycleCloser('cycle closer')
fp = Pump('boiler feedwater pump')
fp.set_attr(eta_s=0.7)
hd = Splitter('LP header')
cv = Valve('pressure control valve')
lpsi = Sink('industrial process')
cnrt = Source('condensate return')
mk = Source('demi water makeup')
tk = Merge('boiler feedwater tank', num_in=3)
ec = SimpleHeatExchanger('economizer')
ec.set_attr(pr=1)
dr = Drum("drum")
ev = SimpleHeatExchanger("evaporator")
bd = Splitter('blowdown')
wst = Sink('waste')
# Connections
c = [None] * 14
names = [None] * 14
c[0] = Connection(dr, 'out2', cc, 'in1', label='0') # same state as c[1]
names[0] = 'boiler outlet'
c[1] = Connection(cc, 'out1', hd, 'in1', label='1') # boiler outlet
c[1].set_attr(p=13, fluid={'water': 1})
names[1] = 'boiler outlet'
from tespy.connections import Ref
c[0].set_attr(m=Ref(c[1], 1, 0))
c[2] = Connection(hd, 'out1', lpsi, 'in1', label='2') # process steam
c[2].set_attr(m=100)
names[2] = 'process steam'
c[3] = Connection(hd, 'out2', cv, 'in1', label='3') # tk steam
names[3] = 'tk steam'
c[4] = Connection(cv, 'out1', tk, 'in1', label='4') # vlp tk steam
names[4] = 'vlp tk steam'
c[5] = Connection(tk, 'out1', fp, 'in1', label='5') # tk outlet
c[5].set_attr(T=105, x=0, fluid={'water': 1})
names[5] = 'tk outlet'
c[6] = Connection(fp, 'out1', ec, 'in1', label='6') # boiler fw
names[6] = 'boiler fw'
c[7] = Connection(mk, 'out1', tk, 'in2', label='7') # makeup water
c[7].set_attr(T=25, fluid={'water': 1})
names[7] = 'makeup water'
c[8] = Connection(cnrt, 'out1', tk, 'in3', label='8') # condensate return
c[8].set_attr(T=70, m=70, fluid={'water': 1})
names[8] = 'condensate return'
c[9] = Connection(ec, 'out1', dr, 'in1', label='9') # economizer outlet
names[9] = 'economizer outlet'
c[9].set_attr(Td_bp=-50)
c[10] = Connection(dr, 'out1', bd, 'in1', label='10') # drum water outlet
names[10] = 'drum water outlet'
c[11] = Connection(ev, 'out1', dr, 'in2', label='11') # riser
c[11].set_attr(x=0.05)
names[11] = 'riser'
c[12] = Connection(bd, 'out1', wst, 'in1', label='12') # blowdown
names[12] = 'blowdown'
c[12].set_attr(m=Ref(c[6], 0.05, 0))
c[13] = Connection(bd, 'out2', ev, 'in1', label='13') # downcomer
names[13] = 'downcomer'
for j in range(0,14):
my_plant.add_conns(c[j])
my_plant.solve(mode='design')
df_results_for_conns = my_plant.results['Connection']
df_results_for_conns['denomination'] = names
results = df_results_for_conns[['denomination',
'p','p_unit',
'T','T_unit',
'h','h_unit',
's','s_unit',
'x',
'm','m_unit']]
results = results.drop(results.index[0])
def impresion(__file__, results):
results = results.round(3)
import os
directorio_actual = os.path.dirname(os.path.abspath(__file__))
archivo_texto = os.path.join(directorio_actual, 'archivo.txt')
texto_formateado = results.to_string(index=False, justify='left')
with open(archivo_texto, 'w') as file:
file.write(texto_formateado)
impresion(__file__, results) |
Beta Was this translation helpful? Give feedback.
Okay, there seem to be bugs in the drum. I have never catched this issue here. The following code should work, but does not with the current state of the code. I will update the source code in a pull request, add some tests and then create a release. Likely I cannot finalize this until the weekend or half way next week. So you would need to install tespy in editable version by cloning this repository and checking out the respective branch (see installation information for developers in the tespy documentation).