Performing a BHE Simulation Using Geoloop
The configuration of a simulation is defined through JSON input files (*.json), organized in a json directory
(e.g. /examples/simple_simulation).
One Geoloop simulation uses different modules from various packages, depending on the configuration defined in the main input JSON file.
This main input JSON file defines the physical and operational design of the simulated Borehole Heat Exchanger (BHE) system,
and may include links to additional input JSON files for:
- Configuration of a borehole field simulation
- Configuration for a stochastic simulation
- Configuration of an optimization simulation
- Configuration of depth-dependent subsurface thermal properties
- Configuration of a power load time-profile
- Configuration of a flow rate time-profile
The following sections provide a nomenclature for the input for the different simulation types and modules, including model configuration conditions and options.
Configuration Files and Path Resolution
This section explains how configuration files are interpreted by Geoloop, how relative paths are resolved, how nested configuration files behave, and which model-specific validation rules apply. Understanding these rules is essential when writing configuration JSON files for single runs, batch runs, and stochastic simulations.
General Rules for All Configurations
All configuration models (LithologyConfig, LoadProfileConfig,
FlowDataConfig, SingleRunConfig, PlotInputConfig) follow the same core
pattern:
-
Every loaded config JSON is assigned a
config_file_path, pointing to the absolute path of the file that defined it. -
Any relative path in the configuration is always interpreted relative to the folder containing that configuration file.
-
Output directories are created automatically if they do not exist.
-
Certain models have type-dependent rules (e.g. borehole type, model type), and validation errors are raised if required fields are missing.
How Path Resolution Works
When a configuration file at:
contains:
Geoloop resolves these as:
input_dir→/path/to/config/input/out_dir→/path/to/config/output/
If a linked path is already absolute, it is left unchanged.
Any directory that corresponds to an output location is created if missing.
Linked Configuration JSONs
A main configuration file can reference sub-configs like:
When running a simulation, those paths are resolved relative to the main configuration file.
Best Practices When Creating Config Files
- Always provide paths relative to the config file’s directory.
- Keep related configs (lithology, heat load profile, flow rate profile) in the same folder.
- Avoid absolute paths for portability.
- For batch simulations, place all configs in one structured directory.
- Remember: paths inside nested configs are resolved using their own file location, not the main config.
Configuration of a Single BHE Simulation
The main input JSON file is directly used for a deterministic simulation by the SingleRunSim module or the
single-run command in the CLI (see Geoloop Interface).
For an example of a simple deterministic model simulation, see the example of a simple model simulation.
The main input JSON file includes the following parameters:
| Parameter | Description | Unit | Type | Remark |
|---|---|---|---|---|
| base_dir | Path to output folder | — | string | Creates folder if it does not exist |
| type | Type of BHE design | — | string | Options: UTUBE or COAXIAL for model_type ANALYTICAL and PYG and PYGFIELD; UTUBE for model_type FINVOL |
| H | Borehole length | m | scalar | — |
| D | Buried depth of the BHE | m | scalar | — |
| borefield | Path to configuration file for borehole field design | — | string | Optional; only used for model_type PYGFIELD |
| r_b | Borehole radius | m | scalar | — |
| pos | Positions of pipes in borehole | — | nested_list | [x;y]* coordinates of pipes; first position(s) are of inlet pipe(s); required if type is UTUBE, falls back to default of [[0,0][0,0]] if type is COAXIAL |
| r_out | Outer pipe radius | m | list | First position(s) are of inlet pipe(s), Radii must be the same for inlet and outlet pipes respectively. |
| r_in | Inner pipe radius | m | list | Only used if SDR is not provided. First position(s) are of inlet pipe(s), Radii must be the same for inlet and outlet pipes respectively. |
| SDR | SDR value of the pipes | — | scalar | Only used if r_in is not provided. Determines pipe thickness through: thickness = (r_out*2) / SDR. |
| k_p | Pipe thermal conductivity | W/mK | scalar | — |
| nInlets | Number of inlet pipes | — | scalar | Required if type is UTUBE, falls back to default of 1 if type is COAXIAL |
| insu_dr | Fraction of pipe thickness with insulating material | — | scalar | Range: 0–1 |
| insu_k | Thermal conductivity of insulating material | W/mK | scalar | — |
| insu_z | Maximum depth of insulating material | m | scalar | — |
| k_g | Grout thermal conductivity | W/mK | scalar or list | — |
| z_k_g | End depths of k_g values | m | list | Used only if k_g is a list |
| epsilon | Pipe surface roughness | m | scalar | — |
| fluid_str | Type of fluid mixed with water | — | string | Must be supported by pygfunction media module |
| fluid_percent | Fluid percentage | % | scalar | — |
| m_flow | Total flow rate | kg/s | scalar | The total flow into the system is is equally divided between the sets of inlet and outlet pipes, with a negative value for the outlet flow. Used if dploopcrit and flow_data are not defined. |
| litho_k_param | Path to lithology module configuration file | — | string | Optional |
| Tg | (Sub)surface temperature | °C | scalar or list | Represents surface temperature if scalar |
| Tgrad | Subsurface temperature gradient | °C/100m | scalar | Used only if Tg is scalar |
| z_Tg | End depths of Tg values | m | list | Used only if Tg is a list |
| k_s | Subsurface thermal conductivity | W/mK | scalar or list | Used only if litho_k_param is not defined |
| z_k_s | End depths of k_s values | m | list | Used only if k_s is a list and litho_k_param is not defined |
| k_s_scale | Scaling factor for subsurface thermal conductivity | — | scalar | Scales k_s values over depth |
| alfa | Subsurface thermal diffusivity | m²/s | scalar | — |
| model_type | Type of model used in simulation | — | string | Options: ANALYTICAL; FINVOL; PYG; PYGFIELD |
| run_type | Starting point for performance calculation | — | string | Options: POWER or TIN (depends on model_type) |
| nyear | Number of simulated years | year | scalar | — |
| nled | Number of hours per simulated timestep | hour | scalar | — |
| nsegments | Number of model segments over depth | — | scalar | — |
| nr | Number of grid cells in radial direction | — | scalar | Required only if model_type is FINVOL |
| r_sim | Maximum simulation radius | m | scalar | Required only if model_type is FINVOL |
| dploopcrit | Pumping power | bar | scalar | — |
| dooptimize | Enable optimization | — | boolean | true or false |
| copcrit | Minimum COP of circulation pump | — | scalar | Used only if dooptimize is true |
| optimize_keys | Parameters to optimize | — | list | Only variable parameters supported |
| optimize_keys_bounds | Bounds for optimized parameters | — | nested_list | [[lower, upper]] matching optimize_keys |
| loadprofile | Path to configuration file of the heat load profile | — | string | Optional |
| flow_data | Path to configuration file of the flow rate profile | - | string | Optional |
| Q | Power demand | W | scalar | Used if run_type is POWER and no loadprofile defined; positive for heat production, negative for cold production |
| Tin | Inlet temperature | °C | scalar | Used if run_type is TIN |
| variables_config | Path to stochastic simulation configuration file | — | string | Used for stochastic runs (RunMain module) |
| save_Tfield_res | Flag to save results of 3D temperature field in a numarical simulation | — | boolean | Only used if model_type is FINVOL |
The pos parameter includes:
| Parameter | Unit | Description |
|---|---|---|
| x | m | Position along x-axis |
| y | m | Position along y-axis |
To maintain a constant borehole wall temperature for each depth slice (UBWT boundary condition, see Theory),
inlet and outlet pipes in a multi-U-tube configuration should alternate and be radially symmetric.
By default, Geoloop uses a fixed surface temperature with a linear subsurface thermal gradient, as defined by scalar values for the input parameters Tg and Tgrad in the main input JSON.
However, a pre-defined temperature–depth profile can be used in the simulations, by assigning:
- a
listof temperature values toTg - a corresponding
listof depth values toz_Tg.
These parameters should be defined similarly in the configuration JSON of the lithology module, if used (see below).
For an example simulation using a temperature–depth profile, see a BHE in the city of Roermond
base_diris the main output folder for the simulation. It is resolved relative to the directory where the main configuration JSON is located. When an absolute path is provided, it is unchanged.
Extra Configuration of a Borehole Field
For simulating a field of boreholes, define a separate JSON file for the borehole field design. A field of boreholes can
only be simulated when using the standard functionality of pygfunction (when model_type is PYGFIELD)
This file is linked in the main JSON under borefield and includes:
| Parameter | Description | Unit | Type | Remark |
|---|---|---|---|---|
| field_N | Total number of boreholes | — | int | — |
| field_M | Boreholes per side of the field | — | int | Only equally sided fields supported |
| field_R | Distance between boreholes | m | int | Distance between boreholes. If field_M is 0, defines radius of circular field |
| field_segments | Number of depth segments | — | int | More segments = smoother curved trajectory |
| field_inclination_start | Start inclination angle | ° | int | Applied to all boreholes |
| field_inclination_end | End inclination angle | ° | int | Applied to all boreholes |
If the start and end inclinations differ, boreholes will have a curved shape.
For examples see:
- Square field → BHE field in the Middle East
- Circular curved field → BHE field in Madrid
Values in
borefieldoverride or supply missing values. This is different for a linked configuration JSON of, for example, the Loadprofile module, which uses a nested dictionary.
Configuration of a Stochastic and/or Optimization Simulation
For a stochastic simulation, the main input JSON is used by the RunMain module in the stochastic-run command in the CLI
(see Geoloop Interface). For an example of a simple stochastic simulation see simple model simulation.
A separate JSON defines parameters for Monte Carlo sampling, linked under variables_config:
| Parameter | Description | Unit | Type |
|---|---|---|---|
| n_samples | Number of samples | — | scalar |
| variable parameter | [sampling mode; arg1; arg2] |
— | list[string, scalar, scalar] |
Multiple variable parameters can be defined simultaneously and the user can choose different sampling distributions.
Supported parameters include:
- k_s_scale
- k_p
- insu_z
- insu_dr
- insu_k
- m_flow
- Tin
- H
- epsilon
- alfa
- Tgrad
- Q
- fluid_percent
Supported sampling distributions and their corresponding arguments for the configuration JSON are:
| Sampling Mode | arg1 | arg2 |
|---|---|---|
| Normal | mean | standard deviation |
| Uniform | minimum | maximum |
| Lognormal | μ | σ |
| Triangular | minimum | peak |
The main input JSON file for a Geoloop simulation already includes several
arguments that define the preferences for an optimization simulation,
including sampling type and value range for parameter iteration.
However, in case of using the optimization algorithm for optimization of
the BHE design and/or operational conditions, the sampling type and
value range for parameter iteration should also be defined in the
same input JSON file as is used for a stochastic simulation, under
variables_config.
Geoloop supports optimization of the same parameters as listed above for options to vary in stochastic model runs. For an example of a simple optimization simulation, see the example for Optimization of a coaxial BHE
The coaxial BHE design circulates fluid downwards in the outer pipe and upwards in the inner pipe. Optimization of the pipe radius for this design is only supported for the inner pipe.
Simulation results
After a simulation is finished, most input parameters and the results are stored in a HDF5 (.h5) file. The file contains a subset of parameters that includes (most of) the input parameters of the main input JSON file, and results that follow from the model calculations.
The table below defines the parameters in the results subset and describes its structure. For stochastic simulations, the first dimension of the parameters in the results subset is always the number of samples.
| Parameter | Description | Unit | Dimensions | Remark |
|---|---|---|---|---|
| Q_b | Heat load | W | time | Only calculated for run_type TIN |
| Re_in | Reynolds nr. in the inlet pipe(s) | time | ||
| Re_out | Reynolds nr. in the outlet pipe(s) | time | ||
| T_b | Borehole wall temperature | C | time; zseg | |
| T_bave | Depth-average borehole wall temperature | C | time | |
| T_f | Fluid temperature | C | time; z; nPipes | |
| T_fi | Inlet temperature | C | time | Only calculated for run_type POWER |
| T_fo | Outlet temperature | C | time | |
| Tg | (Sub)surface temperature | C | time or time; zseg | |
| dploop | Pumping pressure | bar | time | |
| flowrate | Flowrate | kg/s | time | Total flow rate |
| hours | Simulation timesteps | hours | time | |
| k_g | Grout thermal conductivity | W/mK | time or time; zseg | |
| k_s | Subsurface thermal conductivity | W/mK | time or time; zseg | |
| qloop | Consumed power by the fluid circulation pump | W | time | |
| qsign | Sign of heat flow | time | Sign indicates heat extraction (positive) or injection (negative) | |
| qzb | Subsurface heat flow | W | time; zseg | |
| nPipes | Number of pipes | Coördinates for the nPipes dimension | ||
| time | Simulation timesteps | hours | Coördinates for the time dimension | |
| z | Depth for top and bottom of simulation depth segments | m | Coördinates for the depth dimension | |
| zseg | Depth for middle of simulation depth segments | m | Coördinates for the depth-segment dimension |
In addition to the database file, a plot is generated from a cross-section of the borehole design. Both are stored according to the following convention:
📁 /jsondir/base_dir/casename/ — HDF5 database file (.h5) with simulation inputs and results
🖼️ /jsondir/base_dir/casename/casename_bhdesign.png — Cross-section figure of the borehole design
The casename in the output files follows the pattern run_name + A/P/F + '_' + T/P, with:
| Symbol | Meaning |
|---|---|
run_name |
Name of the input JSON file used by the scripts SingleRunSim or RunMain |
A/P/F |
Semi-analytical (A) model from Geoloop, semi-analytical model from pygfunction (P), or Finite Volume model (F) |
T/P |
Main input condition type: T (temperature) or P (power/heat load) |
BHE simulations that use the numerical finite volume model, in case the save_Tfield_res was flagged to True,
also produce a separate HDF5 database file with the calculated subsurface temperature field in:
📁 /jsondir/base_dir/casename/casename_FINVOL_T.h5