TNO Intern

Commit 7a3b264a authored by Hen Brett's avatar Hen Brett 🐔
Browse files

Trying some speedups, the well distance optimizer appears to be where it is slowed down

parent 2ebb5e9c
Loading
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -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(
@@ -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:
@@ -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(
@@ -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 = (
@@ -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

@@ -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,
+2 −2
Original line number Diff line number Diff line
@@ -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,
@@ -113,7 +113,7 @@ def calc_lifetime(
    return Eseg / Eflowseg



@njit
def get_along_hole_length(
    true_vertical_depth: float,
    well_distance: float,
+2 −2
Original line number Diff line number Diff line
@@ -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
@@ -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,
@@ -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,
+0 −1
Original line number Diff line number Diff line
@@ -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
+16 −23
Original line number Diff line number Diff line
@@ -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:
@@ -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:
@@ -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