Heat generators package

Annuity Calculation Module

Economic evaluation module for technical installations according to VDI 2067.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

This module provides comprehensive economic analysis capabilities for district heating systems following the German VDI 2067 standard for economic evaluation of technical installations. It implements standardized methodology for calculating annuities considering capital costs, operational expenses, and revenue streams over the entire system lifecycle.

The implementation supports lifecycle cost analysis for various district heating technologies including heat pumps, thermal storage systems, solar thermal installations, and conventional heating equipment. It provides standardized economic evaluation suitable for investment decisions, subsidy calculations, and economic optimization of district heating systems.

Features:

  • VDI 2067 compliant annuity calculations

  • Lifecycle cost analysis with inflation and interest rate considerations

  • Capital-bound, demand-bound, and operation-bound cost components

  • Residual value calculations for asset replacement cycles

  • Revenue integration for economic optimization

  • Support for multiple replacement cycles over analysis period

Mathematical Foundation:

The module implements the VDI 2067 methodology for economic evaluation:

Annuity Factor:

a = (q - 1) / [1 - q^(-T)]

Where: - q = interest rate factor (1 + interest rate) - T = consideration time period [years]

Price-Dynamic Present Value Factor:

b = [1 - (r/q)^T] / (q - r)

Where: - r = inflation rate factor (1 + inflation rate) - q = interest rate factor - T = consideration time period [years]

Total Annuity:

A_N = A_N_K + A_N_V + A_N_B + A_N_S - A_N_E

Where: - A_N_K = Capital-bound costs annuity - A_N_V = Demand-bound costs annuity - A_N_B = Operation-bound costs annuity - A_N_S = Other costs annuity - A_N_E = Revenue annuity

Cost Categories:

Capital-Bound Costs (A_N_K):

Investment costs, replacement costs, and residual value considerations

Demand-Bound Costs (A_N_V):

Energy costs (electricity, gas, fuel) varying with system operation

Operation-Bound Costs (A_N_B):

Maintenance, inspection, insurance, and labor costs

Other Costs (A_N_S):

Additional system-specific costs not covered by other categories

districtheatingsim.heat_generators.annuity.annuity(initial_investment_cost: float, asset_lifespan_years: int, installation_factor: float, maintenance_inspection_factor: float, operational_effort_h: float = 0, interest_rate_factor: float = 1.05, inflation_rate_factor: float = 1.03, consideration_time_period_years: int = 20, annual_energy_demand: float = 0, energy_cost_per_unit: float = 0, annual_revenue: float = 0, hourly_rate: float = 45) float[source]

Calculate annuity for technical installations according to VDI 2067.

Parameters:
  • initial_investment_cost (float) – Initial capital investment cost [€]

  • asset_lifespan_years (int) – Technical lifetime [years]

  • installation_factor (float) – Installation cost factor [%]

  • maintenance_inspection_factor (float) – Annual maintenance cost factor [%]

  • operational_effort_h (float) – Annual operational effort [hours/year], defaults to 0

  • interest_rate_factor (float) – Interest rate factor (1 + rate), defaults to 1.05

  • inflation_rate_factor (float) – Inflation rate factor (1 + rate), defaults to 1.03

  • consideration_time_period_years (int) – Economic analysis period [years], defaults to 20

  • annual_energy_demand (float) – Annual energy consumption [MWh/year], defaults to 0

  • energy_cost_per_unit (float) – Energy cost [€/MWh], defaults to 0

  • annual_revenue (float) – Annual revenue [€/year], defaults to 0

  • hourly_rate (float) – Labor cost rate [€/hour], defaults to 45

Returns:

Total annual equivalent cost [€/year]

Return type:

float

Note

Implements VDI 2067 methodology for lifecycle cost analysis including capital-bound, demand-bound, and operation-bound costs with revenue integration.

Raises:
  • ValueError – If asset_lifespan_years is zero or negative, or if interest_rate_factor <= 1 / inflation_rate_factor < 1 (a rate such as 0.05 was passed where a factor such as 1.05 is required — see BACKLOG C5).

  • ZeroDivisionError – If interest and inflation factors are equal (mathematical singularity).

districtheatingsim.heat_generators.annuity.infrastructure_annuity(initial_investment_cost: float, asset_lifespan_years: int, installation_factor: float, maintenance_inspection_factor: float, operational_effort_h: float, economic_parameters: dict) float[source]

Annuity for one infrastructure cost row from a GUI economic_parameters mapping.

Adapts economic_parameters (capital_interest_rate / inflation_rate as VDI 2067 factors, time_period, hourly_rate) to annuity(). Returns 0.0 for a zero lifespan (a not-yet-configured row), avoiding a division by zero. Lives here, not in the cost tab, so the economic mapping is testable and the GUI holds no VDI 2067 logic (BACKLOG B2).

Parameters:
  • initial_investment_cost – Initial capital investment cost [€].

  • asset_lifespan_years – Technical lifetime [years]; 0 → returns 0.0.

  • installation_factor – Installation cost factor [%].

  • maintenance_inspection_factor – Annual maintenance cost factor [%].

  • operational_effort_h – Annual operational effort [hours/year].

  • economic_parameters – Mapping with capital_interest_rate, inflation_rate, time_period, hourly_rate.

Returns:

The annuity [€/year].

AqvaHeat Heat Pump Module

Vacuum ice slurry generator with heat pump.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.aqvaheat_heat_pump.AqvaHeat(name, nominal_power=100, temperature_difference=0)[source]

Bases: HeatPump

AqvaHeat vacuum ice slurry heat pump system.

Parameters:
  • name (str) – System identifier

  • nominal_power (float) – Nominal power [kW], defaults to 100

  • temperature_difference (float) – Temperature difference [K], defaults to 0

__init__(name, nominal_power=100, temperature_difference=0)[source]

Initialize heat pump system.

Parameters:
  • name (str) – Unique identifier

  • spezifische_Investitionskosten_WP (float) – Specific investment costs [€/kW], defaults to 1000

  • active (bool) – Initial operational status, defaults to True

calculate(economic_parameters, duration, load_profile, **kwargs)[source]

Calculate AqvaHeat system performance.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Simulation duration [h]

  • load_profile (numpy.ndarray) – Load profile [kW]

  • kwargs – VLT_L (flow temperatures), COP_data (COP interpolation data)

Returns:

Performance metrics and results

Return type:

dict

set_parameters(variables, variables_order, idx)[source]

Set optimization parameters for the heat generator (abstract).

Parameters:
  • variables (list of float) – List of optimization variable values

  • variables_order (list of str) – Order and assignment of optimization variables

  • idx (int) – Technology index in the system list

Raises:

NotImplementedError – Must be implemented by derived classes

add_optimization_parameters(idx)[source]

Return empty optimization parameters (no optimization for AqvaHeat).

Parameters:

idx (int) – Technology index

Returns:

Empty lists (initial_values, variables_order, bounds)

Return type:

tuple

get_display_text()[source]
extract_tech_data()[source]

Base Heat Generator Module

Abstract base classes for heat generation technologies.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.base_heat_generator.BaseHeatGenerator(name: str)[source]

Bases: object

Abstract base class for heat generators.

Parameters:

name (str) – Unique identifier

Note

Derived classes must implement: calculate(), set_parameters(), add_optimization_parameters()

__init__(name: str) None[source]

Initialize the base heat generator.

Parameters:

name (str) – Unique identifier for the heat generator instance

annuity(*args, **kwargs) float[source]

VDI 2067 compliant economic evaluation wrapper.

Parameters:
  • args – Positional arguments for annuity function

  • kwargs – Keyword arguments for annuity function

Returns:

Annual equivalent cost [€/year]

Return type:

float

Note

See annuity.py for complete parameter documentation.

generate(t: int, **kwargs) tuple[source]

Generate heat for a single time step (used in storage-coupled dispatch).

Parameters:
  • t (int) – Time step index

  • kwargs – Technology-specific context (remaining_load, VLT_L, RLT_L, etc.)

Returns:

(heat_output_kW, electricity_output_kW)

Return type:

tuple

Raises:

NotImplementedError – Must be implemented by derived classes that support STES coupling.

calculate(economic_parameters: dict[str, Any], duration: float, load_profile, **kwargs) dict[str, Any][source]

Full-profile calculation including economic and environmental analysis (abstract).

Parameters:
  • economic_parameters (dict) – Economic parameters (electricity_price, gas_price, etc.)

  • duration (float) – Time step duration [hours]

  • load_profile (numpy.ndarray) – Remaining heat demand profile [kW]

  • kwargs – Technology-specific parameters

Returns:

Results dict with Wärmemenge, WGK, spec_co2_total, etc.

Return type:

dict

Raises:

NotImplementedError – Must be implemented by derived classes.

load_economic_parameters(economic_parameters: dict[str, Any]) None[source]

Extract and store common economic parameters from the shared parameters dict.

Parameters:

economic_parameters (dict) – Dict with keys electricity_price, gas_price, wood_price, capital_interest_rate, inflation_rate, time_period, subsidy_eligibility, hourly_rate.

Note

Call this at the start of calculate_heat_generation_cost() in each subclass instead of repeating the same 7-8 assignment lines.

set_parameters(variables: list[float], variables_order: list[str], idx: int) None[source]

Set optimization parameters for the heat generator (abstract).

Parameters:
  • variables (list of float) – List of optimization variable values

  • variables_order (list of str) – Order and assignment of optimization variables

  • idx (int) – Technology index in the system list

Raises:

NotImplementedError – Must be implemented by derived classes

add_optimization_parameters(idx: int) dict[str, Any][source]

Define optimization variables and constraints for the technology (abstract).

Parameters:

idx (int) – Technology index in the system list

Returns:

Dict with ‘variables’, ‘bounds’, ‘constraints’ keys

Return type:

dict

Raises:

NotImplementedError – Must be implemented by derived classes

update_parameters(optimized_values: list[float], variables_order: list[str]) None[source]

Update technology parameters from optimization results.

