Internal Combustion Engine Combined Heat & Power
See also
Note
An internal combustion engine (ICE) combined heat & power (CHP) element consists of one element and one controller. The element defines its physical parameters, while the controller governs the operational logic.
The create_controlled function creates both and connects them.
Create Controlled Function
- pandaprosumer.create_controlled_ice_chp(prosumer, size, fuel, altitude, name=None, index=None, in_service=True, level=0, order=0, period=0, **kwargs)[source]
Creates an ICE CHP element in prosumer[“ice_chp”] and an ICE CHP controller
- INPUT:
prosumer - The prosumer within this ice_chp should be created
size (float) - ICE CHP rating [kW]
fuel (string) - Type of the fuel used in the calculation
altitude (float) - Altitude above sea level of the ICE CHP installation site [m]
- OPTIONAL:
name (string, default None) - The name of the ICE CHP instance
index (int, default None) - Force a specified ID if it is available. If None, the index one higher than the highest already existing index is selected.
in_service (boolean, default True) - True for in_service or False for out of service
level (int, default 0) - The level of the controller
order (int, default 0) - The order of the controller
period (int, default 0) - Index of the period, default is 0
- OUTPUT:
index (int) - The unique ID of the created ICE CHP
- EXAMPLE:
create_controlled_ice_chp(prosumer, 350, “ng”, 0, “example_ice_chp”)
Controller
Input Static Data
Parameter |
Description |
Unit |
|---|---|---|
name |
Unique name or identifier for the ICE CHP element |
N/A |
size |
ICE CHP rating (nominal max. electrical power) |
kW |
fuel |
Fuel type used in the calculation |
N/A |
altitude |
Altitude above sea level of the ICE CHP installation site |
m |
Input Time Series
Parameter |
Description |
Unit |
|---|---|---|
cycle |
Output preference: electricity or heat |
N/A |
temp_intake_k |
Air intake temperature (e.g. ambient air temperature) |
K |
Output Time Series
Output |
Description |
Unit |
|---|---|---|
load |
Percentage of the ICE CHP max. output power |
N/A |
p_in_kw |
Total input energy flow (from the fuel) |
kW |
p_el_out_kw |
Electrical power on the generator |
kW |
p_th_out_kw |
Recovered heat flow |
kW |
p_rad_out_kw |
Radiated heat flow |
kW |
ice_chp_efficiency |
ICE CHP’s total efficiency (electrical + thermal) |
N/A |
mdot_fuel_in_kg_per_s |
Required fuel mass flow |
kg/s |
acc_m_fuel_in_kg |
Total mass of fuel consumed |
kg |
acc_co2_equiv_kg |
Total mass of CO2-equivalent emissions |
kg |
acc_co2_inst_kg |
Total mass of CO2 emissions (emissions at ICE CHP location) |
kg |
acc_nox_mg |
Total mass of NOx emissions |
mg |
acc_time_ice_chp_oper_s |
Total time of ICE CHP operation |
s |
Mapping
The ICE CHP Controller can be mapped using the Generic Mapping Scheme.
No inputs are mapped as ICE CHP is an independent energy source
The following outputs can be mapped:
p_el_out_kw
p_th_out_kw
Note
Input file values and the mapping setup:
If the mapped output is electrical power (p_el_out_kw), the recommended value of the time-dependant input cycle is 1.
If the mapped output is thermal power, i.e. heat (p_th_out_kw), the recommended value of the time-dependant input cycle is 2.
In case the cycle and the mapped output don’t match, the ICE CHP will pair the demand to the mapped output, which may lead to inaccuracies.
Example: For the given heat demand q_demand_kw = 500 kW, the expected output of a (700 kW) ICE CHP is p_th_out_kw = 500 kW. However, if cycle = 1, but the mapped output is p_th_out_kw, the ICE CHP module will give the following output values:
p_el_out_kw = 500 kW
p_th_out_kw = 495 kW
Because the instruction to the ICE CHP module is that electrical power (p_el_out_kw) is preferred, it will try to match electrical power to the demand and the level of recovered heat will be lower than the demanded energy flow.
Particular care should be taken when the ICE CHP module is connected to more consumers (more than one demand), especially where one consumer demands heat and another demands electrical power.
Model
- class pandaprosumer.controller.models.IceChpController(prosumer, chp_object, order=0, level=0, in_service=True, index=None, **kwargs)[source]
- calculate_air_density(temperature_k: float, altitude_m: float, pressure_ref_pa=101325, m_molar_air_kg_per_mol=0.0289652, g_m_per_s2=9.81, gas_const_universal_j_per_molk=8.314) float[source]
Calculates air density according to the ideal gas law.
- param temperature_k:
air temperature in K
- param altitude_m:
the altitude of the CHP location in m
- param pressure_ref_pa:
reference pressure in Pa
- param m_molar_air_kg_per_mol:
air molar mass in kg/mol
- param g_m_per_s2:
gravitational acceleration in m/s2
- param gas_const_universal_j_per_molk:
universal gas constant in J/molK
- return density:
air density in kg/m3
- calculate_co2_equiv_mass_flow(p_in_kw: float, fuel_type: str, map_fuel: dict) float[source]
Calculates equivalent CO2 emissions.
- param p_in_kw:
input energy flow in kW
- param fuel_type:
selected fuel type (options: ng, sng1, sng2, sng3, sng4, sng5, sng6)
- param map_fuel:
data for the chosen CHP size from the map in the JSON file
- return mdot_co2_inst_kg_per_s:
mass flow of CO2 emissions at the location of the ICE CHP in kg/s
- calculate_co2_instant_mass_flow(mdot_fuel_kg_per_s: float, fuel_type: str, map_fuel: dict) float[source]
Calculates CO2 emissions at the location of the ICE CHP (instantaneous emissions).
- param mdot_fuel_kg_per_s:
fuel mass flow in kg/s
- param r_oxidised_c:
fraction of fully oxidised carbon
- param fuel_type:
selected fuel type (options: ng, sng1, sng2, sng3, sng4, sng5, sng6)
- param map_fuel:
data for the chosen CHP size from the map in the JSON file
- return mdot_co2_inst_kg_per_s:
mass flow of CO2 emissions at the location of the ICE CHP in kg/s
- calculate_density_ratio(temperature_act_k: float, altitude_act_m: float, map_chp: dict) float[source]
Calculates the ratio between the reference density for which the CHP maps were designed and the actual density of the air at intake.
- param temperature_act_k:
actual air temperature at CHP intake in K
- param altitude_act_m:
the actual altitude of the CHP location in m
- param map_engine:
data for the chosen CHP size
- return ratio:
ratio between map reference density and actual density
- calculate_efficiency(p_in_kw: float, p_loss_kw: float) float[source]
Calculates the efficiency of the entire ICE CHP.
- param p_in_kw:
input energy flow in kW
- param p_loss_kw:
lost energy flow in kW
- return efficiency:
efficiency of the ICE CHP in %
- calculate_electrical_power_out(load: float, map_chp: dict) float[source]
Calculates the generated electrical power.
- param load:
CHP load in %
- param map_chp:
data for the chosen CHP size from the map in the JSON file
- return p_el_out_kw:
output electrical power on the generator in kW
- calculate_energy_flow_loss(p_in_kw: float, p_out_kw: float, p_el_kw: float) float[source]
Calculates the amount of energy flow that is lost —> wasted heat.
- param p_in_kw:
input energy flow in kW
- param p_out_kw:
total recovered energy flow on the output side in kW
- param p_el_kw:
generated electrical power in kW
- return p_loss_kw:
wasted heat flow from the ICE CHP in kW
- calculate_fuel_input_mass_flow(p_in_kw: float, fuel_type: str, map_fuel: dict) float[source]
Determines the required fuel mass flow.
- param p_in_kw:
required energy flow into the CHP in kW
- param fuel_type:
selected fuel type (options: ng, sng1, sng2, sng3, sng4, sng5, sng6)
- param map_fuel:
data for the fuels in the fuels JSON file
- return mdot_fuel_in_kg_per_s:
required fuel mass flow in kg/s
- calculate_input_energy_flow(load: float, map_chp: dict) float[source]
Determines the input energy flow into the engine.
- param load_calc:
CHP load in %
- param map_engine:
data for the chosen CHP size
- return p_in_kw:
required energy flow for the defined load/output power in kW
- calculate_load(cycle: int, demand_kw: float, temperature_k: float, altitude_m: float, map_chp: dict, time) float[source]
Calculates the engine load based on the desired output.
- param cycle:
defines output priority (electrical power = 1, heat = 2)
- param demand_kw:
current demand value in kW
- param temperature_k:
current air temperature at intake in K
- param altitude_m:
the altitude of the CHP location in m
- param map_chp:
data for the chosen CHP size
- param time:
the current step’s simulation time
- returns:
load - CHP load under reference conditions in %
load_actual - CHP load under actual conditions in %
- calculate_nox_mass_flow(load: float, map_chp: dict) float[source]
Determines the amount of NOx emissions.
- param load:
CHP load in %
- param map_chp:
data for the chosen CHP size from the map in the JSON file
- return mdot_nox_mg_per_s:
mass flow of NOx emissions at the location of the ICE CHP in mg/s
- calculate_radiation(load: float, map_chp: dict) float[source]
Determines the amount of radiation from the ICE CHP unit into the sorounding space.
- param load:
CHP load in %
- param map_chp:
data for the chosen CHP size from the map in the JSON file
- return p_rad_out_kw:
radiation int in kW
- calculate_recovered_heat_flow(load: float, map_chp: dict) float[source]
Calculates the recovered energy (heat) flow.
- param load:
CHP load in %
- param map_chp:
data for the chosen CHP size from the map in the JSON file
- return p_th_out_kw:
useful heat flow extracted from the ICE CHP in kW
- control_step(prosumer)[source]
Executes the control step for the controller.
- Parameters:
prosumer – The prosumer object
- is_converged(container)[source]
This method is calculated whether or not the controller converged. This is where any target values are being calculated and compared to the actual measurements. Returns convergence of the controller.
- Parameters:
container (_type_) – _description_
- q_requested_kw(prosumer)[source]
Calculates the heat to deliver in kW.
- Parameters:
prosumer – The prosumer object
- Returns:
Heat to deliver in kW
- read_json_maps(map_filename: str) dict[source]
Opens a JSON file and reads data from it.
- param map_filename:
name of the file with maps to import
- return jason_data:
contains all data in the JSON file
The ICE CHP module is map based. Its response is read from tabulated data contained in a map associated with the chosen size of the ICE CHP. Maps for three sizes are provided:
350 kWe,
700 kWe,
1400 kWe.
They are stored in a dedicated JSON file in pandaprosumer2/library/chp_maps/ice_chp_maps.json to make modifications to the maps easier. If required, maps can be added or removed. However, in case of changes, their sizes must be added to or removed from the chp_ice_size_kw list. All sizes should be in kW. The file should not contain two or more maps of the same size. The minimum information in an ICE CHP map should include the following:
temperature_reference_k: the temperature at which values in the map were measured (in K)
altitude_reference_m: the altitude at which values in the map were measured (in m)
pressure_reference_pa: air intake pressure at which values in the map were measured (in Pa)
air_molar_mass_kg_per_mol: average molar mass of intake air at the location of measurement (in kg/mol)
gravitational_acc_m_per_s2: gravitational acceleration at the location of measurement (in m/s2)
universal_gas_const_j_per_molk: the value of the universal gas constant (in J/molK)
load_limits_percent: minimum and maximum limits below and above which the CHP should not operate (in % of maximum load)
engine_load_percent: a list of load values at which measurements were taken (in % of maximum load)
power_el_kw: a list of values for the power on the electrical generator at each load (in kW)
energy_flow_input_kw: required input energy flow for each load value (in kW)
heat_flow_radiation_kw: the amount of radiation emitted at each load (in kW)
heat_flow_recovered_kw: total recovered heat flow at each load (in kW); provided maps include contributions from the jacket water (cooling) and the exhaust recovered to 150°C
exhaust_flow_rate_m3n_per_h: the rate of the exhaust flow (in m3N/h)
emiss_rate_nox_mg_per_m3n: an average rate of NOx emissions (in mg/m3N)
If data for the parameters above is not available, a value of zero should be used, except for temperature_reference_k for which a value of 293 is recommended instead of zero. Other information can be included for completeness, but will not be used by the program.
Similarly to the engine, information about available fuels is stored in a dedicated JSON file in pandaprosumer2/library/chp_maps/fuel_maps.json. Data for seven types of gaseous fuels is provided.
Input key |
Fuel type |
Production method |
Ref. |
|---|---|---|---|
ng |
Natural gas |
[GFM+21] |
|
sng1 |
Sythetic natural gas 1 |
Biogas catalytic methanation with 38% renewable electricity mix |
[GFM+21] |
sng2 |
Sythetic natural gas 2 |
Biogas catalytic methanation with 100% renewable electricity mix |
[GFM+21] |
sng3 |
Sythetic natural gas 3 |
Catalytic methanation from green H2 and CO2 sourced from iron/steel processing |
[LSE+24] |
sng4 |
Sythetic natural gas 4 |
Catalytic methanation from green H2 and CO2 sourced from direct air capture |
[LSE+24] |
sng5 |
Sythetic natural gas 5 |
Catalytic methanation from green H2 and CO2 sourced from ethanol production |
[LSE+24] |
sng6 |
Sythetic natural gas 6 |
Catalytic methanation from green H2 and CO2 sourced from ammonia production |
[LSE+24] |
Data in the fuel map can also be modified if required. It should include at least the following:
fuel_types: a list of available fuel types
lower_heating_value_kwh_per_kg: a list of lower heating value parameters associated with each type of fuel (in kWh/kg)
carbon_fraction: the percentage of carbon weight to total molecule weight for each type of fuel
co2eq_kg_per_kwh: CO2 equivalent emissions for each fuel type (in kg/kWh)
An instance of the ICE CHP is defined by its size, fuel type, and altitude. A CHP map is selected based on the chosen size. If the size is not in the chp_ice_size_kw list, the program will choose one size larger to guarantee that the chosen maximum power can be obtained. In the case where the chosen size is outside of the available range, the program will print a warning to the console and will shut down before starting calculations.
An example of how the ICE CHP module reads the value of recovered heat flow from its map, which takes the (thermal) power requirement as basis for determining the load at each time step. (source: University of Ljubljana, Faculty of Mechanical Engineering)
At each time step the algorithm follows the procedure described below:
Based on the current demand, the reference CHP load \(L_\text{ref}\) is determined from the map:
A check is performed to determine the preferred output - (1) electricity or (2) heat
For electricity, the demand is compared against values in power_el_kw, while for heat is compared against heat_flow_recovered_kw
If the demand exceeds the maximum values, the load is set to 100%
If the demand is not equal to any of the values in engine_load_percent, the algorithm performs a piece-wise linear interpolation
The actual load \(L_\text{act}\), i.e. the load perceived by the engine, is calulated next:
A ratio \(r_\text{air}\) betwen the reference and actual intak air density is calculated to take into account the effects of different ambient temperatures and altitudes. The perfect gas law is used to calculate air densities since air is assumed to be dry and homogeneously mixed.
For consistency, if \(r_\text{air} > 1\), then \(r_\text{air} = 1\)
Obtained load limits are compared against the values in load_limits_percent:
If \(L_\text{act}\) is below the lower limit, the ICE CHP is considered to be switched off and \(L_\text{act} = 0\)
If \(L_\text{act}\) is bigger than the upper limit, \(L_\text{act}\) is set to the upper limit
Parameter values associated with the calculated load are read or interpolated from the map:
Input: required input energy \(P_\text{in}\) (in kW) - from energy_flow_input_kw
Output: electrical energy on the generator \(P_\text{el}\) (in kW) - from power_el_kw
Output: recovered thermal energy \(P_\text{th}\) (in kW) - from heat_flow_recovered_kw
Output: radiated thermal energy \(P_\text{rad}\) (in kW) - from heat_flow_radiation_kw
Fuel consumption is calculated in two ways:
Fuel mass flow \(P_\text{el}\) (in kg/s):
where \(LHV\) (in kWh/kg) is the lower heating value obtained from the fuel map (lower_heating_value_kwh_per_kg) for the selected type of fuel
Total mass of fuel consumed (in kg) from the start of the calculation to the current time step :
where \(\Delta t\) is the duration of the time step (in s)
Three typical emissions are calculated in the following way:
CO2 mass flow (in kg/s) at the location of the ICE CHP:
where \(r_\text{C}\) is the carbon fraction for the chosen fuel obtained from the fuel map (carbon_fraction). \(M_{\text{CO}_2}\) and \(M_\text{C}\) represent molar masses of CO2 and C (in kg/mol), respectively.
CO2-equivalent mass flow (in kg/s):
where \(r_\text{eq}\) (kg/kWh) is the rate of CO2-equivalent emissions specified in the fuel map (co2eq_kg_per_kwh).
NOx mass flow (in mg/s):
where \(\dot{V}_\text{exh}\) is the volumetric flow of exhaust gases (in m3N/h) and \(q_{\text{NO}_x}\) is the rate of NOx emissions (in mg/m3N). Both are properties of the ICE CHP and their values are specified in the CHP map, exhaust_flow_rate_m3n_per_h and emiss_rate_nox_mg_per_m3n, respectively
Note
Results for CO2 and CO2-equivalent emissions are given in kg/s
Results for NOx emissions are given in mg/s
Information about the ICE CHP efficiency and total time of operation is also provided:
The total time is a sum of time steps during which the CHP load is not zero, i.e. it is considered to be operating
The total efficiency is calculated with the formula shown below: