Skip to content

Commit eb95a36

Browse files
committed
Changes after review
Signed-off-by: Giovanni Ferrari <[email protected]>
1 parent 07e1c71 commit eb95a36

File tree

5 files changed

+883
-4
lines changed

5 files changed

+883
-4
lines changed

cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/OperationalLimitConversion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public OperationalLimitConversion(PropertyBag l, Context context) {
4747
terminalId = l.getId("Terminal");
4848
equipmentId = l.getId("Equipment");
4949
Terminal terminal = null;
50-
if (limitSubclass.equals(CgmesNames.ACTIVE_POWER_LIMIT) || limitSubclass.equals(CgmesNames.APPARENT_POWER_LIMIT) || limitSubclass.equals(CgmesNames.CURRENT_LIMIT)) {
50+
if (CgmesNames.ACTIVE_POWER_LIMIT.equals(limitSubclass) || CgmesNames.APPARENT_POWER_LIMIT.equals(limitSubclass) || CgmesNames.CURRENT_LIMIT.equals(limitSubclass)) {
5151
if (terminalId != null) {
5252
terminal = context.terminalMapping().findForFlowLimits(terminalId);
5353
}

cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/elements/SynchronousMachineConversion.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class SynchronousMachineConversion extends AbstractReactiveLimitsOwnerCon
3030
public SynchronousMachineConversion(PropertyBag sm, Context context) {
3131
super(CgmesNames.SYNCHRONOUS_MACHINE, sm, context);
3232
String type = p.getLocal("type");
33-
isCondenser = type.equals("SynchronousMachineKind.condenser");
33+
isCondenser = "SynchronousMachineKind.condenser".equals(type);
3434
}
3535

3636
@Override

cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/export/EquipmentExportTest.java

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,26 @@
1717
import com.powsybl.cgmes.conversion.Conversion;
1818
import com.powsybl.cgmes.conversion.export.CgmesExportContext;
1919
import com.powsybl.cgmes.conversion.export.EquipmentExport;
20+
import com.powsybl.cgmes.conversion.export.TopologyExport;
2021
import com.powsybl.cgmes.extensions.*;
2122
import com.powsybl.cgmes.model.CgmesNames;
2223
import com.powsybl.commons.test.AbstractSerDeTest;
2324
import com.powsybl.commons.datasource.DirectoryDataSource;
2425
import com.powsybl.commons.datasource.ReadOnlyDataSource;
26+
import com.powsybl.commons.datasource.ResourceDataSource;
27+
import com.powsybl.commons.datasource.ResourceSet;
2528
import com.powsybl.commons.xml.XmlUtil;
2629
import com.powsybl.computation.local.LocalComputationManager;
2730
import com.powsybl.iidm.network.*;
28-
import com.powsybl.iidm.network.ThreeSides;
2931
import com.powsybl.iidm.network.extensions.RemoteReactivePowerControl;
3032
import com.powsybl.iidm.network.test.*;
3133
import com.powsybl.iidm.serde.ExportOptions;
3234
import com.powsybl.iidm.serde.NetworkSerDe;
35+
import com.powsybl.iidm.serde.XMLImporter;
3336
import com.powsybl.iidm.network.util.BranchData;
3437
import com.powsybl.iidm.network.util.TwtData;
3538

39+
import org.apache.commons.lang3.tuple.Pair;
3640
import org.junit.jupiter.api.BeforeEach;
3741
import org.junit.jupiter.api.Test;
3842
import org.xmlunit.diff.DifferenceEvaluator;
@@ -194,6 +198,145 @@ void microGridCreateEquivalentInjectionAliases() throws IOException, XMLStreamEx
194198
assertTrue(compareNetworksEQdata(expected, actual));
195199
}
196200

201+
@Test
202+
void nordic32() throws IOException, XMLStreamException {
203+
ReadOnlyDataSource dataSource = new ResourceDataSource("nordic32", new ResourceSet("/", "nordic32.xiidm"));
204+
Network network = new XMLImporter().importData(dataSource, NetworkFactory.findDefault(), null);
205+
exportToCgmesEQ(network);
206+
exportToCgmesTP(network);
207+
// Import EQ & TP file, no additional information (boundaries) are required
208+
Network actual = new CgmesImport().importData(new DirectoryDataSource(tmpDir, "exported"), NetworkFactory.findDefault(), null);
209+
210+
// The xiidm file does not contain ratedS values, but during the cgmes export process default values
211+
// are exported for each transformer that are reading in the import process.
212+
// we reset the default imported ratedS values before comparing
213+
TwoWindingsTransformer twta = actual.getTwoWindingsTransformerStream().findFirst().orElseThrow();
214+
network.getTwoWindingsTransformers().forEach(twtn -> twtn.setRatedS(twta.getRatedS()));
215+
216+
// Ignore OperationalLimitsGroup id
217+
DifferenceEvaluator knownDiffs = DifferenceEvaluators.chain(
218+
DifferenceEvaluators.Default,
219+
ExportXmlCompare::numericDifferenceEvaluator,
220+
ExportXmlCompare::ignoringNonEQ,
221+
ExportXmlCompare::ignoringOperationalLimitsGroupId);
222+
assertTrue(compareNetworksEQdata(network, actual, knownDiffs));
223+
}
224+
225+
@Test
226+
void nordic32SortTransformerEnds() throws IOException, XMLStreamException {
227+
ReadOnlyDataSource dataSource = new ResourceDataSource("nordic32", new ResourceSet("/", "nordic32.xiidm"));
228+
Network network = new XMLImporter().importData(dataSource, NetworkFactory.findDefault(), importParams);
229+
exportToCgmesEQ(network, true);
230+
exportToCgmesTP(network);
231+
// Import EQ & TP file, no additional information (boundaries) are required
232+
Network actual = new CgmesImport().importData(new DirectoryDataSource(tmpDir, "exported"), NetworkFactory.findDefault(), null);
233+
// Before comparing, interchange ends in twoWindingsTransformers that do not follow the high voltage at end1 rule
234+
prepareNetworkForSortedTransformerEndsComparison(network);
235+
236+
// The xiidm file does not contain ratedS values, but during the cgmes export process default values
237+
// are exported for each transformer that are reading in the import process.
238+
// we reset the default imported ratedS values before comparing
239+
TwoWindingsTransformer twta = actual.getTwoWindingsTransformerStream().findFirst().orElseThrow();
240+
network.getTwoWindingsTransformers().forEach(twtn -> twtn.setRatedS(twta.getRatedS()));
241+
242+
// Ignore OperationalLimitsGroup id
243+
DifferenceEvaluator knownDiffs = DifferenceEvaluators.chain(
244+
DifferenceEvaluators.Default,
245+
ExportXmlCompare::numericDifferenceEvaluator,
246+
ExportXmlCompare::ignoringNonEQ,
247+
ExportXmlCompare::ignoringOperationalLimitsGroupId);
248+
assertTrue(compareNetworksEQdata(network, actual, knownDiffs));
249+
}
250+
251+
private void prepareNetworkForSortedTransformerEndsComparison(Network network) {
252+
List<Pair<String, TwtRecord>> pairs = new ArrayList<>();
253+
network.getTwoWindingsTransformerStream().filter(twt -> twt
254+
.getTerminal1().getVoltageLevel().getNominalV() < twt.getTerminal2().getVoltageLevel().getNominalV())
255+
.forEach(twt -> {
256+
TwtRecord twtRecord = obtainRecord(twt);
257+
pairs.add(Pair.of(twt.getId(), twtRecord));
258+
});
259+
260+
pairs.forEach(pair -> {
261+
TwoWindingsTransformer twt = network.getTwoWindingsTransformer(pair.getLeft());
262+
twt.remove();
263+
TwoWindingsTransformer newTwt = pair.getRight().getAdder().add();
264+
Optional<CurrentLimits> currentLimits1 = pair.getRight().getCurrentLimits1();
265+
if (currentLimits1.isPresent()) {
266+
newTwt.newCurrentLimits1().setPermanentLimit(currentLimits1.get().getPermanentLimit()).add();
267+
}
268+
Optional<CurrentLimits> currentLimits2 = pair.getRight().getCurrentLimits2();
269+
if (currentLimits2.isPresent()) {
270+
newTwt.newCurrentLimits2().setPermanentLimit(currentLimits2.get().getPermanentLimit()).add();
271+
}
272+
pair.getRight().getAliases().forEach(aliasPair -> {
273+
if (aliasPair.getLeft() == null) {
274+
newTwt.addAlias(aliasPair.getRight());
275+
} else {
276+
newTwt.addAlias(aliasPair.getRight(), aliasPair.getLeft());
277+
}
278+
});
279+
});
280+
}
281+
282+
private TwtRecord obtainRecord(TwoWindingsTransformer twt) {
283+
Substation substation = twt.getSubstation().orElseThrow();
284+
double a0 = twt.getRatedU1() / twt.getRatedU2();
285+
double a02 = a0 * a0;
286+
TwoWindingsTransformerAdder adder = substation.newTwoWindingsTransformer()
287+
.setId(twt.getId())
288+
.setName(twt.getNameOrId())
289+
.setBus1(twt.getTerminal2().getBusBreakerView().getBus().getId())
290+
.setBus2(twt.getTerminal1().getBusBreakerView().getBus().getId())
291+
.setR(twt.getR() * a02)
292+
.setX(twt.getX() * a02)
293+
.setG(twt.getG() / a02)
294+
.setB(twt.getB() / a02)
295+
.setRatedU1(twt.getRatedU2())
296+
.setRatedU2(twt.getRatedU1());
297+
298+
CurrentLimits currentLimits1 = twt.getCurrentLimits1().orElse(null);
299+
CurrentLimits currentLimits2 = twt.getCurrentLimits2().orElse(null);
300+
301+
List<Pair<String, String>> aliases = new ArrayList<>();
302+
twt.getAliases().forEach(alias -> {
303+
String type = twt.getAliasType(alias).orElse(null);
304+
aliases.add(Pair.of(type, alias));
305+
});
306+
return new TwtRecord(adder, currentLimits2, currentLimits1, aliases);
307+
}
308+
309+
private static final class TwtRecord {
310+
private final TwoWindingsTransformerAdder adder;
311+
private final CurrentLimits currentLimits1;
312+
private final CurrentLimits currentLimits2;
313+
private final List<Pair<String, String>> aliases;
314+
315+
private TwtRecord(TwoWindingsTransformerAdder adder, CurrentLimits currentLimits1, CurrentLimits currentLimits2,
316+
List<Pair<String, String>> aliases) {
317+
this.adder = adder;
318+
this.currentLimits1 = currentLimits1;
319+
this.currentLimits2 = currentLimits2;
320+
this.aliases = aliases;
321+
}
322+
323+
private TwoWindingsTransformerAdder getAdder() {
324+
return adder;
325+
}
326+
327+
private Optional<CurrentLimits> getCurrentLimits1() {
328+
return Optional.ofNullable(currentLimits1);
329+
}
330+
331+
private Optional<CurrentLimits> getCurrentLimits2() {
332+
return Optional.ofNullable(currentLimits2);
333+
}
334+
335+
private List<Pair<String, String>> getAliases() {
336+
return aliases;
337+
}
338+
}
339+
197340
@Test
198341
void bPerSectionTest() throws IOException, XMLStreamException {
199342
ReadOnlyDataSource ds = CgmesConformity1Catalog.microGridType4BE().dataSource();
@@ -1525,6 +1668,18 @@ private Path exportToCgmesEQ(Network network, boolean transformersWithHighestVol
15251668
return exportedEq;
15261669
}
15271670

1671+
private Path exportToCgmesTP(Network network) throws IOException, XMLStreamException {
1672+
// Export CGMES EQ file
1673+
Path exportedTp = tmpDir.resolve("exportedTp.xml");
1674+
try (OutputStream os = new BufferedOutputStream(Files.newOutputStream(exportedTp))) {
1675+
XMLStreamWriter writer = XmlUtil.initializeWriter(true, " ", os);
1676+
CgmesExportContext context = new CgmesExportContext(network);
1677+
TopologyExport.write(network, writer, context);
1678+
}
1679+
1680+
return exportedTp;
1681+
}
1682+
15281683
private boolean compareNetworksEQdata(Network expected, Network actual) {
15291684
DifferenceEvaluator knownDiffs = DifferenceEvaluators.chain(
15301685
DifferenceEvaluators.Default,

0 commit comments

Comments
 (0)