Parameters:
  • optimized_values (list of float) – Optimized values for all system variables

  • variables_order (list of str) – Order of variables defining parameter assignment

get_plot_data() dict[str, list | ndarray][source]

Extract time-series data for visualization.

Returns:

Dict mapping variable names to time-series arrays

Return type:

dict

to_dict() dict[str, Any][source]

Convert heat generator to dictionary for serialization.

Returns:

Dictionary representation excluding non-serializable attributes

Return type:

dict

Note

Numpy arrays are converted to lists for JSON compatibility.

classmethod from_dict(data: dict[str, Any]) BaseHeatGenerator[source]

Create heat generator from dictionary representation.

Parameters:

data (dict) – Dictionary containing heat generator attributes

Returns:

New heat generator object

Return type:

BaseHeatGenerator

class districtheatingsim.heat_generators.base_heat_generator.BaseStrategy(charge_on: float, charge_off: float)[source]

Bases: object

Base control strategy with hysteresis logic.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float) – Temperature threshold for deactivation [°C]

__init__(charge_on: float, charge_off: float) None[source]

Initialize control strategy with temperature thresholds.

Parameters:
  • charge_on (float) – Storage temperature threshold for activation [°C]

  • charge_off (float) – Storage temperature threshold for deactivation [°C]

decide_operation(current_state: bool, upper_storage_temp: float, lower_storage_temp: float, remaining_demand: float) bool[source]

Decide heat generator operation based on storage conditions and demand.

Parameters:
  • current_state (bool) – Current operational state of the heat generator

  • upper_storage_temp (float) – Upper storage layer temperature [°C]

  • lower_storage_temp (float) – Lower storage layer temperature [°C]

  • remaining_demand (float) – Remaining heat demand [kW]

Returns:

True to operate, False to stop

Return type:

bool

Note

ON: Continue if lower_temp < charge_off AND demand > 0. OFF: Start if upper_temp ≤ charge_on AND demand > 0.

to_dict() dict[str, Any][source]

Convert strategy to dictionary for serialization.

Returns:

Dictionary representation of the strategy

Return type:

dict

classmethod from_dict(data: dict[str, Any]) BaseStrategy[source]

Create strategy from dictionary representation.

Looks up the concrete subclass via the _strategy_class key written by to_dict() so the correct decide_operation() override is preserved. Falls back to cls (typically BaseStrategy) for legacy JSON files that do not contain the key.

Parameters:

data (dict) – Dictionary containing strategy attributes

Returns:

New strategy object

Return type:

BaseStrategy

Base Heat Pump Classes

Base classes for heat pump modeling with COP calculations and economic analysis.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.base_heat_pumps.HeatPump(name: str, spezifische_Investitionskosten_WP: float = 1000, active: bool = True)[source]

Bases: BaseHeatGenerator

Comprehensive heat pump model for district heating applications.

Parameters:
  • name (str) – Unique identifier

  • spezifische_Investitionskosten_WP (float, optional) – Specific investment costs [€/kW], defaults to 1000

  • active (bool, optional) – Initial operational status, defaults to True

Note

Supports geothermal, waste heat, wastewater, and river sources with BEW subsidy (40%).

__init__(name: str, spezifische_Investitionskosten_WP: float = 1000, active: bool = True) None[source]

Initialize heat pump system.

Parameters:
  • name (str) – Unique identifier

  • spezifische_Investitionskosten_WP (float) – Specific investment costs [€/kW], defaults to 1000

  • active (bool) – Initial operational status, defaults to True

init_operation(hours: int) None[source]

Initialize operational arrays for simulation period.

Parameters:

hours (int) – Number of simulation hours

calculate_COP(VLT_L: ndarray, QT: float | ndarray, COP_data: ndarray) tuple[ndarray, ndarray][source]

Calculate Coefficient of Performance using manufacturer data interpolation.

Parameters:
Returns:

(COP_L, VLT_L_adjusted)

Return type:

tuple

calculate_heat_generation_costs(Wärmeleistung: float, Wärmemenge_MWh: float, Strombedarf: float, spez_Investitionskosten_WQ: float, economic_parameters: dict[str, Any]) float[source]

Calculate heat generation costs (WGK).

Parameters:
  • Wärmeleistung (float) – Thermal capacity [kW]

  • Wärmemenge_MWh (float) – Annual heat production [MWh]

  • Strombedarf (float) – Annual electricity consumption [MWh]

  • spez_Investitionskosten_WQ (float) – Specific heat source costs [€/kW]

  • economic_parameters (dict) – Economic parameters dict

Returns:

Heat generation costs [€/MWh]

Return type:

float

calculate_environmental_impact() None[source]

Calculate CO2 emissions and primary energy consumption.

Note

Uses German grid emission factors and primary energy factor.

class districtheatingsim.heat_generators.base_heat_pumps.HeatPumpStrategy(charge_on: float, charge_off: float)[source]

Bases: BaseStrategy

Control strategy for heat pump operation with hysteresis.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float) – Temperature threshold for deactivation [°C]

__init__(charge_on: float, charge_off: float) None[source]

Initialize heat pump control strategy.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float) – Temperature threshold for deactivation [°C]

decide_operation(current_state: bool, upper_storage_temp: float, lower_storage_temp: float, remaining_demand: float) bool[source]

Decide heat pump operation based on storage temperature and demand.

Parameters:
  • current_state (bool) – Current operational state

  • upper_storage_temp (float) – Upper storage temperature [°C]

  • lower_storage_temp (float) – Lower storage temperature [°C]

  • remaining_demand (float) – Remaining heat demand [kW]

Returns:

Operational decision (True=run, False=stop)

Return type:

bool

Biomass Boiler System Module

Biomass boiler system with storage integration, economic analysis and BEW subsidy support.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.biomass_boiler.BiomassBoiler(name: str, thermal_capacity_kW: float, Größe_Holzlager: float = 40, spez_Investitionskosten: float = 200, spez_Investitionskosten_Holzlager: float = 400, Nutzungsgrad_BMK: float = 0.8, min_Teillast: float = 0.3, speicher_aktiv: bool = False, Speicher_Volumen: float = 20, T_vorlauf: float = 90, T_ruecklauf: float = 60, initial_fill: float = 0.0, min_fill: float = 0.2, max_fill: float = 0.8, spez_Investitionskosten_Speicher: float = 750, active: bool = True, opt_BMK_min: float = 0, opt_BMK_max: float = 1000, opt_Speicher_min: float = 0, opt_Speicher_max: float = 100)[source]

Bases: BaseHeatGenerator

Biomass boiler system with storage and efficiency modeling.

Parameters:
  • name (str) – Unique identifier

  • thermal_capacity_kW (float) – Nominal thermal power [°kW]

  • Größe_Holzlager (float, optional) – Wood storage capacity [tons], defaults to 40

  • spez_Investitionskosten (float, optional) – Specific investment costs [€/kW], defaults to 200

  • Nutzungsgrad_BMK (float, optional) – Thermal efficiency [-], defaults to 0.8

  • speicher_aktiv (bool, optional) – Enable thermal storage, defaults to False

  • Speicher_Volumen (float, optional) – Storage volume [m³], defaults to 20

Note

Supports BEW subsidy calculation and part-load operation constraints.

__init__(name: str, thermal_capacity_kW: float, Größe_Holzlager: float = 40, spez_Investitionskosten: float = 200, spez_Investitionskosten_Holzlager: float = 400, Nutzungsgrad_BMK: float = 0.8, min_Teillast: float = 0.3, speicher_aktiv: bool = False, Speicher_Volumen: float = 20, T_vorlauf: float = 90, T_ruecklauf: float = 60, initial_fill: float = 0.0, min_fill: float = 0.2, max_fill: float = 0.8, spez_Investitionskosten_Speicher: float = 750, active: bool = True, opt_BMK_min: float = 0, opt_BMK_max: float = 1000, opt_Speicher_min: float = 0, opt_Speicher_max: float = 100)[source]

Initialize the base heat generator.

Parameters:

name (str) – Unique identifier for the heat generator instance

init_operation(hours: int) None[source]

Initialize operational arrays.

Parameters:

hours (int) – Simulation hours

simulate_operation(Last_L: ndarray) None[source]

Simulate boiler operation without storage.

Parameters:

Last_L (numpy.ndarray) – Thermal load [kW]

Note

Considers minimum part-load constraints.

simulate_storage(Last_L: ndarray, duration: float) None[source]

Simulate boiler with thermal buffer storage (backed by ThermalStorage1D).

Parameters:

Note

Boiler runs at full nominal load; excess heat charges the buffer. Hysteresis control (min_fill / max_fill SOC thresholds) decides when to switch on/off. Buffer provides discharge when boiler is off.

generate(t: int, **kwargs) tuple[float, float][source]

Generate heat for time step.

Parameters:

t (int) – Time step index

Returns:

(heat_output [kW], electricity_output [kW])

Return type:

tuple

calculate_results(duration: float) None[source]

Calculate operational metrics.

Parameters:

duration (float) – Time step [hours]

calculate_heat_generation_costs(economic_parameters: dict) float[source]

Calculate heat generation costs with BEW subsidies.

Parameters:

economic_parameters (dict) – Economic parameters (prices, rates, subsidies)

Returns:

Heat generation cost [€/MWh]

Return type:

float

Note

Includes BEW subsidy (40%) if eligible.

calculate_environmental_impact() None[source]

Calculate environmental impact metrics.

Note

Biomass: 0.036 tCO2/MWh, primary energy factor 0.2

calculate(economic_parameters: dict, duration: float, load_profile: ndarray, **kwargs) dict[source]

Comprehensive system analysis.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Time step [hours]

  • load_profile (numpy.ndarray) – Load profile [kW]

Returns:

Results dictionary with thermal, economic and environmental data

Return type:

dict

Note

Includes thermal simulation, economic and environmental analysis.

set_parameters(variables: list[float], variables_order: list[str], idx: int) None[source]

Set optimization parameters.

