diff --git a/README.md b/README.md index eb52133b..601b8da6 100644 --- a/README.md +++ b/README.md @@ -59,4 +59,4 @@ your publications: Dinkelbach, J., Razik, L., Mirz, M., Benigni, A., Monti, A.: Template-based generation of programming language specific code for smart grid modelling compliant with CIM and CGMES. -J. Eng. 2023, 1–13 (2022). [https://doi.org/10.1049/tje2.12208](https://doi.org/10.1049/tje2.12208) +J. Eng. 2023, 1-13 (2022). [https://doi.org/10.1049/tje2.12208](https://doi.org/10.1049/tje2.12208) diff --git a/cimgen/languages/modernpython/README.md b/cimgen/languages/modernpython/README.md index 3b4e0c73..d567d629 100644 --- a/cimgen/languages/modernpython/README.md +++ b/cimgen/languages/modernpython/README.md @@ -6,12 +6,11 @@ - [Examples](#examples) - [Python](#python) - [Modern Python](#modern-python) - - [Modern Python after black (formatting)](#modern-python-after-black-formatting) ## Description It mostly uses dataclasses (pydantic one, to get data checks) and adds some attribute walking -directly into the class. See for instance `cgmes_attributes_in_profile` in [Base.py](./Base.py). +directly into the class. See for instance `cgmes_attributes_in_profile` in [Base.py](utils/Base.py). ## Warning @@ -21,83 +20,94 @@ other code using these classes) much simpler. ## Examples -Example of ACLineSegment. +Example of ACLineSegment (generated with --cgmes_version cgmes_v3_0_0). ### Python ```python from .Conductor import Conductor +from .CGMESProfile import Profile class ACLineSegment(Conductor): - ''' - A wire or combination of wires, with consistent electrical characteristics, building a single electrical system, used to carry alternating current between points in the power system. For symmetrical, transposed 3ph lines, it is sufficient to use attributes of the line segment, which describe impedances and admittances for the entire length of the segment. Additionally impedances can be computed by using length and associated per length impedances. The BaseVoltage at the two ends of ACLineSegments in a Line shall have the same BaseVoltage.nominalVoltage. However, boundary lines may have slightly different BaseVoltage.nominalVoltages and variation is allowed. Larger voltage difference in general requires use of an equivalent branch. - - :b0ch: Zero sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. Default: 0.0 - :bch: Positive sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. This value represents the full charging over the full length of the line. Default: 0.0 - :g0ch: Zero sequence shunt (charging) conductance, uniformly distributed, of the entire line section. Default: 0.0 - :gch: Positive sequence shunt (charging) conductance, uniformly distributed, of the entire line section. Default: 0.0 - :r: Positive sequence series resistance of the entire line section. Default: 0.0 - :r0: Zero sequence series resistance of the entire line section. Default: 0.0 - :shortCircuitEndTemperature: Maximum permitted temperature at the end of SC for the calculation of minimum short-circuit currents. Used for short circuit data exchange according to IEC 60909 Default: 0.0 - :x: Positive sequence series reactance of the entire line section. Default: 0.0 - :x0: Zero sequence series reactance of the entire line section. Default: 0.0 - ''' - - cgmesProfile = Conductor.cgmesProfile - - possibleProfileList = {'class': [cgmesProfile.EQ.value, ], - 'b0ch': [cgmesProfile.EQ.value, ], - 'bch': [cgmesProfile.EQ.value, ], - 'g0ch': [cgmesProfile.EQ.value, ], - 'gch': [cgmesProfile.EQ.value, ], - 'r': [cgmesProfile.EQ.value, ], - 'r0': [cgmesProfile.EQ.value, ], - 'shortCircuitEndTemperature': [cgmesProfile.EQ.value, ], - 'x': [cgmesProfile.EQ.value, ], - 'x0': [cgmesProfile.EQ.value, ], - } - - serializationProfile = {} - - __doc__ += '\n Documentation of parent class Conductor: \n' + Conductor.__doc__ - - def __init__(self, b0ch = 0.0, bch = 0.0, g0ch = 0.0, gch = 0.0, r = 0.0, r0 = 0.0, shortCircuitEndTemperature = 0.0, x = 0.0, x0 = 0.0, *args, **kw_args): - super().__init__(*args, **kw_args) - - self.b0ch = b0ch - self.bch = bch - self.g0ch = g0ch - self.gch = gch - self.r = r - self.r0 = r0 - self.shortCircuitEndTemperature = shortCircuitEndTemperature - self.x = x - self.x0 = x0 - - def __str__(self): - str = 'class=ACLineSegment\n' - attributes = self.__dict__ - for key in attributes.keys(): - str = str + key + '={}\n'.format(attributes[key]) - return str + """ + A wire or combination of wires, with consistent electrical characteristics, building a single electrical system, used to carry alternating current between points in the power system. For symmetrical, transposed three phase lines, it is sufficient to use attributes of the line segment, which describe impedances and admittances for the entire length of the segment. Additionally impedances can be computed by using length and associated per length impedances. The BaseVoltage at the two ends of ACLineSegments in a Line shall have the same BaseVoltage.nominalVoltage. However, boundary lines may have slightly different BaseVoltage.nominalVoltages and variation is allowed. Larger voltage difference in general requires use of an equivalent branch. + + :Clamp: The clamps connected to the line segment. Default: "list" + :Cut: Cuts applied to the line segment. Default: "list" + :b0ch: Zero sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. Default: 0.0 + :bch: Positive sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. This value represents the full charging over the full length of the line. Default: 0.0 + :g0ch: Zero sequence shunt (charging) conductance, uniformly distributed, of the entire line section. Default: 0.0 + :gch: Positive sequence shunt (charging) conductance, uniformly distributed, of the entire line section. Default: 0.0 + :r: Positive sequence series resistance of the entire line section. Default: 0.0 + :r0: Zero sequence series resistance of the entire line section. Default: 0.0 + :shortCircuitEndTemperature: Maximum permitted temperature at the end of SC for the calculation of minimum short-circuit currents. Used for short circuit data exchange according to IEC 60909. Default: 0.0 + :x: Positive sequence series reactance of the entire line section. Default: 0.0 + :x0: Zero sequence series reactance of the entire line section. Default: 0.0 + """ + + possibleProfileList = { + "class": [Profile.EQ.value, Profile.SC.value, ], + "Clamp": [Profile.EQ.value, ], + "Cut": [Profile.EQ.value, ], + "b0ch": [Profile.SC.value, ], + "bch": [Profile.EQ.value, ], + "g0ch": [Profile.SC.value, ], + "gch": [Profile.EQ.value, ], + "r": [Profile.EQ.value, ], + "r0": [Profile.SC.value, ], + "shortCircuitEndTemperature": [Profile.SC.value, ], + "x": [Profile.EQ.value, ], + "x0": [Profile.SC.value, ], + } + + serializationProfile = {} + + recommendedClassProfile = Profile.EQ.value + + __doc__ += "\nDocumentation of parent class Conductor:\n" + Conductor.__doc__ + + def __init__(self, Clamp = "list", Cut = "list", b0ch = 0.0, bch = 0.0, g0ch = 0.0, gch = 0.0, r = 0.0, r0 = 0.0, shortCircuitEndTemperature = 0.0, x = 0.0, x0 = 0.0, *args, **kw_args): + super().__init__(*args, **kw_args) + + self.Clamp = Clamp + self.Cut = Cut + self.b0ch = b0ch + self.bch = bch + self.g0ch = g0ch + self.gch = gch + self.r = r + self.r0 = r0 + self.shortCircuitEndTemperature = shortCircuitEndTemperature + self.x = x + self.x0 = x0 + + def __str__(self): + str = "class=ACLineSegment\n" + attributes = self.__dict__ + for key in attributes.keys(): + str = str + key + "={}\n".format(attributes[key]) + return str ``` ### Modern Python ```python """ -Generated from the CGMES 3 files via cimgen: https://github.com/sogno-platform/cimgen +Generated from the CGMES files via cimgen: https://github.com/sogno-platform/cimgen """ from functools import cached_property from typing import Optional + from pydantic import Field from pydantic.dataclasses import dataclass -from .Base import DataclassConfig, Profile + +from ..utils.profile import BaseProfile, Profile from .Conductor import Conductor -@dataclass(config=DataclassConfig) + +@dataclass class ACLineSegment(Conductor): """ A wire or combination of wires, with consistent electrical characteristics, building a single electrical system, @@ -108,171 +118,177 @@ class ACLineSegment(Conductor): BaseVoltage.nominalVoltage. However, boundary lines may have slightly different BaseVoltage.nominalVoltages and variation is allowed. Larger voltage difference in general requires use of an equivalent branch. - bch: Positive sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. This value - represents the full charging over the full length of the line. - gch: Positive sequence shunt (charging) conductance, uniformly distributed, of the entire line section. - r: Positive sequence series resistance of the entire line section. - x: Positive sequence series reactance of the entire line section. Clamp: The clamps connected to the line segment. Cut: Cuts applied to the line segment. b0ch: Zero sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. - g0ch: Zero sequence shunt (charging) conductance, uniformly distributed, of the entire line section. - r0: Zero sequence series resistance of the entire line section. - shortCircuitEndTemperature: Maximum permitted temperature at the end of SC for the calculation of minimum short- - circuit currents. Used for short circuit data exchange according to IEC 60909. - x0: Zero sequence series reactance of the entire line section. - """ - - bch : float = Field(default=0.0, in_profiles = [Profile.EQ, ]) - - gch : float = Field(default=0.0, in_profiles = [Profile.EQ, ]) - - r : float = Field(default=0.0, in_profiles = [Profile.EQ, ]) - - x : float = Field(default=0.0, in_profiles = [Profile.EQ, ]) - - # *Association not used* - # Type M:0..n in CIM # pylint: disable-next=line-too-long - # Clamp : list = Field(default_factory=list, in_profiles = [Profile.EQ, ]) # noqa: E501 - - # *Association not used* - # Type M:0..n in CIM # pylint: disable-next=line-too-long - # Cut : list = Field(default_factory=list, in_profiles = [Profile.EQ, ]) # noqa: E501 - - b0ch : float = Field(default=0.0, in_profiles = [Profile.SC, ]) - - g0ch : float = Field(default=0.0, in_profiles = [Profile.SC, ]) - - r0 : float = Field(default=0.0, in_profiles = [Profile.SC, ]) - - shortCircuitEndTemperature : float = Field(default=0.0, in_profiles = [Profile.SC, ]) - - x0 : float = Field(default=0.0, in_profiles = [Profile.SC, ]) - - - - @cached_property - def possible_profiles(self)->set[Profile]: - """ - A resource can be used by multiple profiles. This is the set of profiles - where this element can be found. - """ - return { Profile.EQ, Profile.SC, } -``` - -### Modern Python after black (formatting) - -```python -""" -Generated from the CGMES 3 files via cimgen: https://github.com/sogno-platform/cimgen -""" - -from functools import cached_property -from pydantic import Field -from pydantic.dataclasses import dataclass -from .Base import DataclassConfig, Profile -from .Conductor import Conductor - - -@dataclass(config=DataclassConfig) -class ACLineSegment(Conductor): - """ - A wire or combination of wires, with consistent electrical characteristics, building a single electrical system, - used to carry alternating current between points in the power system. For symmetrical, transposed three phase - lines, it is sufficient to use attributes of the line segment, which describe impedances and admittances for - the entire length of the segment. Additionally impedances can be computed by using length and associated per - length impedances. The BaseVoltage at the two ends of ACLineSegments in a Line shall have the same - BaseVoltage.nominalVoltage. However, boundary lines may have slightly different BaseVoltage.nominalVoltages - and variation is allowed. Larger voltage difference in general requires use of an equivalent branch. - bch: Positive sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. This value represents the full charging over the full length of the line. + g0ch: Zero sequence shunt (charging) conductance, uniformly distributed, of the entire line section. gch: Positive sequence shunt (charging) conductance, uniformly distributed, of the entire line section. r: Positive sequence series resistance of the entire line section. - x: Positive sequence series reactance of the entire line section. - Clamp: The clamps connected to the line segment. - Cut: Cuts applied to the line segment. - b0ch: Zero sequence shunt (charging) susceptance, uniformly distributed, of the entire line section. - g0ch: Zero sequence shunt (charging) conductance, uniformly distributed, of the entire line section. r0: Zero sequence series resistance of the entire line section. shortCircuitEndTemperature: Maximum permitted temperature at the end of SC for the calculation of minimum short- circuit currents. Used for short circuit data exchange according to IEC 60909. + x: Positive sequence series reactance of the entire line section. x0: Zero sequence series reactance of the entire line section. """ - bch: float = Field( - default=0.0, - in_profiles=[ - Profile.EQ, - ], + Clamp: list = Field( + default_factory=list, + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": False, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": True, + "is_primitive_attribute": False, + }, ) - gch: float = Field( - default=0.0, - in_profiles=[ - Profile.EQ, - ], + Cut: list = Field( + default_factory=list, + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": False, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": True, + "is_primitive_attribute": False, + }, ) - r: float = Field( + b0ch: float = Field( default=0.0, - in_profiles=[ - Profile.EQ, - ], + json_schema_extra={ + "in_profiles": [ + Profile.SC, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) - x: float = Field( + bch: float = Field( default=0.0, - in_profiles=[ - Profile.EQ, - ], + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) - # *Association not used* - # Type M:0..n in CIM # pylint: disable-next=line-too-long - # Clamp : list = Field(default_factory=list, in_profiles = [Profile.EQ, ]) - - # *Association not used* - # Type M:0..n in CIM # pylint: disable-next=line-too-long - # Cut : list = Field(default_factory=list, in_profiles = [Profile.EQ, ]) + g0ch: float = Field( + default=0.0, + json_schema_extra={ + "in_profiles": [ + Profile.SC, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, + ) - b0ch: float = Field( + gch: float = Field( default=0.0, - in_profiles=[ - Profile.SC, - ], + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) - g0ch: float = Field( + r: float = Field( default=0.0, - in_profiles=[ - Profile.SC, - ], + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) r0: float = Field( default=0.0, - in_profiles=[ - Profile.SC, - ], + json_schema_extra={ + "in_profiles": [ + Profile.SC, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) shortCircuitEndTemperature: float = Field( default=0.0, - in_profiles=[ - Profile.SC, - ], + json_schema_extra={ + "in_profiles": [ + Profile.SC, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, + ) + + x: float = Field( + default=0.0, + json_schema_extra={ + "in_profiles": [ + Profile.EQ, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) x0: float = Field( default=0.0, - in_profiles=[ - Profile.SC, - ], + json_schema_extra={ + "in_profiles": [ + Profile.SC, + ], + "is_used": True, + "is_class_attribute": False, + "is_enum_attribute": False, + "is_list_attribute": False, + "is_primitive_attribute": True, + }, ) @cached_property - def possible_profiles(self) -> set[Profile]: + def possible_profiles(self) -> set[BaseProfile]: """ A resource can be used by multiple profiles. This is the set of profiles where this element can be found. @@ -281,4 +297,12 @@ class ACLineSegment(Conductor): Profile.EQ, Profile.SC, } + + @cached_property + def recommended_profile(self) -> BaseProfile: + """ + This is the profile with most of the attributes. + It should be used to write the data to as few as possible files. + """ + return Profile.EQ ```