TNO Intern

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

Merge branch '41-setup-docs-which-can-be-hosted-on-gitlab' into 'main'

Resolve "Setup docs which can be hosted on gitlab"

Closes #41

See merge request AGS/pythermogis!43
parents 1443ac7a 26dc7995
Loading
Loading
Loading
Loading

MANIFEST.in

deleted100644 → 0
+0 −1
Original line number Diff line number Diff line
recursive-include pythermogis/resources *
+0 −268
Original line number Diff line number Diff line
@@ -136,274 +136,6 @@ pixi run pytg simulate-doublet --depth 500 --temperature 150 --thickness 200 --n

## 2. Usage in your own python projects

### 🧪 Basic Example

```python
from src.pythermogis import calculate_doublet_performance
import xarray as xr

input_data = xr.Dataset({
    "thickness_mean": ((), 300),
    "thickness_sd": ((), 50),
    "ntg": ((), 0.5),
    "porosity": ((), 0.5),
    "depth": ((), 5000),
    "ln_permeability_mean": ((), 5),
    "ln_permeability_sd": ((), 0.5),
})

results = calculate_doublet_performance(input_data)
print(results)
```

---

### 🌍 2D Grid Example

```python
from src.pythermogis import calculate_doublet_performance
import xarray as xr
import numpy as np

input_data = xr.Dataset({
    "thickness_mean": (("x", "y"), np.array([[300, 300], [200, 200]])),
    "thickness_sd": (("x", "y"), np.array([[50, 50], [25, 25]])),
    "ntg": (("x", "y"), np.array([[0.5, 0.5], [0.25, 0.25]])),
    "porosity": (("x", "y"), np.array([[0.5, 0.5], [0.75, 0.7]])),
    "depth": (("x", "y"), np.array([[5000, 5000], [4500, 4500]])),
    "ln_permeability_mean": (("x", "y"), np.array([[5, 5], [4.5, 4.5]])),
    "ln_permeability_sd": (("x", "y"), np.array([[0.5, 0.5], [0.75, 0.75]])),
}, coords={"x": [0, 1], "y": [10, 20]})

results = calculate_doublet_performance(input_data)
print(results)
```

---

### 🗺️ Reading Raster Grids with pygridsio

```python
from src.pythermogis import calculate_doublet_performance
from pygridsio import read_grid

input_grids = read_grid("thickness.zmap").to_dataset(name="thickness_mean")
input_grids["thickness_sd"] = read_grid("thickness_sd.zmap")
input_grids["ntg"] = read_grid("ntg.zmap")
input_grids["porosity"] = read_grid("porosity.zmap")
input_grids["depth"] = read_grid("top_depth.zmap")
input_grids["mask"] = read_grid("hydrocarbons.zmap")
input_grids["ln_permeability_mean"] = read_grid("ln_perm.zmap")
input_grids["ln_permeability_sd"] = read_grid("ln_perm_sd.zmap")

results = calculate_doublet_performance(input_grids)
print(results)
```

### 🧰 Running Doublet simulations with custom simulation parameters
To adjust properties of the simulation, you can pass a `utc_properties` instance to the calculate_doublet_performance function.
A `utc_properties` instance is a JClass implementation of the Java UTCProperties class. It is generated by using the `utc_properties_builder`, upon which custom properties can be set, and used to build an instance of the `utc_properties`.

Be aware: that you will need access to the ThermoGIS java source code to fully understand what these properties do and not all properties are actually utilised in this python api (especially those which refer to paths to files).

Common properties to change include:
- `setUseHeatPump(Boolean)`: if true, include a heat-pump when modelling
- `setUseStimulation(Boolean)`: if true, apply reservoir stimulation when simulating a doublet
- `setSurfaceTemperature(float)`: The temperature of the surface
- `setTempGradient(float)`: The gradient at which temperature increases with depth, in C/km
- `setDhReturnTemp(float)`: The goal of the direct heat return temperature
- `setStimKhMax(float)`: The maximum transmissivity above which no stimulation will occur (if UseStimulation = True)

Here is an example, where the default utc_properties is used, but the UseHeatPump option is set to True. this is achievied by instantiating a `utc_properties_builder` class, running `.useHeatPump(True)` on that class, and then building the 
`utc_properties` themselves, with the `.build()` method of the `utc_properties_builder`.

```python
from src.pythermogis import calculate_doublet_performance, instantiate_utc_properties_builder
import xarray as xr

input_data = xr.Dataset({
    "thickness_mean": ((), 300),
    "thickness_sd": ((), 50),
    "ntg": ((), 0.5),
    "porosity": ((), 0.5),
    "depth": ((), 5000),
    "ln_permeability_mean": ((), 5),
    "ln_permeability_sd": ((), 0.5),
})

utc_properties = instantiate_utc_properties_builder().setUseHeatPump(True).build()
results = calculate_doublet_performance(input_data, utc_properties=utc_properties)
print(results)
```

