TNO Intern

Commit faea72c8 authored by Hen Brett's avatar Hen Brett 🐔
Browse files

Merge remote-tracking branch 'origin/59-experiment-with-some-speedups' into...

Merge remote-tracking branch 'origin/59-experiment-with-some-speedups' into 59-experiment-with-some-speedups
parents 13019534 7a3c0da1
Loading
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
stages:
  - test
  - deploy

Run tests:
  stage: test
  tags:
    - docker
  image: ghcr.io/prefix-dev/pixi:latest
  allow_failure: false
  script:
    - export TZ=Europe/Amsterdam
    - ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
    - apt-get update
    - apt-get install -y build-essential gcc tk openjdk-17-jdk
    - export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
    - export PATH=$JAVA_HOME/bin:$PATH
    - export THERMOGIS_JAR=$CI_PROJECT_DIR/resources/thermogis_jar/thermogis-1.7.0-shaded.jar
    - pixi install
    - pixi run pytest -rx tests/
    - rm -rf /var/lib/apt/lists/*
  only:
    - main
    - merge_requests

pages:
  stage: deploy
  image: python:latest
+12 −3
Original line number Diff line number Diff line
# pyThermoGIS

**pyThermoGIS** is a Python package that provides API access to the [ThermoGIS](https://www.thermogis.nl/en) doublet simulations and economic calculations,  ThermoGIS is developed and maintained by the [Geological Survey of the Netherlands](https://www.geologischedienst.nl/en/) which is part of [TNO](https://www.tno.nl/en/), additionally, pythermogis was also partially developed by and for the [GoForward](https://go-forward-project.eu/) project.
**pyThermoGIS** is a Python package that provides API access to the [ThermoGIS](https://www.thermogis.nl/en) doublet simulations and economic calculations,  ThermoGIS is developed and maintained by the [Geological Survey of the Netherlands](https://www.geologischedienst.nl/en/) which is part of [TNO](https://www.tno.nl/en/).


<div style="display: flex; gap: 10px;">
@@ -8,11 +8,20 @@
  <img src="../images/GeologischeDienstlogo.png" alt="Image 1" style="width: 100%; max-width: 600px; height: auto;">
</div>
<div style="display: flex; gap: 10px;">
  <img src="../images/TNOLogo.jpg" alt="Image 1" style="width: 25%; max-width: 600px; height: auto;">
  <img src="images/GO-Forward-gros_transparent.png" style="width: 90%; max-width: 600px; height: auto;">
  <img src="../images/TNOLogo.jpg" alt="Image 1" style="width: 50%; max-width: 600px; height: auto;">
</div>

pythermogis is currently used by the following research programs:

<div style="display: flex; gap: 10px;">
  <img src="images/GO-Forward-gros_transparent.png" style="width: 50%; max-width: 600px; height: auto;">
</div>
<div style="display: flex; gap: 10px;">
  <img src="images/leapre.jpg" alt="Image 1" style="width: 50%; max-width: 600px; height: auto;">
</div>

1. [GoForward](https://go-forward-project.eu/) 
2. [Geothermal Atlas for Africa](https://geothermalatlasforafrica.org/) (which is a part of the [LEAP-RE](https://www.leap-re.eu/) project).


# Usage
+27 −28
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ def simulate_doublet(output_data: xr.Dataset, reservoir_properties: xr.Dataset,
                                        input_core_dims=[[], [], [], [], [], [], [], [],[]],
                                        output_core_dims=[[], [], [], [], [], [], [], [], [], [], [], [], [], []],
                                        vectorize=True,
                                        dask="parallelized")
                                        )

    # Assign output DataArrays to the output_data object
    output_data["power"] = output_data_arrays[0]
@@ -41,8 +41,7 @@ def simulate_doublet(output_data: xr.Dataset, reservoir_properties: xr.Dataset,
    return output_data


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) -> float:
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) -> float:
    """
    Calculate the performance of a doublet at a single location.

@@ -93,11 +92,12 @@ def calculate_performance_of_single_location(mask: float, depth: float, thicknes
    if not np.isnan(mask):
        return 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

    # Instantiate ThermoGIS doublet
    doublet = instantiate_thermogis_doublet(utc_properties, rng_seed)
    set_doublet_parameters(doublet, transmissivity_with_ntg, depth, porosity, ntg, temperature, utc_properties)

    # The Java routine which calculates DoubletPerformance, for more detail on the simulation inspect the Java source code
    doublet.calculateDoubletPerformance(-9999.0, thickness, transmissivity)
    doublet.calculateDoubletPerformance(-9999.0, thickness, transmissivity, False)

    if doublet.getUtcPeurctkWh() == -9999.0:  # If calculation was not successful, return all 0.0
        return 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
@@ -108,24 +108,24 @@ def calculate_performance_of_single_location(mask: float, depth: float, thicknes
    else:
        utc_cut = utc_properties.utcCutoff()

    hprod = doublet.economicalData.getDiscountedHeatProducedP()
    npv = 1e-6 * (utc_cut - doublet.getUtcPeurctkWh()) * 3.6 * hprod * (1 - doublet.economicalData.getTaxRate())
    hprod = doublet.getDiscountedHeatProducedP()
    npv = 1e-6 * (utc_cut - doublet.getUtcPeurctkWh()) * 3.6 * hprod * (1 - utc_properties.taxRate())

    # get values from doublet
    output_values = {"power": doublet.doubletCalc1DData.getHpP(),
                     "heat_pump_power": doublet.doubletCalc1DData.getHpPHeatPump(),
                     "capex": doublet.economicalData.getSumcapex(),
                     "opex": doublet.economicalData.getOpexFirstProdYear(),
    output_values = {"power": doublet.getHpP(),
                     "heat_pump_power": doublet.getHeatPowerPerDoublet(),
                     "capex": doublet.getSumcapex(),
                     "opex": doublet.getOpexFirstProdYear(),
                     "utc": doublet.getUtcPeurctkWh(),
                     "npv": npv,
                     "hprod": hprod,
                     "cop": doublet.doubletCalc1DData.getCop(),
                     "cophp": doublet.doubletCalc1DData.getCopHpP(),
                     "pres": doublet.doubletCalc1DData.getPresP() / 1e5,
                     "flow_rate": doublet.doubletCalc1DData.getFlowrate(),
                     "welld": doublet.doubletCalc1DData.getWellDistP(),
                     "inj_temp": doublet.doubletCalc1DData.getInjectionTemp(),
                     "prd_temp": doublet.doubletCalc1DData.getProductionTemp()
                     "cop": doublet.getCop(),
                     "cophp": doublet.getCopHpP(),
                     "pres": doublet.getPresP() / 1e5,
                     "flow_rate": doublet.getFlowrate(),
                     "welld": doublet.getWellDistP(),
                     "inj_temp": doublet.getInjectionTemp(),
                     "prd_temp": doublet.getProductionTemp()
                     }

    # Reset doublet variables for next calculation
@@ -166,9 +166,8 @@ def instantiate_thermogis_doublet(utc_properties, rng_seed: int = None) -> JClas
    doublet = ThermoGISDoublet(Mockito.mock(Logger), rng, utc_properties)

    # Set parameters that do not change across simulations
    doublet.doubletCalc1DData.setSurfaceTemperature(utc_properties.surfaceTemperature())
    doublet.doubletCalc1DData.setUseHeatPump(utc_properties.useHeatPump())
    doublet.doubletCalc1DData.setDhReturnTemp(utc_properties.dhReturnTemp())
    doublet.setSurfaceTemperature(utc_properties.surfaceTemperature())
    doublet.setDhReturnTemp(utc_properties.dhReturnTemp())

    return doublet

@@ -201,15 +200,15 @@ def set_doublet_parameters(doublet, transmissivity_with_ntg: float, depth: float
    if not utc_properties.useStimulation() or transmissivity_with_ntg > utc_properties.stimKhMax():
        doublet.setNoStimulation()

    doublet.doubletCalc1DData.setDepth(depth)
    doublet.doubletCalc1DData.setPorosity(porosity)
    doublet.doubletCalc1DData.setNtg(ntg)
    doublet.doubletCalc1DData.setReservoirTemp(temperature)
    doublet.setDepth(depth)
    doublet.setPorosity(porosity)
    doublet.setNtg(ntg)
    doublet.setReservoirTemp(temperature)

    if utc_properties.useHeatPump():
        if utc_properties.calculateCop() and not utc_properties.hpApplicationMode():
            doublet.doubletCalc1DData.setInjectionTemp(doublet.calculateInjectionTempWithHeatPump(temperature, utc_properties.hpDirectHeatInputTemp()))
            doublet.setInjectionTemp(doublet.calculateInjectionTempWithHeatPump(temperature, utc_properties.hpDirectHeatInputTemp()))
        else:
            doublet.doubletCalc1DData.setInjectionTemp(np.max([temperature - utc_properties.maxCoolingTempRange(), utc_properties.hpMinimumInjectionTemperature()]))
            doublet.setInjectionTemp(np.max([temperature - utc_properties.maxCoolingTempRange(), utc_properties.hpMinimumInjectionTemperature()]))
    else:
        doublet.doubletCalc1DData.setInjectionTemp(np.max([temperature - utc_properties.maxCoolingTempRange(), utc_properties.dhReturnTemp()]))
        doublet.setInjectionTemp(np.max([temperature - utc_properties.maxCoolingTempRange(), utc_properties.dhReturnTemp()]))
+25 −0
Original line number Diff line number Diff line
from pathlib import Path
import typing as t
import xml.etree.ElementTree as ET
from jpype import JClass

@@ -37,3 +38,27 @@ def instantiate_utc_properties_builder() -> JClass:
    """
    start_jvm()
    return JClass("thermogis.properties.builders.UTCPropertiesBuilder")()

def get_viscosity_mode(mode: t.Literal["kestin", "batzlewang"]) -> JClass:
    """
    Map a string to the Java ViscosityMode enum.

    Parameters
    ----------
    mode : Literal["kestin", "batzlewang"]
        The viscosity mode to select.

    Returns
    -------
    viscosity_mode_enum : jpype.JClass
        The corresponding Java enum instance.
    """
    start_jvm()
    viscosity_mode = JClass("tno.geoenergy.ViscosityMode")

    if mode == "kestin":
        return viscosity_mode.KESTIN
    elif mode == "batzlewang":
        return viscosity_mode.BATZLEWANG
    else:
        raise ValueError(f"Unknown viscosity mode: {mode}")
 No newline at end of file
Loading