public ComplexMatrix(Complex[,] values)
     : this(values.GetLength(0), values.GetLength(1))
 {
     for (int i = 0; i < rows; i++)
     {
         for (int j = 0; j < columns; j++)
         {
             SetEntryInternal(i, j, values[i, j]);
         }
     }
 }
Beispiel #2
0
 // [X] = ([A]*)t
 public static Complex[,] matrix_ConjugateTranspose(Complex[,] matA)
 {
     Complex[,] matX = new Complex[matA.GetLength(1), matA.GetLength(0)];
     for (int i = 0; i < matX.GetLength(0); i++)
     {
         for (int j = 0; j < matX.GetLength(1); j++)
         {
             matX[i, j] = new Complex(matA[j, i].Real, -matA[j, i].Imag);
         }
     }
     return matX;
 }
        /// <summary>
        /// 2�����z�񂩂�V�����s���쐬����D
        /// </summary>
        /// <param name="arr">�s��̗v�f��i�[����2�����z��</param>
        public MyComplexMatrix(Complex[,] arr)
        {
            int rsize = arr.GetLength(0);
            int csize = arr.GetLength(1);

            Resize(rsize, csize);

            for (int r = 0; r < rsize; ++r)
            {
                for (int c = 0; c < csize; ++c)
                {
                    this[r, c] = arr[r, c];
                }
            }
        }
Beispiel #4
0
 public static Complex[,] product(Complex[,] matA, Complex[,] matB)
 {
     System.Diagnostics.Debug.Assert(matA.GetLength(1) == matB.GetLength(0));
     Complex[,] matX = new Complex[matA.GetLength(0), matB.GetLength(1)];
     for (int i = 0; i < matX.GetLength(0); i++)
     {
         for (int j = 0; j < matX.GetLength(1); j++)
         {
             matX[i, j] = 0.0;
             for (int k = 0; k < matA.GetLength(1); k++)
             {
                 matX[i, j] += matA[i, k] * matB[k, j];
             }
         }
     }
     return matX;
 }
Beispiel #5
0
 public static void printMatrix(string tag, Complex[,] mat)
 {
     for (int i = 0; i < mat.GetLength(0); i++)
     {
         for (int j = 0; j < mat.GetLength(1); j++)
         {
             Complex val = mat[i, j];
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = "
                                + "(" + val.Real + "," + val.Imag + ") " + Complex.Norm(val));
         }
     }
 }
Beispiel #6
0
 // [X] = [A] + [B]
 public static Complex[,] plus(Complex[,] matA, Complex[,] matB)
 {
     System.Diagnostics.Debug.Assert(matA.GetLength(0) == matB.GetLength(0));
     System.Diagnostics.Debug.Assert(matA.GetLength(1) == matB.GetLength(1));
     Complex[,] matX = new Complex[matA.GetLength(0), matA.GetLength(1)];
     for (int i = 0; i < matA.GetLength(0); i++)
     {
         for (int j = 0; j < matA.GetLength(1); j++)
         {
             matX[i, j] = matA[i, j] + matB[i, j];
         }
     }
     return matX;
 }
Beispiel #7
0
 /// <summary>
 ///   Constructs a matrix from the array.
 /// </summary>
 /// <param name="table"> The array the matrix gets constructed from. </param>
 public Matrix(Complex[,] table)
     : this((uint) table.GetLength(0), (uint) table.GetLength(1))
 {
     Initialize(table);
 }