### plotting the results of a pythermoigs simulation
It is expected that the user knows how to plot using matplotlib and xarrays, such that they can make plots of the inputs and outputs to suit their needs.
That being said, a plotting function is provided which will produce a plot of a results DataSet, provided it either:
 - has dimensions = ["p_value"] and processes more than 1 p_value
 - has dimensions = ["p_value", "x", "y"], in which case the results will be plotted as maps
Check out the definition of `plot_doublet_performance_results` for more details.

```python
from src.pythermogis import calculate_doublet_performance, instantiate_utc_properties_builder, plot_doublet_performance_results
import xarray as xr

input_data = xr.Dataset({
    "thickness_mean": ((), 300),
    "thickness_sd": ((), 50),
    "ntg": ((), 0.5),
    "porosity": ((), 0.5),
    "depth": ((), 5000),
    "ln_permeability_mean": ((), 5),
    "ln_permeability_sd": ((), 0.5),
})

utc_properties = instantiate_utc_properties_builder().setUseHeatPump(True).build()
results = calculate_doublet_performance(input_data, utc_properties=utc_properties)
plot_doublet_performance_results(results, outfile="path/to/outfile")

```



## ThermoGIS Scenario Configuration Files

If you have a valid configuration file, you can parse a utc_properties class using the method: `instantiate_utc_properties_from_xml`.
Examples of valid configuration files are found in `tests/resources/test_input/scenarios`.
The vast majority of the parameters in the xml are not used by this python API; but are required by the ThermoGIS java code, unfortunately they are still needed in the xml file to enable parsing.

The minimum parameters which are required in the XML file are:

| #   | Parameter Name                                                           |
|-----|--------------------------------------------------------------------------|
| 1   | input_data_directory                                                     |
| 2   | results_directory                                                        |
| 3   | comparison_directory                                                     |
| 4   | compare_results                                                          |
| 5   | output_maps_for_petrel                                                   |
| 6   | max_number_of_processors_for_calculations                               |
| 7   | copy_aquifer_files                                                       |
| 8   | validate_input_grids                                                     |
| 9   | validate_output_grids                                                    |
| 10  | aquifers_to_calculate                                                    |
| 11  | output_scenario_name                                                     |
| 12  | temperature_from_input_grids                                             |
| 13  | exclude_hydrocarbon_areas                                                |
| 14  | use_boundary_shapefile                                                   |
| 15  | output_grid_file_type___zmap___asc___nc_                                 |
| 16  | pvalues_to_calculate                                                     |
| 17  | temperature_voxet_file                                                   |
| 18  | surface_temperature                                                      |
| 19  | temp_gradient__surface_temp__below__also_used_                          |
| 20  | max_undefined_cells__of_surrounding_4__for_interp                        |
| 21  | xy_grid_size_factor_for_thickness_grid__integer_                         |
| 22  | remove_padding_from_input_grids                                          |
| 23  | use_heat_pump                                                            |
| 24  | heating_return_temperature                                               |
| 25  | rosim_settings_file__must_contain__aquifer__layer_                       |
| 26  | scale_factor_for_h_and_lnk_standard_deviations                          |
| 27  | calculate_cop                                                            |
| 28  | application_mode                                                         |
| 29  | goal_temperature                                                         |
| 30  | unit_technical_cost_cutoff                                               |
| 31  | unit_technical_cost_cutoff_deep                                          |
| 32  | depth_for_deep_unit_technical_cost_cutoff                                |
| 33  | calculate_mean_over_last_nyears_for_efficiency__energyin_and_energyout_ |
| 34  | rosim_simulation_time__constant_power_after_                             |
| 35  | maximum_depth_for_calculations                                           |
| 36  | ates_minimum_depth__speed_up_calculation_                                |
| 37  | ates_maximum_depth__speed_up_calculation_                                |
| 38  | minimum_production_temperature                                           |
| 39  | kh_cutoff__speed_up_calculation_                                         |
| 40  | stimulate_well_s_                                                        |
| 41  | maximum_kh_value_for_stimulation                                         |
| 42  | maximum_cooling_temperature_range                                        |
| 43  | _minimum__injection_temperature                                          |
| 44  | ates_charge_temperature                                                  |
| 45  | use_kestin_viscosity                                                     |
| 46  | economic_lifetime                                                        |
| 47  | ates_minimum_flow_rate__speed_up_calculation_                            |
| 48  | include__non_sde__electric_power_in_output                               |
| 49  | use_values_from_last_rosim_year_for_all_years                            |
| 50  | maximum_flow                                                             |
| 51  | ates_charge_temperature                                                  |
| 52  | ates_aquifer_anisotropy                                                  |
| 53  | ates_filter_fraction__of_aquifer_thickness_                              |
| 54  | salinity_at_surface__ppm_                                                |
| 55  | salinity_gradient__ppm_m_                                                |
| 56  | ates_injection_production_period__max_182_days_                          |
| 57  | ates_clogging_velocity                                                   |
| 58  | ates_membrane_filter_index                                               |
| 59  | ates_depth_multiplication_factor                                         |
| 60  | thermal_radius_factor                                                    |
| 61  | maximum_pump_pressure                                                    |
| 62  | minimum_pump_pressure                                                    |
| 63  | hydraulic_gradient_injection_water__sodm_max_inj_pres_                   |
| 64  | optimize_well_distance                                                   |
| 65  | minimum_well_distance                                                    |
| 66  | maximum_well_distance                                                    |
| 67  | lifetime                                                                 |
| 68  | max_tvd_stepout_factor                                                   |
| 69  | rock_heat_capacity                                                       |
| 70  | rock_density                                                             |
| 71  | allowed_temperature_drop_as_fraction_of_deltat                           |
| 72  | well_distance                                                            |
| 73  | pump_efficiency                                                          |
| 74  | pump_depth                                                               |
| 75  | calculation_segment_length                                               |
| 76  | casing_roughness                                                         |
| 77  | added_skin_injector__negative_increases_flow_                            |
| 78  | added_skin_producer__negative_increases_flow_                            |
| 79  | stimulation_capex__for_both_wells_                                       |
| 80  | calculate_cop                                                            |
| 81  | coefficient_of_performance                                               |
| 82  | heat_pump_capex                                                          |
| 83  | heat_pump_annual_opex                                                    |
| 84  | alternative_heating_price                                                |
| 85  | economic_lifetime                                                        |
| 86  | drilling_time                                                            |
| 87  | tax_rate                                                                 |
| 88  | interest_on_loan                                                         |
| 89  | inflation                                                                |
| 90  | required_return_on_equity                                                |
| 91  | debt_equity                                                              |
| 92  | tolerance_of_utc_increase___bar_                                         |
| 93  | annual_load_hours                                                        |
| 94  | annual_opex_base                                                         |
| 95  | annual_opex_per_unit_power                                               |
| 96  | opex_electricity_purchase_price_for_operations                           |
| 97  | annual_opex_per_unit_energy_produced                                     |
| 98  | annual_opex_based_on_capex                                               |
| 99  | well_costs_scaling                                                       |
| 100 | well_costs_base                                                          |
| 101 | well_costs_depth__along_hole__factor                                     |
| 102 | well_costs_depth_2__along_hole__factor                                   |
| 103 | capex_base_expenses__excl_wells_                                         |
| 104 | capex_variable_expenses__excl_wells_                                     |
| 105 | capex_contingency                                                        |
| 106 | well_trajectory_curvature_scaling_factor__0__vert_wells_                 |
| 107 | use_orc                                                                  |
| 108 | heat_conversion_efficiency                                               |
| 109 | parasitic_power_fraction_of_net_power                                    |
| 110 | base_temperature                                                         |

