Coverage for backend/pinch_service/OpenPinch/src/analysis/operation_analysis.py: 4%

283 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-11-06 23:27 +0000

1import copy 

2from typing import Optional 

3from ..utils import * 

4from ..classes import * 

5from .support_methods import * 

6 

7 

8# TODO: Refactor this entire file. 

9 

10__all__ = ["get_energy_transfer_retrofit_analysis"] 

11 

12####################################################################################################### 

13# Public API --- TODO 

14####################################################################################################### 

15 

16def get_energy_transfer_retrofit_analysis(site: Zone): 

17 """Calculates the ETD and retrofit targets. 

18 """ 

19 

20 # Prepares variables and arrays 

21 ETD = [ [0, 0] for i in range(1 + len(site.subzones) * 3) ] 

22 ETD_star = copy.deepcopy(ETD) 

23 

24 for z in site.subzones: 

25 # Redefine heat exchanger pockets based on detailed ETD retrofit analysis 

26 Req_ut = True if z.hot_utility_target + z.cold_utility_target > ZERO else False 

27 if site.config.GCC_VERT_CUT_KINK_OPTION and not Req_ut: 

28 z.graphs['GCC_etc'] = site.Reshape_GCC_Pockets(z.graphs['PT_star'], z.graphs['GCC_etc']) 

29 site.Extract_Pro_ETC(ETD_star, z, z.graphs['PT_star'], Req_ut) 

30 site.Extract_Pro_ETC(ETD, z, z.graphs['PT'], Req_ut) 

31 

32 site_tit: Zone = site.targets[TargetType.DI.value] 

33 PT_TIT = site_tit.graphs['PT'] 

34 PT_star_TIT = site_tit.graphs['PT_star'] 

35 

36 # Forms a complete set of temperature intervals 

37 T_int_star = site.Compile_ETD_T_int(ETD_star, PT_star_TIT) 

38 T_int = site.Compile_ETD_T_int(ETD, PT_TIT) 

39 

40 # Expands Heat Cascade Table to be based on the complete set of temperature intervals 

41 ETD_star = site.Transpose_ETD_T(ETD_star, T_int_star) 

42 ETD = site.Transpose_ETD_T(ETD, T_int) 

43 

44 # Calculates the ETD 

45 ETD_star_header = site.Stack_ETD(ETD_star, PT_star_TIT, 'ETD', True) 

46 ETD_header = site.Stack_ETD(ETD, PT_TIT, 'ETD', False) 

47 

48 # Shift thermodynamic limiting curve to match the end of the ETD 

49 dh = ETD_star[-1][1] - PT_TIT[10][0] 

50 PT_TIT = shift_heat_cascade(PT_TIT, dh, 10) 

51 

52 # Determines the Advanced Composite Curve that combines conventional CC and the ETD 

53 ACC_star = site.Calc_ACCN(ETD_star, PT_star_TIT) 

54 ACC = site.Calc_ACCN(ETD, PT_TIT) 

55 

56 # Reduces the number of T int to the minimum 

57 site.Simplify_ETD(ETD_star) 

58 site.Simplify_ETD(ETD) 

59 site.Simplify_ETD(ACC_star) 

60 site.Simplify_ETD(ACC) 

61 

62 # Record retrofit targets 

63 Hot_Pinch, Cold_Pinch = get_pinch_temperatures(PT_star_TIT, 10, 0) 

64 

65 Retrofit = Zone(name=TargetType.ET.value, config=site.config) 

66 Retrofit.hot_pinch = Hot_Pinch 

67 Retrofit.hot_utility_target = ETD_star[-1][1] 

68 Retrofit.cold_utility_target = ETD_star[-1][-1] 

69 Retrofit.retrofit_target = Retrofit.hot_utility_target - site_tit.hot_utility_target 

70 Retrofit.heat_recovery_target = site_tit.heat_recovery_target - Retrofit.retrofit_target 

71 Retrofit.degree_of_int = Retrofit.heat_recovery_target / site_tit.heat_recovery_limit if site_tit.heat_recovery_limit > 0 else 1 

72 Retrofit.add_graph('ETD', ETD) 

73 Retrofit.add_graph('ETD_star', ETD_star) 

74 Retrofit.add_graph('ACC', ACC) 

75 Retrofit.add_graph('ACC_star', ACC_star) 

