drzg's picture
new modules
21b4b99
from tabulate import tabulate
from Modules.HeatPumpIntegration.HPIPlot import HPIPlot
from Modules.Utility.TemperaturePocketDeletion import TemperaturePocketDeletion as TPD
class HeatPumpIntegration():
def __init__(self,streamsDataFile, Tsinkout, pyPinch):
self.Integrationtype = None
if Tsinkout == None:
self.Integrationtype = 'Itterativ'
self.processdesignation = streamsDataFile[:-4]
self.streamsDataFile = streamsDataFile
self.options = {'draw', 'debug'}
self.KoWP = []
self.EvWP = []
self.COPwerte = []
self.COPT = []
self.SchrittweiteTemp = 0.05
self.Tsinkout = Tsinkout
self.pyPinch = pyPinch
def COP(self,T):
COPList = []
StringList = []
if 144 <= self.Tsinkout <= 212 and 25 <= self.Tsinkout-T <= 190: #Prototypical Stirling
COPList.append(1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992)
StringList.append('Prototypical Stirling')
if 80 <= self.Tsinkout <= 160 and 25 <= self.Tsinkout-T <= 95: #VHTHP (HFC/HFO)
COPList.append(1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895)
StringList.append('VHTHP (HFC/HFO)')
if 25 <= self.Tsinkout <= 100 and 10 <= self.Tsinkout-T <= 78: #SHP and HTHPs (HFC/HFO)
COPList.append(1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469))
StringList.append('SHP and HTHPs (HFC/HFO)')
if 70 <= self.Tsinkout <= 85 and 30 <= self.Tsinkout-T <= 75: #SHP and HTHPs (R717)
COPList.append(40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998)
StringList.append('SHP and HTHPs (R717)')
if len(COPList) == 0:
COPList.append((self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5) # Carnot
StringList.append('Carnot')
return max(COPList),StringList[COPList.index(max(COPList))]
def get_available_heat_pumps(self, T):
"""Returns list of all heat pump types with their COPs and availability status"""
hp_list = []
delta_T = self.Tsinkout - T
# Prototypical Stirling
if 144 <= self.Tsinkout <= 212 and 25 <= delta_T <= 190:
cop = 1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992
hp_list.append({'name': 'Prototypical Stirling', 'cop': cop, 'available': True, 'reason': ''})
else:
hp_list.append({'name': 'Prototypical Stirling', 'cop': None, 'available': False,
'reason': f'Requires: 144°C≤T_sink≤212°C, 25°C≤ΔT≤190°C (Current: T_sink={self.Tsinkout:.1f}°C, ΔT={delta_T:.1f}°C)'})
# VHTHP (HFC/HFO)
if 80 <= self.Tsinkout <= 160 and 25 <= delta_T <= 95:
cop = 1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895
hp_list.append({'name': 'VHTHP (HFC/HFO)', 'cop': cop, 'available': True, 'reason': ''})
else:
hp_list.append({'name': 'VHTHP (HFC/HFO)', 'cop': None, 'available': False,
'reason': f'Requires: 80°C≤T_sink≤160°C, 25°C≤ΔT≤95°C (Current: T_sink={self.Tsinkout:.1f}°C, ΔT={delta_T:.1f}°C)'})
# SHP and HTHPs (HFC/HFO)
if 25 <= self.Tsinkout <= 100 and 10 <= delta_T <= 78:
cop = 1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469)
hp_list.append({'name': 'SHP and HTHPs (HFC/HFO)', 'cop': cop, 'available': True, 'reason': ''})
else:
hp_list.append({'name': 'SHP and HTHPs (HFC/HFO)', 'cop': None, 'available': False,
'reason': f'Requires: 25°C≤T_sink≤100°C, 10°C≤ΔT≤78°C (Current: T_sink={self.Tsinkout:.1f}°C, ΔT={delta_T:.1f}°C)'})
# SHP and HTHPs (R717)
if 70 <= self.Tsinkout <= 85 and 30 <= delta_T <= 75:
cop = 40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998
hp_list.append({'name': 'SHP and HTHPs (R717)', 'cop': cop, 'available': True, 'reason': ''})
else:
hp_list.append({'name': 'SHP and HTHPs (R717)', 'cop': None, 'available': False,
'reason': f'Requires: 70°C≤T_sink≤85°C, 30°C≤ΔT≤75°C (Current: T_sink={self.Tsinkout:.1f}°C, ΔT={delta_T:.1f}°C)'})
# Carnot (always available)
cop_carnot = (self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5
hp_list.append({'name': 'Carnot', 'cop': cop_carnot, 'available': True, 'reason': ''})
return hp_list
def COP_specific(self, T, hp_type):
"""Calculate COP for a specific heat pump type"""
if hp_type == 'Prototypical Stirling':
if 144 <= self.Tsinkout <= 212 and 25 <= self.Tsinkout-T <= 190:
return 1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992
elif hp_type == 'VHTHP (HFC/HFO)':
if 80 <= self.Tsinkout <= 160 and 25 <= self.Tsinkout-T <= 95:
return 1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895
elif hp_type == 'SHP and HTHPs (HFC/HFO)':
if 25 <= self.Tsinkout <= 100 and 10 <= self.Tsinkout-T <= 78:
return 1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469)
elif hp_type == 'SHP and HTHPs (R717)':
if 70 <= self.Tsinkout <= 85 and 30 <= self.Tsinkout-T <= 75:
return 40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998
# Fallback to Carnot
return (self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5
def deleteTemperaturePockets(self):
self.pyPinch = self.pyPinch.PinchAnalyse
self.hotUtility = self.pyPinch.hotUtility
self.heatCascade = self.pyPinch.heatCascade
self._temperatures = self.pyPinch._temperatures
self.deletedPocketdict = TPD(self.hotUtility, self.heatCascade, self._temperatures).deleteTemperaturePockets()
def splitHotandCold(self):
self.splitHotTemperatures = []
self.splitColdTemperatures = []
self.splitHotH = []
self.splitColdH = []
testHot = 0
testCold = 0
for i in range(len(self.deletedPocketdict['T'][0])):
if i >= len(self.deletedPocketdict['deltaH'][0]):
continue
if self.deletedPocketdict['deltaH'][0][i] > 0 and testHot == 0:
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i])
self.splitHotH.append(self.deletedPocketdict['H'][0][i])
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
testHot = 1
elif self.deletedPocketdict['deltaH'][0][i] > 0 and testHot == 1:
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
elif self.deletedPocketdict['deltaH'][0][i] < 0 and testCold == 0:
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i])
self.splitColdH.append(self.deletedPocketdict['H'][0][i])
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
testCold = 1
elif self.deletedPocketdict['deltaH'][0][i] < 0 and testCold == 1:
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
elif self.deletedPocketdict['deltaH'][0][i] == 0:
if self.deletedPocketdict['deltaH'][0][i-1] < 0:
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
elif self.deletedPocketdict['deltaH'][0][i-1] > 0:
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
else:
pass
else:
pass
self.splitColddeltaH = []
self.splitHotdeltaH = []
for i in range(len(self.splitColdH)-1):
self.splitColddeltaH.append(self.splitColdH[i+1]-self.splitColdH[i])
for i in range(len(self.splitHotH)-1):
self.splitHotdeltaH.append(self.splitHotH[i+1]-self.splitHotH[i])
return {'H':self.splitHotH, 'T':self.splitHotTemperatures, 'deltaH':self.splitHotdeltaH},{'H':self.splitColdH, 'T':self.splitColdTemperatures, 'deltaH':self.splitColddeltaH}
def QpunktEv(self,T,Quelle): # FEHLER
return self.GCCSource['H'][Quelle] + ((self.GCCSource['H'][Quelle+1]-self.GCCSource['H'][Quelle])/(self.GCCSource['T'][Quelle+1]-self.GCCSource['T'][Quelle])) * (T-self.GCCSource['T'][Quelle])
def QpunktKo(self,T,Quelle):
return self.GCCSink['H'][Quelle-1] + ((self.GCCSink['H'][Quelle-1]-self.GCCSink['H'][Quelle])/(self.GCCSink['T'][Quelle-1]-self.GCCSink['T'][Quelle])) * (T-self.GCCSink['T'][Quelle-1])
def TKo(self,H,Quelle):
return self.GCCSink['T'][Quelle] - ((self.GCCSink['T'][Quelle]-self.GCCSink['T'][Quelle+1])/(self.GCCSink['H'][Quelle]-self.GCCSink['H'][Quelle+1])) * (self.GCCSink['H'][Quelle]-H)
def IntegrateHeatPump(self):
Test = 0
TSTest = 0
#Starttemperatur
if self.Integrationtype == 'Itterativ':
self.Tsinkout = self.GCCSink['T'][0]
else:
pass
Quelle = 0
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
while T > self.GCCSource['T'][-1]:
if T <= self.GCCSource['T'][Quelle+1]:
Quelle +=1
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
if self.GCCSource['deltaH'][Quelle] == 0.0:
Quelle +=1
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
if T < self.GCCSource['T'][Quelle+1]:
T = self.GCCSource['T'][Quelle+1]
COP = self.COP(T)
QpunktEv = self.QpunktEv(T,Quelle)
QpunktKo = QpunktEv * ((1-(1/COP[0]))**(-1))
self.COPwerte.append(round(COP[0],3))
self.EvWP.append(round(QpunktEv))
self.KoWP.append(round(QpunktKo))
self.COPT.append(T)
for i in range(len(self.GCCSink['T'])):
if self.GCCSink['T'][i] <= self.Tsinkout:
KoQuelle = i
break
if QpunktKo >= self.QpunktKo(self.Tsinkout, KoQuelle) and self.Integrationtype == None and TSTest == 1 and self.Tsinkout < self.GCCSink['T'][0]:
break
if QpunktKo >= self.QpunktKo(self.Tsinkout, KoQuelle) and self.Integrationtype == None and TSTest == 0:
if self.Tsinkout <= self.GCCSink['T'][0]:
T+=self.SchrittweiteTemp
self.SchrittweiteTemp = self.SchrittweiteTemp/200
TSTest = 1
else:
break
if QpunktKo >= self.GCCSink['H'][0] and Test == 0:
T+=self.SchrittweiteTemp
self.SchrittweiteTemp = self.SchrittweiteTemp/200
Test = 1
elif QpunktKo >= self.GCCSink['H'][0] and Test == 1:
break
T-=self.SchrittweiteTemp
if T < self.GCCSource['T'][Quelle+1]:
T = self.GCCSource['T'][Quelle+1]
if T <= self.GCCSource['T'][-1]:
T = self.GCCSource['T'][-1]
COP = self.COP(T)
QpunktEv = self.GCCSource['H'][-1]
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
if self.Integrationtype == 'Itterativ':
for i in range(len(self.GCCSink['H'])):
if QpunktKo >= self.GCCSink['H'][i]:
QuelleSenke = i-1
break
self.Tsinkout = self.TKo(QpunktKo,QuelleSenke)
COP = self.COP(T)
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
TSinktest = self.TKo(QpunktKo, QuelleSenke)
while abs(self.Tsinkout - TSinktest) >= 1:
for i in range(len(self.GCCSink['H'])):
if QpunktKo >= self.GCCSink['H'][i]:
QuelleSenke = i-1
break
self.Tsinkout = self.TKo(QpunktKo,QuelleSenke)
COP = self.COP(T)
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
TSinktest = self.TKo(QpunktKo, QuelleSenke)
self.COPwerte.append(COP[0])
self.EvWP.append(round(QpunktEv))
self.KoWP.append(round(QpunktKo))
self.COPT.append(T)
self.COPRegression = COP[1]
table = {'COP':self.COPwerte[::30],'QQuelle':self.EvWP[::30],'QSenke':self.KoWP[::30]}
self.tableISSP = {'Temp': self.COPT, 'COP':self.COPwerte,'QQuelle':self.EvWP,'QSenke':self.KoWP}
print(tabulate(table,headers='keys'))
print({'COP':self.COPwerte[-1],'QQuelle':self.EvWP[-1],'QSenke':self.KoWP[-1]})
def findIntegration(self):#Genaue Integration implementieren!
self.IntegrationPoint = {'Temp': [], 'COP':[],'QQuelle':[],'QSenke':[]}
for i in range(len(self.tableISSP['QSenke'])):
if self.tableISSP['QSenke'][i] >= self.GCCdraw['H'][0]:
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][0]+self.SchrittweiteTemp)
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][i])
self.IntegrationPoint['COP'].append(self.tableISSP['COP'][i])
self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][i])
#self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][self.tableISSP['Temp'].index(self.IntegrationPoint['Temp'][-1])])
self.IntegrationPoint['QSenke'].append(self.tableISSP['QSenke'][i])
break
else:
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][0]+self.SchrittweiteTemp)
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][-1])
self.IntegrationPoint['COP'].append(self.tableISSP['COP'][-1])
self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][-1])
#self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][self.tableISSP['Temp'].index(self.IntegrationPoint['Temp'][-1])])
self.IntegrationPoint['QSenke'].append(self.tableISSP['QSenke'][-1])
break
def IntegrateHeatPump_specific(self, hp_type):
"""Same as IntegrateHeatPump but uses specific heat pump type"""
self.selected_hp_type = hp_type
# Store original COP method
original_COP = self.COP
# Replace COP method temporarily
def COP_wrapper(T):
cop_val = self.COP_specific(T, hp_type)
return (cop_val, hp_type) if cop_val else original_COP(T)
self.COP = COP_wrapper
# Run integration
self.IntegrateHeatPump()
# Restore original method
self.COP = original_COP
def solveforISSP(self):
self.GCCdraw = self.pyPinch.solvePinchforHPI().grandCompositeCurve
self.GCC = self.deleteTemperaturePockets()
self.IntegrateHeatPump()
self.findIntegration()
return self.IntegrationPoint
def HPI(self):
self.GCCdraw = self.pyPinch.solvePinchforHPI().grandCompositeCurve
Temperaturesdraw = []
for i in self.pyPinch.PinchAnalyse._temperatures:
Temperaturesdraw.append(i)
self.deleteTemperaturePockets()
self.GCCSource, self.GCCSink = self.splitHotandCold()
self.IntegrateHeatPump()
self.findIntegration()
HPIPlot(self.streamsDataFile[:-4],self.Tsinkout,self.pyPinch,self.EvWP,self.KoWP,
self.COPwerte,self.COPT,self.GCCdraw, Temperaturesdraw, self.COPRegression).drawCOPKo()
HPIPlot(self.streamsDataFile[:-4],self.Tsinkout,self.pyPinch,self.EvWP,self.KoWP,
self.COPwerte,self.COPT,self.GCCdraw, Temperaturesdraw, self.COPRegression).drawGrandCompositeCurve()