Skip to content

Commit

Permalink
update physicsconfig with other energy carrier values for condensing …
Browse files Browse the repository at this point in the history
…boiler component
  • Loading branch information
k-rieck committed Oct 23, 2024
1 parent 787c9dd commit 798801b
Show file tree
Hide file tree
Showing 8 changed files with 884 additions and 42 deletions.
764 changes: 764 additions & 0 deletions hisim/components/condensing_boiler.py

Large diffs are not rendered by default.

120 changes: 99 additions & 21 deletions hisim/components/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
# clean

from typing import Any
from dataclasses import dataclass
from dataclasses import dataclass, field
from dataclasses_json import dataclass_json
from hisim.loadtypes import LoadTypes
from hisim.component import ConfigBase


Expand All @@ -23,10 +24,7 @@ class WarmWaterStorageConfig(ConfigBase):
slice_height_minimum: float # [m]

@classmethod
def get_default_config(
cls,
building_name: str = "BUI1",
) -> Any:
def get_default_config(cls, building_name: str = "BUI1",) -> Any:
"""Gets a default config."""
return WarmWaterStorageConfig(
building_name=building_name,
Expand Down Expand Up @@ -212,10 +210,7 @@ class ExtendedControllerConfig(ConfigBase):
maximum_autarky: bool

@classmethod
def get_default_config(
cls,
building_name: str = "BUI1",
) -> Any:
def get_default_config(cls, building_name: str = "BUI1",) -> Any:
"""Gets a default ExtendedControllerConfig."""
return ExtendedControllerConfig(
building_name=building_name,
Expand All @@ -232,28 +227,111 @@ def get_default_config(
)


@dataclass_json
@dataclass
class PhysicsConfig:
"""Physics config class."""
"""Physics config class.
Returns physical and chemical properties of different energy carries.
Sources:
Schmidt 2020: Wasserstofftechnik S.170ff
https://gammel.de/de/lexikon/heizwert---brennwert/4838.
Values are taken at standard conditions (25°C)
https://energyfaculty.com/physical-and-thermal-properties/
Brennwert: Higher heating value gross caloric value, Heizwert: Lower heating value or net caloric value.
"""

# Init
density_in_kg_per_m3: float
lower_heating_value_in_joule_per_m3: float
higher_heating_value_in_joule_per_m3: float
specific_heat_capacity_in_joule_per_kg_per_kelvin: float

# Post-Init
specific_volume_in_m3_per_kg: float = field(init=False)
lower_heating_value_in_joule_per_kg: float = field(init=False)
higher_heating_value_in_joule_per_kg: float = field(init=False)
specific_heat_capacity_in_watthour_per_kg_per_kelvin: float = field(init=False)

def __post_init__(self):
"""Post init function.
These variables are calculated automatically based on init values.
"""

self.specific_volume_in_m3_per_kg = 1 / self.density_in_kg_per_m3
self.lower_heating_value_in_joule_per_kg = (
self.lower_heating_value_in_joule_per_m3 / self.density_in_kg_per_m3
)
self.higher_heating_value_in_joule_per_kg = (
self.higher_heating_value_in_joule_per_m3 / self.density_in_kg_per_m3
)
self.specific_heat_capacity_in_watthour_per_kg_per_kelvin = (
self.specific_heat_capacity_in_joule_per_kg_per_kelvin / 3600
)

@classmethod
def get_properties_for_energy_carrier(cls, energy_carrier: LoadTypes) -> "PhysicsConfig":
"""Get physical and chemical properties from specific energy carrier."""
if energy_carrier == LoadTypes.GAS:
# natural gas (here we use the values of methane because this is what natural gas for residential heating mostly consists of)
return PhysicsConfig(
density_in_kg_per_m3=0.71750,
lower_heating_value_in_joule_per_m3=35.895 * 1e6,
higher_heating_value_in_joule_per_m3=39.819 * 1e6,
specific_heat_capacity_in_joule_per_kg_per_kelvin=2190,
)
if energy_carrier == LoadTypes.HYDROGEN:
return PhysicsConfig(
density_in_kg_per_m3=0.08989,
lower_heating_value_in_joule_per_m3=10.783 * 1e6,
higher_heating_value_in_joule_per_m3=12.745 * 1e6,
specific_heat_capacity_in_joule_per_kg_per_kelvin=14200,
)
if energy_carrier == LoadTypes.OIL:
return PhysicsConfig(
density_in_kg_per_m3=0.83 * 1e3,
lower_heating_value_in_joule_per_m3=35.358 * 1e9,
higher_heating_value_in_joule_per_m3=37.682 * 1e9,
specific_heat_capacity_in_joule_per_kg_per_kelvin=1970,
)
if energy_carrier == LoadTypes.PELLETS:
# density here = bulk density (Schüttdichte)
# source: https://www.chemie.de/lexikon/Holzpellet.html
# higher heating value of pellets unknown -> set to lower heating value
return PhysicsConfig(
density_in_kg_per_m3=650,
lower_heating_value_in_joule_per_m3=11.7 * 1e3,
higher_heating_value_in_joule_per_m3=11.7 * 1e3,
specific_heat_capacity_in_joule_per_kg_per_kelvin=2500,
)
if energy_carrier == LoadTypes.WATER:
return PhysicsConfig(
density_in_kg_per_m3=1000,
lower_heating_value_in_joule_per_m3=0,
higher_heating_value_in_joule_per_m3=0,
specific_heat_capacity_in_joule_per_kg_per_kelvin=4180,
)

water_density = 1000 # [kg/m^3]
water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin = 4180 # J/kgK
water_specific_heat_capacity_in_watthour_per_kilogramm_per_kelvin = 1.163 # Wh/kgK
raise ValueError(f"Energy carrier {energy_carrier} not implemented in PhysicsConfig yet.")

# Schmidt 2020: Wasserstofftechnik S.170ff
# fuel value H2: 10.782 MJ/m³ (S.172)
# density H2: 0.08989 kg/m³ (S. 23) -> standard conditions
hydrogen_density = 0.08989 # [kg/m³]
hydrogen_specific_volume = 1 / hydrogen_density # [m^3/kg]
hydrogen_specific_fuel_value_per_m_3 = 10.782 * 10**6 # [J/m³]
hydrogen_specific_fuel_value_per_kg = hydrogen_specific_fuel_value_per_m_3 / hydrogen_density # [J/kg]
# hydrogen_density_in_kg_per_m3 = 0.08989 # [kg/m³]
# hydrogen_specific_volume_in_m3_per_kg = 1 / hydrogen_density_in_kg_per_m3 # [m^3/kg]
# hydrogen_specific_fuel_value_in_joule_per_m3 = 10.782 * 10**6 # [J/m³]
# hydrogen_specific_fuel_value_in_joule_per_kg = hydrogen_specific_fuel_value_in_joule_per_m3 / hydrogen_density_in_kg_per_m3 # [J/kg]

# Schmidt 2020: Wasserstofftechnik S.170ff
# fuel value Methan: 35.894 MJ/m³ (S.172)
# density Methan: 0.71750 kg/m³ (S. 23) -> standard conditions
natural_gas_density = 0.71750 # [kg/m³]
natural_gas_specific_volume = 1 / hydrogen_density # [m^3/kg]
natural_gas_specific_fuel_value_per_m_3 = 35.894 * 10**6 # [J/m³]
natural_gas_specific_fuel_value_per_kg = natural_gas_specific_fuel_value_per_m_3 / natural_gas_density # [J/kg]
# natural_gas_density = 0.71750 # [kg/m³]
# natural_gas_specific_volume = 1 / hydrogen_density_in_kg_per_m3 # [m^3/kg]
# natural_gas_specific_fuel_value_per_m_3 = 35.894 * 10**6 # [J/m³]
# natural_gas_specific_fuel_value_per_kg = natural_gas_specific_fuel_value_per_m_3 / natural_gas_density # [J/kg]


@dataclass_json
Expand Down
6 changes: 3 additions & 3 deletions hisim/components/generic_electrolyzer_and_h2_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,14 +179,14 @@ def convert_electricity(self, electricity_input, hydrogen_not_stored):
)
assert self.min_hydrogen_production_rate <= hydrogen_output_liter <= self.max_hydrogen_production_rate
# kg/s = l/s / 1000 * kg/m³
hydrogen_output = (hydrogen_output_liter / 1000) * PhysicsConfig.hydrogen_density
hydrogen_output = (hydrogen_output_liter / 1000) * PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.HYDROGEN).density_in_kg_per_m3
oxygen_output = hydrogen_output * (88.8 / 11.2)