Beispiel #8
0
 public static void matrix_setRowVec(Complex[,] matA, int row, Complex[] rowVec)
 {
     System.Diagnostics.Debug.Assert(matA.GetLength(1) == rowVec.Length);
     for (int j = 0; j < matA.GetLength(1); j++)
     {
         matA[row, j] = rowVec[j];
     }
 }
        /// <summary>
        /// ポート固有値解析
        /// </summary>
        public static void SolvePortWaveguideEigen(
            FemSolver.WaveModeDV WaveModeDv,
            double waveLength,
            double latticeA,
            int maxModeSpecified,
            IList<FemNode> Nodes,
            Dictionary<string, IList<int>> EdgeToElementNoH,
            IList<FemElement> Elements,
            MediaInfo[] Medias,
            Dictionary<int, bool> ForceNodeNumberH,
            IList<int> portNodes,
            IList<uint> portElemNoPeriodic,
            IList<IList<int>> portNodePeriodicB,
            IList<int> defectNodePeriodic,
            out int[] nodesBoundary,
            out MyDoubleMatrix ryy_1d,
            out Complex[] eigenValues,
            out Complex[,] eigenVecsB1,
            out Complex[,] eigen_dFdXsB1,
            out IList<int> nodePeriodic,
            out Dictionary<int, int> toNodePeriodic,
            out IList<double[]> coordsPeriodic,
            out KrdLab.clapack.Complex[][] eigenVecsPeriodic
            )
        {
            // ポート境界上
            nodesBoundary = null;
            ryy_1d = null;
            eigenValues = null;
            eigenVecsB1 = null;
            eigen_dFdXsB1 = null;
            // ポート周期構造領域
            nodePeriodic = null;
            toNodePeriodic = null;
            coordsPeriodic = null;
            eigenVecsPeriodic = null;

            // 波数
            double k0 = 2.0 * pi / waveLength;
            // 角周波数
            double omega = k0 * c0;

            getPortFemMat1D(
                WaveModeDv,
                waveLength,
                latticeA,
                Nodes,
                EdgeToElementNoH,
                Elements,
                Medias,
                ForceNodeNumberH,
                portNodes,
                out nodesBoundary,
                out ryy_1d
                );
            Dictionary<int, int> toNodesB = new Dictionary<int, int>();
            for (int ino = 0; ino < nodesBoundary.Length; ino++)
            {
                int nodeNumber = nodesBoundary[ino];
                //System.Diagnostics.Debug.WriteLine("nodesBoundary[{0}] = {1}", ino, nodesBoundary[ino]);
                toNodesB.Add(nodeNumber, ino);
            }

            //////////////////////////////////////////////////////////////////////////////
            // 周期構造導波路
            /////////////////////////////////////////////////////////////////////////////
            int incidentModeIndex = 0;
            Constants.FemElementShapeDV elemShapeDv;
            FemElement workElement = Elements[0];
            int order;
            int vertexCnt;
            FemMeshLogic.GetElementShapeDvAndOrderByElemNodeCnt(workElement.NodeNumbers.Length, out elemShapeDv, out order, out vertexCnt);

            // 領域の節点リスト、座標リストを取得する
            //IList<int> nodePeriodic = null;
            //Dictionary<int, int> toNodePeriodic = null;
            //IList<double[]> coordsPeriodic = null;
            getCoordListPeriodic(
                Nodes,
                Elements,
                portElemNoPeriodic,
                out nodePeriodic,
                out toNodePeriodic,
                out coordsPeriodic
                );
            // 全節点数
            int nodeCntPeriodic = nodePeriodic.Count;

            IList<IList<int>> nodePeriodicB = portNodePeriodicB;
            IList<int> nodePeriodicB1 = nodePeriodicB[0];
            IList<int> nodePeriodicB2 = nodePeriodicB[1];
            Dictionary<int, int> toNodePeriodicB1 = new Dictionary<int, int>();
            Dictionary<int, int> toNodePeriodicB2 = new Dictionary<int, int>();
            for (int ino = 0; ino < nodePeriodicB1.Count; ino++)
            {
                int nodeNumber = nodePeriodicB1[ino];
                toNodePeriodicB1.Add(nodeNumber, ino);
            }
            for (int ino = 0; ino < nodePeriodicB2.Count; ino++)
            {
                int nodeNumber = nodePeriodicB2[ino];
                toNodePeriodicB2.Add(nodeNumber, ino);
            }

            // Y方向に周期構造?
            bool isYDirectionPeriodic = false;
            {
                int nodeNumber_first = nodePeriodicB1[0];
                int nodeNumber_last = nodePeriodicB1[nodePeriodicB1.Count - 1];
                int noB_first = toNodePeriodic[nodeNumber_first];
                int noB_last = toNodePeriodic[nodeNumber_last];
                double[] coord_first = coordsPeriodic[noB_first];
                double[] coord_last = coordsPeriodic[noB_last];
                if (Math.Abs(coord_first[1] - coord_last[1]) < 1.0e-12)
                {
                    isYDirectionPeriodic = true;
                }
            }
            System.Diagnostics.Debug.WriteLine("isYDirectionPeriodic: {0}", isYDirectionPeriodic);

            // 節点の並び替え
            IList<int> sortedNodesPeriodic = new List<int>();
            Dictionary<int, int> toSortedPeriodic = new Dictionary<int, int>();
            // ポート境界1
            for (int ino = 0; ino < nodePeriodicB1.Count; ino++)
            {
                // 境界1の節点番号
                int nodeNumberB1 = nodePeriodicB1[ino];
                if (ForceNodeNumberH.ContainsKey(nodeNumberB1))
                {
                    // 強制境界は除外
                    continue;
                }
                sortedNodesPeriodic.Add(nodeNumberB1);
                int index = sortedNodesPeriodic.Count - 1;
                toSortedPeriodic.Add(nodeNumberB1, index);
            }
            int nodeCntBPeriodic = sortedNodesPeriodic.Count; // 境界1
            // 内部領域
            for (int ino = 0; ino < nodeCntPeriodic; ino++)
            {
                int nodeNumber = nodePeriodic[ino];
                if (ForceNodeNumberH.ContainsKey(nodeNumber))
                {
                    // 強制境界は除外
                    continue;
                }
                if (toNodePeriodicB1.ContainsKey(nodeNumber))
                {
                    // 境界1は除外
                    continue;
                }
                if (toNodePeriodicB2.ContainsKey(nodeNumber))
                {
                    // 境界2は除外
                    continue;
                }
                sortedNodesPeriodic.Add(nodeNumber);
                int index = sortedNodesPeriodic.Count - 1;
                toSortedPeriodic.Add(nodeNumber, index);
            }
            int freeNodeCntPeriodic = sortedNodesPeriodic.Count; // 境界1 + 内部領域
            // ポート境界2
            for (int ino = 0; ino < nodePeriodicB2.Count; ino++)
            {
                // 境界2の節点番号
                int nodeNumberB2 = nodePeriodicB2[ino];
                if (ForceNodeNumberH.ContainsKey(nodeNumberB2))
                {
                    // 強制境界は除外
                    continue;
                }
                sortedNodesPeriodic.Add(nodeNumberB2);
                int index = sortedNodesPeriodic.Count - 1;
                toSortedPeriodic.Add(nodeNumberB2, index);
            }
            int freeNodeCntPeriodic_0 = sortedNodesPeriodic.Count; // 境界1 + 内部領域 + 境界2

            // 周期構造導波路固有値問題用FEM行列の作成
            //bool isSVEA = false; // Φを直接解く方法
            bool isSVEA = true; // Φ= φexp(-jβx)と置く方法(SVEA)
            double[] KMat0 = null;
            double[] CMat0 = null;
            double[] MMat0 = null;
            if (isSVEA)
            {
                // Φ = φexp(-jβx)と置く方法
                KMat0 = new double[freeNodeCntPeriodic_0 * freeNodeCntPeriodic_0];
                CMat0 = new double[freeNodeCntPeriodic_0 * freeNodeCntPeriodic_0];
                MMat0 = new double[freeNodeCntPeriodic_0 * freeNodeCntPeriodic_0];
            }
            else
            {
                // Φを直接解く方法
                KMat0 = new double[freeNodeCntPeriodic_0 * freeNodeCntPeriodic_0];
                CMat0 = null;
                MMat0 = null;
            }
            IList<uint> elemNoPeriodic = portElemNoPeriodic;
            int elemCnt = elemNoPeriodic.Count;
            for (int ie = 0; ie < elemCnt; ie++)
            {
                int elemNo = (int)elemNoPeriodic[ie];
                FemElement femElement = Elements[elemNo - 1];
                System.Diagnostics.Debug.Assert(femElement.No == elemNo);

                if (elemShapeDv == Constants.FemElementShapeDV.Triangle && order == Constants.SecondOrder)
                {
                    // 2次三角形要素
                    FemMat_Tri_Second.AddElementMatPeriodic(
                        isYDirectionPeriodic,
                        isSVEA,
                        waveLength,
                        nodeCntPeriodic,
                        freeNodeCntPeriodic_0,
                        toSortedPeriodic,
                        femElement,
                        Nodes,
                        Medias,
                        ForceNodeNumberH,
                        WaveModeDv,
                        ref KMat0,
                        ref CMat0,
                        ref MMat0);
                }
                else if (elemShapeDv == Constants.FemElementShapeDV.Triangle && order == Constants.FirstOrder)
                {
                    // 1次三角形要素
                    FemMat_Tri_First.AddElementMatPeriodic(
                        isYDirectionPeriodic,
                        isSVEA,
                        waveLength,
                        nodeCntPeriodic,
                        freeNodeCntPeriodic_0,
                        toSortedPeriodic,
                        femElement,
                        Nodes,
                        Medias,
                        ForceNodeNumberH,
                        WaveModeDv,
                        ref KMat0,
                        ref CMat0,
                        ref MMat0);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
            }

            double periodicDistance = latticeA; // 正方格子誘電体ロッド限定
            bool isModeTrace = false;
            KrdLab.clapack.Complex[] tmpPrevModalVec_1stMode = null;
            double minBeta = 0.00; // 正方格子誘電体ロッド限定
            //double maxBeta = 0.90; // 正方格子誘電体ロッド限定
            double maxBeta = 0.5 * (2.0 * pi / periodicDistance) / k0;
            bool isPortBc2Reverse = false;
            // 伝搬定数
            KrdLab.clapack.Complex[] betamToSolveList = null;
            // 界ベクトルは全節点分作成
            KrdLab.clapack.Complex[][] resVecList = null;
            if (isSVEA)
            {
                System.Diagnostics.Debug.Assert(isSVEA == true);
                solveSVEAAsQuadraticGeneralizedEigenToStandardWithRealMat(
                    incidentModeIndex,
                    k0,
                    KMat0,
                    CMat0,
                    MMat0,
                    isPortBc2Reverse,
                    nodeCntPeriodic,
                    freeNodeCntPeriodic_0,
                    freeNodeCntPeriodic,
                    nodeCntBPeriodic,
                    sortedNodesPeriodic,
                    toSortedPeriodic,
                    toNodePeriodic,
                    toNodePeriodicB1,
                    defectNodePeriodic,
                    isModeTrace,
                    ref tmpPrevModalVec_1stMode,
                    minBeta,
                    maxBeta,
                    k0, //(2.0 * pi / periodicDistance), //k0, //1.0,
                    out betamToSolveList,
                    out resVecList);
            }
            else
            {
                System.Diagnostics.Debug.Assert(isSVEA == false);
                solveNonSVEAModeAsQuadraticGeneralizedEigenWithRealMat(
                    incidentModeIndex,
                    periodicDistance,
                    k0,
                    KMat0,
                    isPortBc2Reverse,
                    nodeCntPeriodic,
                    freeNodeCntPeriodic_0,
                    freeNodeCntPeriodic,
                    nodeCntBPeriodic,
                    sortedNodesPeriodic,
                    toSortedPeriodic,
                    toNodePeriodic,
                    toNodePeriodicB1,
                    coordsPeriodic,
                    defectNodePeriodic,
                    isModeTrace,
                    ref tmpPrevModalVec_1stMode,
                    minBeta,
                    maxBeta,
                    (2.0 * pi / periodicDistance), //k0, //1.0,
                    out betamToSolveList,
                    out resVecList);
            }

            // 固有値が1つでも取得できているかチェック
            if (betamToSolveList == null)
            {
                System.Diagnostics.Debug.WriteLine("betamToSolveList == null");
                //System.Diagnostics.Debug.Assert(false);
                return;
            }
            for (int imode = 0; imode < betamToSolveList.Length; imode++)
            {
                KrdLab.clapack.Complex betam = betamToSolveList[imode];
                KrdLab.clapack.Complex[] resVec = resVecList[imode];
                // ポート境界1の節点の値を境界2にも格納する
                for (int ino = 0; ino < nodePeriodicB1.Count; ino++)
                {
                    // 境界1の節点
                    int nodeNumberPortBc1 = nodePeriodicB1[ino];
                    int ino_InLoop_PortBc1 = toNodePeriodic[nodeNumberPortBc1];
                    // 境界1の節点の界の値を取得
                    KrdLab.clapack.Complex cvalue = resVec[ino_InLoop_PortBc1];

                    // 境界2の節点
                    int ino_B2 = isPortBc2Reverse ? (int)(nodePeriodicB2.Count - 1 - ino) : (int)ino;
                    int nodeNumberPortBc2 = nodePeriodicB2[ino_B2];

                    int ino_InLoop_PortBc2 = toNodePeriodic[nodeNumberPortBc2];
                    if (isSVEA)
                    {
                        // 緩慢変化包絡線近似の場合は、Φ2 = Φ1
                        resVec[ino_InLoop_PortBc2] = cvalue;
                    }
                    else
                    {
                        // 緩慢変化包絡線近似でない場合は、Φ2 = expA * Φ1
                        KrdLab.clapack.Complex expA = KrdLab.clapack.Complex.Exp(-1.0 * KrdLab.clapack.Complex.ImaginaryOne * betam * periodicDistance);
                        resVec[ino_InLoop_PortBc2] = expA * cvalue; // 直接Bloch境界条件を指定する場合
                    }
                }
            }

            /////////////////////////////////////////////////////////////////////////////////////
            // 位相調整

            for (int imode = 0; imode < betamToSolveList.Length; imode++)
            {
                KrdLab.clapack.Complex[] resVec = resVecList[imode];
                KrdLab.clapack.Complex phaseShift = 1.0;
                double maxAbs = double.MinValue;
                KrdLab.clapack.Complex fValueAtMaxAbs = 0.0;
                {
                    /*
                    // 境界上で位相調整する
                    for (int ino = 0; ino < nodePeriodicB1.Count; ino++)
                    {
                        int nodeNumberPortBc1 = nodePeriodicB1[ino];
                        int ino_InLoop_PortBc1 = toNodePeriodic[nodeNumberPortBc1];
                        KrdLab.clapack.Complex cvalue = resVec[ino_InLoop_PortBc1];
                        double abs = KrdLab.clapack.Complex.Abs(cvalue);
                        if (abs > maxAbs)
                        {
                            maxAbs = abs;
                            fValueAtMaxAbs = cvalue;
                        }
                    }
                     */

                    // 領域全体で位相調整する
                    for (int ino_InLoop = 0; ino_InLoop < resVec.Length; ino_InLoop++)
                    {
                        KrdLab.clapack.Complex cvalue = resVec[ino_InLoop];
                        double abs = KrdLab.clapack.Complex.Abs(cvalue);
                        if (abs > maxAbs)
                        {
                            maxAbs = abs;
                            fValueAtMaxAbs = cvalue;
                        }
                    }

                }
                if (maxAbs >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    phaseShift = fValueAtMaxAbs / maxAbs;
                }
                System.Diagnostics.Debug.WriteLine("phaseShift: {0} (°)", Math.Atan2(phaseShift.Imaginary, phaseShift.Real) * 180.0 / pi);
                for (int i = 0; i < resVec.Length; i++)
                {
                    resVec[i] /= phaseShift;
                }
            }

            /////////////////////////////////////////////////////////////////////////////////////
            // X方向の微分値を取得する
            KrdLab.clapack.Complex[][] resDFDXVecList = new KrdLab.clapack.Complex[betamToSolveList.Length][];
            for (int imode = 0; imode < betamToSolveList.Length; imode++)
            {
                KrdLab.clapack.Complex[] resVec = resVecList[imode];
                KrdLab.clapack.Complex[] resDFDXVec = null;
                KrdLab.clapack.Complex[] resDFDYVec = null;
                double rotAngle = 0.0; // 暫定
                double[] rotOrigin = null; // 暫定

                if (elemShapeDv == Constants.FemElementShapeDV.Triangle && order == Constants.SecondOrder)
                {
                    // 2次三角形要素
                    getDFDXValues_Tri_SecondOrder(
                        WaveModeDv,
                        k0,
                        rotAngle,
                        rotOrigin,
                        Nodes,
                        Elements,
                        Medias,
                        ForceNodeNumberH,
                        elemNoPeriodic,
                        nodePeriodicB,
                        toNodePeriodic,
                        resVec,
                        out resDFDXVec,
                        out resDFDYVec);
                }
                else if (elemShapeDv == Constants.FemElementShapeDV.Triangle && order == Constants.FirstOrder)
                {
                    // 1次三角形要素
                    getDFDXValues_Tri_FirstOrder(
                        WaveModeDv,
                        k0,
                        rotAngle,
                        rotOrigin,
                        Nodes,
                        Elements,
                        Medias,
                        ForceNodeNumberH,
                        elemNoPeriodic,
                        nodePeriodicB,
                        toNodePeriodic,
                        resVec,
                        out resDFDXVec,
                        out resDFDYVec);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (isYDirectionPeriodic)
                {
                    // Y方向周期構造の場合
                    resDFDXVecList[imode] = resDFDYVec;
                }
                else
                {
                    // X方向周期構造の場合
                    resDFDXVecList[imode] = resDFDXVec;
                }
            }
            // 境界1と境界2の節点の微分値は同じという条件を弱形式で課している為、微分値は同じにならない。
            // 加えて、getDFDXValuesは内部節点からの寄与を片側のみしか計算していない。
            // →境界の両側からの寄与を考慮する為に境界1の微分値と境界2の微分値を平均してみる
            for (int imode = 0; imode < betamToSolveList.Length; imode++)
            {
                KrdLab.clapack.Complex betam = betamToSolveList[imode];
                KrdLab.clapack.Complex[] resDFDXVec = resDFDXVecList[imode];
                // ポート境界1の節点の微分値、ポート境界2の微分値は、両者の平均をとる
                for (int ino = 0; ino < nodePeriodicB1.Count; ino++)
                {
                    // 境界1の節点
                    int nodeNumberPortBc1 = nodePeriodicB1[ino];
                    int ino_InLoop_PortBc1 = toNodePeriodic[nodeNumberPortBc1];
                    // 境界1の節点の界の微分値値を取得
                    KrdLab.clapack.Complex cdFdXValue1 = resDFDXVec[ino_InLoop_PortBc1];

                    // 境界2の節点
                    int ino_B2 = isPortBc2Reverse ? (int)(nodePeriodicB2.Count - 1 - ino) : (int)ino;
                    int nodeNumberPortBc2 = nodePeriodicB2[ino_B2];
                    int ino_InLoop_PortBc2 = toNodePeriodic[nodeNumberPortBc2];
                    // 境界2の節点の界の微分値値を取得
                    KrdLab.clapack.Complex cdFdXValue2 = resDFDXVec[ino_InLoop_PortBc2];

                    // 平均値を計算し、境界の微分値として再格納する
                    if (isSVEA)
                    {
                        KrdLab.clapack.Complex cdFdXValue = (cdFdXValue1 + cdFdXValue2) * 0.5;
                        resDFDXVec[ino_InLoop_PortBc1] = cdFdXValue;
                        resDFDXVec[ino_InLoop_PortBc2] = cdFdXValue;
                    }
                    else
                    {
                        // 緩慢変化包絡線近似でない場合は、Φ2 = expA * Φ1
                        KrdLab.clapack.Complex expA = KrdLab.clapack.Complex.Exp(-1.0 * KrdLab.clapack.Complex.ImaginaryOne * betam * periodicDistance);
                        // Φ2から逆算でΦ1を求め、平均をとる
                        KrdLab.clapack.Complex cdFdXValue = (cdFdXValue1 + cdFdXValue2 / expA) * 0.5;
                        resDFDXVec[ino_InLoop_PortBc1] = cdFdXValue;
                        resDFDXVec[ino_InLoop_PortBc2] = cdFdXValue * expA;
                    }
                }
            }

            //////////////////////////////////////////////////////////////////////////////////////
            if (!isSVEA)
            {
                // 緩慢変化包絡線近似でない場合は、緩慢変化包絡線近似の分布に変換する
                for (int imode = 0; imode < betamToSolveList.Length; imode++)
                {
                    KrdLab.clapack.Complex betam = betamToSolveList[imode];
                    KrdLab.clapack.Complex betam_periodic = ToBetaPeriodic(betam, periodicDistance);
                    KrdLab.clapack.Complex[] resVec = resVecList[imode];
                    KrdLab.clapack.Complex[] resDFDXVec = resDFDXVecList[imode];
                    System.Diagnostics.Debug.Assert(resVec.Length == coordsPeriodic.Count);
                    int nodeNumber1st = sortedNodesPeriodic[0];
                    int ino_InLoop_1st = toNodePeriodic[nodeNumber1st];
                    double[] coord1st = coordsPeriodic[ino_InLoop_1st];
                    for (int ino_InLoop = 0; ino_InLoop < resVec.Length; ino_InLoop++)
                    {
                        // 節点の界の値
                        KrdLab.clapack.Complex fieldVal = resVec[ino_InLoop];
                        // 節点の界の微分値
                        KrdLab.clapack.Complex dFdXVal = resDFDXVec[ino_InLoop];
                        // 節点の座標
                        double[] coord = coordsPeriodic[ino_InLoop];
                        double x_pt = 0.0;
                        if (isYDirectionPeriodic)
                        {
                            x_pt = (coord[1] - coord1st[1]);
                        }
                        else
                        {
                            x_pt = (coord[0] - coord1st[0]);
                        }
                        //KrdLab.clapack.Complex expX = KrdLab.clapack.Complex.Exp(-1.0 * KrdLab.clapack.Complex.ImaginaryOne * betam * x_pt);
                        KrdLab.clapack.Complex expX = KrdLab.clapack.Complex.Exp(-1.0 * KrdLab.clapack.Complex.ImaginaryOne * betam_periodic * x_pt);

                        // ΦのSVEA(φ)
                        KrdLab.clapack.Complex fieldVal_SVEA = fieldVal / expX;
                        resVec[ino_InLoop] = fieldVal_SVEA;

                        // SVEAの微分( exp(-jβx)dφ/dx = dΦ/dx + jβφexp(-jβx))
                        //resDFDXVec[ino_InLoop] = dFdXVal / expX + KrdLab.clapack.Complex.ImaginaryOne * betam * fieldVal_SVEA;
                        resDFDXVec[ino_InLoop] = dFdXVal / expX + KrdLab.clapack.Complex.ImaginaryOne * betam_periodic * fieldVal_SVEA;
                    }
                }
            }

            System.Diagnostics.Debug.WriteLine("betamToSolveList.Length {0}", betamToSolveList.Length);

            //////////////////////////////////////////////////////////////////////////////////////
            // モード数の修正
            int maxMode = maxModeSpecified;
            if (maxMode > betamToSolveList.Length)
            {
                maxMode = betamToSolveList.Length;
            }

            //////////////////////////////////////////////////////////////////////////////////////
            // 表示用に周期構造領域の固有モード分布を格納する
            eigenVecsPeriodic = new KrdLab.clapack.Complex[maxMode][];
            for (int imode = betamToSolveList.Length - 1, tagtModeIndex = 0; imode >= 0 && tagtModeIndex < maxMode; imode--, tagtModeIndex++)
            {
                KrdLab.clapack.Complex[] resVec = resVecList[imode];
                System.Diagnostics.Debug.Assert(resVec.Length == nodePeriodic.Count);
                eigenVecsPeriodic[tagtModeIndex] = new KrdLab.clapack.Complex[nodePeriodic.Count];
                resVec.CopyTo(eigenVecsPeriodic[tagtModeIndex], 0);
            }

            //////////////////////////////////////////////////////////////////////////////////////
            // 固有値、固有ベクトル
            // 格納
            int nodeCntB1 = nodePeriodicB1.Count;
            eigenValues = new Complex[maxMode];
            //eigenVecsB1 = new Complex[maxMode, nodeCntB1];
            //eigen_dFdXsB1 = new Complex[maxMode, nodeCntB1];
            eigenVecsB1 = new Complex[maxMode, nodesBoundary.Length]; // 強制境界を除く
            eigen_dFdXsB1 = new Complex[maxMode, nodesBoundary.Length]; // 強制境界を除く
            for (int imode = 0; imode < maxMode; imode++)
            {
                eigenValues[imode] = new Complex(0, 0);
                for (int ino = 0; ino < eigenVecsB1.GetLength(1); ino++)
                {
                    eigenVecsB1[imode, ino] = new Complex(0, 0);
                    eigen_dFdXsB1[imode, ino] = new Complex(0, 0);
                }
            }
            for (int imode = betamToSolveList.Length - 1, tagtModeIndex = 0; imode >= 0 && tagtModeIndex < maxMode; imode--, tagtModeIndex++)
            {
                //System.Diagnostics.Debug.WriteLine("imode = {0}", imode);

                KrdLab.clapack.Complex workBetam = betamToSolveList[imode];
                KrdLab.clapack.Complex[] resVec = resVecList[imode];
                KrdLab.clapack.Complex[] resDFDXVec = resDFDXVecList[imode];

                Complex betam = new Complex(workBetam.Real, workBetam.Imaginary);
                bool isComplexConjugateMode = false;
                //   減衰定数は符号がマイナス(β = -jα)
                if (betam.Imaginary > 0.0 && Math.Abs(betam.Real) <= 1.0e-12)
                {
                    betam = new Complex(betam.Real, -betam.Imaginary);
                    isComplexConjugateMode = true;
                }
                //Complex[] evec = new Complex[nodeCntB1];
                //Complex[] evec_dFdX = new Complex[nodeCntB1];
                Complex[] evec = new Complex[nodesBoundary.Length]; // 強制境界を除く
                Complex[] evec_dFdX = new Complex[nodesBoundary.Length]; // 強制境界を除く
                for (int ino = 0; ino < nodeCntB1; ino++)
                {
                    int nodeNumberPortBc1 = nodePeriodicB1[ino];
                    //System.Diagnostics.Debug.WriteLine("ino = {0} nodeNumberPortBc1 = {1}", ino, nodeNumberPortBc1);
                    int ino_InLoop_PortBc1 = toNodePeriodic[nodeNumberPortBc1];
                    Complex cvalue = new Complex(resVec[ino_InLoop_PortBc1].Real, resVec[ino_InLoop_PortBc1].Imaginary);
                    Complex dFdXValue = new Complex(resDFDXVec[ino_InLoop_PortBc1].Real, resDFDXVec[ino_InLoop_PortBc1].Imaginary);
                    if (isComplexConjugateMode)
                    {
                        cvalue = Complex.Conjugate(cvalue);
                        dFdXValue = Complex.Conjugate(dFdXValue);
                    }

                    //evec[ino] = cvalue;
                    //evec_dFdX[ino] = dFdXValue;
                    ///////////////////////////////////////////////////
                    // 強制境界を除く
                    if (!toNodesB.ContainsKey(nodeNumberPortBc1))
                    {
                        continue;
                    }
                    int ino_f = toNodesB[nodeNumberPortBc1];
                    //System.Diagnostics.Debug.WriteLine("ino_f = {0}", ino_f);

                    evec[ino_f] = cvalue;
                    evec_dFdX[ino_f] = dFdXValue;
                    ///////////////////////////////////////////////////

                    //if (tagtModeIndex == incidentModeIndex)
                    {
                        //System.Diagnostics.Debug.WriteLine("evec[{0}] = {1} + {2} i", ino_f, evec[ino_f].Real, evec[ino_f].Imaginary);
                    }
                }
                // 規格化定数を求める
                Complex[] workVec = MyMatrixUtil.product(ryy_1d, evec);
                //Complex[] evec_Modify = new Complex[nodeCntB1];
                Complex[] evec_Modify = new Complex[nodesBoundary.Length];//強制境界を除く
                Complex imagOne = new Complex(0.0, 1.0);
                Complex betam_periodic = ToBetaPeriodic(betam, periodicDistance);
                for (int ino = 0; ino < nodeCntB1; ino++)
                {
                    //evec_Modify[ino] = evec[ino] - evec_dFdX[ino] / (imagOne * betam_periodic);
                    ///////////////////////////////////////////////////
                    // 強制境界を除く
                    int nodeNumberPortBc1 = nodePeriodicB1[ino];
                    if (!toNodesB.ContainsKey(nodeNumberPortBc1))
                    {
                        continue;
                    }
                    int ino_f = toNodesB[nodeNumberPortBc1];
                    evec_Modify[ino_f] = evec[ino_f] - evec_dFdX[ino_f] / (imagOne * betam_periodic);
                    ///////////////////////////////////////////////////
                }
                //Complex dm = MyMatrixUtil.vector_Dot(MyMatrixUtil.vector_Conjugate(evec), workVec);
                Complex dm = MyMatrixUtil.vector_Dot(MyMatrixUtil.vector_Conjugate(evec_Modify), workVec);
                if (WaveModeDv == FemSolver.WaveModeDV.TM)
                {
                    // TMモード
                    dm = Complex.Sqrt(omega * eps0 * Complex.Conjugate(betam) / (Complex.Abs(betam) * Complex.Conjugate(betam_periodic)) / dm);
                }
                else
                {
                    // TEモード
                    dm = Complex.Sqrt(omega * mu0 * Complex.Conjugate(betam) / (Complex.Abs(betam) * Complex.Conjugate(betam_periodic)) / dm);
                }

                // 伝搬定数の格納
                eigenValues[tagtModeIndex] = betam;
                if (tagtModeIndex < 10)
                {
                    System.Diagnostics.Debug.WriteLine("β/k0  ( " + tagtModeIndex + " ) = " + betam.Real / k0 + " + " + betam.Imaginary / k0 + " i " + ((incidentModeIndex == tagtModeIndex) ? " incident" : ""));
                }
                // 固有ベクトルの格納(規格化定数を掛ける)
                for (int ino = 0; ino < evec.Length; ino++)
                {
                    Complex fm = dm * evec[ino];
                    Complex dfmdx = dm * evec_dFdX[ino];
                    eigenVecsB1[tagtModeIndex, ino] = fm;
                    eigen_dFdXsB1[tagtModeIndex, ino] = dfmdx;
                    //System.Diagnostics.Debug.WriteLine("eigen_vecs_Bc1({0}, {1}) = {2} + {3} i", imode, ino, fm.Real, fm.Imag);
                }
            }
            System.Diagnostics.Debug.WriteLine("eigen end");
        }
Beispiel #10
0
 // [X] = alpha * [A]
 public static Complex[,] product(Complex alpha, Complex[,] matA)
 {
     Complex[,] matX = new Complex[matA.GetLength(0), matA.GetLength(1)];
     for (int i = 0; i < matA.GetLength(0); i++)
     {
         for (int j = 0; j < matA.GetLength(1); j++)
         {
             matX[i, j] = alpha * matA[i, j];
         }
     }
     return matX;
 }
Beispiel #11
0
        private static Complex int_Det(Complex[,] matrix)
        {
            var frow = new List<Complex>();
            var size = matrix.GetLength(0);
            if (size == 2) return matrix[0, 0] * matrix[1, 1] - matrix[1, 0] * matrix[0, 1];
            var mat = new Complex[size - 1, size];
            for (int row = 0; row < size; row++)
            {
                frow.Add(matrix[0, row]);
                for (int col = 0; col < size - 1; col++)
                {
                    mat[col, row] = matrix[col + 1, row];
                }
            }
            Complex result = 0;
            for (int i = 0; i < size; i++)
            {
                var fac = frow[i];
                var mtt = new List<Complex>();
                for (int row = 0; row < size; row++)
                {
                    if (row != i)
                    {
                        for (int col = 0; col < size - 1; col++)
                        {
                            mtt.Add(mat[col, row]);
                        }
                    }
                }
                var det = fac * Determinant(mtt.ToArray());
                if (i % 2 != 0) result -= det;
                else result += det;
            }


            return result;
        }
Beispiel #12
0
        /// <summary>
        /// 入射振幅を取得する
        /// </summary>
        /// <param name="world"></param>
        /// <param name="fieldPortBcId"></param>
        /// <param name="eigen_values"></param>
        /// <param name="eigen_vecs"></param>
        /// <returns></returns>
        public static Complex[] GetIncidentAmplitude(
            CFieldWorld world,
            uint fieldPortBcId,
            IList<IList<uint>> PCWaveguidePorts,
            Complex[] eigen_values,
            Complex[,] eigen_vecs)
        {
            // 2チャンネルのポート?
            if (PCWaveguidePorts.Count != 2)
            {
                return null;
            }

            //境界節点番号→全体節点番号変換テーブル(no_c_all)
            uint[] no_c_all = null;
            // 全体節点番号→境界節点番号変換テーブル(to_no_boundary
            Dictionary<uint, uint> to_no_boundary = null;
            // 境界節点の座標
            double[][] coord_c_all = null;

            // 境界上のすべての節点番号を取り出す
            //bool res = WgUtil.GetBoundaryNodeList(world, fieldPortBcId, out no_c_all, out to_no_boundary);
            bool res = WgUtil.GetBoundaryCoordList(world, fieldPortBcId, out no_c_all, out to_no_boundary, out coord_c_all);
            if (!res)
            {
                return null;
            }
            uint max_mode = (uint)eigen_values.Length;
            uint node_cnt = (uint)eigen_vecs.GetLength(1);
            System.Diagnostics.Debug.Assert(max_mode >= 2);
            System.Diagnostics.Debug.Assert(node_cnt == no_c_all.Length);
            // check
            //for (int ino = 0; ino < node_cnt; ino++)
            //{
            //    double[] coord = coord_c_all[ino];
            //    System.Diagnostics.Debug.WriteLine("coord[1]: {0}", coord[1]);
            //}
            double[] coord_c_first = coord_c_all[0];
            double[] coord_c_last = coord_c_all[node_cnt - 1];

            // 振幅を合わせる基準点節点
            int no_base = -1;
            // 入射モードの電力
            //double inputPower = 1.0 / max_mode;

            ////////////////////////////////
            /*
            // チャンネル2のみ入力
            // ポート1のチャンネル1(上側)の節点を基準点にする モード減算
            bool isMinus = true; // 減算
            int channelIndex = 0; // チャンネル1
            // ポート1のチャンネル2(下側)の節点を基準点にする モード加算
            //bool isMinus = false; // 加算
            //int channelIndex = 1; // チャンネル2
             */
            // チャンネル1のみ入力
            // ポート1のチャンネル1(上側)の節点を基準点にする モード減算
            //bool isMinus = false; // 加算
            //int channelIndex = 0; // チャンネル1
            // ポート1のチャンネル2(下側)の節点を基準点にする モード加算
            bool isMinus = true; // 減算
            int channelIndex = 1; // チャンネル2
            IList<uint> channelNodes = PCWaveguidePorts[channelIndex];
            double waveguideWidth = Math.Abs(coord_c_last[1] - coord_c_first[1]);
            int rodCntHalf = g_rodCntHalf;
            int rodCntMiddle = g_rodCntMiddle;
            int defectRodCnt = g_defectRodCnt;
            int rodCntY = rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle;
            double rodDistanceY = waveguideWidth / rodCntY;
            double yy_min = 0.0;
            double yy_max = 0.0;
            //double margin = 0.05;
            double margin = 0.10;
            double yy_0 = 0;
            if (channelIndex == 0)
            {
               yy_0 = (rodCntHalf + defectRodCnt + rodCntMiddle) * rodDistanceY + 0.5 * rodDistanceY;
            }
            else
            {
                yy_0 = rodCntHalf * rodDistanceY + 0.5 * rodDistanceY;
            }
            yy_min = yy_0 - margin * rodDistanceY;
            yy_max = yy_0 + margin * rodDistanceY;

            foreach (uint no in channelNodes)
            {
                // 境界上の節点以外は処理しない(チャンネル節点は内部領域の節点も格納されている)
                if (!to_no_boundary.ContainsKey(no)) continue;

                // noは全体節点番号
                // 境界節点番号へ変換
                uint ino = to_no_boundary[no];
                double[] coord = coord_c_all[ino];
                double yy = coord[1] - coord_c_last[1];
                // チャンネル2の中央の節点を取得
                if (yy >= yy_min && yy <= yy_max)
                {
                    // 境界節点番号を格納
                    no_base = (int)ino;
                    break;
                }
            }
            System.Diagnostics.Debug.Assert(no_base >= 0 && no_base < node_cnt);

            // 固有モードベクトルの取得
            Complex[][] fmVecList = new Complex[max_mode][];
            Complex[] fieldValsAtBaseNode = new Complex[max_mode];
            for (uint imode = 0; imode < max_mode; imode++)
            {
                // 固有モードベクトル
                Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigen_vecs, (int)imode);
                fmVecList[imode] = fmVec;
                // 基準節点の界の値を取得
                fieldValsAtBaseNode[imode] = fmVec[no_base];
            }

            // 全入射電力
            double totalPower = 0.0;
            // 振幅のリスト
            Complex[] amps = new Complex[max_mode];
            for (uint imode = 0; imode < max_mode; imode++)
            {
                if (imode >= 2)
                {
                    // 2モード以上は入射させない(2チャンネル結合導波路)
                    amps[imode] = 0.0;
                    continue;
                }
                Complex fValue = fieldValsAtBaseNode[imode];
                // 特定の節点の位相を基準に入射振幅を決める
                //Complex phase = fValue / Complex.Norm(fValue);
                ////amList[imode] = 1.0 / phase;
                //amps[imode] = Math.Sqrt(inputPower) / phase;
                // 基準点の振幅、位相を一致させる
                Complex ratio = fieldValsAtBaseNode[imode] / fieldValsAtBaseNode[0];
                if (isMinus)
                {
                    if (imode == 0)
                    {
                        amps[imode] = 1.0 / ratio;
                    }
                    else
                    {
                        amps[imode] = -1.0 / ratio;
                    }
                }
                else
                {
                    amps[imode] = 1.0 / ratio;
                }
                totalPower += Complex.Norm(amps[imode]) * Complex.Norm(amps[imode]);
            }
            // 全電力で規格化
            double totalRootPower = Math.Sqrt(totalPower);
            for (uint imode = 0; imode < max_mode; imode++)
            {
                amps[imode] /= totalRootPower;
                System.Diagnostics.Debug.WriteLine("amps[{0}]: {1} + {2}i (square Norm: {3})", imode, amps[imode].Real, amps[imode].Imag, Complex.Norm(amps[imode]) * Complex.Norm(amps[imode]));
            }

            // check : チャンネル2だけの分布になっているか
            {
                Complex[] totalfVec = new Complex[node_cnt];
                for (int ino = 0; ino < node_cnt; ino++)
                {
                    totalfVec[ino] = 0.0;
                }
                for (uint imode = 0; imode < max_mode; imode++)
                {
                    Complex[] fmVec = fmVecList[imode];
                    for (int ino = 0; ino < node_cnt; ino++)
                    {
                        totalfVec[ino] += amps[imode] * fmVec[ino];
                    }
                }
                System.Diagnostics.Debug.WriteLine("-----------------");
                System.Diagnostics.Debug.WriteLine("y,ReHz,ImHz");
                for (int ino = 0; ino < node_cnt; ino++)
                {
                    double[] coord = coord_c_all[ino];
                    System.Diagnostics.Debug.WriteLine("{0},{1},{2}", coord[1], totalfVec[ino].Real, totalfVec[ino].Imag);
                }
            }
            return amps;
        }
Beispiel #13
0
        /// <summary>
        /// 問題を解く
        /// </summary>
        /// <param name="probNo">問題番号</param>
        /// <param name="freqIndex">計算する周波数のインデックス</param>
        /// <param name="NormalizedFreq1">開始規格化周波数</param>
        /// <param name="NormalizedFreq2">終了規格化周波数</param>
        /// <param name="FreqDelta">計算刻み幅</param>
        /// <param name="initFlg">カメラ初期化フラグ</param>
        /// <param name="WaveguideWidth">波長</param>
        /// <param name="WaveModeDv">波のモード区分</param>
        /// <param name="World">ワールド座標系</param>
        /// <param name="FieldValId">値のフィールドID</param>
        /// <param name="FieldLoopId">ループの値のフィールドID</param>
        /// <param name="FieldForceBcId">強制境界の値のフィールドID</param>
        /// <param name="WgPortInfoList">入出力導波路情報リスト</param>
        /// <param name="Medias">媒質リスト</param>
        /// <param name="LoopDic">ループID→ループ情報マップ</param>
        /// <param name="EdgeDic">エッジID→エッジ情報マップ</param>
        /// <param name="IsInoutWgSame">同じ入出力導波路?</param>
        /// <param name="IsShowAbsField">絶対値表示する?</param>
        /// <param name="Ls">リニアシステム</param>
        /// <param name="Prec">プリコンディショナ―</param>
        /// <param name="ScatterVecList">散乱係数リスト(ポート毎のモード散乱係数リストのリスト)</param>
        /// <param name="DrawerAry">描画オブジェクトアレイ</param>
        /// <param name="Camera">カメラ</param>
        /// <returns></returns>
        private static bool solveProblem(
            int probNo,
            ref int freqIndex,
            double NormalizedFreq1,
            double NormalizedFreq2,
            double FreqDelta,
            bool initFlg,
            double WaveguideWidth,
            WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            bool IsInoutWgSame,
            bool IsShowAbsField,
            ref CZLinearSystem Ls, ref CZPreconditioner_ILU Prec,
            ref IList<IList<Complex[]>> ScatterVecList,
            ref CDrawerArrayField DrawerAry,
            CCamera Camera)
        {
            //long memorySize1 = GC.GetTotalMemory(false);
            //Console.WriteLine("    total memory: {0}", memorySize1);

            bool success = false;
            // ポート数
            int portCnt = WgPortInfoList.Count;
            // モード電力の合計を出力として表示する
            //bool isShowTotalPortPower = true;
            bool isShowTotalPortPower = false;
            // PC導波路?
            bool isPCWaveguide = false;
            foreach (WgUtilForPeriodicEigenExt.WgPortInfo workWgPortInfo in WgPortInfoList)
            {
                if (workWgPortInfo.IsPCWaveguide)
                {
                    isPCWaveguide = true;
                    break;
                }
            }
            //// モード追跡する?
            //bool isModeTrace = true;
            //if (!isPCWaveguide)
            //{
            //    isModeTrace = false;
            //}

            // モード追跡用の固有ベクトル格納先の初期化
            if (freqIndex == 0)
            {
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    WgPortInfoList[portIndex].PrevModalVecList = null;
                }
            }
            try
            {

                // 規格化周波数
                double normalizedFreq = getNormalizedFreq(
                    ref freqIndex,
                    NormalizedFreq1,
                    NormalizedFreq2,
                    FreqDelta);
                if (freqIndex == -1)
                {
                    return success;
                }
                // 格子定数
                double latticeA = 0.0;
                double periodicDistance = 0.0;
                if (portCnt > 0)
                {
                    latticeA = WgPortInfoList[0].LatticeA;
                    periodicDistance = WgPortInfoList[0].PeriodicDistance;
                }
                // 波数
                double k0 = 0;
                if (isPCWaveguide)
                {
                    k0 = normalizedFreq * 2.0 * pi / latticeA;
                    System.Diagnostics.Debug.WriteLine("a/λ:{0}", normalizedFreq);
                }
                else
                {
                    k0 = normalizedFreq * pi / WaveguideWidth;
                    System.Diagnostics.Debug.WriteLine("2W/λ:{0}", normalizedFreq);
                }
                // 波長
                double waveLength = 2.0 * pi / k0;

                //------------------------------------------------------------------
                // リニアシステム
                //------------------------------------------------------------------
                Ls.Clear();
                Prec.Clear();
                WgUtil.GC_Collect();

                //------------------------------------------------------------------
                // 界パターン追加
                //------------------------------------------------------------------
                // ワールド座標系のフィールド値をクリア
                WgUtil.ClearFieldValues(World, FieldValId);
                // 領域全体の界パターンを追加
                Ls.AddPattern_Field(FieldValId, World);

                // 上記界パターンでは、隣接する要素以外の剛性行列の値は追加できないようです。境界用に追加パターンを作成
                foreach (WgUtilForPeriodicEigenExt.WgPortInfo workWgPortInfo in WgPortInfoList)
                {
                    WgUtil.MakeWaveguidePortBCPattern(Ls, World, workWgPortInfo.FieldPortBcId);
                }

                //------------------------------------------------------------------
                // 固定境界条件を設定
                //------------------------------------------------------------------
                if (FieldForceBcId != 0)
                {
                    Ls.SetFixedBoundaryCondition_Field(FieldForceBcId, 0, World); // 固定境界条件を設定
                }
                uint[] fixedBcNodes = null;
                // 強制境界条件を課す節点を取得する
                // 境界の固有モード解析で強制境界を指定する際に使用する(CZLinearSystemのBCFlagを参照できないので)
                Dictionary<uint, uint> tmp_to_no_boundary = null;
                if (FieldForceBcId != 0)
                {
                    WgUtil.GetBoundaryNodeList(World, FieldForceBcId, out fixedBcNodes, out tmp_to_no_boundary);
                }

                //------------------------------------------------------------------
                // 剛性行列、残差ベクトルのマージ
                //------------------------------------------------------------------
                Ls.InitializeMarge();

                IList<double[,]> ryy_1d_port_list = new List<double[,]>();
                IList<Complex[]> eigen_values_port_list = new List<Complex[]>();
                IList<Complex[,]> eigen_vecs_port_list = new List<Complex[,]>();
                IList<Complex[,]> eigen_dFdXs_port_list = new List<Complex[,]>();

                // 境界の界に導波路開口条件を追加
                bool retAddPort = false;

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    WgUtilForPeriodicEigenExt.WgPortInfo workWgPortInfo = WgPortInfoList[portIndex];

                    if (!IsInoutWgSame || (IsInoutWgSame && portIndex == 0))
                    {
                        // 導波路開口1
                        double[,] ryy_1d_port1 = null;
                        Complex[] eigen_values_port1 = null;
                        Complex[,] eigen_vecs_port1 = null;
                        Complex[,] eigen_dFdXs_port1 = null;
                        bool isModeTrace = workWgPortInfo.IsModeTrace;
                        if (!workWgPortInfo.IsPCWaveguide)
                        {
                            isModeTrace = false;
                        }
                        retAddPort = WgUtilForPeriodicEigenExt.GetPortPeriodicWaveguideFemMatAndEigenVec(
                            Ls,
                            waveLength,
                            WaveModeDv,
                            World,
                            workWgPortInfo.FieldInputWgLoopId,
                            workWgPortInfo.FieldPortBcId,
                            workWgPortInfo.FieldInputWgBcId,
                            fixedBcNodes,
                            workWgPortInfo.IsPCWaveguide,
                            workWgPortInfo.LatticeA,
                            workWgPortInfo.PeriodicDistance,
                            workWgPortInfo.PCWaveguidePorts,
                            workWgPortInfo.IncidentModeIndex,
                            workWgPortInfo.IsSolveEigenItr,
                            workWgPortInfo.PropModeCntToSolve,
                            workWgPortInfo.IsSVEA,
                            isModeTrace,
                            ref workWgPortInfo.PrevModalVecList,
                            workWgPortInfo.MinEffN,
                            workWgPortInfo.MaxEffN,
                            workWgPortInfo.MinWaveNum,
                            workWgPortInfo.MaxWaveNum,
                            Medias,
                            workWgPortInfo.InputWgLoopDic,
                            workWgPortInfo.InputWgEdgeDic,
                            (portIndex == 0) ? true : false, // isPortBc2Reverse : 周期構造導波路の外部境界と内部境界の辺の方向が逆かどうかを指定する。
                                                             //                    図面の作成手順より、ポート1の場合true ポート2の場合false
                            out ryy_1d_port1,
                            out eigen_values_port1,
                            out eigen_vecs_port1,
                            out eigen_dFdXs_port1);
                        /*
                        // DEBUG モード確認
                        {
                            //暫定描画処理
                            DrawerAry.Clear();
                            DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                            DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                            // カメラの変換行列初期化
                            DrawerAry.InitTrans(Camera);
                            return true;
                        }
                         */
                        // 格納する
                        ryy_1d_port_list.Add(ryy_1d_port1);
                        eigen_values_port_list.Add(eigen_values_port1);
                        eigen_vecs_port_list.Add(eigen_vecs_port1);
                        eigen_dFdXs_port_list.Add(eigen_dFdXs_port1);

                        // 入射モードチェック
                        if (retAddPort)
                        {
                            if ((workWgPortInfo.IncidentModeIndex >= eigen_values_port_list[portIndex].Length)
                                || (Math.Abs(eigen_values_port_list[portIndex][workWgPortInfo.IncidentModeIndex].Real) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit) // 入射モードが伝搬モードでない
                                )
                            {
                                retAddPort = false;
                            }
                        }
                    }
                    else if (IsInoutWgSame && portIndex != 0)
                    {
                        double[,] ryy_1d_port2 = null;
                        Complex[] eigen_values_port2 = null;
                        Complex[,] eigen_vecs_port2 = null;
                        Complex[,] eigen_dFdXs_port2 = null;

                        //  出力側は入力側と同じ導波路とする
                        double[,] ryy_1d_port1 = ryy_1d_port_list[0];
                        Complex[] eigen_values_port1 = eigen_values_port_list[0];
                        Complex[,] eigen_vecs_port1 = eigen_vecs_port_list[0];
                        Complex[,] eigen_dFdXs_port1 = eigen_dFdXs_port_list[0];
                        ryy_1d_port2 = new double[ryy_1d_port1.GetLength(0), ryy_1d_port1.GetLength(1)];
                        for (int i = 0; i < ryy_1d_port2.GetLength(0); i++)
                        {
                            // 位置を反転
                            for (int j = 0; j < ryy_1d_port2.GetLength(1); j++)
                            {
                                double value = ryy_1d_port1[ryy_1d_port2.GetLength(0) - 1 - i, ryy_1d_port2.GetLength(1) - 1 - j];
                                ryy_1d_port2[i, j] = value;
                            }
                        }
                        eigen_values_port2 = new Complex[eigen_values_port1.Length];
                        eigen_vecs_port2 = new Complex[eigen_vecs_port1.GetLength(0), eigen_vecs_port1.GetLength(1)];
                        eigen_dFdXs_port2 = new Complex[eigen_dFdXs_port1.GetLength(0), eigen_dFdXs_port1.GetLength(1)];
                        for (int i = 0; i < eigen_vecs_port2.GetLength(0); i++)
                        {
                            Complex betam = eigen_values_port1[i];
                            eigen_values_port2[i] = betam;
                            // 位置を反転
                            for (int j = 0; j < eigen_vecs_port2.GetLength(1); j++)
                            {
                                eigen_vecs_port2[i, j] = eigen_vecs_port1[i, eigen_vecs_port2.GetLength(1) - 1 - j];
                                eigen_dFdXs_port2[i, j] = eigen_dFdXs_port1[i, eigen_dFdXs_port2.GetLength(1) - 1 - j];
                            }
                        }

                        // 格納する
                        ryy_1d_port_list.Add(ryy_1d_port2);
                        eigen_values_port_list.Add(eigen_values_port2);
                        eigen_vecs_port_list.Add(eigen_vecs_port2);
                        eigen_dFdXs_port_list.Add(eigen_dFdXs_port2);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                        retAddPort = false;
                    }
                    if (!retAddPort)
                    {
                        System.Diagnostics.Debug.WriteLine("failed addPort (port{0})", (portIndex + 1));
                        // 表示用にデータを格納する
                        if (freqIndex == 0)
                        {
                            ScatterVecList.Clear();
                        }
                        {
                            IList<Complex[]> work_portScatterVecList = new List<Complex[]>();
                            for (int p = 0; p < portCnt; p++)
                            {
                                WgUtilForPeriodicEigenExt.WgPortInfo tmpWgPortInfo = WgPortInfoList[p];
                                int propModeCnt = tmpWgPortInfo.PropModeCntToSolve;
                                if (isShowTotalPortPower)
                                {
                                    propModeCnt = 1;
                                }
                                Complex[] work_scatterVec = new Complex[propModeCnt];
                                for (int imode = 0; imode < propModeCnt; imode++)
                                {
                                    work_scatterVec[imode] = 0;
                                }
                                work_portScatterVecList.Add(work_scatterVec);
                            }
                            ScatterVecList.Add(work_portScatterVecList);
                        }
                        {
                            DrawerAry.Clear();
                            Ls.UpdateValueOfField(FieldValId, World, FIELD_DERIVATION_TYPE.VALUE);
                            DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                            DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                            // カメラの変換行列初期化
                            DrawerAry.InitTrans(Camera);
                            // 表示位置調整
                            setupPanAndScale(probNo, Camera);
                        }
                        return false;
                    }

                    // 入射振幅を指定する(全モード入射)
                    Complex[] work_amps = null;
                    if (probNo == 13)
                    {
                        if (workWgPortInfo.IsIncidentPort)
                        {
                            /*
                            work_amps = Problem13_2.GetIncidentAmplitude(
                                World,
                                workWgPortInfo.FieldPortBcId,
                                workWgPortInfo.PCWaveguidePorts,
                                eigen_values_port_list[portIndex],
                                eigen_vecs_port_list[portIndex]);
                             */
                            /*
                            work_amps = Problem13_3.GetIncidentAmplitude(
                                World,
                                workWgPortInfo.FieldPortBcId,
                                workWgPortInfo.PCWaveguidePorts,
                                eigen_values_port_list[portIndex],
                                eigen_vecs_port_list[portIndex]);
                             */
                        }
                    }
                    workWgPortInfo.Amps = work_amps;

                    retAddPort = WgUtilForPeriodicEigenExt.AddLinSys_PeriodicWaveguidePortBC(
                        Ls,
                        waveLength,
                        WaveModeDv,
                        workWgPortInfo.PeriodicDistance,
                        World,
                        workWgPortInfo.FieldInputWgLoopId,
                        workWgPortInfo.FieldPortBcId,
                        fixedBcNodes,
                        workWgPortInfo.IsIncidentPort, // isInputPort : true
                        workWgPortInfo.IncidentModeIndex,
                        workWgPortInfo.Amps,
                        false, // isFreeBc: false:モード展開  true:PMLを装荷する場合、Sommerfeld境界条件を適用する場合
                        ryy_1d_port_list[portIndex],
                        eigen_values_port_list[portIndex],
                        eigen_vecs_port_list[portIndex],
                        eigen_dFdXs_port_list[portIndex]);
                    if (!retAddPort)
                    {
                        System.Diagnostics.Debug.WriteLine("failed addPort (port{0})", (portIndex + 1));
                        // 表示用にデータを格納する
                        if (freqIndex == 0)
                        {
                            ScatterVecList.Clear();
                        }
                        {
                            IList<Complex[]> work_portScatterVecList = new List<Complex[]>();
                            for (int p = 0; p < portCnt; p++)
                            {
                                WgUtilForPeriodicEigenExt.WgPortInfo tmpWgPortInfo = WgPortInfoList[p];
                                int propModeCnt = tmpWgPortInfo.PropModeCntToSolve;
                                if (isShowTotalPortPower)
                                {
                                    propModeCnt = 1;
                                }
                                Complex[] work_scatterVec = new Complex[propModeCnt];
                                for (int imode = 0; imode < propModeCnt; imode++)
                                {
                                    work_scatterVec[imode] = 0;
                                }
                                work_portScatterVecList.Add(work_scatterVec);
                            }
                            ScatterVecList.Add(work_portScatterVecList);
                        }
                        return false;
                    }
                    System.Diagnostics.Debug.WriteLine("port{0} node_cnt: {1}", (portIndex + 1), eigen_vecs_port_list[portIndex].GetLength(1));
                }
                /*
                // TEST Sommerfelt
                CEqnHelmholz.AddLinSys_SommerfeltRadiationBC(Ls, waveLength, World, FieldPortBcId1);
                CEqnHelmholz.AddLinSys_SommerfeltRadiationBC(Ls, waveLength, World, FieldPortBcId2);
                 */
                /*
                //  散乱係数計算用に1のモード分布をセット
                ryy_1d_port2 = ryy_1d_port1;
                eigen_values_port2 = eigen_values_port1;
                eigen_vecs_port2 = eigen_vecs_port1;
                eigen_dFdXs_port2 = eigen_dFdXs_port1;
                */

                // 領域
                WgUtil.AddLinSysHelmholtz(Ls, waveLength, World, FieldLoopId
                    , Medias, LoopDic);

                double res = Ls.FinalizeMarge();
                //System.Diagnostics.Debug.WriteLine("Residual : " + res);

                //------------------------------------------------------------------
                // プリコンディショナ―
                //------------------------------------------------------------------
                // set Preconditioner
                //Prec.SetFillInLevel(1);
                //Prec.SetFillInLevel(int.MaxValue);  // 対称でなくても解けてしまう
                // ILU(0)のパターン初期化
                //Prec.SetLinearSystem(Ls);

                //------------------------------------------------------------------
                // リニアシステムを解く
                //------------------------------------------------------------------
                // メモリを解放する
                WgUtil.GC_Collect();
                /*
                // プリコンディショナに値を設定してILU分解を行う
                Prec.SetValue(Ls);
                double tol = 1.0e-6;
                uint maxIter = 2000;
                uint iter = maxIter;
                CZSolverLsIter.Solve_PCOCG(ref tol, ref iter, Ls, Prec);
                if (iter == maxIter)
                {
                    Console.WriteLine("Not converged at 2W/λ = {0}", normalizedFreq);
                    System.Diagnostics.Debug.WriteLine("Not converged at 2W/λ = {0}", normalizedFreq);
                }
                //System.Diagnostics.Debug.WriteLine("Solved!");

                // 計算結果をワールド座標系に反映する
                Ls.UpdateValueOfField(FieldValId, World, FIELD_DERIVATION_TYPE.VALUE);
                 */

                //// 非対称複素行列の連立方程式をclapackで解く
                //solveAsymmetricCompplexMatEqn(Ls, World, FieldValId);

                // 非対称複素帯行列の連立方程式をclapackで解く
                solveAsymmetricComplexBandMatEqn(Ls, World, FieldValId);

                //------------------------------------------------------------------
                // 計算結果の後処理
                //------------------------------------------------------------------
                // 反射、透過係数
                double totalPower = 0.0;
                int incidentPortNo = getIncidentPortNo(WgPortInfoList);
                IList<Complex[]> portScatterVecList = new List<Complex[]>();
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    Complex[] eigen_values_port1 = eigen_values_port_list[portIndex];
                    double[,] ryy_1d_port1 = ryy_1d_port_list[portIndex];
                    Complex[,] eigen_vecs_port1 = eigen_vecs_port_list[portIndex];
                    Complex[,] eigen_dFdXs_port1 = eigen_dFdXs_port_list[portIndex];
                    WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                    int propModeCntToShow = wgPortInfo1.PropModeCntToSolve;
                    if (isShowTotalPortPower)
                    {
                        propModeCntToShow = 1;
                    }
                    Complex[] scatterVec = new Complex[propModeCntToShow];
                    for (int m = 0; m < propModeCntToShow; m++)
                    {
                        scatterVec[m] = 0.0;
                    }

                    for (uint imode = 0; imode < eigen_values_port1.Length; imode++)
                    {
                        if (Math.Abs(eigen_values_port1[imode].Real) >= 1.0e-12 && Math.Abs(eigen_values_port1[imode].Imag) < 1.0e-12)
                        {
                            Complex s11 = 0.0;
                            bool isIncidentMode = (wgPortInfo1.IsIncidentPort && imode == wgPortInfo1.IncidentModeIndex);
                            if (wgPortInfo1.Amps != null)
                            {
                                // 全モード入射の時
                                isIncidentMode = wgPortInfo1.IsIncidentPort;
                            }
                            s11 = WgUtilForPeriodicEigenExt.GetPeriodicWaveguidePortReflectionCoef(
                                Ls,
                                waveLength,
                                WaveModeDv,
                                wgPortInfo1.PeriodicDistance,
                                World,
                                wgPortInfo1.FieldPortBcId,
                                imode,
                                isIncidentMode,
                                wgPortInfo1.Amps,
                                ryy_1d_port1,
                                eigen_values_port1,
                                eigen_vecs_port1,
                                eigen_dFdXs_port1);
                            System.Diagnostics.Debug.WriteLine("    s" + (portIndex + 1) + incidentPortNo + " = (" + s11.Real + "," + s11.Imag + ")" + " |s" + (portIndex + 1) + incidentPortNo + "|^2 = " + Complex.SquaredNorm(s11) + ((imode == wgPortInfo1.IncidentModeIndex) ? "  incident" : ""));
                            if (Math.Abs(eigen_values_port1[imode].Real) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit
                                && Math.Abs(eigen_values_port1[imode].Imag) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit) // 伝搬モード
                            {
                                totalPower += Complex.SquaredNorm(s11);
                            }
                            if (isShowTotalPortPower)
                            {
                                // ポート電力を計算
                                scatterVec[0] += Complex.Norm(s11) * Complex.Norm(s11);
                            }
                            else
                            {
                                if (imode < propModeCntToShow)
                                {
                                    scatterVec[imode] = s11;
                                }
                            }
                        }
                    }
                    portScatterVecList.Add(scatterVec);
                }
                System.Diagnostics.Debug.WriteLine("    totalPower = {0}", totalPower);
                if (isShowTotalPortPower)
                {
                    for (int p = 0; p < portCnt; p++)
                    {
                        // ルート電力に変換
                        Complex[] scatterVec = portScatterVecList[p];
                        double sqrtPower = Math.Sqrt(Complex.Norm(scatterVec[0]));
                        scatterVec[0] = sqrtPower;
                        //portScatterVecList[p] = scatterVec;
                        System.Diagnostics.Debug.WriteLine("port total sqrt power s{0}{1} : {2}", (p + 1), incidentPortNo, sqrtPower);
                    }
                }

                // 表示用にデータを格納する
                if (freqIndex == 0)
                {
                    ScatterVecList.Clear();
                }
                {
                    ScatterVecList.Add(portScatterVecList);
                }

                // 描画する界の値を加工して置き換える
                //    そのまま描画オブジェクトにフィールドを渡すと、複素数で格納されているフィールド値の実数部が表示されます。
                //    絶対値を表示したかったので、下記処理を追加しています。
                if (IsShowAbsField)
                {
                    WgUtil.ReplaceFieldValueForDisplay(World, FieldValId); // 絶対値表示
                }
                // DEBUG
                //WgUtil.ReplaceFieldValueForDisplay(World, FieldValId); // 絶対値表示
                //WgUtil.ReplaceFieldValueForDisplay(World, FieldValId, 1); // 虚数部表示

                //------------------------------------------------------------------
                // 描画する界の追加
                //------------------------------------------------------------------
                DrawerAry.Clear();
                DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                if (initFlg)
                {
                    // カメラの変換行列初期化
                    DrawerAry.InitTrans(Camera);

                    // 表示位置調整
                    setupPanAndScale(probNo, Camera);
                }
                success = true;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                // 表示用にデータを格納する
                if (freqIndex == 0)
                {
                    ScatterVecList.Clear();
                }
                {
                    IList<Complex[]> work_portScatterVecList = new List<Complex[]>();
                    for (int p = 0; p < portCnt; p++)
                    {
                        WgUtilForPeriodicEigenExt.WgPortInfo tmpWgPortInfo = WgPortInfoList[p];
                        int propModeCnt = tmpWgPortInfo.PropModeCntToSolve;
                        if (isShowTotalPortPower)
                        {
                            propModeCnt = 1;
                        }
                        Complex[] work_scatterVec = new Complex[propModeCnt];
                        for (int imode = 0; imode < propModeCnt; imode++)
                        {
                            work_scatterVec[imode] = 0;
                        }
                        work_portScatterVecList.Add(work_scatterVec);
                    }
                    ScatterVecList.Add(work_portScatterVecList);
                }
                {
                    DrawerAry.Clear();
                    Ls.UpdateValueOfField(FieldValId, World, FIELD_DERIVATION_TYPE.VALUE);
                    DrawerAry.PushBack(new CDrawerFace(FieldValId, true, World, FieldValId));
                    DrawerAry.PushBack(new CDrawerEdge(FieldValId, true, World));
                    // カメラの変換行列初期化
                    DrawerAry.InitTrans(Camera);
                    // 表示位置調整
                    setupPanAndScale(probNo, Camera);
                }
            }
            return success;
        }