Parameters:
  • variables (list) – Variable values

  • variables_order (list) – Variable names

  • idx (int) – Technology index

add_optimization_parameters(idx: int) tuple[list[float], list[str], list[tuple[float, float]]][source]

Define optimization parameters for system sizing.

Parameters:

idx (int) – Technology index

Returns:

(initial_values, variables_order, bounds)

Return type:

tuple

Note

Includes boiler capacity and storage volume (if active).

get_display_text() str[source]

Generate display text for GUI.

Returns:

Formatted system configuration text

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting.

Returns:

(name, dimensions, costs, full_costs)

Return type:

tuple

class districtheatingsim.heat_generators.biomass_boiler.BiomassBoilerStrategy(charge_on: float, charge_off: float)[source]

Bases: BaseStrategy

Control strategy for biomass boiler with storage.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float) – Temperature threshold for deactivation [°C]

__init__(charge_on: float, charge_off: float)[source]

Initialize control strategy.

Parameters:
  • charge_on (float) – Activation temperature [°C]

  • charge_off (float) – Deactivation temperature [°C]

Combined Heat and Power (CHP) System Module

CHP system modeling with thermal/electrical efficiency, storage integration and electricity revenue calculation.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.chp.CHP(name: str, th_Leistung_kW: float, spez_Investitionskosten_GBHKW: float = 1500, spez_Investitionskosten_HBHKW: float = 1850, el_Wirkungsgrad: float = 0.33, KWK_Wirkungsgrad: float = 0.9, min_Teillast: float = 0.7, speicher_aktiv: bool = False, Speicher_Volumen_BHKW: float = 20, T_vorlauf: float = 90, T_ruecklauf: float = 60, initial_fill: float = 0.0, min_fill: float = 0.2, max_fill: float = 0.8, spez_Investitionskosten_Speicher: float = 750, active: bool = True, opt_BHKW_min: float = 0, opt_BHKW_max: float = 1000, opt_BHKW_Speicher_min: float = 0, opt_BHKW_Speicher_max: float = 100, fuel_type: str | None = None)[source]

Bases: BaseHeatGenerator

Combined Heat and Power system with storage.

Parameters:
  • name (str) – Unique identifier (prefix “BHKW” for gas, “Holzgas-BHKW” for biomass)

  • th_Leistung_kW (float) – Nominal thermal power [kW]

  • spez_Investitionskosten_GBHKW (float, optional) – Gas CHP investment costs [€/kW], defaults to 1500

  • el_Wirkungsgrad (float, optional) – Electrical efficiency [-], defaults to 0.33

  • KWK_Wirkungsgrad (float, optional) – Combined efficiency [-], defaults to 0.9

  • speicher_aktiv (bool, optional) – Enable thermal storage, defaults to False

Note

Supports BEW/KWKG subsidies and electricity revenue calculations.

__init__(name: str, th_Leistung_kW: float, spez_Investitionskosten_GBHKW: float = 1500, spez_Investitionskosten_HBHKW: float = 1850, el_Wirkungsgrad: float = 0.33, KWK_Wirkungsgrad: float = 0.9, min_Teillast: float = 0.7, speicher_aktiv: bool = False, Speicher_Volumen_BHKW: float = 20, T_vorlauf: float = 90, T_ruecklauf: float = 60, initial_fill: float = 0.0, min_fill: float = 0.2, max_fill: float = 0.8, spez_Investitionskosten_Speicher: float = 750, active: bool = True, opt_BHKW_min: float = 0, opt_BHKW_max: float = 1000, opt_BHKW_Speicher_min: float = 0, opt_BHKW_Speicher_max: float = 100, fuel_type: str | None = None)[source]

Initialize the base heat generator.

Parameters:

name (str) – Unique identifier for the heat generator instance

init_operation(hours: int) None[source]

Initialize operational arrays.

Parameters:

hours (int) – Simulation hours

simulate_operation(Last_L: ndarray) None[source]

Simulate CHP operation without storage (heat-led mode).

Parameters:

Last_L (numpy.ndarray) – Thermal load [kW]

Note

Heat-led with minimum part-load constraints.

simulate_storage(Last_L: ndarray, duration: float) None[source]

Simulate CHP with thermal buffer storage (backed by ThermalStorage1D).

Parameters:

Note

CHP runs at full nominal load; excess heat charges the buffer. Hysteresis control (min_fill / max_fill SOC thresholds) decides when to switch on/off. Buffer provides discharge when CHP is off.

generate(t: int, **kwargs) tuple[float, float][source]

Generate heat and electricity for time step.

Parameters:

t (int) – Time step index

Returns:

(heat_output [kW], electricity_output [kW])

Return type:

tuple

calculate_results(duration: float) None[source]

Calculate cogeneration metrics.

Parameters:

duration (float) – Time step [hours]

calculate_heat_generation_costs(economic_parameters: dict) float[source]

Calculate net heat generation costs with electricity revenue.

Parameters:

economic_parameters (dict) – Economic parameters

Returns:

Net heat generation cost [€/MWh]

Return type:

float

Note

Includes KWKG/BEW subsidies and electricity revenue offset.

calculate_environmental_impact() None[source]

Calculate environmental impact with CO2 savings.

Note

CO2 balance: fuel emissions minus grid displacement savings. Gas: 0.201 tCO2/MWh, Biomass: 0.036 tCO2/MWh

calculate(economic_parameters: dict, duration: float, load_profile: ndarray, **kwargs) dict[source]

Comprehensive CHP analysis.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Time step [hours]

  • load_profile (numpy.ndarray) – Load profile [kW]

Returns:

Results with heat, electricity, economic and environmental data

Return type:

dict

Note

Includes cogeneration simulation with electricity revenue.

set_parameters(variables: list[float], variables_order: list[str], idx: int) None[source]

Set optimization parameters.

Parameters:
  • variables (list) – Variable values

  • variables_order (list) – Variable names

  • idx (int) – Technology index

add_optimization_parameters(idx: int) tuple[list[float], list[str], list[tuple[float, float]]][source]

Define optimization parameters for CHP sizing.

Parameters:

idx (int) – Technology index

Returns:

(initial_values, variables_order, bounds)

Return type:

tuple

Note

Includes thermal capacity and storage volume (if active).

get_display_text() str[source]

Generate display text for GUI.

Returns:

Formatted configuration text

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting.

Returns:

(name, dimensions, costs, full_costs)

Return type:

tuple

class districtheatingsim.heat_generators.chp.CHPStrategy(charge_on: float, charge_off: float)[source]

Bases: BaseStrategy

Control strategy for CHP with storage.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float) – Temperature threshold for deactivation [°C]

__init__(charge_on: float, charge_off: float)[source]

Initialize control strategy.

Parameters:
  • charge_on (float) – Activation temperature [°C]

  • charge_off (float) – Deactivation temperature [°C]

Energy System Module

Multi-technology energy system modeling with optimization and visualization.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.energy_system.EnergySystem(time_steps: ndarray, load_profile: ndarray, VLT_L: ndarray, RLT_L: ndarray, TRY_data: object, COP_data: object, economic_parameters: dict)[source]

Bases: object

Multi-technology district heating system integration.

Parameters:
  • time_steps (numpy.ndarray) – Simulation time steps

  • load_profile (numpy.ndarray) – Hourly thermal load [kW]

  • VLT_L (numpy.ndarray) – Supply temperature profile [°C]

  • RLT_L (numpy.ndarray) – Return temperature profile [°C]

  • TRY_data (object) – Test Reference Year meteorological data

  • COP_data (object) – Heat pump performance data

  • economic_parameters (dict) – Economic parameters dict

Note

Supports multi-technology dispatch, storage integration and optimization.

__init__(time_steps: ndarray, load_profile: ndarray, VLT_L: ndarray, RLT_L: ndarray, TRY_data: object, COP_data: object, economic_parameters: dict)[source]

Initialize energy system.

Parameters:
  • time_steps (numpy.ndarray) – Time steps for simulation

  • load_profile (numpy.ndarray) – Hourly thermal load [kW]

  • VLT_L (numpy.ndarray) – Supply temperature [°C]

  • RLT_L (numpy.ndarray) – Return temperature [°C]

  • TRY_data (object) – Test Reference Year data

  • COP_data (object) – Heat pump performance data

  • economic_parameters (dict) – Economic parameters

add_technology(tech) None[source]

Add a heat generation technology to the energy system.

Parameters:

tech (BaseHeatGenerator) – Technology object to add.

Note

Technologies operate based on priority and control strategies.

add_storage(storage) None[source]

Add a seasonal thermal energy storage system to the energy system.

Parameters:

storage (ThermalStorageAdapter) – Seasonal Thermal Energy Storage object.

Note

Enables temporal decoupling of generation and demand for improved efficiency.

initialize_results() None[source]

Initialize the results dictionary for energy system calculations.

Note

Sets up structure for energy balance, economic, environmental, and performance results.

set_optimization_variables(variables: list, variables_order: list) None[source]

Set optimization variables for technologies.

Parameters:
  • variables (list) – Optimization variable values

  • variables_order (list) – Variable names

aggregate_results(tech_results: dict) None[source]

Aggregate technology results into system-level metrics.

Parameters:

tech_results (dict) – Technology results dictionary

calculate_mix(variables: list | None = None, variables_order: list | None = None) dict[source]

Calculate energy generation mix with technology dispatch and storage.

Parameters:
  • variables (list) – Optimization variables, defaults to []

  • variables_order (list) – Variable order, defaults to []

Returns:

System results dictionary

Return type:

dict

optimize_mix(weights: dict, num_restarts: int = 5, unmet_demand_penalty: float = 1000000.0, seed=None)[source]

Optimize energy mix for multi-objective performance.

Parameters:
  • weights (dict) – Optimization weights (WGK_Gesamt, specific_emissions_Gesamt, primärenergiefaktor_Gesamt)

  • num_restarts (int) – Number of random restarts, defaults to 5

  • unmet_demand_penalty (float) – Penalty weight on the uncovered-demand fraction added to the objective, defaults to 1e6 (see EnergySystemOptimizer for the rationale)

  • seed (int or None) – Seed for the random-restart draws; None (default) is non-deterministic, an int makes optimize_mix reproducible.

