Skip to content

API Reference

calculate_performance_of_single_location(mask, depth, thickness, porosity, ntg, temperature, transmissivity, transmissivity_with_ntg, rng_seed, utc_properties=None, mask_value=0.0)

Calculate the performance of a doublet at a single location.

Parameters:

Name Type Description Default
utc_properties dict

Dictionary containing UTC (Underground Thermal Capacity) properties.

None
mask float

Mask value; if not NaN, all output values will be set to mask_value.

required
depth float

Depth of the aquifer in meters.

required
thickness float

Thickness of the aquifer in meters.

required
porosity float

Porosity of the aquifer (fraction).

required
ntg float

Net-to-gross ratio of the aquifer (fraction).

required
temperature float

Temperature of the aquifer in degrees Celsius.

required
transmissivity float

Transmissivity of the aquifer.

required
transmissivity_with_ntg float

Product of transmissivity and net-to-gross.

required
mask_value float

0.0 by default, Any cell that results in a failed simulation or corresponds to a non-nan value in the mask parameter will be assigned the mask value

0.0

Returns:

Name Type Description
power float geothermal power [MW]
heat_pump_power float power after heat pump [MW]
capex float Capital expenditure [M€]
opex float for first production year [M€]
utc float unit technical costs/levelized cost of geothermal heat [€/kWh]
npv float (net-present-value) [M€]
hprod float total energy production for firstyear [kWh]
cop float system cop [-]
cophp float heat pump cop[-]
pres float for driving loop [bar]
flow_rate float[m3 / h]
welld float[m]
inj_temp float[C]
prd_temp float[C]
Source code in src/pythermogis/thermogis_classes/doublet.py
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
def calculate_performance_of_single_location(mask: float, depth: float, thickness: float, porosity: float, ntg: float, temperature: float, transmissivity: float, transmissivity_with_ntg: float, rng_seed: int, utc_properties: JClass = None, mask_value: float = 0.0) -> float:
    """
    Calculate the performance of a doublet at a single location.

    Parameters
    ----------
    utc_properties : dict
        Dictionary containing UTC (Underground Thermal Capacity) properties.
    mask : float
        Mask value; if not NaN, all output values will be set to mask_value.
    depth : float
        Depth of the aquifer in meters.
    thickness : float
        Thickness of the aquifer in meters.
    porosity : float
        Porosity of the aquifer (fraction).
    ntg : float
        Net-to-gross ratio of the aquifer (fraction).
    temperature : float
        Temperature of the aquifer in degrees Celsius.
    transmissivity : float
        Transmissivity of the aquifer.
    transmissivity_with_ntg : float
        Product of transmissivity and net-to-gross.
    mask_value : float
        0.0 by default, Any cell that results in a failed simulation or corresponds to a
        non-nan value in the mask parameter will be assigned the mask value

    Returns
    -------
    power: float  geothermal power [MW]
    heat_pump_power: float  power after heat pump [MW]
    capex: float Capital expenditure  [M€]
    opex: float for first production year [M€]
    utc: float unit technical costs/levelized cost of geothermal heat [€/kWh]
    npv: float (net-present-value) [M€]
    hprod: float total energy production for firstyear [kWh]
    cop: float  system cop [-]
    cophp: float  heat pump cop[-]
    pres: float for driving loop [bar]
    flow_rate: float [m3/h]
    welld: float [m]
    inj_temp: float [C]
    prd_temp: float [C]
    """
    if not validate_input(depth, ntg, porosity, temperature, thickness, transmissivity,
                   transmissivity_with_ntg):
        return (np.nan,) * 14

    if not np.isnan(mask) or temperature < utc_properties.minProdTemp():
        return (mask_value,) * 14

    # Instantiate ThermoGIS doublet
    doublet = instantiate_thermogis_doublet(utc_properties, rng_seed)

    DoubletInput = JClass("thermogis.calc.utc.doublet.records.DoubletInput")
    input = DoubletInput(
            -9999.0, # unknowninput
            thickness,
            transmissivity,
            transmissivity_with_ntg,
            ntg,
            depth,
            porosity,
            temperature,
            None, # ates input
        )

    # The Java routine which calculates DoubletPerformance, for more detail on the simulation inspect the Java source code
    try:
        results = doublet.calculateDoubletPerformance(input)
    except:
        return (mask_value,) * 14

    # If calculation was not successful, return mask value
    if results is None or results.utc() == -9999.0:
        return (mask_value,) * 14

    # calculate net-present-value using the utc-cutoffs
    if depth > utc_properties.utcDeepDepth():
        utc_cut = utc_properties.utcCutoffDeep()
    else:
        utc_cut = utc_properties.utcCutoff()

    hprod = results.hprod()
    npv = 1e-6 * (utc_cut - results.utc()) * 3.6 * hprod * (1 - utc_properties.taxRate())

    # get values from doublet
    output_values = {"power": results.power(),
                     "heat_pump_power": results.hppower(),
                     "capex": results.capex(),
                     "opex": results.opex(),
                     "utc": results.utc(),
                     "npv": npv,
                     "hprod": hprod,
                     "cop": results.cop(),
                     "cophp": results.cophp(),
                     "pres": results.pres(),
                     "flow_rate": results.flow(),
                     "welld": results.welld(),
                     "inj_temp": results.injectionTemp(),
                     "prd_temp": results.productionTemp(),
                     }

    # Reset doublet variables for next calculation
    return output_values["power"], output_values["heat_pump_power"], output_values["capex"], output_values["opex"], output_values["utc"], output_values["npv"], output_values["hprod"], output_values["cop"], output_values[
        "cophp"], output_values["pres"], output_values["flow_rate"], output_values["welld"], output_values["inj_temp"], output_values["prd_temp"]

