Skip to content

Commit 125e2f1

Browse files
Parameterize indirect costs in SBTEconomics
1 parent 1b24b03 commit 125e2f1

File tree

3 files changed

+42
-36
lines changed

3 files changed

+42
-36
lines changed

src/geophires_x/Economics.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,14 +2416,9 @@ def Calculate(self, model: Model) -> None:
24162416
)
24172417
else:
24182418
self.cost_lateral_section.value = 0.0
2419-
# cost of the well field
2420-
2421-
indirect_cost_factor = (
2422-
1 +
2423-
self.wellfield_indirect_capital_cost_percentage.quantity().to('dimensionless').magnitude
2424-
)
24252419

2426-
self.Cwell.value = indirect_cost_factor * (
2420+
# cost of the well field
2421+
self.Cwell.value = self._wellfield_indirect_cost_factor * (
24272422
self.cost_one_production_well.value * model.wellbores.nprod.value +
24282423
self.cost_one_injection_well.value * model.wellbores.ninj.value +
24292424
self.cost_lateral_section.value
@@ -2737,6 +2732,14 @@ def Calculate(self, model: Model) -> None:
27372732
def _indirect_cost_factor(self) -> float:
27382733
return 1 + self.indirect_capital_cost_percentage.quantity().to('dimensionless').magnitude
27392734

2735+
@property
2736+
def _wellfield_indirect_cost_factor(self) -> float:
2737+
return 1 + self.wellfield_indirect_capital_cost_percentage.quantity().to('dimensionless').magnitude
2738+
2739+
@property
2740+
def _stimulation_indirect_cost_factor(self) -> float:
2741+
return 1 + self.stimulation_indirect_capital_cost_percentage.quantity().to('dimensionless').magnitude
2742+
27402743
def calculate_stimulation_costs(self, model: Model) -> PlainQuantity:
27412744
if self.ccstimfixed.Valid:
27422745
stimulation_costs = self.ccstimfixed.quantity().to(self.Cstim.CurrentUnits).magnitude
@@ -2746,15 +2749,13 @@ def calculate_stimulation_costs(self, model: Model) -> PlainQuantity:
27462749
stim_cost_per_production_well = self.stimulation_cost_per_production_well.quantity().to(
27472750
self.Cstim.CurrentUnits).magnitude
27482751

2749-
stimulation_indirect_cost_fraction = (self.stimulation_indirect_capital_cost_percentage.quantity()
2750-
.to('dimensionless').magnitude)
27512752
stimulation_costs = (
27522753
(
27532754
stim_cost_per_injection_well * model.wellbores.ninj.value
27542755
+ stim_cost_per_production_well * model.wellbores.nprod.value
27552756
)
27562757
* self.ccstimadjfactor.value
2757-
* (1 + stimulation_indirect_cost_fraction)
2758+
* self._stimulation_indirect_cost_factor
27582759
* 1.15 # 15% contingency TODO https://github.com/NREL/GEOPHIRES-X/issues/383
27592760
)
27602761

src/geophires_x/SBTEconomics.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,15 @@ def Calculate(self, model: Model) -> None:
224224
(self.cost_one_injection_well.value * model.wellbores.ninj.value))
225225
else:
226226
# calculate the cost of one vertical production well
227-
# 1.05 for 5% indirect costs
228-
self.cost_one_production_well.value = 1.05 * calculate_cost_of_one_vertical_well(model, model.wellbores.vertical_section_length.value,
229-
self.wellcorrelation.value,
230-
self.Vertical_drilling_cost_per_m.value,
231-
self.per_production_well_cost.Name,
232-
self.production_well_cost_adjustment_factor.value)
227+
self.cost_one_production_well.value = (
228+
self._wellfield_indirect_cost_factor
229+
* calculate_cost_of_one_vertical_well(model,
230+
model.wellbores.vertical_section_length.value,
231+
self.wellcorrelation.value,
232+
self.Vertical_drilling_cost_per_m.value,
233+
self.per_production_well_cost.Name,
234+
self.production_well_cost_adjustment_factor.value)
235+
)
233236

234237
# If there is no injector well, then we assume we are doing a coaxial closed-loop.
235238
if model.wellbores.ninj.value == 0:
@@ -241,26 +244,32 @@ def Calculate(self, model: Model) -> None:
241244

242245
if hasattr(model.wellbores, 'numnonverticalsections') and model.wellbores.numnonverticalsections.Provided:
243246
# now calculate the costs if we have a lateral section
244-
# 1.05 for 5% indirect costs
245-
self.cost_lateral_section.value = 1.05 * calculate_cost_of_lateral_section(model, model.wellbores.tot_lateral_m.value,
246-
self.wellcorrelation.value,
247-
self.Nonvertical_drilling_cost_per_m.value,
248-
model.wellbores.numnonverticalsections.value,
249-
self.per_injection_well_cost.Name,
250-
model.wellbores.NonverticalsCased.value,
251-
self.production_well_cost_adjustment_factor.value)
247+
self.cost_lateral_section.value = (
248+
self._wellfield_indirect_cost_factor
249+
* calculate_cost_of_lateral_section(model,
250+
model.wellbores.tot_lateral_m.value,
251+
self.wellcorrelation.value,
252+
self.Nonvertical_drilling_cost_per_m.value,
253+
model.wellbores.numnonverticalsections.value,
254+
self.per_injection_well_cost.Name,
255+
model.wellbores.NonverticalsCased.value,
256+
self.production_well_cost_adjustment_factor.value)
257+
)
252258

253259
# If it is an EavorLoop, we need to calculate the cost of the section of the well from
254260
# the bottom of the vertical to the junction with the laterals.
255261
# This section is not vertical, but it is cased, so we will estimate the cost
256262
# of this section as if it were a vertical section.
257263
if model.wellbores.Configuration.value == Configuration.EAVORLOOP:
258-
self.cost_to_junction_section.value = 1.05 * calculate_cost_of_one_vertical_well(model,
259-
model.wellbores.tot_to_junction_m.value,
260-
self.wellcorrelation.value,
261-
self.Vertical_drilling_cost_per_m.value,
262-
self.per_injection_well_cost.Name,
263-
self.injection_well_cost_adjustment_factor.value)
264+
self.cost_to_junction_section.value = (
265+
self._wellfield_indirect_cost_factor
266+
* calculate_cost_of_one_vertical_well(model,
267+
model.wellbores.tot_to_junction_m.value,
268+
self.wellcorrelation.value,
269+
self.Vertical_drilling_cost_per_m.value,
270+
self.per_injection_well_cost.Name,
271+
self.injection_well_cost_adjustment_factor.value)
272+
)
264273
else:
265274
self.cost_lateral_section.value = 0.0
266275
self.cost_to_junction_section.value = 0.0
@@ -270,11 +279,7 @@ def Calculate(self, model: Model) -> None:
270279
(self.cost_one_injection_well.value * model.wellbores.ninj.value) +
271280
self.cost_lateral_section.value + self.cost_to_junction_section.value)
272281

273-
# reservoir stimulation costs (M$/injection well). These are calculated whether totalcapcost.Valid = 1
274-
if self.ccstimfixed.Valid:
275-
self.Cstim.value = self.ccstimfixed.value
276-
else:
277-
self.Cstim.value = 1.05 * 1.15 * self.ccstimadjfactor.value * model.wellbores.ninj.value * 1.25 # 1.15 for 15% contingency and 1.05 for 5% indirect costs
282+
self.Cstim.value = self.calculate_stimulation_costs(model).to(self.Cstim.CurrentUnits).magnitude
278283

279284
# field gathering system costs (M$)
280285
if self.ccgathfixed.Valid:

tests/test_geophires_x.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ def test_drilling_cost_curves(self):
814814
drilling cost per well and the raw value calculated by the curve.
815815
"""
816816

817-
indirect_cost_factor = 1.05 # See TODO re:parameterizing at src/geophires_x/Economics.py:652
817+
indirect_cost_factor = 1.05
818818

819819
for test_case in WellDrillingCostCorrelationTestCase.COST_CORRELATION_TEST_CASES:
820820
correlation: WellDrillingCostCorrelation = test_case[0]

0 commit comments

Comments
 (0)