Skip to content

Commit a3a99c7

Browse files
Merge pull request NREL#399 from softwareengineerprogrammer/main
Parameterize Reservoir Stimulation Capital Cost per well [v3.9.33]
2 parents 96f98ae + 2fb0d58 commit a3a99c7

File tree

13 files changed

+143
-32
lines changed

13 files changed

+143
-32
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 3.9.31
2+
current_version = 3.9.33
33
commit = True
44
tag = True
55

.cookiecutterrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ default_context:
5454
sphinx_doctest: "no"
5555
sphinx_theme: "sphinx-py3doc-enhanced-theme"
5656
test_matrix_separate_coverage: "no"
57-
version: 3.9.31
57+
version: 3.9.33
5858
version_manager: "bump2version"
5959
website: "https://github.com/NREL"
6060
year_from: "2023"

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Free software: `MIT license <LICENSE>`__
5858
:alt: Supported implementations
5959
:target: https://pypi.org/project/geophires-x
6060

61-
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.9.31.svg
61+
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.9.33.svg
6262
:alt: Commits since latest release
63-
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.9.31...main
63+
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.9.33...main
6464

6565
.. |docs| image:: https://readthedocs.org/projects/GEOPHIRES-X/badge/?style=flat
6666
:target: https://nrel.github.io/GEOPHIRES-X

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
year = '2025'
1919
author = 'NREL'
2020
copyright = f'{year}, {author}'
21-
version = release = '3.9.31'
21+
version = release = '3.9.33'
2222

2323
pygments_style = 'trac'
2424
templates_path = ['./templates']

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def read(*names, **kwargs):
1313

