Skip to main content

cimstructs/
RegulatingControl.rs

1/// Specifies a set of equipment that works together to control a power system quantity such as voltage or flow. Remote bus voltage control is possible by specifying the controlled terminal located at some place remote from the controlling equipment. The specified terminal shall be associated with the connectivity node of the controlled point. The most specific subtype of RegulatingControl shall be used in case such equipment participate in the control, e.g. TapChangerControl for tap changers. For flow control, load sign convention is used, i.e. positive sign means flow out from a TopologicalNode (bus) into the conducting equipment. The attribute minAllowedTargetValue and maxAllowedTargetValue are required in the following cases: - For a power generating module operated in power factor control mode to specify maximum and minimum power factor values; - Whenever it is necessary to have an off center target voltage for the tap changer regulator. For instance, due to long cables to off shore wind farms and the need to have a simpler setup at the off shore transformer platform, the voltage is controlled from the land at the connection point for the off shore wind farm. Since there usually is a voltage rise along the cable, there is typical and overvoltage of up 3-4 kV compared to the on shore station. Thus in normal operation the tap changer on the on shore station is operated with a target set point, which is in the lower parts of the dead band. The attributes minAllowedTargetValue and maxAllowedTargetValue are not related to the attribute targetDeadband and thus they are not treated as an alternative of the targetDeadband. They are needed due to limitations in the local substation controller. The attribute targetDeadband is used to prevent the power flow from move the tap position in circles (hunting) that is to be used regardless of the attributes minAllowedTargetValue and maxAllowedTargetValue.
2#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
3pub struct RegulatingControl {
4    #[serde(flatten)]
5    pub base: super::PowerSystemResource,
6    /// The terminal associated with this regulating control. The terminal is associated instead of a node, since the terminal could connect into either a topological node or a connectivity node. Sometimes it is useful to model regulation at a terminal of a bus bar object.
7    #[serde(skip_serializing_if = "Option::is_none")]
8    pub terminal: Option<super::base::MridRef>,
9    /// The regulation is performed in a discrete mode. This applies to equipment with discrete controls, e.g. tap changers and shunt compensators.
10    #[serde(skip_serializing_if = "Option::is_none")]
11    pub discrete: Option<bool>,
12    /// The flag tells if regulation is enabled.
13    #[serde(skip_serializing_if = "Option::is_none")]
14    pub enabled: Option<bool>,
15    /// Maximum allowed target value (RegulatingControl.targetValue).
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub max_allowed_target_value: Option<f64>,
18    /// Minimum allowed target value (RegulatingControl.targetValue).
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub min_allowed_target_value: Option<f64>,
21    /// The regulating control mode presently available. This specification allows for determining the kind of regulation without need for obtaining the units from a schedule.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub mode: Option<super::base::UriRef>,
24    /// This is a deadband used with discrete control to avoid excessive update of controls like tap changers and shunt compensator banks while regulating. The units of those appropriate for the mode. The attribute shall be a positive value or zero. If RegulatingControl.discrete is set to 'false', the RegulatingControl.targetDeadband is to be ignored. Note that for instance, if the targetValue is 100 kV and the targetDeadband is 2 kV the range is from 99 to 101 kV.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub target_deadband: Option<f64>,
27    /// The target value specified for case input. This value can be used for the target value without the use of schedules. The value has the units appropriate to the mode attribute.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub target_value: Option<f64>,
30    /// Specify the multiplier for used for the targetValue.
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub target_value_unit_multiplier: Option<super::base::UriRef>,
33}
34impl crate::base::CimElement for RegulatingControl {
35    fn mrid(&self) -> &str { &self.base.base.id }
36    fn type_name(&self) -> &'static str { "RegulatingControl" }
37    fn as_any(&self) -> &dyn std::any::Any { self }
38    fn to_json_value(&self) -> serde_json::Value {
39        serde_json::to_value(self).unwrap_or(serde_json::Value::Null)
40    }
41    fn to_block(&self) -> crate::base::RdfBlock {
42        let mut block = self.base.to_block();
43        block.type_name = "RegulatingControl".to_string();
44        if let Some(ref v) = self.terminal {
45            block.fields.insert("RegulatingControl.Terminal".into(), crate::base::FieldValue::Resource(v.mrid.clone()));
46        }
47        if let Some(v) = self.discrete {
48            block.fields.insert("RegulatingControl.discrete".into(), crate::base::FieldValue::Text(v.to_string()));
49        }
50        if let Some(v) = self.enabled {
51            block.fields.insert("RegulatingControl.enabled".into(), crate::base::FieldValue::Text(v.to_string()));
52        }
53        if let Some(v) = self.max_allowed_target_value {
54            block.fields.insert("RegulatingControl.maxAllowedTargetValue".into(), crate::base::FieldValue::Text(v.to_string()));
55        }
56        if let Some(v) = self.min_allowed_target_value {
57            block.fields.insert("RegulatingControl.minAllowedTargetValue".into(), crate::base::FieldValue::Text(v.to_string()));
58        }
59        if let Some(ref v) = self.mode {
60            block.fields.insert("RegulatingControl.mode".into(), crate::base::FieldValue::Resource(v.uri.clone()));
61        }
62        if let Some(v) = self.target_deadband {
63            block.fields.insert("RegulatingControl.targetDeadband".into(), crate::base::FieldValue::Text(v.to_string()));
64        }
65        if let Some(v) = self.target_value {
66            block.fields.insert("RegulatingControl.targetValue".into(), crate::base::FieldValue::Text(v.to_string()));
67        }
68        if let Some(ref v) = self.target_value_unit_multiplier {
69            block.fields.insert("RegulatingControl.targetValueUnitMultiplier".into(), crate::base::FieldValue::Resource(v.uri.clone()));
70        }
71        block
72    }
73}
74
75impl RegulatingControl {
76    pub fn from_block(b: &crate::base::RdfBlock) -> Self {
77        let mut obj = Self::default();
78        obj.base.base.id.clone_from(&b.mrid);
79        for (key, val) in &b.fields {
80            match key.as_str() {
81                "RegulatingControl.Terminal" => {
82                    if let crate::base::FieldValue::Resource(sv) = val {
83                        obj.terminal = Some(crate::base::MridRef { mrid: sv.clone() });
84                    }
85                }
86                "RegulatingControl.discrete" => {
87                    match val {
88                        crate::base::FieldValue::Text(sv) => { obj.discrete = Some(sv.trim() == "true"); }
89                        crate::base::FieldValue::TextList(svs) => {
90                            if let Some(sv) = svs.last() { obj.discrete = Some(sv.trim() == "true"); }
91                        }
92                        _ => {}
93                    }
94                }
95                "RegulatingControl.enabled" => {
96                    match val {
97                        crate::base::FieldValue::Text(sv) => { obj.enabled = Some(sv.trim() == "true"); }
98                        crate::base::FieldValue::TextList(svs) => {
99                            if let Some(sv) = svs.last() { obj.enabled = Some(sv.trim() == "true"); }
100                        }
101                        _ => {}
102                    }
103                }
104                "RegulatingControl.maxAllowedTargetValue" => {
105                    match val {
106                        crate::base::FieldValue::Text(sv) => { if let Ok(v) = sv.trim().parse() { obj.max_allowed_target_value = Some(v); } }
107                        crate::base::FieldValue::TextList(svs) => {
108                            if let Some(sv) = svs.last() { if let Ok(v) = sv.trim().parse() { obj.max_allowed_target_value = Some(v); } }
109                        }
110                        _ => {}
111                    }
112                }
113                "RegulatingControl.minAllowedTargetValue" => {
114                    match val {
115                        crate::base::FieldValue::Text(sv) => { if let Ok(v) = sv.trim().parse() { obj.min_allowed_target_value = Some(v); } }
116                        crate::base::FieldValue::TextList(svs) => {
117                            if let Some(sv) = svs.last() { if let Ok(v) = sv.trim().parse() { obj.min_allowed_target_value = Some(v); } }
118                        }
119                        _ => {}
120                    }
121                }
122                "RegulatingControl.mode" => {
123                    if let crate::base::FieldValue::Resource(sv) = val {
124                        obj.mode = Some(crate::base::UriRef { uri: sv.clone() });
125                    }
126                }
127                "RegulatingControl.targetDeadband" => {
128                    match val {
129                        crate::base::FieldValue::Text(sv) => { if let Ok(v) = sv.trim().parse() { obj.target_deadband = Some(v); } }
130                        crate::base::FieldValue::TextList(svs) => {
131                            if let Some(sv) = svs.last() { if let Ok(v) = sv.trim().parse() { obj.target_deadband = Some(v); } }
132                        }
133                        _ => {}
134                    }
135                }
136                "RegulatingControl.targetValue" => {
137                    match val {
138                        crate::base::FieldValue::Text(sv) => { if let Ok(v) = sv.trim().parse() { obj.target_value = Some(v); } }
139                        crate::base::FieldValue::TextList(svs) => {
140                            if let Some(sv) = svs.last() { if let Ok(v) = sv.trim().parse() { obj.target_value = Some(v); } }
141                        }
142                        _ => {}
143                    }
144                }
145                "RegulatingControl.targetValueUnitMultiplier" => {
146                    if let crate::base::FieldValue::Resource(sv) = val {
147                        obj.target_value_unit_multiplier = Some(crate::base::UriRef { uri: sv.clone() });
148                    }
149                }
150                "IdentifiedObject.description" => {
151                    match val {
152                        crate::base::FieldValue::Text(sv) => { obj.base.base.description = sv.clone(); }
153                        crate::base::FieldValue::TextList(svs) => {
154                            if let Some(sv) = svs.last() { obj.base.base.description = sv.clone(); }
155                        }
156                        _ => {}
157                    }
158                }
159                "IdentifiedObject.energyIdentCodeEic" => {
160                    match val {
161                        crate::base::FieldValue::Text(sv) => { obj.base.base.energy_ident_code_eic = sv.clone(); }
162                        crate::base::FieldValue::TextList(svs) => {
163                            if let Some(sv) = svs.last() { obj.base.base.energy_ident_code_eic = sv.clone(); }
164                        }
165                        _ => {}
166                    }
167                }
168                "IdentifiedObject.mRID" => {
169                    match val {
170                        crate::base::FieldValue::Text(sv) => { obj.base.base.m_rid = sv.clone(); }
171                        crate::base::FieldValue::TextList(svs) => {
172                            if let Some(sv) = svs.last() { obj.base.base.m_rid = sv.clone(); }
173                        }
174                        _ => {}
175                    }
176                }
177                "IdentifiedObject.name" => {
178                    match val {
179                        crate::base::FieldValue::Text(sv) => { obj.base.base.name = sv.clone(); }
180                        crate::base::FieldValue::TextList(svs) => {
181                            if let Some(sv) = svs.last() { obj.base.base.name = sv.clone(); }
182                        }
183                        _ => {}
184                    }
185                }
186                "IdentifiedObject.shortName" => {
187                    match val {
188                        crate::base::FieldValue::Text(sv) => { obj.base.base.short_name = sv.clone(); }
189                        crate::base::FieldValue::TextList(svs) => {
190                            if let Some(sv) = svs.last() { obj.base.base.short_name = sv.clone(); }
191                        }
192                        _ => {}
193                    }
194                }
195                _ => {}
196            }
197        }
198        obj
199    }
200}