diff --git a/src/geophires_x/GeoPHIRESUtils.py b/src/geophires_x/GeoPHIRESUtils.py index 09b2805e..1c49c2f5 100644 --- a/src/geophires_x/GeoPHIRESUtils.py +++ b/src/geophires_x/GeoPHIRESUtils.py @@ -102,15 +102,13 @@ def quantity(value: float, unit: str) -> PlainQuantity: @lru_cache -def density_water_kg_per_m3( - Twater_degC: float, - pressure: Optional[PlainQuantity] = None) -> float: +def density_water_kg_per_m3(Twater_degC: float, pressure: Optional[PlainQuantity] = None) -> float: """ Calculate the density of water as a function of temperature. Args: Twater_degC: The temperature of water in degrees C. - pressure: Pressure - should be provided + pressure: Pressure - should be provided as a Pint quantity that knows its units Returns: The density of water in kg/m³. Raises: @@ -244,15 +242,13 @@ def RecoverableHeat(Twater_degC: float) -> float: @lru_cache -def vapor_pressure_water_kPa( - Twater_degC: float, - pressure: Optional[PlainQuantity] = None) -> float: +def vapor_pressure_water_kPa(Twater_degC: float, pressure: Optional[PlainQuantity] = None) -> float: """ Calculate the vapor pressure of water as a function of temperature. Args: Twater_degC: the temperature of water in degrees C - pressure: Pressure - should be provided + pressure: Pressure - should be provided as a Pint quantity that knows its units Returns: The vapor pressure of water as a function of temperature in kPa Raises: @@ -275,22 +271,23 @@ def vapor_pressure_water_kPa( return (quantity(CP.PropsSI('P', 'T', celsius_to_kelvin(Twater_degC), 'Q', 0, 'Water'), 'Pa') .to('kPa').magnitude) - except (NotImplementedError, ValueError) as e: raise ValueError(f'Input temperature {Twater_degC} is out of range or otherwise not implemented') from e @lru_cache -def entropy_water_kJ_per_kg_per_K(temperature_degC: float) -> float: +def entropy_water_kJ_per_kg_per_K(temperature_degC: float, pressure: Optional[PlainQuantity] = None) -> float: """ Calculate the entropy of water as a function of temperature - TODO take pressure as a parameter https://github.com/NREL/GEOPHIRES-X/issues/119 Args: temperature_degC: the temperature of water in degrees C + pressure: Pressure - should be provided as a Pint quantity that knows its units Returns: the entropy of water as a function of temperature in kJ/(kg·K) Raises: + TypeError: If temperature is not a float or convertible to float. + ValueError: If temperature is not within the range of 0 to 373.946 degrees C. """ try: @@ -299,19 +296,23 @@ def entropy_water_kJ_per_kg_per_K(temperature_degC: float) -> float: raise TypeError(f'Input temperature ({temperature_degC}) must be a float') try: - return CP.PropsSI('S', 'T', celsius_to_kelvin(temperature_degC), 'Q', 0, 'Water') * 1e-3 + if pressure is not None: + return CP.PropsSI('S', 'T', celsius_to_kelvin(temperature_degC), + 'P', pressure.to('Pa').magnitude, 'Water') * 1e-3 + else: + return CP.PropsSI('S', 'T', celsius_to_kelvin(temperature_degC), 'Q', 0, 'Water') * 1e-3 except (NotImplementedError, ValueError) as e: raise ValueError(f'Input temperature {temperature_degC} is out of range or otherwise not implemented') from e @lru_cache -def enthalpy_water_kJ_per_kg(temperature_degC: float) -> float: +def enthalpy_water_kJ_per_kg(temperature_degC: float, pressure: Optional[PlainQuantity] = None) -> float: """ Calculate the enthalpy of water as a function of temperature - TODO take pressure as a parameter https://github.com/NREL/GEOPHIRES-X/issues/119 Args: temperature_degC: the temperature of water in degrees C (float) + pressure: Pressure - should be provided as a Pint quantity that knows its units Returns: the enthalpy of water as a function of temperature in kJ/kg Raises: @@ -324,7 +325,12 @@ def enthalpy_water_kJ_per_kg(temperature_degC: float) -> float: raise TypeError(f'Input temperature ({temperature_degC}) must be a float') try: - return CP.PropsSI('H', 'T', celsius_to_kelvin(temperature_degC), 'Q', 0, 'Water') * 1e-3 + if pressure is not None: + return CP.PropsSI('H', 'T', celsius_to_kelvin(temperature_degC), + 'P', pressure.to('Pa').magnitude, 'Water') * 1e-3 + else: + return CP.PropsSI('H', 'T', celsius_to_kelvin(temperature_degC), 'Q', 0, 'Water') * 1e-3 + except (NotImplementedError, ValueError) as e: raise ValueError(f'Input temperature {temperature_degC} is out of range or otherwise not implemented') from e @@ -456,15 +462,15 @@ def json_dumpse(obj) -> str: return json.dumps(obj, cls=_EnhancedJSONEncoder) -def lithostatic_pressure_MPa(rho_kg_per_m3: float, depth_m: float) -> float: +def static_pressure_MPa(rho_kg_per_m3: float, depth_m: float) -> float: """ - Calculate lithostatic pressure in a reservoir. + Calculate litho- (or hydro-) static pressure in a reservoir. Args: rho_kg_per_m3 (float): Density of the fluid in kg/m^3. depth_m (float): Depth of the reservoir in meters. Returns: - float: Lithostatic pressure in megapascals (MPa). + pint quantity: Lithostatic pressure in megapascals (MPa). """ g = scipy.constants.g # Acceleration due to gravity (m/s^2) diff --git a/src/geophires_x/Reservoir.py b/src/geophires_x/Reservoir.py index 129a5aaf..f644efd1 100644 --- a/src/geophires_x/Reservoir.py +++ b/src/geophires_x/Reservoir.py @@ -10,7 +10,7 @@ from .Units import * import geophires_x.Model as Model -from geophires_x.GeoPHIRESUtils import heat_capacity_water_J_per_kg_per_K, quantity, lithostatic_pressure_MPa +from geophires_x.GeoPHIRESUtils import heat_capacity_water_J_per_kg_per_K, quantity, static_pressure_MPa from geophires_x.GeoPHIRESUtils import density_water_kg_per_m3 class Reservoir: @@ -795,7 +795,7 @@ def Calculate(self, model: Model) -> None: model.logger.info(f'complete {str(__class__)}: {sys._getframe().f_code.co_name}') def lithostatic_pressure(self) -> PlainQuantity: - return quantity(lithostatic_pressure_MPa(self.rhorock.quantity().to('kg/m**3').magnitude, - self.depth.quantity().to('m').magnitude), 'MPa') + return quantity(static_pressure_MPa(self.rhorock.quantity().to('kg/m**3').magnitude, + self.depth.quantity().to('m').magnitude), 'MPa') diff --git a/src/geophires_x/Units.py b/src/geophires_x/Units.py index 008531eb..fef9c48f 100644 --- a/src/geophires_x/Units.py +++ b/src/geophires_x/Units.py @@ -193,6 +193,7 @@ class CostPerDistanceUnit(str, Enum): class PressureUnit(str, Enum): """Pressure Units""" + MPASCAL = "mPa" KPASCAL = "kPa" PASCAL = "Pa" BAR = "bar" diff --git a/src/geophires_x/WellBores.py b/src/geophires_x/WellBores.py index b3c436a9..1be24f51 100644 --- a/src/geophires_x/WellBores.py +++ b/src/geophires_x/WellBores.py @@ -3,7 +3,7 @@ from pint.facets.plain import PlainQuantity from .Parameter import floatParameter, intParameter, boolParameter, OutputParameter, ReadParameter -from geophires_x.GeoPHIRESUtils import vapor_pressure_water_kPa, quantity, lithostatic_pressure_MPa +from geophires_x.GeoPHIRESUtils import vapor_pressure_water_kPa, quantity, static_pressure_MPa from geophires_x.GeoPHIRESUtils import density_water_kg_per_m3 from geophires_x.GeoPHIRESUtils import viscosity_water_Pa_sec from .Units import * diff --git a/src/hip_ra_x/hip_ra_x.py b/src/hip_ra_x/hip_ra_x.py index bbf3c50a..5a8b75a2 100644 --- a/src/hip_ra_x/hip_ra_x.py +++ b/src/hip_ra_x/hip_ra_x.py @@ -17,6 +17,7 @@ from geophires_x.GeoPHIRESUtils import entropy_water_kJ_per_kg_per_K from geophires_x.GeoPHIRESUtils import heat_capacity_water_J_per_kg_per_K from geophires_x.GeoPHIRESUtils import read_input_file +from geophires_x.GeoPHIRESUtils import static_pressure_MPa from geophires_x.Parameter import ConvertOutputUnits from geophires_x.Parameter import ConvertUnitsBack from geophires_x.Parameter import LookupUnits @@ -39,6 +40,7 @@ from geophires_x.Units import PowerPerUnitAreaUnit from geophires_x.Units import PowerPerUnitVolumeUnit from geophires_x.Units import PowerUnit +from geophires_x.Units import PressureUnit from geophires_x.Units import TemperatureUnit from geophires_x.Units import TimeUnit from geophires_x.Units import Units @@ -278,6 +280,38 @@ def parameter_dict_entry(param: Parameter) -> Parameter: ToolTipText='percent of fluid that is recoverable from the reservoir (0.5 = 50%)', ) ) + self.reservoir_depth: Parameter = parameter_dict_entry( + floatParameter( + 'Reservoir Depth', + value=-1.0, + Min=0.001, + Max=15.0, + UnitType=Units.LENGTH, + PreferredUnits=LengthUnit.KILOMETERS, + CurrentUnits=LengthUnit.KILOMETERS, + Required=False, + Provided=False, + ErrMessage='calculate based on an assumed gradient of 30 C/km and the reservoir temperature', + ToolTipText='depth to top of reservoir (km). Calculated based on an assumed gradient \ + and the reservoir temperature if no value given', + ) + ) + self.reservoir_pressure: Parameter = parameter_dict_entry( + floatParameter( + 'Reservoir Pressure', + value=-1.0, + Min=0.00, + Max=10000.000, + UnitType=Units.PRESSURE, + PreferredUnits=PressureUnit.MPASCAL, + CurrentUnits=PressureUnit.MPASCAL, + Required=False, + Provided=False, + ErrMessage='calculate assuming hydrostatic pressure and the reservoir depth & water density', + ToolTipText='pressure of the of reservoir (in mPa). Calculated assuming hydrostatic pressure and \ + reservoir depth & water density if no value given', + ) + ) self.recoverable_rock_heat: Parameter = parameter_dict_entry( floatParameter( 'Recoverable Heat from Rock', @@ -555,9 +589,8 @@ def read_parameters(self) -> None: # Before we change the parameter, let's assume that the unit preferences will match - # if they don't, the later code will fix this. ParameterToModify.CurrentUnits = ParameterToModify.PreferredUnits - ReadParameter( - ParameterReadIn, ParameterToModify, self - ) # this should handle all the non-special cases + # this should handle all the non-special cases + ReadParameter(ParameterReadIn, ParameterToModify, self) else: self.logger.info('No parameters read because no content provided') @@ -578,25 +611,42 @@ def Calculate(self): try: # Calculate the volume of rock and fluid in the reservoir. - self.reservoir_volume.value = self.reservoir_area.value * self.reservoir_thickness.value self.volume_rock.value = self.reservoir_volume.value * (1.0 - (self.reservoir_porosity.value / 100.0)) + + # Note that we can't recover all the fluid from the reservoir, so we multiply by the recoverable fluid factor self.volume_recoverable_fluid.value = ( self.reservoir_volume.value * (self.reservoir_porosity.value / 100.0) * self.recoverable_fluid_factor.value - # Note that we can't recover all the fluid from the reservoir, - # so we multiply by the recoverable fluid factor ) + if not self.reservoir_depth.Provided: + self.logger.info( + f'Deriving value of {self.reservoir_depth.Name} because provided value ' + f'({self.reservoir_depth.value}) was not provided)' + ) + # assume ambient Temperature of 15 C and 30C/km + self.reservoir_depth.value = (self.reservoir_temperature.value - 15.0) / 30.0 + + if not self.reservoir_pressure.Provided: + self.logger.info( + f'Deriving value of {self.reservoir_pressure.Name} because provided value ' + f'({self.reservoir_pressure.value}) was not provided)' + ) + # Assumes a water density of 1.0 g/cm3, which is high, since the water density decreases with depth + self.reservoir_pressure.value = static_pressure_MPa(1000.0, self.reservoir_depth.value * 1000.0) + if self.fluid_density.value < self.fluid_density.Min: self.logger.info( f'Deriving value of {self.fluid_density.Name} because provided value ' f'({self.fluid_density.value}) was less than min ({self.fluid_density.Min})' ) - density_h20_kg_per_m3 = density_water_kg_per_m3(self.reservoir_temperature.value) - + density_h20_kg_per_m3 = density_water_kg_per_m3( + self.reservoir_temperature.value, + pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa'), + ) self.fluid_density.value = density_h20_kg_per_m3 * 1_000_000_000.0 # converted to kg/km3 self.mass_rock.value = self.volume_rock.value * self.rock_density.value @@ -609,48 +659,50 @@ def Calculate(self): f'({self.fluid_heat_capacity.value}) was less than min ({self.fluid_heat_capacity.Min})' ) + # converted to kJ/(kg·K) self.fluid_heat_capacity.value = ( - heat_capacity_water_J_per_kg_per_K(self.reservoir_temperature.value) + heat_capacity_water_J_per_kg_per_K( + self.reservoir_temperature.value, + pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa'), + ) / 1000.0 - # converted to kJ/(kg·K) ) rejection_temperature_k = celsius_to_kelvin(self.rejection_temperature.value) reservoir_temperature_k = celsius_to_kelvin(self.reservoir_temperature.value) delta_temperature_k = reservoir_temperature_k - rejection_temperature_k - fluid_net_enthalpy = fluid_net_enthalpy = enthalpy_water_kJ_per_kg( - self.reservoir_temperature.value - ) - enthalpy_water_kJ_per_kg(self.rejection_temperature.value) + fluid_net_enthalpy = enthalpy_water_kJ_per_kg( + self.reservoir_temperature.value, pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa') + ) - enthalpy_water_kJ_per_kg( + self.rejection_temperature.value, pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa') + ) fluid_net_entropy = entropy_water_kJ_per_kg_per_K( - self.reservoir_temperature.value - ) - entropy_water_kJ_per_kg_per_K(self.rejection_temperature.value) + self.reservoir_temperature.value, pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa') + ) - entropy_water_kJ_per_kg_per_K( + self.rejection_temperature.value, pressure=HIP_RA_X._ureg.Quantity(self.reservoir_pressure.value, 'MPa') + ) # fmt: off - self.enthalpy_rock.value = ( - self.rock_heat_capacity.value * delta_temperature_k * self.volume_rock.value - ) / self.mass_rock.value + self.enthalpy_rock.value = ((self.rock_heat_capacity.value * delta_temperature_k * self.volume_rock.value) / + self.mass_rock.value) # fmt: on + # result in kJ self.stored_heat_rock.value = ( - self.recoverable_rock_heat.value - * self.enthalpy_rock.value - * self.mass_rock.value - # result in kJ + self.recoverable_rock_heat.value * self.enthalpy_rock.value * self.mass_rock.value ) - self.stored_heat_fluid.value = fluid_net_enthalpy * self.mass_recoverable_fluid.value # result in kJ + self.stored_heat_fluid.value = fluid_net_enthalpy * self.mass_recoverable_fluid.value self.reservoir_stored_heat.value = self.stored_heat_rock.value + self.stored_heat_fluid.value # equation 4 in Garg and Combs(2011) amount_fluid_produced_kg = self.reservoir_stored_heat.value / fluid_net_enthalpy self.mass_recoverable_fluid.value = amount_fluid_produced_kg + # equation 7 in Garg and Combs(2011) fluid_exergy_kJ_per_kg = ( - # equation 7 in Garg and Combs(2011) - fluid_net_enthalpy - - celsius_to_kelvin(self.rejection_temperature.value) * fluid_net_entropy + fluid_net_enthalpy - celsius_to_kelvin(self.rejection_temperature.value) * fluid_net_entropy ) self.enthalpy_fluid.value = fluid_exergy_kJ_per_kg - self.reservoir_enthalpy.value = self.enthalpy_rock.value + self.enthalpy_fluid.value # (equation 8 in Garg and Combs(2011)) @@ -671,9 +723,7 @@ def Calculate(self): self.reservoir_producible_heat.value / self.reservoir_stored_heat.value ) - # Now assuming a 30-year lifetime: - plant_lifetime_years = 30 - maximum_power_kW = maximum_lifetime_electricity_kJ / (plant_lifetime_years * 365 * 24 * 3600) + maximum_power_kW = maximum_lifetime_electricity_kJ / (self.reservoir_life_cycle.value * 365 * 24 * 3600) electricity_with_actual_power_plant_kW = UtilEff_func(self.reservoir_temperature.value) * maximum_power_kW producible_power_kW = electricity_with_actual_power_plant_kW @@ -744,9 +794,7 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: 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 + inputs = [ (self.reservoir_temperature, render_default), (self.rejection_temperature, render_default), (self.reservoir_porosity, render_default), @@ -757,63 +805,52 @@ def render_scientific(p: floatParameter | OutputParameter) -> str: (self.fluid_heat_capacity, 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), - ]: + ] + + # If depth and/or pressure are provided, report them as inputs. If not, as outputs + if self.reservoir_depth.Provided: + inputs.append((self.reservoir_depth, render_default)) + if self.reservoir_pressure.Provided: + inputs.append((self.reservoir_pressure, render_default)) + + for param, render in inputs: 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 + outputs = [ (self.reservoir_volume, render_default), (self.volume_rock, render_default), (self.volume_recoverable_fluid, render_default), (self.reservoir_stored_heat, render_scientific), (self.stored_heat_rock, render_scientific), (self.stored_heat_fluid, render_scientific), - # (self.reservoir_mass, render_scientific), (self.mass_rock, render_scientific), (self.mass_recoverable_fluid, render_scientific), (self.reservoir_enthalpy, render_default), (self.enthalpy_rock, render_default), (self.enthalpy_fluid, render_default), - # (self.wellhead_heat, render_scientific), - # (self.wellhead_heat_recovery_rock, render_scientific), - # (self.wellhead_heat_recovery_fluid, render_scientific), ( self.reservoir_recovery_factor, lambda rg: f'{(100 * rg.value):10.2f} {self.reservoir_recovery_factor.CurrentUnits.value}', ), - # ( - # self.recovery_factor_rock, - # lambda rg: f'{(100 * rg.value):10.2f} {self.recovery_factor_rock.CurrentUnits.value}', - # ), - # ( - # self.recovery_factor_fluid, - # lambda rg: f'{(100 * rg.value):10.2f} {self.recovery_factor_fluid.CurrentUnits.value}', - # ), (self.reservoir_available_heat, render_scientific), - # (self.available_heat_rock, render_scientific), - # (self.available_heat_fluid, render_scientific), (self.reservoir_producible_heat, render_scientific), - # (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), - ]: + ] + + # If depth and/or pressure are provided, report them as inputs. If not, as outputs + if not self.reservoir_depth.Provided: + outputs.insert(0, (self.reservoir_depth, render_default)) + if not self.reservoir_pressure.Provided: + outputs.insert(0, (self.reservoir_pressure, render_default)) + for param, render in outputs: summary_of_results[param.Name] = render(param) case_data_results = {'SUMMARY OF RESULTS': summary_of_results} diff --git a/tests/geophires_x_tests/test_reservoir.py b/tests/geophires_x_tests/test_reservoir.py index a5a837d4..0cedc225 100644 --- a/tests/geophires_x_tests/test_reservoir.py +++ b/tests/geophires_x_tests/test_reservoir.py @@ -5,14 +5,14 @@ from pint.facets.plain import PlainQuantity from base_test_case import BaseTestCase -from geophires_x.GeoPHIRESUtils import lithostatic_pressure_MPa +from geophires_x.GeoPHIRESUtils import static_pressure_MPa from geophires_x.Model import Model from geophires_x.Reservoir import Reservoir class ReservoirTestCase(BaseTestCase): def test_lithostatic_pressure(self): - p = lithostatic_pressure_MPa(2700, 3000) + p = static_pressure_MPa(2700, 3000) self.assertEqual(79.433865, p) def test_reservoir_lithostatic_pressure(self): 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 2ee618ee..3856b409 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 @@ -10,29 +10,31 @@ Reservoir Thickness: 0.25 kilometer Reservoir Life Cycle: 25.00 yr Rock Heat Capacity: 2.84e+12 kJ/km**3C - Fluid Specific Heat Capacity: 4.87 kJ/kgC - Density Of Reservoir Fluid: 7.99e+11 kg/km**3 + Fluid Specific Heat Capacity: 4.34 kJ/kgC + Density Of Reservoir Fluid: 8.62e+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*** + Reservoir Pressure: 76.82 mPa + Reservoir Depth: 7.83 kilometer Reservoir Volume (reservoir): 13.75 km**3 Reservoir Volume (rock): 12.38 km**3 Recoverable Volume (recoverable fluid): 0.69 km**3 - Stored Heat (reservoir): 5.47e+15 kJ + Stored Heat (reservoir): 5.48e+15 kJ Stored Heat (rock): 5.01e+15 kJ - Stored Heat (fluid): 4.58e+14 kJ + Stored Heat (fluid): 4.67e+14 kJ Mass of Reservoir (rock): 3.16e+13 kilogram - Mass of Reservoir (fluid): 6.55e+12 kilogram - Specific Enthalpy (reservoir): 392.48 kJ/kg + Mass of Reservoir (fluid): 6.95e+12 kilogram + Specific Enthalpy (reservoir): 377.60 kJ/kg Specific Enthalpy (rock): 211.61 kJ/kg - Specific Enthalpy (fluid): 180.87 kJ/kg - 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 Electricity (reservoir): 500.89 MW - Producible Electricity/Unit Area (reservoir): 9.11 MW/km**2 - Producible Electricity/Unit Volume (reservoir): 36.43 MW/km**3 + Specific Enthalpy (fluid): 166.00 kJ/kg + Recovery Factor (reservoir): 13.90 % + Available Heat (reservoir): 1.15e+15 kJ + Producible Heat (reservoir): 7.61e+14 kJ + Producible Heat/Unit Area (reservoir): 1.38e+13 kJ/km**2 + Producible Heat/Unit Volume (reservoir): 5.54e+13 kJ/km**3 + Producible Electricity (reservoir): 585.09 MW + Producible Electricity/Unit Area (reservoir): 10.64 MW/km**2 + Producible Electricity/Unit Volume (reservoir): 42.55 MW/km**3