Returns:

Optimized energy system

Return type:

EnergySystem

getInitialPlotData() tuple[source]

Extract and prepare data for visualization.

Returns:

(extracted_data, initial_vars)

Return type:

tuple

plot_stack_plot(figure=None, selected_vars=None, second_y_axis=False) None[source]

Create stack plot visualization of energy system operation.

Parameters:
  • figure (matplotlib.figure.Figure, optional) – Figure object, defaults to None

  • selected_vars (list, optional) – Selected variables, defaults to None

  • second_y_axis (bool, optional) – Use second y-axis, defaults to False

plot_pie_chart(figure=None) None[source]

Create pie chart visualization of technology contributions.

Parameters:

figure (matplotlib.figure.Figure, optional) – Figure object, defaults to None

copy()[source]

Create deep copy of EnergySystem instance.

Returns:

Deep copy of energy system

Return type:

EnergySystem

to_dict() dict[source]

Convert EnergySystem to dictionary for serialization and storage.

Returns:

Dictionary representation of the complete energy system.

Return type:

dict

classmethod from_dict(data: dict)[source]

Recreate EnergySystem instance from dictionary representation.

Parameters:

data (dict) – Dictionary representation of the EnergySystem.

Returns:

Fully initialized EnergySystem object.

Return type:

EnergySystem

save_to_csv(file_path: str) None[source]

Save energy system results to CSV file.

Parameters:

file_path (str) – Path for CSV output

save_to_json(file_path: str) None[source]

Save complete EnergySystem object to JSON file for persistence.

Parameters:

file_path (str) – Path for JSON file output.

classmethod load_from_json(file_path: str)[source]

Load complete EnergySystem object from JSON file.

Parameters:

file_path (str) – Path to JSON file for loading.

Returns:

Loaded EnergySystem object with complete configuration.

Return type:

EnergySystem

class districtheatingsim.heat_generators.energy_system.EnergySystemOptimizer(initial_energy_system: EnergySystem, weights: dict[str, float], num_restarts: int = 5, unmet_demand_penalty: float = 1000000.0, seed=None)[source]

Bases: object

Multi-objective optimizer for energy system configuration.

Parameters:
  • initial_energy_system (EnergySystem) – Initial system configuration

  • weights (dict) – Optimization weights dict with ‘WGK_Gesamt’, ‘specific_emissions_Gesamt’, ‘primärenergiefaktor_Gesamt’

  • num_restarts (int, optional) – Number of random restart runs, defaults to 5

Note

Uses SLSQP with random restarts for multi-objective optimization.

__init__(initial_energy_system: EnergySystem, weights: dict[str, float], num_restarts: int = 5, unmet_demand_penalty: float = 1000000.0, seed=None)[source]

Initialize multi-objective optimizer.

Parameters:
  • initial_energy_system (EnergySystem) – Initial system configuration

  • weights (dict) – Optimization weights

  • num_restarts (int) – Number of random restarts, defaults to 5

  • unmet_demand_penalty (float) – Penalty weight applied to the uncovered-demand fraction (Restwärmebedarf / Jahreswärmebedarf) and added to the objective, defaults to 1e6. Without it the objective (WGK + emissions + primary-energy, all divided by the full annual demand) is minimised by shrinking generators: less generation → the uncovered load lands in the cost-free “Ungedeckter Bedarf” row → every term falls toward 0, so the optimum is an empty/non-covering system (verified: a CHP collapses to 0 kW / 0 % coverage). A large penalty makes covering demand strictly dominate the cost saving from undersizing.

Raises:

ValueError – If required weights missing or negative

optimize() EnergySystem[source]

Perform multi-objective optimization with random restarts.

Returns:

Optimized energy system

Return type:

EnergySystem

Raises:
  • ValueError – If no optimization parameters available

  • RuntimeError – If optimization fails in all restarts

get_optimization_summary() dict[str, float | int | bool][source]

Generate optimization summary report.

Returns:

Summary dict with success, best_objective_value, num_restarts, etc.

Return type:

dict

Gas Boiler System Module

Gas-fired boiler system with economic analysis and environmental assessment.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.gas_boiler.GasBoiler(name: str, thermal_capacity_kW: float, spez_Investitionskosten: float = 30, Nutzungsgrad: float = 0.9, active: bool = True)[source]

Bases: BaseHeatGenerator

Gas-fired boiler system for backup and peak load.

Parameters:
  • name (str) – Unique identifier

  • thermal_capacity_kW (float) – Nominal thermal power [kW]

  • spez_Investitionskosten (float, optional) – Specific investment costs [€/kW], defaults to 30

  • Nutzungsgrad (float, optional) – Thermal efficiency [-], defaults to 0.9

  • active (bool, optional) – Initial operational state, defaults to True

Note

Simple load-following operation without minimum load constraints.

__init__(name: str, thermal_capacity_kW: float, spez_Investitionskosten: float = 30, Nutzungsgrad: float = 0.9, active: bool = True)[source]

Initialize gas boiler system.

Parameters:
  • name (str) – System identifier

  • thermal_capacity_kW (float) – Thermal power [kW]

  • spez_Investitionskosten (float) – Specific costs [€/kW], defaults to 30

  • Nutzungsgrad (float) – Efficiency [-], defaults to 0.9

  • active (bool) – Operational state, defaults to True

init_operation(hours: int) None[source]

Initialize operational arrays.

Parameters:

hours (int) – Simulation hours

calculate_operation(Last_L: ndarray) None[source]

Simulate gas boiler with load-following strategy.

Parameters:

Last_L (numpy.ndarray) – Thermal load [kW]

Note

Simple on/off without minimum load constraints.

generate(t: int, **kwargs) tuple[float, float][source]

Generate heat for time step.

Parameters:
  • t (int) – Time step index

  • remaining_load (float) – Remaining demand [kW]

Returns:

(heat_output [kW], electricity_output [kW])

Return type:

tuple

calculate_results(duration: float) None[source]

Calculate operational metrics.

Parameters:

duration (float) – Time step [hours]

calculate_heat_generation_cost(economic_parameters: dict) None[source]

Calculate heat generation costs.

Parameters:

economic_parameters (dict) – Economic parameters (prices, rates)

Note

Low investment costs but high fuel costs.

calculate_environmental_impact() None[source]

Calculate environmental impact metrics.

Note

Natural gas: 0.201 tCO2/MWh, primary energy factor 1.1

calculate(economic_parameters: dict, duration: float, load_profile: ndarray, **kwargs) dict[source]

Comprehensive system analysis.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Time step [hours]

  • load_profile (numpy.ndarray) – Load profile [kW]

Returns:

Results dictionary

Return type:

dict

Note

Includes thermal simulation, economic and environmental analysis.

set_parameters(variables: list[float], variables_order: list[str], idx: int) None[source]

Set optimization parameters.

Note

Gas boiler typically has no optimization parameters (fixed capacity).

add_optimization_parameters(idx: int) tuple[list[float], list[str], list[tuple[float, float]]][source]

Define optimization parameters.

Parameters:

idx (int) – Technology index

Returns:

Empty (no optimization for gas boiler)

Return type:

tuple

get_display_text() str[source]

Generate display text for GUI.

Returns:

Formatted configuration text

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting.

Returns:

(name, dimensions, costs, full_costs)

Return type:

tuple

class districtheatingsim.heat_generators.gas_boiler.GasBoilerStrategy(charge_on: float, charge_off: float | None = None)[source]

Bases: BaseStrategy

Control strategy for gas boiler backup operation.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float, optional) – Temperature threshold for deactivation [°C], optional

__init__(charge_on: float, charge_off: float | None = None)[source]

Initialize control strategy.

Parameters:
  • charge_on (float) – Activation temperature [°C]

  • charge_off (float) – Deactivation temperature [°C]

decide_operation(current_state: float, upper_storage_temp: float, lower_storage_temp: float, remaining_demand: float) bool[source]

Decide gas boiler operation based on storage and demand.

Parameters:
  • current_state (float) – Current state

  • upper_storage_temp (float) – Storage temperature [°C]

  • lower_storage_temp (float) – Lower storage temperature [°C]

  • remaining_demand (float) – Remaining demand [kW]

Returns:

True if boiler should operate

Return type:

bool

Note

Activates if storage temp < threshold AND demand exists.

Geothermal Heat Pump System Module

Geothermal heat pump modeling with borehole field design and drilling cost analysis.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.geothermal_heat_pump.Geothermal(name: str, Fläche: float, Bohrtiefe: float, Temperatur_Geothermie: float, spez_Bohrkosten: float = 100, spez_Entzugsleistung: float = 50, Vollbenutzungsstunden: float = 2400, Abstand_Sonden: float = 10, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, min_area_geothermal: float = 0, max_area_geothermal: float = 5000, min_depth_geothermal: float = 0, max_depth_geothermal: float = 400)[source]

Bases: HeatPump

Geothermal heat pump with borehole field modeling.

Parameters:
  • name (str) – Unique identifier

  • Fläche (float) – Borehole field area [m²]

  • Bohrtiefe (float) – Drilling depth [m]

  • Temperatur_Geothermie (float) – Ground temperature [°C]

  • spez_Bohrkosten (float, optional) – Drilling costs [€/m], defaults to 100

  • spez_Entzugsleistung (float, optional) – Heat extraction [W/m], defaults to 50

Note

Stable source temperature for high seasonal efficiency.

__init__(name: str, Fläche: float, Bohrtiefe: float, Temperatur_Geothermie: float, spez_Bohrkosten: float = 100, spez_Entzugsleistung: float = 50, Vollbenutzungsstunden: float = 2400, Abstand_Sonden: float = 10, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, min_area_geothermal: float = 0, max_area_geothermal: float = 5000, min_depth_geothermal: float = 0, max_depth_geothermal: float = 400) None[source]

Initialize geothermal heat pump.

Parameters:
  • name (str) – System identifier

  • Fläche (float) – Available area [m²]

  • Bohrtiefe (float) – Drilling depth [m]

  • Temperatur_Geothermie (float) – Ground temperature [°C]

  • spez_Bohrkosten (float) – Drilling costs [€/m], defaults to 100

  • spez_Entzugsleistung (float) – Extraction power [W/m], defaults to 50

calculate_operation(Last_L: ndarray, VLT_L: ndarray, COP_data: ndarray) None[source]

Calculate operation with thermal sustainability constraints.

Parameters:

Note

Uses iterative method to balance thermal extraction with sustainability.

generate(t: int, **kwargs) tuple[float, float][source]

Generate heat for time step.

Parameters:
  • t (int) – Time step index

  • VLT_L (float) – Required flow temperature [°C]

Returns:

(heat_output [kW], electricity_consumption [kW])

Return type:

tuple

Note

Checks sustainable extraction limits and temperature constraints.

calculate_results(duration: float) None[source]

Calculate performance metrics.

Parameters:

duration (float) – Time step [hours]

calculate(economic_parameters: dict[str, Any], duration: float, load_profile: ndarray, **kwargs) dict[str, Any][source]

Comprehensive geothermal heat pump analysis.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Time step [hours]

  • load_profile (numpy.ndarray) – Load profile [kW]

Returns:

Results with performance, economic and environmental data

Return type:

dict

Note

Includes borehole field modeling and thermal sustainability.

set_parameters(variables: list, variables_order: list, idx: int) None[source]

Set optimization parameters.

Parameters:
  • variables (list) – Variable values

  • variables_order (list) – Variable names

  • idx (int) – Technology index

add_optimization_parameters(idx: int) tuple[list, list, list][source]

Define optimization parameters for borehole field sizing.

Parameters:

idx (int) – Technology index

Returns:

(initial_values, variables_order, bounds)

Return type:

tuple

Note

Optimizes area and drilling depth.

get_display_text() str[source]

Generate display text for GUI.

Returns:

Formatted configuration text

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting.

Returns:

(name, dimensions, costs, full_costs)

Return type:

tuple

JSON encoder for energy-system serialization.

GUI-free json.JSONEncoder that handles the non-standard types produced by the domain core (numpy scalars/arrays, pandas DataFrames, heat-generator/storage objects). Lives here — not in the gui package — so that energy_system.save_to_json does not drag PyQt6 into the GUI-free domain core (BACKLOG B5). The GUI re-exports it from EnergySystemTab/_10_utilities.py.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.json_encoder.CustomJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)[source]

Bases: JSONEncoder

Custom JSON Encoder for handling numpy arrays, pandas DataFrames, and custom objects.

default(obj)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return super().default(o)

Photovoltaics Module

Photovoltaic power generation modeling based on EU PVGIS methodology.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.heat_generators.photovoltaics.Calculate_PV(TRY_data: str, Gross_area: float, Longitude: float, STD_Longitude: float, Latitude: float, Albedo: float, East_West_collector_azimuth_angle: float, Collector_tilt_angle: float) tuple[float, float, ndarray][source]

Calculate photovoltaic power output based on EU PVGIS methodology.

Parameters:
  • TRY_data (str) – Path to Test Reference Year data

  • Gross_area (float) – PV system area [m²]

  • Longitude (float) – Geographic longitude [degrees]

  • STD_Longitude (float) – Standard longitude for time zone [degrees]

  • Latitude (float) – Geographic latitude [degrees]

  • Albedo (float) – Ground reflection coefficient [-]

  • East_West_collector_azimuth_angle (float) – Azimuth angle [degrees]

  • Collector_tilt_angle (float) – Tilt angle from horizontal [degrees]

Returns:

(yield_kWh, P_max, P_L)

Return type:

tuple

districtheatingsim.heat_generators.photovoltaics.azimuth_angle(direction: str) float | None[source]

Convert cardinal direction to azimuth angle.

Parameters:

direction (str) – Cardinal direction (N, S, E, W, O, NE, etc.)

Returns:

Azimuth angle [degrees] or None

Return type:

float or None

districtheatingsim.heat_generators.photovoltaics.calculate_building(TRY_data: str, building_data: str, output_filename: str) None[source]

Calculate photovoltaic yield for multiple buildings.

Parameters:
  • TRY_data (str) – Path to Test Reference Year data

  • building_data (str) – Path to building CSV (building_id, roof_area, orientation)

  • output_filename (str) – Path for results CSV output

Power-to-Heat System Module

Electric heating system modeling with storage integration and control strategies.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.power_to_heat.PowerToHeat(name: str, thermal_capacity_kW: float = 1000, spez_Investitionskosten: float = 30, Nutzungsgrad: float = 0.9, active: bool = True)[source]

Bases: BaseHeatGenerator

Electric heating system with grid integration.

Parameters:
  • name (str) – Unique identifier

  • thermal_capacity_kW (float, optional) – Maximum thermal capacity [kW], defaults to 1000

  • spez_Investitionskosten (float, optional) – Specific investment costs [€/kW], defaults to 30

  • Nutzungsgrad (float, optional) – Electric heating efficiency [-], defaults to 0.9

Note

Near-instantaneous response for demand response and grid services.

__init__(name: str, thermal_capacity_kW: float = 1000, spez_Investitionskosten: float = 30, Nutzungsgrad: float = 0.9, active: bool = True) None[source]

Initialize power-to-heat system.

Parameters:
  • name (str) – Unique identifier

  • thermal_capacity_kW (float) – Thermal capacity [kW], defaults to 1000

  • spez_Investitionskosten (float) – Specific investment costs [€/kW], defaults to 30

  • Nutzungsgrad (float) – Electric heating efficiency [-], defaults to 0.9

  • active (bool) – Activation status, defaults to True

init_operation(hours: int) None[source]

Initialize operational data arrays for simulation.

Parameters:

hours (int) – Number of simulation hours.

Note

Initializes time-series arrays and resets calculation flags.

simulate_operation(Last_L: ndarray) None[source]

Simulate power-to-heat system operation for given load profile.

Parameters:

Last_L (numpy.ndarray) – Thermal load demand time series [kW].

Note

System operates when demand exists, limited by thermal capacity. Electrical consumption calculated using efficiency factor.

generate(t: int, **kwargs) tuple[float, float][source]

Generate thermal power for specific time step.

Parameters:
  • t (int) – Current time step index.

  • kwargs (dict) – Additional parameters (remaining_load).

Returns:

Heat generation [kW] and electricity consumption [kW].

Return type:

tuple of float

Note

Heat output limited by thermal_capacity_kW and remaining demand.

calculate_results(duration: float) None[source]

Calculate aggregated performance metrics.

Parameters:

duration (float) – Time step duration [hours]

calculate_heat_generation_cost(economic_parameters: dict[str, Any]) None[source]

Calculate heat generation costs using VDI 2067 methodology.

Parameters:

economic_parameters (dict) – Economic analysis parameters.

Note

Includes capital costs, electricity costs, and operational expenses. Uses annuity method for levelized cost calculation.

calculate_environmental_impact() None[source]

Calculate environmental impact of power-to-heat operation.

Note

CO2 emissions from electricity grid and primary energy consumption. Uses grid emission factor and primary energy factor.

calculate(economic_parameters: dict[str, Any], duration: float, load_profile: ndarray, **kwargs) dict[str, Any][source]

Comprehensive calculation of power-to-heat performance and economics.

Parameters:
  • economic_parameters (dict) – Economic analysis parameters.

  • duration (float) – Simulation time step duration [hours].

  • load_profile (numpy.ndarray) – Thermal load demand time series [kW].

  • kwargs (dict) – Additional parameters.

Returns:

Performance, economic, and environmental results.

Return type:

dict

Note

Performs operational simulation, economic evaluation, and environmental assessment.

set_parameters(variables: list, variables_order: list, idx: int) None[source]

Set optimization parameters (interface compatibility).

Parameters:
  • variables (list) – Optimization variable values

  • variables_order (list) – Variable order

  • idx (int) – Technology index

add_optimization_parameters(idx: int) tuple[list, list, list][source]

Define optimization parameters for power-to-heat system.

Parameters:

idx (int) – Technology index.

Returns:

Empty lists for initial values, variable names, and bounds.

Return type:

tuple

Note

No optimization parameters for basic power-to-heat systems.

get_display_text() str[source]

Generate human-readable display text for system configuration.

Returns:

Formatted display text with system parameters.

Return type:

str

Note

Includes system name and specific investment costs.

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting and analysis.

Returns:

Name, technical dimensions, cost breakdown, and total investment.

Return type:

tuple of str

Note

Includes thermal capacity and investment costs.

class districtheatingsim.heat_generators.power_to_heat.PowerToHeatStrategy(charge_on: float, charge_off: float | None = None)[source]

Bases: BaseStrategy

Control strategy for power-to-heat with storage.

Parameters:
  • charge_on (float) – Temperature threshold for activation [°C]

  • charge_off (float, optional) – Temperature threshold for deactivation [°C], optional

__init__(charge_on: float, charge_off: float | None = None) None[source]

Initialize power-to-heat control strategy.

Parameters:
  • charge_on (float) – Activation temperature threshold [°C]

  • charge_off (float, optional) – Deactivation temperature threshold [°C], defaults to None

decide_operation(current_state: float, upper_storage_temp: float, lower_storage_temp: float, remaining_demand: float) bool[source]

Decide whether to operate power-to-heat system based on control strategy.

Parameters:
  • current_state (float) – Current system state (reserved).

  • upper_storage_temp (float) – Current upper storage temperature [°C].

  • lower_storage_temp (float) – Current lower storage temperature [°C].

  • remaining_demand (float) – Remaining heat demand [kW].

Returns:

True if system should operate, False otherwise.

Return type:

bool

Note

Operates if temperature below charge_on threshold and demand exists.

Energy-system result records.

One TechnologyResult per row of the energy-system result, replacing the eight hand-maintained parallel lists in energy_system.py (BACKLOG C4). The record is the single source of truth; the legacy German results lists (techs, Wärmemengen, Anteile …) are projected from it for the GUI and serialization. Appending one record keeps every projected list in lockstep, so the divergence bugs that motivated this are structurally impossible.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.results.TechnologyResult(name: str, heat_output_kW: ndarray, heat_amount_MWh: float, share: float, heat_generation_cost: float, specific_co2: float, primary_energy: float, color: str)[source]

Bases: object

A single technology’s (or storage/unmet-demand row’s) contribution.

Field → legacy results list it projects to:

  • nametechs

  • heat_output_kWWärmeleistung_L

  • heat_amount_MWhWärmemengen

  • shareAnteile

  • heat_generation_costWGK

  • specific_co2specific_emissions_L

  • primary_energyprimärenergie_L

  • colorcolors

name: str
heat_output_kW: ndarray
heat_amount_MWh: float
share: float
heat_generation_cost: float
specific_co2: float
primary_energy: float
color: str
__init__(name: str, heat_output_kW: ndarray, heat_amount_MWh: float, share: float, heat_generation_cost: float, specific_co2: float, primary_energy: float, color: str) None

River Water Heat Pump System Module

River water heat pump modeling with temperature-dependent performance and intake costs.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.river_heat_pump.RiverHeatPump(name: str, Wärmeleistung_FW_WP: float, Temperatur_FW_WP: float | ndarray, dT: float = 0, spez_Investitionskosten_Flusswasser: float = 1000, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, opt_power_min: float = 0, opt_power_max: float = 500)[source]

Bases: HeatPump

River water heat pump with intake infrastructure.

Parameters:
  • name (str) – Unique identifier

  • Wärmeleistung_FW_WP (float) – Thermal capacity [kW]

  • Temperatur_FW_WP (float or numpy.ndarray) – River water temperature [°C], constant or time-series

  • spez_Investitionskosten_Flusswasser (float, optional) – River system costs [€/kW], defaults to 1000

Note

Supports variable river temperature profiles for seasonal analysis.

__init__(name: str, Wärmeleistung_FW_WP: float, Temperatur_FW_WP: float | ndarray, dT: float = 0, spez_Investitionskosten_Flusswasser: float = 1000, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, opt_power_min: float = 0, opt_power_max: float = 500) None[source]

Initialize river water heat pump.

Parameters:
  • name (str) – System identifier

  • Wärmeleistung_FW_WP (float) – Thermal capacity [kW]

  • Temperatur_FW_WP (float or numpy.ndarray) – River water temperature [°C]

  • spez_Investitionskosten_Flusswasser (float) – River system costs [€/kW], defaults to 1000

calculate_heat_pump(VLT_L: ndarray, COP_data: ndarray) tuple[ndarray, ndarray, ndarray, ndarray][source]

Calculate heat pump performance.

Parameters:
Returns:

(cooling_power, electric_power, achievable_temp, COP)

Return type:

tuple

Note

Uses river water temperature as heat source.

calculate_operation(Last_L: ndarray, VLT_L: ndarray, COP_data: ndarray) None[source]

Calculate operation with load and temperature constraints.

Parameters:
generate(t: int, **kwargs) tuple[float, float][source]

Generate heat for time step.

Parameters:
  • t (int) – Time step index

  • VLT_L (float) – Required flow temperature [°C]

Returns:

(heat_output [kW], electricity_consumption [kW])

Return type:

tuple

calculate_results(duration: float) None[source]

Calculate performance metrics.

Parameters:

duration (float) – Time step [hours]

calculate(economic_parameters: dict[str, Any], duration: float, load_profile: ndarray, **kwargs) dict[str, Any][source]

Comprehensive river heat pump analysis.

Parameters:
  • economic_parameters (dict) – Economic parameters

  • duration (float) – Time step [hours]

  • load_profile (numpy.ndarray) – Load profile [kW]

Returns:

Results dictionary

Return type:

dict

Note

Includes performance, economic and environmental analysis.

set_parameters(variables: list, variables_order: list, idx: int) None[source]

Set optimization parameters.

Parameters:
  • variables (list) – Optimization variable values

  • variables_order (list) – Variable order

  • idx (int) – Technology index

add_optimization_parameters(idx: int) tuple[list, list, list][source]

Define optimization parameters for capacity sizing.

Parameters:

idx (int) – Technology index

Returns:

(initial_values, variables_order, bounds)

Return type:

tuple

get_display_text() str[source]

Generate human-readable display text.

Returns:

Formatted display text with system parameters

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting.

Returns:

(name, dimensions, costs, full_costs)

Return type:

tuple of str

Solar Radiation Calculation Module

Solar radiation calculations for tilted collectors using Test Reference Year data.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

districtheatingsim.heat_generators.solar_radiation.calculate_solar_radiation(time_steps: ndarray, global_radiation: ndarray, direct_radiation: ndarray, Longitude: float, STD_Longitude: float, Latitude: float, Albedo: float, East_West_collector_azimuth_angle: float, Collector_tilt_angle: float, IAM_W: dict[float, float] | None = None, IAM_N: dict[float, float] | None = None) tuple[ndarray, ndarray | None, ndarray, ndarray][source]

Calculate solar radiation components for tilted collectors using Test Reference Year data.

Parameters:
  • time_steps (numpy.ndarray) – Time series as datetime64 array [hours]

  • global_radiation (numpy.ndarray) – Global horizontal irradiance [W/m²]

  • direct_radiation (numpy.ndarray) – Direct normal irradiance [W/m²]

  • Longitude (float) – Site longitude [degrees], range -180° to +180°

  • STD_Longitude (float) – Standard time zone longitude [degrees] (e.g., 15° for CET)

  • Latitude (float) – Site latitude [degrees], range -90° to +90°

  • Albedo (float) – Ground reflectance factor [-], typical values 0.2 (grass), 0.8 (snow)

  • East_West_collector_azimuth_angle (float) – Collector azimuth [degrees], 0° = south

  • Collector_tilt_angle (float) – Collector tilt from horizontal [degrees], 0-90°

  • IAM_W (Optional[Dict[float, float]]) – Incidence Angle Modifier lookup table for East-West direction {angle: factor}

  • IAM_N (Optional[Dict[float, float]]) – Incidence Angle Modifier lookup table for North-South direction {angle: factor}

Returns:

(GT_total[W/m²], K_beam[-], Gb_tilted[W/m²], Gd_tilted[W/m²])

Return type:

Tuple[np.ndarray, Optional[np.ndarray], np.ndarray, np.ndarray]

Note

Implements comprehensive solar geometry, atmospheric effects, and collector-specific IAM corrections. Total radiation GT = beam + diffuse sky + ground-reflected components.

Solar Thermal Collector System Module

Solar thermal collector modeling with flat-plate and vacuum tube technologies.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

Note

Based on Scenocalc 2.0 solar thermal model (https://www.scfw.de)

class districtheatingsim.heat_generators.solar_thermal.SolarThermal(name: str, bruttofläche_STA: float, vs: float, Typ: str, kosten_speicher_spez: float = 750, kosten_fk_spez: float = 430, kosten_vrk_spez: float = 590, Tsmax: float = 90, Longitude: float = -14.4222, STD_Longitude: float = -15, Latitude: float = 51.1676, East_West_collector_azimuth_angle: float = 0, Collector_tilt_angle: float = 36, Tm_rl: float = 60, Qsa: float = 0, Vorwärmung_K: float = 8, DT_WT_Solar_K: float = 5, DT_WT_Netz_K: float = 5, opt_volume_min: float = 0, opt_volume_max: float = 200, opt_area_min: float = 0, opt_area_max: float = 2000, active: bool = True)[source]

Bases: BaseHeatGenerator

Solar thermal collector system with storage.

Parameters:
  • name (str) – Unique identifier

  • bruttofläche_STA (float) – Gross collector area [m²]

  • vs (float) – Storage volume [m³]

  • Typ (str) – Collector type (“Flachkollektor” or “Vakuumröhrenkollektor”)

  • kosten_speicher_spez (float, optional) – Storage costs [€/m³], defaults to 750

  • kosten_fk_spez (float, optional) – Flat-plate costs [€/m²], defaults to 430

Note

Includes detailed solar radiation calculations and efficiency modeling.

__init__(name: str, bruttofläche_STA: float, vs: float, Typ: str, kosten_speicher_spez: float = 750, kosten_fk_spez: float = 430, kosten_vrk_spez: float = 590, Tsmax: float = 90, Longitude: float = -14.4222, STD_Longitude: float = -15, Latitude: float = 51.1676, East_West_collector_azimuth_angle: float = 0, Collector_tilt_angle: float = 36, Tm_rl: float = 60, Qsa: float = 0, Vorwärmung_K: float = 8, DT_WT_Solar_K: float = 5, DT_WT_Netz_K: float = 5, opt_volume_min: float = 0, opt_volume_max: float = 200, opt_area_min: float = 0, opt_area_max: float = 2000, active: bool = True)[source]

Initialize solar thermal collector system with technical and economic parameters.

Parameters:
  • name (str) – Unique identifier

  • bruttofläche_STA (float) – Gross collector area [m²]

  • vs (float) – Storage volume [m³]

  • Typ (str) – Collector type (“Flachkollektor” or “Vakuumröhrenkollektor”)

  • kosten_speicher_spez (float) – Storage costs [€/m³], defaults to 750

  • kosten_fk_spez (float) – Flat-plate costs [€/m²], defaults to 430

  • kosten_vrk_spez (float) – Vacuum tube costs [€/m²], defaults to 590

init_calculation_constants() None[source]

Initialize technology-specific calculation constants for collector performance modeling.

Note

Sets efficiency parameters, heat loss coefficients, IAM data, and geometric factors based on collector type. Flat-plate: η0=0.763, c1=1.969 W/(m²·K). Vacuum tube: η0=0.693, c1=0.583 W/(m²·K).

init_operation(hours: int) None[source]

Initialize operational arrays for annual simulation.

Parameters:

hours (int) – Number of simulation hours (typically 8760)

calculate_heat_generation_costs(economic_parameters: dict) float[source]

Calculate levelized heat generation costs with subsidy integration.

Parameters:

economic_parameters (Dict) – Economic parameters (interest_rate, inflation_rate, subsidy_eligibility, etc.)

Returns:

Heat generation cost [€/MWh]

Return type:

float

Note

Includes BEW program: 40% investment cost reduction and 10 €/MWh operational incentive for 10 years.

calculate_environmental_impact() None[source]

Calculate environmental impact metrics (zero CO2 emissions, zero primary energy factor).

Note

Solar thermal has zero direct emissions and no fossil fuel dependency.

calculate_solar_thermal_with_storage(Last_L: ndarray, VLT_L: ndarray, RLT_L: ndarray, TRY_data: tuple, time_steps: ndarray, duration: float) None[source]

Hourly solar thermal simulation with storage integration.

Parameters:
  • Last_L (numpy.ndarray) – Heat demand profile [kW]

  • VLT_L (numpy.ndarray) – Supply temperature [°C]

  • RLT_L (numpy.ndarray) – Return temperature [°C]

  • TRY_data (Tuple) – Weather data (air_temp, wind_speed, direct_rad, global_rad)

  • time_steps (numpy.ndarray) – Time step array

  • duration (float) – Time step duration [hours]

Note

Calculates solar radiation, collector efficiency, storage stratification, and heat generation.

generate(t: int, **kwargs) tuple[float, float][source]

Generate instantaneous heat output with detailed collector and storage modeling.

Parameters:
  • t (int) – Current time step index

  • kwargs – Simulation parameters (remaining_load, storage temps, TRY_data, time_steps, etc.)

Returns:

(heat_output[kW], electrical_output[kW]=0)

Return type:

Tuple[float, float]

Note

Implements dual collector A/B approach, temperature stratification, and stagnation prevention.

calculate(economic_parameters: dict[str, float | str], duration: float, load_profile: ndarray, **kwargs) dict[str, str | float | ndarray][source]

Comprehensive system analysis including performance and economic evaluation.

Parameters:
  • economic_parameters (Dict[str, Union[float, str]]) – Economic parameters (interest_rate, inflation_rate, subsidies, etc.)

  • duration (float) – Time step duration [hours]

  • load_profile (numpy.ndarray) – Heat demand profile [kW]

  • kwargs – VLT_L, RLT_L, TRY_data, time_steps

Returns:

Results dict with Wärmemenge, Wärmeleistung_L, WGK, operational stats, environmental data

Return type:

Dict[str, Union[str, float, np.ndarray]]

Note

Performs thermal simulation, operational analysis, economic cost assessment, and environmental evaluation.

set_parameters(variables: list[float], variables_order: list[str], idx: int) None[source]

Set optimization parameters from optimizer variable list.

Parameters:
  • variables (List[float]) – Optimization variable values

  • variables_order (List[str]) – Variable names corresponding to values

  • idx (int) – Technology index for unique parameter identification

Note

Updates bruttofläche_STA and vs from variables with names f”bruttofläche_STA_{idx}” and f”vs_{idx}”.

add_optimization_parameters(idx: int) tuple[list[float], list[str], list[tuple[float, float]]][source]

Define optimization parameters for solar thermal system sizing.

Parameters:

idx (int) – Technology index for unique parameter names

Returns:

(initial_values, variables_order, bounds)

Return type:

Tuple[List[float], List[str], List[Tuple[float, float]]]

Note

Returns [bruttofläche_STA, vs] with bounds from opt_area_min/max and opt_volume_min/max.

get_display_text() str[source]

Generate formatted display text for GUI representation.

Returns:

Formatted text with key system parameters

Return type:

str

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting and documentation.

Returns:

(name, dimensions, costs, full_costs)

Return type:

Tuple[str, str, str, str]

classmethod from_dict(data: dict[str, Any]) SolarThermal[source]

Create SolarThermal object from dictionary representation.

Parameters:

data (Dict[str, Any]) – Dictionary containing SolarThermal attributes

Returns:

Restored SolarThermal object

Return type:

SolarThermal

Note

Ensures IAM dictionaries are properly restored when loading saved objects.

class districtheatingsim.heat_generators.solar_thermal.SolarThermalStrategy(charge_on: int, charge_off: int | None = None)[source]

Bases: BaseStrategy

Control strategy for solar thermal systems.

Parameters:
  • charge_on (int) – Temperature threshold for activation [°C]

  • charge_off (int, optional) – Temperature threshold for deactivation [°C], optional

Note

Operates continuously when solar irradiation available.

__init__(charge_on: int, charge_off: int | None = None)[source]

Initialize solar thermal control strategy.

Parameters:
  • charge_on (int) – Activation temperature threshold [°C]

  • charge_off (int, optional) – Deactivation temperature threshold [°C], optional

decide_operation(current_state: float, upper_storage_temp: float, lower_storage_temp: float, remaining_demand: float) bool[source]

Decide solar thermal operation (always True for renewable energy priority).

Parameters:
  • current_state (float) – Current system state (not used)

  • upper_storage_temp (float) – Upper storage temperature [°C] (not used)

  • lower_storage_temp (float) – Lower storage temperature [°C] (not used)

  • remaining_demand (float) – Remaining heat demand [kW] (not used)

Returns:

Always True (renewable energy priority strategy)

Return type:

bool

Thermal Storage Adapter Module

Wrapper around ThermalStorage1D from the thermal-energy-storage-1d package, exposing the interface required by EnergySystem and the GUI.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.thermal_storage.ThermalStorageAdapter(name: str, volume: float = 1000.0, height: float = 10.0, T_min: float = 40.0, T_max: float = 95.0, initial_temp: float = 60.0, n_nodes: int = 50, geometry_type: str = 'cylinder', loss_model_type: str = 'constant', U_loss: float = 0.3, U_top: float = 0.3, U_side: float = 0.06, U_bottom: float = 0.4, T_ambient: float = 10.0, z_ground: float = 2.0, fluid_type: str = 'water', rho: float = 977.8, cp: float = 4187.0, lambda_fluid: float = 0.663, solver: str = 'implicit', advection_scheme: str = 'tvd', buoyancy: bool = True, lambda_eff_factor: float = 5.0, spez_Investitionskosten: float = 50.0, Nutzungsdauer: int = 30, f_Inst: float = 1.0, f_W_Insp: float = 1.0, Bedienaufwand: float = 0.0, hours: int = 8760, T_charge: float = 90.0, T_discharge_return: float = 50.0)[source]

Bases: BaseHeatGenerator

Seasonal / large-scale thermal storage backed by ThermalStorage1D.

Exposes the interface expected by EnergySystem.calculate_mix() and the GUI, while delegating all physics to the 1D stratified model.

Parameters:
  • name (str) – Display name.

  • volume (float) – Tank volume [m³].

  • height (float) – Tank height [m].

  • T_min (float) – Minimum useful temperature for SOC calculation [°C].

  • T_max (float) – Maximum operating temperature [°C].

  • initial_temp (float) – Uniform initial temperature [°C].

  • n_nodes (int) – Number of vertical nodes (default 50).

  • geometry_type (str) – "cylinder", "truncated_cone", or "truncated_pyramid".

  • loss_model_type (str) – "constant", "split", or "ground".

  • U_loss (float) – Overall heat-loss coefficient [W/m²K] (used for "constant").

  • U_top (float) – Surface-specific U-values [W/m²K] (used for "split").

  • U_side (float) – Surface-specific U-values [W/m²K] (used for "split").

  • U_bottom (float) – Surface-specific U-values [W/m²K] (used for "split").

  • T_ambient (float) – Ambient / ground-surface temperature [°C].

  • z_ground (float) – Depth of tank bottom below ground [m] (used for "ground").

  • fluid_type (str) – "water" (temperature-dependent) or "constant".

  • rho (float) – Constant fluid properties (used when fluid_type="constant").

  • cp (float) – Constant fluid properties (used when fluid_type="constant").

  • lambda_fluid (float) – Constant fluid properties (used when fluid_type="constant").

  • solver (str) – "implicit" (default, unconditionally stable) or "explicit".

  • advection_scheme (str) – "tvd" (default) or "upwind".

  • buoyancy (bool) – Enable convective mixing correction (default True).

  • spez_Investitionskosten (float) – Specific investment cost [€/m³] for cost calculation.

  • hours (int) – Simulation horizon [h] (default 8760).

__init__(name: str, volume: float = 1000.0, height: float = 10.0, T_min: float = 40.0, T_max: float = 95.0, initial_temp: float = 60.0, n_nodes: int = 50, geometry_type: str = 'cylinder', loss_model_type: str = 'constant', U_loss: float = 0.3, U_top: float = 0.3, U_side: float = 0.06, U_bottom: float = 0.4, T_ambient: float = 10.0, z_ground: float = 2.0, fluid_type: str = 'water', rho: float = 977.8, cp: float = 4187.0, lambda_fluid: float = 0.663, solver: str = 'implicit', advection_scheme: str = 'tvd', buoyancy: bool = True, lambda_eff_factor: float = 5.0, spez_Investitionskosten: float = 50.0, Nutzungsdauer: int = 30, f_Inst: float = 1.0, f_W_Insp: float = 1.0, Bedienaufwand: float = 0.0, hours: int = 8760, T_charge: float = 90.0, T_discharge_return: float = 50.0)[source]

Initialize the base heat generator.

Parameters:

name (str) – Unique identifier for the heat generator instance

simulate_stratified_temperature_mass_flows(t: int, Q_in: float, Q_out: float, T_Q_in_flow: float, T_Q_out_return: float) None[source]

Advance storage by one timestep (dt = 3600 s).

Parameters:
  • t (int) – Current simulation timestep index.

  • Q_in (float) – Total heat delivered by all generators [kW].

  • Q_out (float) – Total network heat demand [kW].

  • T_Q_in_flow (float) – Network supply temperature passed by EnergySystem [°C]. Not used for mass-flow calculation — the fixed self.T_charge (generator-side temperature) is used instead, so that a variable network supply curve (“Gleitung”) does not inadvertently cool the storage in summer.

  • T_Q_out_return (float) – Network return temperature passed by EnergySystem [°C]. Not used directly — self.T_discharge_return is used instead.

Notes

The storage is either charging or discharging in a given timestep:

  • Charging (generators over-produce): excess Q_in Q_out enters the storage at the top at self.T_charge (fixed generator supply temperature, e.g. 90 °C).

  • Discharging (demand exceeds generation): deficit Q_out Q_in is drawn from the storage top; cold return enters at the bottom at self.T_discharge_return.

Port assignments (StorageInputs.two_port):
  • charge_in : z = height (top), m_dot > 0, T_in = T_charge

  • charge_out : z = 0 (bottom), m_dot < 0 → outlet T = T_bottom

  • discharge_in : z = 0 (bottom), m_dot > 0, T_in = T_discharge_return

  • discharge_out : z = height (top), m_dot < 0 → outlet T = T_top

property Q_net_storage_flow: ndarray

positive = discharge, negative = charge.

Type:

Net heat flow [kW]

current_storage_temperatures(t: int) tuple[source]

Return (upper_temp, lower_temp) [°C] at timestep t, used by generator control strategies via EnergySystem.calculate_mix().

upper_temp = T_top (hot side – used for charge_on threshold). lower_temp = T_middle (middle node – strategy turn-off threshold,

better indicator of overall charge state than T_bottom).

current_storage_state(t: int, T_Q_out_return: float, T_Q_in_flow: float) tuple[source]

Return (storage_fraction, available_energy_kWh, max_energy_kWh) at timestep t.

calculate_efficiency(Q_in_array: ndarray) None[source]

Compute round-trip efficiency and store on self.efficiency.

calculate_costs(Wärmemenge_MWh: float, economic_parameters: dict) None[source]

Compute the storage’s annuity and heat-generation cost (VDI 2067).

Capital-bound costs come from the tank investment (volume × spez_Investitionskosten); the annual maintenance share is the f_W_Insp factor folded into the annuity. There are no demand-bound (fuel) costs – the energy to cover the storage losses is paid for on the generator side, so charging it here too would double-count.

Parameters:
  • Wärmemenge_MWh – Annual heat discharged from the storage [MWh].

  • economic_parameters – Shared economic-parameters dict.

get_display_text() str[source]
extract_tech_data() tuple[source]
to_dict() dict[source]

Convert heat generator to dictionary for serialization.

Returns:

Dictionary representation excluding non-serializable attributes

Return type:

dict

Note

Numpy arrays are converted to lists for JSON compatibility.

classmethod from_dict(data: dict) ThermalStorageAdapter | None[source]

Deserialize from a saved dict.

Returns None and logs a warning when an old-format config is detected, so the caller can inform the user to re-configure the storage.

class districtheatingsim.heat_generators.thermal_storage.BufferStorage(volume: float, T_flow: float = 90.0, T_return: float = 60.0, U_loss: float = 0.5, T_ambient: float = 15.0)[source]

Bases: object

Simple buffer tank backed by ThermalStorage1D.

Replaces the inline scalar energy-bucket (speicher_fill / speicher_kapazitaet) previously embedded in CHP and BiomassBoiler dispatch loops.

Parameters:
  • volume (float) – Tank volume [m³].

  • T_flow (float) – Generator supply temperature [°C] (sets T_max for SOC).

  • T_return (float) – Generator return temperature [°C] (sets T_min for SOC).

  • U_loss (float) – Heat-loss coefficient [W/m²K] (default 0.5, well-insulated steel tank).

  • T_ambient (float) – Ambient temperature [°C] (default 15).

__init__(volume: float, T_flow: float = 90.0, T_return: float = 60.0, U_loss: float = 0.5, T_ambient: float = 15.0)[source]
step(Q_net_kw: float, dt_h: float = 1.0) None[source]

Advance buffer by one timestep.

Parameters:
  • Q_net_kw (float) – Net power into the tank [kW]. Positive = charging, negative = discharging.

  • dt_h (float) – Timestep duration [h] (default 1).

reset_history() None[source]

Clear all per-timestep history lists (call after pre-charge, before main loop).

get_soc() float[source]

State of charge in [0, 1].

get_capacity_kwh() float[source]

Usable capacity [kWh].

get_heat_loss_kw() float[source]

Heat loss during last timestep [kW].

Waste Heat Pump Module

Waste heat pump modeling with variable source temperatures and heat recovery.

author:

Dipl.-Ing. (FH) Jonas Pfeiffer

class districtheatingsim.heat_generators.waste_heat_pump.WasteHeatPump(name: str, Kühlleistung_Abwärme: float, Temperatur_Abwärme: float, spez_Investitionskosten_Abwärme: float = 500, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, opt_cooling_min: float = 0, opt_cooling_max: float = 500)[source]

Bases: HeatPump

Waste heat pump utilizing industrial/data center waste heat.

Parameters:
  • name (str) – Unique identifier

  • Kühlleistung_Abwärme (float) – Waste heat cooling capacity [kW]

  • Temperatur_Abwärme (float) – Waste heat temperature [°C]

  • spez_Investitionskosten_Abwärme (float, optional) – Waste heat system costs [€/kW], defaults to 500

Note

High COP due to elevated source temperatures.

__init__(name: str, Kühlleistung_Abwärme: float, Temperatur_Abwärme: float, spez_Investitionskosten_Abwärme: float = 500, spezifische_Investitionskosten_WP: float = 1000, min_Teillast: float = 0.2, opt_cooling_min: float = 0, opt_cooling_max: float = 500) None[source]

Initialize waste heat pump system.

Parameters:
  • name (str) – Unique identifier for the waste heat pump system.

  • Kühlleistung_Abwärme (float) – Waste heat cooling capacity available for extraction [kW].

  • Temperatur_Abwärme (float) – Waste heat source temperature [°C].

  • spez_Investitionskosten_Abwärme (float, optional) – Specific investment costs for waste heat recovery system [€/kW]. Default is 500.

  • spezifische_Investitionskosten_WP (float, optional) – Specific investment costs for heat pump unit [€/kW]. Default is 1000.

  • min_Teillast (float, optional) – Minimum part-load ratio [-]. Default is 0.2.

  • opt_cooling_min (float, optional) – Minimum cooling capacity for optimization [kW]. Default is 0.

  • opt_cooling_max (float, optional) – Maximum cooling capacity for optimization [kW]. Default is 500.

calculate_heat_pump(VLT_L: ndarray, COP_data: ndarray) tuple[ndarray, ndarray, ndarray, ndarray][source]

Calculate heat pump performance for waste heat operation.

Parameters:
  • VLT_L (numpy.ndarray) – Required flow temperature array [°C].

  • COP_data (numpy.ndarray) – COP lookup table for performance interpolation.

Returns:

Heat output [kW], electrical power [kW], achievable flow temps [°C], COP [-].

Return type:

tuple of numpy.ndarray

Note

Uses waste heat temperature as source for COP calculation.

calculate_operation(Last_L: ndarray, VLT_L: ndarray, COP_data: ndarray) None[source]

Calculate operational performance considering waste heat availability.

Parameters:
  • Last_L (numpy.ndarray) – Heat load demand time series [kW].

  • VLT_L (numpy.ndarray) – Required flow temperature time series [°C].

  • COP_data (numpy.ndarray) – COP lookup table for performance interpolation.

Note

Heat output limited by waste heat capacity and load demand. Updates time-series attributes for simulation period.

generate(t: int, **kwargs) tuple[float, float][source]

Generate heat at specific time step with waste heat constraints.

Parameters:
  • t (int) – Current time step index.

  • kwargs (dict) – Additional parameters (VLT_L, COP_data).

Returns:

Heat generation [kW] and electricity consumption [kW].

Return type:

tuple of float

Note

Checks waste heat availability and operational constraints.

calculate_results(duration: float) None[source]

Calculate aggregated performance metrics from simulation results.

Parameters:

duration (float) – Time step duration [hours].

Note

Calculates energy totals, SCOP, and operational statistics.

calculate(economic_parameters: dict[str, Any], duration: float, load_profile: ndarray, **kwargs) dict[str, Any][source]

Comprehensive calculation of waste heat pump performance and economics.

Parameters:
  • economic_parameters (dict) – Economic analysis parameters.

  • duration (float) – Simulation time step duration [hours].

  • load_profile (numpy.ndarray) – Heat demand time series [kW].

  • kwargs (dict) – Additional parameters (VLT_L, COP_data).

Returns:

Performance, economic, and environmental results.

Return type:

dict

Note

Integrates waste heat recovery with heat pump performance and lifecycle cost analysis.

set_parameters(variables: list, variables_order: list, idx: int) None[source]

Set optimization parameters for the waste heat pump system.

Parameters:
  • variables (list) – List of optimization variable values.

  • variables_order (list) – List defining variable order and identification.

  • idx (int) – Technology index for parameter identification.

Note

Updates waste heat cooling capacity from optimization variables.

add_optimization_parameters(idx: int) tuple[list, list, list][source]

Define optimization parameters for waste heat pump system.

Parameters:

idx (int) – Technology index for unique variable identification.

Returns:

Initial values, variable names, and bounds for optimization.

Return type:

tuple

Note

Returns waste heat cooling capacity bounds and initial value.

get_display_text() str[source]

Generate human-readable display text for system configuration.

Returns:

Formatted display text with system parameters.

Return type:

str

Note

Includes waste heat capacity, temperature, and investment costs.

extract_tech_data() tuple[str, str, str, str][source]

Extract technology data for reporting and analysis.

Returns:

Name, technical dimensions, cost breakdown, and total investment.

Return type:

tuple of str

Note

Includes waste heat capacity, source temperature, and component costs.