Skip to content

Commit 2e1a576

Browse files
SurfacePlant.integrate_time_series_slice utility method; incorporated into SurfacePlant, SurfacePlantAGS, and SurfacePlantIndustrialHeat (other plant types remain WIP/TODO to fix still; unit tests not yet updated)
1 parent fa14f39 commit 2e1a576

File tree

3 files changed

+52
-52
lines changed

3 files changed

+52
-52
lines changed

src/geophires_x/SurfacePlant.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
import sys
2-
import os
31
import numpy as np
42

53
from .GeoPHIRESUtils import quantity
64
from .OptionList import EndUseOptions, PlantType
7-
from .Parameter import floatParameter, intParameter, strParameter, OutputParameter, ReadParameter, \
5+
from .Parameter import floatParameter, intParameter, OutputParameter, ReadParameter, \
86
coerce_int_params_to_enum_values
97
from .Units import *
108
import geophires_x.Model as Model
11-
import pandas as pd
9+
1210

1311
class SurfacePlant:
12+
@staticmethod
13+
def integrate_time_series_slice(
14+
series: np.ndarray,
15+
_i: int,
16+
time_steps_per_year: int,
17+
utilization_factor: float
18+
) -> np.float64:
19+
_slice = series[(0 + _i * time_steps_per_year):((_i + 1) * time_steps_per_year) + 1]
20+
21+
# Note that len(_slice) - 1 may be less than time_steps_per_year for the last slice.
22+
23+
if len(_slice) == 1:
24+
return _slice[0]
25+
26+
return np.trapz(
27+
_slice,
28+
dx=1. / (len(_slice) - 1) * 365. * 24.
29+
) * 1000. * utilization_factor
30+
1431
def remaining_reservoir_heat_content(self, InitialReservoirHeatContent: np.ndarray, HeatkWhExtracted: np.ndarray) -> np.ndarray:
1532
"""
1633
Calculate reservoir heat content
@@ -176,19 +193,12 @@ def annual_electricity_pumping_power(self, plant_lifetime: int,enduse_option: En
176193
NetkWhProduced = np.zeros(plant_lifetime)
177194
HeatkWhProduced = np.zeros(plant_lifetime)
178195

179-
def integrate_slice(series: np.ndarray, _i: int) -> np.float64:
180-
_slice = series[(0 + _i * time_steps_per_year):((_i + 1) * time_steps_per_year) + 1]
181-
182-
# Note that len(_slice) - 1 may be less than time_steps_per_year for the last slice.
183-
184-
return np.trapz(
185-
_slice,
186-
dx=1. / (len(_slice) - 1) * 365. * 24.
187-
) * 1000. * utilization_factor
196+
def _integrate_slice(series: np.ndarray, _i: int) -> np.float64:
197+
return SurfacePlant.integrate_time_series_slice(series, _i, time_steps_per_year, utilization_factor)
188198

189199
for i in range(0, plant_lifetime):
190-
HeatkWhExtracted[i] = integrate_slice(HeatExtracted, i)
191-
PumpingkWh[i] = integrate_slice(PumpingPower, i)
200+
HeatkWhExtracted[i] = _integrate_slice(HeatExtracted, i)
201+
PumpingkWh[i] = _integrate_slice(PumpingPower, i)
192202

193203

194204
if enduse_option in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT,
@@ -201,14 +211,14 @@ def integrate_slice(series: np.ndarray, _i: int) -> np.float64:
201211
TotalkWhProduced = np.zeros(plant_lifetime)
202212
NetkWhProduced = np.zeros(plant_lifetime)
203213
for i in range(0, plant_lifetime):
204-
TotalkWhProduced[i] = integrate_slice(ElectricityProduced, i)
205-
NetkWhProduced[i] = integrate_slice(NetElectricityProduced, i)
214+
TotalkWhProduced[i] = _integrate_slice(ElectricityProduced, i)
215+
NetkWhProduced[i] = _integrate_slice(NetElectricityProduced, i)
206216

207217
if enduse_option is not EndUseOptions.ELECTRICITY:
208218
# all those end-use options have a direct-use component
209219
HeatkWhProduced = np.zeros(plant_lifetime)
210220
for i in range(0, plant_lifetime):
211-
HeatkWhProduced[i] = integrate_slice(HeatProduced, i)
221+
HeatkWhProduced[i] = _integrate_slice(HeatProduced, i)
212222

213223
return HeatkWhExtracted, PumpingkWh, TotalkWhProduced, NetkWhProduced, HeatkWhProduced
214224

src/geophires_x/SurfacePlantAGS.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -738,28 +738,23 @@ def Calculate(self, model: Model) -> None:
738738
self.HeatExtracted.value = self.HeatExtracted.value / 1000.0
739739
# useful direct-use heat provided to application [MWth]
740740
self.HeatProduced.value = self.HeatExtracted.value * self.enduseefficiencyfactor.value
741+
742+
def _integrate_slice(series: np.ndarray, _i: int) -> np.float64:
743+
return SurfacePlant.integrate_time_series_slice(
744+
series, _i, model.economics.timestepsperyear.value, self.utilization_factor.value
745+
)
746+
741747
for i in range(0, self.plant_lifetime.value):
742-
# FIXME TODO WIP adjust dx for slice size
743-
self.HeatkWhExtracted.value[i] = np.trapz(self.HeatExtracted.value[
744-
(i * model.economics.timestepsperyear.value):((
745-
i + 1) * model.economics.timestepsperyear.value) + 1],
746-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
747-
self.PumpingkWh.value[i] = np.trapz(model.wellbores.PumpingPower.value[
748-
(i * model.economics.timestepsperyear.value):((
749-
i + 1) * model.economics.timestepsperyear.value) + 1],
750-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
748+
self.HeatkWhExtracted.value[i] = _integrate_slice(self.HeatExtracted.value, i)
749+
self.PumpingkWh.value[i] = _integrate_slice(model.wellbores.PumpingPower.value, i)
751750

752751
self.RemainingReservoirHeatContent.value = model.reserv.InitialReservoirHeatContent.value - np.cumsum(
753752
self.HeatkWhExtracted.value) * 3600 * 1E3 / 1E15
754753

755754
if self.End_use is not EndUseOptions.ELECTRICITY:
756755
self.HeatkWhProduced.value = np.zeros(self.plant_lifetime.value)
757756
for i in range(0, self.plant_lifetime.value):
758-
# FIXME TODO WIP adjust dx for slice size
759-
self.HeatkWhProduced.value[i] = np.trapz(self.HeatProduced.value[
760-
(0 + i * model.economics.timestepsperyear.value):((
761-
i + 1) * model.economics.timestepsperyear.value) + 1],
762-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
757+
self.HeatkWhProduced.value[i] = _integrate_slice(self.HeatProduced.value, i)
763758
else:
764759
# copy some arrays so we have a GEOPHIRES equivalent
765760
self.TotalkWhProduced.value = self.Annual_electricity_production.copy()

src/geophires_x/SurfacePlantIndustrialHeat.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def __init__(self, model: Model):
1616
:return: None
1717
"""
1818

19-
model.logger.info("Init " + self.__class__.__name__ + ": " + __name__)
19+
model.logger.info(f'Init {self.__class__.__name__}: {__name__}')
2020
super().__init__(model) # Initialize all the parameters in the superclass
2121

2222
# There are no parameters unique to this class, so we don't need to set any up here.
@@ -26,7 +26,7 @@ def __init__(self, model: Model):
2626
self.MyClass = sclass
2727
self.MyPath = os.path.abspath(__file__)
2828

29-
model.logger.info("Complete " + self.__class__.__name__ + ": " + __name__)
29+
model.logger.info(f'Complete {self.__class__.__name__}: {__name__}')
3030

3131
def __str__(self):
3232
return "SurfacePlantIndustrialHeat"
@@ -39,12 +39,12 @@ def read_parameters(self, model: Model) -> None:
3939
:param model: The container class of the application, giving access to everything else, including the logger
4040
:return: None
4141
"""
42-
model.logger.info("Init " + self.__class__.__name__ + ": " + __name__)
42+
model.logger.info(f'Init {self.__class__.__name__}: {__name__}')
4343
super().read_parameters(model) # Read in all the parameters from the superclass
4444

4545
# Since there are no parameters unique to this class, we don't need to read any in here.
4646

47-
model.logger.info("complete " + self.__class__.__name__ + ": " + __name__)
47+
model.logger.info(f'complete {self.__class__.__name__}: {__name__}')
4848

4949
def Calculate(self, model: Model) -> None:
5050
"""
@@ -54,7 +54,7 @@ def Calculate(self, model: Model) -> None:
5454
:type model: :class:`~geophires_x.Model.Model`
5555
:return: Nothing, but it does make calculations and set values in the model
5656
"""
57-
model.logger.info("Init " + self.__class__.__name__ + ": " + __name__)
57+
model.logger.info(f'Init {self.__class__.__name__}: {__name__}')
5858

5959
# This is where all the calculations are made using all the values that have been set.
6060
# If you subclass this class, you can choose to run these calculations before (or after) your calculations,
@@ -73,28 +73,23 @@ def Calculate(self, model: Model) -> None:
7373
# useful direct-use heat provided to application [MWth]
7474
self.HeatProduced.value = self.HeatExtracted.value * self.enduse_efficiency_factor.value
7575

76-
# Calculate annual electricity/heat production because all end-use options have "heat extracted from reservoir" and pumping kWs
76+
# Calculate annual electricity/heat production because all end-use options have "heat extracted from reservoir"
77+
# and pumping kWs
7778
self.HeatkWhExtracted.value = np.zeros(self.plant_lifetime.value)
7879
self.PumpingkWh.value = np.zeros(self.plant_lifetime.value)
7980

81+
def _integrate_slice(series, _i):
82+
return SurfacePlant.integrate_time_series_slice(
83+
series, _i, model.economics.timestepsperyear.value, self.utilization_factor.value
84+
)
85+
8086
for i in range(0, self.plant_lifetime.value):
81-
# FIXME TODO WIP adjust dx for slice size
82-
self.HeatkWhExtracted.value[i] = np.trapz(self.HeatExtracted.value[
83-
(0 + i * model.economics.timestepsperyear.value):((
84-
i + 1) * model.economics.timestepsperyear.value) + 1],
85-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
86-
self.PumpingkWh.value[i] = np.trapz(model.wellbores.PumpingPower.value[
87-
(0 + i * model.economics.timestepsperyear.value):((
88-
i + 1) * model.economics.timestepsperyear.value) + 1],
89-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
87+
self.HeatkWhExtracted.value[i] = _integrate_slice(self.HeatExtracted.value, i)
88+
self.PumpingkWh.value[i] = _integrate_slice(model.wellbores.PumpingPower.value, i)
9089

9190
self.HeatkWhProduced.value = np.zeros(self.plant_lifetime.value)
9291
for i in range(0, self.plant_lifetime.value):
93-
# FIXME TODO WIP adjust dx for slice size
94-
self.HeatkWhProduced.value[i] = np.trapz(self.HeatProduced.value[
95-
(0 + i * model.economics.timestepsperyear.value):((
96-
i + 1) * model.economics.timestepsperyear.value) + 1],
97-
dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value
92+
self.HeatkWhProduced.value[i] = _integrate_slice(self.HeatProduced.value, i)
9893

9994
# calculate reservoir heat content
10095
self.RemainingReservoirHeatContent.value = SurfacePlant.remaining_reservoir_heat_content(

0 commit comments

Comments
 (0)