1414
setup(
1515
name='geophires-x',
16-
version='3.9.31',
16+
version='3.9.33',
1717
license='MIT',
1818
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
1919
long_description='{}\n{}'.format(

src/geophires_x/Economics.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ def __init__(self, model: Model):
572572
ToolTipText="Specify the economic model to calculate the levelized cost of energy. " +
573573
'; '.join([f'{it.int_value}: {it.value}' for it in EconomicModel])
574574
)
575+
575576
self.ccstimfixed = self.ParameterDict[self.ccstimfixed.Name] = floatParameter(
576577
"Reservoir Stimulation Capital Cost",
577578
DefaultValue=-1.0,
@@ -584,6 +585,38 @@ def __init__(self, model: Model):
584585
Valid=False,
585586
ToolTipText="Total reservoir stimulation capital cost"
586587
)
588+
589+
max_stimulation_cost_per_well_MUSD = 100
590+
self.stimulation_cost_per_injection_well = \
591+
self.ParameterDict[self.stimulation_cost_per_injection_well.Name] = floatParameter(
592+
'Reservoir Stimulation Capital Cost per Injection Well',
593+
DefaultValue=1.25,
594+
Min=0,
595+
Max=max_stimulation_cost_per_well_MUSD,
596+
UnitType=Units.CURRENCY,
597+
PreferredUnits=CurrencyUnit.MDOLLARS,
598+
CurrentUnits=CurrencyUnit.MDOLLARS,
599+
Provided=False,
600+
ToolTipText='Reservoir stimulation capital cost per injection well'
601+
)
602+
603+
stimulation_cost_per_production_well_default_value_MUSD = 0
604+
stimulation_cost_per_production_well_default_value_note = \
605+
'. By default, only the injection wells are assumed to be stimulated unless this parameter is provided.' \
606+
if stimulation_cost_per_production_well_default_value_MUSD == 0 else ''
607+
self.stimulation_cost_per_production_well = \
608+
self.ParameterDict[self.stimulation_cost_per_production_well.Name] = floatParameter(
609+
'Reservoir Stimulation Capital Cost per Production Well',
610+
DefaultValue=stimulation_cost_per_production_well_default_value_MUSD,
611+
Min=0,
612+
Max=max_stimulation_cost_per_well_MUSD,
613+
UnitType=Units.CURRENCY,
614+
PreferredUnits=CurrencyUnit.MDOLLARS,
615+
CurrentUnits=CurrencyUnit.MDOLLARS,
616+
ToolTipText=f'Reservoir stimulation capital cost per production well'
617+
f'{stimulation_cost_per_production_well_default_value_note}'
618+
)
619+
587620
self.ccstimadjfactor = self.ParameterDict[self.ccstimadjfactor.Name] = floatParameter(
588621
"Reservoir Stimulation Capital Cost Adjustment Factor",
589622
DefaultValue=1.0,
@@ -594,7 +627,7 @@ def __init__(self, model: Model):
594627
CurrentUnits=PercentUnit.TENTH,
595628
Provided=False,
596629
Valid=True,
597-
ToolTipText="Multiplier for built-in reservoir stimulation capital cost correlation"
630+
ToolTipText="Multiplier for reservoir stimulation capital cost correlation"
598631
)
599632
self.ccexplfixed = self.ParameterDict[self.ccexplfixed.Name] = floatParameter(
600633
"Exploration Capital Cost",
@@ -1606,19 +1639,27 @@ def __init__(self, model: Model):
16061639
)
16071640

16081641
# TODO https://github.com/NREL/GEOPHIRES-X/issues/383?title=Parameterize+indirect+cost+factor
1609-
contingency_and_indirect_costs_tooltip = 'plus 15% contingency plus 12% indirect costs'
1642+
stimulation_contingency_and_indirect_costs_tooltip = 'plus 15% contingency plus 5% indirect costs'
16101643

16111644
# noinspection SpellCheckingInspection
16121645
self.Cstim = self.OutputParameterDict[self.Cstim.Name] = OutputParameter(
16131646
Name="Stimulation costs",
16141647
UnitType=Units.CURRENCY,
16151648
PreferredUnits=CurrencyUnit.MDOLLARS,
16161649
CurrentUnits=CurrencyUnit.MDOLLARS,
1617-
ToolTipText=f'Default correlation: $1.25M per injection well {contingency_and_indirect_costs_tooltip}. '
1618-
f'Provide {self.ccstimadjfactor.Name} to multiply the default correlation. '
1619-
f'Provide {self.ccstimfixed.Name} to override the default correlation and set your own cost.'
1650+
ToolTipText=f'Default correlation: ${self.stimulation_cost_per_injection_well.value}M '
1651+
f'per injection well {stimulation_contingency_and_indirect_costs_tooltip}. '
1652+
f'Provide {self.stimulation_cost_per_injection_well.Name} and '
1653+
f'{self.stimulation_cost_per_production_well.Name} to set the correlation '
1654+
f'costs per well. '
1655+
f'Provide {self.ccstimadjfactor.Name} to multiply the correlation-calculated cost. '
1656+
f'Provide {self.ccstimfixed.Name} to override the correlation and set your own '
1657+
f'total stimulation cost.'
16201658
)
16211659

1660+
# TODO https://github.com/NREL/GEOPHIRES-X/issues/383?title=Parameterize+indirect+cost+factor
1661+
contingency_and_indirect_costs_tooltip = 'plus 15% contingency plus 12% indirect costs'
1662+
16221663
# See TODO re:parameterizing indirect costs at src/geophires_x/Economics.py:652
16231664
# (https://github.com/NREL/GEOPHIRES-X/issues/383)
16241665
self.Cexpl = self.OutputParameterDict[self.Cexpl.Name] = OutputParameter(
@@ -2336,12 +2377,18 @@ def Calculate(self, model: Model) -> None:
23362377
if self.ccstimfixed.Valid:
23372378
self.Cstim.value = self.ccstimfixed.value
23382379
else:
2339-
base_stimulation_cost_MUSD_per_injection_well = 1.25 # TODO parameterize
2380+
stim_cost_per_injection_well = self.stimulation_cost_per_injection_well.quantity().to(
2381+
self.Cstim.CurrentUnits).magnitude
2382+
stim_cost_per_production_well = self.stimulation_cost_per_production_well.quantity().to(
2383+
self.Cstim.CurrentUnits).magnitude
23402384

23412385
# 1.15 for 15% contingency and 1.05 for 5% indirect costs
23422386
# TODO https://github.com/NREL/GEOPHIRES-X/issues/383?title=Parameterize+indirect+cost+factor
2343-
self.Cstim.value = (base_stimulation_cost_MUSD_per_injection_well * self.ccstimadjfactor.value
2344-
* model.wellbores.ninj.value
2387+
self.Cstim.value = ((
2388+
stim_cost_per_injection_well * model.wellbores.ninj.value
2389+
+ stim_cost_per_production_well * model.wellbores.nprod.value
2390+
)
2391+
* self.ccstimadjfactor.value
23452392
* 1.05 * 1.15)
23462393

23472394
# field gathering system costs (M$)

src/geophires_x/MPFReservoir.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def Calculate(self, model: Model):
6767
:type model: :class:`~geophires_x.Model.Model`
6868
:return: None
6969
"""
70-
model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name)
70+
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')
7171
super().Calculate(model) # run calculate for the parent.
7272

7373
# convert flowrate to volumetric rate
@@ -90,14 +90,15 @@ def Calculate(self, model: Model):
9090
for t in range(1, len(model.reserv.timevector.value)):
9191
Twnd = Twnd + [float(invertlaplace(fp, td[t], method='stehfest'))]
9292
except:
93-
print(
94-
"Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1. Simulation will abort.")
95-
sys.exit()
93+
msg = ('Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1. '
94+
'Simulation will abort.')
95+
print(msg)
96+
raise RuntimeError(msg)
9697

9798
Twnd = np.asarray(Twnd)
9899

99100
# calculate dimensional temperature, add initial rock temperature to beginning of array
100101
model.reserv.Tresoutput.value = model.reserv.Trock.value - (Twnd * (model.reserv.Trock.value - model.wellbores.Tinj.value))
101102
model.reserv.Tresoutput.value = np.append([model.reserv.Trock.value], model.reserv.Tresoutput.value)
102103

103-
model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
104+
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
@@ -478,7 +478,7 @@ def PrintOutputs(self, model: Model):
478478
if model.economics.totalcapcost.Valid and model.wellbores.redrill.value > 0:
479479
f.write(f' Drilling and completion costs (for redrilling):{model.economics.Cwell.value:10.2f} ' + model.economics.Cwell.CurrentUnits.value + NL)
480480
f.write(f' Drilling and completion costs per redrilled well: {(model.economics.Cwell.value/(model.wellbores.nprod.value+model.wellbores.ninj.value)):10.2f} ' + model.economics.Cwell.CurrentUnits.value + NL)
481-
f.write(f' Stimulation costs (for redrilling): {model.economics.Cstim.value:10.2f} ' + model.economics.Cstim.CurrentUnits.value + NL)
481+
f.write(f' Stimulation costs (for redrilling): {econ.Cstim.value:10.2f} {econ.Cstim.CurrentUnits.value}\n')
482482
if model.economics.RITCValue.value:
483483
f.write(f' {model.economics.RITCValue.display_name}: {-1*model.economics.RITCValue.value:10.2f} {model.economics.RITCValue.CurrentUnits.value}\n')
484484

src/geophires_x/WellBores.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -824,17 +824,28 @@ def __init__(self, model: Model):
824824
'production well, this parameter specifies the overall pressure drop in the reservoir between '
825825
'injection well and production well (see docs)'
826826
)
827+
828+
well_separation_default_value_m = 1000
829+
well_separation_default_unit = LengthUnit.INCHES
830+
well_separation_preferred_unit = LengthUnit.METERS
831+
well_separation_unit_mismatch_note = (f'. (Note that the default unit is '
832+
f'{well_separation_default_unit.name.lower()}.)'
833+
if well_separation_default_unit != well_separation_preferred_unit else '')
834+
# noinspection SpellCheckingInspection
827835
self.wellsep = self.ParameterDict[self.wellsep.Name] = floatParameter(
828836
"Well Separation",
829-
DefaultValue=1000.0,
837+
DefaultValue=int(quantity(well_separation_default_value_m, 'm')
838+
.to(well_separation_default_unit.value).magnitude),
830839
Min=10.,
831-
Max=10000.,
840+
Max=int(quantity(10000, 'm').to(well_separation_default_unit.value).magnitude),
832841
UnitType=Units.LENGTH,
833-
PreferredUnits=LengthUnit.METERS,
834-
CurrentUnits=LengthUnit.INCHES,
835-
ErrMessage="assume default well separation (1000 m)",
836-
ToolTipText="Well separation for built-in TOUGH2 doublet reservoir model"
842+
PreferredUnits=well_separation_preferred_unit,
843+
CurrentUnits=well_separation_default_unit,
844+
ErrMessage=f'assume default well separation ({well_separation_default_value_m} m)',
845+
ToolTipText=f'Well separation for built-in TOUGH2 doublet reservoir model'
846+
f'{well_separation_unit_mismatch_note}'
837847
)
848+
838849
self.Tinj = self.ParameterDict[self.Tinj.Name] = floatParameter(
839850
"Injection Temperature",
840851
DefaultValue=70.0,

src/geophires_x/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '3.9.31'
1+
__version__ = '3.9.33'

0 commit comments

Comments
 (0)