76 Retrofit.add_graph('ETD_header', ETD_header) 

77 site.add_zone(Retrofit) 

78 

79 

80####################################################################################################### 

81# Helper Functions 

82####################################################################################################### 

83 

84def Reshape_GCC_Pockets(site, PT_star, GCC_etc): 

85 """Redefine GCC pockets based on possible HEN retrofit design considerations. 

86 """ 

87 GCC_etc = GCC_etc[:2] 

88 for i in range(len(GCC_etc)): 

89 GCC_etc[i] = GCC_etc[i][:len(PT_star[0])] 

90 

91 min_H_cross = 1E+35 

92 

93 for j in range(len(PT_star[0])): 

94 GCC_etc[1][j] = PT_star[1][j] 

95 if j == 0 or j == len(PT_star[0]): 

96 GCC_etc[2][j] = 0 

97 else: 

98 if abs(PT_star[9][j]) > ZERO: 

99 if PT_star[3][j] > PT_star[6][j]: 

100 GCC_etc[2][j] = GCC_etc[2][j - 1] + PT_star[2][j] * PT_star[3][j] 

101 else: 

102 GCC_etc[2][j] = GCC_etc[2][j - 1] - PT_star[2][j] * PT_star[6][j] 

103 else: 

104 GCC_etc[2][j] = GCC_etc[2][j - 1] 

105 if PT_star[3][j] > ZERO and PT_star[6][j] > ZERO: 

106 min_H_cross = min(PT_star[11][j], min_H_cross) 

107 min_H_cross = min(PT_star[11][j - 1], min_H_cross) 

108 

109 DH_shift = GCC_etc[2][len(GCC_etc[0])] 

110 for j in range(len(PT_star[0])): 

111 GCC_etc[2][j] = GCC_etc[2][j] - DH_shift 

112 

113 for j in range(1, len(PT_star[0])): 

114 if min_H_cross > (min(GCC_etc[2][j], GCC_etc[2][j - 1])) + ZERO and min_H_cross < (max(GCC_etc[2][j], GCC_etc[2][j - 1])) - ZERO: 

115 j_0 = j 

116 h_0 = min_H_cross 

117 T_new = linear_interpolation(h_0, GCC_etc[2][j_0], GCC_etc[2][j_0 - 1], GCC_etc[1][j_0], GCC_etc[1][j_0 - 1]) 

118 PT_star = insert_temperature_interval_into_pt(PT_star, T_new, j_0) 

119 j_0 = j 

120 GCC_etc = insert_temperature_interval_into_pt(GCC_etc, T_new, j_0) 

121 

122 for j in range(len(PT_star[0])): 

123 if PT_star[11][j] > min_H_cross: 

124 PT_star[11][j] = min_H_cross 

125 return GCC_etc 

126 

127def Write_HSDT(site, ETD, ETD_header, sheet, row=4, col=1, exclude_small_DH=False): 

128 """Prints the ETD table to a spreadsheet. 

129 """ 

130 # DoEvents 

131 if not sheet.visible: 

132 sheet.visible = True 

133 

134 k = 1 

135 row_0 = row 

136 sheet.cells(1, col).value = 'Ti' 

137 # sheet.cells(1, col).characters[1].font.defscript = True 

138 sheet.cells(3, col).value = chr(176) 

139 

140 for i in range(1, len(ETD), 3): 

141 sheet.cells(1, col + k).value = ETD[i][0] 

142 sheet.cells(2, col + k).value = chr(916) + 'Hnet' 

143 # sheet.cells(2, col + k).characters[2:5].font.defscript = True 

144 sheet.cells(3, col + k).value = 'kW' 

145 k += 1 

146 

147 k = 0 

148 for j in range(len(ETD[0])): 

149 sheet.cells(row + (j - 1), col + k).value = ETD[0][j] 

150 

151 k = 1 

152 for i in range(1, len(ETD), 3): 

153 for j in range(1, len(ETD[0])): 

154 sheet.cells(row + (j - 1), col + k).value = ETD[i][j] if ETD_header[i + 1][5] == 0 or exclude_small_DH == False else 0 

155 k += 1 

156 

157 # With Range(sheet.cells(row_0, 2), sheet.cells(row_0 + len(ETD[0]) - 1, (len(ETD) - 1) / 3 + 3)) 

