PerEquationTypeStoppingCriteria.java

/**
 * Copyright (c) 2023, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
 * 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.solver;

import com.powsybl.openloadflow.ac.equations.AcEquationType;
import com.powsybl.openloadflow.ac.equations.AcVariableType;
import com.powsybl.openloadflow.equations.EquationSystem;
import com.powsybl.openloadflow.equations.Vectors;
import com.powsybl.openloadflow.util.PerUnit;

/**
 * @author Alexandre Le Jean {@literal <alexandre.le-jean at artelys.com>}
 */
public class PerEquationTypeStoppingCriteria implements NewtonRaphsonStoppingCriteria {

    private final double convEpsPerEq;

    private final double maxDefaultAngleMismatch;

    private final double maxDefaultRatioMismatch;

    private final double maxDefaultSusceptanceMismatch;

    private final double maxActivePowerMismatch;

    private final double maxReactivePowerMismatch;

    private final double maxVoltageMismatch;

    public PerEquationTypeStoppingCriteria(double convEpsPerEq, double maxActivePowerMismatch,
                                           double maxReactivePowerMismatch, double maxVoltageMismatch,
                                           double maxDefaultAngleMismatch, double maxDefaultRatioMismatch,
                                           double maxDefaultSusceptanceMismatch) {
        this.convEpsPerEq = convEpsPerEq;
        this.maxActivePowerMismatch = maxActivePowerMismatch;
        this.maxReactivePowerMismatch = maxReactivePowerMismatch;
        this.maxVoltageMismatch = maxVoltageMismatch;
        this.maxDefaultAngleMismatch = maxDefaultAngleMismatch;
        this.maxDefaultRatioMismatch = maxDefaultRatioMismatch;
        this.maxDefaultSusceptanceMismatch = maxDefaultSusceptanceMismatch;
    }

    private double computeNorm(double[] fx) {
        return Vectors.norm2(fx);
    }

    private boolean computeStop(double[] fx, EquationSystem<AcVariableType, AcEquationType> equationSystem) {
        for (var eq : equationSystem.getIndex().getSortedEquationsToSolve()) {
            var type = eq.getType();
            var idx = eq.getColumn();
            switch (type) {
                case BRANCH_TARGET_P, BUS_TARGET_P, DUMMY_TARGET_P, BUS_DISTR_SLACK_P -> {
                    if (Math.abs(fx[idx]) * PerUnit.SB >= maxActivePowerMismatch) {
                        return false;
                    }
                }
                case BRANCH_TARGET_Q, BUS_TARGET_Q, DISTR_Q, DUMMY_TARGET_Q -> {
                    if (Math.abs(fx[idx]) * PerUnit.SB >= maxReactivePowerMismatch) {
                        return false;
                    }
                }
                case BUS_TARGET_V, ZERO_V -> {
                    if (Math.abs(fx[idx]) >= maxVoltageMismatch) {
                        return false;
                    }
                }
                case BRANCH_TARGET_RHO1, DISTR_RHO -> {
                    if (Math.abs(fx[idx]) >= maxDefaultRatioMismatch) {
                        return false;
                    }
                }
                case DISTR_SHUNT_B, SHUNT_TARGET_B -> {
                    if (Math.abs(fx[idx]) >= maxDefaultSusceptanceMismatch) {
                        return false;
                    }
                }
                case BUS_TARGET_PHI, ZERO_PHI, BRANCH_TARGET_ALPHA1 -> {
                    if (Math.abs(fx[idx]) >= maxDefaultAngleMismatch) {
                        return false;
                    }
                }
                default -> {
                    if (Math.abs(fx[idx]) >= convEpsPerEq) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    @Override
    public TestResult test(double[] fx, EquationSystem<AcVariableType, AcEquationType> equationSystem) {
        return new TestResult(computeStop(fx, equationSystem), computeNorm(fx));
    }
}