Beispiel #14
0
 /// <summary>
 /// </summary>
 /// <param name="table"> </param>
 public void Initialize(Complex[,] table)
 {
     for (var i = 0; i < 2; ++i) if (_matrix.GetLength(i) != table.GetLength(i)) throw new ArgumentException("Dimensions doesnot matches (+,-).");
     //M = table; // Logical Error (reference type)
     var rows = Rows;
     var cols = Cols;
     for (var i = 0; i < rows; ++i) for (var j = 0; j < cols; ++j) _matrix[i, j] = table[i, j];
 }
Beispiel #15
0
        // {x} = [A]{v}
        public static Complex[] product(Complex[,] matA, Complex[] vec)
        {
            System.Diagnostics.Debug.Assert(matA.GetLength(1) == vec.Length);
            //BUGFIX
            //Complex[] retVec = new Complex[vec.Length];
            Complex[] retVec = new Complex[matA.GetLength(0)];

            for (int i = 0; i < matA.GetLength(0); i++)
            {
                retVec[i] = new Complex(0.0, 0.0);
                for (int k = 0; k < matA.GetLength(1); k++)
                {
                    retVec[i] += matA[i, k] * vec[k];
                }
            }
            return retVec;
        }
Beispiel #16
0
 public static Complex[,] matrix_FromBuffer(KrdLab.clapack.Complex[] mat_, int nRow, int nCol)
 {
     Complex[,] mat = new Complex[nRow, nCol];
     // rowから先に埋めていく
     for (int j = 0; j < mat.GetLength(1); j++) // col
     {
         for (int i = 0; i < mat.GetLength(0); i++)  // row
         {
             KrdLab.clapack.Complex cval = mat_[j * mat.GetLength(0) + i];
             mat[i, j] = new Complex(cval.Real, cval.Imaginary);
         }
     }
     return mat;
 }
Beispiel #17
0
        public static Complex[,] matrix_Inverse(Complex[,] matA)
        {
            System.Diagnostics.Debug.Assert(matA.GetLength(0) == matA.GetLength(1));
            int n = matA.GetLength(0);
            KrdLab.clapack.Complex[] matA_ = matrix_ToBuffer(matA);
            KrdLab.clapack.Complex[] matB_ = new KrdLab.clapack.Complex[n * n];
            // 単位行列
            for (int i = 0; i < matB_.Length; i++)
            {
                matB_[i] = (KrdLab.clapack.Complex)0.0;
            }
            for (int i = 0; i < n; i++)
            {
                matB_[i * n + i] = (KrdLab.clapack.Complex)1.0;
            }
            // [A][X] = [B]
            //  [B]の内容が書き換えられるので、matXを新たに生成せず、matBを出力に指定している
            int x_row = 0;
            int x_col = 0;
            KrdLab.clapack.FunctionExt.zgesv(ref matB_, ref x_row, ref x_col, matA_, n, n, matB_, n, n);

            Complex[,] matX = matrix_FromBuffer(matB_, x_row, x_col);
            return matX;
        }
        /// <summary>
        /// 2�����z�񂩂�V�����s���쐬����D
        /// </summary>
        /// <param name="arr">�s��̗v�f��i�[����2�����z��</param>
        public MyComplexBandMatrix(Complex[,] arr)
        {
            System.Diagnostics.Debug.Assert(arr.GetLength(0) == arr.GetLength(1));
            if (arr.GetLength(0) != arr.GetLength(1))
            {
                Clear();
                return;
            }
            int rowcolSize = arr.GetLength(0);

            // subdia�T�C�Y�Asuperdia�T�C�Y��擾����
            int subdiaSize = 0;
            int superdiaSize = 0;
            for (int c = 0; c < rowcolSize; c++)
            {
                if (c < rowcolSize - 1)
                {
                    int cnt = 0;
                    for (int r = rowcolSize - 1; r >= c + 1; r--)
                    {
                        // ��O�v�f�����‚������甲����
                        if (Math.Abs(arr[r, c].Real) >= Constants.PrecisionLowerLimit || Math.Abs(arr[r, c].Imaginary) >= Constants.PrecisionLowerLimit)
                        {
                            cnt = r - c;
                            break;
                        }
                    }
                    if (cnt > subdiaSize)
                    {
                        subdiaSize = cnt;
                    }
                }
                if (c > 0)
                {
                    int cnt = 0;
                    for (int r = 0; r <= c - 1; r++)
                    {
                        // ��O�v�f�����‚������甲����
                        if (Math.Abs(arr[r, c].Real) >= Constants.PrecisionLowerLimit || Math.Abs(arr[r, c].Imaginary) >= Constants.PrecisionLowerLimit)
                        {
                            cnt = c - r;
                            break;
                        }
                    }
                    if (cnt > superdiaSize)
                    {
                        superdiaSize = cnt;
                    }
                }
            }

            // �o�b�t�@�̊m��
            Resize(rowcolSize, subdiaSize, superdiaSize);
            // �l��R�s�[����
            for (int c = 0; c < rowcolSize; ++c)
            {
                // �Ίp����
                this[c, c] = arr[c, c];

                // subdiagonal����
                if (c < rowcolSize - 1)
                {
                    for (int r = c + 1; r < c + subdiaSize && c < rowcolSize; r++)
                    {
                        this[r, c] = arr[r, c];
                    }
                }
                if (c > 0)
                {
                    for (int r = c - 1; r >= c - superdiaSize && r >= 0; r--)
                    {
                        this[r, c] = arr[r, c];
                    }
                }
            }
        }
Beispiel #19
0
 public static KrdLab.clapack.Complex[] matrix_ToBuffer(Complex[,] mat)
 {
     KrdLab.clapack.Complex[] mat_ = new KrdLab.clapack.Complex[mat.GetLength(0) * mat.GetLength(1)];
     // rowから先に埋めていく
     for (int j = 0; j < mat.GetLength(1); j++) //col
     {
         for (int i = 0; i < mat.GetLength(0); i++) // row
         {
             //mat_[j * mat.GetLength(0) + i] = new KrdLab.clapack.Complex(mat[i, j].Real, mat[i,j].Imag);
             mat_[j * mat.GetLength(0) + i].Real = mat[i, j].Real;
             mat_[j * mat.GetLength(0) + i].Imaginary = mat[i,j].Imag;
         }
     }
     return mat_;
 }
Beispiel #20
0
 public static Complex[] matrix_GetRowVec(Complex[,] matA, int row)
 {
     Complex[] rowVec = new Complex[matA.GetLength(1)];
     for (int j = 0; j < matA.GetLength(1); j++)
     {
         rowVec[j] = matA[row, j];
     }
     return rowVec;
 }
Beispiel #21
0
 // [X] = [A]t
 public static Complex[,] matrix_Transpose(Complex[,] matA)
 {
     Complex[,] matX = new Complex[matA.GetLength(1), matA.GetLength(0)];
     for (int i = 0; i < matX.GetLength(0); i++)
     {
         for (int j = 0; j < matX.GetLength(1); j++)
         {
             matX[i, j] = matA[j, i];
         }
     }
     return matX;
 }
Beispiel #22
0
 public static void printMatrixNoZero(string tag, Complex[,] mat)
 {
     for (int i = 0; i < mat.GetLength(0); i++)
     {
         for (int j = 0; j < mat.GetLength(1); j++)
         {
             Complex val = mat[i, j];
             if (Complex.Abs(val) < Constants.PrecisionLowerLimit) continue;
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = "
                                + "(" + val.Real + "," + val.Imaginary + ") ");
         }
     }
 }
        /// <summary>
        /// 矩形導波管開口反射(透過)係数
        ///    ※要素アレイは1つに限定しています。
        ///     ポート境界を指定するときに複数の辺をリストで境界条件設定することでこの条件をクリアできます。
        /// </summary>
        /// <param name="ls">リニアシステム</param>
        /// <param name="waveLength">波長</param>
        /// <param name="fieldValId">フィールド値のID</param>
        /// <param name="imode">固有モードのモード次数</param>
        /// <param name="isIncidentMode">入射モード?</param>
        /// <param name="ryy_1d">[ryy]FEM行列</param>
        /// <param name="eigen_values">固有値配列</param>
        /// <param name="eigen_vecs">固有ベクトル行列{f}(i,j: i:固有値インデックス j:節点)</param>
        /// <param name="eigen_dFdXs">固有ベクトル行列{df/dx}(i,j: i:固有値インデックス j:節点)</param>
        /// <returns>散乱係数</returns>
        public static Complex GetPeriodicWaveguidePortReflectionCoef(
            CZLinearSystem ls,
            double waveLength,
            WaveModeDV waveModeDv,
            double periodicDistance,
            CFieldWorld world,
            uint fieldValId,
            uint imode,
            bool isIncidentMode,
            Complex[] amps,
            double[,] ryy_1d,
            Complex[] eigen_values,
            Complex[,] eigen_vecs,
            Complex[,] eigen_dFdXs)
        {
            Complex s11 = new Complex(0.0, 0.0);
            if (ryy_1d == null || eigen_values == null || eigen_vecs == null)
            {
                return s11;
            }
            if (!world.IsIdField(fieldValId))
            {
                return s11;
            }
            CField valField = world.GetField(fieldValId);
            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return s11;
            }

            bool res;

            //境界節点番号→全体節点番号変換テーブル(no_c_all)
            uint[] no_c_all = null;
            // 全体節点番号→境界節点番号変換テーブル(to_no_boundary
            Dictionary<uint, uint> to_no_boundary = null;

            // 境界上のすべての節点番号を取り出す
            res = GetBoundaryNodeList(world, fieldValId, out no_c_all, out to_no_boundary);
            if (!res)
            {
                return s11;
            }

            // 境界上のすべての節点の界の値を取り出す
            Complex[] value_c_all = null;
            res = WgUtil.GetBoundaryFieldValueList(world, fieldValId, no_c_all, to_no_boundary, out value_c_all);
            if (!res)
            {
                return s11;
            }

            uint node_cnt = (uint)no_c_all.Length;
            System.Diagnostics.Debug.Assert(node_cnt == ryy_1d.GetLength(0));
            System.Diagnostics.Debug.Assert(node_cnt == ryy_1d.GetLength(1));
            System.Diagnostics.Debug.Assert(node_cnt == eigen_vecs.GetLength(1));
            s11 = getPeriodicWaveguidePortReflectionCoef_Core(
                waveLength,
                waveModeDv,
                periodicDistance,
                imode,
                isIncidentMode,
                amps,
                no_c_all,
                to_no_boundary,
                value_c_all,
                ryy_1d,
                eigen_values,
                eigen_vecs,
                eigen_dFdXs);

            return s11;
        }