158 # Add conditional formatting to Table 

159 # .FormatConditions.AddColorScale ColorScaleType:=3 

160 # .FormatConditions(.FormatConditions.count).SetFirstPriority 

161 # .FormatConditions(1).ColorScaleCriteria(1).Type = xlConditionValueLowestValue 

162 # With .FormatConditions(1).ColorScaleCriteria(1).FormatColor 

163 # .ThemeColor = xlThemeColorAccent1 

164 # .TintAndShade = 0 

165 # End With 

166 # .FormatConditions(1).ColorScaleCriteria(2).Type = xlConditionValueNumber 

167 # .FormatConditions(1).ColorScaleCriteria(2).Value = 0 

168 # With .FormatConditions(1).ColorScaleCriteria(2).FormatColor 

169 # .ThemeColor = xlThemeColorDark1 

170 # .TintAndShade = 0 

171 # End With 

172 # .FormatConditions(1).ColorScaleCriteria(3).Type = xlConditionValueHighestValue 

173 # With .FormatConditions(1).ColorScaleCriteria(3).FormatColor 

174 # .Color = 255 

175 # .TintAndShade = 0 

176 # End With 

177 

178 # Draw boarders for Table 

179 # With .Borders(xlEdgeLeft) 

180 # .LineStyle = xlContinuous 

181 # .ThemeColor = 1 

182 # .TintAndShade = -0.149998474074526 

183 # .Weight = xlThin 

184 # End With 

185 # With .Borders(xlEdgeTop) 

186 # .LineStyle = xlContinuous 

187 # .ThemeColor = 1 

188 # .TintAndShade = -0.149998474074526 

189 # .Weight = xlThin 

190 # End With 

191 # With .Borders(xlEdgeBottom) 

192 # .LineStyle = xlContinuous 

193 # .ThemeColor = 1 

194 # .TintAndShade = -0.149998474074526 

195 # .Weight = xlThin 

196 # End With 

197 # With .Borders(xlEdgeRight) 

198 # .LineStyle = xlContinuous 

199 # .ThemeColor = 1 

200 # .TintAndShade = -0.149998474074526 

201 # .Weight = xlThin 

202 # End With 

203 # With .Borders(xlInsideVertical) 

204 # .LineStyle = xlContinuous 

205 # .ThemeColor = 1 

206 # .TintAndShade = -0.149998474074526 

207 # .Weight = xlThin 

208 # End With 

209 # With .Borders(xlInsideHorizontal) 

210 # .LineStyle = xlContinuous 

211 # .ThemeColor = 1 

212 # .TintAndShade = -0.149998474074526 

213 # .Weight = xlThin 

214 # End With 

215 # End With 

216 

217def Compile_ETD_T_int(site, ETD, PT_TIT): 

218 """Grabs temperatures from every process operation GCC with a defined system,  

219 order, and remove duplicates. 

220 """ 

221 T_int = [ [None for i in range(10000)] ] 

222 

223 n = 0 

224 j = 1 

225 while j < len(ETD): 

226 for i in range(1, len(ETD[0])): 

227 if ETD[j][i] == None: 

228 break 

229 T_int[0][n] = ETD[j][i] 

230 n += 1 

231 j += 3 

232 

233 j_0 = j + 1 

234 

235 for j in range(0, len(PT_TIT), 3): 

236 for i in range(len(PT_TIT[0])): 

237 if PT_TIT[j][i] == None: 

238 break 

239 T_int[0][n] = PT_TIT[j][i] 

240 n += 1 

241 

242 T_int = T_int.sort(reverse=True) 

243 

244 # TODO: I think this is unnecessary because the None values would be removed in get_ordered_list. 

245 # if T_int[0][len(T_int[0])] < ZERO or T_int[0][len(T_int[0])] == None: 

246 # for i in range(len(T_int[0]) - 1, -1, -1): 

247 # if T_int[0][i] == None: 

248 # break 

249 # T_int[0][i] = 0 

250 return T_int 

251 

252def Transpose_ETD_T(site, ETD, T_int): 

253 """Transposes temperature intervals from individual GCC cascades to a common set of temperature intervals for the entire system. 

254 """ 

255 ETD_temp = [ [ None for j in range(len(T_int[0]) + 1)] for i in range(len(ETD))] 

256 

257 ETD_temp[0][0] = 'T' 

