Skip to content

Commit 4eb9734

Browse files
Merge pull request NREL#336 from softwareengineerprogrammer/main
Fix lateral cost output, add missing result fields [v3.7.13]
2 parents b142b10 + a32ce23 commit 4eb9734

File tree

14 files changed

+115
-50
lines changed

14 files changed

+115
-50
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.7.6
2+
current_version = 3.7.13
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.7.6
57+
version: 3.7.13
5858
version_manager: "bump2version"
5959
website: "https://github.com/NREL"
6060
year_from: "2023"

README.rst

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

59-
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.7.6.svg
59+
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.7.13.svg
6060
:alt: Commits since latest release
61-
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.7.6...main
61+
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.7.13...main
6262

6363
.. |docs| image:: https://readthedocs.org/projects/GEOPHIRES-X/badge/?style=flat
6464
:target: https://nrel.github.io/GEOPHIRES-X
@@ -298,6 +298,9 @@ The capital and O&M costs for the different geothermal system components (explor
298298
well drilling, surface plant, etc.) are either provided by the user or calculated with built-in
299299
correlations.
300300

301+
For more information on the theoretical basis for GEOPHIRES see
302+
`GEOPHIRES v2.0: updated geothermal techno‐economic simulation tool (Beckers & McCabe, 2019) <References/Beckers%202019%20GEOPHIRES%20v2.pdf>`__.
303+
301304
Parameters
302305
----------
303306

@@ -496,9 +499,6 @@ Extending GEOPHIRES-X
496499
Additional Documentation
497500
------------------------
498501

499-
Theoretical basis for GEOPHIRES: `GEOPHIRES v2.0: updated geothermal techno‐economic simulation tool <References/Beckers%202019%20GEOPHIRES%20v2.pdf>`__;
500-
accompanying `GEOPHIRES v2.0 user manual <References/GEOPHIRES%20v2.0%20User%20Manual.pdf>`__.
501-
502502
Additional materials can be found in `/References </References>`__.
503503

504504

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.7.6'
21+
version = release = '3.7.13'
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.7.6',
16+
version='3.7.13',
1717
license='MIT',
1818
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
1919
long_description='{}\n{}'.format(

src/geophires_x/Outputs.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,8 +1742,11 @@ def PrintOutputs(self, model: Model):
17421742
f.write(f' Number of fractures: {model.reserv.fracnumbcalc.value:10.2f}' + NL)
17431743
f.write(f' Fracture separation: {model.reserv.fracsepcalc.value:10.2f} ' + model.reserv.fracsep.CurrentUnits.value + NL)
17441744
f.write(f' Reservoir volume: {model.reserv.resvolcalc.value:10.0f} ' + model.reserv.resvol.CurrentUnits.value + NL)
1745+
17451746
if model.wellbores.impedancemodelused.value:
1746-
f.write(f' Reservoir impedance: {model.wellbores.impedance.value/1000:10.2f} ' + model.wellbores.impedance.CurrentUnits.value + NL)
1747+
# See note re: unit conversion:
1748+
# https://github.com/NREL/GEOPHIRES-X/blob/d51eb8d1dc8b21c7a79c4d35f296d740347658e0/src/geophires_x/WellBores.py#L1280-L1282
1749+
f.write(f' Reservoir impedance: {model.wellbores.impedance.value/1000:10.4f} {model.wellbores.impedance.CurrentUnits.value}\n')
17471750
else:
17481751
if model.wellbores.overpressure_percentage.Provided:
17491752
# write the reservoir pressure as an average in the overpressure case
@@ -1803,14 +1806,14 @@ def PrintOutputs(self, model: Model):
18031806
f.write(NL)
18041807
if not model.economics.totalcapcost.Valid:
18051808
f.write(f' Drilling and completion costs: {model.economics.Cwell.value:10.2f} ' + model.economics.Cwell.CurrentUnits.value + NL)
1806-
if round(econ.cost_one_production_well.value, 4) != round(econ.cost_one_injection_well.value, 4) and \
1807-
model.economics.cost_one_injection_well.value != -1:
1808-
f.write(f' Drilling and completion costs per production well: {econ.cost_one_production_well.value:10.2f} ' + econ.cost_one_production_well.CurrentUnits.value + NL)
1809-
f.write(f' Drilling and completion costs per injection well: {econ.cost_one_injection_well.value:10.2f} ' + econ.cost_one_injection_well.CurrentUnits.value + NL)
1810-
elif econ.cost_lateral_section.value > 0.0:
1809+
if econ.cost_lateral_section.value > 0.0:
18111810
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)
18121811
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)
18131812
f.write(f' {econ.cost_per_lateral_section.Name}: {econ.cost_per_lateral_section.value:10.2f} {econ.cost_lateral_section.CurrentUnits.value}\n')
1813+
elif round(econ.cost_one_production_well.value, 4) != round(econ.cost_one_injection_well.value, 4) and \
1814+
model.economics.cost_one_injection_well.value != -1:
1815+
f.write(f' Drilling and completion costs per production well: {econ.cost_one_production_well.value:10.2f} ' + econ.cost_one_production_well.CurrentUnits.value + NL)
1816+
f.write(f' Drilling and completion costs per injection well: {econ.cost_one_injection_well.value:10.2f} ' + econ.cost_one_injection_well.CurrentUnits.value + NL)
18141817
else:
18151818
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)
18161819
f.write(f' Stimulation costs: {model.economics.Cstim.value:10.2f} ' + model.economics.Cstim.CurrentUnits.value + NL)

