Simulation helpers¶
Per-step state, energy / exergy helpers, and the stdout summary tables emitted at the end of a dynamic run.
Per-step dynamic context¶
Shared dynamic simulation context and control helpers.
Provides reusable dataclasses and pure functions that form the
backbone of time-stepping heat-pump simulations. Extracted from
AirSourceHeatPumpBoiler so that GroundSourceHeatPumpBoiler
and future models can share the same infrastructure.
- class tmhp.dynamic_context.ControlState(is_on, Q_heat_source, dV_tank_w_in_ctrl, result=<factory>)[source]
Bases:
objectHeat-source control decisions for one timestep.
Model-agnostic container: any boiler model populates these fields in its Phase-A helper. Subsystem states are managed separately via
sub_states: dict[str, dict].- is_on
Whether the heat source is running.
- Type:
bool
- Q_heat_source
Net heat delivered to the tank from the heat source [W].
- Type:
float
- dV_tank_w_in_ctrl
Refill flow rate [m³/s].
None= always-full sentinel (inflow resolved inside residual).- Type:
float | None
- result
Full result dictionary from the model’s
_calc_state. Contents are model-specific.- Type:
dict
- Parameters:
is_on (
bool)Q_heat_source (
float)dV_tank_w_in_ctrl (
float|None)result (
dict)
-
is_on:
bool
-
Q_heat_source:
float
-
dV_tank_w_in_ctrl:
float|None
-
result:
dict
- __init__(is_on, Q_heat_source, dV_tank_w_in_ctrl, result=<factory>)
- Parameters:
is_on (
bool)Q_heat_source (
float)dV_tank_w_in_ctrl (
float|None)result (
dict)
- class tmhp.dynamic_context.StepContext(n, current_time_s, current_hour, hour_of_day, T0, T0_K, activation_flags, T_tank_w_K, tank_level, dV_mix_w_out, I_DN=0.0, I_dH=0.0, T_sup_w_K=288.15)[source]
Bases:
objectPer-timestep immutable context (time, environment, demand).
- n
Current step index.
- Type:
int
- current_time_s
Elapsed simulation time [s].
- Type:
float
- current_hour
Elapsed simulation time [h].
- Type:
float
- hour_of_day
Hour within the current day (0–24, repeating).
- Type:
float
- T0
Dead-state / outdoor-air temperature [°C].
- Type:
float
- T0_K
Dead-state temperature [K].
- Type:
float
- activation_flags
Per-subsystem schedule activation flags for this step. e.g.
{"stc": True}when the STC preheat window is active. An empty dict means no subsystem has a schedule constraint.- Type:
dict[str, bool]
- T_tank_w_K
Current tank water temperature [K].
- Type:
float
- tank_level
Fractional tank fill level (0–1).
- Type:
float
- dV_mix_w_out
Service water draw-off flow rate [m³/s].
- Type:
float
- I_DN
Direct-normal irradiance on collector plane [W/m²].
- Type:
float
- I_dH
Diffuse-horizontal irradiance [W/m²].
- Type:
float
- T_sup_w_K
Mains water supply temperature [K].
- Type:
float
- Parameters:
n (
int)current_time_s (
float)current_hour (
float)hour_of_day (
float)T0 (
float)T0_K (
float)activation_flags (
dict)T_tank_w_K (
float)tank_level (
float)dV_mix_w_out (
float)I_DN (
float)I_dH (
float)T_sup_w_K (
float)
-
n:
int
-
current_time_s:
float
-
current_hour:
float
-
hour_of_day:
float
-
T0:
float
-
T0_K:
float
-
activation_flags:
dict
-
T_tank_w_K:
float
-
tank_level:
float
-
dV_mix_w_out:
float
-
I_DN:
float= 0.0
-
I_dH:
float= 0.0
-
T_sup_w_K:
float= 288.15
- __init__(n, current_time_s, current_hour, hour_of_day, T0, T0_K, activation_flags, T_tank_w_K, tank_level, dV_mix_w_out, I_DN=0.0, I_dH=0.0, T_sup_w_K=288.15)
- Parameters:
n (
int)current_time_s (
float)current_hour (
float)hour_of_day (
float)T0 (
float)T0_K (
float)activation_flags (
dict)T_tank_w_K (
float)tank_level (
float)dV_mix_w_out (
float)I_DN (
float)I_dH (
float)T_sup_w_K (
float)
- class tmhp.dynamic_context.Subsystem(*args, **kwargs)[source]
Bases:
ProtocolPluggable subsystem interface.
Each subsystem computes its contribution for a single timestep and assembles result columns for the output DataFrame. New subsystems (PV, battery, …) implement this protocol and register with the boiler model.
- step(ctx, ctrl, dt, T_tank_w_in_K)[source]
Compute subsystem state for this timestep.
- Parameters:
ctx (StepContext) – Current-step immutable context.
ctrl (ControlState) – Heat-source control decisions.
dt (float) – Time-step size [s].
T_tank_w_in_K (float) – Mains water inlet temperature [K].
- Returns:
Must include at least the following keys:
'Q_contribution'(float) — net energy contribution to the tank [W].'E_subsystem'(float) — electrical power consumed [W].'T_tank_w_in_override_K'(float | None) — heated tank-inlet temperature [K] if the subsystem modifies the inlet (e.g. mains preheat);Noneif there is no modification.
- Return type:
dict
- assemble_results(ctx, ctrl, step_state, T_solved_K)[source]
Build result columns for DataFrame output.
- Parameters:
ctx (StepContext) – Current-step immutable context.
ctrl (ControlState) – HP control decisions.
step_state (dict) – Dict returned by
step().T_solved_K (float) – Solved tank temperature [K].
- Returns:
Keyed result entries for the output DataFrame.
- Return type:
dict
- calc_exergy(df, T0_K)[source]
Compute subsystem-level exergy items.
- Parameters:
df (
DataFrame)T0_K (
Series)
- Return type:
SubsystemExergy|None
- calc_performance(**kwargs)[source]
Calculate performance at a specific condition.
- Return type:
dict
- __init__(*args, **kwargs)
- class tmhp.dynamic_context.SubsystemExergy(columns, X_tot_add=0.0, X_in_tank_add=0.0, X_out_tank_add=0.0)[source]
Bases:
objectSubsystem-specific exergy calculation results.
Each subsystem’s
calc_exergy()returns this object so that the host boiler can merge subsystem columns into the result DataFrame and adjust system-level totals.- columns
Exergy columns to append (key = column name).
- Type:
dict[str, pd.Series]
- X_tot_add
Additive contribution to system total exergy input
X_tot [W](e.g. pump electricity).- Type:
pd.Series | float
- X_in_tank_add
Additive exergy entering the tank boundary (e.g. heated return water in
tank_circuit).- Type:
pd.Series | float
- X_out_tank_add
Additive exergy leaving the tank boundary (e.g. water drawn to STC in
tank_circuit).- Type:
pd.Series | float
- Parameters:
columns (
dict)X_tot_add (
object)X_in_tank_add (
object)X_out_tank_add (
object)
-
columns:
dict
-
X_tot_add:
object= 0.0
-
X_in_tank_add:
object= 0.0
-
X_out_tank_add:
object= 0.0
- __init__(columns, X_tot_add=0.0, X_in_tank_add=0.0, X_out_tank_add=0.0)
- Parameters:
columns (
dict)X_tot_add (
object)X_in_tank_add (
object)X_out_tank_add (
object)
- tmhp.dynamic_context.check_hp_schedule_active(hour, hp_on_schedule)[source]
Check whether current hour falls within HP operating schedule.
- Parameters:
hour (float) – Current time of day [h] (0.0–24.0).
hp_on_schedule (list of tuple) – List of
(start_hour, end_hour)operating windows.
- Return type:
bool
- tmhp.dynamic_context.determine_heat_source_on_off(T_tank_w_C, T_lower, T_upper, is_on_prev, hour_of_day, on_schedule)[source]
Hysteresis-based heat-source on/off decision.
- Parameters:
T_tank_w_C (float) – Current tank water temperature [°C].
T_lower (float) – Lower hysteresis bound [°C].
T_upper (float) – Upper hysteresis bound [°C].
is_on_prev (bool) – Heat-source state at the previous timestep.
hour_of_day (float) – Hour within the day (0–24).
on_schedule (list[tuple[float, float]]) – Active operating windows
(start_h, end_h).
- Returns:
Whether the heat source should run this timestep.
- Return type:
bool
- tmhp.dynamic_context.determine_tank_refill_flow(dt, tank_level, dV_tank_w_out, V_tank_full, tank_always_full, prevent_simultaneous_flow, tank_level_lower_bound, tank_level_upper_bound, dV_tank_w_in_refill, is_refilling)[source]
Determine refill flow rate from current level and operational mode.
Pure tank-level management: all subsystem-specific flow overrides (e.g. STC mains-preheat forced refill) are the responsibility of the scenario class via
_run_subsystems/ctrl.dV_tank_w_in_ctrl.- Parameters:
dt (float) – Time-step size [s].
tank_level (float) – Current fractional tank level (0–1).
dV_tank_w_out (float) – Current outflow rate [m³/s].
V_tank_full (float) – Tank full volume [m³].
tank_always_full (bool) – Whether the tank is forced to stay full.
prevent_simultaneous_flow (bool) – Exclusive-flow mode flag.
tank_level_lower_bound (float) – Level lower bound for refill trigger.
tank_level_upper_bound (float) – Level upper bound for refill cut-off.
dV_tank_w_in_refill (float) – Refill flow rate [m³/s].
is_refilling (bool) – Whether we are currently in a refill cycle.
- Returns:
(dV_tank_w_in, is_refilling).Nonemeans always-full sentinel (no PSF).- Return type:
tuple[float | None, bool]
- tmhp.dynamic_context.tank_mass_energy_residual(x, ctx, ctrl, dt, T_tank_w_in_K, T_sup_w_K, T_mix_w_out_K, C_tank, UA_tank, V_tank_full, subsystems, sub_states)[source]
Energy and mass balance residuals at T^{n+1}.
The 3-way mixing valve ratio α(T) makes the outflow a nonlinear function of T^{n+1}, requiring
fsolve.Subsystem energy contributions and tank-inlet temperature overrides are read from
sub_states.- Parameters:
x (list[float]) –
[T_next_K, level_next].ctx (StepContext) – Current-step immutable context.
ctrl (ControlState) – Current-step HP control decisions.
dt (float) – Time-step size [s].
T_tank_w_in_K (float) – Mains water inlet temperature [K].
T_sup_w_K (float) – Mains water supply temperature [K] (for mixing valve).
T_mix_w_out_K (float) – Target mixing-valve outlet temperature [K].
C_tank (float) – Tank thermal capacitance [J/K].
UA_tank (float) – Tank overall heat-loss coefficient [W/K].
V_tank_full (float) – Tank full volume [m³].
subsystems (dict[str, Subsystem]) – Registered subsystem instances.
sub_states (dict[str, dict]) – Per-subsystem state dicts from
step().
- Returns:
[r_energy, r_mass].- Return type:
list[float]
Energy & exergy helpers¶
Utility functions for energy, entropy, and exergy analysis.
This module contains helper functions organized into the following categories:
Friction and Flow Functions - darcy_friction_factor: Calculate Darcy friction factor - calc_Orifice_flow_coefficient: Calculate orifice flow coefficient - calc_boussinessq_mixing_flow: Calculate mixing flow based on Boussinesq approximation
Heat Transfer Functions - calc_h_vertical_plate: Natural convection heat transfer coefficient - calc_UA_tank_arr: Tank heat loss UA calculation - calc_lmtd_*: Log mean temperature difference calculations - calc_UA_from_dV_fan: Heat transfer coefficient from fan flow rate
Curve Fitting Functions - linear_function, quadratic_function, cubic_function, quartic_function
Exergy and Entropy Functions - generate_entropy_exergy_term: Calculate entropy and exergy terms - calc_exergy_flow: Calculate exergy flow rate due to material flow
G-function Calculations (Ground Source Heat Pumps) - f, chi, G_FLS: Helper functions for g-function calculation
TDMA Solver Functions - TDMA: Solve tri-diagonal matrix system - _add_loop_advection_terms: Add forced convection terms to TDMA coefficients
Heat Pump Cycle Functions - calculate_ASHP_*_COP: Air source heat pump COP calculations - calculate_GSHP_COP: Ground source heat pump COP calculation - calc_ref_state: Calculate refrigerant cycle states (with superheating/subcooling support) - find_ref_loop_optimal_operation: Find optimal operation point
Tank Functions - update_tank_temperature: Update tank temperature based on energy balance
Schedule Functions - _build_dhw_usage_ratio: Build schedule ratio array
Balance Printing Utilities - print_balance: Print energy/entropy/exergy balance
- tmhp.enex_functions.calc_HX_perf_for_target_heat(Q_ref_target, T_a_in_C=None, T_ref_sat_K=None, A_cross=None, UA_design=None, dV_fan_design=None, is_active=True, exponent=0.71, T_ou_a_in_C=None, T_ref_evap_sat_K=None, T_ref_cond_sat_l_K=None)[source]¶
Numerically solve for the air-side flow rate of an ε-NTU heat exchanger.
Given a target heat transfer duty, find the airflow that delivers it, accounting for the velocity dependence of UA via the Wang et al. (2000) fin-and-tube correlation (UA ∝ velocity^0.71).
- Parameters:
Q_ref_target (float) – Target heat transfer rate [W] (always positive).
T_a_in_C (float, optional) – Air-side inlet temperature [°C].
T_ref_sat_K (float, optional) – Refrigerant saturation temperature [K] on the constant-temperature side.
A_cross (float) – Heat-exchanger cross-sectional area [m²].
UA_design (float) – Design UA [W/K].
dV_fan_design (float) – Design fan volumetric flow rate [m³/s].
is_active (bool) – Active flag.
exponent (float) – UA scaling exponent (default: 0.71).
(optional) (# Legacy aliases)
T_ou_a_in_C (float, optional) – Backward-compat alias for
T_a_in_C.T_ref_evap_sat_K (float, optional) – Backward-compat alias for
T_ref_sat_K.T_ref_cond_sat_l_K (float, optional) – Unused; kept only to preserve the older function signature.
- Returns:
Dictionary with the following keys:
dV_fan— required air-side flow rate [m³/s]UA— overall heat-transfer coefficient at the solution point [W/K]T_a_mid_C— air temperature between the heat exchanger and the fan [°C]Q_air— heat-transfer rate at the operating point [W]epsilon— effectiveness at the operating point [–]converged— whether the solver converged
All numeric values are
np.nanwhenis_active=False.- Return type:
dict
- tmhp.enex_functions.calc_Orifice_flow_coefficient(D0, D1)[source]¶
Calculate the orifice flow coefficient based on diameters.
Flow configuration:
--------------- -> | D0 D1 -> -> | ---------------
- Parameters:
D0 (float) – Pipe diameter [m]
D1 (float) – Hole diameter [m]
- Returns:
C_d – Orifice flow coefficient (dimensionless)
- Return type:
float
Notes
This is a simplified calculation. A more complete implementation should be based on physical equations.
- tmhp.enex_functions.calc_boussinessq_mixing_flow(T_upper, T_lower, A, dz, C_d=0.1)[source]¶
Calculate mixing flow rate between two adjacent nodes based on Boussinesq approximation.
Mixing occurs only when the lower node temperature is higher than the upper node, creating a gravitationally unstable condition.
- Parameters:
T_upper (float) – Upper node temperature [K]
T_lower (float) – Lower node temperature [K]
A (float) – Tank cross-sectional area [m²]
dz (float) – Node height [m]
C_d (float, optional) – Flow coefficient (empirical constant), default 0.1
- Returns:
dV_mix – Volumetric flow rate exchanged between nodes [m3/s]
- Return type:
float
Notes
TODO: C_d value should be calculated based on physical equations.
- tmhp.enex_functions.calc_mixing_valve_flows(dV_mix_out, alp)[source]¶
Calculate volumetric flow rates at a 3-way mixing valve given a mixing ratio.
- Parameters:
dV_mix_out (float) – Total requested service/mixed flow rate [m³/s].
alp (float) – Hot water mixing ratio [0-1].
- Returns:
Dictionary containing generic mixing valve mass balances: - dV_hot_in: Flow rate drawn from the hot source [m³/s] - dV_cold_in: Flow rate drawn from the cold source [m³/s] - dV_mix_out: Total mixed flow rate [m³/s]
- Return type:
dict
- tmhp.enex_functions.calc_mixing_valve_temp(T_tank_w_K, T_tank_w_in_K, T_mix_w_out_K)[source]¶
Calculate 3-way mixing valve output temperature and mixing ratio.
Mixes hot tank water with cold mains water to achieve the target service temperature
T_mix_w_out_K.- Parameters:
T_tank_w_K (float) – Current tank water temperature [K].
T_tank_w_in_K (float) – Mains (cold) water supply temperature [K].
T_mix_w_out_K (float) – Target delivery temperature [K].
- Returns:
{'alp': float, 'T_mix_w_out': float, 'T_mix_w_out_K': float}-alp: hot-water fraction [0–1] -T_mix_w_out: actual service temperature [°C] -T_mix_w_out_K: actual service temperature [K]- Return type:
dict
- tmhp.enex_functions.calc_stc_performance(I_DN_stc, I_dH_stc, T_stc_w_in_K, T0_K, A_stc_pipe, alpha_stc, h_o_stc, h_r_stc, k_ins_stc, x_air_stc, x_ins_stc, dV_stc, E_pump, is_active=True)[source]¶
Compute the performance of a solar thermal collector (STC).
Adapted from the
SolarAssistedGasBoiler.system_updatelogic in the legacyenex_engine.py.- Parameters:
I_DN_stc (float) – Direct normal irradiance [W/m²].
I_dH_stc (float) – Diffuse horizontal irradiance [W/m²].
T_stc_w_in_K (float) – Inlet water temperature to the STC (equal to the tank temperature) [K].
T0_K (float) – Reference / ambient temperature [K].
A_stc_pipe (float) – STC pipe area [m²].
alpha_stc (float) – Absorptance [-].
h_o_stc (float) – Outer convective heat-transfer coefficient [W/m²K].
h_r_stc (float) – Air-gap radiative heat-transfer coefficient [W/m²K].
k_ins_stc (float) – Insulation thermal conductivity [W/mK].
x_air_stc (float) – Air-gap thickness [m].
x_ins_stc (float) – Insulation thickness [m].
dV_stc (float) – STC volumetric flow rate [m³/s].
E_pump (float) – Pump electrical input [W].
is_active (bool, optional) – Active flag (default: True). When
False, returns a dict filled withnp.nan(exceptT_stc_w_out_KandT_stc_w_in_K, which are set to the inlet temperature).
- Returns:
I_sol_stc— total incident irradiance [W/m²]Q_sol_stc— absorbed solar heat [W]Q_stc_w_in— inlet enthalpy flow relative toT0_K[W]Q_stc_w_out— outlet enthalpy flow relative toT0_K[W]ksi_stc— dimensionless efficiency parameter [-]T_stc_w_out_K— outlet water temperature [K]T_stc_w_final_K— outlet temperature including pump heat gain [K]T_stc_w_in_K— inlet water temperature (echoed back) [K]T_stc_K— mean absorber-plate temperature [K]Q_l_stc— absorber-plate heat loss [W]
- Return type:
dict
Notes
All variable names are suffixed with
_stcto mark them as STC-specific.Heat losses are reported as
Q_l_stc.Entropy and exergy quantities are intentionally not computed here; do them as a post-processing step on the result CSV if needed.
- tmhp.enex_functions.cubic_function(x, a, b, c, d)[source]¶
Cubic function: y = a*x³ + b*x² + c*x + d
- tmhp.enex_functions.print_balance(balance, decimal=2)[source]¶
Print energy, entropy, or exergy balance dictionary in a formatted way.
This function prints balance information for subsystems, categorizing entries into in, out, consumed, and generated categories.
- Parameters:
balance (dict) – Dictionary containing balance information for subsystems. Structure: {subsystem_name: {category: {symbol: value}}} Categories: ‘in’, ‘out’, ‘con’ (consumed), ‘gen’ (generated)
decimal (int, optional) – Number of decimal places for output (default: 2)
- Returns:
Only prints output
- Return type:
None
Example
>>> balance = { ... "hot water tank": { ... "in": {"E_heater": 5000.0}, ... "out": {"Q_w_tank": 4500.0, "Q_l_tank": 400.0}, ... "con": {"X_c_tank": 100.0} ... } ... } >>> print_balance(balance)
- tmhp.enex_functions.quartic_function(x, a, b, c, d, e)[source]¶
Quartic function: y = a*x⁴ + b*x³ + c*x² + d*x + e
- tmhp.enex_functions.update_tank_temperature(T_tank_w_K, Q_gain, UA_tank, T0_K, C_tank, dt)[source]¶
Update tank temperature using the Crank-Nicolson implicit scheme.
The governing ODE for a lumped-capacitance tank is:
C dT/dt = Q_gain - UA (T - T0)
Crank-Nicolson averages the loss term across both time levels:
T^{n+1} = [(C/dt - UA/2) T^n + Q_gain + UA T0] / (C/dt + UA/2)
This scheme is second-order accurate in time and unconditionally stable, eliminating the overshoot that Forward Euler can exhibit when dt is large relative to the thermal time constant C/UA.
- Parameters:
T_tank_w_K (float) – Current tank temperature [K].
Q_gain (float) – Total heat gain rate [W] (condenser, UV, STC, refill, etc.).
UA_tank (float) – Overall tank heat-loss coefficient [W/K].
T0_K (float) – Dead-state / ambient temperature [K].
C_tank (float) – Tank thermal capacitance [J/K] (= c_w * rho_w * V_tank * level).
dt (float) – Time step [s].
- Returns:
Updated tank temperature [K].
- Return type:
float
- tmhp.enex_functions.G_FLS(t, ks, as_, rb, H)[source]¶
Calculate the g-function for finite line source (FLS) model.
This function calculates the g-function used in ground source heat pump analysis. Results are cached for performance.
- Parameters:
t (float) – Time [s]
ks (float) – Ground thermal conductivity [W/mK]
as (float) – Ground thermal diffusivity [m²/s]
rb (float) – Borehole radius [m]
H (float) – Borehole height [m]
- Returns:
g-function value [mK/W]. Returns scalar for single time value, array for multiple time values.
- Return type:
float or array
- tmhp.enex_functions.air_dynamic_viscosity(T_K)[source]¶
Calculate air dynamic viscosity using Sutherland’s formula.
- Parameters:
T_K (float) – Temperature [K]
- Returns:
float – Dynamic viscosity [Pa·s]
Reference (Sutherland’s formula for air)
mu = mu0 * (T/T0)^1.5 * (T0 + S) / (T + S)
where mu0 = 1.716e-5 Pa·s at T0 = 273.15 K, S = 110.4 K
- tmhp.enex_functions.air_prandtl_number(T_K)[source]¶
Calculate air Prandtl number.
- Parameters:
T_K (float) – Temperature [K]
- Returns:
float – Prandtl number [-]
Note (Pr ≈ 0.71 for air at typical temperatures (20-50°C))
Temperature dependence is weak, so using constant value.
- tmhp.enex_functions.calc_ASHP_cooling_COP(T_a_int_out, T_a_ext_in, Q_r_int, Q_r_max, COP_ref)[source]¶
Calculate the Coefficient of Performance (COP) for an Air Source Heat Pump (ASHP) in cooling mode.
Reference: https://publications.ibpsa.org/proceedings/bs/2023/papers/bs2023_1118.pdf
- Parameters:
T_a_int_out (float) – Indoor air temperature [K]
T_a_ext_in (float) – Outdoor air temperature [K]
Q_r_int (float) – Indoor heat load [W]
Q_r_max (float) – Maximum cooling capacity [W]
COP_ref (float) – Reference COP at standard conditions
- Returns:
COP value
- Return type:
float
Note
COP is calculated based on: - PLR: Part Load Ratio - EIR: Energy input to cooling output ratio
- tmhp.enex_functions.calc_ASHP_heating_COP(T0, Q_r_int, Q_r_max)[source]¶
Calculate the Coefficient of Performance (COP) for an Air Source Heat Pump (ASHP) in heating mode.
Reference: https://www.mdpi.com/2071-1050/15/3/1880
- Parameters:
T0 (float) – Environmental temperature [K]
Q_r_int (float) – Indoor heat load [W]
Q_r_max (float) – Maximum heating capacity [W]
- Returns:
COP value
- Return type:
float
Note
COP is calculated based on PLR (Part Load Ratio).
- tmhp.enex_functions.calc_energy_flow(G, T, T0)[source]¶
Calculate energy flow rate.
- Parameters:
G (float or pd.Series) – Heat capacity flow rate (mass_flow * Cp) [W/K].
T (float or pd.Series) – Current temperature [K].
T0 (float or pd.Series) – Reference/dead state temperature [K].
- Returns:
Energy flow rate [W].
- Return type:
float or pd.Series
- tmhp.enex_functions.calc_exergy_flow(G, T, T0)[source]¶
Calculate exergy flow rate.
- Parameters:
G (float or pd.Series) – Heat capacity flow rate (mass_flow * Cp) [W/K].
T (float or pd.Series) – Current temperature [K].
T0 (float or pd.Series) – Reference/dead state temperature [K].
- Returns:
Exergy flow rate [W].
- Return type:
float or pd.Series
- tmhp.enex_functions.calc_fan_power_from_dV_fan(dV_fan, fan_params, vsd_coeffs, is_active=True)[source]¶
Calculate fan power using ASHRAE 90.1 VSD Curve.
- Parameters:
dV_fan (float) – Current flow rate [m³/s].
fan_params (dict) – Must contain
fan_design_flow_rateandfan_design_power.vsd_coeffs (dict) – VSD Curve coefficients (
c1throughc5).is_active (bool) – If False, returns
np.nan.
- Returns:
Fan power [W].
- Return type:
float
- tmhp.enex_functions.calc_GSHP_COP(T_a_iu_in_K, T_f_out_K, dV_a_ratio, mode)[source]¶
Calculate COP for a Ground Source Heat Pump.
Uses the EnergyPlus
Coil:*:WaterToAir:EquationFitmodel (Equation-Fit Method).References
EnergyPlus Engineering Reference, Ch. 16.5.10.2 (Eq. 16.412–16.418, Tang 2005). Dataset: TCH072_GLHP (ClimateMaster 6-ton, Ground Loop HP), source:
EnergyPlus/datasets/WaterToAirHeatPumps.idf.Rated conditions (from IDF comment, 15% methanol antifreeze):
Cooling: 70.29 kBtu/h @ 77 °F (25 °C) entering water, EER = 14.35
Heating: 56.14 kBtu/h @ 32 °F (0 °C) entering water, COP = 3.42
- Parameters:
T_a_iu_in_K (float) – Indoor air inlet dry-bulb temperature [K] (= T_a_room). For cooling, internally converted to wet-bulb (T_wb) via CoolProp assuming RH = 50%.
T_f_out_K (float) – Source-side inlet water temperature [K] — water returning from the borehole to the heat pump (
T_w,inin EnergyPlus notation).dV_a_ratio (float) – Load-side air volumetric flow ratio: V_a / V_a_ref [-] V_a_ref = Q_rated / (rho_a * c_a * 10K) [m³/s]
mode (str) – “cooling” or “heating”
Units
-----
Temperatures (K)
rates (Flow)
Heat/Power (W)
- Returns:
COP (dimensionless). Polynomial model is unconditionally stable— no ValueError on temperature inversion.
- Return type:
float
- tmhp.enex_functions.calc_refrigerant_exergy(df, ref, T0_K, P0=101325)[source]¶
Calculate refrigerant state-point exergy using pre-computed properties.
Uses the entropy (
s_ref_*) and enthalpy (h_ref_*) columns already present indf(produced bycalc_ref_state) to compute specific exergy and exergy flow rate for each refrigerant state point.Dead-state properties (h0, s0) are evaluated at (T0, P0) for the given refrigerant using CoolProp (vectorized via unique T0 values).
- Parameters:
df (pd.DataFrame) – DataFrame containing pre-computed enthalpy
h_ref_* [J/kg], entropys_ref_* [J/(kg·K)], and mass-flowm_dot_ref [kg/s]columns.ref (str) – CoolProp refrigerant identifier (e.g.
'R410A').T0_K (pd.Series) – Dead-state (environment) temperature per row [K].
P0 (float) – Dead-state pressure [Pa] (default
101325).
- Returns:
dfwith columns added per state point:x_ref_{name} [J/kg],X_ref_{name} [W].- Return type:
pd.DataFrame
Notes
Exergy equation: x = (h − h0) − T0·(s − s0) [J/kg]
Exergy flow: X = ṁ · x [W]
Rows with NaN enthalpy/entropy propagate NaN naturally.
- tmhp.enex_functions.calc_UA_from_dV_fan(dV_fan, dV_fan_design, A_cross, UA, exponent=0.71)[source]¶
Calculate velocity-dependent UA via lumped scaling (Wang et al., 2000).
- Parameters:
dV_fan (float) – Current fan flow rate [m³/s].
dV_fan_design (float) – Design fan flow rate [m³/s].
A_cross (float) – Heat exchanger cross-sectional area [m²].
UA (float) – Design UA value [W/K].
exponent (float) – Exponent for velocity scaling. Default is 0.71 for a 1-row configuration.
- Returns:
Scaled UA value [W/K].
- Return type:
float
Notes
Instead of the Dittus-Boelter tube-side exponent (0.8), this uses a simplified lumped exponent (default 0.71). This derivation assumes a 1-row plain fin-and-tube configuration (N=1) where the Colburn j-factor is proportional to Re^-0.29, leading to h ∝ V^0.71. Multi-row coils may use exponents between 0.5 and 0.8 depending on configuration. Reference: Wang et al. (2000), DOI: 10.1016/S0017-9310(99)00333-6
- tmhp.enex_functions.calc_uv_exposure_time(radius_cm, uvc_output_W, lamp_arc_length_cm, target_dose_mj_cm2=186, turbidity_ntu=0.25)[source]¶
Calculate required UV lamp exposure time via Radial Model.
Reference: ADA453967.pdf — Radial Model for UV disinfection.
- Parameters:
radius_cm (float) – Tank radius (lamp-to-wall distance) [cm].
uvc_output_W (float) – UV-C output power of the lamp [W].
lamp_arc_length_cm (float) – Arc length of the lamp [cm].
target_dose_mj_cm2 (float) – Target germicidal dose [mJ/cm²]. Default 186 (EPA 4-log virus).
turbidity_ntu (float) – Water turbidity [NTU].
- Returns:
Required single-exposure time [min].
- Return type:
float
- tmhp.enex_functions.calc_uv_lamp_power(current_time_s, period_sec, num_switching, exposure_sec, lamp_watts)[source]¶
Calculate UV lamp power at a given time instant.
The lamp switches on
num_switchingtimes perperiod_sec, each activation lastingexposure_sec.- Parameters:
current_time_s (float) – Current simulation time [s].
period_sec (float) – Switching period (e.g. 3 h → 10800 s).
num_switching (int) – Number of on-cycles per period.
exposure_sec (float) – Duration of each on-cycle [s].
lamp_watts (float) – Rated lamp power [W].
- Returns:
Instantaneous lamp power [W] (0 or
lamp_watts).- Return type:
float
- tmhp.enex_functions.chi(s, rb, H, z0=0)[source]¶
Helper function for G-function calculation.
- Parameters:
s (float) – Integration variable
rb (float) – Borehole radius [m]
H (float) – Borehole height [m]
z0 (float, optional) – Reference depth [m] (default: 0)
- Returns:
chi function value
- Return type:
float
- tmhp.enex_functions.convert_electricity_to_exergy(df)[source]¶
Copy all electricity columns (
E_*) to exergy columns (X_*).Electrical energy is 100 %% pure exergy, so
X = Efor all electricity-consumption columns.The function searches for columns matching the pattern
E_xxx [W]and creates correspondingX_xxx [W]columns.- Parameters:
df (pd.DataFrame) – DataFrame with
E_xxx [W]columns.- Returns:
dfwithX_xxx [W]columns added.- Return type:
pd.DataFrame
- tmhp.enex_functions.f(x)[source]¶
Helper function for G-function calculation.
- Parameters:
x (float) – Input value
- Returns:
f(x) = x*erf(x) - (1-exp(-x²))/√π
- Return type:
float
- tmhp.enex_functions.generate_entropy_exergy_term(fluid, T, P, Q, T0, P0, phase='gas')[source]¶
Calculate entropy, enthalpy, and exergy.
- Parameters:
fluid (str) – Fluid name.
T (float) – Temperature [K].
P (float) – Pressure [Pa].
Q (float) – Quality (0 to 1).
T0 (float) – Dead state temperature [K].
P0 (float) – Dead state pressure [Pa].
phase (Literal['gas', 'liquid', 'twophase'], optional) – Fluid phase. Default is ‘gas’.
- Returns:
Entropy [J/kg-K], Enthalpy [J/kg], Exergy [J/kg].
- Return type:
tuple[float, float, float]
- tmhp.enex_functions.get_uv_params_from_turbidity(turbidity_ntu)[source]¶
Return UV parameters from a turbidity lookup table.
Table data based on Table 1. Effect of Turbidity on UVT, UV Absorbance, UV Intensity, and Exposure Time.
- Parameters:
turbidity_ntu (float) – Turbidity value [NTU].
- Returns:
Keys:
uv_absorbance,uv_transmittance_percent,reference_intensity_mw_cm2,reference_exposure_time_sec.- Return type:
dict
Simulation summary tables¶
Simulation summary output functions.
- tmhp.simulation_summary.print_simulation_summary(df, simulation_time_step, dV_ou_a_design)[source]¶
Print a comprehensive summary of simulation results.
- Parameters:
df (pd.DataFrame) – Simulation result DataFrame.
simulation_time_step (int) – Time step [s].
dV_ou_a_design (float) – Design airflow rate of outdoor unit [m3/s].
- Return type:
None