Configuration of a Model

This page explains the structure of a model.py to enable you to create your own models. The model.py defines the properties and methods of instances of the respective model. Within a scenario, you may have multiple e.g. electric vehicles with differing property values, configured within the model_data.json. A model.py is always paired with a simulator.py.

Note

All code-blocks derive from charging_station_model.py as of (01/24) if not stated otherwise.

Introduction and imports

Basic explanation about the models and import relevant packages.
 1"""
 2eElib charging station model is built to manage the charging processes of EVs.
 3
 4Author: elenia@TUBS
 5"""
 6
 7import warnings
 8import math
 9
10from eelib.utils.ancillary_services.voltage_control_concepts import cos_phi_fix

Class definition

Short explanation, listing of parameters with their allowed values for initialization (+ method to return them)
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": [int], "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

Initialization of model properties

To initialize static properties and input-output-values of the model (to not set them in init function)
34# dynamic INPUT properties
35appearance = {}  # Identifier if car at station [-]
36e_bat = {}  # Actual charging level [kWh]
37e_bat_max = {}  # Maximal capacity [kWh]
38p_charge_max = {}  # Maximal charging active power [W]
39p_discharge_max = {}  # Maximal discharging active power [W]
40appearance_end_step = {}  # index for ending point of standing time [-]
41bev_consumption_period = {}  # Electricity consumption of EV in next period not being home,
42
43# control signals & charging strategy values
44p_set = {}  # active power set-point [W]
45
46# dynamic OUTPUT properties
47p = 0  # Active Power (after control) [W]
48q = 0  # Reactive Power (after control) [W]
49p_device = {}  # active power for every vehicle [W]
50p_min = 0  # Minimal active Power [W]
51p_max = 0  # Maximal active Power [W]
52
53efficiency = 1.0  # efficiency of the current time step for the charging station

Initialization method __init__()

takes parameter values as inputs
55def __init__(
56    self,
57    ename: 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):
creates entity of this model
78    # Set attributes of init_vals to static properties
79    self.ename = ename
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    # edit efficiency rates
87    if self.output_type == "AC" and (charge_efficiency != 1.0 or discharge_efficiency != 1.0):
88        self.charge_efficiency = 1
89        self.discharge_efficiency = 1
90        warnings.warn(
91            "WARNING: Efficiency of AC charging is instead set to 1!",
92            UserWarning,
93        )
94
95    # save time step length and current time step
96    self.step_size = step_size
97    self.time = 0

Model methods

Type-specific function like calculation of power limits, aging, efficiency, adaption of stored energy etc.
 99def _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    # 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_appearance in self.appearance.items():
114        # check for each ev if connected - consider their limits, efficiency and nominal power
115        if ev_appearance:
116            # check if min. and max. power are correct
117            if self.p_discharge_max[ev_id] > self.p_charge_max[ev_id]:
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 + self.p_discharge_max[ev_id] / self.efficiency,
122                -self.p_rated,
123            )
124            self.p_max = min(
125                self.p_max + self.p_charge_max[ev_id] / self.efficiency,
126                self.p_rated,
127            )
128...

step() method

The step() method of storage_model.py (01/24).

For handling of the processes of the model within a time step
226def step(self, time):
227    """Performs simulation step of eELib battery model.
228    Calculates all of the Dynamic Properties based on the Input Properties.
229
230    Args:
231        time (int): Current simulation time
232    """
At first: Handling of a new time step (if entity was called for first time, do some processes once, like adapting energy)
233    # handle current time step
234    if not self.time == time:
235        self.time = time
236
237        # adapt energy content from last time step ( + self-discharge)
238        e_bat_self_discharge = -(self.e_bat * self.loss_rate) * (
239            self.step_size / (60 * 60 * 24 * 30)
240        )
241        if self.p >= 0:  # charging
242            self.e_bat_step_volume = (
243                self.p * self.charge_efficiency * (self.step_size / 3600) + e_bat_self_discharge
244            )
245        else:  # discharging
246            self.e_bat_step_volume = (
247                self.p / self.discharge_efficiency * (self.step_size / 3600)
248                + e_bat_self_discharge
249            )
250        self.e_bat += self.e_bat_step_volume
251
252        # Calculate battery cycles
253        self.bat_cycles += abs(self.e_bat_step_volume / self.e_cycle)
254
255        # Calculate battery state of health and aging properties
256        if self.status_aging:
257            self.__calculate_aging_status()
Call model-specific methods in supposed order
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_bat_usable
263
264    self.__calc_charging_efficiency()
265
266    self.__calc_power_limits()

Checklist for adding / enhancing a model

What changes?

adapting current implementation?

Try to make use of the existing properties and methods of the model

adding new implementation (e.g. new method) or need for new properties?
  1. Add the part of code to the model

  2. Write proper comments and documentation (docstrings for every method!)

  3. Write a corresponding test function!

New packages have been added?

add them to the requirements.txt file

Where to add?

New model attributes need to be …
  1. … added to the META of the simulator.

  2. If they are also input data, add them to the model_data of the test scenarios (examples/data/model_data_scenario) as well as the VALID_PARAMETERS of the model.

New connections between properties of different models …

… need to be integrated to the model_connections/model_connect_config.json file, simply paste them in the direction of the connection.

New models need to be integrated …
  1. … into the test scenario scripts (in the SIM_CONFIG).

  2. … into the model_data of the test scenarios (examples/data/model_data_scenario).

  3. … into the model_connections/model_connect_config.json file with their connections to/from other models. If the direction of the connection is of importance, there may be a need to adapt the simulation_helper functions connect_entities() and connect_entities_of_two_model_types().

  4. … into the simulator META data.

  5. … with a unit test file that checks all the relevant model functionalities.