Subsystems

Composable subsystems that the *_stc_* and *_pv_ess model variants plug onto the core cycle, plus the UV-treatment subsystem.

Solar thermal collector

class tmhp.subsystems.SolarThermalCollector(A_stc=2.0, stc_tilt=35.0, stc_azimuth=180.0, A_stc_pipe=2.0, alpha_stc=0.95, h_o_stc=15.0, h_r_stc=2.0, k_ins_stc=0.03, x_air_stc=0.01, x_ins_stc=0.05, preheat_start_hour=6.0, preheat_end_hour=18.0, dV_stc_w=0.001, E_stc_pump=50.0)[source]

Bases: object

Solar Thermal Collector (STC) — pure physics engine.

Bundles collector geometry, optical and thermal properties, and pump parameters. This class is a stateless physics calculator: given physical inputs it returns a performance dict. All simulation orchestration (activation logic, result assembly, exergy calculation) is the responsibility of the scenario class that uses this engine.

The public API consists of:

Parameters:
  • A_stc (float) – Collector gross area [m²].

  • stc_tilt (float) – Tilt from horizontal [°].

  • stc_azimuth (float) – Azimuth angle (180 = south) [°].

  • A_stc_pipe (float) – Pipe surface area [m²].

  • alpha_stc (float) – Absorptivity [–].

  • h_o_stc (float) – External convective coefficient [W/(m²·K)].

  • h_r_stc (float) – Radiative coefficient [W/(m²·K)].

  • k_ins_stc (float) – Insulation conductivity [W/(m·K)].

  • x_air_stc (float) – Air gap thickness [m].

  • x_ins_stc (float) – Insulation thickness [m].

  • preheat_start_hour (float) – Preheat window start hour.

  • preheat_end_hour (float) – Preheat window end hour.

  • dV_stc_w (float) – Default STC loop flow rate [m³/s].

  • E_stc_pump (float) – STC pump rated power [W].

A_stc: float = 2.0
stc_tilt: float = 35.0
stc_azimuth: float = 180.0
A_stc_pipe: float = 2.0
alpha_stc: float = 0.95
h_o_stc: float = 15.0
h_r_stc: float = 2.0
k_ins_stc: float = 0.03
x_air_stc: float = 0.01
x_ins_stc: float = 0.05
preheat_start_hour: float = 6.0
preheat_end_hour: float = 18.0
dV_stc_w: float = 0.001
E_stc_pump: float = 50.0
calc_overall_heat_transfer_coeff()[source]

Compute overall U-value from parallel resistances.

The collector has two heat-loss paths in parallel:

  • Path 1 (top): radiation gap ‖ air gap → external conv

  • Path 2 (bottom): insulation → external conv

Returns:

Overall heat-loss coefficient [W/(m²·K)].

Return type:

float

calc_performance(I_DN_stc, I_dH_stc, T_stc_w_in_K, T0_K, dV_stc=None, is_active=True)[source]

Compute STC thermal performance for one timestep.

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 [K].

  • T0_K (float) – Dead-state temperature [K].

  • dV_stc (float | None) – Override flow rate [m³/s]; defaults to self.dV_stc_w.

  • is_active (bool) – If False, return NaN-filled dict.

Returns:

Performance results including: I_sol_stc, Q_sol_stc, Q_stc_w_in, Q_stc_w_out, Q_stc_pump_w_out, ksi_stc, T_stc_w_out_K, T_stc_pump_w_out_K, T_stc_w_in_K, T_stc_K, Q_l_stc.

Return type:

dict

is_preheat_on(hour_of_day)[source]

Check whether hour_of_day falls in the window.

Parameters:

hour_of_day (float) – Hour within the day (0–24).

Return type:

bool