258 for i in range(1, len(ETD_temp[0])): 

259 ETD_temp[0][i] = T_int[0][i - 1] 

260 

261 for j in range(1, len(ETD), 3): 

262 k = 2 

263 ETD_temp[j][0] = ETD[j][0] 

264 ETD_temp[j + 1][0] = None 

265 ETD_temp[j + 2][0] = ETD[j + 2][0] 

266 

267 ETD_temp[j][1] = None 

268 ETD_temp[j + 1][1] = ETD[j + 2][1] 

269 ETD_temp[j + 2][1] = 0 

270 

271 for i in range(2, len(ETD_temp[0])): 

272 if k >= len(ETD[0]): 

273 ETD_temp[j][i] = 0 

274 ETD_temp[j + 1][i] = ETD_temp[j + 1][i - 1] 

275 continue 

276 if (ETD_temp[0][i - 1] <= ETD[j][k - 1] + ZERO) and (ETD_temp[0][i] >= ETD[j][k] - ZERO): 

277 CPnet = ETD[j + 1][k] 

278 dt = ETD_temp[0][i - 1] - ETD_temp[0][i] 

279 ETD_temp[j][i] = dt * CPnet 

280 ETD_temp[j + 1][i] = ETD_temp[j + 1][i - 1] + dt * CPnet 

281 if abs(ETD_temp[0][i] - ETD[j][k]) < ZERO: 

282 k += 1 

283 else: 

284 ETD_temp[j][i] = 0 

285 ETD_temp[j + 1][i] = ETD_temp[j + 1][i - 1] 

286 return ETD_temp 

287 

288def Simplify_ETD(site, ETD): 

289 """Reduces the ETD (and HSDT) to the minimum number of T intervals by removing all  

290 intervals between which there are not changes in CP for all process operations. 

291 """ 

292 # Remove low temperature intervals that exceed the maximum temperatures 

293 # for i in range(len(ETD[0]) - 1, 1, -1): # Loop from lowerest to highest temperature 

294 # for j in range(1, len(ETD), 3): 

295 # if ETD[j][i] > ZERO: 

296 # break # Temperature interval cannot be removed if true 

297 # else: 

298 # continue 

299 # break 

300 

301 # if i < len(ETD[0]): 

302 # for j in range(len(ETD)): 

303 # ETD[j] = ETD[j][:i] 

304 

305 # # Remove high temperature intervals that exceed the maximum temperatures 

306 # for i in range(2, len(ETD[0])): # Loop from highest to lowerest temperature 

307 # for j in range(1, len(ETD), 3): 

308 # if abs(ETD[j][i]) > ZERO: 

309 # break # Temperature interval cannot be removed if true 

310 # else: 

311 # continue 

312 # break 

313 

314 # i = i - 2 

315 # if i > 0: 

316 # for n in range(1, len(ETD[0]) - i): 

317 # for m in range(len(ETD)): 

318 # ETD[m][n] = ETD[m][n + i] 

319 # for row in ETD: 

320 # row.pop() 

321 

322 # Join two T intervals where CP is constant for all zones 

323 for i in range(len(ETD[0]) - 1, 2, -1): # Loop from lowest to highest temperature 

324 for j in range(1, len(ETD), 3): 

325 CP_0 = ETD[j][i] / (ETD[0][i - 1] - ETD[0][i]) 

326 CP_1 = ETD[j][i - 1] / (ETD[0][i - 2] - ETD[0][i - 1]) 

327 if abs(CP_0 - CP_1) > ZERO: 

328 break # Temperature interval cannot be removed if true 

329 else: 

330 n = i 

331 ETD[0][n - 1] = ETD[0][n] 

332 for m in range(1, len(ETD), 3): 

333 ETD[m][n - 1] = ETD[m][n - 1] + ETD[m][n] 

334 ETD[m + 1][n - 1] = ETD[m + 1][n - 1] + ETD[m][n] 

335 ETD[m + 2][n - 1] = ETD[m + 2][n - 1] + ETD[m][n] 

336 for n in range(i, len(ETD[0]) - 1): 

337 for m in range(len(ETD)): 

338 ETD[m][n] = ETD[m][n + 1] 

339 for row in ETD: 

340 row.pop() 

341 

342def Stack_ETD(site, ETD, PT, Diagram_type, shifted): 

343 """Determine the order and stack individual heat cascades of process operations. 

344 """ 

345 Hot_Pinch, Cold_Pinch = get_pinch_temperatures(PT, 10, 0) 

346 

347 ETD_header = [ [None for j in range(11)] for i in range(len(ETD))] 

348 

349 for j in range(1, len(ETD), 3): 

350 site.Characterise_ETC(ETD, ETD_header, Hot_Pinch, Cold_Pinch, j + 1, ETD[j + 2][0]) 

351 

352 # Reorder HX in the ETD 

353 ETD_temp = copy.deepcopy(ETD) 

354 

355 for j in range(1, len(ETD)): 

356 ETD[j] = [None for k in range(len(ETD[0]))] 

357 

358 ETD_header_temp = copy.deepcopy(ETD_header) 

359 

360 col_ETD = 2 

361 site.Write_Next_ETC(ETD, ETD_temp, ETD_header, ETD_header_temp, col_ETD) 

362 

363 HX_type_1 = 'C' 

364 HX_type_2 = 'R' 

365 HX_type_3 = 'H' 

366 

367 j_0 = 0 

368 for j in range(3, len(ETD), 3): 

369 if ETD[j][0] == HX_type_1[:1] or \ 

370 ETD[j][0] == HX_type_2[:1] or \ 

371 ETD[j][0] == HX_type_3[:1]: 

372 if j_0 == 0: 

373 j_0 = j 

374 for i in range(1, len(ETD[0])): 

375 if j == j_0: 

376 ETD[j][i] = 0 if ETD_header[j - 1][5] == 1 and shifted else ETD[j - 1][i] 

377 else: 

378 ETD[j][i] = ETD[j_0][i] if ETD_header[j - 1][5] == 1 and shifted else ETD[j - 1][i] + ETD[j_0][i] 

379 j_0 = j 

380 

381 return ETD_header 

382 

383def Calc_ACCN(site, ETD, PT_TIT): 

384 """Calculate Adv CC with integrated ETD. 

385 """ 

386 ACC = [ 

387 [ None for j in range(len(ETD[0])) ] for i in range(len(ETD) + 3) 

388 ] 

389 

390 i = 0 

391 ACC[0][0] = ETD[0][0] 

392 ACC[1][0] = 'HCC' 

393 

394 for j in range(1, len(ETD), 3): 

395 ACC[j + 3][0] = ETD[j][0] 

396 ACC[j + 4][0] = ETD[j + 1][0] 

397 ACC[j + 5][0] = ETD[j + 2][0] 

398 

399 for i in range(1, len(ACC[0])): 

400 ACC[0][i] = ETD[0][i] 

401 

402 if abs(ACC[0][i] - PT_TIT[0][i]) > ZERO: 

403 PT_TIT = insert_temperature_interval_into_pt(PT_TIT, ACC[0][i], i) 

404 

405 if i > 1: 

406 ACC[1][i] = PT_TIT[4][i] - PT_TIT[4][i - 1] 

407 ACC[2][i] = PT_TIT[4][i] 

408 ACC[3][i] = PT_TIT[4][i] 

409 

410 for i in range(1, len(ACC[0])): 

411 for j in range(1, len(ETD), 3): 

412 ACC[j + 3][i] = ETD[j][i] 

413 ACC[j + 4][i] = ETD[j + 1][i] 

414 ACC[j + 5][i] = ETD[j + 2][i] + ACC[3][i] 

415 

416 return ACC 

417 

418def Characterise_ETC(site, ETD, ETD_header, Hot_Pinch, Cold_Pinch, Col_j, HX_mode): 

419 """Characterises the shape, enclosed area, and temperature driving force of each heat cascade. 

420 """ 

421 TH_tot_area = 0 

422 TH_w_tot_area = 0 

423 T_h_max = -1000 

424 H_max = 0 

425 ETD_header[Col_j][0] = 0 # Check for Cross-Pinch Heat Transfer 

426 t_const = 99 # tune weghting constant 

427 for i in range(2, len(ETD[0])): 

428 TH_sub_area = abs(0.5 * (ETD[Col_j][i - 1] + ETD[Col_j][i]) / (ETD[0][i - 1] - ETD[0][i])) # Determine T-H area (row 1) 

429 # Determine weighting factor 

430 if ETD[0][i] > Hot_Pinch + ZERO: 

