Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better drilling cost correlation for depth >7km; HIP-RA deprecated in favor of HIP-RA-X #148

Merged
merged 11 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.4.16
current_version = 3.4.19
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion .cookiecutterrc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ default_context:
sphinx_doctest: "no"
sphinx_theme: "sphinx-py3doc-enhanced-theme"
test_matrix_separate_coverage: "no"
version: 3.4.16
version: 3.4.19
version_manager: "bump2version"
website: "https://github.com/NREL"
year_from: "2023"
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ Free software: `MIT license <LICENSE>`__
:alt: Supported implementations
:target: https://pypi.org/project/geophires-x

.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.4.16.svg
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.4.19.svg
:alt: Commits since latest release
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.4.16...main
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.4.19...main

.. |docs| image:: https://readthedocs.org/projects/GEOPHIRES-X/badge/?style=flat
:target: https://nrel.github.io/GEOPHIRES-X
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
year = '2023'
author = 'NREL'
copyright = f'{year}, {author}'
version = release = '3.4.16'
version = release = '3.4.19'

pygments_style = 'trac'
templates_path = ['./templates']
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def read(*names, **kwargs):

setup(
name='geophires-x',
version='3.4.16',
version='3.4.19',
license='MIT',
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
long_description='{}\n{}'.format(
Expand Down
43 changes: 29 additions & 14 deletions src/geophires_x/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1974,17 +1974,33 @@ def Calculate(self, model: Model) -> None:
self.C1well = self.ccwellfixed.value
self.Cwell.value = self.C1well * (model.wellbores.nprod.value + model.wellbores.ninj.value)
else:
# if depth is > 7000 m, we don't have a correlation for it, so we must use the SIMPLE logic
checkdepth = model.reserv.depth.quantity().to('m').magnitude
if ((checkdepth > 7000.0 or checkdepth < 500) and
not self.wellcorrelation.value == WellDrillingCostCorrelation.SIMPLE):
msg = (f'Invalid cost correlation specified for drilling depth <500 or >7000 m ({checkdepth}m), '
f'falling back to simple user-specified cost '
f'({self.Vertical_drilling_cost_per_m.value} per meter)')
model.logger.warning(msg)
# Check if well depth is out of standard bounds for cost correlation
checkdepth_m = model.reserv.depth.quantity().to('m').magnitude

correlations_min_valid_depth_m = 500.
correlations_max_valid_depth_m = 7000.

if (checkdepth_m < correlations_min_valid_depth_m
and not self.wellcorrelation.value == WellDrillingCostCorrelation.SIMPLE):

self.wellcorrelation.value = WellDrillingCostCorrelation.SIMPLE
model.logger.warning(
f'Invalid cost correlation specified ({self.wellcorrelation.value}) for drilling depth '
f'<{correlations_min_valid_depth_m}m ({checkdepth_m}m). '
f'Falling back to simple user-specified cost '
f'({self.Vertical_drilling_cost_per_m.value} per meter)'
)

if (checkdepth_m > correlations_max_valid_depth_m
and not self.wellcorrelation.value == WellDrillingCostCorrelation.SIMPLE):
model.logger.warning(
f'{self.wellcorrelation.value} may be invalid for drilling depth '
f'>{correlations_max_valid_depth_m}m ({checkdepth_m}m). '
f'Consider using {WellDrillingCostCorrelation.SIMPLE} (per-meter cost) or '
f'{self.ccwellfixed.Name} (fixed cost per well) instead.'
)


# use SIMPLE approach if user has specified it
if self.wellcorrelation.value == WellDrillingCostCorrelation.SIMPLE:
# using the "Configuration" keywords means we are doing an AGS calculation
if hasattr(model.wellbores, 'Configuration'):
Expand All @@ -2009,18 +2025,17 @@ def Calculate(self, model: Model) -> None:
'm').magnitude * 1E-6

elif self.wellcorrelation.value == WellDrillingCostCorrelation.VERTICAL_SMALL:
self.C1well = ((0.3021 * checkdepth ** 2 + 584.9112 * checkdepth + 751368.)
self.C1well = ((0.3021 * checkdepth_m ** 2 + 584.9112 * checkdepth_m + 751368.)
* 1E-6) # well drilling and completion cost in M$/well

elif self.wellcorrelation.value == WellDrillingCostCorrelation.DEVIATED_SMALL:
self.C1well = (0.2898 * checkdepth ** 2 + 822.1507 * checkdepth + 680563.) * 1E-6
self.C1well = (0.2898 * checkdepth_m ** 2 + 822.1507 * checkdepth_m + 680563.) * 1E-6

elif self.wellcorrelation.value == WellDrillingCostCorrelation.VERTICAL_LARGE:

self.C1well = (0.2818 * checkdepth ** 2 + 1275.5213 * checkdepth + 632315.) * 1E-6
self.C1well = (0.2818 * checkdepth_m ** 2 + 1275.5213 * checkdepth_m + 632315.) * 1E-6

elif self.wellcorrelation.value == WellDrillingCostCorrelation.DEVIATED_LARGE:
self.C1well = (0.2553 * checkdepth ** 2 + 1716.7157 * checkdepth + 500867.) * 1E-6
self.C1well = (0.2553 * checkdepth_m ** 2 + 1716.7157 * checkdepth_m + 500867.) * 1E-6

# account for adjustment factor
self.C1well = self.ccwelladjfactor.value * self.C1well
Expand Down
1 change: 1 addition & 0 deletions src/geophires_x/GEOPHIRESv3.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def main(enable_geophires_logging_config=True):
outputfile = sys.argv[2]

with open(outputfile, 'r', encoding='UTF-8') as f:
sys.stdout.write('\n')
content = f.readlines() # store all output in one long list

# Now write each line to the screen
Expand Down
5 changes: 2 additions & 3 deletions src/geophires_x/SurfacePlant.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,8 @@ def read_parameters(self, model:Model) -> None:
if ParameterToModify.value < 0 or ParameterToModify.value > 10000:
if self.setinjectionpressurefixed:
ParameterToModify.value = 100
msg = f'Provided plant outlet pressure outside of range 0-10000. GEOPHIRES will assume default plant outlet pressure ({ParameterToModify.value} kPa)'
msg = (f'Provided plant outlet pressure outside of range 0-10000. GEOPHIRES will '
f'assume default plant outlet pressure ({ParameterToModify.value} kPa)')
print(f'Warning: {msg}')
model.logger.warning(msg)
else:
Expand All @@ -607,13 +608,11 @@ def read_parameters(self, model:Model) -> None:
self.plant_outlet_pressure.value = 100
msg = (f'No valid plant outlet pressure provided. '
f'GEOPHIRES will assume default plant outlet pressure ({self.plant_outlet_pressure.value} kPa)')
print(f'Warning: {msg}')
model.logger.warning(msg)
else:
self.usebuiltinoutletplantcorrelation.value = True
msg = (f'No valid plant outlet pressure provided. GEOPHIRES will calculate plant outlet pressure '
f'based on production wellhead pressure and surface equipment pressure drop of 10 psi')
print(f'Warning: {msg}')
model.logger.warning(msg)
else:
model.logger.info('No parameters read because no content provided')
Expand Down
1 change: 0 additions & 1 deletion src/geophires_x/WellBores.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,6 @@ def ProdPressureDropAndPumpingPowerUsingIndexes(
elif pumpdepthfinal_m > 600.0:
msg = (f'GEOPHIRES calculates production pump depth to be deeper than 600m ({pumpdepthfinal_m:.2f}m). '
f'Verify reservoir pressure, production well flow rate and production well dimensions')
print(f'Warning: {msg}')
model.logger.warning(msg)

# calculate production well pumping pressure [kPa]
Expand Down
2 changes: 1 addition & 1 deletion src/geophires_x/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.4.16'
__version__ = '3.4.19'
5 changes: 4 additions & 1 deletion src/geophires_x_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@


class GeophiresXClient:
def __init__(self, enable_caching=True, logger_name='root'):
def __init__(self, enable_caching=True, logger_name=None):
if logger_name is None:
logger_name = __name__

self._logger = _get_logger(logger_name=logger_name)
self._enable_caching = enable_caching
self._cache = {}
Expand Down
5 changes: 4 additions & 1 deletion src/geophires_x_client/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
_geophires_x_client_logger = None


def _get_logger(logger_name='root'):
def _get_logger(logger_name=None):
global _geophires_x_client_logger
if _geophires_x_client_logger is None:
sh = logging.StreamHandler(sys.stdout)
sh.setLevel(logging.INFO)
sh.setFormatter(logging.Formatter(fmt='[%(asctime)s][%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

if logger_name is None:
logger_name = __name__

_geophires_x_client_logger = logging.getLogger(logger_name)
_geophires_x_client_logger.addHandler(sh)

Expand Down
4 changes: 3 additions & 1 deletion src/geophires_x_client/geophires_x_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,9 @@ class GeophiresXResult:
'Reservoir Model',
)

def __init__(self, output_file_path, logger_name='root'):
def __init__(self, output_file_path, logger_name=None):
if logger_name is None:
logger_name = __name__
self._logger = _get_logger(logger_name)
self.output_file_path = output_file_path

Expand Down
5 changes: 5 additions & 0 deletions src/hip_ra/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# HIP-RA: Deprecated

HIP-RA is succeeded by HIP-RA-X as of 2024-03-06.

See https://github.com/NREL/GEOPHIRES-X/tree/main/src/hip_ra_x
6 changes: 2 additions & 4 deletions src/hip_ra_x/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# HIP-RA-X: Under development
# HIP-RA-X

HIP-RA-X will be the successor version to HIP-RA.
As of 2024-01-31, HIP-RA-X is still under development and should not be used for actual calculations until work is
complete. (This README should be updated or deleted once HIP-RA-X is ready to be used as a replacement for HIP-RA.)
HIP-RA-X is the successor version to HIP-RA.
Loading
Loading