drzg commited on
Commit
db79a6a
·
1 Parent(s): 2462d27

new modules

Browse files
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 pinch_tool directory to the path for imports
14
- pinch_tool_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'pinch_tool'))
15
- if pinch_tool_path not in sys.path:
16
- sys.path.insert(0, pinch_tool_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 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: