Spaces:
Running
Running
new modules
Browse files- pinch_tool/HPI_main.py +1 -1
- pinch_tool/ISSP_main.py +1 -1
- pinch_tool/Modules/TotalSiteProfile/TotalSiteProfile.py +1 -1
- src/Modules/HeatPumpIntegration/HPIPlot.py +61 -0
- src/Modules/HeatPumpIntegration/HeatPumpIntegration.py +319 -0
- src/Modules/ISSP/ISSP.py +142 -0
- src/Modules/Pinch/Pinch.py +366 -0
- src/Modules/Pinch/PinchExport.py +129 -0
- src/Modules/Pinch/PinchPlot.py +193 -0
- src/Modules/Pinch/Streams.py +105 -0
- src/Modules/Pinch_main.py +53 -0
- src/Modules/TotalSiteProfile/TSPPlot.py +96 -0
- src/Modules/TotalSiteProfile/TotalSiteProfile.py +222 -0
- src/Modules/Utility/TemperaturePocketDeletion.py +280 -0
- src/Modules/Utility/Thermodynamic_Properties.py +21 -0
- src/Modules/Utility/splitStreams.py +105 -0
- src/Modules/__init__.py +0 -0
- src/pages/potential_analysis.py +5 -5
pinch_tool/HPI_main.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from Pinch_main import Pinchmain
|
| 2 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
|
|
|
| 1 |
+
from Modules.Pinch_main import Pinchmain
|
| 2 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
pinch_tool/ISSP_main.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from Pinch_main import Pinchmain
|
| 2 |
from Modules.ISSP.ISSP import ISSP
|
| 3 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 4 |
import matplotlib.pyplot as plt
|
|
|
|
| 1 |
+
from Modules.Pinch_main import Pinchmain
|
| 2 |
from Modules.ISSP.ISSP import ISSP
|
| 3 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 4 |
import matplotlib.pyplot as plt
|
pinch_tool/Modules/TotalSiteProfile/TotalSiteProfile.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
from Pinch_main import Pinchmain as Pinch
|
| 2 |
import csv
|
| 3 |
import ast
|
| 4 |
from Modules.TotalSiteProfile.TSPPlot import TSPPlot
|
|
|
|
| 1 |
+
from Modules.Pinch_main import Pinchmain as Pinch
|
| 2 |
import csv
|
| 3 |
import ast
|
| 4 |
from Modules.TotalSiteProfile.TSPPlot import TSPPlot
|
src/Modules/HeatPumpIntegration/HPIPlot.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from matplotlib import pyplot as plt
|
| 2 |
+
|
| 3 |
+
class HPIPlot():
|
| 4 |
+
def __init__(self, processdesignation, Tsinkout, pyPinch, EvWP, KoWP, COPWerte, COPT, GCCdraw, _temperatures, COPRegression):
|
| 5 |
+
self.processdesignation = processdesignation
|
| 6 |
+
self.grandCompositeCurve = GCCdraw
|
| 7 |
+
self.KoWP = KoWP
|
| 8 |
+
self.EvWP = EvWP
|
| 9 |
+
self.COPWerte = COPWerte
|
| 10 |
+
self.COPT = COPT
|
| 11 |
+
self.Tsinkout = Tsinkout
|
| 12 |
+
self.pyPinch = pyPinch
|
| 13 |
+
self._temperatures = _temperatures
|
| 14 |
+
self.COPRegression = COPRegression
|
| 15 |
+
def drawCOPKo(self):
|
| 16 |
+
self.x = []
|
| 17 |
+
self.y = []
|
| 18 |
+
fig1 = plt.figure()
|
| 19 |
+
for i in self.KoWP[::3]:
|
| 20 |
+
self.x.append(i)
|
| 21 |
+
for i in self.COPWerte[::3]:
|
| 22 |
+
self.y.append(i)
|
| 23 |
+
plt.plot(self.x,self.y)
|
| 24 |
+
plt.grid(True)
|
| 25 |
+
plt.title('COP gegen Qpunkt Ko')#plt.title('Grand Composite Curve')
|
| 26 |
+
plt.xlabel('Qpunkt Ko [kW]')#plt.xlabel('Net Enthalpy Change ∆H (kW)')
|
| 27 |
+
plt.ylabel('COP [-]')#plt.ylabel('Shifted Temperature S (degC)')
|
| 28 |
+
|
| 29 |
+
def drawGrandCompositeCurve(self):
|
| 30 |
+
grandCompositeCurve = self.grandCompositeCurve
|
| 31 |
+
Tempplus = 0
|
| 32 |
+
self.heatCascade = self.pyPinch.heatCascade
|
| 33 |
+
plt.close('all')
|
| 34 |
+
fig = plt.figure()
|
| 35 |
+
if self.heatCascade[0]['deltaH'] > 0:
|
| 36 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [self.grandCompositeCurve['T'][0],self.grandCompositeCurve['T'][1]], 'tab:red')
|
| 37 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [self.grandCompositeCurve['T'][0],self.grandCompositeCurve['T'][1]], 'ro')
|
| 38 |
+
elif self.heatCascade[0]['deltaH'] < 0:
|
| 39 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [self.grandCompositeCurve['T'][0],self.grandCompositeCurve['T'][1]], 'tab:blue')
|
| 40 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [grandCompositeCurve['T'][0],grandCompositeCurve['T'][1]], 'bo')
|
| 41 |
+
|
| 42 |
+
for i in range(1, len(self._temperatures)-1):
|
| 43 |
+
if self.heatCascade[i]['deltaH'] > 0:
|
| 44 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:red')
|
| 45 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'ro')
|
| 46 |
+
elif self.heatCascade[i]['deltaH'] < 0:
|
| 47 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:blue')
|
| 48 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'bo')
|
| 49 |
+
elif self.heatCascade[i]['deltaH'] == 0 and grandCompositeCurve['H'][i]!=0:
|
| 50 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:blue')
|
| 51 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'bo')
|
| 52 |
+
|
| 53 |
+
plt.plot(self.EvWP[-1],self.COPT[-1],'g^')
|
| 54 |
+
plt.plot(self.KoWP[-1],self.Tsinkout,'g^')
|
| 55 |
+
plt.text(0.94*self.KoWP[-1],0.93*self.Tsinkout,round(self.COPWerte[-1],2))
|
| 56 |
+
plt.grid(True)
|
| 57 |
+
name = self.processdesignation
|
| 58 |
+
plt.suptitle('Großverbundkurve {} °C ({})'.format(round(self.Tsinkout,1),name))#plt.title('Grand Composite Curve')
|
| 59 |
+
plt.title(self.COPRegression)
|
| 60 |
+
plt.xlabel('Nettoenthalpiestromänderung ∆H in kW')#plt.xlabel('Net Enthalpy Change ∆H (kW)')
|
| 61 |
+
plt.ylabel('Verschobene Temperatur in °C')#plt.ylabel('Shifted Temperature S (degC)')
|
src/Modules/HeatPumpIntegration/HeatPumpIntegration.py
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tabulate import tabulate
|
| 2 |
+
from Modules.HeatPumpIntegration.HPIPlot import HPIPlot
|
| 3 |
+
from Modules.Utility.TemperaturePocketDeletion import TemperaturePocketDeletion as TPD
|
| 4 |
+
|
| 5 |
+
class HeatPumpIntegration():
|
| 6 |
+
def __init__(self,streamsDataFile, Tsinkout, pyPinch):
|
| 7 |
+
self.Integrationtype = None
|
| 8 |
+
if Tsinkout == None:
|
| 9 |
+
self.Integrationtype = 'Itterativ'
|
| 10 |
+
self.processdesignation = streamsDataFile[:-4]
|
| 11 |
+
self.streamsDataFile = streamsDataFile
|
| 12 |
+
self.options = {'draw', 'debug'}
|
| 13 |
+
self.KoWP = []
|
| 14 |
+
self.EvWP = []
|
| 15 |
+
self.COPwerte = []
|
| 16 |
+
self.COPT = []
|
| 17 |
+
self.SchrittweiteTemp = 0.05
|
| 18 |
+
self.Tsinkout = Tsinkout
|
| 19 |
+
|
| 20 |
+
self.pyPinch = pyPinch
|
| 21 |
+
|
| 22 |
+
def COP(self,T):
|
| 23 |
+
COPList = []
|
| 24 |
+
StringList = []
|
| 25 |
+
if 144 <= self.Tsinkout <= 212 and 25 <= self.Tsinkout-T <= 190: #Prototypical Stirling
|
| 26 |
+
COPList.append(1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992)
|
| 27 |
+
StringList.append('Prototypical Stirling')
|
| 28 |
+
if 80 <= self.Tsinkout <= 160 and 25 <= self.Tsinkout-T <= 95: #VHTHP (HFC/HFO)
|
| 29 |
+
COPList.append(1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895)
|
| 30 |
+
StringList.append('VHTHP (HFC/HFO)')
|
| 31 |
+
if 25 <= self.Tsinkout <= 100 and 10 <= self.Tsinkout-T <= 78: #SHP and HTHPs (HFC/HFO)
|
| 32 |
+
COPList.append(1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469))
|
| 33 |
+
StringList.append('SHP and HTHPs (HFC/HFO)')
|
| 34 |
+
if 70 <= self.Tsinkout <= 85 and 30 <= self.Tsinkout-T <= 75: #SHP and HTHPs (R717)
|
| 35 |
+
COPList.append(40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998)
|
| 36 |
+
StringList.append('SHP and HTHPs (R717)')
|
| 37 |
+
if len(COPList) == 0:
|
| 38 |
+
COPList.append((self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5) # Carnot
|
| 39 |
+
StringList.append('Carnot')
|
| 40 |
+
return max(COPList),StringList[COPList.index(max(COPList))]
|
| 41 |
+
|
| 42 |
+
def get_available_heat_pumps(self, T):
|
| 43 |
+
"""Returns list of all heat pump types with their COPs and availability status"""
|
| 44 |
+
hp_list = []
|
| 45 |
+
delta_T = self.Tsinkout - T
|
| 46 |
+
|
| 47 |
+
# Prototypical Stirling
|
| 48 |
+
if 144 <= self.Tsinkout <= 212 and 25 <= delta_T <= 190:
|
| 49 |
+
cop = 1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992
|
| 50 |
+
hp_list.append({'name': 'Prototypical Stirling', 'cop': cop, 'available': True, 'reason': ''})
|
| 51 |
+
else:
|
| 52 |
+
hp_list.append({'name': 'Prototypical Stirling', 'cop': None, 'available': False,
|
| 53 |
+
'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)'})
|
| 54 |
+
|
| 55 |
+
# VHTHP (HFC/HFO)
|
| 56 |
+
if 80 <= self.Tsinkout <= 160 and 25 <= delta_T <= 95:
|
| 57 |
+
cop = 1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895
|
| 58 |
+
hp_list.append({'name': 'VHTHP (HFC/HFO)', 'cop': cop, 'available': True, 'reason': ''})
|
| 59 |
+
else:
|
| 60 |
+
hp_list.append({'name': 'VHTHP (HFC/HFO)', 'cop': None, 'available': False,
|
| 61 |
+
'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)'})
|
| 62 |
+
|
| 63 |
+
# SHP and HTHPs (HFC/HFO)
|
| 64 |
+
if 25 <= self.Tsinkout <= 100 and 10 <= delta_T <= 78:
|
| 65 |
+
cop = 1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469)
|
| 66 |
+
hp_list.append({'name': 'SHP and HTHPs (HFC/HFO)', 'cop': cop, 'available': True, 'reason': ''})
|
| 67 |
+
else:
|
| 68 |
+
hp_list.append({'name': 'SHP and HTHPs (HFC/HFO)', 'cop': None, 'available': False,
|
| 69 |
+
'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)'})
|
| 70 |
+
|
| 71 |
+
# SHP and HTHPs (R717)
|
| 72 |
+
if 70 <= self.Tsinkout <= 85 and 30 <= delta_T <= 75:
|
| 73 |
+
cop = 40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998
|
| 74 |
+
hp_list.append({'name': 'SHP and HTHPs (R717)', 'cop': cop, 'available': True, 'reason': ''})
|
| 75 |
+
else:
|
| 76 |
+
hp_list.append({'name': 'SHP and HTHPs (R717)', 'cop': None, 'available': False,
|
| 77 |
+
'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)'})
|
| 78 |
+
|
| 79 |
+
# Carnot (always available)
|
| 80 |
+
cop_carnot = (self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5
|
| 81 |
+
hp_list.append({'name': 'Carnot', 'cop': cop_carnot, 'available': True, 'reason': ''})
|
| 82 |
+
|
| 83 |
+
return hp_list
|
| 84 |
+
|
| 85 |
+
def COP_specific(self, T, hp_type):
|
| 86 |
+
"""Calculate COP for a specific heat pump type"""
|
| 87 |
+
if hp_type == 'Prototypical Stirling':
|
| 88 |
+
if 144 <= self.Tsinkout <= 212 and 25 <= self.Tsinkout-T <= 190:
|
| 89 |
+
return 1.28792 * ((self.Tsinkout-(T)) + 2 * 0.54103)**(-0.37606) * (self.Tsinkout+273 + 0.54103)**0.35992
|
| 90 |
+
elif hp_type == 'VHTHP (HFC/HFO)':
|
| 91 |
+
if 80 <= self.Tsinkout <= 160 and 25 <= self.Tsinkout-T <= 95:
|
| 92 |
+
return 1.9118 * ((self.Tsinkout-(T)) + 2 * 0.04419)**(-0.89094) * (self.Tsinkout+273 + 0.04419)**0.67895
|
| 93 |
+
elif hp_type == 'SHP and HTHPs (HFC/HFO)':
|
| 94 |
+
if 25 <= self.Tsinkout <= 100 and 10 <= self.Tsinkout-T <= 78:
|
| 95 |
+
return 1.4480*(10**12) * ((self.Tsinkout-(T)) + 2 * 88.73)**(-4.9469)
|
| 96 |
+
elif hp_type == 'SHP and HTHPs (R717)':
|
| 97 |
+
if 70 <= self.Tsinkout <= 85 and 30 <= self.Tsinkout-T <= 75:
|
| 98 |
+
return 40.789 * ((self.Tsinkout-(T)) + 2 * 1.0305)**(-1.0489) * (self.Tsinkout+273 + 1.0305)**0.29998
|
| 99 |
+
# Fallback to Carnot
|
| 100 |
+
return (self.Tsinkout+273.15)/(self.Tsinkout-T)*0.5
|
| 101 |
+
|
| 102 |
+
def deleteTemperaturePockets(self):
|
| 103 |
+
self.pyPinch = self.pyPinch.PinchAnalyse
|
| 104 |
+
self.hotUtility = self.pyPinch.hotUtility
|
| 105 |
+
self.heatCascade = self.pyPinch.heatCascade
|
| 106 |
+
self._temperatures = self.pyPinch._temperatures
|
| 107 |
+
self.deletedPocketdict = TPD(self.hotUtility, self.heatCascade, self._temperatures).deleteTemperaturePockets()
|
| 108 |
+
|
| 109 |
+
def splitHotandCold(self):
|
| 110 |
+
self.splitHotTemperatures = []
|
| 111 |
+
self.splitColdTemperatures = []
|
| 112 |
+
self.splitHotH = []
|
| 113 |
+
self.splitColdH = []
|
| 114 |
+
testHot = 0
|
| 115 |
+
testCold = 0
|
| 116 |
+
|
| 117 |
+
for i in range(len(self.deletedPocketdict['T'][0])):
|
| 118 |
+
if i >= len(self.deletedPocketdict['deltaH'][0]):
|
| 119 |
+
continue
|
| 120 |
+
if self.deletedPocketdict['deltaH'][0][i] > 0 and testHot == 0:
|
| 121 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i])
|
| 122 |
+
self.splitHotH.append(self.deletedPocketdict['H'][0][i])
|
| 123 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 124 |
+
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
|
| 125 |
+
testHot = 1
|
| 126 |
+
|
| 127 |
+
elif self.deletedPocketdict['deltaH'][0][i] > 0 and testHot == 1:
|
| 128 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 129 |
+
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
|
| 130 |
+
|
| 131 |
+
elif self.deletedPocketdict['deltaH'][0][i] < 0 and testCold == 0:
|
| 132 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i])
|
| 133 |
+
self.splitColdH.append(self.deletedPocketdict['H'][0][i])
|
| 134 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 135 |
+
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
|
| 136 |
+
testCold = 1
|
| 137 |
+
elif self.deletedPocketdict['deltaH'][0][i] < 0 and testCold == 1:
|
| 138 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 139 |
+
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
|
| 140 |
+
elif self.deletedPocketdict['deltaH'][0][i] == 0:
|
| 141 |
+
if self.deletedPocketdict['deltaH'][0][i-1] < 0:
|
| 142 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 143 |
+
self.splitColdH.append(self.deletedPocketdict['H'][0][i+1])
|
| 144 |
+
|
| 145 |
+
elif self.deletedPocketdict['deltaH'][0][i-1] > 0:
|
| 146 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][0][i+1])
|
| 147 |
+
self.splitHotH.append(self.deletedPocketdict['H'][0][i+1])
|
| 148 |
+
else:
|
| 149 |
+
pass
|
| 150 |
+
|
| 151 |
+
else:
|
| 152 |
+
pass
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
self.splitColddeltaH = []
|
| 157 |
+
self.splitHotdeltaH = []
|
| 158 |
+
for i in range(len(self.splitColdH)-1):
|
| 159 |
+
self.splitColddeltaH.append(self.splitColdH[i+1]-self.splitColdH[i])
|
| 160 |
+
|
| 161 |
+
for i in range(len(self.splitHotH)-1):
|
| 162 |
+
self.splitHotdeltaH.append(self.splitHotH[i+1]-self.splitHotH[i])
|
| 163 |
+
|
| 164 |
+
return {'H':self.splitHotH, 'T':self.splitHotTemperatures, 'deltaH':self.splitHotdeltaH},{'H':self.splitColdH, 'T':self.splitColdTemperatures, 'deltaH':self.splitColddeltaH}
|
| 165 |
+
|
| 166 |
+
def QpunktEv(self,T,Quelle): # FEHLER
|
| 167 |
+
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])
|
| 168 |
+
|
| 169 |
+
def QpunktKo(self,T,Quelle):
|
| 170 |
+
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])
|
| 171 |
+
|
| 172 |
+
def TKo(self,H,Quelle):
|
| 173 |
+
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)
|
| 174 |
+
|
| 175 |
+
def IntegrateHeatPump(self):
|
| 176 |
+
Test = 0
|
| 177 |
+
TSTest = 0
|
| 178 |
+
|
| 179 |
+
#Starttemperatur
|
| 180 |
+
if self.Integrationtype == 'Itterativ':
|
| 181 |
+
self.Tsinkout = self.GCCSink['T'][0]
|
| 182 |
+
else:
|
| 183 |
+
pass
|
| 184 |
+
Quelle = 0
|
| 185 |
+
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
|
| 186 |
+
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
|
| 187 |
+
|
| 188 |
+
while T > self.GCCSource['T'][-1]:
|
| 189 |
+
if T <= self.GCCSource['T'][Quelle+1]:
|
| 190 |
+
Quelle +=1
|
| 191 |
+
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
|
| 192 |
+
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
|
| 193 |
+
if self.GCCSource['deltaH'][Quelle] == 0.0:
|
| 194 |
+
Quelle +=1
|
| 195 |
+
self.SchrittweiteTemp = (self.GCCSource['T'][Quelle] - self.GCCSource['T'][Quelle+1])/10
|
| 196 |
+
T = self.GCCSource['T'][Quelle]-self.SchrittweiteTemp
|
| 197 |
+
if T < self.GCCSource['T'][Quelle+1]:
|
| 198 |
+
T = self.GCCSource['T'][Quelle+1]
|
| 199 |
+
COP = self.COP(T)
|
| 200 |
+
QpunktEv = self.QpunktEv(T,Quelle)
|
| 201 |
+
QpunktKo = QpunktEv * ((1-(1/COP[0]))**(-1))
|
| 202 |
+
self.COPwerte.append(round(COP[0],3))
|
| 203 |
+
self.EvWP.append(round(QpunktEv))
|
| 204 |
+
self.KoWP.append(round(QpunktKo))
|
| 205 |
+
self.COPT.append(T)
|
| 206 |
+
for i in range(len(self.GCCSink['T'])):
|
| 207 |
+
if self.GCCSink['T'][i] <= self.Tsinkout:
|
| 208 |
+
KoQuelle = i
|
| 209 |
+
break
|
| 210 |
+
if QpunktKo >= self.QpunktKo(self.Tsinkout, KoQuelle) and self.Integrationtype == None and TSTest == 1 and self.Tsinkout < self.GCCSink['T'][0]:
|
| 211 |
+
break
|
| 212 |
+
if QpunktKo >= self.QpunktKo(self.Tsinkout, KoQuelle) and self.Integrationtype == None and TSTest == 0:
|
| 213 |
+
if self.Tsinkout <= self.GCCSink['T'][0]:
|
| 214 |
+
T+=self.SchrittweiteTemp
|
| 215 |
+
self.SchrittweiteTemp = self.SchrittweiteTemp/200
|
| 216 |
+
TSTest = 1
|
| 217 |
+
else:
|
| 218 |
+
break
|
| 219 |
+
if QpunktKo >= self.GCCSink['H'][0] and Test == 0:
|
| 220 |
+
T+=self.SchrittweiteTemp
|
| 221 |
+
self.SchrittweiteTemp = self.SchrittweiteTemp/200
|
| 222 |
+
Test = 1
|
| 223 |
+
elif QpunktKo >= self.GCCSink['H'][0] and Test == 1:
|
| 224 |
+
break
|
| 225 |
+
T-=self.SchrittweiteTemp
|
| 226 |
+
if T < self.GCCSource['T'][Quelle+1]:
|
| 227 |
+
T = self.GCCSource['T'][Quelle+1]
|
| 228 |
+
|
| 229 |
+
if T <= self.GCCSource['T'][-1]:
|
| 230 |
+
T = self.GCCSource['T'][-1]
|
| 231 |
+
COP = self.COP(T)
|
| 232 |
+
QpunktEv = self.GCCSource['H'][-1]
|
| 233 |
+
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
|
| 234 |
+
if self.Integrationtype == 'Itterativ':
|
| 235 |
+
for i in range(len(self.GCCSink['H'])):
|
| 236 |
+
if QpunktKo >= self.GCCSink['H'][i]:
|
| 237 |
+
QuelleSenke = i-1
|
| 238 |
+
break
|
| 239 |
+
self.Tsinkout = self.TKo(QpunktKo,QuelleSenke)
|
| 240 |
+
COP = self.COP(T)
|
| 241 |
+
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
|
| 242 |
+
TSinktest = self.TKo(QpunktKo, QuelleSenke)
|
| 243 |
+
while abs(self.Tsinkout - TSinktest) >= 1:
|
| 244 |
+
for i in range(len(self.GCCSink['H'])):
|
| 245 |
+
if QpunktKo >= self.GCCSink['H'][i]:
|
| 246 |
+
QuelleSenke = i-1
|
| 247 |
+
break
|
| 248 |
+
self.Tsinkout = self.TKo(QpunktKo,QuelleSenke)
|
| 249 |
+
COP = self.COP(T)
|
| 250 |
+
QpunktKo = QpunktEv * (1-(1/COP[0]))**(-1)
|
| 251 |
+
TSinktest = self.TKo(QpunktKo, QuelleSenke)
|
| 252 |
+
|
| 253 |
+
self.COPwerte.append(COP[0])
|
| 254 |
+
self.EvWP.append(round(QpunktEv))
|
| 255 |
+
self.KoWP.append(round(QpunktKo))
|
| 256 |
+
self.COPT.append(T)
|
| 257 |
+
self.COPRegression = COP[1]
|
| 258 |
+
table = {'COP':self.COPwerte[::30],'QQuelle':self.EvWP[::30],'QSenke':self.KoWP[::30]}
|
| 259 |
+
self.tableISSP = {'Temp': self.COPT, 'COP':self.COPwerte,'QQuelle':self.EvWP,'QSenke':self.KoWP}
|
| 260 |
+
print(tabulate(table,headers='keys'))
|
| 261 |
+
print({'COP':self.COPwerte[-1],'QQuelle':self.EvWP[-1],'QSenke':self.KoWP[-1]})
|
| 262 |
+
|
| 263 |
+
def findIntegration(self):#Genaue Integration implementieren!
|
| 264 |
+
self.IntegrationPoint = {'Temp': [], 'COP':[],'QQuelle':[],'QSenke':[]}
|
| 265 |
+
for i in range(len(self.tableISSP['QSenke'])):
|
| 266 |
+
if self.tableISSP['QSenke'][i] >= self.GCCdraw['H'][0]:
|
| 267 |
+
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][0]+self.SchrittweiteTemp)
|
| 268 |
+
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][i])
|
| 269 |
+
self.IntegrationPoint['COP'].append(self.tableISSP['COP'][i])
|
| 270 |
+
self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][i])
|
| 271 |
+
#self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][self.tableISSP['Temp'].index(self.IntegrationPoint['Temp'][-1])])
|
| 272 |
+
self.IntegrationPoint['QSenke'].append(self.tableISSP['QSenke'][i])
|
| 273 |
+
break
|
| 274 |
+
else:
|
| 275 |
+
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][0]+self.SchrittweiteTemp)
|
| 276 |
+
self.IntegrationPoint['Temp'].append(self.tableISSP['Temp'][-1])
|
| 277 |
+
self.IntegrationPoint['COP'].append(self.tableISSP['COP'][-1])
|
| 278 |
+
self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][-1])
|
| 279 |
+
#self.IntegrationPoint['QQuelle'].append(self.tableISSP['QQuelle'][self.tableISSP['Temp'].index(self.IntegrationPoint['Temp'][-1])])
|
| 280 |
+
self.IntegrationPoint['QSenke'].append(self.tableISSP['QSenke'][-1])
|
| 281 |
+
break
|
| 282 |
+
|
| 283 |
+
def IntegrateHeatPump_specific(self, hp_type):
|
| 284 |
+
"""Same as IntegrateHeatPump but uses specific heat pump type"""
|
| 285 |
+
self.selected_hp_type = hp_type
|
| 286 |
+
# Store original COP method
|
| 287 |
+
original_COP = self.COP
|
| 288 |
+
# Replace COP method temporarily
|
| 289 |
+
def COP_wrapper(T):
|
| 290 |
+
cop_val = self.COP_specific(T, hp_type)
|
| 291 |
+
return (cop_val, hp_type) if cop_val else original_COP(T)
|
| 292 |
+
self.COP = COP_wrapper
|
| 293 |
+
# Run integration
|
| 294 |
+
self.IntegrateHeatPump()
|
| 295 |
+
# Restore original method
|
| 296 |
+
self.COP = original_COP
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def solveforISSP(self):
|
| 300 |
+
self.GCCdraw = self.pyPinch.solvePinchforHPI().grandCompositeCurve
|
| 301 |
+
self.GCC = self.deleteTemperaturePockets()
|
| 302 |
+
self.IntegrateHeatPump()
|
| 303 |
+
self.findIntegration()
|
| 304 |
+
return self.IntegrationPoint
|
| 305 |
+
|
| 306 |
+
def HPI(self):
|
| 307 |
+
self.GCCdraw = self.pyPinch.solvePinchforHPI().grandCompositeCurve
|
| 308 |
+
Temperaturesdraw = []
|
| 309 |
+
for i in self.pyPinch.PinchAnalyse._temperatures:
|
| 310 |
+
Temperaturesdraw.append(i)
|
| 311 |
+
self.deleteTemperaturePockets()
|
| 312 |
+
self.GCCSource, self.GCCSink = self.splitHotandCold()
|
| 313 |
+
self.IntegrateHeatPump()
|
| 314 |
+
self.findIntegration()
|
| 315 |
+
HPIPlot(self.streamsDataFile[:-4],self.Tsinkout,self.pyPinch,self.EvWP,self.KoWP,
|
| 316 |
+
self.COPwerte,self.COPT,self.GCCdraw, Temperaturesdraw, self.COPRegression).drawCOPKo()
|
| 317 |
+
HPIPlot(self.streamsDataFile[:-4],self.Tsinkout,self.pyPinch,self.EvWP,self.KoWP,
|
| 318 |
+
self.COPwerte,self.COPT,self.GCCdraw, Temperaturesdraw, self.COPRegression).drawGrandCompositeCurve()
|
| 319 |
+
|
src/Modules/ISSP/ISSP.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from matplotlib import pyplot as plt
|
| 2 |
+
from Modules.Utility.Thermodynamic_Properties import ThermodynamicProperties as Props
|
| 3 |
+
|
| 4 |
+
class ISSP():
|
| 5 |
+
def __init__(self, streamsDataFile, TS, TProcess, batchtimeSeconds, pyPinch, HPI, fromPinch, intermediateCircuit = {}):
|
| 6 |
+
|
| 7 |
+
self.processdesignation = streamsDataFile[:-4]
|
| 8 |
+
self.streamsDataFile = streamsDataFile
|
| 9 |
+
self.options = {'draw', 'debug'}
|
| 10 |
+
self.fromPinch = bool(fromPinch)
|
| 11 |
+
self.intermediateCircuit = bool(intermediateCircuit)
|
| 12 |
+
self.TS = TS
|
| 13 |
+
self.TProcess = TProcess
|
| 14 |
+
|
| 15 |
+
self.IntegrationPoint = HPI.solveforISSP()
|
| 16 |
+
self.Pinch = pyPinch.solvePinchforISSP()
|
| 17 |
+
self.CC = self.Pinch[0]
|
| 18 |
+
self.pyPinch = self.Pinch[1]
|
| 19 |
+
|
| 20 |
+
self.deltaTmin = self.pyPinch.tmin
|
| 21 |
+
|
| 22 |
+
self.t = batchtimeSeconds/3600
|
| 23 |
+
|
| 24 |
+
def CCinkWh(self):
|
| 25 |
+
for i in range(len(self.CC['hot']['H'])):
|
| 26 |
+
self.CC['hot']['H'][i] = self.CC['hot']['H'][i]*self.t
|
| 27 |
+
self.CC['hot']['kWh'] = self.CC['hot']['H']
|
| 28 |
+
del self.CC['hot']['H']
|
| 29 |
+
|
| 30 |
+
for i in range(len(self.CC['cold']['H'])):
|
| 31 |
+
self.CC['cold']['H'][i] = self.CC['cold']['H'][i]*self.t
|
| 32 |
+
self.CC['cold']['kWh'] = self.CC['cold']['H']
|
| 33 |
+
del self.CC['cold']['H']
|
| 34 |
+
|
| 35 |
+
def ISSPHotIntermediateGerade(self, kWh, Tempdiff):
|
| 36 |
+
return (self.IntegrationPoint['Temp'][-1]-Tempdiff) + ((self.IntegrationPoint['Temp'][0]-self.TemperaturKorrektur) - (self.IntegrationPoint['Temp'][-1]-Tempdiff))/(self.IntegrationPoint['QQuelle'][0]*self.t) * (kWh-self.DifferenzHot)
|
| 37 |
+
|
| 38 |
+
def drawISSPHotIntermediate(self):#Verdichter
|
| 39 |
+
if self.fromPinch == True:
|
| 40 |
+
self.TemperaturKorrektur = 1.25 * self.deltaTmin
|
| 41 |
+
else:
|
| 42 |
+
self.TemperaturKorrektur = 0.25 * self.deltaTmin
|
| 43 |
+
deltaTZwischenlreislauf0 = 2/4 * self.deltaTmin
|
| 44 |
+
self.DifferenzHot = self.CC['hot']['kWh'][-1] - self.IntegrationPoint['QQuelle'][0]*self.t
|
| 45 |
+
self.coldUtility = self.pyPinch.coldUtility*self.t
|
| 46 |
+
self.hotUtility = self.pyPinch.hotUtility*self.t
|
| 47 |
+
self._temperatures = self.pyPinch._temperatures
|
| 48 |
+
self.pinchTemperature = self.pyPinch.pinchTemperature
|
| 49 |
+
m = 0
|
| 50 |
+
for i in range(len(self.CC['hot']['T'])):
|
| 51 |
+
if self.CC['hot']['T'][i] >= self.IntegrationPoint['Temp'][-1]:
|
| 52 |
+
|
| 53 |
+
try: m = self.CC['hot']['T'][i-1] + (self.CC['hot']['T'][i] - self.CC['hot']['T'][i-1])/(self.CC['hot']['kWh'][i] - self.CC['hot']['kWh'][i-1]) * (self.DifferenzHot-self.CC['hot']['kWh'][i-1])
|
| 54 |
+
|
| 55 |
+
except: print('error m') #m = self.CC['hot']['T'][1] + (self.CC['hot']['T'][i+1] - self.CC['hot']['T'][i])/(self.CC['hot']['kWh'][i+1] - self.CC['hot']['kWh'][i]) * (self.IntegrationPoint['QQuelle'][0]*self.t - self.CC['hot']['kWh'][i])
|
| 56 |
+
if m != 0:
|
| 57 |
+
break
|
| 58 |
+
if float(self.DifferenzHot) == 0.0 and float(self.CC['hot']['kWh'][-2]) == 0.0:
|
| 59 |
+
ZwischenkreislaufTemp = self.CC['hot']['T'][-1] - deltaTZwischenlreislauf0
|
| 60 |
+
else:
|
| 61 |
+
ZwischenkreislaufTemp = (self.CC['hot']['T'][-2] - deltaTZwischenlreislauf0) + (self.CC['hot']['T'][-2] - m) / (self.CC['hot']['kWh'][-2] - self.DifferenzHot) * (self.CC['hot']['kWh'][-1] -self.CC['hot']['kWh'][-2])
|
| 62 |
+
self.TemperaturKorrektur = (self.CC['hot']['T'][-2] - self.TemperaturKorrektur) + (self.CC['hot']['T'][-2] - m) / (self.CC['hot']['kWh'][-2] - self.DifferenzHot) * (self.CC['hot']['kWh'][-1] -self.CC['hot']['kWh'][-2])
|
| 63 |
+
|
| 64 |
+
self.VolumenWWSpeicher = round(self.IntegrationPoint['QQuelle'][0]*self.t * 3600 / (4.18 * (ZwischenkreislaufTemp-(m-deltaTZwischenlreislauf0)))/1000,1) #m^3
|
| 65 |
+
plt.close('all')
|
| 66 |
+
fig = plt.figure(num='{} Verd'.format(self.processdesignation))
|
| 67 |
+
if self.intermediateCircuit == True:
|
| 68 |
+
plt.plot(self.CC['hot']['kWh'], self.CC['hot']['T'], 'tab:red')
|
| 69 |
+
plt.plot([self.DifferenzHot,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self.IntegrationPoint['Temp'][-1]-1.25*self.deltaTmin,+self.TemperaturKorrektur], 'tab:blue')
|
| 70 |
+
plt.plot([self.DifferenzHot,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [m-deltaTZwischenlreislauf0,ZwischenkreislaufTemp], 'k')
|
| 71 |
+
|
| 72 |
+
#plt.plot(self.CC['hot']['kWh'], self.CC['hot']['T'], 'ro')
|
| 73 |
+
plt.plot([self.DifferenzHot,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self.IntegrationPoint['Temp'][-1]-1.25*self.deltaTmin,self.TemperaturKorrektur], 'bo')
|
| 74 |
+
plt.plot([self.DifferenzHot,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot],[(m-deltaTZwischenlreislauf0),ZwischenkreislaufTemp],'ko')
|
| 75 |
+
elif self.fromPinch == False:
|
| 76 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self._temperatures[-1]+0.5*self.deltaTmin,ZwischenkreislaufTemp-self.deltaTmin], 'tab:red')
|
| 77 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self._temperatures[-1]+0.25*self.deltaTmin,self._temperatures[-1]+0.25*self.deltaTmin])#,self.TemperaturKorrektur], 'tab:blue')
|
| 78 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self._temperatures[-1]+0.5*self.deltaTmin,ZwischenkreislaufTemp-self.deltaTmin],linestyle = (0, (5, 10)), color = 'black')
|
| 79 |
+
|
| 80 |
+
#plt.plot(self.CC['hot']['kWh'], self.CC['hot']['T'], 'ro')
|
| 81 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self._temperatures[-1]+0.25*self.deltaTmin,self._temperatures[-1]+0.25*self.deltaTmin], 'bo') #self.TemperaturKorrektur
|
| 82 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot],[self._temperatures[-1]+0.5*self.deltaTmin,ZwischenkreislaufTemp-self.deltaTmin],'ko')
|
| 83 |
+
elif self.fromPinch == True:
|
| 84 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [m-deltaTZwischenlreislauf0,ZwischenkreislaufTemp], 'tab:red')
|
| 85 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self._temperatures[-1]+0.25*self.deltaTmin,self._temperatures[-1]+0.25*self.deltaTmin])#,self.TemperaturKorrektur], 'tab:blue')
|
| 86 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [m-deltaTZwischenlreislauf0,ZwischenkreislaufTemp],linestyle = (0, (5, 10)), color = 'black')
|
| 87 |
+
|
| 88 |
+
#plt.plot(self.CC['hot']['kWh'], self.CC['hot']['T'], 'ro')
|
| 89 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot], [self.IntegrationPoint['Temp'][-1]-1.25*self.deltaTmin,self.IntegrationPoint['Temp'][-1]-1.25*self.deltaTmin], 'bo') #self.TemperaturKorrektur
|
| 90 |
+
plt.plot([0,self.IntegrationPoint['QQuelle'][0]*self.t+self.DifferenzHot],[(m-deltaTZwischenlreislauf0),ZwischenkreislaufTemp],'ko')
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
plt.grid(True,linewidth=1.5)
|
| 94 |
+
plt.tick_params(axis='both', which='major', labelsize=12)
|
| 95 |
+
plt.title('a) ISSP stratified TES', fontsize=14)
|
| 96 |
+
plt.xlabel('ΔH / Batch in kWh', fontsize=14)
|
| 97 |
+
plt.ylabel('Shifted temperature T in °C', fontsize=14)
|
| 98 |
+
|
| 99 |
+
def drawISSPColdIntermediate(self):
|
| 100 |
+
deltaTZwischenkreislauf = 3/4 * self.deltaTmin
|
| 101 |
+
if self.fromPinch == True:
|
| 102 |
+
Verschiebung = 1.25 * self.deltaTmin
|
| 103 |
+
Verschiebung2 = 1.25 * self.deltaTmin
|
| 104 |
+
else:
|
| 105 |
+
Verschiebung = 0.25 * self.deltaTmin
|
| 106 |
+
Verschiebung2 = 0.25 * self.deltaTmin
|
| 107 |
+
self.Dampfmasse = (self.IntegrationPoint['QSenke'][0]*self.t * 3600)/Props.get_latentheat(self.TS)
|
| 108 |
+
#vStrich1 = 1/925.014712422 #140 °C
|
| 109 |
+
h1_prime = Props.get_hprime(self.TS)
|
| 110 |
+
h1_double_prime = Props.get_hdouble_prime(self.TS)
|
| 111 |
+
v1_prime = Props.get_vprime(self.TS)
|
| 112 |
+
h2_prime = Props.get_hprime(self.TProcess)
|
| 113 |
+
h2_double_prime = Props.get_hdouble_prime(self.TProcess)
|
| 114 |
+
|
| 115 |
+
Füllgrad = 0.9
|
| 116 |
+
self.VolumenDampfSpeicher = round(self.Dampfmasse/ ((Füllgrad/v1_prime)*((h1_prime-h2_prime)/(0.5*(h1_double_prime+h2_double_prime)-h2_prime))),1)
|
| 117 |
+
#http://berndglueck.de/Waermespeicher
|
| 118 |
+
|
| 119 |
+
fig = plt.figure(num='{} Kond'.format(self.processdesignation))
|
| 120 |
+
if self.intermediateCircuit == True:
|
| 121 |
+
plt.plot([self.CC['cold']['kWh'][-1],self.IntegrationPoint['QSenke'][0]*self.t+self.CC['cold']['kWh'][-1]], [self.CC['cold']['T'][-1]+Verschiebung,self.CC['cold']['T'][0]+Verschiebung], 'tab:red')
|
| 122 |
+
plt.plot(self.CC['cold']['kWh'], self.CC['cold']['T'], 'tab:blue')
|
| 123 |
+
plt.plot([self.CC['cold']['kWh'][-1],self.IntegrationPoint['QSenke'][0]*self.t+self.CC['cold']['kWh'][-1]], [self.CC['cold']['T'][-1]+Verschiebung-deltaTZwischenkreislauf,self.CC['cold']['T'][0]+Verschiebung-deltaTZwischenkreislauf], 'k')
|
| 124 |
+
|
| 125 |
+
plt.plot([self.CC['cold']['kWh'][-1],self.IntegrationPoint['QSenke'][0]*self.t+self.CC['cold']['kWh'][-1]], [self.CC['cold']['T'][-1]+Verschiebung,self.CC['cold']['T'][0]+Verschiebung], 'ro')
|
| 126 |
+
plt.plot(self.CC['cold']['kWh'], self.CC['cold']['T'], 'bo')
|
| 127 |
+
plt.plot([self.CC['cold']['kWh'][-1],self.IntegrationPoint['QSenke'][0]*self.t+self.CC['cold']['kWh'][-1]], [self.CC['cold']['T'][-1]+Verschiebung-deltaTZwischenkreislauf,self.CC['cold']['T'][0]+Verschiebung-deltaTZwischenkreislauf], 'ko')
|
| 128 |
+
else:
|
| 129 |
+
plt.plot([0,self.IntegrationPoint['QSenke'][0]*self.t], [self.CC['cold']['T'][0]+Verschiebung2,self.CC['cold']['T'][0]+Verschiebung2], 'tab:red')
|
| 130 |
+
plt.plot([0,self.IntegrationPoint['QSenke'][0]*self.t], [self.CC['cold']['T'][-1]+Verschiebung-deltaTZwischenkreislauf,self.CC['cold']['T'][0]+Verschiebung-deltaTZwischenkreislauf], 'tab:blue')
|
| 131 |
+
plt.plot([0,self.IntegrationPoint['QSenke'][0]*self.t], [self.CC['cold']['T'][-1]+Verschiebung-deltaTZwischenkreislauf,self.CC['cold']['T'][0]+Verschiebung-deltaTZwischenkreislauf],linestyle = (0, (5, 10)), color = 'black')
|
| 132 |
+
|
| 133 |
+
plt.plot([0,self.IntegrationPoint['QSenke'][0]*self.t], [self.CC['cold']['T'][0]+Verschiebung2,self.CC['cold']['T'][0]+Verschiebung2], 'ro')
|
| 134 |
+
#plt.plot(self.CC['cold']['kWh'], self.CC['cold']['T'], 'bo')
|
| 135 |
+
plt.plot([0,self.IntegrationPoint['QSenke'][0]*self.t], [self.CC['cold']['T'][-1]+Verschiebung-deltaTZwischenkreislauf,self.CC['cold']['T'][0]+Verschiebung-deltaTZwischenkreislauf], 'ko')
|
| 136 |
+
|
| 137 |
+
plt.grid(True,linewidth=1.5)
|
| 138 |
+
plt.tick_params(axis='both', which='major', labelsize=12)
|
| 139 |
+
plt.title('b) ISSP steam RSA', fontsize=14)
|
| 140 |
+
plt.xlabel('ΔH / Batch in kWh', fontsize=14)
|
| 141 |
+
plt.xlim(right = 2500)
|
| 142 |
+
plt.ylabel('Shifted temperature T in °C', fontsize=14)
|
src/Modules/Pinch/Pinch.py
ADDED
|
@@ -0,0 +1,366 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#Based on:
|
| 2 |
+
#!/usr/bin/env python3
|
| 3 |
+
# -*- coding: utf-8 -*-
|
| 4 |
+
# File : PyPinch.py
|
| 5 |
+
# License : License: GNU v3.0
|
| 6 |
+
# Author : Andrei Leonard Nicusan <aln705@student.bham.ac.uk>
|
| 7 |
+
# Date : 25.05.2019
|
| 8 |
+
|
| 9 |
+
import csv
|
| 10 |
+
import os
|
| 11 |
+
import numpy as np
|
| 12 |
+
from Modules.Pinch.Streams import Streams
|
| 13 |
+
from Modules.Pinch.PinchPlot import PinchPlot
|
| 14 |
+
from Modules.Pinch.PinchExport import PinchExport
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class Pinch:
|
| 18 |
+
|
| 19 |
+
def __init__(self, streamsDataFile, options = {}):
|
| 20 |
+
|
| 21 |
+
self.tmin = 0
|
| 22 |
+
self.streams = []
|
| 23 |
+
self.temperatureInterval = []
|
| 24 |
+
self.problemTable = []
|
| 25 |
+
self.hotUtility = 0
|
| 26 |
+
self.coldUtility = 0
|
| 27 |
+
self.unfeasibleHeatCascade = []
|
| 28 |
+
self.heatCascade = []
|
| 29 |
+
self.pinchTemperature = 0
|
| 30 |
+
self.shiftedCompositeDiagram = {'hot': {'H': [], 'T': []}, 'cold': {'H': [], 'T': []}}
|
| 31 |
+
self.compositeDiagram = {'hot': {'H': [], 'T': []}, 'cold': {'H': [], 'T': []}}
|
| 32 |
+
self.grandCompositeCurve = {'H': [], 'T': []}
|
| 33 |
+
|
| 34 |
+
self._temperatures = []
|
| 35 |
+
self._deltaHHot = []
|
| 36 |
+
self._deltaHCold = []
|
| 37 |
+
self._options = {'debug': False, 'draw': False, 'csv': False}
|
| 38 |
+
self._temperaturesHOT= []
|
| 39 |
+
self._temperaturesCOLD = []
|
| 40 |
+
self.emptyintervalstartHOT= []
|
| 41 |
+
self.emptyintervalstartCOLD = []
|
| 42 |
+
self.lastHotStream = 0
|
| 43 |
+
self.lastColdStream = 0
|
| 44 |
+
|
| 45 |
+
self.emptyintervalsHot = {'H': [], 'T': []}
|
| 46 |
+
self.emptyintervalsCold = {'H': [], 'T': []}
|
| 47 |
+
|
| 48 |
+
self.processdesignation = streamsDataFile[:-4]
|
| 49 |
+
path = r"{} Pinch".format(self.processdesignation)
|
| 50 |
+
self.newpath = 'Output'+ '\\' + path
|
| 51 |
+
|
| 52 |
+
self.streams = Streams(streamsDataFile)
|
| 53 |
+
self.tmin = self.streams.tmin
|
| 54 |
+
|
| 55 |
+
if 'debug' in options:
|
| 56 |
+
self._options['debug'] = True
|
| 57 |
+
if 'draw' in options:
|
| 58 |
+
self._options['draw'] = True
|
| 59 |
+
if 'csv' in options:
|
| 60 |
+
self._options['csv'] = True
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def shiftTemperatures(self):
|
| 64 |
+
for stream in self.streams:
|
| 65 |
+
if stream['type'] == 'HOT':
|
| 66 |
+
stream['ss'] = stream['ts'] - self.tmin / 2
|
| 67 |
+
stream['st'] = stream['tt'] - self.tmin / 2
|
| 68 |
+
else:
|
| 69 |
+
stream['ss'] = stream['ts'] + self.tmin / 2
|
| 70 |
+
stream['st'] = stream['tt'] + self.tmin / 2
|
| 71 |
+
|
| 72 |
+
if self._options['debug'] == True:
|
| 73 |
+
print("\nStreams: ")
|
| 74 |
+
for stream in self.streams:
|
| 75 |
+
print(stream)
|
| 76 |
+
print("Tmin = {}".format(self.tmin))
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def constructTemperatureInterval(self):
|
| 80 |
+
# Take all shifted temperatures and reverse sort them,
|
| 81 |
+
# removing all duplicates
|
| 82 |
+
for stream in self.streams:
|
| 83 |
+
self._temperatures.append(stream['ss'])
|
| 84 |
+
self._temperatures.append(stream['st'])
|
| 85 |
+
|
| 86 |
+
if (stream["type"] == "HOT"):
|
| 87 |
+
self._temperaturesHOT.append(stream['ss'])
|
| 88 |
+
self._temperaturesHOT.append(stream['st'])
|
| 89 |
+
|
| 90 |
+
else:
|
| 91 |
+
self._temperaturesCOLD.append(stream['ss'])
|
| 92 |
+
self._temperaturesCOLD.append(stream['st'])
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
self._temperaturesHOT = list(set(self._temperaturesHOT))
|
| 96 |
+
self._temperaturesHOT.sort()
|
| 97 |
+
self._temperaturesCOLD = list(set(self._temperaturesCOLD))
|
| 98 |
+
self._temperaturesCOLD.sort()
|
| 99 |
+
self._temperatures = list(set(self._temperatures))
|
| 100 |
+
self._temperatures.sort(reverse = True)
|
| 101 |
+
|
| 102 |
+
# Save the stream number of all the streams that pass
|
| 103 |
+
# through each shifted temperature interval
|
| 104 |
+
for i in range(len(self._temperatures) - 1):
|
| 105 |
+
t1 = self._temperatures[i]
|
| 106 |
+
t2 = self._temperatures[i + 1]
|
| 107 |
+
interval = {'t1': t1, 't2': t2, 'streamNumbers': []}
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
j = 0
|
| 111 |
+
for stream in self.streams:
|
| 112 |
+
if (stream['type'] == 'HOT'):
|
| 113 |
+
if (stream['ss'] >= t1 and stream['st'] <= t2):
|
| 114 |
+
interval['streamNumbers'].append(j)
|
| 115 |
+
else:
|
| 116 |
+
if (stream['st'] >= t1 and stream['ss'] <= t2):
|
| 117 |
+
interval['streamNumbers'].append(j)
|
| 118 |
+
j = j + 1
|
| 119 |
+
|
| 120 |
+
self.temperatureInterval.append(interval)
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
if self._options['debug'] == True:
|
| 125 |
+
print("\nTemperature Intervals: ")
|
| 126 |
+
i = 0
|
| 127 |
+
print(self._temperatures)
|
| 128 |
+
for interval in self.temperatureInterval:
|
| 129 |
+
print("Interval {} : {}".format(i, interval))
|
| 130 |
+
i = i + 1
|
| 131 |
+
|
| 132 |
+
if self._options['draw'] == True:
|
| 133 |
+
PinchPlot().drawTemperatureInterval(self._temperatures, self.streams)
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def constructProblemTable(self):
|
| 138 |
+
|
| 139 |
+
for interval in self.temperatureInterval:
|
| 140 |
+
row = {}
|
| 141 |
+
row['deltaS'] = interval['t1'] - interval['t2']
|
| 142 |
+
row['deltaCP'] = 0
|
| 143 |
+
|
| 144 |
+
for i in interval['streamNumbers']:
|
| 145 |
+
if interval['streamNumbers'] != []:
|
| 146 |
+
if self.streams.streamsData[i]['type'] == 'HOT':
|
| 147 |
+
row['deltaCP'] = row['deltaCP'] + self.streams.streamsData[i]['cp']
|
| 148 |
+
else:
|
| 149 |
+
row['deltaCP'] = row['deltaCP'] - self.streams.streamsData[i]['cp']
|
| 150 |
+
else:
|
| 151 |
+
row['deltaCP'] = 0
|
| 152 |
+
|
| 153 |
+
row['deltaH'] = row['deltaS'] * row['deltaCP']
|
| 154 |
+
self.problemTable.append(row)
|
| 155 |
+
|
| 156 |
+
if self._options['debug'] == True:
|
| 157 |
+
print("\nProblem Table: ")
|
| 158 |
+
i = 0
|
| 159 |
+
for interval in self.problemTable:
|
| 160 |
+
print("Interval {} : {}".format(i, interval))
|
| 161 |
+
i = i + 1
|
| 162 |
+
|
| 163 |
+
if self._options['draw'] == True:
|
| 164 |
+
PinchPlot().drawProblemTable(self.problemTable, self._temperatures)
|
| 165 |
+
|
| 166 |
+
if self._options['csv'] == True:
|
| 167 |
+
PinchExport().csvProblemTable(self.problemTable, self._temperatures, self.newpath)
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def constructHeatCascade(self):
|
| 171 |
+
|
| 172 |
+
exitH = 0
|
| 173 |
+
lowestExitH = 0
|
| 174 |
+
|
| 175 |
+
i = 0
|
| 176 |
+
pinchInterval = 0
|
| 177 |
+
for interval in self.problemTable:
|
| 178 |
+
row = {}
|
| 179 |
+
row['deltaH'] = interval['deltaH']
|
| 180 |
+
|
| 181 |
+
exitH = exitH + row['deltaH']
|
| 182 |
+
row['exitH'] = exitH
|
| 183 |
+
if exitH < lowestExitH:
|
| 184 |
+
lowestExitH = exitH
|
| 185 |
+
pinchInterval = i
|
| 186 |
+
|
| 187 |
+
self.unfeasibleHeatCascade.append(row)
|
| 188 |
+
i = i + 1
|
| 189 |
+
|
| 190 |
+
self.hotUtility = -lowestExitH
|
| 191 |
+
exitH = self.hotUtility
|
| 192 |
+
|
| 193 |
+
for interval in self.problemTable:
|
| 194 |
+
row = {}
|
| 195 |
+
row['deltaH'] = interval['deltaH']
|
| 196 |
+
|
| 197 |
+
exitH = exitH + row['deltaH']
|
| 198 |
+
row['exitH'] = exitH
|
| 199 |
+
|
| 200 |
+
self.heatCascade.append(row)
|
| 201 |
+
|
| 202 |
+
self.coldUtility = exitH
|
| 203 |
+
if pinchInterval == 0:
|
| 204 |
+
self.pinchTemperature = self.temperatureInterval[pinchInterval]['t2']
|
| 205 |
+
else:
|
| 206 |
+
self.pinchTemperature = self.temperatureInterval[pinchInterval]['t2']
|
| 207 |
+
|
| 208 |
+
if self._options['debug'] == True:
|
| 209 |
+
print("\nUnfeasible Heat Cascade: ")
|
| 210 |
+
i = 0
|
| 211 |
+
for interval in self.unfeasibleHeatCascade:
|
| 212 |
+
print("Interval {} : {}".format(i, interval))
|
| 213 |
+
i = i + 1
|
| 214 |
+
|
| 215 |
+
print("\nFeasible Heat Cascade: ")
|
| 216 |
+
i = 0
|
| 217 |
+
for interval in self.heatCascade:
|
| 218 |
+
print("Interval {} : {}".format(i, interval))
|
| 219 |
+
i = i + 1
|
| 220 |
+
|
| 221 |
+
print("\nPinch Temperature (degC): {}".format(self.pinchTemperature))
|
| 222 |
+
print("Minimum Hot Utility (kW): {}".format(self.hotUtility))
|
| 223 |
+
print("Minimum Cold Utility (kW): {}".format(self.coldUtility))
|
| 224 |
+
|
| 225 |
+
if self._options['draw'] == True:
|
| 226 |
+
PinchPlot().drawHeatCascade(self.unfeasibleHeatCascade, self.heatCascade, self.hotUtility)
|
| 227 |
+
|
| 228 |
+
if self._options['csv'] == True:
|
| 229 |
+
PinchExport().csvHeatCascade(self.unfeasibleHeatCascade, self.hotUtility, self.heatCascade, self.pinchTemperature, self.newpath)
|
| 230 |
+
|
| 231 |
+
|
| 232 |
+
def constructShiftedCompositeDiagram(self, localisation):
|
| 233 |
+
emptylist = []
|
| 234 |
+
for interval in self.temperatureInterval:
|
| 235 |
+
hotH = 0
|
| 236 |
+
coldH = 0
|
| 237 |
+
# Add CP values for the hot and cold streams
|
| 238 |
+
# in a given temperature interval
|
| 239 |
+
for i in interval['streamNumbers']:
|
| 240 |
+
if interval['streamNumbers'] != []:
|
| 241 |
+
if self.streams.streamsData[i]['type'] == 'HOT':
|
| 242 |
+
hotH = hotH + self.streams.streamsData[i]['cp']
|
| 243 |
+
#self.shiftedCompositeDiagram['hot']['T'].append(self.streamsData[i]['ss'])
|
| 244 |
+
#self.shiftedCompositeDiagram['hot']['T'].append(self.streamsData[i]['st'])
|
| 245 |
+
else:
|
| 246 |
+
coldH = coldH + self.streams.streamsData[i]['cp']
|
| 247 |
+
#self.shiftedCompositeDiagram['cold']['T'].append(self.streamsData[i]['ss'])
|
| 248 |
+
#self.shiftedCompositeDiagram['cold']['T'].append(self.streamsData[i]['st'])
|
| 249 |
+
else:
|
| 250 |
+
hotH = 0
|
| 251 |
+
emptylist.append(i)
|
| 252 |
+
# Enthalpy = CP * deltaT
|
| 253 |
+
#checken ob geprüftes interval einen heißen strom enthält und erst dann anfangen
|
| 254 |
+
#dann immer wieder prüfen, ob danach noch ein heoßer strom kommt
|
| 255 |
+
|
| 256 |
+
hotH = hotH * (interval['t1'] - interval['t2'])
|
| 257 |
+
self._deltaHHot.append(hotH)
|
| 258 |
+
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
coldH = coldH * (interval['t1'] - interval['t2'])
|
| 262 |
+
self._deltaHCold.append(coldH)
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
# rot bei 0/t1 anfangen
|
| 266 |
+
# blau bei coldutility/t2 anfangen
|
| 267 |
+
self.shiftedCompositeDiagram['hot']['T']= []
|
| 268 |
+
|
| 269 |
+
self._deltaHHot.reverse()
|
| 270 |
+
self.shiftedCompositeDiagram['hot']['H'].append(0.0)
|
| 271 |
+
for i in range(1, len(self._temperatures)):
|
| 272 |
+
self.shiftedCompositeDiagram['hot']['H'].append(self.shiftedCompositeDiagram['hot']['H'][-1] + self._deltaHHot[i-1])
|
| 273 |
+
self.shiftedCompositeDiagram['hot']['T'].append(self._temperatures[len(self._temperatures)-i])
|
| 274 |
+
|
| 275 |
+
|
| 276 |
+
self.shiftedCompositeDiagram['hot']['T'].append(self._temperatures[0])
|
| 277 |
+
#Summe aus allen deltaHCold + coldutility machen und für die Schritte jeweils deltaHCold abziehen
|
| 278 |
+
coldgesamt = self.coldUtility
|
| 279 |
+
for i in range(len(self._deltaHCold)):
|
| 280 |
+
coldgesamt += self._deltaHCold[i]
|
| 281 |
+
|
| 282 |
+
#Experimentell
|
| 283 |
+
self.shiftedCompositeDiagram['cold']['T']= []
|
| 284 |
+
|
| 285 |
+
self.shiftedCompositeDiagram['cold']['H'].append(coldgesamt)
|
| 286 |
+
|
| 287 |
+
#Experimentell
|
| 288 |
+
self.shiftedCompositeDiagram['cold']['T'].append(self._temperatures[0])
|
| 289 |
+
for i in range(1, len(self._temperatures)):
|
| 290 |
+
self.shiftedCompositeDiagram['cold']['H'].append(self.shiftedCompositeDiagram['cold']['H'][-1] - self._deltaHCold[i-1])
|
| 291 |
+
self.shiftedCompositeDiagram['cold']['T'].append(self._temperatures[i])
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
iliste = []
|
| 295 |
+
for i in range(1,(len(self.shiftedCompositeDiagram['cold']['H'])-1)):
|
| 296 |
+
if self.shiftedCompositeDiagram['cold']['H'] == 0.0:
|
| 297 |
+
iliste.append(i+1)
|
| 298 |
+
elif self.shiftedCompositeDiagram['cold']['H'][i] == self.shiftedCompositeDiagram['cold']['H'][0]:
|
| 299 |
+
iliste.append(i-1)
|
| 300 |
+
elif self.shiftedCompositeDiagram['cold']['H'][i] == self.shiftedCompositeDiagram['cold']['H'][-1]:
|
| 301 |
+
iliste.append(i+1)
|
| 302 |
+
iliste.reverse()
|
| 303 |
+
|
| 304 |
+
for i in iliste:
|
| 305 |
+
self.shiftedCompositeDiagram['cold']['H'].pop(i)
|
| 306 |
+
self.shiftedCompositeDiagram['cold']['T'].pop(i)
|
| 307 |
+
iliste = []
|
| 308 |
+
for i in range(1,(len(self.shiftedCompositeDiagram['hot']['H'])-1)):
|
| 309 |
+
if self.shiftedCompositeDiagram['hot']['H'][i] == 0.0:
|
| 310 |
+
iliste.append(i-1)
|
| 311 |
+
elif self.shiftedCompositeDiagram['hot']['H'][i] == self.shiftedCompositeDiagram['hot']['H'][-1]:
|
| 312 |
+
iliste.append(i+1)
|
| 313 |
+
iliste.reverse()
|
| 314 |
+
|
| 315 |
+
for i in iliste:
|
| 316 |
+
self.shiftedCompositeDiagram['hot']['H'].pop(i)
|
| 317 |
+
self.shiftedCompositeDiagram['hot']['T'].pop(i)
|
| 318 |
+
|
| 319 |
+
if self._options['draw'] == True:
|
| 320 |
+
PinchPlot().drawShiftedCompositeDiagram(self.shiftedCompositeDiagram, self.coldUtility,
|
| 321 |
+
self._temperatures, self.hotUtility, self.pinchTemperature,
|
| 322 |
+
self.processdesignation, localisation)
|
| 323 |
+
|
| 324 |
+
if self._options['csv'] == True:
|
| 325 |
+
PinchExport().csvShiftedCompositeDiagram(self.newpath, self.shiftedCompositeDiagram)
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
|
| 329 |
+
def constructCompositeDiagram(self, localisation):
|
| 330 |
+
self.compositeDiagram['hot']['T'] = [x + self.tmin / 2 for x in self.shiftedCompositeDiagram['hot']['T']]
|
| 331 |
+
self.compositeDiagram['hot']['H'] = self.shiftedCompositeDiagram['hot']['H']
|
| 332 |
+
self.compositeDiagram['cold']['T'] = [x - self.tmin / 2 for x in self.shiftedCompositeDiagram['cold']['T']]
|
| 333 |
+
self.compositeDiagram['cold']['H'] = self.shiftedCompositeDiagram['cold']['H']
|
| 334 |
+
print(self._temperatures)
|
| 335 |
+
if self._options['draw'] == True:
|
| 336 |
+
PinchPlot().drawCompositeDiagram(self.compositeDiagram, self.shiftedCompositeDiagram,
|
| 337 |
+
self.coldUtility, self._temperatures, self.tmin, self.hotUtility,
|
| 338 |
+
self.pinchTemperature, self.processdesignation, localisation)
|
| 339 |
+
|
| 340 |
+
if self._options['csv'] == True:
|
| 341 |
+
PinchExport().csvCompositeDiagram(self.newpath, self.compositeDiagram)
|
| 342 |
+
|
| 343 |
+
|
| 344 |
+
|
| 345 |
+
def constructGrandCompositeCurve(self,localisation):
|
| 346 |
+
self.grandCompositeCurve['H'].append(self.hotUtility)
|
| 347 |
+
self.grandCompositeCurve['T'].append(self._temperatures[0])
|
| 348 |
+
for i in range(1, len(self._temperatures)):
|
| 349 |
+
self.grandCompositeCurve['H'].append(self.heatCascade[i - 1]['exitH'])
|
| 350 |
+
self.grandCompositeCurve['T'].append(self._temperatures[i])
|
| 351 |
+
print(self.grandCompositeCurve)
|
| 352 |
+
print(self.heatCascade)
|
| 353 |
+
|
| 354 |
+
if self._options['debug'] == True:
|
| 355 |
+
print("\nGrand Composite Curve: ")
|
| 356 |
+
print("Net H (kW): {}".format(self.grandCompositeCurve['H']))
|
| 357 |
+
print("T (degC): {}".format(self.grandCompositeCurve['T']))
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
if self._options['draw'] == True:
|
| 361 |
+
PinchPlot().drawGrandCompositeCurve(self.processdesignation, self.heatCascade,
|
| 362 |
+
self.grandCompositeCurve, self._temperatures, self.pinchTemperature, localisation)
|
| 363 |
+
|
| 364 |
+
if self._options['csv'] == True:
|
| 365 |
+
PinchExport().csvGrandCompositeCurve(self.newpath, self.grandCompositeCurve)
|
| 366 |
+
|
src/Modules/Pinch/PinchExport.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import csv
|
| 3 |
+
|
| 4 |
+
class PinchExport:
|
| 5 |
+
def __init__(self):
|
| 6 |
+
pass
|
| 7 |
+
def csvProblemTable(self, problemTable, _temperatures, newpath):
|
| 8 |
+
colLabels = ['$Interval: S_i - S_{i+1}$', '$\\Delta T (\\degree C)$', '$\\Delta CP (kW / \\degree C)$', '$\\Delta H (kW)$', '']
|
| 9 |
+
cellText = []
|
| 10 |
+
|
| 11 |
+
i = 1
|
| 12 |
+
for interval in problemTable:
|
| 13 |
+
cellRow = []
|
| 14 |
+
cellRow.extend(['{}: {} - {}'.format(i, _temperatures[i - 1], _temperatures[i]),
|
| 15 |
+
interval['deltaS'], interval['deltaCP'], interval['deltaH']])
|
| 16 |
+
|
| 17 |
+
if interval['deltaH'] > 0:
|
| 18 |
+
cellRow.append('Surplus')
|
| 19 |
+
elif interval['deltaH'] == 0:
|
| 20 |
+
cellRow.append('-')
|
| 21 |
+
else:
|
| 22 |
+
cellRow.append('Deficit')
|
| 23 |
+
cellText.append(cellRow)
|
| 24 |
+
i = i + 1
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
if not os.path.exists(newpath):
|
| 28 |
+
os.makedirs(newpath)
|
| 29 |
+
fileName = 'ProblemTable.csv'
|
| 30 |
+
|
| 31 |
+
path = os.path.join(newpath, fileName)
|
| 32 |
+
with open(path, 'w', newline='') as f:
|
| 33 |
+
writer = csv.writer(f, delimiter=',')
|
| 34 |
+
writer.writerow(['Interval: S1 - S2', 'delta T (degC)', 'delta CP (kW / degC)', 'delta H (kW)', ''])
|
| 35 |
+
for rowText in cellText:
|
| 36 |
+
writer.writerow(rowText)
|
| 37 |
+
|
| 38 |
+
def csvHeatCascade(self, unfeasibleHeatCascade, hotUtility, heatCascade, pinchTemperature, newpath):
|
| 39 |
+
cellText = [['Unfeasible Heat Cascade: ']]
|
| 40 |
+
cellText.append(['', '', 'Hot Utility: 0 kW'])
|
| 41 |
+
cellText.append(['Interval', 'Delta H (kW)', 'Exit H (total kW)'])
|
| 42 |
+
|
| 43 |
+
i = 1
|
| 44 |
+
for interval in unfeasibleHeatCascade:
|
| 45 |
+
cellText.append([str(i), interval['deltaH'], interval['exitH']])
|
| 46 |
+
i = i + 1
|
| 47 |
+
|
| 48 |
+
cellText.append(['', '', 'Cold Utility: {} kW'.format(unfeasibleHeatCascade[-1]['exitH'])])
|
| 49 |
+
cellText.append([''])
|
| 50 |
+
|
| 51 |
+
cellText.append(['Feasible Heat Cascade: '])
|
| 52 |
+
cellText.append(['', '', 'Hot Utility: {} kW'.format(hotUtility)])
|
| 53 |
+
cellText.append(['Interval', 'Delta H (kW)', 'Exit H (total kW)'])
|
| 54 |
+
|
| 55 |
+
i = 1
|
| 56 |
+
for interval in heatCascade:
|
| 57 |
+
cellText.append([str(i), interval['deltaH'], interval['exitH']])
|
| 58 |
+
i = i + 1
|
| 59 |
+
|
| 60 |
+
cellText.append(['', '', 'Cold Utility: {} kW'.format(heatCascade[-1]['exitH'])])
|
| 61 |
+
cellText.append(['','', 'Pinch Temperature: {} degC'.format(pinchTemperature)])
|
| 62 |
+
|
| 63 |
+
if not os.path.exists(newpath):
|
| 64 |
+
os.makedirs(newpath)
|
| 65 |
+
fileName = 'HeatCascade.csv'
|
| 66 |
+
|
| 67 |
+
path = os.path.join(newpath, fileName)
|
| 68 |
+
|
| 69 |
+
with open(path, 'w', newline='') as f:
|
| 70 |
+
writer = csv.writer(f, delimiter=',')
|
| 71 |
+
for rowText in cellText:
|
| 72 |
+
writer.writerow(rowText)
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def csvShiftedCompositeDiagram(self, newpath, shiftedCompositeDiagram):
|
| 76 |
+
if not os.path.exists(newpath):
|
| 77 |
+
os.makedirs(newpath)
|
| 78 |
+
fileName = 'ShiftedCompositeDiagram.csv'
|
| 79 |
+
|
| 80 |
+
path = os.path.join(newpath, fileName)
|
| 81 |
+
|
| 82 |
+
with open(path, 'w', newline='') as f:
|
| 83 |
+
writer = csv.writer(f, delimiter=',')
|
| 84 |
+
writer.writerow(['Hot H', 'Hot T'])
|
| 85 |
+
for i in range(0, len(shiftedCompositeDiagram['hot']['H'])):
|
| 86 |
+
writer.writerow([shiftedCompositeDiagram['hot']['H'][i],
|
| 87 |
+
shiftedCompositeDiagram['hot']['T'][i]])
|
| 88 |
+
|
| 89 |
+
writer.writerow([''])
|
| 90 |
+
writer.writerow(['Cold H', 'Cold T'])
|
| 91 |
+
for i in range(0, len(shiftedCompositeDiagram['cold']['H'])):
|
| 92 |
+
writer.writerow([shiftedCompositeDiagram['cold']['H'][i],
|
| 93 |
+
shiftedCompositeDiagram['cold']['T'][i]])
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
def csvCompositeDiagram(self, newpath, compositeDiagram):
|
| 97 |
+
if not os.path.exists(newpath):
|
| 98 |
+
os.makedirs(newpath)
|
| 99 |
+
fileName = 'CompositeDiagram.csv'
|
| 100 |
+
|
| 101 |
+
path = os.path.join(newpath, fileName)
|
| 102 |
+
with open(path, 'w', newline='') as f:
|
| 103 |
+
writer = csv.writer(f, delimiter=',')
|
| 104 |
+
writer.writerow(['Hot H', 'Hot T'])
|
| 105 |
+
for i in range(0, len(compositeDiagram['hot']['H'])):
|
| 106 |
+
writer.writerow([compositeDiagram['hot']['H'][i],
|
| 107 |
+
compositeDiagram['hot']['T'][i]])
|
| 108 |
+
|
| 109 |
+
writer.writerow([''])
|
| 110 |
+
writer.writerow(['Cold H', 'Cold T'])
|
| 111 |
+
for i in range(0, len(compositeDiagram['cold']['H'])):
|
| 112 |
+
writer.writerow([compositeDiagram['cold']['H'][i],
|
| 113 |
+
compositeDiagram['cold']['T'][i]])
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def csvGrandCompositeCurve(self, newpath, grandCompositeCurve):
|
| 118 |
+
if not os.path.exists(newpath):
|
| 119 |
+
os.makedirs(newpath)
|
| 120 |
+
fileName = 'GrandCompositeCurve.csv'
|
| 121 |
+
|
| 122 |
+
path = os.path.join(newpath, fileName)
|
| 123 |
+
with open(path, 'w', newline='') as f:
|
| 124 |
+
writer = csv.writer(f, delimiter=',')
|
| 125 |
+
writer.writerow(['Net H (kW)', 'T(degC)'])
|
| 126 |
+
for i in range(0, len(grandCompositeCurve['H'])):
|
| 127 |
+
writer.writerow([grandCompositeCurve['H'][i],
|
| 128 |
+
grandCompositeCurve['T'][i]])
|
| 129 |
+
|
src/Modules/Pinch/PinchPlot.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import matplotlib.pyplot as plt
|
| 2 |
+
|
| 3 |
+
class PinchPlot:
|
| 4 |
+
|
| 5 |
+
def drawTemperatureInterval(self, _temperatures, streams):
|
| 6 |
+
fig, ax = plt.subplots()
|
| 7 |
+
|
| 8 |
+
plt.title('Shifted Temperature Interval Diagram')
|
| 9 |
+
plt.ylabel('Shifted Temperature S (degC)')
|
| 10 |
+
ax.set_xticklabels([])
|
| 11 |
+
|
| 12 |
+
xOffset = 50
|
| 13 |
+
|
| 14 |
+
for temperature in _temperatures:
|
| 15 |
+
plt.plot([0, xOffset * (streams.numberOf + 1)], [temperature, temperature], ':k', alpha=0.8)
|
| 16 |
+
|
| 17 |
+
arrow_width = streams.numberOf * 0.05
|
| 18 |
+
head_width = arrow_width * 15
|
| 19 |
+
head_length = _temperatures[0] * 0.02
|
| 20 |
+
i = 1
|
| 21 |
+
for stream in streams:
|
| 22 |
+
if stream['type'] == 'HOT':
|
| 23 |
+
plt.text(xOffset, stream['ss'], str(i), bbox=dict(boxstyle='round', alpha=1, fc='tab:red', ec="k"))
|
| 24 |
+
plt.arrow(xOffset, stream['ss'], 0, stream['st'] - stream['ss'], color='tab:red', ec='k', alpha=1,
|
| 25 |
+
length_includes_head=True, width=arrow_width, head_width=head_width, head_length=head_length)
|
| 26 |
+
else:
|
| 27 |
+
plt.text(xOffset, stream['ss'], str(i), bbox=dict(boxstyle='round', alpha=1, fc='tab:blue', ec="k"))
|
| 28 |
+
plt.arrow(xOffset, stream['ss'], 0, stream['st'] - stream['ss'], color='tab:blue', ec='k', alpha=1,
|
| 29 |
+
length_includes_head=True, width=arrow_width, head_width=head_width, head_length=head_length)
|
| 30 |
+
xOffset = xOffset + 50
|
| 31 |
+
i = i + 1
|
| 32 |
+
|
| 33 |
+
def drawProblemTable(self, problemTable, _temperatures):
|
| 34 |
+
fig, ax = plt.subplots(figsize=(6, 6))
|
| 35 |
+
ax.axis('tight')
|
| 36 |
+
ax.axis('off')
|
| 37 |
+
ax.set_title('Problem Table')
|
| 38 |
+
|
| 39 |
+
colLabels = ['$Interval: S_i - S_{i+1}$', '$\\Delta T (\\degree C)$', '$\\Delta CP (kW / \\degree C)$', '$\\Delta H (kW)$', '']
|
| 40 |
+
cellText = []
|
| 41 |
+
|
| 42 |
+
i = 1
|
| 43 |
+
for interval in problemTable:
|
| 44 |
+
cellRow = []
|
| 45 |
+
cellRow.extend(['{}: {} - {}'.format(i, _temperatures[i - 1], _temperatures[i]),
|
| 46 |
+
interval['deltaS'], interval['deltaCP'], interval['deltaH']])
|
| 47 |
+
|
| 48 |
+
if interval['deltaH'] > 0:
|
| 49 |
+
cellRow.append('Surplus')
|
| 50 |
+
elif interval['deltaH'] == 0:
|
| 51 |
+
cellRow.append('-')
|
| 52 |
+
else:
|
| 53 |
+
cellRow.append('Deficit')
|
| 54 |
+
cellText.append(cellRow)
|
| 55 |
+
i = i + 1
|
| 56 |
+
|
| 57 |
+
table = ax.table(cellText=cellText, colLabels=colLabels, loc='center')
|
| 58 |
+
table.auto_set_column_width([0, 1, 2, 3, 4])
|
| 59 |
+
table.scale(1.3, 1.3)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def drawHeatCascade(self, unfeasibleHeatCascade, heatCascade, hotUtility):
|
| 63 |
+
fig, axs = plt.subplots(1, 2, figsize=(10, 6))
|
| 64 |
+
axs[0].axis('auto')
|
| 65 |
+
axs[0].axis('off')
|
| 66 |
+
axs[1].axis('auto')
|
| 67 |
+
axs[1].axis('off')
|
| 68 |
+
|
| 69 |
+
axs[0].set_title('Unfeasible Heat Cascade')
|
| 70 |
+
axs[1].set_title('Feasible Heat Cascade')
|
| 71 |
+
|
| 72 |
+
cellText = []
|
| 73 |
+
cellText.append(['', '', 'Hot Utility: 0'])
|
| 74 |
+
cellText.append(['Interval', '$\\Delta H (kW)$', 'Exit H (total kW)'])
|
| 75 |
+
|
| 76 |
+
i = 1
|
| 77 |
+
for interval in unfeasibleHeatCascade:
|
| 78 |
+
cellText.append([str(i), interval['deltaH'], interval['exitH']])
|
| 79 |
+
i = i + 1
|
| 80 |
+
|
| 81 |
+
cellText.append(['', '', 'Cold Utility: {}'.format(unfeasibleHeatCascade[-1]['exitH'])])
|
| 82 |
+
table = axs[0].table(cellText=cellText, loc='center')
|
| 83 |
+
table.auto_set_column_width([0, 1, 2])
|
| 84 |
+
table.scale(1.3, 1.3)
|
| 85 |
+
|
| 86 |
+
cellText = []
|
| 87 |
+
cellText.append(['', '', 'Hot Utility: {}'.format(hotUtility)])
|
| 88 |
+
cellText.append(['Interval', '$\\Delta H (kW)$', 'Exit H (total kW)'])
|
| 89 |
+
|
| 90 |
+
i = 1
|
| 91 |
+
for interval in heatCascade:
|
| 92 |
+
cellText.append([str(i), interval['deltaH'], interval['exitH']])
|
| 93 |
+
i = i + 1
|
| 94 |
+
|
| 95 |
+
cellText.append(['', '', 'Cold Utility: {}'.format(heatCascade[-1]['exitH'])])
|
| 96 |
+
table = axs[1].table(cellText=cellText, loc='center')
|
| 97 |
+
table.auto_set_column_width([0, 1, 2])
|
| 98 |
+
table.scale(1.3, 1.3)
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
def drawShiftedCompositeDiagram(self, shiftedCompositeDiagram, coldUtility, _temperatures, hotUtility, pinchTemperature, processdesignation, localisation):
|
| 102 |
+
fig = plt.figure()
|
| 103 |
+
plt.plot(shiftedCompositeDiagram['hot']['H'], shiftedCompositeDiagram['hot']['T'], 'tab:red')
|
| 104 |
+
plt.plot(shiftedCompositeDiagram['cold']['H'], shiftedCompositeDiagram['cold']['T'], 'tab:blue')
|
| 105 |
+
|
| 106 |
+
plt.plot(shiftedCompositeDiagram['hot']['H'], shiftedCompositeDiagram['hot']['T'], 'ro')
|
| 107 |
+
plt.plot(shiftedCompositeDiagram['cold']['H'], shiftedCompositeDiagram['cold']['T'], 'bo')
|
| 108 |
+
|
| 109 |
+
maxColdH = max(shiftedCompositeDiagram['cold']['H'])
|
| 110 |
+
|
| 111 |
+
try:
|
| 112 |
+
pinchIndex = shiftedCompositeDiagram['cold']['T'].index(pinchTemperature)
|
| 113 |
+
pinchH = shiftedCompositeDiagram['cold']['H'][pinchIndex]
|
| 114 |
+
plt.plot([pinchH, pinchH], [_temperatures[0], _temperatures[-1]], ':')
|
| 115 |
+
except ValueError:
|
| 116 |
+
pass
|
| 117 |
+
|
| 118 |
+
a = plt.fill_between([coldUtility, shiftedCompositeDiagram['cold']['H'][0]-hotUtility], [shiftedCompositeDiagram['cold']['T'][0]])
|
| 119 |
+
a.set_hatch('\\')
|
| 120 |
+
a.set_facecolor('w')
|
| 121 |
+
plt.grid(True)
|
| 122 |
+
if localisation == 'DE':
|
| 123 |
+
plt.title('Verschobene Verbundkurven ({})'.format(processdesignation))#plt.title('Shifted Temperature-Enthalpy Composite Diagram')
|
| 124 |
+
plt.xlabel('Enthalpiestrom H in kW')
|
| 125 |
+
plt.ylabel('Verschobene Temperatur in °C')
|
| 126 |
+
elif localisation == 'EN':
|
| 127 |
+
plt.title('Shifted Composite Diagram')
|
| 128 |
+
plt.xlabel('Enthalpy H in kW')
|
| 129 |
+
plt.ylabel('Shifted Temperature T in °C')
|
| 130 |
+
|
| 131 |
+
def drawCompositeDiagram(self, compositeDiagram, shiftedCompositeDiagram, coldUtility,
|
| 132 |
+
_temperatures, tmin, hotUtility, pinchTemperature, processdesignation, localisation):
|
| 133 |
+
fig = plt.figure()
|
| 134 |
+
plt.plot(compositeDiagram['hot']['H'], compositeDiagram['hot']['T'], 'tab:red')
|
| 135 |
+
plt.plot(compositeDiagram['cold']['H'], compositeDiagram['cold']['T'], 'tab:blue')
|
| 136 |
+
|
| 137 |
+
plt.plot(compositeDiagram['hot']['H'], compositeDiagram['hot']['T'], 'ro')
|
| 138 |
+
plt.plot(compositeDiagram['cold']['H'], compositeDiagram['cold']['T'], 'bo')
|
| 139 |
+
|
| 140 |
+
maxColdH = max(compositeDiagram['cold']['H'])
|
| 141 |
+
|
| 142 |
+
try:
|
| 143 |
+
pinchIndex = shiftedCompositeDiagram['cold']['T'].index(pinchTemperature)
|
| 144 |
+
pinchH = shiftedCompositeDiagram['cold']['H'][pinchIndex]
|
| 145 |
+
plt.plot([pinchH, pinchH], [_temperatures[0], _temperatures[-1]], ':')
|
| 146 |
+
except ValueError:
|
| 147 |
+
pass
|
| 148 |
+
|
| 149 |
+
plt.grid(True)
|
| 150 |
+
if localisation == 'DE':
|
| 151 |
+
plt.title('Verbundkurven ({})'.format(processdesignation))#plt.title('Shifted Temperature-Enthalpy Composite Diagram')
|
| 152 |
+
plt.xlabel('Enthalpiestrom H in kW')
|
| 153 |
+
plt.ylabel('Temperatur in °C')
|
| 154 |
+
elif localisation == 'EN':
|
| 155 |
+
plt.title('Composite Diagram ({})'.format(processdesignation))
|
| 156 |
+
plt.xlabel('Enthalpy H in kW')
|
| 157 |
+
plt.ylabel('Temperature T in °C')
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
def drawGrandCompositeCurve(self, processdesignation, heatCascade, grandCompositeCurve, _temperatures, pinchTemperature, localisation):
|
| 161 |
+
fig = plt.figure(num='{}'.format(processdesignation))
|
| 162 |
+
if heatCascade[0]['deltaH'] > 0:
|
| 163 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [grandCompositeCurve['T'][0],grandCompositeCurve['T'][1]], 'tab:red')
|
| 164 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [grandCompositeCurve['T'][0],grandCompositeCurve['T'][1]], 'ro')
|
| 165 |
+
elif heatCascade[0]['deltaH'] < 0:
|
| 166 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [grandCompositeCurve['T'][0],grandCompositeCurve['T'][1]], 'tab:blue')
|
| 167 |
+
plt.plot([grandCompositeCurve['H'][0],grandCompositeCurve['H'][1]], [grandCompositeCurve['T'][0],grandCompositeCurve['T'][1]], 'bo')
|
| 168 |
+
|
| 169 |
+
for i in range(1, len(_temperatures)-1):
|
| 170 |
+
if heatCascade[i]['deltaH'] > 0:
|
| 171 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:red')
|
| 172 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'ro')
|
| 173 |
+
elif heatCascade[i]['deltaH'] < 0:
|
| 174 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:blue')
|
| 175 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'bo')
|
| 176 |
+
elif heatCascade[i]['deltaH'] == 0 and grandCompositeCurve['H'][i]!=0:
|
| 177 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'tab:blue')
|
| 178 |
+
plt.plot([grandCompositeCurve['H'][i],grandCompositeCurve['H'][i+1]], [grandCompositeCurve['T'][i],grandCompositeCurve['T'][i+1]], 'bo')
|
| 179 |
+
|
| 180 |
+
plt.plot([0, grandCompositeCurve['H'][-1]], [pinchTemperature, pinchTemperature], ':')
|
| 181 |
+
|
| 182 |
+
plt.grid(True)
|
| 183 |
+
if localisation == 'DE':
|
| 184 |
+
plt.title('Großverbundkurve ({})'.format(processdesignation))
|
| 185 |
+
plt.xlabel('Nettoenthalpiestromänderung ∆H [kW]')
|
| 186 |
+
plt.ylabel('Verschobene Temperatur [°C]')
|
| 187 |
+
elif localisation == 'EN':
|
| 188 |
+
plt.title('Grand Composite Diagram ({})'.format(processdesignation))
|
| 189 |
+
plt.xlabel('Net Enthalpy Change ∆H in kW')
|
| 190 |
+
plt.ylabel('Shifted Temperature T in °C')
|
| 191 |
+
|
| 192 |
+
def showPlots():
|
| 193 |
+
plt.show()
|
src/Modules/Pinch/Streams.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import csv
|
| 2 |
+
|
| 3 |
+
class Streams:
|
| 4 |
+
|
| 5 |
+
def __init__(self, streamsDataFile):
|
| 6 |
+
|
| 7 |
+
self.tmin = 0
|
| 8 |
+
self.numberOf = 0
|
| 9 |
+
self.streamsData = []
|
| 10 |
+
|
| 11 |
+
self._rawStreamsData = []
|
| 12 |
+
self._index = 0
|
| 13 |
+
self._length = 0
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
with open(streamsDataFile, newline='') as f:
|
| 19 |
+
reader = csv.reader(f)
|
| 20 |
+
for row in reader:
|
| 21 |
+
self._rawStreamsData.append(row)
|
| 22 |
+
|
| 23 |
+
if (self._rawStreamsData[0][0].strip() != 'Tmin' or
|
| 24 |
+
[ item.strip() for item in self._rawStreamsData[1] ] != ['CP', 'TSUPPLY', 'TTARGET']):
|
| 25 |
+
raise Exception("""\n[ERROR] Bad formatting in streams data file. \n
|
| 26 |
+
The first two rows of the streams data file should be: \n
|
| 27 |
+
`` Tmin, <TMIN VALUE> ''
|
| 28 |
+
`` CP, TSUPPLY, TTARGET ''\n
|
| 29 |
+
Where CP is the heat capacity (kW / degC);
|
| 30 |
+
TSUPPLY is the starting temperature of the given stream (degC);
|
| 31 |
+
TTARGET is the ending temperature of the given stream (degC);\n""")
|
| 32 |
+
|
| 33 |
+
self.createStreams()
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def createStreams(self):
|
| 37 |
+
try:
|
| 38 |
+
self.tmin = float(self._rawStreamsData[0][1])
|
| 39 |
+
except ValueError:
|
| 40 |
+
print("\n[ERROR] Wrong type supplied for Tmin in the streams data file. Perhaps used characters?\n")
|
| 41 |
+
raise
|
| 42 |
+
except IndexError:
|
| 43 |
+
print("\n[ERROR] Missing value for Tmin in the streams data file.\n")
|
| 44 |
+
raise
|
| 45 |
+
except:
|
| 46 |
+
print("\n[ERROR] Unexpected error for Tmin. Try using the supplied streams data file format.\n")
|
| 47 |
+
raise
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
for rawStream in self._rawStreamsData[2:]:
|
| 51 |
+
try:
|
| 52 |
+
stream = {}
|
| 53 |
+
|
| 54 |
+
if float(rawStream[1]) > float(rawStream[2]):
|
| 55 |
+
stream["type"] = "HOT"
|
| 56 |
+
else:
|
| 57 |
+
stream["type"] = "COLD"
|
| 58 |
+
|
| 59 |
+
stream["cp"] = float(rawStream[0])
|
| 60 |
+
stream["ts"] = float(rawStream[1])
|
| 61 |
+
stream["tt"] = float(rawStream[2])
|
| 62 |
+
|
| 63 |
+
self.streamsData.append(stream)
|
| 64 |
+
|
| 65 |
+
except ValueError:
|
| 66 |
+
print("\n[ERROR] Wrong number type supplied in the streams data file. Perhaps used characters?\n")
|
| 67 |
+
raise
|
| 68 |
+
except IndexError:
|
| 69 |
+
print("\n[ERROR] Missing number in the streams data file.\n")
|
| 70 |
+
raise
|
| 71 |
+
except:
|
| 72 |
+
print("\n[ERROR] Unexpected error. Try using the supplied streams data file format.\n")
|
| 73 |
+
raise
|
| 74 |
+
|
| 75 |
+
self._length = len(self.streamsData)
|
| 76 |
+
self.numberOf = len(self.streamsData)
|
| 77 |
+
if (self._length < 2):
|
| 78 |
+
raise Exception("\n[ERROR] Need to supply at least 2 streams in the streams data file.\n")
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def __iter__(self):
|
| 82 |
+
return self
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def __next__(self):
|
| 86 |
+
if self._index == self._length:
|
| 87 |
+
self._index = 0
|
| 88 |
+
raise StopIteration
|
| 89 |
+
self._index = self._index + 1
|
| 90 |
+
|
| 91 |
+
return self.streamsData[self._index - 1]
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def printTmin(self):
|
| 95 |
+
print(self.tmin)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def printStreams(self):
|
| 99 |
+
for stream in self.streamsData:
|
| 100 |
+
print(stream)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def printRawStreams(self):
|
| 104 |
+
for rawStream in self._rawStreamsData:
|
| 105 |
+
print(rawStream)
|
src/Modules/Pinch_main.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import csv
|
| 2 |
+
from Modules.Pinch.Pinch import Pinch
|
| 3 |
+
from Modules.Pinch.PinchPlot import PinchPlot
|
| 4 |
+
|
| 5 |
+
class Pinchmain():
|
| 6 |
+
def __init__(self, CSV, options = {}):
|
| 7 |
+
self.PinchAnalyse = Pinch(CSV, options)
|
| 8 |
+
self._options = {}
|
| 9 |
+
|
| 10 |
+
def solvePinch(self, localisation = 'DE'):
|
| 11 |
+
|
| 12 |
+
self.PinchAnalyse.shiftTemperatures()
|
| 13 |
+
self.PinchAnalyse.constructTemperatureInterval()
|
| 14 |
+
self.PinchAnalyse.constructProblemTable()
|
| 15 |
+
self.PinchAnalyse.constructHeatCascade()
|
| 16 |
+
self.PinchAnalyse.constructShiftedCompositeDiagram(localisation)
|
| 17 |
+
self.PinchAnalyse.constructCompositeDiagram(localisation)
|
| 18 |
+
self.PinchAnalyse.constructGrandCompositeCurve(localisation)
|
| 19 |
+
|
| 20 |
+
with open("Buffer file for TotalSiteProfile creation.csv", "w", newline="") as csvfile:
|
| 21 |
+
self.newstreamsdata = csv.writer(csvfile)
|
| 22 |
+
self.newstreamsdata.writerow(self.PinchAnalyse._temperatures)
|
| 23 |
+
self.newstreamsdata.writerow(self.PinchAnalyse.heatCascade)
|
| 24 |
+
self.newstreamsdata.writerow([self.PinchAnalyse.hotUtility])
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
if self.PinchAnalyse._options['draw'] == True:
|
| 28 |
+
PinchPlot.showPlots()
|
| 29 |
+
|
| 30 |
+
def solvePinchforISSP(self, localisation = 'DE'):
|
| 31 |
+
|
| 32 |
+
self.PinchAnalyse.shiftTemperatures()
|
| 33 |
+
self.PinchAnalyse.constructTemperatureInterval()
|
| 34 |
+
self.PinchAnalyse.constructProblemTable()
|
| 35 |
+
self.PinchAnalyse.constructHeatCascade()
|
| 36 |
+
self.PinchAnalyse.constructShiftedCompositeDiagram(localisation)
|
| 37 |
+
|
| 38 |
+
return[self.PinchAnalyse.shiftedCompositeDiagram, self.PinchAnalyse]
|
| 39 |
+
|
| 40 |
+
def solvePinchforHPI(self, localisation = 'DE'):
|
| 41 |
+
|
| 42 |
+
self.PinchAnalyse.shiftTemperatures()
|
| 43 |
+
self.PinchAnalyse.constructTemperatureInterval()
|
| 44 |
+
self.PinchAnalyse.constructProblemTable()
|
| 45 |
+
self.PinchAnalyse.constructHeatCascade()
|
| 46 |
+
self.PinchAnalyse.constructShiftedCompositeDiagram(localisation)
|
| 47 |
+
self.PinchAnalyse.constructCompositeDiagram(localisation)
|
| 48 |
+
self.PinchAnalyse.constructGrandCompositeCurve(localisation)
|
| 49 |
+
|
| 50 |
+
return(self.PinchAnalyse)
|
| 51 |
+
|
| 52 |
+
#Pinchmain('Example.csv', options={'draw', 'csv'}).solvePinch()
|
| 53 |
+
#Pinchmain('Prozess_neu.csv', options={'draw', 'csv'}).solvePinch()
|
src/Modules/TotalSiteProfile/TSPPlot.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import matplotlib.pyplot as plt
|
| 2 |
+
|
| 3 |
+
class TSPPlot():
|
| 4 |
+
|
| 5 |
+
def drawDeletedCurve(self, heatCascadedeltaH, deletedPocketdict, _temperatures, plottest):
|
| 6 |
+
fig = plt.figure()
|
| 7 |
+
if heatCascadedeltaH[0] > 0:
|
| 8 |
+
plt.plot([deletedPocketdict['H'][0][0],deletedPocketdict['H'][0][1]], [deletedPocketdict['T'][0][0],deletedPocketdict['T'][0][1]], 'tab:red')
|
| 9 |
+
plt.plot([deletedPocketdict['H'][0][0],deletedPocketdict['H'][0][1]], [deletedPocketdict['T'][0][0],deletedPocketdict['T'][0][1]], 'ro')
|
| 10 |
+
elif heatCascadedeltaH[0] < 0:
|
| 11 |
+
plt.plot([deletedPocketdict['H'][0][0],deletedPocketdict['H'][0][1]], [deletedPocketdict['T'][0][0],deletedPocketdict['T'][0][1]], 'tab:blue')
|
| 12 |
+
plt.plot([deletedPocketdict['H'][0][0],deletedPocketdict['H'][0][1]], [deletedPocketdict['T'][0][0],deletedPocketdict['T'][0][1]], 'bo')
|
| 13 |
+
|
| 14 |
+
if plottest == 1:
|
| 15 |
+
for i in range(1, len(_temperatures)-2):
|
| 16 |
+
if heatCascadedeltaH[i] > 0:
|
| 17 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:red')
|
| 18 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'ro')
|
| 19 |
+
elif heatCascadedeltaH[i] < 0:
|
| 20 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:blue')
|
| 21 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'bo')
|
| 22 |
+
else:
|
| 23 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:blue')
|
| 24 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'bo')
|
| 25 |
+
if plottest == 0:
|
| 26 |
+
for i in range(1, len(_temperatures)-1):
|
| 27 |
+
if heatCascadedeltaH[i] > 0:
|
| 28 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:red')
|
| 29 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'ro')
|
| 30 |
+
elif heatCascadedeltaH[i] < 0:
|
| 31 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:blue')
|
| 32 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'bo')
|
| 33 |
+
else:
|
| 34 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'tab:blue')
|
| 35 |
+
plt.plot([deletedPocketdict['H'][0][i],deletedPocketdict['H'][0][i+1]], [deletedPocketdict['T'][0][i],deletedPocketdict['T'][0][i+1]], 'bo')
|
| 36 |
+
|
| 37 |
+
# plt.fill_between([0, deletedPocketdict['H'][0][0]], 0, _temperatures[0], color = 'r', alpha = 0.5)
|
| 38 |
+
# plt.fill_between([0, deletedPocketdict['H'][0][-1]], 0, _temperatures[-1], color = 'b', alpha = 0.5)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
plt.grid(True)
|
| 42 |
+
plt.title('Grand Composite Curve')
|
| 43 |
+
plt.xlabel('Net Enthalpy Change ∆H [kW]')
|
| 44 |
+
plt.ylabel('Shifted Temperature T [°C]')
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def drawTotalSiteProfile(self, siteDesignation, tstHotH, tstHotTemperatures, tstColdH, tstColdTemperatures, localisation):
|
| 48 |
+
#Wieder aus den ausgegebenen Werten fuer alle Prozesse Temperaturintervalle erstellen und diese dann plotten
|
| 49 |
+
fig, (ax1, ax2) = plt.subplots(1, 2)
|
| 50 |
+
|
| 51 |
+
fig.suptitle('Total Site Profile ({})'.format(siteDesignation))
|
| 52 |
+
|
| 53 |
+
ax1.plot(tstHotH, tstHotTemperatures, 'tab:red')
|
| 54 |
+
if localisation == 'DE':
|
| 55 |
+
ax1.set(xlabel='Nettoenthalpieänderung ∆H in kW', ylabel='Verschobene Temperatur T in °C')
|
| 56 |
+
elif localisation == 'EN':
|
| 57 |
+
ax1.set(xlabel='Net Enthalpy Change ∆H in kW', ylabel='Shifted Temperature T in °C')
|
| 58 |
+
|
| 59 |
+
ax1.grid()
|
| 60 |
+
ax2.plot(tstColdH, tstColdTemperatures, 'tab:blue')
|
| 61 |
+
if localisation == 'DE':
|
| 62 |
+
ax2.set_xlabel('Nettoenthalpieänderung ∆H in kW')
|
| 63 |
+
elif localisation == 'EN':
|
| 64 |
+
ax2.set(xlabel='Net Enthalpy Change ∆H in kW')
|
| 65 |
+
|
| 66 |
+
ax2.grid()
|
| 67 |
+
|
| 68 |
+
ax2.set_xlim([0,tstColdH[-1]])
|
| 69 |
+
ax1.set_xlim([tstHotH[0],0])
|
| 70 |
+
|
| 71 |
+
if tstHotH == [] or tstColdH == []:
|
| 72 |
+
pass
|
| 73 |
+
|
| 74 |
+
elif tstHotTemperatures[-1] > tstColdTemperatures[-1]:
|
| 75 |
+
if tstHotTemperatures[0] > tstColdTemperatures[0]:
|
| 76 |
+
ax1.set_ylim([tstColdTemperatures[0]-2.5,tstHotTemperatures[-1]+2.5])
|
| 77 |
+
ax2.set_ylim([tstColdTemperatures[0]-2.5,tstHotTemperatures[-1]+2.5])
|
| 78 |
+
elif tstHotTemperatures[0] < tstColdTemperatures[0]:
|
| 79 |
+
ax1.set_ylim([tstHotTemperatures[0]-2.5,tstHotTemperatures[-1]+2.5])
|
| 80 |
+
ax2.set_ylim([tstHotTemperatures[0]-2.5,tstHotTemperatures[-1]+2.5])
|
| 81 |
+
else:
|
| 82 |
+
pass
|
| 83 |
+
|
| 84 |
+
elif tstHotTemperatures[-1] < tstColdTemperatures[-1]:
|
| 85 |
+
if tstHotTemperatures[0] > tstColdTemperatures[0]:
|
| 86 |
+
ax1.set_ylim([tstColdTemperatures[0]-2.5,tstColdTemperatures[-1]+2.5])
|
| 87 |
+
ax2.set_ylim([tstColdTemperatures[0]-2.5,tstColdTemperatures[-1]+2.5])
|
| 88 |
+
elif tstHotTemperatures[0] < tstColdTemperatures[0]:
|
| 89 |
+
ax1.set_ylim([tstHotTemperatures[0]-2.5,tstColdTemperatures[-1]+2.5])
|
| 90 |
+
ax2.set_ylim([tstHotTemperatures[0]-2.5,tstColdTemperatures[-1]+2.5])
|
| 91 |
+
else:
|
| 92 |
+
pass
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def showPlots(self):
|
| 96 |
+
plt.show()
|
src/Modules/TotalSiteProfile/TotalSiteProfile.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Modules.Pinch_main import Pinchmain as Pinch
|
| 2 |
+
import csv
|
| 3 |
+
import ast
|
| 4 |
+
from Modules.TotalSiteProfile.TSPPlot import TSPPlot
|
| 5 |
+
from Modules.Utility.TemperaturePocketDeletion import TemperaturePocketDeletion as TPD
|
| 6 |
+
from Modules.Utility.splitStreams import splitStreams
|
| 7 |
+
|
| 8 |
+
class TotalSiteProfile:
|
| 9 |
+
|
| 10 |
+
def __init__(self, siteDesignation, options = {}):
|
| 11 |
+
|
| 12 |
+
self.siteDesignation = siteDesignation
|
| 13 |
+
|
| 14 |
+
self.heatCascadedeltaH = []
|
| 15 |
+
self.heatCascadeexitH = []
|
| 16 |
+
|
| 17 |
+
self.deletedPocketdict = []
|
| 18 |
+
self.heatCascadedeltaHdict = []
|
| 19 |
+
self.heatCascadeexitHdict = []
|
| 20 |
+
self.deletedPocketdictlist = []
|
| 21 |
+
|
| 22 |
+
self.splitHotTemperatures = []
|
| 23 |
+
self.splitColdTemperatures = []
|
| 24 |
+
self.splitHotH = []
|
| 25 |
+
self.splitColdH = []
|
| 26 |
+
self.splitHotdeltaH = []
|
| 27 |
+
self.splitColddeltaH = []
|
| 28 |
+
self.splitdict = {'HotTemperatures': [], 'ColdTemperatures': [], 'HotH': [], 'ColdH': [], 'HotdeltaH': [], 'ColddeltaH': [], 'SteigungHot': [], 'SteigungCold': []}
|
| 29 |
+
|
| 30 |
+
self.tstHotConstructionAid = {'T': [], 'Process': [], 'Stream': []}
|
| 31 |
+
self.tstColdConstructionAid = {'T': [], 'Process': [], 'Stream': []}
|
| 32 |
+
|
| 33 |
+
self.tstHotTemperatures = []
|
| 34 |
+
self.tstColdTemperatures = []
|
| 35 |
+
self.tstHotH = []
|
| 36 |
+
self.tstColdH = []
|
| 37 |
+
|
| 38 |
+
self.emptyintervalsHot = []
|
| 39 |
+
self.emptyintervalsCold = []
|
| 40 |
+
|
| 41 |
+
self._options = {'debug': False, 'draw': False, 'csv': False}
|
| 42 |
+
|
| 43 |
+
if 'debug' in options:
|
| 44 |
+
self._options['debug'] = True
|
| 45 |
+
if 'draw' in options:
|
| 46 |
+
self._options['draw'] = True
|
| 47 |
+
if 'csv' in options:
|
| 48 |
+
self._options['csv'] = True
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def importData(self, siteProfilecsv):
|
| 52 |
+
nooption = {}
|
| 53 |
+
Pinch('{}'.format(siteProfilecsv),nooption).solvePinch()
|
| 54 |
+
with open('Buffer file for TotalSiteProfile creation.csv', newline='') as f:
|
| 55 |
+
reader = csv.reader(f)
|
| 56 |
+
csvdata=[]
|
| 57 |
+
for row in reader:
|
| 58 |
+
csvdata.append(row)
|
| 59 |
+
self._temperatures = csvdata[0]
|
| 60 |
+
self.heatCascade = csvdata[1]
|
| 61 |
+
for i in range(len(self.heatCascade)):
|
| 62 |
+
self.heatCascade[i] = ast.literal_eval(self.heatCascade[i])
|
| 63 |
+
self.hotUtility = float(csvdata[2][0])
|
| 64 |
+
for i in range(len(self._temperatures)):
|
| 65 |
+
self._temperatures[i] = float(self._temperatures[i])
|
| 66 |
+
|
| 67 |
+
def deleteTemperaturePockets(self):
|
| 68 |
+
self.deletedPocketdict = TPD(self.hotUtility, self.heatCascade, self._temperatures).deleteTemperaturePockets()
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def noDeletionHelper(self):
|
| 72 |
+
self.deletedPocketdict = {'H': [], 'deltaH': [], 'T': []}
|
| 73 |
+
self.heatCascadedeltaH = []
|
| 74 |
+
self.heatCascadeexitH = []
|
| 75 |
+
self.heatCascadeexitH.append(self.hotUtility)
|
| 76 |
+
|
| 77 |
+
for o in range(len(self.heatCascade)):
|
| 78 |
+
self.heatCascadedeltaH.append(self.heatCascade[o]['deltaH'])
|
| 79 |
+
self.heatCascadeexitH.append(self.heatCascade[o]['exitH'])
|
| 80 |
+
|
| 81 |
+
self.deletedPocketdict['H'].append(self.heatCascadeexitH)
|
| 82 |
+
self.deletedPocketdict['deltaH'].append(self.heatCascadedeltaH)
|
| 83 |
+
self.deletedPocketdict['T'].append(self._temperatures)
|
| 84 |
+
self.deletedPocketdictlist.append(self.deletedPocketdict)
|
| 85 |
+
|
| 86 |
+
def splitHotandCold(self): # Fall für 2 aufeinander folgende heiße Ströme ohne deletion implementieren
|
| 87 |
+
self.splitdict = splitStreams(self.deletedPocketdict, self.splitdict).splitHotandCold()
|
| 88 |
+
|
| 89 |
+
def constructTotalSiteProfile(self, localisation): #Temperaturen sind in jedem Prozess bereits einzigartig für Heiß/Kalt
|
| 90 |
+
#Mit ColddeltaH und Temperaturen jeweils Steigungen für alle Schritte in Reihenfolge ermitteln
|
| 91 |
+
#Dann abfragen, welche Steigung im aktuellen Temperaturintervall benötigt wird(einfach der Reihe nach oder wenn T kleiner als die aktuelle Temperatur aber größer als die vorherige)
|
| 92 |
+
#Anschließend jeweils die Steigungen addieren und mal dem aktuellen Temperaturintervall rechnen und mit dem vorherigen Wert addiert anfügen
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
for i in range(len(self.splitdict['HotTemperatures'])):
|
| 96 |
+
for j in range(len(self.splitdict['HotTemperatures'][i])):
|
| 97 |
+
self.tstHotTemperatures.append(self.splitdict['HotTemperatures'][i][j])
|
| 98 |
+
|
| 99 |
+
if self.splitdict['HotTemperatures'][i][j] not in self.tstHotConstructionAid['T']:
|
| 100 |
+
self.tstHotConstructionAid['T'].append(self.splitdict['HotTemperatures'][i][j])
|
| 101 |
+
self.tstHotConstructionAid['Process'].append([i])
|
| 102 |
+
self.tstHotConstructionAid['Stream'].append([j])
|
| 103 |
+
|
| 104 |
+
elif self.splitdict['HotTemperatures'][i][j] in self.tstHotConstructionAid['T']:
|
| 105 |
+
temp = self.tstHotConstructionAid['T'].index(self.splitdict['HotTemperatures'][i][j])
|
| 106 |
+
self.tstHotConstructionAid['Process'][temp].append(i)
|
| 107 |
+
self.tstHotConstructionAid['Stream'][temp].append(j)
|
| 108 |
+
|
| 109 |
+
self.tstHotTemperatures = list(set(self.tstHotTemperatures))
|
| 110 |
+
self.tstHotTemperatures.sort()
|
| 111 |
+
|
| 112 |
+
for i in range(len(self.splitdict['ColdTemperatures'])):
|
| 113 |
+
for j in range(len(self.splitdict['ColdTemperatures'][i])):
|
| 114 |
+
self.tstColdTemperatures.append(self.splitdict['ColdTemperatures'][i][j])
|
| 115 |
+
|
| 116 |
+
if self.splitdict['ColdTemperatures'][i][j] not in self.tstColdConstructionAid['T']:
|
| 117 |
+
self.tstColdConstructionAid['T'].append(self.splitdict['ColdTemperatures'][i][j])
|
| 118 |
+
self.tstColdConstructionAid['Process'].append([i])
|
| 119 |
+
self.tstColdConstructionAid['Stream'].append([j])
|
| 120 |
+
|
| 121 |
+
elif self.splitdict['ColdTemperatures'][i][j] in self.tstColdConstructionAid['T']:
|
| 122 |
+
temp = self.tstColdConstructionAid['T'].index(self.splitdict['ColdTemperatures'][i][j])
|
| 123 |
+
self.tstColdConstructionAid['Process'][temp].append(i)
|
| 124 |
+
self.tstColdConstructionAid['Stream'][temp].append(j)
|
| 125 |
+
|
| 126 |
+
self.tstColdTemperatures = list(set(self.tstColdTemperatures))
|
| 127 |
+
self.tstColdTemperatures.sort()
|
| 128 |
+
|
| 129 |
+
Steigung = []
|
| 130 |
+
for Prozess in range(len(self.splitdict['ColdTemperatures'])):
|
| 131 |
+
for Temperatur in range(len(self.splitdict['ColdTemperatures'][Prozess])-1):
|
| 132 |
+
if self.splitdict['ColdTemperatures'][Prozess][Temperatur]-self.splitdict['ColdTemperatures'][Prozess][Temperatur+1] == 0:
|
| 133 |
+
Steigung.append(0.0)
|
| 134 |
+
elif self.splitdict['ColdH'][Prozess][Temperatur]-self.splitdict['ColdH'][Prozess][Temperatur+1]<0:
|
| 135 |
+
Steigung.append(0.0)
|
| 136 |
+
else:
|
| 137 |
+
Steigung.append((self.splitdict['ColdH'][Prozess][Temperatur]-self.splitdict['ColdH'][Prozess][Temperatur+1])/(self.splitdict['ColdTemperatures'][Prozess][Temperatur]-self.splitdict['ColdTemperatures'][Prozess][Temperatur+1]))
|
| 138 |
+
self.splitdict['SteigungCold'].append(Steigung)
|
| 139 |
+
Steigung = []
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
Steigung = []
|
| 143 |
+
for Prozess in range(len(self.splitdict['HotTemperatures'])):
|
| 144 |
+
for Temperatur in range(len(self.splitdict['HotTemperatures'][Prozess])-1):
|
| 145 |
+
if self.splitdict['HotH'][Prozess][Temperatur]-self.splitdict['HotH'][Prozess][Temperatur+1]>0:
|
| 146 |
+
Steigung.append(0.0)
|
| 147 |
+
else:
|
| 148 |
+
Steigung.append((self.splitdict['HotH'][Prozess][Temperatur]-self.splitdict['HotH'][Prozess][Temperatur+1])/(self.splitdict['HotTemperatures'][Prozess][Temperatur]-self.splitdict['HotTemperatures'][Prozess][Temperatur+1]))
|
| 149 |
+
self.splitdict['SteigungHot'].append(Steigung)
|
| 150 |
+
Steigung = []
|
| 151 |
+
|
| 152 |
+
kW = 0.0
|
| 153 |
+
for Temperatur in self.tstHotTemperatures:
|
| 154 |
+
for Prozess in reversed(range(len(self.splitdict['HotTemperatures']))):
|
| 155 |
+
if self.splitdict['HotTemperatures'][Prozess] == []:
|
| 156 |
+
continue
|
| 157 |
+
elif self.splitdict['HotTemperatures'][Prozess][-1] >= Temperatur:
|
| 158 |
+
continue
|
| 159 |
+
|
| 160 |
+
for Prozesstemperatur in reversed(range(len(self.splitdict['HotTemperatures'][Prozess]))):
|
| 161 |
+
if Temperatur == self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur]:
|
| 162 |
+
if letzteTemperaturHot > self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur+1] and letzteTemperaturHot < self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur]:
|
| 163 |
+
kW += self.splitdict['SteigungHot'][Prozess][Prozesstemperatur] * (self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur] - letzteTemperaturHot)
|
| 164 |
+
break
|
| 165 |
+
else:
|
| 166 |
+
kW += self.splitdict['SteigungHot'][Prozess][Prozesstemperatur] * (Temperatur - self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur+1])
|
| 167 |
+
break
|
| 168 |
+
|
| 169 |
+
elif Temperatur > self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur] and Temperatur < self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur-1]:
|
| 170 |
+
if letzteTemperaturHot > self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur] and letzteTemperaturHot < self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur-1]:
|
| 171 |
+
kW += self.splitdict['SteigungHot'][Prozess][Prozesstemperatur-1] * (Temperatur - letzteTemperaturHot)
|
| 172 |
+
else:
|
| 173 |
+
kW += self.splitdict['SteigungHot'][Prozess][Prozesstemperatur-1] * (Temperatur - self.splitdict['HotTemperatures'][Prozess][Prozesstemperatur])
|
| 174 |
+
break
|
| 175 |
+
else:
|
| 176 |
+
continue
|
| 177 |
+
if self.tstHotH == []:
|
| 178 |
+
self.tstHotH.append(kW)
|
| 179 |
+
else:
|
| 180 |
+
self.tstHotH.append(self.tstHotH[-1] + kW)
|
| 181 |
+
kW = 0.0
|
| 182 |
+
letzteTemperaturHot = Temperatur
|
| 183 |
+
|
| 184 |
+
kW = 0.0
|
| 185 |
+
for Temperatur in self.tstColdTemperatures:
|
| 186 |
+
for Prozess in reversed(range(len(self.splitdict['ColdTemperatures']))):
|
| 187 |
+
if self.splitdict['ColdTemperatures'][Prozess][-1] >= Temperatur:
|
| 188 |
+
continue
|
| 189 |
+
|
| 190 |
+
for Prozesstemperatur in reversed(range(len(self.splitdict['ColdTemperatures'][Prozess]))):
|
| 191 |
+
if Temperatur == self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur]:
|
| 192 |
+
if letzteTemperaturCold > self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur+1] and letzteTemperaturCold < self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur]:
|
| 193 |
+
kW += self.splitdict['SteigungCold'][Prozess][Prozesstemperatur] * (self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur] - letzteTemperaturCold)
|
| 194 |
+
break
|
| 195 |
+
else:
|
| 196 |
+
kW += self.splitdict['SteigungCold'][Prozess][Prozesstemperatur] * (Temperatur - self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur+1])
|
| 197 |
+
break
|
| 198 |
+
|
| 199 |
+
elif Temperatur > self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur] and Temperatur < self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur-1]:
|
| 200 |
+
if letzteTemperaturCold > self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur] and letzteTemperaturCold < self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur-1]:
|
| 201 |
+
kW += self.splitdict['SteigungCold'][Prozess][Prozesstemperatur-1] * (Temperatur - letzteTemperaturCold)
|
| 202 |
+
else:
|
| 203 |
+
kW += self.splitdict['SteigungCold'][Prozess][Prozesstemperatur-1] * (Temperatur - self.splitdict['ColdTemperatures'][Prozess][Prozesstemperatur])
|
| 204 |
+
break
|
| 205 |
+
else:
|
| 206 |
+
continue
|
| 207 |
+
if self.tstColdH == []:
|
| 208 |
+
self.tstColdH.append(kW)
|
| 209 |
+
else:
|
| 210 |
+
self.tstColdH.append(self.tstColdH[-1] + kW)
|
| 211 |
+
kW = 0.0
|
| 212 |
+
letzteTemperaturCold = Temperatur
|
| 213 |
+
|
| 214 |
+
maxheiß = self.tstHotH[-1]
|
| 215 |
+
self.tstHotH = [wert - maxheiß for wert in self.tstHotH]
|
| 216 |
+
a = 1
|
| 217 |
+
for i in range(len(self.tstHotH)):
|
| 218 |
+
self.tstHotH[i] = -self.tstHotH[i]
|
| 219 |
+
if self._options['draw'] == True:
|
| 220 |
+
TSPPlot().drawTotalSiteProfile(self.siteDesignation, self.tstHotH,
|
| 221 |
+
self.tstHotTemperatures, self.tstColdH, self.tstColdTemperatures, localisation)
|
| 222 |
+
|
src/Modules/Utility/TemperaturePocketDeletion.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Modules.TotalSiteProfile.TSPPlot import TSPPlot
|
| 2 |
+
|
| 3 |
+
class TemperaturePocketDeletion:
|
| 4 |
+
def __init__(self, hotUtility, heatCascade, _temperatures):
|
| 5 |
+
self.hotUtility = hotUtility
|
| 6 |
+
self.heatCascade = heatCascade
|
| 7 |
+
self._temperatures = _temperatures
|
| 8 |
+
self._options = {'draw': True}
|
| 9 |
+
|
| 10 |
+
def deleteDoubleEmpty(self,u):
|
| 11 |
+
if u < len(self.heatCascadedeltaH)-2:
|
| 12 |
+
if self.heatCascadedeltaH[u+1] == 0.0 and self.heatCascadedeltaH[u+2] == 0.0:
|
| 13 |
+
self.heatCascadedeltaH.pop(u+1)
|
| 14 |
+
self.heatCascadeexitH.pop(u+2)
|
| 15 |
+
self._temperatures.pop(u+2)
|
| 16 |
+
|
| 17 |
+
def deleteTemperaturePockets(self):
|
| 18 |
+
self.deletedPocketdict = {'H': [], 'deltaH': [], 'T': []}
|
| 19 |
+
self.deletedPocketdictlist=[]
|
| 20 |
+
|
| 21 |
+
i = 0
|
| 22 |
+
j = 0
|
| 23 |
+
k = 0
|
| 24 |
+
u = 0
|
| 25 |
+
plottest = 0
|
| 26 |
+
self.heatCascadedeltaH = []
|
| 27 |
+
self.heatCascadeexitH = []
|
| 28 |
+
self.heatCascadeexitH.append(self.hotUtility)
|
| 29 |
+
|
| 30 |
+
for o in range(len(self.heatCascade)):
|
| 31 |
+
self.heatCascadedeltaH.append(self.heatCascade[o]['deltaH'])
|
| 32 |
+
self.heatCascadeexitH.append(self.heatCascade[o]['exitH'])
|
| 33 |
+
|
| 34 |
+
for i in range(len(self.heatCascadeexitH)-1):
|
| 35 |
+
if self.heatCascadeexitH[i] <= 1e-22:
|
| 36 |
+
j = i
|
| 37 |
+
k = i
|
| 38 |
+
break
|
| 39 |
+
if j == 0 and k == 0:
|
| 40 |
+
if self.heatCascadeexitH[-1] <= 1e-22:
|
| 41 |
+
k = len(self.heatCascadeexitH)-1
|
| 42 |
+
j = len(self.heatCascadeexitH)-1
|
| 43 |
+
plottest = 1
|
| 44 |
+
elif self.heatCascadeexitH[0] <= 1e-22:
|
| 45 |
+
j = 0
|
| 46 |
+
while j < len(self.heatCascadeexitH)-1:
|
| 47 |
+
if self.heatCascadedeltaH[j] == 0:
|
| 48 |
+
j += 1
|
| 49 |
+
|
| 50 |
+
if j >= len(self.heatCascadedeltaH)-1:
|
| 51 |
+
break
|
| 52 |
+
|
| 53 |
+
if self.heatCascadedeltaH[j] > 0:
|
| 54 |
+
if self.heatCascadedeltaH[j + 1] < 0:
|
| 55 |
+
if abs(self.heatCascadedeltaH[j+1]) < abs(self.heatCascadedeltaH[j]):
|
| 56 |
+
self._temperatures[j+1] = self._temperatures[j] + ((self._temperatures[j]-self._temperatures[j+1]) / (self.heatCascadeexitH[j] - self.heatCascadeexitH[j+1]))* (self.heatCascadeexitH[j+2]) # lineare regression der Temperatur
|
| 57 |
+
self.heatCascadedeltaH[j] = self.heatCascadeexitH[j+2] - self.heatCascadeexitH[j]
|
| 58 |
+
self.heatCascadeexitH[j+1]=self.heatCascadeexitH[j+2]
|
| 59 |
+
self.heatCascadedeltaH[j+1] = 0.0
|
| 60 |
+
self.deleteDoubleEmpty(j)
|
| 61 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 62 |
+
self.heatCascadedeltaH.pop()
|
| 63 |
+
self._temperatures.pop()
|
| 64 |
+
self.heatCascadeexitH.pop()
|
| 65 |
+
break
|
| 66 |
+
j = i
|
| 67 |
+
elif abs(self.heatCascadedeltaH[j+1]) > abs(self.heatCascadedeltaH[j]):
|
| 68 |
+
self._temperatures[j+1] = self._temperatures[j+2] + ((self._temperatures[j+1]-self._temperatures[j+2]) / (self.heatCascadeexitH[j+1] - self.heatCascadeexitH[j+2]))* (self.heatCascadeexitH[j] - self.heatCascadeexitH[j+2]) # lineare regression der Temperatur
|
| 69 |
+
self.heatCascadeexitH[j+1]=self.heatCascadeexitH[j]
|
| 70 |
+
self.heatCascadedeltaH[j] = 0.0
|
| 71 |
+
self.deleteDoubleEmpty(j)
|
| 72 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 73 |
+
self.heatCascadedeltaH.pop()
|
| 74 |
+
self._temperatures.pop()
|
| 75 |
+
self.heatCascadeexitH.pop()
|
| 76 |
+
break
|
| 77 |
+
j=i
|
| 78 |
+
else:
|
| 79 |
+
self.heatCascadedeltaH = 0.0
|
| 80 |
+
self.heatCascadedeltaH.pop(j+1)
|
| 81 |
+
self.heatCascadeexitH.pop(j+1)
|
| 82 |
+
self._temperatures.pop(j+1)
|
| 83 |
+
self.deleteDoubleEmpty(j)
|
| 84 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 85 |
+
self.heatCascadedeltaH.pop()
|
| 86 |
+
self._temperatures.pop()
|
| 87 |
+
self.heatCascadeexitH.pop()
|
| 88 |
+
break
|
| 89 |
+
j=i
|
| 90 |
+
elif self.heatCascadedeltaH[j+1] == 0:
|
| 91 |
+
if self.heatCascadedeltaH[j+2]<0:
|
| 92 |
+
if abs(self.heatCascadedeltaH[j+2]) > abs(self.heatCascadedeltaH[j]):
|
| 93 |
+
self._temperatures[j+2] = self._temperatures[j+3] + ((self._temperatures[j+2]-self._temperatures[j+3]) / (self.heatCascadeexitH[j+2] - self.heatCascadeexitH[j+3]))* (self.heatCascadeexitH[j]-self.heatCascadeexitH[j+3])
|
| 94 |
+
self.heatCascadeexitH[j+2] = self.heatCascadeexitH[j]
|
| 95 |
+
self.heatCascadedeltaH[j+2] = self.heatCascadedeltaH[j+2] + self.heatCascadedeltaH[j]
|
| 96 |
+
self._temperatures.pop(j+1)
|
| 97 |
+
self.heatCascadeexitH.pop(j+1)
|
| 98 |
+
self.heatCascadedeltaH.pop(j)
|
| 99 |
+
self.deleteDoubleEmpty(j)
|
| 100 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 101 |
+
self.heatCascadedeltaH.pop()
|
| 102 |
+
self._temperatures.pop()
|
| 103 |
+
self.heatCascadeexitH.pop()
|
| 104 |
+
break
|
| 105 |
+
j=i
|
| 106 |
+
elif abs(self.heatCascadedeltaH[j+2]) < abs(self.heatCascadedeltaH[j]):
|
| 107 |
+
self._temperatures[j+1] = self._temperatures[j+1] - ((self._temperatures[j]-self._temperatures[j+1]) / (self.heatCascadeexitH[j] - self.heatCascadeexitH[j+1]))* (self.heatCascadeexitH[j+1]-self.heatCascadeexitH[j+3]) # lineare regression der Temperatur
|
| 108 |
+
self.heatCascadeexitH[j+1] = self.heatCascadeexitH[j+3]
|
| 109 |
+
self.heatCascadeexitH.pop(j+2)
|
| 110 |
+
self.heatCascadedeltaH[j] = self.heatCascadedeltaH[j] + self.heatCascadedeltaH[j+2]
|
| 111 |
+
self.heatCascadedeltaH.pop(j+2)
|
| 112 |
+
self._temperatures.pop(j+2)
|
| 113 |
+
self.deleteDoubleEmpty(j)
|
| 114 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 115 |
+
self.heatCascadedeltaH.pop()
|
| 116 |
+
self._temperatures.pop()
|
| 117 |
+
self.heatCascadeexitH.pop()
|
| 118 |
+
break
|
| 119 |
+
j=i
|
| 120 |
+
else:
|
| 121 |
+
self.heatCascadedeltaH.pop(j+1)
|
| 122 |
+
self._temperatures.pop(j+1)
|
| 123 |
+
self.heatCascadeexitH.pop(j+1)
|
| 124 |
+
self.heatCascadedeltaH.pop(j+1)
|
| 125 |
+
self._temperatures.pop(j+1)
|
| 126 |
+
self.heatCascadeexitH.pop(j+1)
|
| 127 |
+
self.heatCascadedeltaH[j] = 0.0
|
| 128 |
+
self.deleteDoubleEmpty(j)
|
| 129 |
+
if self.heatCascadedeltaH[-1] == 0.0:
|
| 130 |
+
self.heatCascadedeltaH.pop()
|
| 131 |
+
self._temperatures.pop()
|
| 132 |
+
self.heatCascadeexitH.pop()
|
| 133 |
+
break
|
| 134 |
+
j=i
|
| 135 |
+
else:
|
| 136 |
+
j+=1
|
| 137 |
+
else:
|
| 138 |
+
j += 1
|
| 139 |
+
else:
|
| 140 |
+
j += 1
|
| 141 |
+
while u < k-1:
|
| 142 |
+
if u >= len(self.heatCascadedeltaH)-1:
|
| 143 |
+
break
|
| 144 |
+
#unterscheidung einfügen ob u=0
|
| 145 |
+
if self.heatCascadedeltaH[u] > 0 and u == 0: #löscht nur den obersten, wenn der oberste direkt dran ist
|
| 146 |
+
if self.heatCascadedeltaH[u+1] < 0:
|
| 147 |
+
if abs(self.heatCascadedeltaH[u+1]) > abs(self.heatCascadedeltaH[u]):
|
| 148 |
+
#kalt größer heiß
|
| 149 |
+
self._temperatures[u+1] = self._temperatures[u+2] + ((self._temperatures[u+1]-self._temperatures[u+2]) / (self.heatCascadeexitH[u+1] - self.heatCascadeexitH[u+2]))* (self.heatCascadeexitH[u]-self.heatCascadeexitH[u+2]) # lineare regression der Temperatur
|
| 150 |
+
self.heatCascadedeltaH[u] = self.heatCascadeexitH[u+2] - self.heatCascadeexitH[u]
|
| 151 |
+
self._temperatures.pop(u)
|
| 152 |
+
self.heatCascadeexitH.pop(u+1)
|
| 153 |
+
self.heatCascadedeltaH.pop(u+1)
|
| 154 |
+
self.deleteDoubleEmpty(u)
|
| 155 |
+
u = 0
|
| 156 |
+
elif abs(self.heatCascadedeltaH[u+1]) < abs(self.heatCascadedeltaH[u]):
|
| 157 |
+
self._temperatures[u+1] = self._temperatures[u] + ((self._temperatures[u+1]-self._temperatures[u]) / (self.heatCascadeexitH[u+1] - self.heatCascadeexitH[u]))* (self.heatCascadeexitH[u+2]-self.heatCascadeexitH[u]) # lineare regression der Temperatur
|
| 158 |
+
self.heatCascadedeltaH[u] = self.heatCascadeexitH[u] + self.heatCascadeexitH[u+1]
|
| 159 |
+
self.heatCascadeexitH[u+1] = self.heatCascadeexitH[u+2]
|
| 160 |
+
self.heatCascadedeltaH[u+1] = 0.0
|
| 161 |
+
self.deleteDoubleEmpty(u)
|
| 162 |
+
u = 0
|
| 163 |
+
else:
|
| 164 |
+
self._temperatures.pop(u)
|
| 165 |
+
self.heatCascadeexitH.pop(u)
|
| 166 |
+
self.heatCascadedeltaH.pop(u)
|
| 167 |
+
self._temperatures.pop(u)
|
| 168 |
+
self.heatCascadeexitH.pop(u)
|
| 169 |
+
self.heatCascadedeltaH.pop(u)
|
| 170 |
+
u=0
|
| 171 |
+
elif self.heatCascadedeltaH[u+1] == 0:
|
| 172 |
+
if self.heatCascadedeltaH[u+2]<0:
|
| 173 |
+
if abs(self.heatCascadedeltaH[u+2]) > abs(self.heatCascadedeltaH[u]):
|
| 174 |
+
self._temperatures[u+2] = self._temperatures[u+3] + ((self._temperatures[u+2]-self._temperatures[u+3]) / (self.heatCascadeexitH[u+2] - self.heatCascadeexitH[u+3]))* (self.heatCascadeexitH[u]-self.heatCascadeexitH[u+3])
|
| 175 |
+
self.heatCascadeexitH[u+2] = self.heatCascadeexitH[u]
|
| 176 |
+
self.heatCascadedeltaH[u+2] = self.heatCascadedeltaH[u+2] + self.heatCascadedeltaH[u]
|
| 177 |
+
self._temperatures.pop(u+1)
|
| 178 |
+
self.heatCascadeexitH.pop(u+1)
|
| 179 |
+
self.heatCascadedeltaH.pop(u)
|
| 180 |
+
self.deleteDoubleEmpty(u)
|
| 181 |
+
self._temperatures.pop(u)
|
| 182 |
+
self.heatCascadedeltaH.pop(u)
|
| 183 |
+
self.heatCascadeexitH.pop(u)
|
| 184 |
+
u=0
|
| 185 |
+
elif abs(self.heatCascadedeltaH[u+2]) < abs(self.heatCascadedeltaH[u]):
|
| 186 |
+
self._temperatures[u+1] = self._temperatures[u+1] - ((self._temperatures[u]-self._temperatures[u+1]) / (self.heatCascadeexitH[u] - self.heatCascadeexitH[u+1]))* (self.heatCascadeexitH[u+1]-self.heatCascadeexitH[u+3]) # lineare regression der Temperatur
|
| 187 |
+
self.heatCascadeexitH[u+1] = self.heatCascadeexitH[u+3]
|
| 188 |
+
self.heatCascadeexitH.pop(u+2)
|
| 189 |
+
self.heatCascadedeltaH[u] = self.heatCascadedeltaH[u] + self.heatCascadedeltaH[u+2]
|
| 190 |
+
self.heatCascadedeltaH.pop(u+2)
|
| 191 |
+
self._temperatures.pop(u+2)
|
| 192 |
+
self.deleteDoubleEmpty(u)
|
| 193 |
+
self._temperatures.pop(u)
|
| 194 |
+
self.heatCascadedeltaH.pop(u)
|
| 195 |
+
self.heatCascadeexitH.pop(u)
|
| 196 |
+
u=0
|
| 197 |
+
else:
|
| 198 |
+
self._temperatures.pop(u)
|
| 199 |
+
self.heatCascadeexitH.pop(u)
|
| 200 |
+
self.heatCascadedeltaH.pop(u)
|
| 201 |
+
self._temperatures.pop(u)
|
| 202 |
+
self.heatCascadeexitH.pop(u)
|
| 203 |
+
self.heatCascadedeltaH.pop(u)
|
| 204 |
+
self._temperatures.pop(u)
|
| 205 |
+
self.heatCascadeexitH.pop(u)
|
| 206 |
+
self.heatCascadedeltaH.pop(u)
|
| 207 |
+
u=0
|
| 208 |
+
else:
|
| 209 |
+
u+=1
|
| 210 |
+
else:
|
| 211 |
+
u += 1
|
| 212 |
+
elif self.heatCascadedeltaH[u] > 0 and u != 0:
|
| 213 |
+
if self.heatCascadedeltaH[u + 1] < 0:
|
| 214 |
+
if abs(self.heatCascadedeltaH[u+1]) > abs(self.heatCascadedeltaH[u]):
|
| 215 |
+
self._temperatures[u+1] = self._temperatures[u+2] + ((self._temperatures[u+1]-self._temperatures[u+2]) / (self.heatCascadeexitH[u+1] - self.heatCascadeexitH[u+2]))* (self.heatCascadeexitH[u]-self.heatCascadeexitH[u+2]) # lineare regression der Temperatur
|
| 216 |
+
self.heatCascadedeltaH[u+1] = self.heatCascadedeltaH[u+1] + self.heatCascadedeltaH[u]
|
| 217 |
+
self.heatCascadeexitH[u+1] = self.heatCascadeexitH[u]
|
| 218 |
+
self.heatCascadedeltaH[u] = 0.0
|
| 219 |
+
self.deleteDoubleEmpty(u)
|
| 220 |
+
u = 0
|
| 221 |
+
elif abs(self.heatCascadedeltaH[u+1]) < abs(self.heatCascadedeltaH[u]):
|
| 222 |
+
self._temperatures[u+1] = self._temperatures[u] + ((self._temperatures[u+1]-self._temperatures[u]) / (self.heatCascadeexitH[u+1] - self.heatCascadeexitH[u]))* (self.heatCascadeexitH[u+2]-self.heatCascadeexitH[u]) # lineare regression der Temperatur
|
| 223 |
+
self.heatCascadedeltaH[u] = self.heatCascadeexitH[u] + self.heatCascadeexitH[u+1]
|
| 224 |
+
self.heatCascadeexitH[u+1] = self.heatCascadeexitH[u+2]
|
| 225 |
+
self.heatCascadedeltaH[u+1] = 0.0
|
| 226 |
+
self.deleteDoubleEmpty(u)
|
| 227 |
+
u = 0 # selbes wie u==0
|
| 228 |
+
else:
|
| 229 |
+
self._temperatures.pop(u+1)
|
| 230 |
+
self.heatCascadeexitH.pop(u+1)
|
| 231 |
+
self.heatCascadedeltaH[u] = 0.0
|
| 232 |
+
self.heatCascadedeltaH.pop(u+1)
|
| 233 |
+
self.deleteDoubleEmpty(u)
|
| 234 |
+
u=0
|
| 235 |
+
elif self.heatCascadedeltaH[u + 1] == 0:
|
| 236 |
+
if self.heatCascadedeltaH[u+2]<0:
|
| 237 |
+
if abs(self.heatCascadedeltaH[u+2]) > abs(self.heatCascadedeltaH[u]):
|
| 238 |
+
self._temperatures[u+2] = self._temperatures[u+3] + ((self._temperatures[u+2]-self._temperatures[u+3]) / (self.heatCascadeexitH[u+2] - self.heatCascadeexitH[u+3]))* (self.heatCascadeexitH[u]-self.heatCascadeexitH[u+3])
|
| 239 |
+
self.heatCascadeexitH[u+2] = self.heatCascadeexitH[u]
|
| 240 |
+
self.heatCascadedeltaH[u+2] = self.heatCascadedeltaH[u+2] + self.heatCascadedeltaH[u]
|
| 241 |
+
self._temperatures.pop(u+1)
|
| 242 |
+
self.heatCascadeexitH.pop(u+1)
|
| 243 |
+
self.heatCascadedeltaH.pop(u)
|
| 244 |
+
self.deleteDoubleEmpty(u)
|
| 245 |
+
u=0
|
| 246 |
+
elif abs(self.heatCascadedeltaH[u+2]) < abs(self.heatCascadedeltaH[u]):
|
| 247 |
+
self._temperatures[u+1] = self._temperatures[u+1] - ((self._temperatures[u]-self._temperatures[u+1]) / (self.heatCascadeexitH[u] - self.heatCascadeexitH[u+1]))* (self.heatCascadeexitH[u+1]-self.heatCascadeexitH[u+3]) # lineare regression der Temperatur
|
| 248 |
+
self.heatCascadeexitH[u+1] = self.heatCascadeexitH[u+3]
|
| 249 |
+
self.heatCascadeexitH.pop(u+2)
|
| 250 |
+
self.heatCascadedeltaH[u] = self.heatCascadedeltaH[u] + self.heatCascadedeltaH[u+2]
|
| 251 |
+
self.heatCascadedeltaH.pop(u+2)
|
| 252 |
+
self._temperatures.pop(u+2)
|
| 253 |
+
self.deleteDoubleEmpty(u)
|
| 254 |
+
u=0
|
| 255 |
+
else:
|
| 256 |
+
self._temperatures.pop(u+1)
|
| 257 |
+
self.heatCascadeexitH.pop(u+1)
|
| 258 |
+
self._temperatures.pop(u+1)
|
| 259 |
+
self.heatCascadeexitH.pop(u+1)
|
| 260 |
+
self.heatCascadedeltaH[u] = 0.0
|
| 261 |
+
self.heatCascadedeltaH.pop(u+1)
|
| 262 |
+
self.heatCascadedeltaH.pop(u+1)
|
| 263 |
+
self.deleteDoubleEmpty(u)
|
| 264 |
+
u=0
|
| 265 |
+
else:
|
| 266 |
+
u+=1
|
| 267 |
+
else:
|
| 268 |
+
u+=1
|
| 269 |
+
else:
|
| 270 |
+
u+=1
|
| 271 |
+
|
| 272 |
+
self.deletedPocketdict['H'].append(self.heatCascadeexitH)
|
| 273 |
+
self.deletedPocketdict['deltaH'].append(self.heatCascadedeltaH)
|
| 274 |
+
self.deletedPocketdict['T'].append(self._temperatures)
|
| 275 |
+
self.deletedPocketdictlist.append(self.deletedPocketdict)
|
| 276 |
+
|
| 277 |
+
if self._options['draw'] == True:
|
| 278 |
+
TSPPlot.drawDeletedCurve(self, self.heatCascadedeltaH, self.deletedPocketdict, self._temperatures, plottest)
|
| 279 |
+
|
| 280 |
+
return self.deletedPocketdict
|
src/Modules/Utility/Thermodynamic_Properties.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from CoolProp.CoolProp import PropsSI
|
| 2 |
+
|
| 3 |
+
class ThermodynamicProperties():
|
| 4 |
+
|
| 5 |
+
def get_hprime(T, fluid = 'Water'):
|
| 6 |
+
TK = float(T)+273.15
|
| 7 |
+
return PropsSI('H', 'T', TK, 'Q', 0, fluid) / 1000 # kJ/kg
|
| 8 |
+
|
| 9 |
+
def get_hdouble_prime(T, fluid = 'Water'):
|
| 10 |
+
TK = float(T)+273.15
|
| 11 |
+
return PropsSI('H', 'T', TK, 'Q', 1, fluid) / 1000 # kJ/kg
|
| 12 |
+
|
| 13 |
+
def get_vprime(T, fluid = 'Water'):
|
| 14 |
+
TK = float(T)+273.15
|
| 15 |
+
rho_liq = PropsSI('D', 'T', TK, 'Q', 0, fluid) # kg/m3
|
| 16 |
+
return 1 / rho_liq # m3/kg
|
| 17 |
+
|
| 18 |
+
def get_latentheat(T, fluid = 'Water'):
|
| 19 |
+
TK = float(T)+273.15
|
| 20 |
+
return (PropsSI('H', 'T', TK, 'Q', 1, fluid) / 1000) - (PropsSI('H', 'T', TK, 'Q', 0, fluid) / 1000) # kJ/kg
|
| 21 |
+
|
src/Modules/Utility/splitStreams.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
|
| 3 |
+
class splitStreams():
|
| 4 |
+
def __init__(self, deletedPocketdict,splitdict):
|
| 5 |
+
self.deletedPocketdict = deletedPocketdict
|
| 6 |
+
|
| 7 |
+
self.splitdict = splitdict
|
| 8 |
+
|
| 9 |
+
def splitHotandCold(self):
|
| 10 |
+
self.splitHotTemperatures = []
|
| 11 |
+
self.splitColdTemperatures = []
|
| 12 |
+
self.splitHotH = []
|
| 13 |
+
self.splitColdH = []
|
| 14 |
+
testHot = 0
|
| 15 |
+
testCold = 0
|
| 16 |
+
|
| 17 |
+
for i in range(len(self.deletedPocketdict['T'])):
|
| 18 |
+
for j in range(len(self.deletedPocketdict['T'][i])):
|
| 19 |
+
if j >= len(self.deletedPocketdict['deltaH'][i]):
|
| 20 |
+
continue
|
| 21 |
+
if self.deletedPocketdict['deltaH'][i][j] > 0 and testHot == 0:
|
| 22 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j])
|
| 23 |
+
self.splitHotH.append(self.deletedPocketdict['H'][i][j])
|
| 24 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 25 |
+
self.splitHotH.append(self.deletedPocketdict['H'][i][j+1])
|
| 26 |
+
testHot = 1
|
| 27 |
+
|
| 28 |
+
elif self.deletedPocketdict['deltaH'][i][j] > 0 and testHot == 1:
|
| 29 |
+
if j == len(self.deletedPocketdict['deltaH'][i])-1:
|
| 30 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 31 |
+
self.splitHotH.append(self.deletedPocketdict['H'][i][j+1])
|
| 32 |
+
elif self.deletedPocketdict['deltaH'][i][j+1] < 0:
|
| 33 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j])
|
| 34 |
+
self.splitHotH.append(self.splitHotH[-1])
|
| 35 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 36 |
+
self.splitHotH.append(self.splitHotH[-1] + self.deletedPocketdict['deltaH'][i][j])# Anpassen
|
| 37 |
+
else:
|
| 38 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 39 |
+
self.splitHotH.append(self.deletedPocketdict['H'][i][j+1])
|
| 40 |
+
|
| 41 |
+
elif self.deletedPocketdict['deltaH'][i][j] < 0 and testCold == 0:
|
| 42 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j])
|
| 43 |
+
self.splitColdH.append(self.deletedPocketdict['H'][i][j])
|
| 44 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 45 |
+
self.splitColdH.append(self.deletedPocketdict['H'][i][j+1])
|
| 46 |
+
testCold = 1
|
| 47 |
+
elif self.deletedPocketdict['deltaH'][i][j] < 0 and testCold == 1:
|
| 48 |
+
if j == len(self.deletedPocketdict['deltaH'][i])-1:
|
| 49 |
+
if self.splitColdH[-1] < 0:
|
| 50 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 51 |
+
self.splitColdH.append(self.deletedPocketdict['deltaH'][i][j] + self.splitColdH[-1])
|
| 52 |
+
else:
|
| 53 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 54 |
+
self.splitColdH.append(self.deletedPocketdict['H'][i][j+1])
|
| 55 |
+
elif self.deletedPocketdict['deltaH'][i][j+1] > 0 or self.deletedPocketdict['deltaH'][i][j-1]:
|
| 56 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j])
|
| 57 |
+
self.splitColdH.append(self.splitColdH[-1])
|
| 58 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 59 |
+
self.splitColdH.append(self.deletedPocketdict['deltaH'][i][j] + self.splitColdH[-1])# Anpassen
|
| 60 |
+
else:
|
| 61 |
+
if self.splitColdH[-1] < 0:
|
| 62 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 63 |
+
self.splitColdH.append(self.deletedPocketdict['deltaH'][i][j] + self.splitColdH[-1])
|
| 64 |
+
else:
|
| 65 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 66 |
+
self.splitColdH.append(self.deletedPocketdict['H'][i][j+1])
|
| 67 |
+
elif self.deletedPocketdict['deltaH'][i][j] == 0:
|
| 68 |
+
if self.deletedPocketdict['deltaH'][i][j-1] < 0:
|
| 69 |
+
self.splitColdTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 70 |
+
self.splitColdH.append(self.deletedPocketdict['H'][i][j+1])
|
| 71 |
+
|
| 72 |
+
elif self.deletedPocketdict['deltaH'][i][j-1] > 0:
|
| 73 |
+
self.splitHotTemperatures.append(self.deletedPocketdict['T'][i][j+1])
|
| 74 |
+
self.splitHotH.append(self.deletedPocketdict['H'][i][j+1])
|
| 75 |
+
else:
|
| 76 |
+
pass
|
| 77 |
+
|
| 78 |
+
else:
|
| 79 |
+
pass
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
self.splitColddeltaH = []
|
| 84 |
+
self.splitHotdeltaH = []
|
| 85 |
+
for i in range(len(self.splitColdH)-1):
|
| 86 |
+
self.splitColddeltaH.append(self.splitColdH[i+1]-self.splitColdH[i])
|
| 87 |
+
|
| 88 |
+
for i in range(len(self.splitHotH)-1):
|
| 89 |
+
self.splitHotdeltaH.append(self.splitHotH[i+1]-self.splitHotH[i])
|
| 90 |
+
|
| 91 |
+
self.splitHotTemperatures
|
| 92 |
+
#self.splitHotH.sort(reverse=True)
|
| 93 |
+
self.splitHotdeltaH
|
| 94 |
+
self.splitColdTemperatures
|
| 95 |
+
self.splitColdH
|
| 96 |
+
self.splitColddeltaH
|
| 97 |
+
|
| 98 |
+
self.splitdict['HotTemperatures'].append(self.splitHotTemperatures)
|
| 99 |
+
self.splitdict['HotH'].append(self.splitHotH)
|
| 100 |
+
self.splitdict['HotdeltaH'].append(self.splitHotdeltaH)
|
| 101 |
+
self.splitdict['ColdTemperatures'].append(self.splitColdTemperatures)
|
| 102 |
+
self.splitdict['ColdH'].append(self.splitColdH)
|
| 103 |
+
self.splitdict['ColddeltaH'].append(self.splitColddeltaH)
|
| 104 |
+
|
| 105 |
+
return self.splitdict
|
src/Modules/__init__.py
ADDED
|
File without changes
|
src/pages/potential_analysis.py
CHANGED
|
@@ -10,16 +10,16 @@ from PIL import Image, ImageDraw, ImageFont
|
|
| 10 |
from graphics_utils import draw_smooth_ellipse
|
| 11 |
from datetime import datetime
|
| 12 |
|
| 13 |
-
# Add the
|
| 14 |
-
|
| 15 |
-
if
|
| 16 |
-
|
| 17 |
|
| 18 |
# Import pinch analysis modules
|
| 19 |
try:
|
| 20 |
from Modules.Pinch.Pinch import Pinch
|
| 21 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 22 |
-
from Pinch_main import Pinchmain
|
| 23 |
PINCH_AVAILABLE = True
|
| 24 |
PINCH_IMPORT_ERROR = None
|
| 25 |
except ImportError as e:
|
|
|
|
| 10 |
from graphics_utils import draw_smooth_ellipse
|
| 11 |
from datetime import datetime
|
| 12 |
|
| 13 |
+
# # Add the src directory to the path for imports
|
| 14 |
+
# src_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
| 15 |
+
# if src_path not in sys.path:
|
| 16 |
+
# sys.path.insert(0, src_path)
|
| 17 |
|
| 18 |
# Import pinch analysis modules
|
| 19 |
try:
|
| 20 |
from Modules.Pinch.Pinch import Pinch
|
| 21 |
from Modules.HeatPumpIntegration.HeatPumpIntegration import HeatPumpIntegration as HPI
|
| 22 |
+
from Modules.Pinch_main import Pinchmain
|
| 23 |
PINCH_AVAILABLE = True
|
| 24 |
PINCH_IMPORT_ERROR = None
|
| 25 |
except ImportError as e:
|