Configuration of a Model
A Model represents a real process or component in form of the code. It follows the general structure of Input - internal calculation - output, triggered by its corresponding simulator that needs to exist for using the model in simulations. The model just represents the calculation steps, and an entity (see the glossary) is the instantiation of a model. So within a scenario it is possible to have multiple entities (like battery storages) for one model type (battery storage model).
This page explains the structure of a _model.py to enable you to create your own model.
As there can be different implementations of a device type (like storage system), the can be more
than one class within a _model.py (like a very detailled model and a generic model).
Note
All code-blocks derive from charging_station_model.py as of (01/24)
if not stated otherwise.
Imports
Import relevant packages for the model calculation1import warnings
2import math
3from eelib.utils import cos_phi_fix
Class definition
return these).13class ChargingStation:
14 """Models a charging station for electric vehicles of different types."""
15
16 # Valid values and types for each parameter
17 _VALID_PARAMETERS = {
18 "p_rated": {"types": [float], "values": (0, math.inf)},
19 "output_type": {"types": [str], "values": ["AC", "DC"]},
20 "charge_efficiency": {"types": [float, int], "values": (0, 1)},
21 "discharge_efficiency": {"types": [float, int], "values": (0, 1)},
22 "cos_phi": {"types": [float, int], "values": (0, 1)},
23 }
24
25 @classmethod
26 def get_valid_parameters(cls):
27 """Returns dictionary containing valid parameter types and values.
28
29 Returns:
30 dict: valid parameters for this model
31 """
32 return cls._VALID_PARAMETERS
E.g., the rated power p_rated of a charging station has to be a floating point value that is
non-negative. The efficiency should have a value between zero and one (100%). These values are
used when creating a model in simulations to check for correct values.
Initialization method __init__()
55def __init__(
56 self,
57 eid: str,
58 p_rated: int,
59 output_type: str = "AC",
60 charge_efficiency: float = 0.99,
61 discharge_efficiency: float = 0.99,
62 cos_phi: float = 1.0,
63 step_size=60 * 15, # step size in seconds
64):
78 # Set attributes of init_vals to static properties
79 self.eid = eid
80 self.p_rated = p_rated # rated active power (AC/DC) [W]
81 self.output_type = output_type # source AC/DC [-]
82 self.discharge_efficiency = discharge_efficiency # discharging efficiency [-]
83 self.charge_efficiency = charge_efficiency # charging efficiency [-]
84 self.cos_phi = cos_phi
85
86 # initialize dynamic output properties
87 self.p = 0 # Active Power (after control) [W]
88 self.q = 0 # Reactive Power (after control) [W]
89 self.p_device = {} # active power for every vehicle [W]
90 self.p_min = 0 # Minimal active Power [W]
91 self.p_max = 0 # Maximal active Power [W]
92
93 ...
94
95 # save time step length and current time step
96 self.step_size = step_size
97 self.timestep = 0
Model methods
99 def _calc_power_limits(self):
100 """Calculate the power limits for the charging station with the input thats coming from the
101 electric vehicles.
102
103 Raises:
104 ValueError: If the power limits of at least one connected ev do not work together.
105 """
106
107 # calculate current efficiency depending on the direction of power flow
108 self._calc_current_efficiency()
109
110 # in case no ev is connected to cs - no active power flexibility
111 self.p_min = 0
112 self.p_max = 0
113 for ev_id, ev_data in self.ev_data.items():
114 # check for each ev if connected - consider their limits, efficiency and nominal power
115 if ev_data.appearance:
116 # check if min. and max. power are correct
117 if ev_data.p_min > ev_data.p_max:
118 raise ValueError(f"Min. and max. power of ev {ev_id} do not comply.")
119 # handle the power limits
120 self.p_min = max(
121 self.p_min + ev_data.p_min / self.efficiency,
122 -self.p_rated,
123 )
124 self.p_max = min(
125 self.p_max + ev_data.p_max / self.efficiency,
126 self.p_rated,
127 )
128
129 ...
step() method
Within the step() method, the calculation processes are executed for the model entity.
This example is coming from the storage_model.py (01/24).
226 def step(self, timestep):
227 """Performs simulation step of eELib battery model.
228 Calculates all of the Dynamic Properties based on the Input Properties.
229
230 Args:
231 timestep (int): Current simulation time
232 """
233 # handle current timestep
234 if not self.timestep == timestep:
235 self.timestep = timestep
236
237 # adapt energy content from last timestep ( + self-discharge)
238 if self.p >= 0: # charging
239 self.e_bss_step_volume = (
240 self.p * self.charge_efficiency * (self.step_size / 3600)
241 )
242 else: # discharging
243 self.e_bss_step_volume = (
244 self.p / self.discharge_efficiency * (self.step_size / 3600)
245 )
246 self.e_bat += self.e_bss_step_volume
247
248 # Calculate battery cycles
249 self.bss_cycles += abs(self.e_bss_step_volume / self.e_cycle)
250
251 # Calculate battery state of health and aging properties
252 if self.status_aging:
253 self.__calculate_aging_status()
259 # Set active power and energy within limits
260 self.__set_power_within_limit()
261 self.__set_energy_within_limit()
262 self.soc = self.e_bat / self.e_bss_usable
263
264 self.__calc_charging_efficiency()
265
266 self.__calc_power_limits()
Checklist for adding / enhancing a model
- General Guidelines
When adding or enhancing a model, try to make use of the existing properties and methods from this or other models
- Model File Structure
A model includes the following files in a model folder which can be a subfolder inside
eelib/core/***:an init file, e.g.,
eelib/core/devices/example/__init__.py(can be empty or with info about the model itself)a model file, e.g.,
eelib/core/devices/example/example_model.py(see beginning of the article)a simulator file, e.g.,
eelib/core/devices/example/example_simulator.py(see Configuration of a Simulator)
- Required changes to
eelib/data if a model dataclass is needed or helpful to communicate information to other models, add or adjust the specific dataclass in
eelib/data/dataclass.pyupdate
eelib/data/__init__.py, to collect all dataclasses at that point
- Tests & Documentation
Writer proper comments and documentation (e.g. docstrings for every method, but also comments to illustrate the behaviour of the code)
create unit tests for all relevant functionalities
eelib/testing/unit/devices/test_example_model.pyadd the model to the documentation overview,
docs/source/reference_manual/model_overview.rst(you can useeelib/utils/simulation_setup/create_sim_script.ipynband create this automatically by executing the first two cells)
- Other considerations
Add new model attributes to the
METAof the simulator (see Configuration of a Simulator)If you add new packages, update
requirements.txt
Integrating the model into a Simulation
Strategy
If fitting, implement the new model or functionalities into the HEMS strategies to be used in a simulation (see Implementing an operating Strategy). Here you should also add properties for recieving the correct values from the new model to integrate these into the strategies, e.g. by adding the properties to the META listing.
If it is a different model, you should integrate it in a different way into the test scenarios, e.g. a market model should just be added and connected to other models In the case these models are so-called architecture models and have to be connected to all other models, you need to add them to the list in
eelib/model_connections/architecture_models.jsonfile
Model Connections
define new connections between properties of different models in
eelib/model_connections/model_connect_config.jsonfile (simply paste them in the direction of the connection)for connections in both direction, setup strong (first sent value) and weak (at beginning only done with default value) directions, see FAQ . Use lower-case letters for the model names here!
if the direction of the connection is of importance, there may be a need to adapt the
simulation_helperfunctionsconnect_entities()andconnect_entities_of_two_model_types().
Integration into Test Scenarios
Add the model to…
… the test scenario scripts (in the
SIM_CONFIG)… the model data of the test scenarios (
examples/data_input)… the model inputs of the test scenarios (
examples/input)
Then execute the test scenarios and see whether the models works and is correctly integrated into the simulation process.