/*****************************
 * 暂降域计算方法
 * add by yxb
 * 2021-12-14
 ****************************/
package com.pqs9200.utils;

import com.njcn.utils.PubUtils;
import com.njcn.utils.sagDomain.Complex;
import com.njcn.utils.sagDomain.DipZoneModel;
import com.njcn.utils.sagDomain.Matrix;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SagDomain {

    /// <summary>
    /// 正序阻抗矩阵
    /// 首段节点号 末端节点号  支路电阻  支路电抗 对地导纳
    /// </summary>
    public static double[][] ZL1 =
    {
        {1  ,3  ,0.000277,  0.000341,   0.000150    },
        {1  ,4  ,0.003756,  0.004627,   0.002042    },
        {1  ,2  ,0.003505,  0.004318,   0.001905    },
        {3  ,5  ,0.000796,  0.000980,   0.000433    },
        {5  ,4  ,0.002548,  0.003139,   0.001385    },
        {5  ,2  ,0.003289,  0.004052,   0.001788    },
        {6  ,9  ,1.042800,  3.065200,   0.000022    },
        {7  ,9  ,0.976800,  2.871200,   0.000021    },
        {9  ,13 ,5.940000,  17.460000,  0.000126    },
        {9  ,11 ,4.224000,  12.416000,  0.000090    },
        {9  ,12 ,1.320000,  3.880000,   0.000028    },
        {9  ,10 ,4.488000,  13.192000,  0.000095    },
        {12 ,16 ,1.108800,  3.259200,   0.000024    },
        {16 ,10 ,0.910800,  2.677200,   0.000019    },
        {6  ,8  ,1.980000,  5.820000,   0.000042    },
        {8  ,10 ,1.980000,  5.820000,   0.000042    },
        {10 ,15 ,6.072000,  17.848000,  0.000129    },
        {10 ,14 ,6.072000,  17.848000,  0.000129    },
        {15 ,14 ,3.168000,  9.312000,   0.000067    },
        {4  ,7  ,0,         0.208   ,   0.978}, //变压器支路
        {2  ,6  ,0,         0.556   ,   0.969}, //变压器支路
    };
    /// <summary>
    /// 负序阻抗矩阵，数值和正序一致
    /// 首段节点号 末端节点号  支路电阻  支路电抗 对地导纳
    /// </summary>
    public static double[][] ZL2 =
    {
            {1  ,2  ,0.000277,  0.000341,   0.000150    },
            {1  ,4  ,0.003756,  0.004627,   0.002042    },
            {1  ,12 ,0.003505,  0.004318,   0.001905    },
            {2  ,3  ,0.000796,  0.000980,   0.000433    },
            {3  ,4  ,0.002548,  0.003139,   0.001385    },
            {3  ,12 ,0.003289,  0.004052,   0.001788    },
            {13 ,6  ,1.042800,  3.065200,   0.000022    },
            {5  ,6  ,0.976800,  2.871200,   0.000021    },
            {6  ,7  ,5.940000,  17.460000,  0.000126    },
            {6  ,8  ,4.224000,  12.416000,  0.000090    },
            {6  ,9  ,1.320000,  3.880000,   0.000028    },
            {6  ,11 ,4.488000,  13.192000,  0.000095    },
            {9  ,10 ,1.108800,  3.259200,   0.000024    },
            {10 ,11 ,0.910800,  2.677200,   0.000019    },
            {13 ,14 ,1.980000,  5.820000,   0.000042    },
            {14 ,11 ,1.980000,  5.820000,   0.000042    },
            {11 ,15 ,6.072000,  17.848000,  0.000129    },
            {11 ,16 ,6.072000,  17.848000,  0.000129    },
            {15 ,16 ,3.168000,  9.312000,   0.000067    },
            {4  ,5  ,0,         0.208   ,   0.978},	//变压器支路
            {12 ,13 ,0,         0.556   ,   0.969},	//变压器支路
    };
    /// <summary>
    /// 零序阻抗矩阵，数值为正序的2.5倍
    /// 首段节点号 末端节点号  支路电阻  支路电抗 对地导纳
    /// </summary>
    public static double[][] ZL0 =
    {
        {1  ,3  ,0.000693  ,0.000853   ,0.000375},
        {1  ,4  ,0.009390  ,0.011568   ,0.005105},
        {1  ,2  ,0.008763  ,0.010795   ,0.004763},
        {3  ,5  ,0.001990  ,0.002450   ,0.001083},
        {5  ,4  ,0.006370  ,0.007848   ,0.003463},
        {5  ,2  ,0.008223  ,0.010130   ,0.004470},
        {6  ,9  ,2.607000  ,7.663000   ,0.000055},
        {7  ,9  ,2.442000  ,7.178000   ,0.000053},
        {9  ,13  ,14.850000 ,43.650000  ,0.000315},
        {9  ,11 ,10.560000 ,31.040000  ,0.000225},
        {9  ,12 ,3.300000  ,9.700000   ,0.000070},
        {9  ,10 ,11.220000 ,32.980000  ,0.000238},
        {12 ,16 ,2.772000  ,8.148000   ,0.000060},
        {16 ,10 ,2.277000  ,6.693000   ,0.000048},
        {6  ,8  ,4.950000  ,14.550000  ,0.000105},
        {8  ,10 ,4.950000  ,14.550000  ,0.000105},
        {10 ,15 ,15.180000 ,44.620000  ,0.000323},
        {10 ,14 ,15.180000 ,44.620000  ,0.000323},
        {15 ,14 ,7.920000  ,23.280000  ,0.000168},
        {4  ,7  ,0         ,0.52       ,2.445  }, //变压器支路
        {2  ,6  ,0         ,1.39       ,2.4225 }, //变压器支路
    };

    public static Complex[] Vpre =
            {
                    new Complex(0.956   ,0.434239565  ),//1
                    new Complex(1.002   ,0.313840724 ),//12
                    new Complex(0.955   ,0.436434417 ),//2
                    new Complex(0.983   ,0.369067744 ),//4
                    new Complex(0.957   ,0.432031249),//3
                    new Complex(1.003   ,0.310630005 ),//13
                    new Complex(0.984   ,0.366393231 ),//5
                    new Complex(1.011   ,0.283511905 ),//14
                    new Complex(1.007   ,0.297407128 ),//6
                    new Complex(1.021   ,0.245069378 ),//11
                    new Complex(1.03    ,0.203960781 ),//7
                    new Complex(1.01    ,0.287054002 ),//9
                    new Complex(1.03    ,0.203960781 ),//8
                    new Complex(1.04    ,0.144568323 ),//16
                    new Complex(1.028   ,0.213813002  ),//15
                    new Complex(1.009   ,0.290549479 )//10
            };

    public static void main(String[] args) {
        SagDomain sagDomain =new SagDomain();
        sagDomain.analysisSagDomain(0.7,1,1,16,19, ZL1,ZL0,Vpre);
    }

    /**********************************************
     * 获取暂降域的算法
     * uthre 暂降幅值
     * eventType 暂降类型
     * eventPoint 暂降出发点
     * iNodeCount 节点目数
     * iLineCount 线路目数
     * ps_Value 正序数组
     * ns_Value 零序数组
     * vpre_Value 节点信息
     **********************************************/
    public DipZoneModel[] analysisSagDomain(double uthre,int eventType,int eventPoint,int iNodeCount,int iLineCount,double[][] ps_Value,double[][] ns_Value,Complex[] vpre_Value) {
        Complex cmp_Base=new Complex(0,0);//做计算基础
        /*System.out.println("=======静态======");
        for (Complex com : Vpre) {
            System.out.println(com);
        }
        System.out.println("=======动态======");
        for (Complex com : vpre_Value) {
            System.out.println(com);
        }
        vpre_Value = Vpre;*/

        // 旋转因子,不要问我为什么设置这么多，我也不知道
        Complex alpha = new Complex(-0.5,Math.sqrt(3)/2);
        // 根据电网路径表，将路径表上电缆等分为1000个等分点
        double stepValue = 0.001;
        int iAllCount = ps_Value.length;//数组总长度（包含了线路+变压器支路）
        //求节点正序导纳矩阵
        Complex[][] ps_Complex = getMatrix(iNodeCount,iLineCount,ps_Value);
        //求节点零序导纳矩阵
        Complex[][] zs_Complex = getMatrix(iNodeCount,iLineCount,ns_Value);
        int rowLength = ps_Complex.length;// 获取行数
        int colLength = zs_Complex[0].length;// 获取列数

        //矩阵求逆,求节点阻抗矩阵
        Complex[][] ps_Inverse = Matrix.Inverse(ps_Complex);//正序
        Complex[][] ns_Inverse = ps_Inverse;//负序
        Complex[][] zs_Inverse = Matrix.Inverse(zs_Complex);//零序

        //依次选择故障线路，设故障点为f，距首端距离为stepValue，距末端距离为(1-stepValue)
        int nLineStepCount = (int)Math.ceil(1.0 / stepValue + 1 );
        //单相接地故障幅值
        double[][] singleGround = new double[iLineCount][nLineStepCount];
        //两相短路故障幅值
        double[][] twoPhaseShortOut = new double[iLineCount][nLineStepCount];
        //两相短路接地故障幅值
        double[][] twoPhaseGround = new double[iLineCount][nLineStepCount];
        //三相短路故障幅值
        double[][] threePhaseShortOut = new double[iLineCount][nLineStepCount];

        // 组装四种暂降类型数组
        double lStep = 0;
        int m = eventPoint - 1;//敏感负荷节点号    1是节点序号，-1是数组的位置是从0起始
        for (int i = 0;i < iLineCount; i++)
        {
            lStep = 0 ;// 初始化为0
            int iStart = (int)ps_Value[i][0] - 1;//首节点序号
            int iEnd = (int)ps_Value[i][1] - 1;//末点序号

            // 根据分割的步弧去计算
            for(int j=0;j< nLineStepCount; j++)
            {
                lStep += stepValue;//加上计算步骤
                Complex cmp_lStep =new Complex(lStep,0);//步数复数
                Complex cmp_lStep_power =new Complex(Math.pow(lStep, 2),0);//步数复数平方

                // 计算故障点与敏感负荷节点之间的互阻抗
                // 正序
                Complex Zmf1 = cmp_Base.add(cmp_Base.multiplication(cmp_Base.subduction(ps_Inverse[iEnd][m],ps_Inverse[iStart][m]),cmp_lStep ),ps_Inverse[iStart][m]);
                Complex tmpZmf1 = cmp_Base.subduction(cmp_Base.add(ps_Inverse[iStart][iStart],ps_Inverse[iEnd][iEnd]),cmp_Base.multiplication(ps_Inverse[iStart][iEnd],new Complex(2,0)));
                Complex tmpZmf2 = new Complex(ps_Value[i][2],ps_Value[i][3]);
                Complex tmpZmf12 = cmp_Base.multiplication(cmp_Base.subduction(tmpZmf1,tmpZmf2),cmp_lStep_power);
                Complex tmpZmf3 = cmp_Base.subduction(cmp_Base.multiplication(ps_Inverse[iStart][iEnd],new Complex(2,0)),cmp_Base.multiplication(ps_Inverse[iStart][iStart],new Complex(2,0)));
                Complex tmpZmf32 = cmp_Base.multiplication(cmp_Base.add(tmpZmf3,tmpZmf2),cmp_lStep);
                Complex Zff1 = cmp_Base.add(cmp_Base.add(tmpZmf12,tmpZmf32),ps_Inverse[iStart][iStart]);
                //正序=负序
                Complex Zmf2 = Zmf1;
                Complex Zff2 = Zff1;
                //零序
                Complex Zmf0 = cmp_Base.add(cmp_Base.multiplication(cmp_Base.subduction(zs_Inverse[m][iEnd],zs_Inverse[m][iStart]),cmp_lStep),zs_Inverse[m][iStart]);
                Complex tmpZff1 = cmp_Base.subduction(cmp_Base.add(zs_Inverse[iStart][iStart],zs_Inverse[iEnd][iEnd]),cmp_Base.multiplication(zs_Inverse[iStart][iEnd],new Complex(2,0)));
                Complex tmpZff2 = new Complex(ns_Value[i][2],ns_Value[i][3]);
                Complex tmpZff12 = cmp_Base.multiplication(cmp_Base.subduction(tmpZff1,tmpZff2),cmp_lStep_power);
                Complex tmpZff3 = cmp_Base.subduction(cmp_Base.multiplication(zs_Inverse[iStart][iEnd],new Complex(2,0)),cmp_Base.multiplication(zs_Inverse[iStart][iStart],new Complex(2,0)));
                Complex tmpZff32 = cmp_Base.multiplication(cmp_Base.add(tmpZff3,tmpZff2),cmp_lStep);
                Complex Zff0 = cmp_Base.add(cmp_Base.add(tmpZff12,tmpZff32),zs_Inverse[iStart][iStart]);

                //计算故障前故障点电压(iStart + (iEnd - iStart) * lStep)
                Complex Vpre_f = cmp_Base.add(vpre_Value[iStart],cmp_Base.multiplication(cmp_Base.subduction(vpre_Value[iEnd],vpre_Value[iStart]),cmp_lStep));

                //求不同故障类型在敏感负荷点造成的暂降值（以a相为参考相）
                Complex Temp1 = cmp_Base.add(cmp_Base.add(Zmf0,Zmf1),Zmf2);//Zmf0 + Zmf1 + Zmf2
                Complex Temp2 = cmp_Base.add(cmp_Base.add(Zff0,Zff1),Zff2);//Zff0 + Zff1 + Zff2
                Complex Temp3 = cmp_Base.dividion(Temp1,Temp2);//Temp1/Temp2
                //Complex Temp3 = cmp_Base.multiplication(Vpre_f,Temp1);//Vpre_f * Temp1
                //Complex Temp4 = cmp_Base.dividion(Temp3,Temp2);//Temp3/Temp2

                Complex Temp11 = cmp_Base.multiplication(alpha,alpha);
                Complex Temp12 = cmp_Base.multiplication(Temp11,Zmf1);
                Complex Temp13 = cmp_Base.multiplication(alpha,Zmf2);
                Complex Temp14 = cmp_Base.multiplication(Temp11,vpre_Value[m]);
                Complex Temp15 = cmp_Base.subduction(Temp12,Temp13);
                Complex Temp16 = cmp_Base.multiplication(Vpre_f,cmp_Base.add(cmp_Base.multiplication(cmp_Base.subduction(Temp12,Zmf0),Zff2),cmp_Base.multiplication(Temp15,Zff0)));

                Complex Temp21 = cmp_Base.multiplication(Zff0,Zff1);
                Complex Temp22 = cmp_Base.multiplication(Zff1,Zff2);
                Complex Temp23 = cmp_Base.multiplication(Zff2,Zff2);
                Complex Temp24 = cmp_Base.add(cmp_Base.add(Temp21,Temp22),Temp23);
                //单相接地故障
                Complex Vm1 = cmp_Base.subduction(vpre_Value[m],cmp_Base.multiplication(Vpre_f,Temp3));
                singleGround[i][j] = Complex.module(Vm1);  //求电压幅值
                //两相短路
                //Complex Vm2  = Temp14 - Vpre_f * Temp15 / (Zff1 + Zff2);
                Complex Vm2  = cmp_Base.subduction(Temp14,cmp_Base.dividion(cmp_Base.multiplication(Vpre_f,Temp15),cmp_Base.add(Zff1,Zff2)));
                twoPhaseShortOut[i][j] = Complex.module(Vm2);  //求电压幅值
                //两相短路接地
                //Complex Vm3 = Temp14 - Vpre_f *((Temp12 - Zmf0) * Zff2 + Temp15 * Zff0) / (Temp21 + Temp22 + Temp23);
                Complex Vm3 =cmp_Base.subduction(Temp14,cmp_Base.dividion(Temp16,Temp24));
                twoPhaseGround[i][j] = Complex.module(Vm3);  //求电压幅值
                //三相短路
                //Complex Vm4 = vpre_Value[m] - Vpre_f * Zmf1 / Zff1;
                Complex Vm4 = cmp_Base.subduction(vpre_Value[m],cmp_Base.dividion(cmp_Base.multiplication(Vpre_f,Zmf1),Zff1));
                threePhaseShortOut[i][j] = Complex.module(Vm4);  //求电压幅值
            }
        }

        //求取临界点及暂降域
        DipZoneModel[] Usag_area = new DipZoneModel[iLineCount];
        int fg = eventType -1;

        for (int i = 0; i < iLineCount; i++)
        {
            int iStart = (int)ps_Value[i][0] - 1;//线路首端编号
            int iEnd = (int)ps_Value[i][1] - 1;//线路末端编号
            double dlength = ps_Value[i][5];//线路末端编号
            lStep = 0;
            double[] sag = new double[nLineStepCount];//暂降的点位
            List<Double> sag1 = new ArrayList<>();
            int nSagCount = 0;
            for (int j = 0; j < nLineStepCount; j++)
            {
                lStep += stepValue;//加上步距
                switch (fg)
                {
                    //单相接地故障
                    case 0:
                        //统计处于暂降域的故障点
                        if (singleGround[i][j] <= uthre) {
                            sag[j] = lStep;
                            sag1.add(lStep);
                            nSagCount++;
                        }
                    break;
                    //两相短路
                    case 1:
                        //统计处于暂降域的故障点
                        if (twoPhaseShortOut[i][j] <= uthre) {
                            sag[j] = lStep;
                            sag1.add(lStep);
                            nSagCount++;
                        }
                    break;
                    //两相短路接地
                    case 2:
                        //统计处于暂降域的故障点
                        if (twoPhaseGround[i][j] <= uthre) {
                            sag[j] = lStep;
                            sag1.add(lStep);
                            nSagCount++;
                        }
                    break;
                    //三相短路
                    case 3:
                        //统计处于暂降域的故障点
                        if (threePhaseShortOut[i][j] <= uthre) {
                            sag[j] = lStep;
                            sag1.add(lStep);
                            nSagCount++;
                        }
                    break;
                }
            }
            Usag_area[i] = new DipZoneModel();
            Usag_area[i].setHead(iStart + 1);
            Usag_area[i].setTail(iEnd + 1);
            if (nSagCount == 0)//整条线路都不处于暂降域
            {
                Usag_area[i].setJudgeType(DipZoneModel.SagJudge.SAG_NONE);
            }
            else if (nSagCount >= (nLineStepCount-1))//整条线路都处于暂降域
            {
                Usag_area[i].setJudgeType(DipZoneModel.SagJudge.SAG_ALL);
                Usag_area[i].setNode2(1);
            }
            else if (sag[1] == stepValue && sag[nLineStepCount - 1] == 0)//暂降域为线路首端-临界点
            {
                Usag_area[i].setJudgeType(DipZoneModel.SagJudge.SAG_SIGLE);
                Usag_area[i].setNode1(0);
                Usag_area[i].setNode2(sag1.get(sag1.size() - 1));
            }
            else if (sag[1] == 0.0 && sag[nLineStepCount - 1] == (lStep-stepValue))//暂降域为临界点-线路末端
            {
                Usag_area[i].setJudgeType(DipZoneModel.SagJudge.SAG_SIGLE);
                Usag_area[i].setNode1(sag1.get(0));
                Usag_area[i].setNode2(1);
            }
            else
            {
                int pp = 0;
                double p1 = 0;
                double p2 = 0;
                for (int t = 1; t < nLineStepCount; t++)
                {
                    if (sag[t] == 0 && pp == 0)
                    {
                        p1 = (t - 2) * stepValue;
                        pp = 1;
                    }
                    if (sag[t] != 0 && pp == 1)
                    {
                        p2 = (t - 1) * stepValue;
                        break;
                    }
                }
                Usag_area[i].setJudgeType(DipZoneModel.SagJudge.SAG_SIGLE) ;
                Usag_area[i].setNode1(p1) ;
                Usag_area[i].setNode2(p2) ;
            }
            Usag_area[i].setNodeLength1(PubUtils.doubleRound(6,Usag_area[i].getNode1() * dlength)) ;
            Usag_area[i].setNodeLength2(PubUtils.doubleRound(6,Usag_area[i].getNode2() * dlength)) ;

        }

        return  Usag_area;
    }

    /**********************************************
     * 根据线路条目和对应数组获取节点正序、零序导纳矩阵
     * iNodeCount 节点目数
     * iLineCount 线路目数
     * param_Value 正序、零序数组
     **********************************************/
    private Complex[][] getMatrix(int iNodeCount,int iLineCount,double[][] param_Value){
        Complex cmp_Base=new Complex(0,0);//做计算基础
        int iAllCount = param_Value.length;//数组总长度（包含了线路+变压器支路）
        //求节点正序导纳矩阵
        Complex[][] result_Complex = new Complex[iNodeCount][iNodeCount];
        //默认初始值为0
        for(int i = 0; i < iNodeCount; i++){
            for(int j = 0; j < iNodeCount; j++){
                result_Complex[i][j] = cmp_Base;
            }
        }

        for(int i = 0; i < iLineCount; i++)
        {
            int iStart = (int)param_Value[i][0] - 1;//首节点序号
            int iEnd = (int)param_Value[i][1] - 1;//末点序号
            Complex cmp_Line = new Complex(param_Value[i][2],param_Value[i][3]);//电阻+电抗i
            result_Complex[iStart][iEnd] = cmp_Base.dividion(new Complex(-1,0),cmp_Line);
            result_Complex[iEnd][iStart] = result_Complex[iStart][iEnd];
            result_Complex[iStart][iStart] = cmp_Base.add(cmp_Base.add(result_Complex[iStart][iStart],cmp_Base.dividion(new Complex(1,0),cmp_Line)),new Complex(0,param_Value[i][4]));
            result_Complex[iEnd][iEnd] = cmp_Base.add(cmp_Base.add(result_Complex[iEnd][iEnd],cmp_Base.dividion(new Complex(1,0),cmp_Line)), new Complex(0, param_Value[i][4]));
        }
        //变压器支路
        for(int i = iLineCount;i < iAllCount;i++)
        {
            int iStart = (int)param_Value[i][0] - 1;//首节点序号
            int iEnd = (int)param_Value[i][1] - 1;//末点序号
            Complex cmp_Line = new Complex(0,param_Value[i][3] * param_Value[i][4]);//(电阻+电抗)i
            result_Complex[iStart][iEnd] = cmp_Base.dividion(new Complex(-1,0),cmp_Line);
            result_Complex[iEnd][iStart] = result_Complex[iStart][iEnd];
            result_Complex[iStart][iStart] = cmp_Base.add(cmp_Base.add(result_Complex[iStart][iStart],cmp_Base.dividion(new Complex(1,0),cmp_Line)),cmp_Base.multiplication(cmp_Base.dividion(new Complex(1 - param_Value[i][4],0),new Complex(0, Math.pow(param_Value[i][4],2))),new Complex(0, param_Value[i][3])));
            result_Complex[iEnd][iEnd] = cmp_Base.add(cmp_Base.add(result_Complex[iEnd][iEnd],cmp_Base.dividion(new Complex(1,0),cmp_Line)),cmp_Base.multiplication(cmp_Base.dividion(new Complex(param_Value[i][4] - 1,0), new Complex(0, param_Value[i][4])),new Complex(0, param_Value[i][3])));
        }
        return  result_Complex;
    }
}