instantiate_thermogis_doublet(utc_properties, rng_seed=None)

Instantiate a ThermoGIS Doublet class, setting necessary parameters from utc_properties and optionally using a specified random seed.

Parameters:

Name Type Description Default
utc_properties UTCProperties

Instance containing the input parameters required for the doublet simulation.

required
rng_seed int

Optional random seed for reproducibility.

None

Returns:

Name Type Description
doublet object

A JPype-instantiated object of the ThermoGISDoublet class.

Source code in src/pythermogis/thermogis_classes/doublet.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
def instantiate_thermogis_doublet(utc_properties, rng_seed: int = None) -> JClass:
    """
    Instantiate a ThermoGIS Doublet class, setting necessary parameters from utc_properties and optionally using a specified random seed.

    Parameters
    ----------
    utc_properties : UTCProperties
        Instance containing the input parameters required for the doublet simulation.
    rng_seed : int
        Optional random seed for reproducibility.

    Returns
    -------
    doublet : object
        A JPype-instantiated object of the ThermoGISDoublet class.
    """

    # Instantiate doublet class
    Logger = JClass("logging.Logger")
    Mockito = JClass("org.mockito.Mockito")
    RNG = JClass("tno.geoenergy.stochastic.RandomNumberGenerator")
    ThermoGISDoublet = JClass("thermogis.calc.utc.doublet.ThermoGisDoublet")

    # Create an instance of a ThermoGISDoublet
    if rng_seed is not None:
        rng = RNG(rng_seed)
    else:
        rng = RNG()

    doublet = ThermoGISDoublet(Mockito.mock(Logger), rng, utc_properties)

    return doublet

validate_input(depth, ntg, porosity, temperature, thickness, transmissivity, transmissivity_with_ntg)

Check that none of the input is nan

Source code in src/pythermogis/thermogis_classes/doublet.py
162
163
164
165
166
167
168
169
170
171
172
173
def validate_input(depth: float,
    ntg: float,
    porosity: float,
    temperature: float,
    thickness: float,
    transmissivity: float,
    transmissivity_with_ntg: float,
) -> bool:
    """
    Check that none of the input is nan
    """
    return not np.any(np.isnan([depth, ntg, porosity, temperature, thickness, transmissivity, transmissivity_with_ntg]))