if hydrogen_not_stored > 0:
hydrogen_real = hydrogen_output - hydrogen_not_stored
if hydrogen_real == 0:
return hydrogen_output, 0, 0, 0
hydrogen_output_liter_real = hydrogen_real * 1000 / PhysicsConfig.hydrogen_density
hydrogen_output_liter_real = hydrogen_real * 1000 / PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.HYDROGEN).density_in_kg_per_m3
power_level_real = self.min_power_percent + (
hydrogen_output_liter_real - self.min_hydrogen_production_rate
) * (self.max_power_percent - self.min_power_percent) / (
Expand Down Expand Up @@ -431,7 +431,7 @@ def i_simulate(self, timestep: int, stsv: SingleTimeStepValues, force_convergenc
try:
# -/- = kg/s * J/kg / W
electrolyzer_efficiency = (
hydrogen_output * PhysicsConfig.hydrogen_specific_fuel_value_per_kg
hydrogen_output * PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.HYDROGEN).lower_heating_value_in_joule_per_kg
) / electricity_input
assert self.min_power <= electricity_input <= self.max_power
except ZeroDivisionError:
Expand Down
8 changes: 4 additions & 4 deletions hisim/components/heat_distribution_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ def build(self,) -> None:
The function sets important constants and parameters for the calculations.
"""
self.specific_heat_capacity_of_water_in_joule_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
)
self.density_of_water = PhysicsConfig.water_density
self.density_of_water_in_kg_per_m3 = PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).density_in_kg_per_m3

def i_prepare_simulation(self) -> None:
"""Prepare the simulation."""
Expand Down Expand Up @@ -464,7 +464,7 @@ def determine_water_temperature_input_output_effective_thermal_power_without_mas

outer_surface_of_hds_pipe = np.pi * outer_pipe_diameter * length_of_hds_pipe # in m^2

mass_of_water_in_hds = inner_volume_of_hds * self.density_of_water
mass_of_water_in_hds = inner_volume_of_hds * self.density_of_water_in_kg_per_m3

time_constant_hds = (
mass_of_water_in_hds * self.specific_heat_capacity_of_water_in_joule_per_kilogram_per_celsius
Expand Down Expand Up @@ -1276,7 +1276,7 @@ def prepare_calc_heating_dist_temperature(
def calc_heating_distribution_system_water_mass_flow_rate(self, max_thermal_building_demand_in_watt: float,) -> Any:
"""Calculate water mass flow between heating distribution system and hot water storage."""
specific_heat_capacity_of_water_in_joule_per_kg_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
)

heating_distribution_system_water_mass_flow_in_kg_per_second = max_thermal_building_demand_in_watt / (
Expand Down
2 changes: 1 addition & 1 deletion hisim/components/loadprofilegenerator_utsp_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def i_simulate(self, timestep: int, stsv: cp.SingleTimeStepValues, force_converg
energy_discharged = ww_energy_demand + energy_losses
ww_temperature_output: float = freshwater_temperature + temperature_difference_cold
ww_mass_input = energy_discharged / (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
* (ww_temperature_input - ww_temperature_output)
)
else:
Expand Down
2 changes: 1 addition & 1 deletion hisim/components/more_advanced_heat_pump_hplib.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def __init__(
self.heatpump.delta_t = 5

self.specific_heat_capacity_of_water_in_joule_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
)

# protect erros for Water/Water Heatpumps
Expand Down
18 changes: 9 additions & 9 deletions hisim/components/simple_water_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def get_scaled_hot_water_storage(
max_thermal_power_in_watt_of_heating_system
* 1e-3
/ (
PhysicsConfig.water_specific_heat_capacity_in_watthour_per_kilogramm_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_watthour_per_kg_per_kelvin
* temperature_difference_between_flow_and_return_in_celsius
)
) * 1000 # 1m3 = 1000l
Expand Down Expand Up @@ -390,7 +390,7 @@ def calculate_heat_loss_and_temperature_loss(

# basis here: Q = m * cw * delta temperature, temperature loss is another term for delta temperature here
temperature_loss_of_water_in_celsius_per_hour = heat_loss_in_watt / (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin * mass_in_storage_in_kg
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin * mass_in_storage_in_kg
)

# transform from °C/h to °C/timestep
Expand Down Expand Up @@ -449,7 +449,7 @@ def calculate_thermal_energy_in_storage(
# Q = c * m * (Tout - Tin)

thermal_energy_in_storage_in_joule = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
* mass_in_storage_in_kg
* (mean_water_temperature_in_storage_in_celsius)
) # T_mean - 0°C
Expand All @@ -465,7 +465,7 @@ def calculate_thermal_energy_of_water_flow(
# Q = c * m * (Tout - Tin)
thermal_energy_of_input_water_flow_in_watt_hour = (
(1 / 3600)
* PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
* PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
* water_mass_in_kg
* water_temperature_difference_in_kelvin
)
Expand Down Expand Up @@ -493,7 +493,7 @@ def calculate_thermal_power_of_water_flow(
"""Calculate thermal energy of the water flow with respect to 0°C temperature."""

thermal_power_of_input_water_flow_in_watt = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
* water_mass_flow_in_kg_per_s
* (water_temperature_hot_in_celsius - water_temperature_cold_in_celsius)
)
Expand Down Expand Up @@ -1030,10 +1030,10 @@ def build(self, heat_exchanger_is_present: bool) -> None:
The function sets important constants an parameters for the calculations.
"""
self.specific_heat_capacity_of_water_in_joule_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
)
self.specific_heat_capacity_of_water_in_watthour_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_watthour_per_kilogramm_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_watthour_per_kg_per_kelvin
)
# https://www.internetchemie.info/chemie-lexikon/daten/w/wasser-dichtetabelle.php
self.density_water_at_40_degree_celsius_in_kg_per_liter = 0.992
Expand Down Expand Up @@ -1502,10 +1502,10 @@ def build(
)

