diff --git a/cgmes/cgmes-conformity/src/main/java/com/powsybl/cgmes/conformity/CgmesConformity1ModifiedCatalog.java b/cgmes/cgmes-conformity/src/main/java/com/powsybl/cgmes/conformity/CgmesConformity1ModifiedCatalog.java
index 587eee314c4..7580c6a161d 100644
--- a/cgmes/cgmes-conformity/src/main/java/com/powsybl/cgmes/conformity/CgmesConformity1ModifiedCatalog.java
+++ b/cgmes/cgmes-conformity/src/main/java/com/powsybl/cgmes/conformity/CgmesConformity1ModifiedCatalog.java
@@ -1561,6 +1561,20 @@ public static GridModelReference microGridBaseBEInvalidVoltageBus() {
microGridBaseCaseBoundaries());
}
+ public static GridModelReference microGridBaseCaseBELineDisconnectedAtBoundaryNode() {
+ String base = ENTSOE_CONFORMITY_1_MODIFIED
+ + "/MicroGrid/BaseCase/BC_BE_v2_line_disconnected_at_boundary_node/";
+ return new GridModelReferenceResources(
+ "MicroGrid-BaseCase-BE-line-disconnected-at-boundary-node",
+ null,
+ new ResourceSet(base,
+ MICRO_GRID_BE_SSH),
+ new ResourceSet(MICRO_GRID_BE_BASE,
+ MICRO_GRID_BE_EQ,
+ MICRO_GRID_BE_TP),
+ microGridBaseCaseBoundaries());
+ }
+
public static GridModelReferenceResources smallGridBusBranchWithBusbarSectionsAndIpMax() {
String base = ENTSOE_CONFORMITY_1_MODIFIED
+ "/SmallGrid/BusBranch_busbarSections_ipMax";
diff --git a/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_line_disconnected_at_boundary_node/MicroGridTestConfiguration_BC_BE_SSH_V2.xml b/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_line_disconnected_at_boundary_node/MicroGridTestConfiguration_BC_BE_SSH_V2.xml
new file mode 100644
index 00000000000..3338257bca9
--- /dev/null
+++ b/cgmes/cgmes-conformity/src/main/resources/conformity-modified/cas-1.1.3-data-4.0.3/MicroGrid/BaseCase/BC_BE_v2_line_disconnected_at_boundary_node/MicroGridTestConfiguration_BC_BE_SSH_V2.xml
@@ -0,0 +1,286 @@
+
+
+
+ 2014-10-24T11:42:40
+ 2014-06-01T10:30:00
+ 2
+
+ CGMES Conformity Assessment: 'MicroGridTestConfiguration....BC (MAS BE) Test Configuration. The model is owned by ENTSO-E and is provided by ENTSO-E “as it is”. To the fullest extent permitted by law, ENTSO-E shall not be liable for any damages of any kind arising out of the use of the model (including any of its subsequent modifications). ENTSO-E neither warrants, nor represents that the use of the model will not infringe the rights of third parties. Any use of the model shall include a reference to ENTSO-E. ENTSO-E web site is the only official source of information related to the model.
+ http://elia.be/CGMES/2.4.15
+ http://entsoe.eu/CIM/SteadyStateHypothesis/1/1
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ 1.000000
+ 0e+000
+
+
+ 200.000000
+ 90.000000
+
+
+ 200.000000
+ 50.000000
+
+
+ 0e+000
+
+
+ -118.000000
+ -18.720301
+
+ 0
+ true
+
+
+ 0e+000
+
+
+ -90.000000
+ -100.256000
+
+ 0
+ true
+
+
+ 10
+ true
+
+
+ 10
+ false
+
+
+ 14
+ true
+
+
+ 17
+ false
+
+
+ 1
+ false
+
+
+ 1
+ false
+
+
+ -26.805006
+ 1.489867
+ false
+ 0.0
+
+
+ -27.365225
+ 0.425626
+ false
+ 0.0
+
+
+ -43.687227
+ 84.876604
+ false
+ 0.0
+
+
+ -46.816625
+ 79.193778
+ false
+ 0.0
+
+
+ -90.037005
+ 148.603743
+ false
+ 0.0
+
+
+ true
+ 35.00000
+
+ true
+ -65.000000
+
+
+ true
+ 0.500000
+
+ false
+ 0e+000
+
+
+ true
+ 0.500000
+
+ true
+ 10.815000
+
+
+ true
+ 0.500000
+
+ false
+ 0e+000
+
+
+ false
+ 0.500000
+
+ true
+ 21.987000
+
+
+ false
+ 0.500000
+
+ true
+ 115.500000
+
+
+ true
+ 0.500000
+
+ false
+ 110.000000
+
+
+ true
+ 0.500000
+
+ false
+ 380.000000
+
+
diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java
index 4f177e69a85..e282966e27a 100644
--- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java
+++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesImport.java
@@ -277,6 +277,12 @@ private Conversion.Config config(ReadOnlyDataSource ds, Properties p) {
getFormat(),
p,
IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER,
+ defaultValueConfig))
+ .setDisconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected(
+ Parameter.readBoolean(
+ getFormat(),
+ p,
+ DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER,
defaultValueConfig));
String namingStrategy = Parameter.readString(getFormat(), p, NAMING_STRATEGY_PARAMETER, defaultValueConfig);
String idMappingFilePath = Parameter.readString(getFormat(), p, ID_MAPPING_FILE_PATH_PARAMETER, defaultValueConfig);
@@ -350,6 +356,7 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
public static final String STORE_CGMES_MODEL_AS_NETWORK_EXTENSION = "iidm.import.cgmes.store-cgmes-model-as-network-extension";
public static final String STORE_CGMES_CONVERSION_CONTEXT_AS_NETWORK_EXTENSION = "iidm.import.cgmes.store-cgmes-conversion-context-as-network-extension";
public static final String IMPORT_NODE_BREAKER_AS_BUS_BREAKER = "iidm.import.cgmes.import-node-breaker-as-bus-breaker";
+ public static final String DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED = "iidm.import.cgmes.disconnect-dangling-line-if-boundary-side-is-disconnected";
public static final String SOURCE_FOR_IIDM_ID_MRID = "mRID";
public static final String SOURCE_FOR_IIDM_ID_RDFID = "rdfID";
@@ -459,6 +466,11 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
ParameterType.BOOLEAN,
"Force import of CGMES node/breaker models as bus/breaker",
Boolean.FALSE);
+ public static final Parameter DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER = new Parameter(
+ DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED,
+ ParameterType.BOOLEAN,
+ "Force disconnection of dangling line network side if boundary side is disconnected",
+ Boolean.TRUE);
private static final List STATIC_PARAMETERS = List.of(
ALLOW_UNSUPPORTED_TAP_CHANGERS_PARAMETER,
@@ -478,7 +490,8 @@ private void copyStream(ReadOnlyDataSource from, DataSource to, String fromName,
CREATE_ACTIVE_POWER_CONTROL_EXTENSION_PARAMETER,
DECODE_ESCAPED_IDENTIFIERS_PARAMETER,
CREATE_FICTITIOUS_SWITCHES_FOR_DISCONNECTED_TERMINALS_MODE_PARAMETER,
- IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER);
+ IMPORT_NODE_BREAKER_AS_BUS_BREAKER_PARAMETER,
+ DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED_PARAMETER);
private final Parameter boundaryLocationParameter;
private final Parameter preProcessorsParameter;
diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java
index 7f2fb0967e2..9ddedddfa97 100644
--- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java
+++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/CgmesReports.java
@@ -85,4 +85,13 @@ public static void inconsistentProfilesTPRequiredReport(Reporter reporter, Strin
.withSeverity(TypedValue.ERROR_SEVERITY)
.build());
}
+
+ public static void danglingLineDisconnectedAtBoundaryHasBeenDisconnectedReport(Reporter reporter, String danglingLineId) {
+ reporter.report(Report.builder()
+ .withKey("danglingLineDisconnectedAtBoundaryHasBeenDisconnected")
+ .withDefaultMessage("DanglingLine ${danglingLineId} was connected at network side and disconnected at boundary side. It has been disconnected also at network side.")
+ .withValue("danglingLineId", danglingLineId)
+ .withSeverity(TypedValue.WARN_SEVERITY)
+ .build());
+ }
}
diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java
index bc661a590af..aad27e9703a 100644
--- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java
+++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/Conversion.java
@@ -239,6 +239,7 @@ public Network convert(Reporter reporter) {
}
// apply post-processors
+ handleDangingLineDisconnectedAtBoundary(network, context);
for (CgmesImportPostProcessor postProcessor : postProcessors) {
// FIXME generic cgmes models may not have an underlying triplestore
// TODO maybe pass the properties to the post processors
@@ -258,6 +259,28 @@ public Network convert(Reporter reporter) {
return network;
}
+ private void handleDangingLineDisconnectedAtBoundary(Network network, Context context) {
+ if (config.disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected()) {
+ for (DanglingLine dl : network.getDanglingLines()) {
+ String terminalBoundaryId = dl.getAliasFromType(Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + "Terminal_Boundary").orElse(null);
+ if (terminalBoundaryId == null) {
+ LOG.warn("Dangling line {}: alias for terminal at boundary is missing", dl.getId());
+ } else {
+ CgmesTerminal terminalBoundary = cgmes.terminal(terminalBoundaryId);
+ if (terminalBoundary == null) {
+ LOG.warn("Dangling line {}: terminal at boundary with id {} is not found in CGMES model", dl.getId(), terminalBoundaryId);
+ } else {
+ if (!terminalBoundary.connected() && dl.getTerminal().isConnected()) {
+ LOG.warn("DanglingLine {} was connected at network side and disconnected at boundary side. It has been disconnected also at network side.", dl.getId());
+ CgmesReports.danglingLineDisconnectedAtBoundaryHasBeenDisconnectedReport(context.getReporter(), dl.getId());
+ dl.getTerminal().disconnect();
+ }
+ }
+ }
+ }
+ }
+ }
+
private Source isBoundaryBaseVoltage(String graph) {
//There are unit tests where the boundary file contains the sequence "EQBD" and others "EQ_BD"
return graph.contains("EQ") && graph.contains("BD") ? Source.BOUNDARY : Source.IGM;
@@ -913,6 +936,15 @@ public Config createFictitiousSwitchesForDisconnectedTerminalsMode(CgmesImport.F
return this;
}
+ public Config setDisconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected(boolean b) {
+ disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected = b;
+ return this;
+ }
+
+ public boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected() {
+ return disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected;
+ }
+
private boolean allowUnsupportedTapChangers = true;
private boolean convertBoundary = false;
private boolean changeSignForShuntReactivePowerFlowInitialState = false;
@@ -931,6 +963,7 @@ public Config createFictitiousSwitchesForDisconnectedTerminalsMode(CgmesImport.F
private boolean ensureIdAliasUnicity = false;
private boolean importControlAreas = true;
private boolean importNodeBreakerAsBusBreaker = false;
+ private boolean disconnectNetworkSideOfDanglingLinesIfBoundaryIsDisconnected = true;
private NamingStrategy namingStrategy = new NamingStrategy.Identity();
diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java
index c09d81b7db3..4c6f869d5e4 100644
--- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java
+++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/conformity/modified/CgmesConformity1ModifiedConversionTest.java
@@ -997,6 +997,22 @@ void microGridBaseBETargetDeadbandNegative() {
assertFalse(rtc.isRegulating());
}
+ @Test
+ void microGridBELineDisconnectedAtBoundaryNode() {
+ Properties importParams = new Properties();
+ String dlId = "17086487-56ba-4979-b8de-064025a6b4da";
+
+ importParams.setProperty(CgmesImport.DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED, "true");
+ Network be0 = Network.read(CgmesConformity1ModifiedCatalog.microGridBaseCaseBELineDisconnectedAtBoundaryNode().dataSource(), importParams);
+ Bus bus0 = be0.getDanglingLine(dlId).getTerminal().getBusView().getBus();
+ assertNull(bus0);
+
+ importParams.setProperty(CgmesImport.DISCONNECT_DANGLING_LINE_IF_BOUNDARY_SIDE_IS_DISCONNECTED, "false");
+ Network be1 = Network.read(CgmesConformity1ModifiedCatalog.microGridBaseCaseBELineDisconnectedAtBoundaryNode().dataSource(), importParams);
+ Bus bus1 = be1.getDanglingLine(dlId).getTerminal().getBusView().getBus();
+ assertNotNull(bus1);
+ }
+
private static void checkTerminals(PropertyBags eqSeq, PropertyBags eqNoSeq, String idPropertyName, String terminal1PropertyName, String terminal2PropertyName) {
Map eqsSeqTerminal1 = eqSeq.stream().collect(Collectors.toMap(acls -> acls.getId(idPropertyName), acls -> acls.getId(terminal1PropertyName)));
Map eqsSeqTerminal2 = eqSeq.stream().collect(Collectors.toMap(acls -> acls.getId(idPropertyName), acls -> acls.getId(terminal2PropertyName)));