Loading src/pythermogis/workflow/utc/doublet.py +9 −2 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ class DoubletOutput: production_temp: float injection_temp: float def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) -> DoubletOutput | None: def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput, verbose: bool = False) -> DoubletOutput | None: timer = timeit.default_timer() # determine initial well distance well_distance = ( (props.optim_dist_well_dist_min + props.optim_dist_well_dist_max) / 2 Loading @@ -56,6 +57,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) else props.default_well_distance ) # determine injection temperature if props.use_heat_pump: injection_temperature = calculate_injection_temp_with_heat_pump( input.temperature, Loading @@ -68,6 +70,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) else: injection_temperature = max(input.temperature - props.max_cooling_temp_range, props.dh_return_temp) timer = print_time(timer, "injection temperature: ", verbose=verbose) # calculate maximum pressure drawdown_pressure = calculate_max_pressure( Loading @@ -80,6 +83,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) if drawdown_pressure == 0: return None timer = print_time(timer, "maximum pressure: ", verbose=verbose) # cooling temperature and well distance optimization if props.optim_well_dist: Loading @@ -95,6 +99,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) well_distance, injection_temperature, ) timer = print_time(timer, "cooling temperature: ", verbose=verbose) if props.optim_well_dist: well_distance = optimize_well_distance( Loading @@ -103,6 +108,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) drawdown_pressure, injection_temperature, ) timer = print_time(timer, "well distance optimizer: ", verbose=verbose) # stimulation capex stimulation_capex = ( Loading @@ -120,7 +126,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) injection_temp=injection_temperature, stimulation_capex=stimulation_capex, ) timer = print_time(timer, "pressure optimizer: ", verbose=verbose) if pressure_results is None: return None Loading Loading @@ -181,6 +187,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) * (1 - props.tax_rate) ) opex_first_prod_year = total_opex_ts[props.drilling_time] timer = print_time(timer, "economics: ", verbose=verbose) return DoubletOutput( power=heat_power_per_doublet, Loading src/pythermogis/workflow/utc/doublet_utils.py +2 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ def get_cop_carnot(eta: float, Tout: float, Tin: float) -> float: return eta * (Tcond + TKELVIN) / (Tcond - Tevap) @njit def calc_lifetime( well_distance: float, thickness: float, Loading Loading @@ -113,7 +113,7 @@ def calc_lifetime( return Eseg / Eflowseg @njit def get_along_hole_length( true_vertical_depth: float, well_distance: float, Loading src/pythermogis/workflow/utc/doubletcalc.py +2 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from pydoubletcalc import Aquifer, Doublet, Well, WellPipeSegment from pythermogis.workflow.utc.water import get_salinity from pythermogis.workflow.utc.rock import get_geothermal_gradient from utils.timer import print_time from numba import njit INCH_SI = 0.0254 @dataclass Loading @@ -25,7 +25,6 @@ def doubletcalc( well_distance: float, injection_temp: float, ) -> Doublet1DResults: timer = timeit.default_timer() aquifer = Aquifer( permeability=input.permeability, porosity=input.porosity, Loading Loading @@ -131,6 +130,7 @@ def get_total_skin_production(props, input): def get_pump_production_depth(props, depth: float) -> float: return min(props.pump_depth, depth / 2) @njit def get_along_hole_length( true_vertical_depth: float, well_distance: float, Loading src/pythermogis/workflow/utc/flow.py +0 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ def calculate_volumetric_flow( ): STEPS = [0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6] BAR_SI = 1e5 # Units.BAR_SI hp_cop = 0.0 hp_added_power = 0.0 hp_elec_consumption = 0.0 Loading src/pythermogis/workflow/utc/pressure.py +16 −23 Original line number Diff line number Diff line Loading @@ -18,10 +18,10 @@ def calculate_max_pressure( else: max_pres = input_data.depth * (0.135 - props.hy_gradient) * 100000 pres = min(props.max_pump * 1e5, max_pres) pressure = min(props.max_pump * 1e5, max_pres) results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is None: Loading @@ -29,45 +29,45 @@ def calculate_max_pressure( iter_count = 0 pres_min = 1e5 pres_max = pres pres_max = pressure while iter_count < 1000 and abs(pres_max - pres_min) > pres_tol: iter_count += 1 pres = 0.5 * (pres_min + pres_max) pressure = 0.5 * (pres_min + pres_max) results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is not None: pres_min = pres pres_min = pressure else: pres_max = pres pres_max = pressure if results is None: pres -= pres_tol pressure -= pres_tol results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is None or iter_count >= 1000: return 0.0 return pres return pressure if results.heat_power_per_doublet < 0 and not props.is_ates: pres /= 2.0 pressure /= 2.0 results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results.heatPowerPerDoublet() < 0: return 0.0 else: pres *= 2.0 pressure *= 2.0 return pres return pressure @dataclass class PressureOptimizerResults: Loading Loading @@ -192,16 +192,9 @@ def optimize_pressure( return None hp_added_power = flow_results.hp_added_power if hp_added_power > 0: hp_elec_consumption = hp_added_power / (flow_results.hp_cop - 1.0) else: hp_elec_consumption = 0.0 cop = ( (flow_results.heat_power_per_doublet + hp_elec_consumption) / (flow_results.heat_power_per_doublet / flow_results.cop + hp_elec_consumption) (flow_results.heat_power_per_doublet + flow_results.hp_elec_consumption) / (flow_results.heat_power_per_doublet / flow_results.cop + flow_results.hp_elec_consumption) ) econ = calculate_economics( Loading Loading
src/pythermogis/workflow/utc/doublet.py +9 −2 Original line number Diff line number Diff line Loading @@ -48,7 +48,8 @@ class DoubletOutput: production_temp: float injection_temp: float def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) -> DoubletOutput | None: def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput, verbose: bool = False) -> DoubletOutput | None: timer = timeit.default_timer() # determine initial well distance well_distance = ( (props.optim_dist_well_dist_min + props.optim_dist_well_dist_max) / 2 Loading @@ -56,6 +57,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) else props.default_well_distance ) # determine injection temperature if props.use_heat_pump: injection_temperature = calculate_injection_temp_with_heat_pump( input.temperature, Loading @@ -68,6 +70,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) else: injection_temperature = max(input.temperature - props.max_cooling_temp_range, props.dh_return_temp) timer = print_time(timer, "injection temperature: ", verbose=verbose) # calculate maximum pressure drawdown_pressure = calculate_max_pressure( Loading @@ -80,6 +83,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) if drawdown_pressure == 0: return None timer = print_time(timer, "maximum pressure: ", verbose=verbose) # cooling temperature and well distance optimization if props.optim_well_dist: Loading @@ -95,6 +99,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) well_distance, injection_temperature, ) timer = print_time(timer, "cooling temperature: ", verbose=verbose) if props.optim_well_dist: well_distance = optimize_well_distance( Loading @@ -103,6 +108,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) drawdown_pressure, injection_temperature, ) timer = print_time(timer, "well distance optimizer: ", verbose=verbose) # stimulation capex stimulation_capex = ( Loading @@ -120,7 +126,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) injection_temp=injection_temperature, stimulation_capex=stimulation_capex, ) timer = print_time(timer, "pressure optimizer: ", verbose=verbose) if pressure_results is None: return None Loading Loading @@ -181,6 +187,7 @@ def calculate_doublet_performance(props: UTCConfiguration, input: DoubletInput) * (1 - props.tax_rate) ) opex_first_prod_year = total_opex_ts[props.drilling_time] timer = print_time(timer, "economics: ", verbose=verbose) return DoubletOutput( power=heat_power_per_doublet, Loading
src/pythermogis/workflow/utc/doublet_utils.py +2 −2 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ def get_cop_carnot(eta: float, Tout: float, Tin: float) -> float: return eta * (Tcond + TKELVIN) / (Tcond - Tevap) @njit def calc_lifetime( well_distance: float, thickness: float, Loading Loading @@ -113,7 +113,7 @@ def calc_lifetime( return Eseg / Eflowseg @njit def get_along_hole_length( true_vertical_depth: float, well_distance: float, Loading
src/pythermogis/workflow/utc/doubletcalc.py +2 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from pydoubletcalc import Aquifer, Doublet, Well, WellPipeSegment from pythermogis.workflow.utc.water import get_salinity from pythermogis.workflow.utc.rock import get_geothermal_gradient from utils.timer import print_time from numba import njit INCH_SI = 0.0254 @dataclass Loading @@ -25,7 +25,6 @@ def doubletcalc( well_distance: float, injection_temp: float, ) -> Doublet1DResults: timer = timeit.default_timer() aquifer = Aquifer( permeability=input.permeability, porosity=input.porosity, Loading Loading @@ -131,6 +130,7 @@ def get_total_skin_production(props, input): def get_pump_production_depth(props, depth: float) -> float: return min(props.pump_depth, depth / 2) @njit def get_along_hole_length( true_vertical_depth: float, well_distance: float, Loading
src/pythermogis/workflow/utc/flow.py +0 −1 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ def calculate_volumetric_flow( ): STEPS = [0, 1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6] BAR_SI = 1e5 # Units.BAR_SI hp_cop = 0.0 hp_added_power = 0.0 hp_elec_consumption = 0.0 Loading
src/pythermogis/workflow/utc/pressure.py +16 −23 Original line number Diff line number Diff line Loading @@ -18,10 +18,10 @@ def calculate_max_pressure( else: max_pres = input_data.depth * (0.135 - props.hy_gradient) * 100000 pres = min(props.max_pump * 1e5, max_pres) pressure = min(props.max_pump * 1e5, max_pres) results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is None: Loading @@ -29,45 +29,45 @@ def calculate_max_pressure( iter_count = 0 pres_min = 1e5 pres_max = pres pres_max = pressure while iter_count < 1000 and abs(pres_max - pres_min) > pres_tol: iter_count += 1 pres = 0.5 * (pres_min + pres_max) pressure = 0.5 * (pres_min + pres_max) results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is not None: pres_min = pres pres_min = pressure else: pres_max = pres pres_max = pressure if results is None: pres -= pres_tol pressure -= pres_tol results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results is None or iter_count >= 1000: return 0.0 return pres return pressure if results.heat_power_per_doublet < 0 and not props.is_ates: pres /= 2.0 pressure /= 2.0 results = calculate_volumetric_flow( props, input_data, pres, well_distance, injection_temp props, input_data, pressure, well_distance, injection_temp ) if results.heatPowerPerDoublet() < 0: return 0.0 else: pres *= 2.0 pressure *= 2.0 return pres return pressure @dataclass class PressureOptimizerResults: Loading Loading @@ -192,16 +192,9 @@ def optimize_pressure( return None hp_added_power = flow_results.hp_added_power if hp_added_power > 0: hp_elec_consumption = hp_added_power / (flow_results.hp_cop - 1.0) else: hp_elec_consumption = 0.0 cop = ( (flow_results.heat_power_per_doublet + hp_elec_consumption) / (flow_results.heat_power_per_doublet / flow_results.cop + hp_elec_consumption) (flow_results.heat_power_per_doublet + flow_results.hp_elec_consumption) / (flow_results.heat_power_per_doublet / flow_results.cop + flow_results.hp_elec_consumption) ) econ = calculate_economics( Loading