Water-source heat pump boiler (WSHPB)

Source side is a water loop with a prescribed inlet temperature; sink side is the same DHW tank used by ASHPB / GSHPB.

Overview

The class is tmhp.WaterSourceHeatPumpBoiler. Unlike GSHPB, WSHPB takes the source-side inlet temperature as a schedule input rather than computing it from a borehole field — useful when the water loop is driven by an external simulation or measurement.

Base usage

from tmhp import WaterSourceHeatPumpBoiler

wshpb = WaterSourceHeatPumpBoiler(ref="R134a")

result = wshpb.analyze_steady(
    T_tank_w=55.0,
    T_source=15.0,     # water-loop inlet [°C]
    Q_ref_cond=8_000,
)

Source-side mechanics

A single ε-NTU heat exchanger between the refrigerant evaporator and the source-side water loop. No borehole transient — the loop inlet temperature is whatever the user supplies.

Sink-side mechanics

Same DHW tank as ASHPB / GSHPB.

API reference

Ground source heat pump boiler — physics-based cycle model.

Resolves a vapour-compression refrigerant cycle coupled to a borehole heat exchanger (BHE) on the evaporator side and a lumped-capacitance hot-water tank on the condenser side. At each time step the model finds the minimum-power operating point via 1D Brent optimization over the evaporator approach temperature difference, while the condenser temperature is solved analytically.

Borehole thermal response is tracked with pygfunction-based multi-borehole g-functions, enabling robust long-term ground temperature drift modeling.

class tmhp.water_source_heat_pump_boiler.WaterSourceHeatPumpBoiler(ref='R410A', V_disp_cmp=0.0005, eta_cmp_isen=0.7, UA_cond_design=500, UA_evap_design=500, T0=0.0, Ts=16.0, T_tank_w_upper_bound=65.0, T_tank_w_lower_bound=55.0, T_mix_w_out=40.0, T_tank_w_in=15.0, hp_capacity=8000.0, dV_mix_w_out_max=0.0001, r0=0.2, H=0.8, x_shell=0.01, x_ins=0.05, k_shell=25, k_ins=0.03, h_o=15, N_1=1, N_2=1, B=6.0, D_b=0, H_b=200, r_b=0.08, R_b=None, k_g=1.5, k_p=0.4, r_out=0.016, r_in=0.013, D_s=0.025, dV_b_f_lpm=24, k_s=2.0, c_s=800, rho_s=2000, E_pmp=200, v_river=0.5, dT_superheat=5.0, dT_subcool=5.0, tank_always_full=True, prevent_simultaneous_flow=False, tank_level_lower_bound=0.5, tank_level_upper_bound=1.0, dV_tank_w_in_refill=0.001, hp_on_schedule=None, stc=None, pv=None, uv=None, t_max_s=31536000, dt_s=3600, *, refrigerant=None)[source]

Bases: object

Water source heat pump boiler with BHE and lumped-tank model.

The refrigerant cycle is resolved via CoolProp with user-specified superheat / subcool margins. An optimizer minimises total cycle electrical input subject to NTU-based evaporator constraints and analytical condenser temperature relations.

Parameters:
  • ref (str)

  • V_disp_cmp (float)

  • eta_cmp_isen (float)

  • UA_cond_design (float)

  • UA_evap_design (float)

  • T0 (float)

  • Ts (float)

  • T_tank_w_upper_bound (float)

  • T_tank_w_lower_bound (float)

  • T_mix_w_out (float)

  • T_tank_w_in (float)

  • hp_capacity (float)

  • dV_mix_w_out_max (float)

  • r0 (float)

  • H (float)

  • x_shell (float)

  • x_ins (float)

  • k_shell (float)

  • k_ins (float)

  • h_o (float)

  • N_1 (int)

  • N_2 (int)

  • B (float)

  • D_b (float)

  • H_b (float)

  • r_b (float)

  • R_b (Optional[float])

  • k_g (float)

  • k_p (float)

  • r_out (float)

  • r_in (float)

  • D_s (float)

  • dV_b_f_lpm (float)

  • k_s (float)

  • c_s (float)

  • rho_s (float)

  • E_pmp (float)

  • v_river (float)

  • dT_superheat (float)

  • dT_subcool (float)

  • tank_always_full (bool)

  • prevent_simultaneous_flow (bool)

  • tank_level_lower_bound (float)

  • tank_level_upper_bound (float)

  • dV_tank_w_in_refill (float)

  • hp_on_schedule (Optional[list[tuple[float, float]]])

  • stc (Optional[SolarThermalCollector])

  • t_max_s (float)

  • dt_s (float)

  • refrigerant (Optional[str])