__init__(A_stc=2.0, stc_tilt=35.0, stc_azimuth=180.0, A_stc_pipe=2.0, alpha_stc=0.95, h_o_stc=15.0, h_r_stc=2.0, k_ins_stc=0.03, x_air_stc=0.01, x_ins_stc=0.05, preheat_start_hour=6.0, preheat_end_hour=18.0, dV_stc_w=0.001, E_stc_pump=50.0)
Parameters:
  • A_stc (float)

  • stc_tilt (float)

  • stc_azimuth (float)

  • A_stc_pipe (float)

  • alpha_stc (float)

  • h_o_stc (float)

  • h_r_stc (float)

  • k_ins_stc (float)

  • x_air_stc (float)

  • x_ins_stc (float)

  • preheat_start_hour (float)

  • preheat_end_hour (float)

  • dV_stc_w (float)

  • E_stc_pump (float)

Photovoltaic system

class tmhp.subsystems.PhotovoltaicSystem(A_pv=5.0, alp_pv=0.9, pv_tilt=35.0, pv_azimuth=180.0, h_o=15.0, eta_pv=0.15, beta_pv=0.0045, T_ref_pv_K=298.15, eta_ctrl=0.95, T_ctrl_K=308.15)[source]

Bases: object

Photovoltaic System (PV + Charge Controller) — pure physics engine.

Computes PV energy generation from irradiance inputs. This class is a stateless physics calculator: given physical inputs it returns a performance dict. All routing logic (ESS charge/discharge, Grid import, dump) is the responsibility of the scenario class.

The public API:

Parameters:
  • A_pv (float)

  • alp_pv (float)

  • pv_tilt (float)

  • pv_azimuth (float)

  • h_o (float)

  • eta_pv (float)

  • beta_pv (float)

  • T_ref_pv_K (float)

  • eta_ctrl (float)

  • T_ctrl_K (float)

A_pv: float = 5.0
alp_pv: float = 0.9
pv_tilt: float = 35.0
pv_azimuth: float = 180.0
h_o: float = 15.0
eta_pv: float = 0.15
beta_pv: float = 0.0045
T_ref_pv_K: float = 298.15
eta_ctrl: float = 0.95
T_ctrl_K: float = 308.15
calc_performance(I_DN, I_dH, T0_K)[source]

Compute PV generation for one timestep.

Parameters:
  • I_DN (float) – Direct-normal irradiance [W/m²].

  • I_dH (float) – Diffuse-horizontal irradiance [W/m²].

  • T0_K (float) – Dead-state (ambient) temperature [K].

Returns:

Keys: I_sol_pv, T_pv_K, eta_pv_actual, E_pv_out, E_ctrl_out, Q_l_pv, Q_l_ctrl, X_sol, X_pv_out, X_ctrl_out, X_c_pv, X_c_ctrl, X_l_pv, X_l_ctrl.

Return type:

dict

__init__(A_pv=5.0, alp_pv=0.9, pv_tilt=35.0, pv_azimuth=180.0, h_o=15.0, eta_pv=0.15, beta_pv=0.0045, T_ref_pv_K=298.15, eta_ctrl=0.95, T_ctrl_K=308.15)
Parameters:
  • A_pv (float)

  • alp_pv (float)

  • pv_tilt (float)

  • pv_azimuth (float)

  • h_o (float)

  • eta_pv (float)

  • beta_pv (float)

  • T_ref_pv_K (float)

  • eta_ctrl (float)

  • T_ctrl_K (float)

Energy storage system

class tmhp.subsystems.EnergyStorageSystem(C_ess_max=3600000.0, SOC_init=0.0, SOC_min=0.1, SOC_max=1.0, eta_ess_chg=0.9, eta_ess_dis=0.9, T_ess_K=313.15)[source]

Bases: object

Energy Storage System (Battery) — pure physics engine.

Accepts charging / discharging requests (DC power, [W]) and enforces capacity and SOC limits. Internal losses and exergy destruction are computed from round-trip efficiencies.

State (SOC_ess) is updated in-place at each call to charge() or discharge(). Routing decisions (which request to fulfil and in what order) are entirely the responsibility of the scenario class.