src/geophires_x/WellBores.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -749,17 +749,17 @@ def __init__(self, model: Model):
749749
CurrentUnits=LengthUnit.INCHES,
750750
Required=True,
751751
ErrMessage="assume default injection well diameter (8 inch)",
752-
ToolTipText="Inner diameter of production wellbore (assumed constant along the wellbore) to calculate \
753-
frictional pressure drop and wellbore heat transmission with Rameys model"
752+
ToolTipText="Inner diameter of production wellbore (assumed constant along the wellbore) to calculate "
753+
"frictional pressure drop and wellbore heat transmission with Rameys model"
754754
)
755755
self.rameyoptionprod = self.ParameterDict[self.rameyoptionprod.Name] = boolParameter(
756756
"Ramey Production Wellbore Model",
757757
DefaultValue=True,
758758
UnitType=Units.NONE,
759759
Required=True,
760760
ErrMessage="assume default production wellbore model (Ramey model active)",
761-
ToolTipText="Select whether to use Rameys model to estimate the geofluid temperature drop in the \
762-
production wells"
761+
ToolTipText="Select whether to use Rameys model to estimate the geofluid temperature drop in the "
762+
"production wells"
763763
)
764764
self.tempdropprod = self.ParameterDict[self.tempdropprod.Name] = floatParameter(
765765
"Production Wellbore Temperature Drop",
@@ -796,16 +796,20 @@ def __init__(self, model: Model):
796796
)
797797
self.impedance = self.ParameterDict[self.impedance.Name] = floatParameter(
798798
"Reservoir Impedance",
799+
800+
# Note default/input value units are converted as a special case in read_parameters; see
801+
# https://github.com/NREL/GEOPHIRES-X/blob/d51eb8d1dc8b21c7a79c4d35f296d740347658e0/src/geophires_x/WellBores.py#L1280-L1282
799802
DefaultValue=1000.0,
803+
800804
Min=1E-4,
801805
Max=1E4,
802806
UnitType=Units.IMPEDANCE,
803807
PreferredUnits=ImpedanceUnit.GPASPERM3,
804808
CurrentUnits=ImpedanceUnit.GPASPERM3,
805809
ErrMessage="assume default reservoir impedance (0.1 GPa*s/m^3)",
806-
ToolTipText="Reservoir resistance to flow per well-pair. For EGS-type reservoirs when the injection well \
807-
is in hydraulic communication with the production well, this parameter specifies the overall pressure drop \
808-
in the reservoir between injection well and production well (see docs)"
810+
ToolTipText="Reservoir resistance to flow per well-pair. For EGS-type reservoirs when the injection well "
811+
"is in hydraulic communication with the production well, this parameter specifies the overall "
812+
"pressure drop in the reservoir between injection well and production well (see docs)"
809813
)
810814
self.wellsep = self.ParameterDict[self.wellsep.Name] = floatParameter(
811815
"Well Separation",
@@ -839,8 +843,8 @@ def __init__(self, model: Model):
839843
PreferredUnits=PressureUnit.KPASCAL,
840844
CurrentUnits=PressureUnit.KPASCAL,
841845
ErrMessage="calculate reservoir hydrostatic pressure using built-in correlation",
842-
ToolTipText="Reservoir hydrostatic far-field pressure. Default value is calculated with built-in modified \
843-
Xie-Bloomfield-Shook equation (DOE, 2016)."
846+
ToolTipText="Reservoir hydrostatic far-field pressure. Default value is calculated with built-in modified "
847+
"Xie-Bloomfield-Shook equation (DOE, 2016)."
844848
)
845849
self.ppwellhead = self.ParameterDict[self.ppwellhead.Name] = floatParameter(
846850
"Production Wellhead Pressure",
@@ -862,8 +866,8 @@ def __init__(self, model: Model):
862866
PreferredUnits=InjectivityIndexUnit.KGPERSECPERBAR,
863867
CurrentUnits=InjectivityIndexUnit.KGPERSECPERBAR,
864868
ErrMessage="assume default injectivity index (10 kg/s/bar)",
865-
ToolTipText="Injectivity index defined as ratio of injection well flow rate over injection well outflow \
866-
pressure drop (flowing bottom hole pressure - hydrostatic reservoir pressure)."
869+
ToolTipText="Injectivity index defined as ratio of injection well flow rate over injection well outflow "
870+
"pressure drop (flowing bottom hole pressure - hydrostatic reservoir pressure)."
867871
)
868872
self.PI = self.ParameterDict[self.PI.Name] = floatParameter(
869873
"Productivity Index",
@@ -874,8 +878,8 @@ def __init__(self, model: Model):
874878
PreferredUnits=ProductivityIndexUnit.KGPERSECPERBAR,
875879
CurrentUnits=ProductivityIndexUnit.KGPERSECPERBAR,
876880
ErrMessage="assume default productivity index (10 kg/s/bar)",
877-
ToolTipText="Productivity index defined as ratio of production well flow rate over production well inflow \
878-
pressure drop (see docs)"
881+
ToolTipText="Productivity index defined as ratio of production well flow rate over production well inflow "
882+
"pressure drop (see docs)"
879883
)
880884
self.maxdrawdown = self.ParameterDict[self.maxdrawdown.Name] = floatParameter(
881885
"Maximum Drawdown",
@@ -886,10 +890,10 @@ def __init__(self, model: Model):
886890
PreferredUnits=PercentUnit.TENTH,
887891
CurrentUnits=PercentUnit.TENTH,
888892
ErrMessage="assume default maximum drawdown (1)",
889-
ToolTipText="Maximum allowable thermal drawdown before redrilling of all wells into new reservoir \
890-
(most applicable to EGS-type reservoirs with heat farming strategies). E.g. a value of 0.2 means that \
891-
all wells are redrilled after the production temperature (at the wellhead) has dropped by 20% of \
892-
its initial temperature"
893+
ToolTipText="Maximum allowable thermal drawdown before redrilling of all wells into new reservoir "
894+
"(most applicable to EGS-type reservoirs with heat farming strategies). E.g. a value of 0.2 "
895+
"means that all wells are redrilled after the production temperature (at the wellhead) has "
896+
"dropped by 20% of its initial temperature"
893897
)
894898
self.IsAGS = self.ParameterDict[self.IsAGS.Name] = boolParameter(
895899
"Is AGS",
@@ -946,7 +950,8 @@ def __init__(self, model: Model):
946950
PreferredUnits=PressureUnit.KPASCAL,
947951
CurrentUnits=PressureUnit.KPASCAL,
948952
Required=False,
949-
ErrMessage="assume there is not an injection reservoir, so there is no injection reservoir initial pressure",
953+
ErrMessage="assume there is not an injection reservoir, so there is no injection reservoir initial "
954+
"pressure",
950955
ToolTipText="enter the depth of the injection reservoir initial pressure (use lithostatic pressure)"
951956
)
952957
self.injection_reservoir_inflation_rate = self.ParameterDict[self.injection_reservoir_inflation_rate.Name] = floatParameter(
@@ -956,7 +961,8 @@ def __init__(self, model: Model):
956961
CurrentUnits=Inflation_RateUnit.KPASCALPERYEAR,
957962
Required=False,
958963
ErrMessage="assume there is not an injection reservoir, so there is no injection reservoir inflation rate",
959-
ToolTipText="enter the rate at which the pressure increases per year in the injection reservoir (1000 kPa/yr)"
964+
ToolTipText="enter the rate at which the pressure increases per year in the injection reservoir "
965+
"(1000 kPa/yr)"
960966
)
961967
# This is a alias for "Well Geometry Configuration" - putting it here for backwards compatibility
962968
self.Configuration = self.ParameterDict[self.Configuration.Name] = intParameter(
@@ -1275,7 +1281,8 @@ def read_parameters(self, model: Model) -> None:
12751281
# impedance: impedance per well pair (input as GPa*s/m^3 and converted to KPa/kg/s
12761282
# (assuming 1000 for density; density will be corrected for later))
12771283
elif ParameterToModify.Name == "Reservoir Impedance":
1278-
# shift it by a constant to make the units right, per line 619 of GEOPHIRES 2
1284+
# shift it by a constant to make the units right, per line 619 of GEOPHIRES 2:
1285+
# https://github.com/NREL/GEOPHIRES-v2/blob/08485b98ae02aeb7a5acd972f906b2ea81ae2647/GEOPHIRESv2.py#L610-L619
12791286
self.impedance.value = self.impedance.value * (1E6 / 1E3)
12801287
self.impedancemodelused.value = True
12811288
if self.impedance.Provided is False:

src/geophires_x/__init__.py

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

src/geophires_x_client/geophires_x_result.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,15 @@ class GeophiresXResult:
143143
# TODO moved to power generation profile, parse from there
144144
# 'Annual Thermal Drawdown (%/year)',
145145
'Bottom-hole temperature',
146+
'Well separation: fracture diameter',
146147
'Well separation: fracture height',
147-
'Fracture area',
148148
'Fracture width',
149+
'Fracture area',
150+
'Number of fractures',
151+
'Fracture separation',
152+
# TODO reservoir volume note
149153
'Reservoir volume',
154+
'Reservoir impedance',
150155
'Reservoir hydrostatic pressure',
151156
'Average reservoir pressure',
152157
'Plant outlet pressure',
@@ -166,10 +171,16 @@ class GeophiresXResult:
166171
'Initial Production Temperature',
167172
'Average Reservoir Heat Extraction',
168173
_EqualSignDelimitedField('Production Wellbore Heat Transmission Model'),
174+
_EqualSignDelimitedField('Wellbore Heat Transmission Model'),
169175
'Average Production Well Temperature Drop',
176+
'Total Average Pressure Drop',
177+
'Average Injection Well Pressure Drop',
178+
'Average Production Pressure', # AGS
179+
'Average Reservoir Pressure Drop',
180+
'Average Production Well Pressure Drop',
181+
'Average Buoyancy Pressure Drop',
170182
'Average Injection Well Pump Pressure Drop',
171183
'Average Production Well Pump Pressure Drop',
172-
'Average Production Pressure',
173184
'Average Heat Production',
174185
'First Year Heat Production',
175186
'Average Net Electricity Production',
@@ -187,7 +198,6 @@ class GeophiresXResult:
187198
'Average Annual Heat Supplied',
188199
'Minimum Annual Heat Supplied',
189200
'Average Round-Trip Efficiency',
190-
'Total Average Pressure Drop',
191201
],
192202
'CAPITAL COSTS (M$)': [
193203
'Drilling and completion costs',
@@ -477,7 +487,7 @@ def normalize_spaces(matched_line):
477487
return {'value': self._parse_number(str_val, field=f'field "{field_name}"'), 'unit': unit}
478488

479489
def _get_equal_sign_delimited_field(self, field_name):
480-
metadata_marker = f'{field_name} = '
490+
metadata_marker = f' {field_name} = '
481491
matching_lines = set(filter(lambda line: metadata_marker in line, self._lines))
482492

483493
if len(matching_lines) == 0:

src/geophires_x_schema_generator/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from geophires_x.SUTRAReservoir import SUTRAReservoir
2828
from geophires_x.SUTRAWellBores import SUTRAWellBores
2929
from geophires_x.TDPReservoir import TDPReservoir
30+
from geophires_x.TOUGH2Reservoir import TOUGH2Reservoir
3031
from hip_ra_x.hip_ra_x import HIP_RA_X
3132

3233

@@ -60,6 +61,7 @@ def get_parameter_sources(self) -> list:
6061
(CylindricalReservoir(dummy_model), 'Reservoir'),
6162
(SBTReservoir(dummy_model), 'Reservoir'),
6263
(SUTRAReservoir(dummy_model), 'Reservoir'),
64+
(TOUGH2Reservoir(dummy_model), 'Reservoir'),
6365
(dummy_model.wellbores, 'Well Bores'),
6466
(AGSWellBores(dummy_model), 'Well Bores'),
6567
(SBTWellbores(dummy_model), 'Well Bores'),

0 commit comments

Comments
 (0)