LP process steam generator #444
-
Hi! I'm having some trouble with the parameter provision. What I have in mind is a steam generator, with a LP steam header, which delivers steam back to the FW Tank and to the sink (an industrial steam consumer). In that tank, there's present a condensate return and the makeup water inlet. I've added a valve (the tank pressure control valve) just to know the temperature of the steam after its pressure reduction (it's not essential knowing this, though). I've experienced two situations: or there's a lack of parameter definition, or the jacobian matrix is zero. It's kind of easy to determine the states in paper, but I'm having a hard time here. My code is as follows (I've added the parameters that undoubtedly go). Some information might be missing: condensate return pressure but by giving the tank pressure (the outlet is a saturated state), those pressures should be calculated. ## Code
from tespy.connections import Connection
from tespy.components import (
CycleCloser, SimpleHeatExchanger, Pump, Splitter, Valve, Sink, Source, Merge)
from tespy.networks import Network
fluid_list = ['water']
my_plant = Network(fluids=fluid_list)
my_plant.set_attr(T_unit='C',p_unit='bar', h_unit='kJ / kg', m_unit='t / h', iterinfo=False)
### Components
cc = CycleCloser('cycle closer')
sg = SimpleHeatExchanger('steam generator')
sg.set_attr(pr=0.9)
fp = Pump('boiler feedwater pump')
fp.set_attr(eta_s=0.75)
hd = Splitter('LP header')
cv = Valve('pressure control valve')
cv.component()
lpsi = Sink('industrial process')
cnrt = Source('condensate return')
mk = Source('demi water makeup')
tk = Merge('boiler feedwater tank', num_in=3)
tk.component()
### Connections
c = [None] * 9
c[0] = Connection(sg, 'out1', cc, 'in1', label='0') # same state as c[1]
c[1] = Connection(cc, 'out1', hd, 'in1', label='1') # boiler outlet
c[2] = Connection(hd, 'out1', lpsi, 'in1', label='2') # process steam
c[2].set_attr(p=13, x=1, m=100, fluid={'water': 1})
c[3] = Connection(hd, 'out2', cv, 'in1', label='3') # tk steam
c[4] = Connection(cv, 'out1', tk, 'in1', label='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})
c[6] = Connection(fp, 'out1', sg, 'in1', label='6') # boiler fw
c[7] = Connection(mk, 'out1', tk, 'in2', label='7') # makeup
c[7].set_attr(T=25, fluid={'water': 1})
c[8] = Connection(cnrt, 'out1', tk, 'in3', label='8') # condensate return
c[8].set_attr(T=70, m=70, fluid={'water': 1})
for j in range(0,9):
my_plant.add_conns(c[j])
my_plant.solve(mode='design')
df_results_for_conns = my_plant.results['Connection'] Thanks!! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
thanks for reaching out. Could it be, you are simply missing one mass flow? For example Btw.: With the latest tespy version there is no need to specify the fluid list to the network instanciation anymore. Best Francesco |
Beta Was this translation helpful? Give feedback.
-
c[8] has been provided. It's the condensate return from industry to the steam plant. c[7] is the makeup water. It should be calculated with the difference from process steam and condensate return. I have a merge (the BFW tank), a splitter (the steam header), and a valve (the BFW tank temperature control valve). I'm assuming that there's only need to provide one state in the splitter and the others are equal to the one given. With the merger I'm assuming that given the outlet state, inlet pressures should be determined as equal to the outlet pressure. In the merger, the tank, I'm trying to calculate how much steam I need to heat the makeup water and the condensate to meet the bfw condition of staturated steam at 105°C. That way, both steam pressure for the valve should be stated, and no parameter should be missing. Sadly, that's not the case. But when I provide one more value, the zero Jacobian matrix problem arises. I've been studying the documentation, but I wasn't able to answer myself. Thanks, and apologies for consuming your time with this. Regards!! |
Beta Was this translation helpful? Give feedback.
-
Just in case, the comment has been answered. For anyone reading: The cycle is just a simple LP boiler with its tank, to determine the natural gas consumption in a reference facility, when doing a CHP feasibility analysis. Perhaps an improvement could be add the boiler blowdon. The code is as follows: # -*- coding: utf-8 -*-
"""
Created on Tue Nov 14 11:14:50 2023
@author: pmbarral
"""
# Application notes:
# TBD: boiler blowdown (use Drum + Evaporator (HeatExchanger)).
from tespy.networks import Network
from tespy.connections import Connection
from tespy.components import (CycleCloser, SimpleHeatExchanger, Pump, Splitter, Valve, Sink, Source, Merge)
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')
sg = SimpleHeatExchanger('steam generator') # needs improving when stating BD
sg.set_attr(pr=1)
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)
#tk.component()
# Connections
c = [None] * 9
names = [None] * 9
c[0] = Connection(sg, 'out1', 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, x=1, 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', sg, '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'
for j in range(0,9):
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]) |
Beta Was this translation helpful? Give feedback.
The issue is the cycle closer. It cuts mass flow and fluid composition into two branches. Since you have a splitter and a merger inside the cycle the cycle closer is not required. You only need it for closed cycles, which do not have a source and a sink.
What you can do to fix this is remove the component (not actually: I tested it and it does not work out of the box, because there is a different bug in the fluid composition set-up... You'd have to fix it in the source code of tespy first). So instead I recommend bringing in a mass flow equality contraint for the cycle closer. You can do that by appending
after you have d…