Parameters:
  • C_ess_max (float) – Rated energy capacity [J]. Default 3.6 MJ (= 1 kWh).

  • SOC_init (float) – Initial state of charge [–].

  • SOC_min (float) – Minimum allowable SOC [–] (depth-of-discharge guard).

  • SOC_max (float) – Maximum allowable SOC [–].

  • eta_ess_chg (float) – Charging efficiency (electricity-in to stored) [–].

  • eta_ess_dis (float) – Discharging efficiency (stored to electricity-out) [–].

  • T_ess_K (float) – Representative battery temperature used for entropy calc [K].

C_ess_max: float = 3600000.0
SOC_init: float = 0.0
SOC_min: float = 0.1
SOC_max: float = 1.0
eta_ess_chg: float = 0.9
eta_ess_dis: float = 0.9
T_ess_K: float = 313.15
SOC_ess: float
charge(E_req_chg, dt, T0_K)[source]

Request to charge the ESS with E_req_chg [W] for dt [s].

Returns a dict with keys E_ess_chg, E_ess_dis, SOC_ess plus exergy keys.

Parameters:
  • E_req_chg (float)

  • dt (float)

  • T0_K (float)

Return type:

dict

discharge(E_req_dis, dt, T0_K)[source]

Request to discharge E_req_dis [W] from the ESS for dt [s].

Returns a dict with keys E_ess_dis (actual), E_ess_chg, SOC_ess plus exergy keys.

Parameters:
  • E_req_dis (float)

  • dt (float)

  • T0_K (float)

Return type:

dict

__init__(C_ess_max=3600000.0, SOC_init=0.0, SOC_min=0.1, SOC_max=1.0, eta_ess_chg=0.9, eta_ess_dis=0.9, T_ess_K=313.15)
Parameters:
  • C_ess_max (float)

  • SOC_init (float)

  • SOC_min (float)

  • SOC_max (float)

  • eta_ess_chg (float)

  • eta_ess_dis (float)

  • T_ess_K (float)

UV lamp

class tmhp.subsystems.UVLamp(lamp_watts=0.0, exposure_sec=0.0, num_switching=1, period_sec=10800)[source]

Bases: object

UV disinfection lamp subsystem.

The lamp switches on periodically (num_switching times per period_sec, each for exposure_sec). All electrical input is converted to heat inside the tank (Q_contribution = E_uv).

Parameters:
  • lamp_watts (float) – Rated lamp power [W].

  • exposure_sec (float) – Duration of each on-cycle [s].

  • num_switching (int) – Number of on-cycles per period.

  • period_sec (float) – Switching period [s] (default 3 h = 10 800 s).

lamp_watts: float = 0.0
exposure_sec: float = 0.0
num_switching: int = 1
period_sec: float = 10800
step(ctx, ctrl, dt, T_tank_w_in_K)[source]

Compute UV lamp state for one timestep.

Parameters:
  • ctx (StepContext)

  • ctrl (ControlState)

  • dt (float)

  • T_tank_w_in_K (float)

Return type:

dict

assemble_results(ctx, ctrl, step_state, T_solved_K)[source]

Report UV power for DataFrame output.

Parameters:
  • ctx (StepContext)

  • ctrl (ControlState)

  • step_state (dict)

  • T_solved_K (float)

Return type:

dict

calc_exergy(df, T0_K)[source]

UV exergy = electricity (handled by E→X conversion).

No additional post-processing needed. Returns None.

Parameters:
  • df (DataFrame)

  • T0_K (Series)

Return type:

SubsystemExergy | None

__init__(lamp_watts=0.0, exposure_sec=0.0, num_switching=1, period_sec=10800)
Parameters:
  • lamp_watts (float)

  • exposure_sec (float)

  • num_switching (int)

  • period_sec (float)

UV treatment

UV water treatment utility functions.

Functions for UV lamp power scheduling, turbidity-based parameter lookup, and required exposure time calculation (Radial Model).

tmhp.uv_treatment.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_switching times per period_sec, each activation lasting exposure_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.uv_treatment.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

tmhp.uv_treatment.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