```python
from src.pythermogis import calculate_doublet_performance, instantiate_utc_properties_from_xml
import xarray as xr

input_data = xr.Dataset({
    "thickness_mean": ((), 300),
    "thickness_sd": ((), 50),
    "ntg": ((), 0.5),
    "porosity": ((), 0.5),
    "depth": ((), 5000),
    "ln_permeability_mean": ((), 5),
    "ln_permeability_sd": ((), 0.5),
})

utc_properties = instantiate_utc_properties_from_xml("path/to/valid/xml/file")
results = calculate_doublet_performance(input_data, utc_properties=utc_properties)
print(results)
```

---

+16 KiB
Loading image diff...

docs/index.md

0 → 100644
+47 −0
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. 

This package allows a user to simulate geothermal doublets providing the following parameters: 
    
- Top depth
- Thickness (mean & standard deviation)
- Porosity
- Permeability (mean & standard deviation)
- Temperature (Optional: if not provided, a temperature gradient will be used)


The code will simulate a Geothermal doublet, utilizing ThermoGIS with DoubletCalc1D as the engine to produce values of:

- power [Mega Watt Hour]
- heat pump power [Mega Watt Hour]
- capex (Capital expenditure) [Million €]
- opex (Operational expenditure) [€/kW]
- utc (Unit Technical Cost [€cent/kWH])
- npv (Net-present-value)
- hprod (Discounted Heat Produced)
- cop 
- cophp
- pressure 
- flow rate [m³/hr]
- well depth [m]

For details on how these parameters are calculated we refer users to the [Thermogis calculation webpage](https://www.thermogis.nl/en/calculation-model)

The simulations are conducted in Java, and this package uses [JPype](https://jpype.readthedocs.io/en/latest/userguide.html) to create a Python-Java binding.

It uses [xarray](https://docs.xarray.dev/en/stable/index.html) to handle input and output parameters, a User should inform themselves and learn the usage of the Xarray package.

This module can be combined with the [pygridsio](https://pypi.org/project/pygridsio/) package to read and process 2D raster data.

## What can this package *not* do?
This package provides a narrow access point to the doublet simulations and UTC economic calculations from ThermoGIS, it does not implement the following ThermoGIS processes/methodologies:

- Stacking of Aquifers
- Calculation of Potential maps
- Calculation of Resources
- Calculation of Overview maps
- HTO-ATES simulations
- Property Modelling
- Temperature Modelling
- Reading, and writing of grid files (Checkout [pygridsio](https://pypi.org/project/pygridsio/))
Loading