From d8959ab36af928ff4d16e10524aea6fb6d796382 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:40:55 -0700 Subject: [PATCH 1/7] Update Fervo_Project_Cape-4 documentation link in examples table to main repo pages URL --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ba71f17c5..0e1828e63 100644 --- a/README.rst +++ b/README.rst @@ -288,7 +288,7 @@ Example-specific web interface deeplinks are listed in the Link column. - `Fervo_Project_Cape-3.txt `__ - `.out `__ - `link `__ - * - Case Study: 500 MWe EGS Project Modeled on Fervo Cape Station (`documentation `__) + * - Case Study: 500 MWe EGS Project Modeled on Fervo Cape Station (`documentation `__) - `Fervo_Project_Cape-4.txt `__ - `.out `__ - `link `__ From 472ee06c34703587e3b6b9f35f52c8d712c7d60f Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 07:43:38 -0700 Subject: [PATCH 2/7] Add Gringarten-Stehfest Precision parameter to MPFReservoir --- src/geophires_x/MPFReservoir.py | 44 ++++++++++++++++--- .../geophires-request.json | 9 ++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/geophires_x/MPFReservoir.py b/src/geophires_x/MPFReservoir.py index efc5ba31c..ee587f23c 100644 --- a/src/geophires_x/MPFReservoir.py +++ b/src/geophires_x/MPFReservoir.py @@ -1,8 +1,12 @@ import sys + +import mpmath import numpy as np from mpmath import * import geophires_x.Model as Model +from .Parameter import intParameter from .Reservoir import Reservoir +from .Units import Units class MPFReservoir(Reservoir): @@ -12,6 +16,7 @@ class MPFReservoir(Reservoir): It also has its own methods and attributes that are unique to this class. """ + # noinspection PyUnresolvedReferences,PyProtectedMember def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -31,15 +36,30 @@ def __init__(self, model: Model): :type model: :class:`~geophires_x.Model.Model` :return: None """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') + super().__init__(model) # initialize the parent parameters and variables sclass = str(__class__).replace("", "") - model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + + max_allowed_precision = 15 + self.gringarten_stehfest_precision = self.ParameterDict[self.gringarten_stehfest_precision.Name] = intParameter( + 'Gringarten-Stehfest Precision', + DefaultValue=15, + AllowableRange=list(range(8, max_allowed_precision + 1)), + UnitType=Units.NONE, + Required=False, + ToolTipText='Sets the numerical precision (decimal places) for the Stehfest ' + 'algorithm used for the inverse Laplace transform.' + ) + + + model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}') def __str__(self): return "MPFReservoir" + # noinspection PyUnresolvedReferences,PyProtectedMember def read_parameters(self, model: Model) -> None: """ The read_parameters function reads in the parameters from a dictionary created by reading the user-provided file @@ -51,15 +71,16 @@ def read_parameters(self, model: Model) -> None: :type model: :class:`~geophires_x.Model.Model` :return: None """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') # if we call super, we don't need to deal with setting the parameters here, # just deal with the special cases for the variables in this class # because the call to the super.readparameters will set all the variables, # including the ones that are specific to this class super().read_parameters(model) # read the parameters for the parent. - model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}') + # noinspection SpellCheckingInspection,PyUnresolvedReferences,PyProtectedMember def Calculate(self, model: Model): """ The Calculate function calculates the values of all the parameters that are calculated by this object. @@ -87,13 +108,22 @@ def Calculate(self, model: Model): # calculate non-dimensional temperature array Twnd = [] try: + stash_dps = mpmath.dps + if self.gringarten_stehfest_precision.Provided: + mpmath.dps = self.gringarten_stehfest_precision.value + for t in range(1, len(model.reserv.timevector.value)): Twnd = Twnd + [float(invertlaplace(fp, td[t], method='stehfest'))] - except: - msg = ('Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1. ' + except Exception as e_: + mpmath.dps = stash_dps + + msg = (f'Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1 ' + f'({self.gringarten_stehfest_precision.Name} = {mpmath.dps}). ' 'Simulation will abort.') print(msg) - raise RuntimeError(msg) + raise RuntimeError(msg) from e_ + + mpmath.dps = stash_dps Twnd = np.asarray(Twnd) diff --git a/src/geophires_x_schema_generator/geophires-request.json b/src/geophires_x_schema_generator/geophires-request.json index 292d7dbd1..151f6fa0a 100644 --- a/src/geophires_x_schema_generator/geophires-request.json +++ b/src/geophires_x_schema_generator/geophires-request.json @@ -412,6 +412,15 @@ "minimum": 0, "maximum": 0.2 }, + "Gringarten-Stehfest Precision": { + "description": "Sets the numerical precision (decimal places) for the Stehfest algorithm used for the inverse Laplace transform.", + "type": "integer", + "units": null, + "category": "Reservoir", + "default": 15, + "minimum": 8, + "maximum": 15 + }, "Cylindrical Reservoir Input Depth": { "description": "Depth of the inflow end of a cylindrical reservoir", "type": "number", From 73e9ce28e8b0c80de4ed9ac43df417c1f42c4edb Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 07:57:26 -0700 Subject: [PATCH 3/7] Parse simulation metadata calculation time in result (will be used in unit test for precision) --- src/geophires_x_client/geophires_x_result.py | 5 ++++- src/geophires_x_schema_generator/geophires-result.json | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/geophires_x_client/geophires_x_result.py b/src/geophires_x_client/geophires_x_result.py index e2ad90298..aabb76199 100644 --- a/src/geophires_x_client/geophires_x_result.py +++ b/src/geophires_x_client/geophires_x_result.py @@ -346,7 +346,10 @@ class GeophiresXResult: 'Average Annual Total Heating Production', 'Average Annual Electricity Use for Pumping', ], - 'Simulation Metadata': [_StringValueField('GEOPHIRES Version')], + 'Simulation Metadata': [ + _StringValueField('GEOPHIRES Version'), + 'Calculation Time', + ], } ) diff --git a/src/geophires_x_schema_generator/geophires-result.json b/src/geophires_x_schema_generator/geophires-result.json index fa345748a..4edc6f710 100644 --- a/src/geophires_x_schema_generator/geophires-result.json +++ b/src/geophires_x_schema_generator/geophires-result.json @@ -555,7 +555,8 @@ "Simulation Metadata": { "type": "object", "properties": { - "GEOPHIRES Version": {} + "GEOPHIRES Version": {}, + "Calculation Time": {} } } } From a38fc4f2a30bcec9b2ee4dc51bd1e8d83097e1d0 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 07:58:03 -0700 Subject: [PATCH 4/7] test_gringarten_stehfest_precision --- src/geophires_x/MPFReservoir.py | 10 ++++----- tests/geophires_x_tests/test_reservoir.py | 26 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/geophires_x/MPFReservoir.py b/src/geophires_x/MPFReservoir.py index ee587f23c..879739983 100644 --- a/src/geophires_x/MPFReservoir.py +++ b/src/geophires_x/MPFReservoir.py @@ -1,6 +1,6 @@ import sys -import mpmath +from mpmath import mp import numpy as np from mpmath import * import geophires_x.Model as Model @@ -108,14 +108,14 @@ def Calculate(self, model: Model): # calculate non-dimensional temperature array Twnd = [] try: - stash_dps = mpmath.dps + stash_dps = mp.dps if self.gringarten_stehfest_precision.Provided: - mpmath.dps = self.gringarten_stehfest_precision.value + mp.dps = self.gringarten_stehfest_precision.value for t in range(1, len(model.reserv.timevector.value)): Twnd = Twnd + [float(invertlaplace(fp, td[t], method='stehfest'))] except Exception as e_: - mpmath.dps = stash_dps + mp.dps = stash_dps msg = (f'Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1 ' f'({self.gringarten_stehfest_precision.Name} = {mpmath.dps}). ' @@ -123,7 +123,7 @@ def Calculate(self, model: Model): print(msg) raise RuntimeError(msg) from e_ - mpmath.dps = stash_dps + mp.dps = stash_dps Twnd = np.asarray(Twnd) diff --git a/tests/geophires_x_tests/test_reservoir.py b/tests/geophires_x_tests/test_reservoir.py index 98985cb6c..f57749729 100644 --- a/tests/geophires_x_tests/test_reservoir.py +++ b/tests/geophires_x_tests/test_reservoir.py @@ -12,10 +12,12 @@ from geophires_x_client import GeophiresInputParameters from geophires_x_client import GeophiresXClient from geophires_x_client import GeophiresXResult +from geophires_x_client import ImmutableGeophiresInputParameters from tests.base_test_case import BaseTestCase class ReservoirTestCase(BaseTestCase): + def test_lithostatic_pressure(self): p = static_pressure_MPa(2700, 3000) self.assertEqual(79.433865, p) @@ -32,6 +34,30 @@ def test_reservoir_lithostatic_pressure(self): self.assertAlmostEqual(79.433865, p.magnitude, places=3) self.assertEqual('megapascal', p.units) + def test_gringarten_stehfest_precision(self): + def _get_result(gringarten_stehfest_precision: int) -> GeophiresXResult: + return GeophiresXClient(enable_caching=False).get_geophires_result( + ImmutableGeophiresInputParameters( + from_file_path=self._get_test_file_path('generic-egs-case.txt'), + params={'Gringarten-Stehfest Precision': gringarten_stehfest_precision}, + ) + ) + + _ = _get_result(15) # warm up any caching + result_15 = _get_result(15) + result_8 = _get_result(8) + + def calc_time(r: GeophiresXResult) -> float: + return r.result['Simulation Metadata']['Calculation Time']['value'] + + calc_time_15_sec = calc_time(result_15) + calc_time_8_sec = calc_time(result_8) + + msg = f'calc_time_15_sec={calc_time_15_sec}, calc_time_8_sec={calc_time_8_sec}' + print(f'[DEBUG] {msg}') + + self.assertLess(calc_time_8_sec, calc_time_15_sec) + # noinspection PyMethodMayBeStatic def _new_model(self, input_file=None) -> Model: stash_cwd = Path.cwd() From 779cc3aa740539ba6211334985eef60d8d2eff4f Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 08:00:34 -0700 Subject: [PATCH 5/7] log speedup --- tests/geophires_x_tests/test_reservoir.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/geophires_x_tests/test_reservoir.py b/tests/geophires_x_tests/test_reservoir.py index f57749729..52ce8e142 100644 --- a/tests/geophires_x_tests/test_reservoir.py +++ b/tests/geophires_x_tests/test_reservoir.py @@ -35,6 +35,9 @@ def test_reservoir_lithostatic_pressure(self): self.assertEqual('megapascal', p.units) def test_gringarten_stehfest_precision(self): + def _log(msg) -> None: + print(f'[DEBUG][test_gringarten_stehfest_precision] {msg}') + def _get_result(gringarten_stehfest_precision: int) -> GeophiresXResult: return GeophiresXClient(enable_caching=False).get_geophires_result( ImmutableGeophiresInputParameters( @@ -53,11 +56,13 @@ def calc_time(r: GeophiresXResult) -> float: calc_time_15_sec = calc_time(result_15) calc_time_8_sec = calc_time(result_8) - msg = f'calc_time_15_sec={calc_time_15_sec}, calc_time_8_sec={calc_time_8_sec}' - print(f'[DEBUG] {msg}') + _log(f'calc_time_15_sec={calc_time_15_sec}, calc_time_8_sec={calc_time_8_sec}') self.assertLess(calc_time_8_sec, calc_time_15_sec) + speedup_pct = ((calc_time_15_sec - calc_time_8_sec) / calc_time_15_sec) * 100 + _log(f'Speedup: {speedup_pct:.2f}%') + # noinspection PyMethodMayBeStatic def _new_model(self, input_file=None) -> Model: stash_cwd = Path.cwd() From c843be0871d4406556caeef55e882d6578c4e68d Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:23:17 -0700 Subject: [PATCH 6/7] update unit tests affected by addition of Calulcation Time result field --- tests/example1_addons.csv | 3 ++- tests/examples/example1_addons.out | 8 ++++---- tests/geophires-result_example-3.csv | 1 + tests/test_geophires_x.py | 11 +++++++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/tests/example1_addons.csv b/tests/example1_addons.csv index 0599d06cf..b02d3b434 100644 --- a/tests/example1_addons.csv +++ b/tests/example1_addons.csv @@ -98,7 +98,8 @@ SURFACE EQUIPMENT SIMULATION RESULTS,Average Annual Net Electricity Generation,, SURFACE EQUIPMENT SIMULATION RESULTS,Average Pumping Power,,0.2,MW SURFACE EQUIPMENT SIMULATION RESULTS,Initial pumping power/net installed power,,3.82,% SURFACE EQUIPMENT SIMULATION RESULTS,Heat to Power Conversion Efficiency,,10.07,% -Simulation Metadata,GEOPHIRES Version,,3.9.44, +Simulation Metadata,GEOPHIRES Version,,3.9.49, +Simulation Metadata,Calculation Time,,0.852,sec POWER GENERATION PROFILE,THERMAL DRAWDOWN,1,1.0, POWER GENERATION PROFILE,THERMAL DRAWDOWN,2,1.0056, POWER GENERATION PROFILE,THERMAL DRAWDOWN,3,1.0073, diff --git a/tests/examples/example1_addons.out b/tests/examples/example1_addons.out index a29a34fa5..298006df1 100644 --- a/tests/examples/example1_addons.out +++ b/tests/examples/example1_addons.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.44 - Simulation Date: 2025-07-29 - Simulation Time: 06:46 - Calculation Time: 0.898 sec + GEOPHIRES Version: 3.9.49 + Simulation Date: 2025-08-21 + Simulation Time: 09:19 + Calculation Time: 0.852 sec ***SUMMARY OF RESULTS*** diff --git a/tests/geophires-result_example-3.csv b/tests/geophires-result_example-3.csv index 471040120..42508b6e1 100644 --- a/tests/geophires-result_example-3.csv +++ b/tests/geophires-result_example-3.csv @@ -82,6 +82,7 @@ SURFACE EQUIPMENT SIMULATION RESULTS,Average Annual Heat Production,,87.2,GWh SURFACE EQUIPMENT SIMULATION RESULTS,Average Pumping Power,,0.18,MW SURFACE EQUIPMENT SIMULATION RESULTS,Initial pumping power/net installed power,,100.0,% Simulation Metadata,GEOPHIRES Version,,3.0, +Simulation Metadata,Calculation Time,,0.057,sec POWER GENERATION PROFILE,THERMAL DRAWDOWN,0,1.0, POWER GENERATION PROFILE,THERMAL DRAWDOWN,1,1.0081, POWER GENERATION PROFILE,THERMAL DRAWDOWN,2,1.0097, diff --git a/tests/test_geophires_x.py b/tests/test_geophires_x.py index 0ac9abf15..0e50e5d4a 100644 --- a/tests/test_geophires_x.py +++ b/tests/test_geophires_x.py @@ -67,6 +67,9 @@ def test_geophires_x_end_use_direct_use_heat(self): if 'metadata' in result_same_input.result: del result_same_input.result['metadata'] + del result.result['Simulation Metadata']['Calculation Time'] + del result_same_input.result['Simulation Metadata']['Calculation Time'] + self.assertDictEqual(result.result, result_same_input.result) # noinspection PyMethodMayBeStatic @@ -362,6 +365,10 @@ def test_RTES_name(self): self.assertEqual(PlantType.RTES.value, 'Reservoir Thermal Energy Storage') def test_input_unit_conversion(self): + def delete_metadata(r: GeophiresXResult) -> None: + del r.result['metadata'] + del r.result['Simulation Metadata']['Calculation Time'] + client = GeophiresXClient() result_meters_input = client.get_geophires_result( @@ -371,7 +378,7 @@ def test_input_unit_conversion(self): ) ) ) - del result_meters_input.result['metadata'] + delete_metadata(result_meters_input) result_kilometers_input = client.get_geophires_result( GeophiresInputParameters( @@ -380,7 +387,7 @@ def test_input_unit_conversion(self): ) ) ) - del result_kilometers_input.result['metadata'] + delete_metadata(result_kilometers_input) self.assertDictEqual(result_kilometers_input.result, result_meters_input.result) From f97ce79099547a74399eeda5689c6235b37ac2df Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:36:03 -0700 Subject: [PATCH 7/7] Ignore calculation time in test_input_with_non_default_units --- docs/_images/geophires-favicon.png | Bin 0 -> 44354 bytes tests/test_geophires_x_client.py | 56 ++++++++++++++++------------- 2 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 docs/_images/geophires-favicon.png diff --git a/docs/_images/geophires-favicon.png b/docs/_images/geophires-favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..d69d881046ae022dc2b05b03b7fc9f676a2b660d GIT binary patch literal 44354 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 literal 0 HcmV?d00001 diff --git a/tests/test_geophires_x_client.py b/tests/test_geophires_x_client.py index d9bb8438b..f3f8fa873 100644 --- a/tests/test_geophires_x_client.py +++ b/tests/test_geophires_x_client.py @@ -440,36 +440,44 @@ def test_input_hashing(self): self.assertNotEqual(hash(input1), hash(input3)) def test_input_with_non_default_units(self): + def delete_metadata(r: GeophiresXResult) -> GeophiresXResult: + del r.result['metadata'] + del r.result['Simulation Metadata']['Calculation Time'] + + return r + client = GeophiresXClient() - result_default_units = client.get_geophires_result( - GeophiresInputParameters( - { - 'Print Output to Console': 0, - 'End-Use Option': EndUseOption.DIRECT_USE_HEAT.value, - 'Reservoir Model': 1, - 'Time steps per year': 1, - 'Reservoir Depth': 3, - 'Gradient 1': 50, - 'Maximum Temperature': 250, - } + result_default_units = delete_metadata( + client.get_geophires_result( + GeophiresInputParameters( + { + 'Print Output to Console': 0, + 'End-Use Option': EndUseOption.DIRECT_USE_HEAT.value, + 'Reservoir Model': 1, + 'Time steps per year': 1, + 'Reservoir Depth': 3, + 'Gradient 1': 50, + 'Maximum Temperature': 250, + } + ) ) ).result - del result_default_units['metadata'] - result_non_default_units = client.get_geophires_result( - GeophiresInputParameters( - { - 'Print Output to Console': 0, - 'End-Use Option': EndUseOption.DIRECT_USE_HEAT.value, - 'Reservoir Model': 1, - 'Time steps per year': 1, - 'Reservoir Depth': '3000 meter', - 'Gradient 1': 50, - 'Maximum Temperature': 250, - } + result_non_default_units = delete_metadata( + client.get_geophires_result( + GeophiresInputParameters( + { + 'Print Output to Console': 0, + 'End-Use Option': EndUseOption.DIRECT_USE_HEAT.value, + 'Reservoir Model': 1, + 'Time steps per year': 1, + 'Reservoir Depth': '3000 meter', + 'Gradient 1': 50, + 'Maximum Temperature': 250, + } + ) ) ).result - del result_non_default_units['metadata'] self.assertDictEqual(result_default_units, result_non_default_units)