AcLoadFlowResult.java
/**
* Copyright (c) 2019, 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.ac;
import com.powsybl.loadflow.LoadFlowResult;
import com.powsybl.openloadflow.ac.solver.AcSolverStatus;
import com.powsybl.openloadflow.lf.AbstractLoadFlowResult;
import com.powsybl.openloadflow.lf.outerloop.OuterLoopResult;
import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.util.PerUnit;
import java.util.Objects;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public class AcLoadFlowResult extends AbstractLoadFlowResult {
public static AcLoadFlowResult createNoCalculationResult(LfNetwork network) {
return new AcLoadFlowResult(network, 0, 0, AcSolverStatus.NO_CALCULATION, OuterLoopResult.stable(), Double.NaN, Double.NaN);
}
private final int solverIterations;
private final AcSolverStatus solverStatus;
public AcLoadFlowResult(LfNetwork network, int outerLoopIterations, int solverIterations,
AcSolverStatus solverStatus, OuterLoopResult outerLoopResult,
double slackBusActivePowerMismatch, double distributedActivePower) {
super(network, slackBusActivePowerMismatch, outerLoopIterations, outerLoopResult, distributedActivePower);
this.solverIterations = solverIterations;
this.solverStatus = Objects.requireNonNull(solverStatus);
}
public int getSolverIterations() {
return solverIterations;
}
public AcSolverStatus getSolverStatus() {
return solverStatus;
}
@Override
public boolean isSuccess() {
return solverStatus == AcSolverStatus.CONVERGED && getOuterLoopResult().status() == OuterLoopStatus.STABLE;
}
public boolean isWithNetworkUpdate() {
// do not reset state in case all results are ok and no NR iterations because it means that the network was
// not changed and no calculation update was needed.
return isSuccess() && solverIterations > 0;
}
@Override
public Status toComponentResultStatus() {
if (network.getValidity() == LfNetwork.Validity.INVALID_NO_GENERATOR || network.getValidity() == LfNetwork.Validity.INVALID_NO_GENERATOR_VOLTAGE_CONTROL) {
return new Status(LoadFlowResult.ComponentResult.Status.NO_CALCULATION, network.getValidity().toString());
}
if (getOuterLoopResult().status() == OuterLoopStatus.UNSTABLE) {
return new Status(LoadFlowResult.ComponentResult.Status.MAX_ITERATION_REACHED, "Reached outer loop max iterations limit. Last outer loop name: " + getOuterLoopResult().outerLoopName());
} else if (getOuterLoopResult().status() == OuterLoopStatus.FAILED) {
return new Status(LoadFlowResult.ComponentResult.Status.FAILED, "Outer loop failed: " + getOuterLoopResult().statusText());
} else {
return switch (getSolverStatus()) {
case CONVERGED -> new Status(LoadFlowResult.ComponentResult.Status.CONVERGED, "Converged");
case MAX_ITERATION_REACHED -> new Status(LoadFlowResult.ComponentResult.Status.MAX_ITERATION_REACHED, "Reached Newton-Raphson max iterations limit");
case SOLVER_FAILED -> new Status(LoadFlowResult.ComponentResult.Status.FAILED, "Solver failed");
case UNREALISTIC_STATE -> new Status(LoadFlowResult.ComponentResult.Status.FAILED, "Unrealistic state");
case NO_CALCULATION -> new Status(LoadFlowResult.ComponentResult.Status.NO_CALCULATION, "No calculation");
};
}
}
@Override
public String toString() {
return "AcLoadFlowResult(outerLoopIterations=" + outerLoopIterations
+ ", newtonRaphsonIterations=" + solverIterations
+ ", solverStatus=" + solverStatus
+ ", outerLoopStatus=" + outerLoopResult.status()
+ ", slackBusActivePowerMismatch=" + slackBusActivePowerMismatch * PerUnit.SB
+ ", distributedActivePower=" + distributedActivePower * PerUnit.SB
+ ")";
}
}