com.farao_community.farao.data.crac_impl.FlowCnecImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of farao-crac-impl Show documentation
Show all versions of farao-crac-impl Show documentation
Object model for CRAC implementation
/*
* Copyright (c) 2020, 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.farao_community.farao.data.crac_impl;
import com.farao_community.farao.commons.FaraoException;
import com.farao_community.farao.commons.PhysicalParameter;
import com.farao_community.farao.commons.Unit;
import com.farao_community.farao.data.crac_api.NetworkElement;
import com.farao_community.farao.data.crac_api.State;
import com.farao_community.farao.data.crac_api.cnec.FlowCnec;
import com.farao_community.farao.data.crac_api.cnec.Side;
import com.farao_community.farao.data.crac_api.threshold.BranchThreshold;
import com.farao_community.farao.data.crac_api.threshold.Threshold;
import com.powsybl.iidm.network.Connectable;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.Terminal;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author Joris Mancini {@literal }
*/
public class FlowCnecImpl extends AbstractBranchCnec implements FlowCnec {
private final Double[] iMax = new Double[2];
FlowCnecImpl(String id,
String name,
NetworkElement networkElement,
String operator,
State state,
boolean optimized,
boolean monitored,
Set thresholds,
double frm,
Double nominalVLeft,
Double nominalVRight,
Double iMaxLeft,
Double iMaxRight) {
super(id, name, networkElement, operator, state, optimized, monitored, thresholds, frm, nominalVLeft, nominalVRight);
this.iMax[0] = iMaxLeft;
this.iMax[1] = iMaxRight;
}
@Override
public Double getIMax(Side side) {
if (side.equals(Side.LEFT)) {
return iMax[0];
} else {
return iMax[1];
}
}
@Override
public Optional getLowerBound(Side side, Unit requestedUnit) {
if (!requestedUnit.equals(Unit.AMPERE) && !requestedUnit.equals(Unit.MEGAWATT)) {
throw new FaraoException("FlowCnec lowerBound can only be requested in AMPERE or MEGAWATT");
}
if (!bounds.isLowerBoundComputed(side, requestedUnit)) {
Set limitingThresholds = thresholds.stream()
.filter(Threshold::limitsByMin)
.filter(branchThreshold -> branchThreshold.getSide().equals(side))
.collect(Collectors.toSet());
if (!limitingThresholds.isEmpty()) {
double lowerBound = Double.NEGATIVE_INFINITY;
for (BranchThreshold threshold : limitingThresholds) {
double currentBound = getRawBound(threshold, threshold.min().orElseThrow());
currentBound = changeValueUnit(currentBound, threshold.getUnit(), requestedUnit, threshold.getSide());
currentBound += changeValueUnit(reliabilityMargin, Unit.MEGAWATT, requestedUnit, side);
if (currentBound > lowerBound) {
lowerBound = currentBound;
}
}
bounds.setLowerBound(lowerBound, side, requestedUnit);
} else {
bounds.setLowerBound(null, side, requestedUnit);
}
}
return Optional.ofNullable(bounds.getLowerBound(side, requestedUnit));
}
@Override
public Optional getUpperBound(Side side, Unit requestedUnit) {
if (!requestedUnit.equals(Unit.AMPERE) && !requestedUnit.equals(Unit.MEGAWATT)) {
throw new FaraoException("FlowCnec upperBound can only be requested in AMPERE or MEGAWATT");
}
requestedUnit.checkPhysicalParameter(getPhysicalParameter());
if (!bounds.isUpperBoundComputed(side, requestedUnit)) {
Set limitingThresholds = thresholds.stream()
.filter(Threshold::limitsByMax)
.filter(branchThreshold -> branchThreshold.getSide().equals(side))
.collect(Collectors.toSet());
if (!limitingThresholds.isEmpty()) {
double upperBound = Double.POSITIVE_INFINITY;
for (BranchThreshold threshold : limitingThresholds) {
double currentBound = getRawBound(threshold, threshold.max().orElseThrow());
currentBound = changeValueUnit(currentBound, threshold.getUnit(), requestedUnit, threshold.getSide());
currentBound -= changeValueUnit(reliabilityMargin, Unit.MEGAWATT, requestedUnit, side);
if (currentBound < upperBound) {
upperBound = currentBound;
}
}
bounds.setUpperBound(upperBound, side, requestedUnit);
} else {
bounds.setUpperBound(null, side, requestedUnit);
}
}
return Optional.ofNullable(bounds.getUpperBound(side, requestedUnit));
}
private double getRawBound(BranchThreshold threshold, double thresholdValue) {
if (threshold.getUnit().equals(Unit.PERCENT_IMAX)) {
return getIMax(threshold.getSide()) * thresholdValue;
} else {
return thresholdValue;
}
}
private double changeValueUnit(double value, Unit oldUnit, Unit newUnit, Side side) {
if (oldUnit.equals(newUnit) || (oldUnit.equals(Unit.PERCENT_IMAX) && newUnit.equals(Unit.AMPERE))) {
return value;
} else {
double conversionFactor = Math.sqrt(3) * getNominalVoltage(side) / 1000; // Conversion from A to MW
if (oldUnit.equals(Unit.MEGAWATT) && newUnit.equals(Unit.AMPERE)) {
conversionFactor = 1 / conversionFactor;
}
return value * conversionFactor;
}
}
public boolean isConnected(Network network) {
Identifiable> identifiable = network.getIdentifiable(getNetworkElement().getId());
if (identifiable instanceof Connectable) {
Connectable> connectable = (Connectable>) identifiable;
return connectable.getTerminals().stream().allMatch(Terminal::isConnected);
}
return true; // by default
}
@Override
public PhysicalParameter getPhysicalParameter() {
return PhysicalParameter.FLOW;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
FlowCnecImpl cnec = (FlowCnecImpl) o;
return super.equals(cnec);
}
@Override
public int hashCode() {
return super.hashCode();
}
}