Skip to content

Commit

Permalink
Use PowerTransformerEnd.endNumber to sort transformer windings (#3234)
Browse files Browse the repository at this point in the history
* Use PowerTransformerEnd.endNumber instead of Terminal.sequenceNumber to sort transformer windings
* Add an UNKNOWN value to the WindingType enum
* Simplify sorting of transformerends

Signed-off-by: Romain Courtier <[email protected]>
  • Loading branch information
rcourtier authored Jan 10, 2025
1 parent d86cb2b commit 9c18cc5
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.powsybl.cgmes.extensions.CgmesTapChangers;
import com.powsybl.cgmes.extensions.CgmesTapChangersAdder;
import com.powsybl.cgmes.model.CgmesNames;
import com.powsybl.cgmes.model.WindingType;
import com.powsybl.iidm.network.*;
import com.powsybl.triplestore.api.PropertyBag;
import com.powsybl.triplestore.api.PropertyBags;
Expand Down Expand Up @@ -111,10 +112,8 @@ protected CgmesRegulatingControlPhase setContextRegulatingDataPhase(TapChanger t
@Override
protected void addAliasesAndProperties(Identifiable<?> identifiable) {
super.addAliasesAndProperties(identifiable);
int end = 1;
for (PropertyBag p : ps) {
identifiable.addAlias(p.getId("TransformerEnd"), Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TRANSFORMER_END + end);
end++;
identifiable.addAlias(p.getId("TransformerEnd"), Conversion.CGMES_PREFIX_ALIAS_PROPERTIES + CgmesNames.TRANSFORMER_END + WindingType.endNumber(p));
}
List<String> ptcs = context.cgmes().phaseTapChangerListForPowerTransformer(identifiable.getId());
if (ptcs != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Luma Zamarreño {@literal <zamarrenolm at aia.es>}
Expand Down Expand Up @@ -202,16 +201,7 @@ private Map<String, PropertyBags> computeGroupedTransformerEnds() {
powerTransformerRatioTapChanger.get(id)[end.asInt(endNumber, 1) - 1] = end.getId("RatioTapChanger");
}
});
gends.entrySet()
.forEach(tends -> {
PropertyBags tends1 = new PropertyBags(
tends.getValue().stream()
.sorted(Comparator
.comparing(WindingType::fromTransformerEnd)
.thenComparing(end -> end.asInt(endNumber, -1)))
.collect(Collectors.toList()));
tends.setValue(tends1);
});
gends.values().forEach(tends -> tends.sort(Comparator.comparing(WindingType::endNumber)));
return gends;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,39 @@
*/
public enum WindingType {

PRIMARY, SECONDARY, TERTIARY;

public static WindingType fromTransformerEnd(PropertyBag end) {
// For CIM14 (CIM ENTSOE Profile1) primary is determined by windingType
// For CIM16 (CGMES) primary is defined by the corresponding terminal sequence number:
// "The Terminal.sequenceNumber distinguishes the terminals much as previously done by
// TransformerWinding.windingType:WindingType"
UNKNOWN, PRIMARY, SECONDARY, TERTIARY;

/**
* Retrieve the WindingType for the given transformer winding/end.
* @param end A PropertyBag with the transformer winding/end properties.
* @return The WindingType (PRIMARY/SECONDARY/TERTIARY) corresponding to the given transformer winding/end.
*/
public static WindingType windingType(PropertyBag end) {
if (end.containsKey("windingType")) {
String wtype = end.getLocal("windingType");
if (wtype.endsWith("WindingType.primary")) {
return WindingType.PRIMARY;
} else if (wtype.endsWith("WindingType.secondary")) {
return WindingType.SECONDARY;
} else if (wtype.endsWith("WindingType.tertiary")) {
return WindingType.TERTIARY;
// For CIM14 (CIM ENTSOE Profile1) primary is determined by TransformerWinding.windingType
return switch (end.getLocal("windingType")) {
case "WindingType.primary" -> WindingType.PRIMARY;
case "WindingType.secondary" -> WindingType.SECONDARY;
case "WindingType.tertiary" -> WindingType.TERTIARY;
default -> WindingType.UNKNOWN;
};
} else if (end.containsKey("endNumber")) {
// For CIM16 (CGMES 2.4.15) primary is defined by TransformerEnd.endNumber
try {
return WindingType.values()[end.asInt("endNumber")];
} catch (Exception e) {
return WindingType.UNKNOWN;
}
} else if (end.containsKey("terminalSequenceNumber")) {
// Terminal.sequenceNumber := 1, 2 ,3 ...
return WindingType.values()[end.asInt("terminalSequenceNumber") - 1];
}
return WindingType.PRIMARY;
return WindingType.UNKNOWN;
}

/**
* Retrieve the endNumber for the given transformer winding/end.
* @param end A PropertyBag with the transformer winding/end properties.
* @return The endNumber value (1/2/3) corresponding to the given transformer winding/end.
*/
public static int endNumber(PropertyBag end) {
return windingType(end).ordinal();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2024, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.cgmes.model;

import com.powsybl.triplestore.api.PropertyBag;
import org.junit.jupiter.api.Test;

import java.util.Collections;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author Romain Courtier {@literal <romain.courtier at rte-france.com>}
*/
class WindingTypeTest {

PropertyBag end1;
PropertyBag end2;
PropertyBag end3;
PropertyBag end4;

static final String WINDING_TYPE = "windingType";
static final String END_NUMBER = "endNumber";

@Test
void cim14WindingTypeTest() {
end1 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true);
end1.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.primary");
assertEquals(WindingType.PRIMARY, WindingType.windingType(end1));
assertEquals(1, WindingType.endNumber(end1));

end2 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true);
end2.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.secondary");
assertEquals(WindingType.SECONDARY, WindingType.windingType(end2));
assertEquals(2, WindingType.endNumber(end2));

end3 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true);
end3.put(WINDING_TYPE, "http://iec.ch/TC57/2009/CIM-schema-cim14#WindingType.tertiary");
assertEquals(WindingType.TERTIARY, WindingType.windingType(end3));
assertEquals(3, WindingType.endNumber(end3));

end4 = new PropertyBag(Collections.singletonList(WINDING_TYPE), true);
end4.put(WINDING_TYPE, "Unknown");
assertEquals(WindingType.UNKNOWN, WindingType.windingType(end4));
assertEquals(0, WindingType.endNumber(end4));
}

@Test
void cim16WindingTypeTest() {
end1 = new PropertyBag(Collections.singletonList(END_NUMBER), true);
end1.put(END_NUMBER, "1");
assertEquals(WindingType.PRIMARY, WindingType.windingType(end1));
assertEquals(1, WindingType.endNumber(end1));

end2 = new PropertyBag(Collections.singletonList(END_NUMBER), true);
end2.put(END_NUMBER, "2");
assertEquals(WindingType.SECONDARY, WindingType.windingType(end2));
assertEquals(2, WindingType.endNumber(end2));

end3 = new PropertyBag(Collections.singletonList(END_NUMBER), true);
end3.put(END_NUMBER, "3");
assertEquals(WindingType.TERTIARY, WindingType.windingType(end3));
assertEquals(3, WindingType.endNumber(end3));

end4 = new PropertyBag(Collections.singletonList(END_NUMBER), true);
end4.put(END_NUMBER, "Unknown");
assertEquals(WindingType.UNKNOWN, WindingType.windingType(end4));
assertEquals(0, WindingType.endNumber(end4));
}
}

0 comments on commit 9c18cc5

Please sign in to comment.