DanglingLineImpl.java
/**
* Copyright (c) 2016, All partners of the iTesla project (http://www.itesla-project.eu/consortium)
* 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.iidm.network.impl;
import com.powsybl.commons.util.trove.TBooleanArrayList;
import com.powsybl.iidm.network.*;
import com.powsybl.commons.ref.Ref;
import gnu.trove.list.array.TDoubleArrayList;
import java.util.Collection;
import java.util.Objects;
import java.util.Optional;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
class DanglingLineImpl extends AbstractConnectable<DanglingLine> implements DanglingLine {
static class GenerationImpl implements Generation, ReactiveLimitsOwner, Validable {
private DanglingLineImpl danglingLine;
private ReactiveLimitsHolderImpl reactiveLimits;
private double minP;
private double maxP;
// attributes depending on the variant
private final TDoubleArrayList targetP;
private final TDoubleArrayList targetQ;
private final TDoubleArrayList targetV;
private final TBooleanArrayList voltageRegulationOn;
GenerationImpl(VariantManagerHolder network, double minP, double maxP, double targetP, double targetQ, double targetV, boolean voltageRegulationOn) {
this.minP = Double.isNaN(minP) ? -Double.MAX_VALUE : minP;
this.maxP = Double.isNaN(maxP) ? Double.MAX_VALUE : maxP;
int variantArraySize = network.getVariantManager().getVariantArraySize();
this.targetP = new TDoubleArrayList(variantArraySize);
this.targetQ = new TDoubleArrayList(variantArraySize);
this.targetV = new TDoubleArrayList(variantArraySize);
this.voltageRegulationOn = new TBooleanArrayList(variantArraySize);
for (int i = 0; i < variantArraySize; i++) {
this.targetP.add(targetP);
this.targetQ.add(targetQ);
this.targetV.add(targetV);
this.voltageRegulationOn.add(voltageRegulationOn);
}
}
GenerationImpl attach(DanglingLineImpl danglingLine) {
if (this.danglingLine != null) {
throw new IllegalStateException("DanglingLine.Generation already attached to " + this.danglingLine.getId());
}
this.danglingLine = Objects.requireNonNull(danglingLine);
this.reactiveLimits = new ReactiveLimitsHolderImpl(this.danglingLine, new MinMaxReactiveLimitsImpl(-Double.MAX_VALUE, Double.MAX_VALUE));
return this;
}
@Override
public double getTargetP() {
return targetP.get(danglingLine.getNetwork().getVariantIndex());
}
@Override
public GenerationImpl setTargetP(double targetP) {
NetworkImpl n = danglingLine.getNetwork();
ValidationUtil.checkActivePowerSetpoint(danglingLine, targetP, n.getMinValidationLevel(), n.getReportNodeContext().getReportNode());
int variantIndex = danglingLine.network.get().getVariantIndex();
double oldValue = this.targetP.set(variantIndex, targetP);
String variantId = danglingLine.network.get().getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
danglingLine.notifyUpdate("targetP", variantId, oldValue, targetP);
return this;
}
@Override
public double getMaxP() {
return maxP;
}
@Override
public GenerationImpl setMaxP(double maxP) {
ValidationUtil.checkMaxP(danglingLine, maxP);
ValidationUtil.checkActivePowerLimits(danglingLine, minP, maxP);
double oldValue = this.maxP;
this.maxP = maxP;
danglingLine.notifyUpdate("maxP", oldValue, maxP);
return this;
}
@Override
public double getMinP() {
return minP;
}
@Override
public GenerationImpl setMinP(double minP) {
ValidationUtil.checkMinP(danglingLine, minP);
ValidationUtil.checkActivePowerLimits(danglingLine, minP, maxP);
double oldValue = this.minP;
this.minP = minP;
danglingLine.notifyUpdate("minP", oldValue, minP);
return this;
}
@Override
public double getTargetQ() {
return targetQ.get(danglingLine.getNetwork().getVariantIndex());
}
@Override
public GenerationImpl setTargetQ(double targetQ) {
NetworkImpl n = danglingLine.getNetwork();
int variantIndex = n.getVariantIndex();
ValidationUtil.checkVoltageControl(danglingLine, voltageRegulationOn.get(variantIndex), targetV.get(variantIndex), targetQ,
n.getMinValidationLevel(), n.getReportNodeContext().getReportNode());
double oldValue = this.targetQ.set(variantIndex, targetQ);
String variantId = n.getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
danglingLine.notifyUpdate("targetQ", variantId, oldValue, targetQ);
return this;
}
@Override
public boolean isVoltageRegulationOn() {
return voltageRegulationOn.get(danglingLine.getNetwork().getVariantIndex());
}
@Override
public GenerationImpl setVoltageRegulationOn(boolean voltageRegulationOn) {
NetworkImpl n = danglingLine.getNetwork();
int variantIndex = danglingLine.getNetwork().getVariantIndex();
ValidationUtil.checkVoltageControl(danglingLine, voltageRegulationOn, targetV.get(variantIndex), targetQ.get(variantIndex),
n.getMinValidationLevel(), n.getReportNodeContext().getReportNode());
boolean oldValue = this.voltageRegulationOn.get(variantIndex);
this.voltageRegulationOn.set(variantIndex, voltageRegulationOn);
String variantId = danglingLine.getNetwork().getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
danglingLine.notifyUpdate("voltageRegulationOn", variantId, oldValue, voltageRegulationOn);
return this;
}
@Override
public NetworkImpl getNetwork() {
return this.danglingLine.getNetwork();
}
@Override
public double getTargetV() {
return this.targetV.get(danglingLine.getNetwork().getVariantIndex());
}
@Override
public GenerationImpl setTargetV(double targetV) {
NetworkImpl n = danglingLine.getNetwork();
int variantIndex = danglingLine.getNetwork().getVariantIndex();
ValidationUtil.checkVoltageControl(danglingLine, voltageRegulationOn.get(variantIndex), targetV, targetQ.get(variantIndex),
n.getMinValidationLevel(), n.getReportNodeContext().getReportNode());
double oldValue = this.targetV.set(variantIndex, targetV);
String variantId = danglingLine.getNetwork().getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
danglingLine.notifyUpdate("targetV", variantId, oldValue, targetV);
return this;
}
@Override
public ReactiveCapabilityCurveAdderImpl newReactiveCapabilityCurve() {
return new ReactiveCapabilityCurveAdderImpl<>(this);
}
@Override
public MinMaxReactiveLimitsAdderImpl newMinMaxReactiveLimits() {
return new MinMaxReactiveLimitsAdderImpl<>(this);
}
@Override
public void setReactiveLimits(ReactiveLimits reactiveLimits) {
this.reactiveLimits.setReactiveLimits(reactiveLimits);
}
@Override
public ReactiveLimits getReactiveLimits() {
return reactiveLimits.getReactiveLimits();
}
@Override
public <R extends ReactiveLimits> R getReactiveLimits(Class<R> type) {
return reactiveLimits.getReactiveLimits(type);
}
@Override
public String getMessageHeader() {
return danglingLine.getMessageHeader();
}
void extendVariantArraySize(int number, int sourceIndex) {
targetP.ensureCapacity(targetP.size() + number);
targetQ.ensureCapacity(targetQ.size() + number);
voltageRegulationOn.ensureCapacity(voltageRegulationOn.size() + number);
targetV.ensureCapacity(targetV.size() + number);
for (int i = 0; i < number; i++) {
targetP.add(targetP.get(sourceIndex));
targetQ.add(targetQ.get(sourceIndex));
voltageRegulationOn.add(voltageRegulationOn.get(sourceIndex));
targetV.add(targetV.get(sourceIndex));
}
}
void reduceVariantArraySize(int number) {
targetP.remove(targetP.size() - number, number);
targetQ.remove(targetQ.size() - number, number);
voltageRegulationOn.remove(voltageRegulationOn.size() - number, number);
targetV.remove(targetV.size() - number, number);
}
void allocateVariantArrayElement(int[] indexes, int sourceIndex) {
for (int index : indexes) {
targetP.set(index, targetP.get(sourceIndex));
targetQ.set(index, targetQ.get(sourceIndex));
voltageRegulationOn.set(index, voltageRegulationOn.get(sourceIndex));
targetV.set(index, targetV.get(sourceIndex));
}
}
}
private final Ref<NetworkImpl> network;
private TieLineImpl tieLine = null;
private double r;
private double x;
private double g;
private double b;
private String pairingKey;
private final GenerationImpl generation;
private final OperationalLimitsGroupsImpl operationalLimitsGroups;
// attributes depending on the variant
private final TDoubleArrayList p0;
private final TDoubleArrayList q0;
private final DanglingLineBoundaryImplExt boundary;
DanglingLineImpl(Ref<NetworkImpl> network, String id, String name, boolean fictitious, double p0, double q0, double r, double x, double g, double b, String pairingKey, GenerationImpl generation) {
super(network, id, name, fictitious);
this.network = network;
int variantArraySize = network.get().getVariantManager().getVariantArraySize();
this.p0 = new TDoubleArrayList(variantArraySize);
this.q0 = new TDoubleArrayList(variantArraySize);
for (int i = 0; i < variantArraySize; i++) {
this.p0.add(p0);
this.q0.add(q0);
}
this.r = r;
this.x = x;
this.g = g;
this.b = b;
this.pairingKey = pairingKey;
this.operationalLimitsGroups = new OperationalLimitsGroupsImpl(this, "limits");
this.boundary = new DanglingLineBoundaryImplExt(this);
this.generation = generation != null ? generation.attach(this) : null;
}
@Override
void replaceId(String newId) {
NetworkIndex.checkId(newId);
network.get().getIndex().remove(this);
id = newId;
network.get().getIndex().checkAndAdd(this);
}
void setTieLine(TieLineImpl tieLine) {
this.tieLine = tieLine;
}
@Override
public TerminalExt getTerminal() {
return terminals.get(0);
}
@Override
public Optional<TieLine> getTieLine() {
return Optional.ofNullable(tieLine);
}
@Override
public void remove() {
if (tieLine != null) {
throw new UnsupportedOperationException("Parent tie line " + tieLine.getId() + " should be removed before the child dangling line");
}
super.remove();
boundary.remove();
}
void removeTieLine() {
tieLine = null;
}
@Override
protected String getTypeDescription() {
return "Dangling line";
}
@Override
public boolean isPaired() {
return tieLine != null;
}
@Override
public double getP0() {
return p0.get(network.get().getVariantIndex());
}
@Override
public DanglingLineImpl setP0(double p0) {
NetworkImpl n = getNetwork();
int variantIndex = n.getVariantIndex();
double oldValue = this.p0.set(variantIndex, p0);
String variantId = n.getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
notifyUpdate("p0", variantId, oldValue, p0);
return this;
}
@Override
public double getQ0() {
return q0.get(network.get().getVariantIndex());
}
@Override
public DanglingLineImpl setQ0(double q0) {
NetworkImpl n = getNetwork();
int variantIndex = n.getVariantIndex();
double oldValue = this.q0.set(variantIndex, q0);
String variantId = n.getVariantManager().getVariantId(variantIndex);
n.invalidateValidationLevel();
notifyUpdate("q0", variantId, oldValue, q0);
return this;
}
@Override
public double getR() {
return r;
}
@Override
public DanglingLineImpl setR(double r) {
ValidationUtil.checkR(this, r);
double oldValue = this.r;
this.r = r;
notifyUpdate("r", oldValue, r);
return this;
}
@Override
public double getX() {
return x;
}
@Override
public DanglingLineImpl setX(double x) {
ValidationUtil.checkX(this, x);
double oldValue = this.x;
this.x = x;
notifyUpdate("x", oldValue, x);
return this;
}
@Override
public double getG() {
return g;
}
@Override
public DanglingLineImpl setG(double g) {
ValidationUtil.checkG(this, g);
double oldValue = this.g;
this.g = g;
notifyUpdate("g", oldValue, g);
return this;
}
@Override
public double getB() {
return b;
}
@Override
public DanglingLineImpl setB(double b) {
ValidationUtil.checkB(this, b);
double oldValue = this.b;
this.b = b;
notifyUpdate("b", oldValue, b);
return this;
}
@Override
public String getPairingKey() {
return pairingKey;
}
@Override
public DanglingLine setPairingKey(String pairingKey) {
if (this.isPaired()) {
throw new ValidationException(this, "pairing key cannot be set if dangling line is paired.");
} else {
String oldValue = this.pairingKey;
this.pairingKey = pairingKey;
notifyUpdate("pairing_key", oldValue, pairingKey);
}
return this;
}
@Override
public Generation getGeneration() {
return generation;
}
@Override
public Collection<OperationalLimitsGroup> getOperationalLimitsGroups() {
return operationalLimitsGroups.getOperationalLimitsGroups();
}
@Override
public Optional<String> getSelectedOperationalLimitsGroupId() {
return operationalLimitsGroups.getSelectedOperationalLimitsGroupId();
}
@Override
public Optional<OperationalLimitsGroup> getOperationalLimitsGroup(String id) {
return operationalLimitsGroups.getOperationalLimitsGroup(id);
}
@Override
public Optional<OperationalLimitsGroup> getSelectedOperationalLimitsGroup() {
return operationalLimitsGroups.getSelectedOperationalLimitsGroup();
}
@Override
public OperationalLimitsGroup newOperationalLimitsGroup(String id) {
return operationalLimitsGroups.newOperationalLimitsGroup(id);
}
@Override
public void setSelectedOperationalLimitsGroup(String id) {
operationalLimitsGroups.setSelectedOperationalLimitsGroup(id);
}
@Override
public void removeOperationalLimitsGroup(String id) {
operationalLimitsGroups.removeOperationalLimitsGroup(id);
}
@Override
public void cancelSelectedOperationalLimitsGroup() {
operationalLimitsGroups.cancelSelectedOperationalLimitsGroup();
}
@Override
public CurrentLimitsAdder newCurrentLimits() {
return operationalLimitsGroups.newCurrentLimits();
}
@Override
public ActivePowerLimitsAdder newActivePowerLimits() {
return operationalLimitsGroups.newActivePowerLimits();
}
@Override
public ApparentPowerLimitsAdder newApparentPowerLimits() {
return operationalLimitsGroups.newApparentPowerLimits();
}
@Override
public Boundary getBoundary() {
return boundary;
}
@Override
public void extendVariantArraySize(int initVariantArraySize, int number, int sourceIndex) {
super.extendVariantArraySize(initVariantArraySize, number, sourceIndex);
p0.ensureCapacity(p0.size() + number);
q0.ensureCapacity(q0.size() + number);
for (int i = 0; i < number; i++) {
p0.add(p0.get(sourceIndex));
q0.add(q0.get(sourceIndex));
}
if (generation != null) {
generation.extendVariantArraySize(number, sourceIndex);
}
}
@Override
public void reduceVariantArraySize(int number) {
super.reduceVariantArraySize(number);
p0.remove(p0.size() - number, number);
q0.remove(q0.size() - number, number);
if (generation != null) {
generation.reduceVariantArraySize(number);
}
}
@Override
public void deleteVariantArrayElement(int index) {
super.deleteVariantArrayElement(index);
// nothing to do
}
@Override
public void allocateVariantArrayElement(int[] indexes, int sourceIndex) {
super.allocateVariantArrayElement(indexes, sourceIndex);
for (int index : indexes) {
p0.set(index, p0.get(sourceIndex));
q0.set(index, q0.get(sourceIndex));
}
if (generation != null) {
generation.allocateVariantArrayElement(indexes, sourceIndex);
}
}
}