self.specific_heat_capacity_of_water_in_joule_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_joule_per_kilogram_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_joule_per_kg_per_kelvin
)
self.specific_heat_capacity_of_water_in_watthour_per_kilogram_per_celsius = (
PhysicsConfig.water_specific_heat_capacity_in_watthour_per_kilogramm_per_kelvin
PhysicsConfig.get_properties_for_energy_carrier(energy_carrier=lt.LoadTypes.WATER).specific_heat_capacity_in_watthour_per_kg_per_kelvin
)
# https://www.internetchemie.info/chemie-lexikon/daten/w/wasser-dichtetabelle.php
self.density_water_at_40_degree_celsius_in_kg_per_liter = 0.992
Expand Down
6 changes: 3 additions & 3 deletions hisim/loadtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class LoadTypes(str, enum.Enum):
TEMPERATURE = "Temperature"
PRESSURE = "Pressure"
TIME = "Time"

PRICE = "Price"
# Substance
GAS = "Gas"
AIR = "Air"
Expand All @@ -94,10 +94,9 @@ class LoadTypes(str, enum.Enum):
WARM_WATER = "WarmWater"
DIESEL = "Diesel"
OIL = "Oil"
PELLETS = "Pellets"
DISTRICTHEATING = "DistrictHeating"

PRICE = "Price"

# Controllers:
ON_OFF = "OnOff" # encoding: 0 means off and 1 means on
ACTIVATION = "Activation"
Expand Down Expand Up @@ -223,6 +222,7 @@ class HeatingSystems(str, enum.Enum):
OIL_HEATING = "OilHeating"
GAS_HEATING = "GasHeating"
DISTRICT_HEATING = "DistrictHeating"
HYDROGEN_HEATING = "HydrogenHeating"


@enum.unique
Expand Down

0 comments on commit 798801b

Please sign in to comment.