Skip to content

Commit

Permalink
For TapChanger and TapChangerBlocking automatons : skip the automaton…
Browse files Browse the repository at this point in the history
… if none of equipments linked to it have the expected properties

Signed-off-by: lisrte <laurent.issertial@rte-france.com>
  • Loading branch information
Lisrte committed Jul 7, 2023
1 parent 128b1e6 commit b2affc7
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.powsybl.dynamicsimulation.EventModel
import com.powsybl.dynamicsimulation.groovy.EventModelGroovyExtension
import com.powsybl.dynawaltz.dsl.AbstractPureDynamicGroovyExtension
import com.powsybl.dynawaltz.dsl.DslEquipment
import com.powsybl.dynawaltz.dsl.DslVariousEquipment
import com.powsybl.dynawaltz.dsl.builders.AbstractEventModelBuilder
import com.powsybl.dynawaltz.models.events.AbstractEventModel
import com.powsybl.dynawaltz.models.events.EventHvdcDisconnection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import com.powsybl.dynawaltz.xml.MacroStaticReference;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Network;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.function.Function;
Expand All @@ -31,7 +33,9 @@
*/
public class DynaWaltzContext {

protected static final Logger LOGGER = LoggerFactory.getLogger(DynaWaltzContext.class);
private static final String MODEL_ID_EXCEPTION = "The model identified by the static id %s does not match the expected model (%s)";
private static final String MODEL_ID_LOG = "The model identified by the static id {} does not match the expected model ({})";

private final Network network;
private final String workingVariantId;
Expand Down Expand Up @@ -111,27 +115,46 @@ public <T extends Model> T getDynamicModel(String staticId, Class<T> clazz) {
}

public <T extends Model> T getDynamicModel(Identifiable<?> equipment, Class<T> connectableClass) {
return getDynamicModel(equipment, connectableClass, true);
}

public <T extends Model> T getDynamicModel(Identifiable<?> equipment, Class<T> connectableClass, boolean throwException) {
BlackBoxModel bbm = staticIdBlackBoxModelMap.get(equipment.getId());
if (bbm == null) {
return defaultModelsHandler.getDefaultModel(equipment, connectableClass);
return defaultModelsHandler.getDefaultModel(equipment, connectableClass, throwException);
}
if (connectableClass.isInstance(bbm)) {
return connectableClass.cast(bbm);
}
throw new PowsyblException(String.format(MODEL_ID_EXCEPTION, equipment.getId(), connectableClass.getSimpleName()));
if (throwException) {
throw new PowsyblException(String.format(MODEL_ID_EXCEPTION, equipment.getId(), connectableClass.getSimpleName()));
} else {
LOGGER.warn(MODEL_ID_LOG, equipment.getId(), connectableClass.getSimpleName());
return null;
}
}

public <T extends Model> T getPureDynamicModel(String dynamicId, Class<T> connectableClass) {
public <T extends Model> T getPureDynamicModel(String dynamicId, Class<T> connectableClass, boolean throwException) {
BlackBoxModel bbm = dynamicModels.stream()
.filter(dm -> dynamicId.equals(dm.getDynamicModelId()))
.findFirst()
.orElseThrow(() -> {
throw new PowsyblException("Pure dynamic model " + dynamicId + " not found");
});
.findFirst().orElse(null);
if (bbm == null) {
if (throwException) {
throw new PowsyblException("Pure dynamic model " + dynamicId + " not found");
} else {
LOGGER.warn("Pure dynamic model {} not found", dynamicId);
return null;
}
}
if (connectableClass.isInstance(bbm)) {
return connectableClass.cast(bbm);
}
throw new PowsyblException(String.format(MODEL_ID_EXCEPTION, dynamicId, connectableClass.getSimpleName()));
if (throwException) {
throw new PowsyblException(String.format(MODEL_ID_EXCEPTION, dynamicId, connectableClass.getSimpleName()));
} else {
LOGGER.warn(MODEL_ID_LOG, dynamicId, connectableClass.getSimpleName());
return null;
}
}

private EquipmentBlackBoxModel mergeDuplicateStaticId(EquipmentBlackBoxModel bbm1, EquipmentBlackBoxModel bbm2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,31 @@ protected final <T extends Model> void createMacroConnections(Identifiable<?> eq
createMacroConnections(connectedModel, varConnectionsSupplier.apply(connectedModel), context, connectFromAttributes);
}

protected final <T extends Model> boolean createMacroConnectionsOrSkip(Identifiable<?> equipment, Class<T> modelClass, Function<T, List<VarConnection>> varConnectionsSupplier, DynaWaltzContext context, MacroConnectAttribute... connectFromAttributes) {
T connectedModel = context.getDynamicModel(equipment, modelClass, false);
if (connectedModel != null) {
createMacroConnections(connectedModel, varConnectionsSupplier.apply(connectedModel), context, connectFromAttributes);
return false;
}
return true;
}

protected <T extends Model> void createMacroConnections(Identifiable<?> equipment, Class<T> modelClass, Function<T, List<VarConnection>> varConnectionsSupplier, DynaWaltzContext context) {
T connectedModel = context.getDynamicModel(equipment, modelClass);
String macroConnectorId = context.addMacroConnector(getName(), connectedModel.getName(), varConnectionsSupplier.apply(connectedModel));
context.addMacroConnect(macroConnectorId, getMacroConnectFromAttributes(), connectedModel.getMacroConnectToAttributes());
}

protected <T extends Model> boolean createMacroConnectionsOrSkip(Identifiable<?> equipment, Class<T> modelClass, Function<T, List<VarConnection>> varConnectionsSupplier, DynaWaltzContext context) {
T connectedModel = context.getDynamicModel(equipment, modelClass, false);
if (connectedModel != null) {
String macroConnectorId = context.addMacroConnector(getName(), connectedModel.getName(), varConnectionsSupplier.apply(connectedModel));
context.addMacroConnect(macroConnectorId, getMacroConnectFromAttributes(), connectedModel.getMacroConnectToAttributes());
return false;
}
return true;
}

/**
* Suffixes MacroConnector id with side name
*/
Expand Down Expand Up @@ -137,12 +156,6 @@ protected <T extends Model> void createMacroConnections(Identifiable<?> equipmen
context.addMacroConnect(macroConnectorId, getMacroConnectFromAttributes(), connectedModel.getMacroConnectToAttributes());
}

protected <T extends Model> void createPureDynamicMacroConnections(String dynamicId, Class<T> modelClass, Function<T, List<VarConnection>> varConnectionsSupplier, DynaWaltzContext context) {
T connectedModel = context.getPureDynamicModel(dynamicId, modelClass);
String macroConnectorId = context.addMacroConnector(getName(), connectedModel.getName(), varConnectionsSupplier.apply(connectedModel));
context.addMacroConnect(macroConnectorId, getMacroConnectFromAttributes(), connectedModel.getMacroConnectToAttributes());
}

protected final <T extends Model> void createMacroConnections(Identifiable<?> equipment, Class<T> modelClass, BiFunction<T, String, List<VarConnection>> varConnectionsSupplier, DynaWaltzContext context, String parametrizedName, MacroConnectAttribute... connectFromAttributes) {
T connectedModel = context.getDynamicModel(equipment, modelClass);
String macroConnectorId = context.addMacroConnector(getName(), connectedModel.getName(), parametrizedName, varConnectionsSupplier.apply(connectedModel, parametrizedName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
import com.powsybl.dynawaltz.models.loads.LoadWithTransformers;
import com.powsybl.dynawaltz.models.transformers.TapChangerModel;
import com.powsybl.iidm.network.Load;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.util.List;
import java.util.Objects;

Expand All @@ -23,9 +27,19 @@
*/
public class TapChangerAutomaton extends AbstractPureDynamicBlackBoxModel implements TapChangerModel {

private static final Logger LOGGER = LoggerFactory.getLogger(TapChangerAutomaton.class);

private final Load load;
private final TransformerSide side;

private ConnectionState connection = ConnectionState.NOT_SET;

private enum ConnectionState {
CONNECTED,
NOT_CONNECTED,
NOT_SET
}

public TapChangerAutomaton(String dynamicModelId, String parameterSetId, Load load, TransformerSide side) {
super(dynamicModelId, parameterSetId);
this.load = Objects.requireNonNull(load);
Expand All @@ -48,7 +62,15 @@ public String getLib() {

@Override
public void createMacroConnections(DynaWaltzContext context) {
createMacroConnections(load, LoadWithTransformers.class, this::getVarConnectionsWith, context);
if (ConnectionState.NOT_SET == connection) {
boolean isSkipped = createMacroConnectionsOrSkip(load, LoadWithTransformers.class, this::getVarConnectionsWith, context);
if (isSkipped) {
connection = ConnectionState.NOT_CONNECTED;
LOGGER.warn("TapChangerAutomaton {} load does not possess a transformer, the automaton will be skipped", getDynamicModelId());
} else {
connection = ConnectionState.CONNECTED;
}
}
}

private List<VarConnection> getVarConnectionsWith(LoadWithTransformers connected) {
Expand All @@ -59,4 +81,18 @@ private List<VarConnection> getVarConnectionsWith(LoadWithTransformers connected
public List<VarConnection> getTapChangerBlockerVarConnections() {
return List.of(new VarConnection(getTapChangerBlockingVarName(side), "tapChanger_locked"));
}

@Override
public void write(XMLStreamWriter writer, DynaWaltzContext context) throws XMLStreamException {
if (ConnectionState.CONNECTED == connection) {
super.write(writer, context);
}
}

public boolean isConnected(DynaWaltzContext context) {
if (ConnectionState.NOT_SET == connection) {
createMacroConnections(context);
}
return ConnectionState.CONNECTED == connection;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@
import com.powsybl.iidm.network.IdentifiableType;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.TwoWindingsTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.util.*;

/**
* @author Laurent Issertial <laurent.issertial at rte-france.com>
*/
public class TapChangerBlockingAutomaton extends AbstractPureDynamicBlackBoxModel {

private static final Logger LOGGER = LoggerFactory.getLogger(TapChangerBlockingAutomaton.class);
private static final Set<IdentifiableType> COMPATIBLE_EQUIPMENTS = EnumSet.of(IdentifiableType.LOAD, IdentifiableType.TWO_WINDINGS_TRANSFORMER);
private static final int MAX_MEASUREMENTS = 5;

private final List<TwoWindingsTransformer> transformers;
private final List<Load> loadsWithTransformer;
private final List<String> tapChangerAutomatonIds;
private final List<Bus> uMeasurements;
private boolean isConnected = true;

public TapChangerBlockingAutomaton(String dynamicModelId, String parameterSetId, List<TwoWindingsTransformer> transformers, List<Load> loadsWithTransformer, List<String> tapChangerAutomatonIds, List<Bus> uMeasurements) {
super(dynamicModelId, parameterSetId);
Expand Down Expand Up @@ -78,16 +84,27 @@ public void createMacroConnections(DynaWaltzContext context) {
for (TwoWindingsTransformer transformer : transformers) {
createMacroConnections(transformer, TapChangerModel.class, this::getVarConnectionsWith, context);
}
int skippedTapChangers = 0;
for (Load load : loadsWithTransformer) {
createMacroConnections(load, TapChangerModel.class, this::getVarConnectionsWith, context);
boolean isSkipped = createMacroConnectionsOrSkip(load, TapChangerModel.class, this::getVarConnectionsWith, context);
if (isSkipped) {
skippedTapChangers++;
}
}
for (String id : tapChangerAutomatonIds) {
createPureDynamicMacroConnections(id, TapChangerModel.class, this::getVarConnectionsWith, context);
if (createTcaMacroConnectionsOrSkip(id, context)) {
skippedTapChangers++;
}
}
int i = 1;
for (Bus bus : uMeasurements) {
createMacroConnections(bus, BusModel.class, this::getVarConnectionsWith, context, MeasurementPoint.of(i));
i++;
if (!transformers.isEmpty() || skippedTapChangers < (loadsWithTransformer.size() + tapChangerAutomatonIds.size())) {
int i = 1;
for (Bus bus : uMeasurements) {
createMacroConnections(bus, BusModel.class, this::getVarConnectionsWith, context, MeasurementPoint.of(i));
i++;
}
} else {
isConnected = false;
LOGGER.warn("None of TapChangerBlockingAutomaton {} equipments are TapChangerModel, the automaton will be skipped", getDynamicModelId());
}
}

Expand All @@ -100,4 +117,21 @@ private List<VarConnection> getVarConnectionsWith(BusModel connected, String suf
.map(uImpinVarName -> List.of(new VarConnection("tapChangerBlocking_UMonitored" + suffix, uImpinVarName)))
.orElse(Collections.emptyList());
}

private boolean createTcaMacroConnectionsOrSkip(String dynamicId, DynaWaltzContext context) {
TapChangerAutomaton connectedModel = context.getPureDynamicModel(dynamicId, TapChangerAutomaton.class, false);
if (connectedModel != null && connectedModel.isConnected(context)) {
String macroConnectorId = context.addMacroConnector(getName(), connectedModel.getName(), getVarConnectionsWith(connectedModel));
context.addMacroConnect(macroConnectorId, getMacroConnectFromAttributes(), connectedModel.getMacroConnectToAttributes());
return false;
}
return true;
}

@Override
public void write(XMLStreamWriter writer, DynaWaltzContext context) throws XMLStreamException {
if (isConnected) {
super.write(writer, context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import com.powsybl.dynawaltz.models.transformers.TransformerModel;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.IdentifiableType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.EnumMap;
import java.util.Map;
Expand All @@ -36,6 +38,8 @@
*/
public class DefaultModelsHandler {

private static final Logger LOGGER = LoggerFactory.getLogger(DefaultModelsHandler.class);

private final Map<IdentifiableType, Class<? extends Model>> powSyBlTypeToModel = new EnumMap<>(IdentifiableType.class);
private final Map<Class<? extends Model>, DefaultModelFactory<? extends Model>> factoryMap;

Expand Down Expand Up @@ -68,6 +72,10 @@ public <T extends Model> T getDefaultModel(String staticId, Class<T> clazz) {
}

public <T extends Model> T getDefaultModel(Identifiable<?> equipment, Class<T> connectableClass) {
return getDefaultModel(equipment, connectableClass, true);
}

public <T extends Model> T getDefaultModel(Identifiable<?> equipment, Class<T> connectableClass, boolean throwException) {

Class<? extends Model> equipmentClass = powSyBlTypeToModel.get(equipment.getType());
if (equipmentClass == null) {
Expand All @@ -79,8 +87,18 @@ public <T extends Model> T getDefaultModel(Identifiable<?> equipment, Class<T> c
if (connectableClass.isInstance(defaultModel)) {
return connectableClass.cast(defaultModel);
}
throw new PowsyblException("Default model " + defaultModel.getClass().getSimpleName() + " does not implement " + connectableClass.getSimpleName() + " interface");
if (throwException) {
throw new PowsyblException("Default model " + defaultModel.getClass().getSimpleName() + " does not implement " + connectableClass.getSimpleName() + " interface");
} else {
LOGGER.warn("Default model {} does not implement {} interface", defaultModel.getClass().getSimpleName(), connectableClass.getSimpleName());
return null;
}
}
if (throwException) {
throw new PowsyblException("Default model not implemented for " + equipmentClass.getSimpleName());
} else {
LOGGER.warn("Default model not implemented for {}", equipmentClass.getSimpleName());
return null;
}
throw new PowsyblException("Default model not implemented for " + equipmentClass.getSimpleName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright (c) 2023, 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.dynawaltz.xml;

import com.powsybl.dynawaltz.models.automatons.TapChangerAutomaton;
import com.powsybl.dynawaltz.models.loads.LoadAlphaBeta;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import org.junit.jupiter.api.Test;
import org.xml.sax.SAXException;

import javax.xml.stream.XMLStreamException;
import java.io.IOException;

/**
* @author Laurent Issertial <laurent.issertial at rte-france.com>
*/
class EmptyTapChangerAutomatonXmlTest extends AbstractDynamicModelXmlTest {

@Override
protected void setupNetwork() {
network = EurostagTutorialExample1Factory.create();
}

@Override
protected void addDynamicModels() {
dynamicModels.add(new LoadAlphaBeta("BBM_LOAD", network.getLoad("LOAD"), "LAB", "LoadAlphaBeta"));
dynamicModels.add(new TapChangerAutomaton("BBM_TC", "tc", network.getLoad("LOAD")));
}

@Test
void writeModel() throws SAXException, IOException, XMLStreamException {
DydXml.write(tmpDir, context);
ParametersXml.write(tmpDir, context);
validate("dyd.xsd", "tap_changer_empty_dyd.xml", tmpDir.resolve(DynaWaltzConstants.DYD_FILENAME));
}
}
Loading

0 comments on commit b2affc7

Please sign in to comment.