From 4fadaa29759593b68f6f2b4d9ba782899cae51f8 Mon Sep 17 00:00:00 2001 From: Malcolm Ross Date: Fri, 9 Feb 2024 12:11:11 -0600 Subject: [PATCH 1/3] Post conversation on jan 30, i am updaating HIP-RA so that you can see a version that doesn't calculate negative enthalpies but may still be wrong. This update to HIP-RA-X adds the input variables to the report, as we discussed during our last meeting. I also added two more calculations and reported values: heat per unit volme and power per unit volume for the reservoir. This is essentially an energy density calculation. This passes the tests (after I updated the .out file to look right with the new reported lines). --- src/geophires_x/Units.py | 12 ++++ src/hip_ra_x/hip_ra_x.py | 71 +++++++++++++++---- .../examples/HIP-RA-X_example1.out | 20 +++++- 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/src/geophires_x/Units.py b/src/geophires_x/Units.py index 32c37fe9..7c484ab8 100644 --- a/src/geophires_x/Units.py +++ b/src/geophires_x/Units.py @@ -44,6 +44,8 @@ class Units(IntEnum): POPDENSITY = auto() HEATPERUNITAREA = auto() POWERPERUNITAREA = auto() + HEATPERUNITVOLUME = auto() + POWERPERUNITVOLUME = auto() class TemperatureUnit(str, Enum): @@ -313,3 +315,13 @@ class HeatPerUnitAreaUnit(str,Enum): class PowerPerUnitAreaUnit(str,Enum): """Population Density Units""" MWPERSQKM = "MW/km**2" + + +class HeatPerUnitVolumeUnit(str,Enum): + """Population Density Units""" + KJPERCUBICKM = "KJ/km**3" + + +class PowerPerUnitVolumeUnit(str,Enum): + """Population Density Units""" + MWPERCUBICKM = "MW/km**3" diff --git a/src/hip_ra_x/hip_ra_x.py b/src/hip_ra_x/hip_ra_x.py index 3d4f4488..b4728d84 100644 --- a/src/hip_ra_x/hip_ra_x.py +++ b/src/hip_ra_x/hip_ra_x.py @@ -41,6 +41,8 @@ from geophires_x.Units import TimeUnit from geophires_x.Units import Units from geophires_x.Units import VolumeUnit +from geophires_x.Units import HeatPerUnitVolumeUnit +from geophires_x.Units import PowerPerUnitVolumeUnit """ Heat in Place calculation: Muffler, P., and Raffaele Cataldi. @@ -305,7 +307,7 @@ def parameter_dict_entry(param: Parameter) -> Parameter: CurrentUnits=VolumeUnit.KILOMETERS3, ) self.volume_recoverable_fluid = self.OutputParameterDict[self.volume_recoverable_fluid.Name] = OutputParameter( - Name='Recoverable Fluid Volume', + Name='Recoverable Volume (recoverable fluid)', UnitType=Units.VOLUME, PreferredUnits=VolumeUnit.KILOMETERS3, CurrentUnits=VolumeUnit.KILOMETERS3, @@ -488,6 +490,12 @@ def parameter_dict_entry(param: Parameter) -> Parameter: PreferredUnits=HeatPerUnitAreaUnit.KJPERSQKM, CurrentUnits=HeatPerUnitAreaUnit.KJPERSQKM, ) + self.heat_per_unit_volume_reservoir = self.OutputParameterDict[self.heat_per_unit_volume_reservoir.Name] = OutputParameter( + Name='Producible Heat/Unit volume (reservoir)', + UnitType=Units.HEATPERUNITVOLUME, + PreferredUnits=HeatPerUnitVolumeUnit.KJPERCUBICKM, + CurrentUnits=HeatPerUnitVolumeUnit.KJPERCUBICKM, + ) self.producible_electricity_per_unit_area = self.OutputParameterDict[ self.producible_electricity_per_unit_area.Name ] = OutputParameter( @@ -512,6 +520,14 @@ def parameter_dict_entry(param: Parameter) -> Parameter: PreferredUnits=PowerPerUnitAreaUnit.MWPERSQKM, CurrentUnits=PowerPerUnitAreaUnit.MWPERSQKM, ) + self.electricity_per_unit_volume_reservoir = self.OutputParameterDict[ + self.electricity_per_unit_volume_reservoir.Name + ] = OutputParameter( + Name='Producible Electricity/Unit volume (reservoir)', + UnitType=Units.POWERPERUNITVOLUME, + PreferredUnits=PowerPerUnitVolumeUnit.MWPERCUBICKM, + CurrentUnits=PowerPerUnitVolumeUnit.MWPERCUBICKM, + ) self.logger.info(f'Complete {__class__.__name__!s}: {__name__}') @@ -659,18 +675,14 @@ def Calculate(self): electricity_with_actual_power_plant_kW = UtilEff_func(self.reservoir_temperature.value) * maximum_power_kW producible_power_kW = electricity_with_actual_power_plant_kW - self.reservoir_producible_electricity.value = ( - HIP_RA_X._ureg.Quantity(producible_power_kW, 'kW').to('MW').magnitude - ) + self.reservoir_producible_electricity.value = HIP_RA_X._ureg.Quantity(producible_power_kW, 'kW').to('MW').magnitude - self.electricity_per_unit_area_fluid.value = ( - self.producible_electricity_fluid.value / self.reservoir_area.value - ) - self.producible_electricity_per_unit_area.value = ( - self.reservoir_producible_electricity.value / self.reservoir_area.value - ) + self.electricity_per_unit_area_fluid.value = self.producible_electricity_fluid.value / self.reservoir_area.value + self.producible_electricity_per_unit_area.value = self.reservoir_producible_electricity.value / self.reservoir_area.value + self.electricity_per_unit_volume_reservoir.value = self.reservoir_producible_electricity.value / self.reservoir_volume.value self.producible_heat_per_unit_area.value = self.reservoir_producible_heat.value / self.reservoir_area.value + self.heat_per_unit_volume_reservoir.value = self.reservoir_producible_heat.value / self.reservoir_volume.value self.logger.info(f'Complete {__class__!s}: {__class__.__name__!s}: {__name__}') except Exception as e: @@ -717,12 +729,34 @@ def render_default(p: floatParameter | OutputParameter) -> str: def render_scientific(p: floatParameter | OutputParameter) -> str: return f'{p.value:10.2e} {p.CurrentUnits.value}' + summary_of_inputs = {} summary_of_results = {} for param, render in [ # TODO: Commented parameters are defined in initialization but not calculated - either calculate or # remove entirely (self.reservoir_temperature, render_default), + (self.rejection_temperature, render_default), + (self.reservoir_porosity, render_default), + (self.reservoir_area, render_default), + (self.reservoir_thickness, render_default), + (self.reservoir_life_cycle, render_default), + (self.rock_heat_capacity, render_default), + (self.fluid_heat_capacity, render_default), + (self.fluid_density, render_default), + (self.rock_density, render_default), +# (self.rock_recoverable_heat, render_default), +# (self.fluid_recoverable_heat, render_default), + (self.recoverable_fluid_factor, render_default), + (self.recoverable_rock_heat, render_default), + ]: + summary_of_inputs[param.Name] = render(param) + + case_data_inputs = {'SUMMARY OF INPUTS': summary_of_inputs} + + for param, render in [ + # TODO: Commented parameters are defined in initialization but not calculated - either calculate or + # remove entirely (self.reservoir_volume, render_default), (self.volume_rock, render_default), (self.volume_recoverable_fluid, render_default), @@ -757,18 +791,20 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: # (self.producible_heat_rock, render_scientific), # (self.producible_heat_fluid, render_scientific), (self.producible_heat_per_unit_area, render_scientific), + (self.heat_per_unit_volume_reservoir, render_scientific), # (self.heat_per_unit_area_rock, render_scientific), # (self.heat_per_unit_area_fluid, render_scientific), (self.reservoir_producible_electricity, render_default), # (self.producible_electricity_rock, render_default), # (self.producible_electricity_fluid, render_default), (self.producible_electricity_per_unit_area, render_default), + (self.electricity_per_unit_volume_reservoir, render_default), # (self.electricity_per_unit_area_rock, render_default), # (self.electricity_per_unit_area_fluid, render_default), ]: summary_of_results[param.Name] = render(param) - case_data = {'SUMMARY OF RESULTS': summary_of_results} + case_data_results = {'SUMMARY OF RESULTS': summary_of_results} with open(outputfile, 'w', encoding='UTF-8') as f: nl = '\n' @@ -777,10 +813,17 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: f.write(f' ***HIP CASE REPORT***{nl}') f.write(f' *********************{nl}') f.write(nl) - f.write(f' ***SUMMARY OF RESULTS***{nl}') - f.write(nl) + f.write(f' ***SUMMARY OF INPUTS***{nl}') - for k, v in case_data['SUMMARY OF RESULTS'].items(): + for k, v in case_data_inputs['SUMMARY OF INPUTS'].items(): + # align space between value and units to same column + kv_spaces = max(1, (24 - (len(v.split(' ')[0]) + len(k)))) * ' ' + + f.write(f' {k}:{kv_spaces}{v}{nl}') + + f.write(nl) + f.write(f' **SUMMARY OF RESULTS***{nl}') + for k, v in case_data_results['SUMMARY OF RESULTS'].items(): # align space between value and units to same column kv_spaces = max(1, (24 - (len(v.split(' ')[0]) + len(k)))) * ' ' diff --git a/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out b/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out index b8d641b8..a5d9d220 100644 --- a/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out +++ b/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out @@ -2,12 +2,24 @@ ***HIP CASE REPORT*** ********************* - ***SUMMARY OF RESULTS*** - + ***SUMMARY OF INPUTS*** Reservoir Temperature: 250.00 degC + Rejection Temperature: 60.00 degC + Reservoir Porosity: 10.00 % + Reservoir Area: 55.00 km**2 + Reservoir Thickness: 0.25 kilometer + Reservoir Life Cycle: 25.00 yr + Rock Heat Capacity: 2840000000000.00 kJ/km**3C + Fluid Specific Heat Capacity: 4.86 kJ/kgC + Density Of Reservoir Fluid: 798889919298.16 kg/km**3 + Density Of Reservoir Rock: 2550000000000.00 kg/km**3 + Recoverable Fluid Factor: 0.50 + Recoverable Heat from Rock: 0.75 + + **SUMMARY OF RESULTS*** Reservoir Volume (reservoir): 13.75 km**3 Reservoir Volume (rock): 12.38 km**3 - Recoverable Fluid Volume: 0.69 km**3 + Recoverable Volume (recoverable fluid): 0.69 km**3 Stored Heat (reservoir): 5.47e+15 kJ Stored Heat (rock): 5.01e+15 kJ Stored Heat (fluid): 4.58e+14 kJ @@ -20,5 +32,7 @@ Available Heat (reservoir): 1.18e+15 kJ Producible Heat (reservoir): 7.82e+14 kJ Producible Heat/Unit Area (reservoir): 1.42e+13 KJ/km**2 + Producible Heat/Unit volume (reservoir): 5.69e+13 KJ/km**3 Producible Electricity (reservoir): 500.82 MW Producible Electricity/Unit Area (reservoir): 9.11 MW/km**2 + Producible Electricity/Unit volume (reservoir): 36.42 MW/km**3 From 5a64729eba40c01431d5414ac47d93b5977bb888 Mon Sep 17 00:00:00 2001 From: Malcolm Ross Date: Fri, 9 Feb 2024 14:19:11 -0600 Subject: [PATCH 2/3] Updated HIP-RA-X for fit and finish issues identified by Jonathan. --- src/geophires_x/Units.py | 4 ++-- src/hip_ra_x/hip_ra_x.py | 44 +++++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/geophires_x/Units.py b/src/geophires_x/Units.py index 7c484ab8..008531eb 100644 --- a/src/geophires_x/Units.py +++ b/src/geophires_x/Units.py @@ -309,7 +309,7 @@ class PopDensityUnit(str,Enum): class HeatPerUnitAreaUnit(str,Enum): """Population Density Units""" - KJPERSQKM = "KJ/km**2" + KJPERSQKM = "kJ/km**2" class PowerPerUnitAreaUnit(str,Enum): @@ -319,7 +319,7 @@ class PowerPerUnitAreaUnit(str,Enum): class HeatPerUnitVolumeUnit(str,Enum): """Population Density Units""" - KJPERCUBICKM = "KJ/km**3" + KJPERCUBICKM = "kJ/km**3" class PowerPerUnitVolumeUnit(str,Enum): diff --git a/src/hip_ra_x/hip_ra_x.py b/src/hip_ra_x/hip_ra_x.py index b4728d84..8f45deb5 100644 --- a/src/hip_ra_x/hip_ra_x.py +++ b/src/hip_ra_x/hip_ra_x.py @@ -31,18 +31,18 @@ from geophires_x.Units import EnthalpyUnit from geophires_x.Units import HeatCapacityUnit from geophires_x.Units import HeatPerUnitAreaUnit +from geophires_x.Units import HeatPerUnitVolumeUnit from geophires_x.Units import HeatUnit from geophires_x.Units import LengthUnit from geophires_x.Units import MassUnit from geophires_x.Units import PercentUnit from geophires_x.Units import PowerPerUnitAreaUnit +from geophires_x.Units import PowerPerUnitVolumeUnit from geophires_x.Units import PowerUnit from geophires_x.Units import TemperatureUnit from geophires_x.Units import TimeUnit from geophires_x.Units import Units from geophires_x.Units import VolumeUnit -from geophires_x.Units import HeatPerUnitVolumeUnit -from geophires_x.Units import PowerPerUnitVolumeUnit """ Heat in Place calculation: Muffler, P., and Raffaele Cataldi. @@ -490,8 +490,10 @@ def parameter_dict_entry(param: Parameter) -> Parameter: PreferredUnits=HeatPerUnitAreaUnit.KJPERSQKM, CurrentUnits=HeatPerUnitAreaUnit.KJPERSQKM, ) - self.heat_per_unit_volume_reservoir = self.OutputParameterDict[self.heat_per_unit_volume_reservoir.Name] = OutputParameter( - Name='Producible Heat/Unit volume (reservoir)', + self.heat_per_unit_volume_reservoir = self.OutputParameterDict[ + self.heat_per_unit_volume_reservoir.Name + ] = OutputParameter( + Name='Producible Heat/Unit Volume (reservoir)', UnitType=Units.HEATPERUNITVOLUME, PreferredUnits=HeatPerUnitVolumeUnit.KJPERCUBICKM, CurrentUnits=HeatPerUnitVolumeUnit.KJPERCUBICKM, @@ -523,7 +525,7 @@ def parameter_dict_entry(param: Parameter) -> Parameter: self.electricity_per_unit_volume_reservoir = self.OutputParameterDict[ self.electricity_per_unit_volume_reservoir.Name ] = OutputParameter( - Name='Producible Electricity/Unit volume (reservoir)', + Name='Producible Electricity/Unit Volume (reservoir)', UnitType=Units.POWERPERUNITVOLUME, PreferredUnits=PowerPerUnitVolumeUnit.MWPERCUBICKM, CurrentUnits=PowerPerUnitVolumeUnit.MWPERCUBICKM, @@ -675,14 +677,24 @@ def Calculate(self): electricity_with_actual_power_plant_kW = UtilEff_func(self.reservoir_temperature.value) * maximum_power_kW producible_power_kW = electricity_with_actual_power_plant_kW - self.reservoir_producible_electricity.value = HIP_RA_X._ureg.Quantity(producible_power_kW, 'kW').to('MW').magnitude + self.reservoir_producible_electricity.value = ( + HIP_RA_X._ureg.Quantity(producible_power_kW, 'kW').to('MW').magnitude + ) - self.electricity_per_unit_area_fluid.value = self.producible_electricity_fluid.value / self.reservoir_area.value - self.producible_electricity_per_unit_area.value = self.reservoir_producible_electricity.value / self.reservoir_area.value - self.electricity_per_unit_volume_reservoir.value = self.reservoir_producible_electricity.value / self.reservoir_volume.value + self.electricity_per_unit_area_fluid.value = ( + self.producible_electricity_fluid.value / self.reservoir_area.value + ) + self.producible_electricity_per_unit_area.value = ( + self.reservoir_producible_electricity.value / self.reservoir_area.value + ) + self.electricity_per_unit_volume_reservoir.value = ( + self.reservoir_producible_electricity.value / self.reservoir_volume.value + ) self.producible_heat_per_unit_area.value = self.reservoir_producible_heat.value / self.reservoir_area.value - self.heat_per_unit_volume_reservoir.value = self.reservoir_producible_heat.value / self.reservoir_volume.value + self.heat_per_unit_volume_reservoir.value = ( + self.reservoir_producible_heat.value / self.reservoir_volume.value + ) self.logger.info(f'Complete {__class__!s}: {__class__.__name__!s}: {__name__}') except Exception as e: @@ -741,12 +753,12 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: (self.reservoir_area, render_default), (self.reservoir_thickness, render_default), (self.reservoir_life_cycle, render_default), - (self.rock_heat_capacity, render_default), + (self.rock_heat_capacity, render_scientific), (self.fluid_heat_capacity, render_default), - (self.fluid_density, render_default), - (self.rock_density, render_default), -# (self.rock_recoverable_heat, render_default), -# (self.fluid_recoverable_heat, render_default), + (self.fluid_density, render_scientific), + (self.rock_density, render_scientific), + # (self.rock_recoverable_heat, render_default), + # (self.fluid_recoverable_heat, render_default), (self.recoverable_fluid_factor, render_default), (self.recoverable_rock_heat, render_default), ]: @@ -822,7 +834,7 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: f.write(f' {k}:{kv_spaces}{v}{nl}') f.write(nl) - f.write(f' **SUMMARY OF RESULTS***{nl}') + f.write(f' ***SUMMARY OF RESULTS***{nl}') for k, v in case_data_results['SUMMARY OF RESULTS'].items(): # align space between value and units to same column kv_spaces = max(1, (24 - (len(v.split(' ')[0]) + len(k)))) * ' ' From 50ae559fb3972569a0b12af51b7042483ea7775c Mon Sep 17 00:00:00 2001 From: Malcolm Ross Date: Fri, 9 Feb 2024 14:24:59 -0600 Subject: [PATCH 3/3] I forgot to upload a new version of the .out file! --- .../hip_ra_x_tests/examples/HIP-RA-X_example1.out | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out b/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out index a5d9d220..9aea3bac 100644 --- a/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out +++ b/tests/hip_ra_x_tests/examples/HIP-RA-X_example1.out @@ -9,14 +9,14 @@ Reservoir Area: 55.00 km**2 Reservoir Thickness: 0.25 kilometer Reservoir Life Cycle: 25.00 yr - Rock Heat Capacity: 2840000000000.00 kJ/km**3C + Rock Heat Capacity: 2.84e+12 kJ/km**3C Fluid Specific Heat Capacity: 4.86 kJ/kgC - Density Of Reservoir Fluid: 798889919298.16 kg/km**3 - Density Of Reservoir Rock: 2550000000000.00 kg/km**3 + Density Of Reservoir Fluid: 7.99e+11 kg/km**3 + Density Of Reservoir Rock: 2.55e+12 kg/km**3 Recoverable Fluid Factor: 0.50 Recoverable Heat from Rock: 0.75 - **SUMMARY OF RESULTS*** + ***SUMMARY OF RESULTS*** Reservoir Volume (reservoir): 13.75 km**3 Reservoir Volume (rock): 12.38 km**3 Recoverable Volume (recoverable fluid): 0.69 km**3 @@ -31,8 +31,8 @@ Recovery Factor (reservoir): 14.30 % Available Heat (reservoir): 1.18e+15 kJ Producible Heat (reservoir): 7.82e+14 kJ - Producible Heat/Unit Area (reservoir): 1.42e+13 KJ/km**2 - Producible Heat/Unit volume (reservoir): 5.69e+13 KJ/km**3 + Producible Heat/Unit Area (reservoir): 1.42e+13 kJ/km**2 + Producible Heat/Unit Volume (reservoir): 5.69e+13 kJ/km**3 Producible Electricity (reservoir): 500.82 MW Producible Electricity/Unit Area (reservoir): 9.11 MW/km**2 - Producible Electricity/Unit volume (reservoir): 36.42 MW/km**3 + Producible Electricity/Unit Volume (reservoir): 36.42 MW/km**3