AbstractEquationSystemUpdater.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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.openloadflow.lf;
import com.powsybl.commons.PowsyblException;
import com.powsybl.openloadflow.equations.Equation;
import com.powsybl.openloadflow.equations.EquationSystem;
import com.powsybl.openloadflow.equations.Quantity;
import com.powsybl.openloadflow.network.*;
import java.util.Objects;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public abstract class AbstractEquationSystemUpdater<V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> extends AbstractLfNetworkListener {
protected final EquationSystem<V, E> equationSystem;
protected final LoadFlowModel loadFlowModel;
protected AbstractEquationSystemUpdater(EquationSystem<V, E> equationSystem, LoadFlowModel loadFlowModel) {
this.equationSystem = Objects.requireNonNull(equationSystem);
this.loadFlowModel = Objects.requireNonNull(loadFlowModel);
}
protected static void checkSlackBus(LfBus bus, boolean disabled) {
if (disabled && bus.isSlack()) {
throw new PowsyblException("Slack bus '" + bus.getId() + "' disabling is not supported");
}
}
protected abstract void updateNonImpedantBranchEquations(LfBranch branch, boolean enable);
@Override
public void onZeroImpedanceNetworkSpanningTreeChange(LfBranch branch, LoadFlowModel loadFlowModel, boolean spanningTree) {
if (loadFlowModel == this.loadFlowModel) {
updateNonImpedantBranchEquations(branch, !branch.isDisabled() && spanningTree);
}
}
protected void updateElementEquations(LfElement element, boolean enable) {
if (element instanceof LfBranch branch && branch.isZeroImpedance(loadFlowModel)) {
updateNonImpedantBranchEquations(branch, enable && branch.isSpanningTreeEdge(loadFlowModel));
} else {
// update all equations related to the element
for (var equation : equationSystem.getEquations(element.getType(), element.getNum())) {
if (equation.isActive() != enable) {
equation.setActive(enable);
}
}
// update all equation terms related to the element
for (var equationTerm : equationSystem.getEquationTerms(element.getType(), element.getNum())) {
if (equationTerm.isActive() != enable) {
equationTerm.setActive(enable);
}
}
}
}
protected abstract E getTypeBusTargetP();
protected abstract E getTypeBusTargetPhi();
protected abstract V getTypeBusPhi();
@Override
public void onSlackBusChange(LfBus bus, boolean slack) {
equationSystem.getEquation(bus.getNum(), getTypeBusTargetP())
.orElseThrow()
.setActive(!slack);
}
@Override
public void onReferenceBusChange(LfBus bus, boolean reference) {
if (reference) {
Equation<V, E> phiEq = equationSystem.getEquation(bus.getNum(), getTypeBusTargetPhi()).orElse(null);
if (phiEq == null) {
phiEq = equationSystem.createEquation(bus, getTypeBusTargetPhi())
.addTerm(equationSystem.getVariable(bus.getNum(), getTypeBusPhi())
.createTerm());
}
phiEq.setActive(true);
} else {
equationSystem.getEquation(bus.getNum(), getTypeBusTargetPhi())
.orElseThrow()
.setActive(false);
}
}
}