SimplePiModel.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.network;

import net.jafama.FastMath;
import org.apache.commons.lang3.Range;

import java.util.Optional;

/**
 * @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
 */
public class SimplePiModel implements PiModel {

    private double r = 0;
    private double x = 0;
    private double g1 = 0;
    private double b1 = 0;
    private double g2 = 0;
    private double b2 = 0;
    private double r1 = 1;
    private double a1 = 0;

    private static final String NO_TAP_POSITION_ERROR = "No tap position change in simple Pi model implementation";

    @Override
    public double getR() {
        return r;
    }

    @Override
    public SimplePiModel setR(double r) {
        this.r = r;
        return this;
    }

    @Override
    public double getX() {
        return x;
    }

    @Override
    public SimplePiModel setX(double x) {
        this.x = x;
        return this;
    }

    @Override
    public double getZ() {
        return FastMath.hypot(r, x);
    }

    @Override
    public double getY() {
        return 1 / getZ();
    }

    @Override
    public double getKsi() {
        return FastMath.atan2(r, x);
    }

    @Override
    public double getG1() {
        return g1;
    }

    public SimplePiModel setG1(double g1) {
        this.g1 = g1;
        return this;
    }

    @Override
    public double getB1() {
        return b1;
    }

    public SimplePiModel setB1(double b1) {
        this.b1 = b1;
        return this;
    }

    @Override
    public double getG2() {
        return g2;
    }

    public SimplePiModel setG2(double g2) {
        this.g2 = g2;
        return this;
    }

    @Override
    public double getB2() {
        return b2;
    }

    public SimplePiModel setB2(double b2) {
        this.b2 = b2;
        return this;
    }

    @Override
    public double getR1() {
        return r1;
    }

    @Override
    public double getMinR1() {
        return getR1();
    }

    @Override
    public double getMaxR1() {
        return getR1();
    }

    @Override
    public double getContinuousR1() {
        return getR1();
    }

    public SimplePiModel setR1(double r1) {
        this.r1 = r1;
        return this;
    }

    @Override
    public double getA1() {
        return a1;
    }

    @Override
    public SimplePiModel setA1(double a1) {
        this.a1 = a1;
        return this;
    }

    @Override
    public void roundA1ToClosestTap() {
        throw new IllegalStateException("A1 rounding is not supported in simple Pi model implementation");
    }

    @Override
    public void roundR1ToClosestTap() {
        throw new IllegalStateException("R1 rounding is not supported in simple Pi model implementation");
    }

    @Override
    public boolean shiftOneTapPositionToChangeA1(Direction direction) {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    @Override
    public Optional<Direction> updateTapPositionToReachNewR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection) {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    @Override
    public Optional<Direction> updateTapPositionToExceedNewA1(double deltaA1, int maxTapShift, AllowedDirection allowedDirection) {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    @Override
    public Optional<Direction> updateTapPositionToReachNewA1(double deltaA1, int maxTapShift, AllowedDirection allowedDirection) {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    private void rescaleZ(double z) {
        double ksi = getKsi();
        r = z * FastMath.sin(ksi);
        x = z * FastMath.cos(ksi);
    }

    @Override
    public boolean setMinZ(double minZ, LoadFlowModel loadFlowModel) {
        if (loadFlowModel == LoadFlowModel.DC) {
            if (FastMath.abs(this.x) < minZ) {
                this.x = minZ;
                return true;
            }
        } else {
            double z = getZ();
            if (z < minZ) {
                rescaleZ(minZ);
                return true;
            }
        }
        return false;
    }

    @Override
    public void setBranch(LfBranch branch) {
        // nothing to set
    }

    @Override
    public int getTapPosition() {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    @Override
    public PiModel setTapPosition(int tapPosition) {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }

    @Override
    public Range<Integer> getTapPositionRange() {
        throw new IllegalStateException(NO_TAP_POSITION_ERROR);
    }
}