@@ -223,230 +223,7 @@ def Calculate(self, model: Model) -> None:
223
223
self .Cgath .value = 1.15 * self .ccgathadjfactor .value * self ._indirect_cost_factor * (
224
224
(model .wellbores .nprod .value + model .wellbores .ninj .value ) * 750 * 500. + self .Cpumps ) / 1E6
225
225
226
- # plant costs
227
- if (model .surfaceplant .enduse_option .value == EndUseOptions .HEAT
228
- and model .surfaceplant .plant_type .value not in [PlantType .ABSORPTION_CHILLER , PlantType .HEAT_PUMP , PlantType .DISTRICT_HEATING ]): # direct-use
229
- if self .ccplantfixed .Valid :
230
- self .Cplant .value = self .ccplantfixed .value
231
- else :
232
- self .Cplant .value = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
233
- model .surfaceplant .HeatExtracted .value ) * 1000. # 1.15 for 15% contingency
234
-
235
- # absorption chiller
236
- elif model .surfaceplant .enduse_option .value == EndUseOptions .HEAT and model .surfaceplant .plant_type .value == PlantType .ABSORPTION_CHILLER : # absorption chiller
237
- if self .ccplantfixed .Valid :
238
- self .Cplant .value = self .ccplantfixed .value
239
- else :
240
- # this is for the direct-use part all the way up to the absorption chiller
241
- self .Cplant .value = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
242
- model .surfaceplant .HeatExtracted .value ) * 1000. # 1.15 for 15% contingency
243
- if self .chillercapex .value == - 1 : # no value provided by user, use built-in correlation ($2500/ton)
244
- self .chillercapex .value = self ._indirect_cost_factor * 1.15 * np .max (
245
- model .surfaceplant .cooling_produced .value ) * 1000 / 3.517 * 2500 / 1e6 # $2,500/ton of cooling. 1.15 for 15% contingency
246
-
247
- # now add chiller cost to surface plant cost
248
- self .Cplant .value += self .chillercapex .value
249
-
250
- # heat pump
251
- elif model .surfaceplant .enduse_option .value == EndUseOptions .HEAT and model .surfaceplant .plant_type .value == PlantType .HEAT_PUMP :
252
- if self .ccplantfixed .Valid :
253
- self .Cplant .value = self .ccplantfixed .value
254
- else :
255
- # this is for the direct-use part all the way up to the heat pump
256
- self .Cplant .value = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
257
- model .surfaceplant .HeatExtracted .value ) * 1000. # 1.15 for 15% contingency
258
- if self .heatpumpcapex .value == - 1 : # no value provided by user, use built-in correlation ($150/kWth)
259
- self .heatpumpcapex .value = self ._indirect_cost_factor * 1.15 * np .max (
260
- model .surfaceplant .HeatProduced .value ) * 1000 * 150 / 1e6 # $150/kW. 1.15 for 15% contingency
261
-
262
- # now add heat pump cost to surface plant cost
263
- self .Cplant .value += self .heatpumpcapex .value
264
-
265
- # district heating
266
- elif model .surfaceplant .enduse_option .value == EndUseOptions .HEAT and model .surfaceplant .plant_type .value == PlantType .DISTRICT_HEATING :
267
- if self .ccplantfixed .Valid :
268
- self .Cplant .value = self .ccplantfixed .value
269
- else :
270
- self .Cplant .value = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
271
- model .surfaceplant .HeatExtracted .value ) * 1000. # 1.15 for 15% contingency
272
-
273
- self .peakingboilercost .value = (self .peaking_boiler_cost_per_kW .quantity ()
274
- .to ('USD / kilowatt' ).magnitude
275
- * model .surfaceplant .max_peaking_boiler_demand .value
276
- / 1000 )
277
-
278
- self .Cplant .value += self .peakingboilercost .value # add peaking boiler cost to surface plant cost
279
-
280
-
281
- else : # all other options have power plant
282
- if model .surfaceplant .plant_type .value == PlantType .SUB_CRITICAL_ORC :
283
- MaxProducedTemperature = np .max (model .surfaceplant .TenteringPP .value )
284
- if MaxProducedTemperature < 150. :
285
- C3 = - 1.458333E-3
286
- C2 = 7.6875E-1
287
- C1 = - 1.347917E2
288
- C0 = 1.0075E4
289
- CCAPP1 = C3 * MaxProducedTemperature ** 3 + C2 * MaxProducedTemperature ** 2 + C1 * MaxProducedTemperature + C0
290
- else :
291
- CCAPP1 = 2231 - 2 * (MaxProducedTemperature - 150. )
292
- x = np .max (model .surfaceplant .ElectricityProduced .value )
293
- y = np .max (model .surfaceplant .ElectricityProduced .value )
294
- if y == 0.0 :
295
- y = 15.0
296
- z = math .pow (y / 15. , - 0.06 )
297
- self .Cplantcorrelation = CCAPP1 * z * x * 1000. / 1E6
298
-
299
- elif model .surfaceplant .plant_type .value == PlantType .SUPER_CRITICAL_ORC :
300
- MaxProducedTemperature = np .max (model .surfaceplant .TenteringPP .value )
301
- if MaxProducedTemperature < 150. :
302
- C3 = - 1.458333E-3
303
- C2 = 7.6875E-1
304
- C1 = - 1.347917E2
305
- C0 = 1.0075E4
306
- CCAPP1 = C3 * MaxProducedTemperature ** 3 + C2 * MaxProducedTemperature ** 2 + C1 * MaxProducedTemperature + C0
307
- else :
308
- CCAPP1 = 2231 - 2 * (MaxProducedTemperature - 150. )
309
- # factor 1.1 to make supercritical 10% more expansive than subcritical
310
- self .Cplantcorrelation = 1.1 * CCAPP1 * math .pow (
311
- np .max (model .surfaceplant .ElectricityProduced .value ) / 15. , - 0.06 ) * np .max (
312
- model .surfaceplant .ElectricityProduced .value ) * 1000. / 1E6
313
-
314
- elif model .surfaceplant .plant_type .value == PlantType .SINGLE_FLASH :
315
- if np .max (model .surfaceplant .ElectricityProduced .value ) < 10. :
316
- C2 = 4.8472E-2
317
- C1 = - 35.2186
318
- C0 = 8.4474E3
319
- D2 = 4.0604E-2
320
- D1 = - 29.3817
321
- D0 = 6.9911E3
322
- PLL = 5.
323
- PRL = 10.
324
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 25. :
325
- C2 = 4.0604E-2
326
- C1 = - 29.3817
327
- C0 = 6.9911E3
328
- D2 = 3.2773E-2
329
- D1 = - 23.5519
330
- D0 = 5.5263E3
331
- PLL = 10.
332
- PRL = 25.
333
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 50. :
334
- C2 = 3.2773E-2
335
- C1 = - 23.5519
336
- C0 = 5.5263E3
337
- D2 = 3.4716E-2
338
- D1 = - 23.8139
339
- D0 = 5.1787E3
340
- PLL = 25.
341
- PRL = 50.
342
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 75. :
343
- C2 = 3.4716E-2
344
- C1 = - 23.8139
345
- C0 = 5.1787E3
346
- D2 = 3.5271E-2
347
- D1 = - 24.3962
348
- D0 = 5.1972E3
349
- PLL = 50.
350
- PRL = 75.
351
- else :
352
- C2 = 3.5271E-2
353
- C1 = - 24.3962
354
- C0 = 5.1972E3
355
- D2 = 3.3908E-2
356
- D1 = - 23.4890
357
- D0 = 5.0238E3
358
- PLL = 75.
359
- PRL = 100.
360
- maxProdTemp = np .max (model .surfaceplant .TenteringPP .value )
361
- CCAPPLL = C2 * maxProdTemp ** 2 + C1 * maxProdTemp + C0
362
- CCAPPRL = D2 * maxProdTemp ** 2 + D1 * maxProdTemp + D0
363
- b = math .log (CCAPPRL / CCAPPLL ) / math .log (PRL / PLL )
364
- a = CCAPPRL / PRL ** b
365
- # factor 0.75 to make double flash 25% more expansive than single flash
366
- self .Cplantcorrelation = (0.8 * a * math .pow (np .max (model .surfaceplant .ElectricityProduced .value ), b ) *
367
- np .max (model .surfaceplant .ElectricityProduced .value ) * 1000. / 1E6 )
368
-
369
- elif model .surfaceplant .plant_type .value == PlantType .DOUBLE_FLASH :
370
- if np .max (model .surfaceplant .ElectricityProduced .value ) < 10. :
371
- C2 = 4.8472E-2
372
- C1 = - 35.2186
373
- C0 = 8.4474E3
374
- D2 = 4.0604E-2
375
- D1 = - 29.3817
376
- D0 = 6.9911E3
377
- PLL = 5.
378
- PRL = 10.
379
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 25. :
380
- C2 = 4.0604E-2
381
- C1 = - 29.3817
382
- C0 = 6.9911E3
383
- D2 = 3.2773E-2
384
- D1 = - 23.5519
385
- D0 = 5.5263E3
386
- PLL = 10.
387
- PRL = 25.
388
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 50. :
389
- C2 = 3.2773E-2
390
- C1 = - 23.5519
391
- C0 = 5.5263E3
392
- D2 = 3.4716E-2
393
- D1 = - 23.8139
394
- D0 = 5.1787E3
395
- PLL = 25.
396
- PRL = 50.
397
- elif np .max (model .surfaceplant .ElectricityProduced .value ) < 75. :
398
- C2 = 3.4716E-2
399
- C1 = - 23.8139
400
- C0 = 5.1787E3
401
- D2 = 3.5271E-2
402
- D1 = - 24.3962
403
- D0 = 5.1972E3
404
- PLL = 50.
405
- PRL = 75.
406
- else :
407
- C2 = 3.5271E-2
408
- C1 = - 24.3962
409
- C0 = 5.1972E3
410
- D2 = 3.3908E-2
411
- D1 = - 23.4890
412
- D0 = 5.0238E3
413
- PLL = 75.
414
- PRL = 100.
415
- maxProdTemp = np .max (model .surfaceplant .TenteringPP .value )
416
- CCAPPLL = C2 * maxProdTemp ** 2 + C1 * maxProdTemp + C0
417
- CCAPPRL = D2 * maxProdTemp ** 2 + D1 * maxProdTemp + D0
418
- b = math .log (CCAPPRL / CCAPPLL ) / math .log (PRL / PLL )
419
- a = CCAPPRL / PRL ** b
420
- self .Cplantcorrelation = (a * math .pow (np .max (model .surfaceplant .ElectricityProduced .value ), b ) *
421
- np .max (model .surfaceplant .ElectricityProduced .value ) * 1000. / 1E6 )
422
-
423
- if self .ccplantfixed .Valid :
424
- self .Cplant .value = self .ccplantfixed .value
425
- self .CAPEX_cost_electricity_plant = self .Cplant .value * self .CAPEX_heat_electricity_plant_ratio .value
426
- self .CAPEX_cost_heat_plant = self .Cplant .value * (1.0 - self .CAPEX_heat_electricity_plant_ratio .value )
427
- else :
428
- # 1.02 to convert cost from 2012 to 2016 #factor 1.15 for 15% contingency and factor 1.10 to convert from 2016 to 2022
429
- self .Cplant .value = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * self .Cplantcorrelation * 1.02 * 1.10
430
- self .CAPEX_cost_electricity_plant = self .Cplant .value
431
-
432
- # add direct-use plant cost of co-gen system to Cplant (only of no total Cplant was provided)
433
- if not self .ccplantfixed .Valid : # 1.15 below for contingency
434
- if model .surfaceplant .enduse_option .value in [EndUseOptions .COGENERATION_TOPPING_EXTRA_ELECTRICITY ,
435
- EndUseOptions .COGENERATION_TOPPING_EXTRA_HEAT ]: # enduse_option = 3: cogen topping cycle
436
- self .CAPEX_cost_heat_plant = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
437
- model .surfaceplant .HeatProduced .value / model .surfaceplant .enduse_efficiency_factor .value ) * 1000.
438
- elif model .surfaceplant .enduse_option .value in [EndUseOptions .COGENERATION_BOTTOMING_EXTRA_HEAT ,
439
- EndUseOptions .COGENERATION_BOTTOMING_EXTRA_ELECTRICITY ]: # enduse_option = 4: cogen bottoming cycle
440
- self .CAPEX_cost_heat_plant = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
441
- model .surfaceplant .HeatProduced .value / model .surfaceplant .enduse_efficiency_factor .value ) * 1000.
442
- elif model .surfaceplant .enduse_option .value in [EndUseOptions .COGENERATION_PARALLEL_EXTRA_ELECTRICITY ,
443
- EndUseOptions .COGENERATION_PARALLEL_EXTRA_HEAT ]: # cogen parallel cycle
444
- self .CAPEX_cost_heat_plant = self ._indirect_cost_factor * 1.15 * self .ccplantadjfactor .value * 250E-6 * np .max (
445
- model .surfaceplant .HeatProduced .value / model .surfaceplant .enduse_efficiency_factor .value ) * 1000.
446
-
447
- self .Cplant .value = self .Cplant .value + self .CAPEX_cost_heat_plant
448
- if not self .CAPEX_heat_electricity_plant_ratio .Provided :
449
- self .CAPEX_heat_electricity_plant_ratio .value = self .CAPEX_cost_electricity_plant / self .Cplant .value
226
+ self .calculate_plant_costs (model )
450
227
451
228
if not self .totalcapcost .Valid :
452
229
# exploration costs (same as in Geophires v1.2) (M$)
0 commit comments