431 w = 1 / (abs((ETD[0][i - 1] + ETD[0][i]) / 2 - Hot_Pinch) / t_const + 1) 

432 elif ETD[0][i] < Cold_Pinch - ZERO: 

433 w = 1 / (abs((ETD[0][i - 1] + ETD[0][i]) / 2 - Cold_Pinch) / t_const + 1) 

434 else: 

435 w = 1 

436 if abs(ETD[Col_j][i]) > ZERO: 

437 ETD_header[Col_j][4] = 1 

438 TH_tot_area += TH_sub_area 

439 TH_w_tot_area += w * TH_sub_area 

440 if H_max < abs(ETD[Col_j][i]): 

441 H_max = abs(ETD[Col_j][i]) 

442 if T_h_max == -1000 and abs(ETD[Col_j - 1][i]) > ZERO: 

443 T_h_max = (ETD[0][i - 1] + 273.15) if HX_mode == 'C' else 1 / (ETD[0][i - 1] + 273.15) 

444 

445 ETD_header[Col_j][0] = ETD[Col_j - 1][0] 

446 ETD_header[Col_j][1] = TH_w_tot_area 

447 ETD_header[Col_j][2] = TH_tot_area 

448 ETD_header[Col_j][3] = H_max 

449 ETD_header[Col_j][4] = T_h_max 

450 

451 ETD_header[Col_j][10] = 1 / T_h_max if HX_mode == 'C' else T_h_max 

452 

453def Write_Next_ETC(site, ETD, ETD_temp, ETD_header, ETD_header_temp, k): 

454 H_thres = site.config.THRESHOLD 

455 TH_area_thres = site.config.AREA_THRESHOLD * 1000 

456 for HX_Type in ['C', 'R', 'H']: 

457 HX_num = 0 

458 for i in range(3, len(ETD), 3): 

459 if ETD_temp[i][0] == HX_Type: 

460 HX_num += 1 

461 

462 if HX_num > 0: 

463 k_max = k + (HX_num - 1) * 3 + 1 

464 for k in range(k, k_max, 3): 

465 Var_temp = 0 

466 for j in range(2, len(ETD_temp), 3): 

467 if ETD_header_temp[j][10] > Var_temp and ETD_temp[j + 1][0] == HX_Type: 

468 Var_temp = ETD_header_temp[j][10] 

469 k_1 = j 

470 ETD_header_temp[k_1][10] = 0 

471 for i in range(len(ETD_temp[0])): 

472 ETD[k - 1][i] = ETD_temp[k_1 - 1][i] 

473 ETD[k][i] = ETD_temp[k_1][i] 

474 

475 ETD[k + 1][0] = ETD_temp[k_1 + 1][0] 

476 for i in range(len(ETD_header_temp[0])): 

477 ETD_header[k][i] = ETD_header_temp[k_1][i] 

478 ETD_header[k][5] = 0 

479 if (site.config.SET_MIN_DH_THRES and ETD_header[k][3] < H_thres) or (site.config.SET_MIN_TH_AREA and ETD_header[k][1] < TH_area_thres): 

480 if HX_Type[:1] == 'R': # (RetrofitForm.Excl_UE_Option.Value and (HX_Type[:1] = 'H' or HX_Type[:1] = 'C')) Or 

481 ETD_header[k][6] = 1 

482 k += 3 

483 

484def Extract_Pro_ETC(site, ETD, z, PT, Req_ut): 

485 """Save an individual process operation GCC for the ETD. 

486 """ 

487 j = z.zone_num * 3 - 1 

488 ETD[j - 1][0] = z.name 

489 ETD[j][0] = 'CP net' 

490 if Req_ut: 

491 ETD[j + 1][0] = 'H' if PT[10][0] > ZERO else 'C' 

492 else: 

493 ETD[j + 1][0] = 'R' 

494 

495 n = max(len(ETD[0]) - 1, len(PT[0])) + 1 

496 if n != len(ETD[0]): 

497 for i in range(len(ETD)): 

498 ETD[i] += [None for k in range(n - len(ETD[i]))] 

499 for i in range(len(PT[0])): 

500 ETD[j - 1][i + 1] = PT[0][i] 

501 ETD[j][i + 1] = PT[8][i] 

502 

503 ETD[j + 1][1] = PT[10][0] 

504