__init__(ref='R410A', V_disp_cmp=0.0005, eta_cmp_isen=0.7, UA_cond_design=500, UA_evap_design=500, T0=0.0, Ts=16.0, T_tank_w_upper_bound=65.0, T_tank_w_lower_bound=55.0, T_mix_w_out=40.0, T_tank_w_in=15.0, hp_capacity=8000.0, dV_mix_w_out_max=0.0001, r0=0.2, H=0.8, x_shell=0.01, x_ins=0.05, k_shell=25, k_ins=0.03, h_o=15, N_1=1, N_2=1, B=6.0, D_b=0, H_b=200, r_b=0.08, R_b=None, k_g=1.5, k_p=0.4, r_out=0.016, r_in=0.013, D_s=0.025, dV_b_f_lpm=24, k_s=2.0, c_s=800, rho_s=2000, E_pmp=200, v_river=0.5, dT_superheat=5.0, dT_subcool=5.0, tank_always_full=True, prevent_simultaneous_flow=False, tank_level_lower_bound=0.5, tank_level_upper_bound=1.0, dV_tank_w_in_refill=0.001, hp_on_schedule=None, stc=None, pv=None, uv=None, t_max_s=31536000, dt_s=3600, *, refrigerant=None)[source]
Parameters:
  • ref (str)

  • V_disp_cmp (float)

  • eta_cmp_isen (float)

  • UA_cond_design (float)

  • UA_evap_design (float)

  • T0 (float)

  • Ts (float)

  • T_tank_w_upper_bound (float)

  • T_tank_w_lower_bound (float)

  • T_mix_w_out (float)

  • T_tank_w_in (float)

  • hp_capacity (float)

  • dV_mix_w_out_max (float)

  • r0 (float)

  • H (float)

  • x_shell (float)

  • x_ins (float)

  • k_shell (float)

  • k_ins (float)

  • h_o (float)

  • N_1 (int)

  • N_2 (int)

  • B (float)

  • D_b (float)

  • H_b (float)

  • r_b (float)

  • R_b (Optional[float])

  • k_g (float)

  • k_p (float)

  • r_out (float)

  • r_in (float)

  • D_s (float)

  • dV_b_f_lpm (float)

  • k_s (float)

  • c_s (float)

  • rho_s (float)

  • E_pmp (float)

  • v_river (float)

  • dT_superheat (float)

  • dT_subcool (float)

  • tank_always_full (bool)

  • prevent_simultaneous_flow (bool)

  • tank_level_lower_bound (float)

  • tank_level_upper_bound (float)

  • dV_tank_w_in_refill (float)

  • hp_on_schedule (Optional[list[tuple[float, float]]])

  • stc (Optional[SolarThermalCollector])

  • t_max_s (float)

  • dt_s (float)

  • refrigerant (Optional[str])

analyze_dynamic(simulation_period_sec, dt_s, T_tank_w_init_C, dhw_usage_schedule, T0_schedule, I_DN_schedule=None, I_dH_schedule=None, T_sup_w_schedule=None, T_source_w_schedule=None, tank_level_init=1.0, result_save_csv_path=None)[source]
Parameters:
  • simulation_period_sec (float)

  • dt_s (float)

  • T_tank_w_init_C (float)

  • tank_level_init (float)

Return type:

DataFrame

analyze_steady(T_tank_w, T_source, Q_ref_cond, T0=0.0, *, return_dict=True)[source]

Run a steady-state performance snapshot.

Evaluates the refrigerant cycle at a given operating point (T_tank_w, T_source, Q_ref_cond) without solving the tank energy balance or tracking dynamic flows.

Parameters:
  • T_tank_w (float) – Tank water temperature [°C] — treated as a given input.

  • T_source (float) – Source fluid temperature entering the heat pump [°C].

  • Q_ref_cond (float) – Target condenser heat rate [W].

  • T0 (float) – Dead-state / outdoor-air temperature [°C] (for exergy calculations).

  • return_dict (bool) – If True return dict; else single-row DataFrame.

Returns:

Cycle state plus diagnostic flags. Notable keys:

  • "converged" (bool) — True only when the HX optimisation and the SciPy optimiser both succeeded.

  • "failure_reason" (str) — one of "none", "cycle_invalid", "hx_not_converged", or "optimizer_failed".

Important: like GSHPB, WSHPB often reports failure_reason="hx_not_converged" on realistic operating points; the cycle numbers (E_cmp, Q_ref_cond, cop_sys, …) are still usable in that case. Only "cycle_invalid" forces an off-mode fallback (E_cmp=0, COP=NaN). Branch on E_cmp [W] > 0 rather than failure_reason == "none" if you only want to discard truly broken results.

Return type:

dict | pd.DataFrame

postprocess_exergy(df)[source]

Compute GSHPB-specific exergy variables.

Parameters:

df (DataFrame)

Return type:

DataFrame