Skip to main content

surge_network/network/
boundary.rs

1// SPDX-License-Identifier: LicenseRef-PolyForm-Noncommercial-1.0.0
2//! ENTSO-E boundary profile types — TSO-TSO interconnection points,
3//! model authority sets, and external network equivalents (EQBD/BD).
4
5use serde::{Deserialize, Serialize};
6
7/// A TSO-TSO boundary point from the ENTSO-E EQBD profile.
8///
9/// Represents an interconnection point between two control areas (typically
10/// national TSOs). The `connectivity_node_mrid` links to the CIM
11/// `ConnectivityNode` at the boundary; the resolved `bus` is filled in
12/// during network building when the CN can be mapped to a topological bus.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct BoundaryPoint {
15    /// CIM mRID of the BoundaryPoint object.
16    pub mrid: String,
17    /// mRID of the ConnectivityNode at the boundary.
18    pub connectivity_node_mrid: Option<String>,
19    /// ISO 3166 country code of one side (e.g., "DE").
20    pub from_end_iso_code: Option<String>,
21    /// ISO 3166 country code of the other side (e.g., "FR").
22    pub to_end_iso_code: Option<String>,
23    /// Human-readable name of the "from" end TSO.
24    pub from_end_name: Option<String>,
25    /// Human-readable name of the "to" end TSO.
26    pub to_end_name: Option<String>,
27    /// Short TSO name for the "from" end.
28    pub from_end_name_tso: Option<String>,
29    /// Short TSO name for the "to" end.
30    pub to_end_name_tso: Option<String>,
31    /// True if this is a DC interconnection (HVDC tie).
32    pub is_direct_current: bool,
33    /// True if this boundary point is excluded from area interchange accounting.
34    pub is_excluded_from_area_interchange: bool,
35    /// Resolved bus number (set when the CN maps to a topological bus).
36    pub bus: Option<u32>,
37}
38
39/// Model authority set — TSO ownership of CIM equipment.
40///
41/// Each `ModelAuthoritySet` identifies a TSO or model authority and lists
42/// the equipment mRIDs that belong to it. Used for multi-TSO model merging
43/// (CGM assembly) to track which authority owns which equipment.
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct ModelAuthoritySet {
46    /// CIM mRID of the ModelAuthoritySet.
47    pub mrid: String,
48    /// TSO identifier / short name.
49    pub name: String,
50    /// Full description of the authority.
51    pub description: Option<String>,
52    /// Equipment mRIDs owned by this authority (reverse-lookup from
53    /// `IdentifiedObject.ModelAuthoritySet` references).
54    pub members: Vec<String>,
55}
56
57/// External network equivalent — represents a reduced model of a
58/// neighbouring control area or external system.
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct EquivalentNetworkData {
61    /// CIM mRID.
62    pub mrid: String,
63    /// Name of the equivalent network.
64    pub name: String,
65    /// Description.
66    pub description: Option<String>,
67    /// mRID of the `SubGeographicalRegion` / `GeographicalRegion` this
68    /// equivalent represents.
69    pub region_mrid: Option<String>,
70}
71
72/// External network branch equivalent — a pi-section branch representing
73/// the impedance of a reduced external network.
74///
75/// Impedances are stored in physical ohms (as in the CIM source); downstream
76/// code converts to per-unit when wiring into the admittance matrix.
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct EquivalentBranchData {
79    /// CIM mRID.
80    pub mrid: String,
81    /// Parent `EquivalentNetwork` mRID.
82    pub network_mrid: Option<String>,
83    /// Positive-sequence resistance (Ohm).
84    pub r_ohm: f64,
85    /// Positive-sequence reactance (Ohm).
86    pub x_ohm: f64,
87    /// Zero-sequence resistance (Ohm), if available.
88    pub r0_ohm: Option<f64>,
89    /// Zero-sequence reactance (Ohm), if available.
90    pub x0_ohm: Option<f64>,
91    /// Negative-sequence resistance (Ohm), if available.
92    pub r2_ohm: Option<f64>,
93    /// Negative-sequence reactance (Ohm), if available.
94    pub x2_ohm: Option<f64>,
95    /// Resolved from-bus number.
96    pub from_bus: Option<u32>,
97    /// Resolved to-bus number.
98    pub to_bus: Option<u32>,
99}
100
101/// External network shunt equivalent — a constant-admittance shunt
102/// representing the reduced external network contribution at a boundary bus.
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct EquivalentShuntData {
105    /// CIM mRID.
106    pub mrid: String,
107    /// Parent `EquivalentNetwork` mRID.
108    pub network_mrid: Option<String>,
109    /// Conductance (Siemens).
110    pub g_s: f64,
111    /// Susceptance (Siemens).
112    pub b_s: f64,
113    /// Resolved bus number.
114    pub bus: Option<u32>,
115}
116
117/// Container for all boundary and external equivalent data from the
118/// ENTSO-E EQBD/BD profile.
119///
120/// Stored on `Network::boundary_data`.
121/// Empty by default for non-CGMES cases.
122#[derive(Debug, Clone, Default, Serialize, Deserialize)]
123pub struct BoundaryData {
124    /// TSO-TSO boundary points.
125    pub boundary_points: Vec<BoundaryPoint>,
126    /// Model authority sets (TSO ownership).
127    pub model_authority_sets: Vec<ModelAuthoritySet>,
128    /// External equivalent networks.
129    pub equivalent_networks: Vec<EquivalentNetworkData>,
130    /// External equivalent branches.
131    pub equivalent_branches: Vec<EquivalentBranchData>,
132    /// External equivalent shunts.
133    pub equivalent_shunts: Vec<EquivalentShuntData>,
134}
135
136impl BoundaryData {
137    /// Returns `true` if no boundary data has been populated.
138    pub fn is_empty(&self) -> bool {
139        self.boundary_points.is_empty()
140            && self.model_authority_sets.is_empty()
141            && self.equivalent_networks.is_empty()
142            && self.equivalent_branches.is_empty()
143            && self.equivalent_shunts.is_empty()
144    }
145}