carm.simulation package

Submodules

carm.simulation.solver module

Time-stepping orchestrator for the BHE simulation.

Assembles all physical inputs, initializes the FLS model and boundary conditions, and runs the simulation via run(). Supports parallel (independent boreholes) and series (fluid outlet of one borehole feeds the next) configurations.

class carm.simulation.solver.Simulation[source]

Bases: object

Time-stepping orchestrator for the BHE simulation.

Assembles all physical inputs, initializes the FLS model and boundary conditions, and runs the simulation via run(). Supports parallel (independent boreholes) and series (fluid outlet of one borehole feeds the next) configurations.

model

Full physical model of the BHE system.

Type:

PhysicalModel

envprops

Static radiative and thermal properties of the external environment.

Type:

EnvironmentalProperties

envinput

Time series of external air temperature and solar irradiance.

Type:

EnvironmentalTimeSeries

timesteps

Duration of each time step [s].

Type:

float

n_steps

Total number of simulation time steps.

Type:

int

mw_tot

Mass flow rate time series, shape (n_bhes, n_steps) or (n_groups, n_steps) in series mode [kg/s].

Type:

NDArray[np.float64]

Tf1

Inlet fluid temperature time series, shape (n_bhes, n_steps) or (n_groups, n_steps) [°C]. When mw is 0 this value must be set as NaN.

Example

>>> Tf1_5 = np.full((1, 100), 4, dtype = np.float64)
>>> Tf1_null = np.full((1, 200), np.nan, dtype = np.float64)
>>> Tf1 = np.concatenate((Tf1_5, Tf1_null), axis = 1)
Type:

NDArray[np.float64]

heat_flux_mode

Building-side load, supply temperature, and heat pump performance curves. When set, Tf1 must be None: the inlet fluid temperature is solved for internally each timestep instead of being prescribed. None by default (Tf1-driven mode).

Type:

HeatFluxMode or None

fls_mode

FLS simulation mode. Accepts 'sqrt' or 'continuous'. The first is less expensive; the latter is more accurate.

Type:

str

groups

Series groups mapping group index to ordered list of borehole indices. Required for series mode, None in parallel mode.

Type:

dict or None

fls_cache_dir

Folder where the FLS thermal responses are saved and reused. None (default) keeps them in memory and saves nothing. When set, any later simulation of the same borefield (same geometry, ground properties and time step) reuses the saved file instead of recomputing it. See FiniteLineSolution.

Type:

str, Path or None

fls_image

True (default) adds the FLS image part. The BHE top is buried at D = ground_geom.L_sup. False uses the real part only. See FiniteLineSolution.

Type:

bool

env

Assembled external environment, built at construction time.

Type:

ExternalEnvironment

T_sup_kusuda

Kusuda-Achenbach temperature profile for upper ground layers, shape (n_steps, m_mesh_sup + 1) [°C].

Type:

NDArray[np.float64]

T_middle_kusuda

Kusuda-Achenbach temperature profile for middle ground and borehole layers, shape (n_steps, m_mesh * (n_mesh + n_equations)) [°C].

Type:

NDArray[np.float64]

T_inf_kusuda

Kusuda-Achenbach temperature profile for lower ground layers, shape (n_steps, m_mesh_inf) [°C].

Type:

NDArray[np.float64]

T_bc

Far-field boundary condition array, shape (n_steps, n_bhes, m_mesh) [°C].

Type:

NDArray[np.float64]

T_history

Output temperature history, shape (n_steps + 1, n_bhes, n_dof) [°C]. float64 in RAM, or a float32 np.memmap of a .npy file when run is given history_path.

Type:

NDArray[np.float64]

history_path

File backing T_history in the last run, None when in RAM.

Type:

Path or None

fls

FLS thermal interference model. None in single-borehole mode.

Type:

FiniteLineSolution or None

gr_p_varprops

Soil moisture module for ground thermophysical properties. Instantiated only if envinput.water_input is not None.

Type:

SoilMoisture or None

bh_p_varprops

Soil moisture module for borehole thermophysical properties. Instantiated only if envinput.water_input is not None.

Type:

SoilMoisture or None

k_ground_history

Thermal conductivity history for the ground, shape (n_steps, n_bhes) [W/(m K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

cp_ground_history

Volumetric heat capacity history for the ground, shape (n_steps, n_bhes) [J/(m³ K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

rho_ground_history

Density history for the ground, shape (n_steps, n_bhes) [kg/m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

k_borehole_history

Thermal conductivity history for the borehole, shape (n_steps, n_bhes) [W/(m K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

cp_borehole_history

Volumetric heat capacity history for the borehole, shape (n_steps, n_bhes) [J/(m³ K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

rho_borehole_history

Density history for the borehole, shape (n_steps, n_bhes) [kg/m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

wc_history_ground

Residual water volume history for the ground, shape (n_steps, n_bhes) [m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

wc_history_borehole

Residual water volume history for the borehole, shape (n_steps, n_bhes) [m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

model: PhysicalModel
envprops: EnvironmentalProperties
envinput: EnvironmentalTimeSeries
timesteps: float
n_steps: int
mw_tot: ndarray[tuple[Any, ...], dtype[float64]]
Tf1: ndarray[tuple[Any, ...], dtype[float64]] | None = None
heat_flux_mode: HeatFluxMode | None = None
fls_mode: str = 'sqrt'
groups: Dict | None = None
fls_cache_dir: str | Path | None = None
fls_image: bool = True
T_sup_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
T_middle_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
T_inf_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
env: ExternalEnvironment
T_bc: ndarray[tuple[Any, ...], dtype[float64]]
T_history: ndarray[tuple[Any, ...], dtype[float64]]
fls: FiniteLineSolution | None = None
history_path: Path | None = None
property heat_flux: bool
run(parallel=None, series=None, save_results=False, history_path=None)[source]

Run the simulation in parallel or series mode.

Dispatches to _run_parallel() or _run_series() based on the provided flags. For single-borehole configurations, parallel and series must both be None.

Parameters:
  • parallel (bool or None) – Set to True to run in parallel mode (independent boreholes).

  • series (bool or None) – Set to True to run in series mode (fluid outlet chaining).

  • save_results (bool) – If True, write a timestamped .npz archive of the results to a results/ directory (created if needed) in the current working directory. False by default: the caller decides whether and where to persist T_history and the other arrays. See examples/ for how to save results manually.

  • history_path (str, Path or None) – None (default) keeps T_history in RAM. When set, T_history is written step by step to a .npy file at this path, so runs larger than the available RAM can complete. Values are stored as float32; the calculation itself is unchanged. Read it back with np.load(history_path, mmap_mode="r").

Returns:

Temperature history array of shape (n_steps + 1, n_bhes, n_dof), a float32 np.memmap when history_path is set.

Return type:

NDArray[np.float64]

Raises:
  • ValueError – If both or neither flags are set, or if series groups are not defined.

  • MemoryError – Before the first step, if T_history (float64, held in RAM when history_path is None) is larger than the available memory (psutil.virtual_memory().available). The FLS increments are already allocated when run starts, so they are already out of the available memory. The message names the sizes and suggests history_path=, and fls_cache_dir= when the increments are held in RAM.

Examples

>>> T_hist = sim.run(parallel=True)
>>> T_hist.shape
(n_steps + 1, n_bhes, n_dof)

carm.simulation.heat_flux_mode module

Heat-flux-mode configuration for the BHE simulation.

Groups the building-side load, supply temperature, and heat pump performance curves needed to drive Simulation from a building thermal load instead of a prescribed inlet fluid temperature.

class carm.simulation.heat_flux_mode.HeatFluxMode[source]

Bases: object

Building load and heat pump settings for heat flux mode.

Q_buildings

Building thermal load per time step, shape (n_steps,) [W]. Positive for heating, negative for cooling, zero when the heat pump is off.

Type:

NDArray[np.float64]

T_supply

Supply temperature to the building per time step, shape (n_steps,) [°C].

Type:

NDArray[np.float64]

cop_curve

Heat pump COP as a function of the temperature lift T_supply - T_f,out [-]. Defaults to Ruhnau et al. (2019).

Type:

Callable[[float], float]

eer_curve

Heat pump EER as a function of the temperature lift T_f,out - T_supply [-]. Defaults to Ruhnau et al. (2019).

Type:

Callable[[float], float]

Q_buildings: ndarray[tuple[Any, ...], dtype[float64]]
T_supply: ndarray[tuple[Any, ...], dtype[float64]]
cop_curve: Callable[[float], float]
eer_curve: Callable[[float], float]

Module contents

class carm.simulation.Simulation[source]

Bases: object

Time-stepping orchestrator for the BHE simulation.

Assembles all physical inputs, initializes the FLS model and boundary conditions, and runs the simulation via run(). Supports parallel (independent boreholes) and series (fluid outlet of one borehole feeds the next) configurations.

model

Full physical model of the BHE system.

Type:

PhysicalModel

envprops

Static radiative and thermal properties of the external environment.

Type:

EnvironmentalProperties

envinput

Time series of external air temperature and solar irradiance.

Type:

EnvironmentalTimeSeries

timesteps

Duration of each time step [s].

Type:

float

n_steps

Total number of simulation time steps.

Type:

int

mw_tot

Mass flow rate time series, shape (n_bhes, n_steps) or (n_groups, n_steps) in series mode [kg/s].

Type:

NDArray[np.float64]

Tf1

Inlet fluid temperature time series, shape (n_bhes, n_steps) or (n_groups, n_steps) [°C]. When mw is 0 this value must be set as NaN.

Example

>>> Tf1_5 = np.full((1, 100), 4, dtype = np.float64)
>>> Tf1_null = np.full((1, 200), np.nan, dtype = np.float64)
>>> Tf1 = np.concatenate((Tf1_5, Tf1_null), axis = 1)
Type:

NDArray[np.float64]

heat_flux_mode

Building-side load, supply temperature, and heat pump performance curves. When set, Tf1 must be None: the inlet fluid temperature is solved for internally each timestep instead of being prescribed. None by default (Tf1-driven mode).

Type:

HeatFluxMode or None

fls_mode

FLS simulation mode. Accepts 'sqrt' or 'continuous'. The first is less expensive; the latter is more accurate.

Type:

str

groups

Series groups mapping group index to ordered list of borehole indices. Required for series mode, None in parallel mode.

Type:

dict or None

fls_cache_dir

Folder where the FLS thermal responses are saved and reused. None (default) keeps them in memory and saves nothing. When set, any later simulation of the same borefield (same geometry, ground properties and time step) reuses the saved file instead of recomputing it. See FiniteLineSolution.

Type:

str, Path or None

fls_image

True (default) adds the FLS image part. The BHE top is buried at D = ground_geom.L_sup. False uses the real part only. See FiniteLineSolution.

Type:

bool

env

Assembled external environment, built at construction time.

Type:

ExternalEnvironment

T_sup_kusuda

Kusuda-Achenbach temperature profile for upper ground layers, shape (n_steps, m_mesh_sup + 1) [°C].

Type:

NDArray[np.float64]

T_middle_kusuda

Kusuda-Achenbach temperature profile for middle ground and borehole layers, shape (n_steps, m_mesh * (n_mesh + n_equations)) [°C].

Type:

NDArray[np.float64]

T_inf_kusuda

Kusuda-Achenbach temperature profile for lower ground layers, shape (n_steps, m_mesh_inf) [°C].

Type:

NDArray[np.float64]

T_bc

Far-field boundary condition array, shape (n_steps, n_bhes, m_mesh) [°C].

Type:

NDArray[np.float64]

T_history

Output temperature history, shape (n_steps + 1, n_bhes, n_dof) [°C]. float64 in RAM, or a float32 np.memmap of a .npy file when run is given history_path.

Type:

NDArray[np.float64]

history_path

File backing T_history in the last run, None when in RAM.

Type:

Path or None

fls

FLS thermal interference model. None in single-borehole mode.

Type:

FiniteLineSolution or None

gr_p_varprops

Soil moisture module for ground thermophysical properties. Instantiated only if envinput.water_input is not None.

Type:

SoilMoisture or None

bh_p_varprops

Soil moisture module for borehole thermophysical properties. Instantiated only if envinput.water_input is not None.

Type:

SoilMoisture or None

k_ground_history

Thermal conductivity history for the ground, shape (n_steps, n_bhes) [W/(m K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

cp_ground_history

Volumetric heat capacity history for the ground, shape (n_steps, n_bhes) [J/(m³ K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

rho_ground_history

Density history for the ground, shape (n_steps, n_bhes) [kg/m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

k_borehole_history

Thermal conductivity history for the borehole, shape (n_steps, n_bhes) [W/(m K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

cp_borehole_history

Volumetric heat capacity history for the borehole, shape (n_steps, n_bhes) [J/(m³ K)]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

rho_borehole_history

Density history for the borehole, shape (n_steps, n_bhes) [kg/m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

wc_history_ground

Residual water volume history for the ground, shape (n_steps, n_bhes) [m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

wc_history_borehole

Residual water volume history for the borehole, shape (n_steps, n_bhes) [m³]. Available only if envinput.water_input is not None.

Type:

NDArray[np.float64]

model: PhysicalModel
envprops: EnvironmentalProperties
envinput: EnvironmentalTimeSeries
timesteps: float
n_steps: int
mw_tot: ndarray[tuple[Any, ...], dtype[float64]]
Tf1: ndarray[tuple[Any, ...], dtype[float64]] | None = None
heat_flux_mode: HeatFluxMode | None = None
fls_mode: str = 'sqrt'
groups: Dict | None = None
fls_cache_dir: str | Path | None = None
fls_image: bool = True
T_sup_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
T_middle_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
T_inf_kusuda: ndarray[tuple[Any, ...], dtype[float64]]
env: ExternalEnvironment
T_bc: ndarray[tuple[Any, ...], dtype[float64]]
T_history: ndarray[tuple[Any, ...], dtype[float64]]
fls: FiniteLineSolution | None = None
history_path: Path | None = None
property heat_flux: bool
run(parallel=None, series=None, save_results=False, history_path=None)[source]

Run the simulation in parallel or series mode.

Dispatches to _run_parallel() or _run_series() based on the provided flags. For single-borehole configurations, parallel and series must both be None.

Parameters:
  • parallel (bool or None) – Set to True to run in parallel mode (independent boreholes).

  • series (bool or None) – Set to True to run in series mode (fluid outlet chaining).

  • save_results (bool) – If True, write a timestamped .npz archive of the results to a results/ directory (created if needed) in the current working directory. False by default: the caller decides whether and where to persist T_history and the other arrays. See examples/ for how to save results manually.

  • history_path (str, Path or None) – None (default) keeps T_history in RAM. When set, T_history is written step by step to a .npy file at this path, so runs larger than the available RAM can complete. Values are stored as float32; the calculation itself is unchanged. Read it back with np.load(history_path, mmap_mode="r").

Returns:

Temperature history array of shape (n_steps + 1, n_bhes, n_dof), a float32 np.memmap when history_path is set.

Return type:

NDArray[np.float64]

Raises:
  • ValueError – If both or neither flags are set, or if series groups are not defined.

  • MemoryError – Before the first step, if T_history (float64, held in RAM when history_path is None) is larger than the available memory (psutil.virtual_memory().available). The FLS increments are already allocated when run starts, so they are already out of the available memory. The message names the sizes and suggests history_path=, and fls_cache_dir= when the increments are held in RAM.

Examples

>>> T_hist = sim.run(parallel=True)
>>> T_hist.shape
(n_steps + 1, n_bhes, n_dof)
class carm.simulation.HeatFluxMode[source]

Bases: object

Building load and heat pump settings for heat flux mode.

Q_buildings

Building thermal load per time step, shape (n_steps,) [W]. Positive for heating, negative for cooling, zero when the heat pump is off.

Type:

NDArray[np.float64]

T_supply

Supply temperature to the building per time step, shape (n_steps,) [°C].

Type:

NDArray[np.float64]

cop_curve

Heat pump COP as a function of the temperature lift T_supply - T_f,out [-]. Defaults to Ruhnau et al. (2019).

Type:

Callable[[float], float]

eer_curve

Heat pump EER as a function of the temperature lift T_f,out - T_supply [-]. Defaults to Ruhnau et al. (2019).

Type:

Callable[[float], float]

Q_buildings: ndarray[tuple[Any, ...], dtype[float64]]
T_supply: ndarray[tuple[Any, ...], dtype[float64]]
cop_curve: Callable[[float], float]
eer_curve: Callable[[float], float]