CHP plant & DHN design_Problem setting up the system #476
-
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
Hi @MikeSennis and thanks for reaching out! The error showing for you is actually a bug, I will fix it asap. Can you give me a couple more insights, if the two gas turbines always will be operated identically? In that case you could also remove the second one from the system and just double the flue gas mass flow... If both gas turbines should not be identical, you could use the subsystem class of tespy to build a gas turbine as a subsystem and include that as desired, or you go even beyond and build your own class to handle that. See below for an example from tespy.networks import Network
from tespy.components import (
DiabaticCombustionChamber, Turbine, Source, Sink, Compressor, Subsystem
)
from tespy.connections import Connection, Ref, Bus
class GasTurbineSubsystem(Subsystem):
"""Class documentation"""
def create_comps(self):
"""Create the subsystem's components."""
self.comps['compressor'] = Compressor(f'{self.label}-compressor')
self.comps['combustion'] = DiabaticCombustionChamber(f'{self.label}-combustion chamber')
self.comps['gas'] = Source(f'{self.label}-gas intake')
self.comps['air'] = Source(f'{self.label}-air intake')
self.comps['turbine'] = Turbine(f'{self.label}-turbine')
def create_conns(self):
"""Define the subsystem's connections."""
self.conns['c1'] = Connection(
self.comps['air'], 'out1', self.comps['compressor'], 'in1',
label=f"{self.label}-1"
)
self.conns['c2'] = Connection(
self.comps['compressor'], 'out1', self.comps['combustion'], 'in1',
label=f"{self.label}-2"
)
self.conns['c3'] = Connection(
self.comps['combustion'], 'out1', self.comps['turbine'], 'in1',
label=f"{self.label}-3"
)
self.conns['c4'] = Connection(
self.comps['gas'], 'out1', self.comps['combustion'], 'in2',
label=f"{self.label}-4",
# you can also include specifications here
# if you want to modify them on creating the class instance, then
# you have to modify the __init__ method and set up respective
# logic and variables
p=Ref(self.conns["c2"], 1.05, 0)
)
nw = Network(p_unit="bar", T_unit="C", h_unit="kJ / kg")
# adding the 1st gas turbine to our existing network
gt1 = GasTurbineSubsystem("gt1")
fg1 = Sink("flue gas sink 1")
c10 = Connection(gt1.comps["turbine"], "out1", fg1, "in1", label="10")
nw.add_subsys(gt1)
nw.add_conns(c10)
generator1 = Bus("generator 1")
generator1.add_comps(
{"comp": gt1.comps["turbine"], "char": 1, "base": "component"},
{"comp": gt1.comps["compressor"], "char": 1, "base": "bus"},
)
nw.add_busses(generator1)
gt1.comps["combustion"].set_attr(pr=0.98, eta=1, lamb=1.5, ti=None) # or ti=138.3899e6 W (LHV = 49.736 MJ/kg for natural gas)
gt1.conns["c1"].set_attr(
p=0.93194, T=13.5,
fluid={"N2": 0.755, "O2": 0.2315, "Ar": 0.0129, "CO2": 0.0006}
) # fluid: (dry) air -> composition by mass fractions, m=122.185 [kg/s]
gt1.conns["c4"].set_attr(m=1, T=13.5, fluid={"CH4": 0.96, "ETHANE": 0.04, "H2": 0}) # fluid: natural gas -> composition by mass fractions
c10.set_attr(p=Ref(gt1.conns["c1"], 1.03, 0))
gt1.comps["compressor"].set_attr(eta_s=0.9, pr=21.1)
gt1.comps["turbine"].set_attr(eta_s=0.89)
nw.solve(mode="design")
# adding the 2nd gas turbine to our existing network
gt2 = GasTurbineSubsystem("gt2")
fg2 = Sink("flue gas sink 2")
c20 = Connection(gt2.comps["turbine"], "out1", fg2, "in1", label="20")
nw.add_subsys(gt2)
nw.add_conns(c20)
generator2 = Bus("generator 2")
generator2.add_comps(
{"comp": gt2.comps["turbine"], "char": 1, "base": "component"},
{"comp": gt2.comps["compressor"], "char": 1, "base": "bus"},
)
nw.add_busses(generator2)
gt2.comps["combustion"].set_attr(pr=0.98, eta=1, lamb=1.5, ti=None) # or ti=138.3899e6 W (LHV = 49.736 MJ/kg for natural gas)
gt2.conns["c1"].set_attr(
p=0.93194, T=13.5,
fluid={"N2": 0.755, "O2": 0.2315, "Ar": 0.0129, "CO2": 0.0006}
) # fluid: (dry) air -> composition by mass fractions, m=122.185 [kg/s]
gt2.conns["c4"].set_attr(m=1, T=13.5, fluid={"CH4": 0.96, "ETHANE": 0.04, "H2": 0}) # fluid: natural gas -> composition by mass fractions
c20.set_attr(p=Ref(gt2.conns["c1"], 1.03, 0))
gt2.comps["compressor"].set_attr(eta_s=0.9, pr=21.1)
gt2.comps["turbine"].set_attr(eta_s=0.89)
nw.solve(mode="design")
nw.print_results()
# adding the flue gas merger and the district heating network to our existing network
from tespy.components import (
Merge, CycleCloser, Pipe, Pump, Valve, SimpleHeatExchanger, HeatExchanger
)
# central heating plant (CHP plant)
me = Merge('flue gas merger') # Power plant's mixing chamber
hs = SimpleHeatExchanger('heat source') # Power plant's heat exchanger
fg = Sink('flue gas sink')
nw.del_conns(c10, c20)
c10 = Connection(gt1.comps["turbine"], "out1", me, "in1", label="10")
c20 = Connection(gt2.comps["turbine"], "out1", me, "in2", label="20")
c17 = Connection(me, "out1", hs, "in1", label="17")
c18 = Connection(hs, "out1", fg, "in1", label="18")
nw.add_conns(c10, c20, c17, c18)
c18.set_attr(p=Ref(gt1.conns["c1"], 1, 0), T=120)
hs.set_attr(pr=.99)
gt1.conns["c4"].set_attr(m=None)
gt2.conns["c4"].set_attr(m=None)
gt1.conns["c3"].set_attr(m=125)
gt2.conns["c3"].set_attr(m=125)
nw.solve("design")
nw.del_conns(c17, c18)
hs = HeatExchanger("waste heat recovery")
cc = CycleCloser('cycle closer')
fp = Pump('feed pump')
fg = Sink('flue gas sink')
# consumer
cons = SimpleHeatExchanger('consumer')
val = Valve('control valve')
# pipes
pipe_feed = Pipe('feed pipe')
pipe_return = Pipe('return pipe')
# flue gas loop
c17 = Connection(me, "out1", hs, 'in1', label="17") # in1 for heat exchanger's hot side inlet
c18 = Connection(hs, 'out1', fg, 'in1', label='18') # out1 for heat exchanger's hot side outlet
nw.add_conns(c17, c18)
# main (closed) cycle: water cycle
c0 = Connection(cc, "out1", hs, "in2", label="0")
c1 = Connection(hs, "out2", fp, "in1", label="1")
c2 = Connection(fp, "out1", pipe_feed, "in1", label="2")
c3 = Connection(pipe_feed, "out1", cons, "in1", label="3")
c4 = Connection(cons, "out1", val, "in1", label="4")
c5 = Connection(val, "out1", pipe_return, "in1", label="5")
c6 = Connection(pipe_return, "out1", cc, "in1", label="6")
nw.add_conns(c0, c1, c2, c3, c4, c5, c6)
# parameters' definition
hs.set_attr(pr2=1, pr1=1)
cons.set_attr(pr=0.98)
fp.set_attr(eta_s=0.75)
pipe_feed.set_attr(Q=-(0.03*128.775e+06), L=17140, D=0.6, pr=0.98) # assuming 4.8 % total thermal losses in the pipes (128.775 MWth from analysis in Excel)
pipe_return.set_attr(Q=-(0.018*128.775e+06), L=32216, D=2*0.45, pr=0.98) # assuming 4.8 % total thermal losses in the pipes (128.775 MWth from analysis in Excel)
# c10.set_attr(m=126.6, h=1053, p=0.9599, fluid={"H2O": 0.04895, "CO2": 0.06102, "N2": 0.73841, "O2": 0.139, "Ar": 0.01262})
# # fluid: flue gas -> composition by mass fractions
# c15.set_attr(m=126.6, h=1053, p=0.9599, fluid={"H2O": 0.04895, "CO2": 0.06102, "N2": 0.73841, "O2": 0.139, "Ar": 0.01262})
# # fluid: flue gas -> composition by mass fractions
c18.set_attr(T=120, p=0.93194)
# using incompressible water for district heating should be faster
c1.set_attr(T=115, p=23, fluid={'INCOMP::Water': 1})
c2.set_attr(p=25)
c0.set_attr(T=65)
# set starting values for incompressible fluid connections (starting value generator is not working well with INCOMPs)
[c.set_attr(h0=100) for c in [c0, c1, c2, c3, c4, c5, c6]]
nw.solve(mode="design")
nw.print_results()
print(f"DHN mass flow rate = {round(c0.m.val, 3)} kg/s")
print(f"Thermal power given from CHP plant to (primary) DHN = {round(abs(hs.Q.val)/1e6, 3)} MWth")
print(f"Thermal power given from primary DHN to secondary DHN (consumers) = {round(abs(cons.Q.val)/1e6, 3)} MWth")
print(f"Thermal efficiency of (primary) DHN = {round((abs(cons.Q.val)/abs(hs.Q.val)) * 100, 2)} %") |
Beta Was this translation helpful? Give feedback.
-
Hello @fwitte and thank you for your time and useful recommendations, they helped a lot! Is it because I always set the combustion thermal efficiency ("eta") equal to 1? |
Beta Was this translation helpful? Give feedback.
And for the second option, in case you have the identical gas turbine setup: