Skip to content

Commit 762067a

Browse files
Fix output of cost per non-vertical section by calculating it as a derived output from the total lateral cost and number of laterals
1 parent 66e4077 commit 762067a

15 files changed

+71
-34
lines changed

src/geophires_x/AGSEconomics.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,5 +259,6 @@ def Calculate(self, model: Model) -> None:
259259
self.Coam.value = self.AverageOPEX_Plant * 1000
260260
self.Coam.CurrentUnits = CurrencyFrequencyUnit.KDOLLARSPERYEAR
261261

262+
self._calculate_derived_outputs(model)
262263
model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}')
263264

src/geophires_x/Economics.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1552,11 +1552,16 @@ def __init__(self, model: Model):
15521552
PreferredUnits=CurrencyUnit.MDOLLARS,
15531553
CurrentUnits=CurrencyUnit.MDOLLARS
15541554
)
1555+
15551556
self.Cwell = self.OutputParameterDict[self.Cwell.Name] = OutputParameter(
15561557
Name="Wellfield cost",
15571558
UnitType=Units.CURRENCY,
15581559
PreferredUnits=CurrencyUnit.MDOLLARS,
1559-
CurrentUnits=CurrencyUnit.MDOLLARS
1560+
CurrentUnits=CurrencyUnit.MDOLLARS,
1561+
1562+
# See TODO re:parameterizing indirect costs at src/geophires_x/Economics.py:652
1563+
ToolTipText="Includes total drilling and completion cost of all injection and production wells and "
1564+
"laterals, plus 5% indirect costs."
15601565
)
15611566
self.Coamwell = self.OutputParameterDict[self.Coamwell.Name] = OutputParameter(
15621567
Name="O&M Wellfield cost",
@@ -1795,6 +1800,12 @@ def __init__(self, model: Model):
17951800
PreferredUnits=CurrencyUnit.MDOLLARS,
17961801
CurrentUnits=CurrencyUnit.MDOLLARS
17971802
)
1803+
self.cost_per_lateral_section = self.OutputParameterDict[self.cost_per_lateral_section.Name] = OutputParameter(
1804+
Name='Drilling and completion costs per non-vertical section',
1805+
UnitType=Units.CURRENCY,
1806+
PreferredUnits=CurrencyUnit.MDOLLARS,
1807+
CurrentUnits=CurrencyUnit.MDOLLARS
1808+
)
17981809
self.cost_to_junction_section = self.OutputParameterDict[self.cost_to_junction_section.Name] = OutputParameter(
17991810
Name="Cost of the entire section of a well from bottom of vertical to junction with laterals",
18001811
UnitType=Units.CURRENCY,
@@ -2882,7 +2893,20 @@ def Calculate(self, model: Model) -> None:
28822893
np.average(model.surfaceplant.ElectricityProduced.quantity().to(
28832894
'MW').magnitude * self.jobs_created_per_MW_electricity.value))
28842895

2896+
self._calculate_derived_outputs(model)
28852897
model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}')
28862898

2899+
def _calculate_derived_outputs(self, model: Model) -> None:
2900+
"""
2901+
Subclasses should call _calculate_derived_outputs at the end of their Calculate methods to populate output
2902+
values that are derived from subclass-calculated outputs.
2903+
"""
2904+
2905+
if hasattr(self, 'cost_lateral_section') and self.cost_lateral_section.value != 0:
2906+
self.cost_per_lateral_section.value = (
2907+
self.cost_lateral_section.quantity().to(self.cost_per_lateral_section.CurrentUnits).magnitude
2908+
/ model.wellbores.numnonverticalsections.value
2909+
)
2910+
28872911
def __str__(self):
28882912
return "Economics"

src/geophires_x/EconomicsAddOns.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ def Calculate(self, model: Model) -> None:
373373
# recalculate LCOE/LCOH
374374
self.LCOE.value, self.LCOH.value, LCOC = Economics.CalculateLCOELCOHLCOC(self, model)
375375

376+
self._calculate_derived_outputs(model)
376377
model.logger.info(f'complete {str(__class__)}: {sys._getframe().f_code.co_name}')
377378

378379
def __str__(self):

src/geophires_x/EconomicsCCUS.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ def Calculate(self, model) -> None:
421421
self.ProjectMOIC.value = self.ProjectCummCashFlow.value[len(self.ProjectCummCashFlow.value) - 1] / (
422422
model.economics.CCap.value + (model.economics.Coam.value * model.surfaceplant.plant_lifetime.value))
423423

424-
model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
424+
self._calculate_derived_outputs(model)
425+
model.logger.info(f'complete {str(__class__)}: {sys._getframe().f_code.co_name}')
425426

426427
def __str__(self):
427428
return "EconomicsCCUS"

src/geophires_x/EconomicsS_DAC_GT.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,4 +676,6 @@ def Calculate(self, model: Model) -> None:
676676
# (self.CarbonExtractedAnnually.value[i] * model.economics.CarbonPrice.value[i]))
677677
# if i > 0:
678678
# model.economics.CarbonCummCashFlow.value[i] = model.economics.CarbonCummCashFlow.value[i - 1] + model.economics.CarbonRevenue.value[i]
679-
model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
679+
680+
self._calculate_derived_outputs(model)
681+
model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}')

src/geophires_x/Outputs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1810,7 +1810,7 @@ def PrintOutputs(self, model: Model):
18101810
elif econ.cost_lateral_section.value > 0.0:
18111811
f.write(f' Drilling and completion costs per vertical production well: {econ.cost_one_production_well.value:10.2f} ' + econ.cost_one_production_well.CurrentUnits.value + NL)
18121812
f.write(f' Drilling and completion costs per vertical injection well: {econ.cost_one_injection_well.value:10.2f} ' + econ.cost_one_injection_well.CurrentUnits.value + NL)
1813-
f.write(f' Drilling and completion costs per non-vertical section: {econ.cost_lateral_section.value:10.2f} ' + econ.cost_lateral_section.CurrentUnits.value + NL)
1813+
f.write(f' {econ.cost_per_lateral_section.Name}: {econ.cost_per_lateral_section.value:10.2f} {econ.cost_lateral_section.CurrentUnits.value}\n')
18141814
else:
18151815
f.write(f' Drilling and completion costs per well: {model.economics.Cwell.value/(model.wellbores.nprod.value+model.wellbores.ninj.value):10.2f} ' + model.economics.Cwell.CurrentUnits.value + NL)
18161816
f.write(f' Stimulation costs: {model.economics.Cstim.value:10.2f} ' + model.economics.Cstim.CurrentUnits.value + NL)

src/geophires_x/SBTEconomics.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,5 +845,6 @@ def Calculate(self, model: Model) -> None:
845845
# Calculate LCOE/LCOH
846846
self.LCOE.value, self.LCOH.value, self.LCOC.value = CalculateLCOELCOHLCOC(self, model)
847847

848+
self._calculate_derived_outputs(model)
848849
model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}')
849850

src/geophires_x/SBTWellbores.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ def __init__(self, model: Model):
5252
# NB: inputs we already have ("already have it") need to be set at ReadParameter time so values are set at the
5353
# last possible time
5454

55+
# Assume CLGS has 1 lateral by default (Non-CLGS default value is 0)
56+
self.numnonverticalsections.value = 1
57+
self.numnonverticalsections.ErrMessage = (f'assume default for Number of Nonvertical Wellbore Sections '
58+
f'({self.numnonverticalsections.value})')
59+
5560
self.vertical_section_length = self.ParameterDict[self.vertical_section_length.Name] = floatParameter(
5661
'Vertical Section Length',
5762
DefaultValue=2000.0,

src/geophires_x/SUTRAEconomics.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ def Calculate(self, model: Model) -> None:
417417
* 1e8
418418
) # cents/kWh
419419

420-
model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
420+
self._calculate_derived_outputs(model)
421+
model.logger.info(f'complete {str(__class__)}: {sys._getframe().f_code.co_name}')
421422

422423
def __str__(self):
423424
return "Economics"

tests/examples/Fervo_Norbeck_Latimer_2023.out

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
Simulation Metadata
66
----------------------
7-
GEOPHIRES Version: 3.7.1
8-
Simulation Date: 2025-01-22
9-
Simulation Time: 10:48
10-
Calculation Time: 0.443 sec
7+
GEOPHIRES Version: 3.7.5
8+
Simulation Date: 2025-01-31
9+
Simulation Time: 11:14
10+
Calculation Time: 0.437 sec
1111

1212
***SUMMARY OF RESULTS***
1313

@@ -97,7 +97,7 @@ Simulation Metadata
9797
Drilling and completion costs: 10.13 MUSD
9898
Drilling and completion costs per vertical production well: 3.02 MUSD
9999
Drilling and completion costs per vertical injection well: 3.02 MUSD
100-
Drilling and completion costs per non-vertical section: 3.61 MUSD
100+
Drilling and completion costs per non-vertical section: 1.80 MUSD
101101
Stimulation costs: 1.51 MUSD
102102
Surface power plant costs: 11.34 MUSD
103103
Field gathering system costs: 1.52 MUSD

0 commit comments

Comments
 (0)