CimContingencyCreator.java
/*
* Copyright (c) 2022, 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/.
*/
package com.powsybl.openrao.data.crac.io.cim.craccreator;
import com.powsybl.contingency.ContingencyElement;
import com.powsybl.contingency.ContingencyElementType;
import com.powsybl.iidm.network.DanglingLine;
import com.powsybl.iidm.network.TieLine;
import com.powsybl.openrao.data.crac.io.cim.xsd.ContingencyRegisteredResource;
import com.powsybl.openrao.data.crac.io.cim.xsd.ContingencySeries;
import com.powsybl.openrao.data.crac.io.cim.xsd.Series;
import com.powsybl.openrao.data.crac.io.cim.xsd.TimeSeries;
import com.powsybl.openrao.data.crac.api.ContingencyAdder;
import com.powsybl.openrao.data.crac.api.Crac;
import com.powsybl.openrao.data.crac.io.commons.api.ElementaryCreationContext;
import com.powsybl.openrao.data.crac.io.commons.api.ImportStatus;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Network;
import com.powsybl.openrao.data.crac.io.commons.api.StandardElementaryCreationContext;
import com.powsybl.openrao.data.crac.io.commons.cgmes.CgmesBranchHelper;
import java.util.*;
/**
* @author Godelaine de Montmorillon {@literal <godelaine.demontmorillon at rte-france.com>}
*/
public class CimContingencyCreator {
private final Crac crac;
private final Network network;
private final List<TimeSeries> cimTimeSeries;
private Set<ElementaryCreationContext> cimContingencyCreationContexts;
private CimCracCreationContext cracCreationContext;
public Set<ElementaryCreationContext> getContingencyCreationContexts() {
return new HashSet<>(cimContingencyCreationContexts);
}
public CimContingencyCreator(List<TimeSeries> cimTimeSeries, Crac crac, Network network, CimCracCreationContext cracCreationContext) {
this.cimTimeSeries = cimTimeSeries;
this.crac = crac;
this.network = network;
this.cracCreationContext = cracCreationContext;
}
public void createAndAddContingencies() {
this.cimContingencyCreationContexts = new HashSet<>();
CimCracUtils.applyActionToEveryPoint(
cimTimeSeries,
cracCreationContext.getTimeStamp().toInstant(),
point -> point.getSeries().stream().filter(this::describesContingencyToImport).forEach(
series -> series.getContingencySeries().forEach(this::addContingency)
)
);
this.cracCreationContext.setContingencyCreationContexts(cimContingencyCreationContexts);
}
private void addContingency(ContingencySeries cimContingency) {
if (cimContingencyCreationContexts.stream().anyMatch(ccc -> ccc.getNativeObjectId().equals(cimContingency.getMRID()))) {
return;
}
String createdContingencyId = cimContingency.getMRID();
ContingencyAdder contingencyAdder = crac.newContingency()
.withId(createdContingencyId)
.withName(cimContingency.getName());
if (cimContingency.getRegisteredResource().isEmpty()) {
cimContingencyCreationContexts.add(StandardElementaryCreationContext.notImported(createdContingencyId, cimContingency.getName(), ImportStatus.INCOMPLETE_DATA, "No registered resources"));
return;
}
boolean anyRegisteredResourceOk = false;
boolean allRegisteredResourcesOk = true;
StringBuilder missingNetworkElements = null;
for (ContingencyRegisteredResource registeredResource : cimContingency.getRegisteredResource()) {
Identifiable<?> networkElement = getNetworkElementInNetwork(registeredResource.getMRID().getValue());
if (networkElement != null) {
String networkElementId = networkElement.getId();
ContingencyElementType contingencyElementType = ContingencyElement.of(networkElement).getType();
contingencyAdder.withContingencyElement(networkElementId, contingencyElementType);
anyRegisteredResourceOk = true;
} else {
allRegisteredResourcesOk = false;
if (missingNetworkElements == null) {
missingNetworkElements = new StringBuilder(registeredResource.getMRID().getValue());
} else {
missingNetworkElements.append(", ").append(registeredResource.getMRID().getValue());
}
}
}
if (anyRegisteredResourceOk) {
contingencyAdder.add();
String message = allRegisteredResourcesOk ? null : String.format("Some network elements were not found in the network: %s", missingNetworkElements.toString());
cimContingencyCreationContexts.add(StandardElementaryCreationContext.imported(createdContingencyId, cimContingency.getName(), createdContingencyId, !allRegisteredResourcesOk, message));
} else {
cimContingencyCreationContexts.add(StandardElementaryCreationContext.notImported(createdContingencyId, cimContingency.getName(), ImportStatus.ELEMENT_NOT_FOUND_IN_NETWORK, "None of the contingency's registered resources was found in network"));
}
}
private Identifiable<?> getNetworkElementInNetwork(String networkElementIdInCrac) {
Identifiable<?> networkElementToReturn = null;
Identifiable<?> networkElement = network.getIdentifiable(networkElementIdInCrac);
if (networkElement == null) {
CgmesBranchHelper cgmesBranchHelper = new CgmesBranchHelper(networkElementIdInCrac, network);
if (cgmesBranchHelper.isValid()) {
networkElementToReturn = cgmesBranchHelper.getBranch();
networkElement = cgmesBranchHelper.getBranch();
}
} else {
networkElementToReturn = networkElement;
}
if (networkElement instanceof DanglingLine danglingLine) {
Optional<TieLine> optionalTieLine = danglingLine.getTieLine();
if (optionalTieLine.isPresent()) {
networkElementToReturn = optionalTieLine.get();
}
}
return networkElementToReturn;
}
private boolean describesContingencyToImport(Series series) {
return series.getBusinessType().equals(CimConstants.CONTINGENCY_SERIES_BUSINESS_TYPE)
|| series.getBusinessType().equals(CimConstants.CNECS_SERIES_BUSINESS_TYPE)
|| series.getBusinessType().equals(CimConstants.REMEDIAL_ACTIONS_SERIES_BUSINESS_TYPE);
}
}