Ejemplo n.º 1
0
        public static double[,] matrix_Inverse(double[,] matA)
        {
            MyDoubleMatrix matA_ = new MyDoubleMatrix(matA);

            matA_ = matrix_Inverse(matA_);
            return(matA_.ToArray());
        }
Ejemplo n.º 2
0
        public static MyDoubleMatrix matrix_Inverse(MyDoubleMatrix matA)
        {
            System.Diagnostics.Debug.Assert(matA.RowSize == matA.ColumnSize);
            int n = matA.RowSize;

            double[] matA_ = matrix_ToBuffer(matA, true);
            double[] matB_ = new double[n * n];
            // 単位行列
            for (int i = 0; i < matB_.Length; i++)
            {
                matB_[i] = 0.0;
            }
            for (int i = 0; i < n; i++)
            {
                matB_[i * n + i] = 1.0;
            }
            // [A][X] = [B]
            //  [B]の内容が書き換えられるので、matXを新たに生成せず、matBを出力に指定している
            int x_row = 0;
            int x_col = 0;

            KrdLab.clapack.Function.dgesv(ref matB_, ref x_row, ref x_col, matA_, n, n, matB_, n, n);

            MyDoubleMatrix matX = matrix_FromBuffer(matB_, x_row, x_col, false);

            return(matX);
        }
Ejemplo n.º 3
0
 public static void printMatrix(string tag, MyDoubleMatrix mat)
 {
     for (int i = 0; i < mat.RowSize; i++)
     {
         for (int j = 0; j < mat.ColumnSize; j++)
         {
             double val = mat[i, j];
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = " + val);
         }
     }
 }
Ejemplo n.º 4
0
        // [X] = alpha * [A]
        public static MyDoubleMatrix product(double alpha, MyDoubleMatrix matA)
        {
            MyDoubleMatrix matX = new MyDoubleMatrix(matA.RowSize, matA.ColumnSize);

            for (int i = 0; i < matA.RowSize; i++)
            {
                for (int j = 0; j < matA.ColumnSize; j++)
                {
                    matX[i, j] = alpha * matA[i, j];
                }
            }
            return(matX);
        }
Ejemplo n.º 5
0
        /*
         * // x = sqrt(c)
         * public static Complex complex_Sqrt(Complex c)
         * {
         *  System.Numerics.Complex work = new System.Numerics.Complex(c.Real, c.Imaginary);
         *  work = System.Numerics.Complex.Sqrt(work);
         *  return new Complex(work.Real, work.Imaginary);
         * }
         */

        // [X] = [A]t
        public static MyDoubleMatrix matrix_Transpose(MyDoubleMatrix matA)
        {
            MyDoubleMatrix matX = new MyDoubleMatrix(matA.ColumnSize, matA.RowSize);

            for (int i = 0; i < matX.RowSize; i++)
            {
                for (int j = 0; j < matX.ColumnSize; j++)
                {
                    matX[i, j] = matA[j, i];
                }
            }
            return(matX);
        }
Ejemplo n.º 6
0
 public static MyDoubleMatrix matrix_FromBuffer(double[] mat_, int nRow, int nCol, bool copyFlg = true)
 {
     MyDoubleMatrix mat = null;
     if (copyFlg)
     {
         mat = new MyDoubleMatrix(mat_, nRow, nCol);
     }
     else
     {
         mat = new MyDoubleMatrix(nRow, nCol);
         mat._body = mat_;
     }
     return mat;
 }
Ejemplo n.º 7
0
        // [X] = [A] - [B]
        public static MyDoubleMatrix minus(MyDoubleMatrix matA, MyDoubleMatrix matB)
        {
            System.Diagnostics.Debug.Assert(matA.RowSize == matB.RowSize);
            System.Diagnostics.Debug.Assert(matA.ColumnSize == matB.ColumnSize);
            MyDoubleMatrix matX = new MyDoubleMatrix(matA.RowSize, matA.ColumnSize);

            for (int i = 0; i < matA.RowSize; i++)
            {
                for (int j = 0; j < matA.ColumnSize; j++)
                {
                    matX[i, j] = matA[i, j] - matB[i, j];
                }
            }
            return(matX);
        }
Ejemplo n.º 8
0
        public static MyDoubleMatrix matrix_FromBuffer(double[] mat_, int nRow, int nCol, bool copyFlg = true)
        {
            MyDoubleMatrix mat = null;

            if (copyFlg)
            {
                mat = new MyDoubleMatrix(mat_, nRow, nCol);
            }
            else
            {
                mat       = new MyDoubleMatrix(nRow, nCol);
                mat._body = mat_;
            }
            return(mat);
        }
Ejemplo n.º 9
0
        /*
         * public static void printVec(string tag, ValueType[] vec)
         * {
         *  for (int i = 0; i < vec.Length; i++)
         *  {
         *      Complex val = (Complex)vec[i];
         *      System.Diagnostics.Debug.WriteLine(tag + "(" + i + ")" + " = "
         + "(" + val.Real + "," + val.Imaginary + ") " + Complex.Abs(val));
         +  }
         + }
         */
        /*
         * public static void compressVec(ref ValueType[] vec)
         * {
         *  KrdLab.clapack.FunctionExt.CompressMatFor_zgesv(ref vec);
         * }
         */

        public static double[] matrix_ToBuffer(MyDoubleMatrix mat, bool copyFlg = true)
        {
            double[] mat_ = null;
            if (copyFlg)
            {
                int size = mat._rsize * mat._csize;
                mat_ = new double[size];
                mat._body.CopyTo(mat_, 0);
            }
            else
            {
                mat_ = mat._body;
            }
            return(mat_);
        }
Ejemplo n.º 10
0
 public static void printMatrixNoZero(string tag, MyDoubleMatrix mat)
 {
     for (int i = 0; i < mat.RowSize; i++)
     {
         for (int j = 0; j < mat.ColumnSize; j++)
         {
             double val = mat[i, j];
             if (Math.Abs(val) < Constants.PrecisionLowerLimit)
             {
                 continue;
             }
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = " + val + " ");
         }
     }
 }
Ejemplo n.º 11
0
        // {x} = [A]{v}
        public static Complex[] product(MyDoubleMatrix matA, Complex[] vec)
        {
            System.Diagnostics.Debug.Assert(matA.ColumnSize == vec.Length);
            //BUGFIX
            //Complex[] retVec = new Complex[vec.Length];
            Complex[] retVec = new Complex[matA.RowSize];

            for (int i = 0; i < matA.RowSize; i++)
            {
                retVec[i] = new Complex(0.0, 0.0);
                for (int k = 0; k < matA.ColumnSize; k++)
                {
                    retVec[i] += matA[i, k] * vec[k];
                }
            }
            return(retVec);
        }
Ejemplo n.º 12
0
        public static MyComplexMatrix product(MyDoubleMatrix matA, MyComplexMatrix matB)
        {
            System.Diagnostics.Debug.Assert(matA.ColumnSize == matB.RowSize);
            MyComplexMatrix matX = new MyComplexMatrix(matA.RowSize, matB.ColumnSize);

            for (int i = 0; i < matX.RowSize; i++)
            {
                for (int j = 0; j < matX.ColumnSize; j++)
                {
                    matX[i, j] = 0.0;
                    for (int k = 0; k < matA.ColumnSize; k++)
                    {
                        matX[i, j] += matA[i, k] * matB[k, j];
                    }
                }
            }
            return(matX);
        }
        /// <summary>
        /// 転置する.
        /// </summary>
        /// <returns>転置後の自身への参照</returns>
        public virtual MyDoubleMatrix Transpose()
        {
            MyDoubleMatrix t = new MyDoubleMatrix(this._csize, this._rsize);

            for (int r = 0; r < this._rsize; ++r)
            {
                for (int c = 0; c < this._csize; ++c)
                {
                    t[c, r] = this[r, c];
                }
            }

            this.Clear();
            this._body  = t._body;
            this._rsize = t._rsize;
            this._csize = t._csize;

            return(this);
        }
Ejemplo n.º 14
0
        public static MyDoubleMatrix matrix_Inverse(MyDoubleMatrix matA)
        {
            System.Diagnostics.Debug.Assert(matA.RowSize == matA.ColumnSize);
            int n = matA.RowSize;
            double[] matA_ = matrix_ToBuffer(matA, true);
            double[] matB_ = new double[n * n];
            // �P�ʍs��
            for (int i = 0; i < matB_.Length; i++)
            {
                matB_[i] = 0.0;
            }
            for (int i = 0; i < n; i++)
            {
                matB_[i * n + i] = 1.0;
            }
            // [A][X] = [B]
            //  [B]�̓�e��������������̂ŁAmatX��V���ɐ��������AmatB��o�͂Ɏw�肵�Ă���
            int x_row = 0;
            int x_col = 0;
            KrdLab.clapack.Function.dgesv(ref matB_, ref x_row, ref x_col, matA_, n, n, matB_, n, n);

            MyDoubleMatrix matX = matrix_FromBuffer(matB_, x_row, x_col, false);
            return matX;
        }
Ejemplo n.º 15
0
        /// <summary>
        /// 散乱行列の計算
        /// </summary>
        /// <param name="waveLength"></param>
        /// <param name="iMode"></param>
        /// <param name="isIncidentMode"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        /// <param name="eigenValues"></param>
        /// <param name="eigenVecs"></param>
        /// <param name="nodesRegion"></param>
        /// <param name="valuesAll"></param>
        /// <returns></returns>
        public static Complex GetWaveguidePortReflectionCoef(
            FemSolver.WaveModeDV WaveModeDv,
            double waveLength,
            double latticeA,
            int iMode,
            bool isIncidentMode,
            int[] nodesBoundary,
            MyDoubleMatrix ryy_1d,
            Complex[] eigenValues,
            Complex[,] eigenVecs,
            Complex[,] eigen_dFdXs,
            int[] nodesRegion,
            IList<FemElement> Elements,
            MediaInfo[] Medias,
            Complex[] valuesAll)
        {
            // 2D節点番号→ソート済みリストインデックスのマップ
            Dictionary<int, int> toSorted = new Dictionary<int, int>();
            // 2D節点番号→ソート済みリストインデックスのマップ作成
            for (int i = 0; i < nodesRegion.Length; i++)
            {
                int nodeNumber = nodesRegion[i];
                if (!toSorted.ContainsKey(nodeNumber))
                {
                    toSorted.Add(nodeNumber, i);
                }
            }

            // ポート上の界を取得する
            int nodeCnt = nodesBoundary.Length;
            Complex[] valuesB = new Complex[nodeCnt];
            for (int ino = 0; ino < nodeCnt; ino++)
            {
                int nodeNumber = nodesBoundary[ino];
                int inoGlobal = toSorted[nodeNumber];
                valuesB[ino] = valuesAll[inoGlobal];
            }

            double k0 = 2.0 * pi / waveLength;
            double omega = k0 * c0;

            Complex s11 = new Complex(0.0, 0.0);

            int maxMode = eigenValues.Length;

            double periodicDistance = latticeA; // 正方格子

            // {tmp_vec}*t = {fm}*t[ryy]*t
            // {tmp_vec}* = [ryy]* {fm}*
            //   ([ryy]*)t = [ryy]*
            //    [ryy]が実数のときは、[ryy]* -->[ryy]
            Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigenVecs, iMode);
            Complex[] dFdXVec = MyMatrixUtil.matrix_GetRowVec(eigen_dFdXs, (int)iMode);
            Complex[] fmVec_Modify = new Complex[fmVec.Length];
            Complex betam = eigenValues[iMode];
            Complex betam_periodic = ToBetaPeriodic(betam, periodicDistance);
            for (int ino = 0; ino < fmVec_Modify.Length; ino++)
            {
                fmVec_Modify[ino] = fmVec[ino] - dFdXVec[ino] / (Complex.ImaginaryOne * betam_periodic);
            }

            // ryyが実数のとき
            //Complex[] tmp_vec = MyMatrixUtil.product(ryy_1d, MyMatrixUtil.vector_Conjugate(fmVec));
            Complex[] tmp_vec = MyMatrixUtil.product(ryy_1d, MyMatrixUtil.vector_Conjugate(fmVec_Modify));

            // s11 = {tmp_vec}t {value_all}
            s11 = MyMatrixUtil.vector_Dot(tmp_vec, valuesB);
            {
                // H面、平行平板
                if (WaveModeDv == FemSolver.WaveModeDV.TM)
                {
                    //s11 *= (Complex.Abs(betam) / (omega * eps0));
                    s11 *= ((Complex.Abs(betam) * Complex.Conjugate(betam_periodic) / Complex.Conjugate(betam)) / (omega * eps0));
                    if (isIncidentMode)
                    {
                        s11 += -1.0;
                    }
                }
                else
                {
                    //s11 *= (Complex.Abs(betam) / (omega * mu0));
                    s11 *= ((Complex.Abs(betam) * Complex.Conjugate(betam_periodic) / Complex.Conjugate(betam)) / (omega * mu0));
                    if (isIncidentMode)
                    {
                        s11 += -1.0;
                    }
                }
            }

            return s11;
        }
Ejemplo n.º 16
0
        /// <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");
        }
Ejemplo n.º 17
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// ポート境界の1D FEM行列 ryy_1dを取得する
        /// </summary>
        /// <param name="WaveModeDv"></param>
        /// <param name="waveLength"></param>
        /// <param name="latticeA"></param>
        /// <param name="Nodes"></param>
        /// <param name="EdgeToElementNoH"></param>
        /// <param name="Elements"></param>
        /// <param name="Medias"></param>
        /// <param name="ForceNodeNumberH"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        private static void getPortFemMat1D(
            FemSolver.WaveModeDV WaveModeDv,
            double waveLength,
            double latticeA,
            IList<FemNode> Nodes,
            Dictionary<string, IList<int>> EdgeToElementNoH,
            IList<FemElement> Elements,
            MediaInfo[] Medias,
            Dictionary<int, bool> ForceNodeNumberH,
            IList<int> portNodes,
            out int[] nodesBoundary,
            out MyDoubleMatrix ryy_1d
            )
        {
            nodesBoundary = null;
            ryy_1d = null;

            // 2D次元数
            const int ndim2d = Constants.CoordDim2D; //2;
            // 波数
            double k0 = 2.0 * pi / waveLength;
            // 角周波数
            double omega = k0 * c0;

            // 節点番号リスト(要素インデックス: 1D節点番号 - 1 要素:2D節点番号)
            IList<int> nodes = portNodes;
            // 2D→1D節点番号マップ
            Dictionary<int, int> to1dNodes = new Dictionary<int, int>();
            // 節点座標リスト
            IList<double> coords = new List<double>();
            // 要素リスト
            IList<FemLineElement> elements = new List<FemLineElement>();
            // 1D節点番号リスト(ソート済み)
            IList<int> sortedNodes = new List<int>();
            // 1D節点番号→ソート済みリストインデックスのマップ
            Dictionary<int, int> toSorted = new Dictionary<int, int>();

            // 2Dの要素から次数を取得する
            Constants.FemElementShapeDV elemShapeDv2d;
            int order;
            int vertexCnt2d;
            FemMeshLogic.GetElementShapeDvAndOrderByElemNodeCnt(Elements[0].NodeNumbers.Length, out elemShapeDv2d, out order, out vertexCnt2d);

            // 2D→1D節点番号マップ作成
            for (int i = 0; i < nodes.Count; i++)
            {
                int nodeNumber2d = nodes[i];
                if (!to1dNodes.ContainsKey(nodeNumber2d))
                {
                    to1dNodes.Add(nodeNumber2d, i + 1);
                }
            }
            // 原点
            int nodeNumber0 = nodes[0];
            int nodeIndex0 = nodeNumber0 - 1;
            FemNode node0 = Nodes[nodeIndex0];
            double[] coord0 = new double[ndim2d];
            coord0[0] = node0.Coord[0];
            coord0[1] = node0.Coord[1];
            // 座標リスト作成
            double[] coord = new double[ndim2d];
            foreach (int nodeNumber in nodes)
            {
                int nodeIndex = nodeNumber - 1;
                FemNode node = Nodes[nodeIndex];
                coord[0] = node.Coord[0];
                coord[1] = node.Coord[1];
                double x = FemMeshLogic.GetDistance(coord, coord0);
                //System.Diagnostics.Debug.WriteLine("{0},{1},{2},{3}", nodeIndex, coord[0], coord[1], x);
                coords.Add(x);
            }

            // 線要素を作成する
            if (order == Constants.FirstOrder)
            {
                // 1次線要素
                FemMat_Line_First.MkElements(
                    nodes,
                    EdgeToElementNoH,
                    Elements,
                    ref elements);
            }
            else
            {
                // 2次線要素
                FemMat_Line_Second.MkElements(
                    nodes,
                    EdgeToElementNoH,
                    Elements,
                    ref elements);
            }

            // 強制境界節点と内部領域節点を分離
            foreach (int nodeNumber2d in nodes)
            {
                int nodeNumber = to1dNodes[nodeNumber2d];
                if (ForceNodeNumberH.ContainsKey(nodeNumber2d))
                {
                    System.Diagnostics.Debug.WriteLine("{0}:    {1}    {2}", nodeNumber, Nodes[nodeNumber2d - 1].Coord[0], Nodes[nodeNumber2d - 1].Coord[1]);
                }
                else
                {
                    sortedNodes.Add(nodeNumber);
                    toSorted.Add(nodeNumber, sortedNodes.Count - 1);
                }
            }
            // 対称バンド行列のパラメータを取得する
            int rowcolSize = 0;
            int subdiaSize = 0;
            int superdiaSize = 0;
            {
                bool[,] matPattern = null;
                FemSolverPort.GetMatNonzeroPatternForEigen(elements, toSorted, out matPattern);
                FemSolverPort.GetBandMatrixSubDiaSizeAndSuperDiaSizeForEigen(matPattern, out rowcolSize, out subdiaSize, out superdiaSize);
            }
            // ソート済み1D節点インデックス→2D節点番号マップ
            nodesBoundary = new int[sortedNodes.Count];
            for (int i = 0; i < sortedNodes.Count; i++)
            {
                int nodeNumber = sortedNodes[i];
                int nodeIndex = nodeNumber - 1;
                int nodeNumber2d = nodes[nodeIndex];
                nodesBoundary[i] = nodeNumber2d;
            }

            // 節点数
            int nodeCnt = sortedNodes.Count;
            // 固有モード解析でのみ使用するuzz_1d, txx_1d
            MyDoubleMatrix txx_1d = new MyDoubleSymmetricBandMatrix(nodeCnt, subdiaSize, superdiaSize);
            MyDoubleMatrix uzz_1d = new MyDoubleSymmetricBandMatrix(nodeCnt, subdiaSize, superdiaSize);
            // ryy_1dマトリクス (線要素)
            ryy_1d = new MyDoubleSymmetricBandMatrix(nodeCnt, subdiaSize, superdiaSize);

            for (int elemIndex = 0; elemIndex < elements.Count; elemIndex++)
            {
                // 線要素
                FemLineElement element = elements[elemIndex];

                // 1Dヘルムホルツ方程式固有値問題の要素行列を加算する
                if (order == Constants.FirstOrder)
                {
                    // 1次線要素
                    FemMat_Line_First.AddElementMatOf1dEigenValueProblem(
                        waveLength, // E面の場合のみ使用
                        element,
                        coords,
                        toSorted,
                        Medias,
                        WaveModeDv,
                        ref txx_1d, ref ryy_1d, ref uzz_1d);
                }
                else
                {
                    // 2次線要素
                    FemMat_Line_Second.AddElementMatOf1dEigenValueProblem(
                        waveLength, // E面の場合のみ使用
                        element,
                        coords,
                        toSorted,
                        Medias,
                        WaveModeDv,
                        ref txx_1d, ref ryy_1d, ref uzz_1d);
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// 入出力ポート境界条件の追加
        /// </summary>
        /// <param name="waveLength"></param>
        /// <param name="isInputPort"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        /// <param name="eigenValues"></param>
        /// <param name="eigenVecs"></param>
        /// <param name="nodesRegion"></param>
        /// <param name="mat"></param>
        /// <param name="resVec"></param>
        public static void AddPortBC(
            FemSolver.WaveModeDV WaveModeDv,
            double waveLength,
            double latticeA,
            bool isInputPort,
            int IncidentModeIndex,
            int[] nodesBoundary,
            MyDoubleMatrix ryy_1d,
            Complex[] eigenValues,
            Complex[,] eigenVecs,
            Complex[,] eigen_dFdXs,
            int[] nodesRegion,
            IList<FemElement> Elements,
            MediaInfo[] Medias,
            Dictionary<int, bool> ForceNodeNumberH,
            MyComplexMatrix mat,
            Complex[] resVec)
        {
            double k0 = 2.0 * pi / waveLength;
            double omega = k0 / Math.Sqrt(mu0 * eps0);

            // 境界上の節点数(1次線要素を想定)
            int nodeCnt = nodesBoundary.Length;
            // 考慮するモード数
            int maxMode = eigenValues.Length;

            // 全体剛性行列の作成
            MyComplexMatrix matB = new MyComplexMatrix(nodeCnt, nodeCnt);

            double periodicDistance = latticeA; // 正方格子
            for (int imode = 0; imode < maxMode; imode++)
            {
                Complex betam = eigenValues[imode];

                Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigenVecs, (int)imode);
                Complex[] dfmdxVec = MyMatrixUtil.matrix_GetRowVec(eigen_dFdXs, (int)imode);
                Complex[] fmVec_Modify = new Complex[fmVec.Length];
                Complex betam_periodic = ToBetaPeriodic(betam, periodicDistance);
                for (uint inoB = 0; inoB < nodeCnt; inoB++)
                {
                    fmVec_Modify[inoB] = fmVec[inoB] - dfmdxVec[inoB] / (Complex.ImaginaryOne * betam_periodic);
                }
                // 2Dの境界積分
                //Complex[] veci = MyMatrixUtil.product(ryy_1d, fmVec);
                // モード電力規格化の積分(1Dの積分)
                // [ryy]が実数の場合
                //Complex[] vecj = MyMatrixUtil.product(ryy_1d, MyMatrixUtil.vector_Conjugate(fmVec));
                Complex[] veci = MyMatrixUtil.product(ryy_1d, fmVec_Modify);
                Complex[] vecj = MyMatrixUtil.product(ryy_1d, MyMatrixUtil.vector_Conjugate(fmVec_Modify));

                for (int inoB = 0; inoB < nodeCnt; inoB++)
                {
                    for (int jnoB = 0; jnoB < nodeCnt; jnoB++)
                    {
                        Complex cvalue;
                        {
                            // H面、平行平板
                            if (WaveModeDv == FemSolver.WaveModeDV.TM)
                            {
                                //cvalue = (Complex.ImaginaryOne / (omega * eps0)) * betam * Complex.Abs(betam) * veci[inoB] * vecj[jnoB];
                                cvalue = (Complex.ImaginaryOne / (omega * eps0)) * (Complex.Abs(betam) * betam_periodic * Complex.Conjugate(betam_periodic) / Complex.Conjugate(betam)) * veci[inoB] * vecj[jnoB];
                            }
                            else
                            {
                                //cvalue = (Complex.ImaginaryOne / (omega * mu0)) * betam * Complex.Abs(betam) * veci[inoB] * vecj[jnoB];
                                cvalue = (Complex.ImaginaryOne / (omega * mu0)) * (Complex.Abs(betam) * betam_periodic * Complex.Conjugate(betam_periodic) / Complex.Conjugate(betam)) * veci[inoB] * vecj[jnoB];
                            }
                        }
                        matB._body[inoB + jnoB * matB.RowSize] += cvalue;
                    }
                }
            }
            // check 対称行列
            bool isSymmetrix = true;
            for (int inoB = 0; inoB < matB.RowSize; inoB++)
            {
                for (int jnoB = inoB; jnoB < matB.ColumnSize; jnoB++)
                {
                    if (Math.Abs(matB[inoB, jnoB].Real - matB[jnoB, inoB].Real) >= Constants.PrecisionLowerLimit)
                    {
                        //System.Diagnostics.Debug.Assert(false);
                        isSymmetrix = false;
                        break;
                    }
                    if (Math.Abs(matB[inoB, jnoB].Imaginary - matB[jnoB, inoB].Imaginary) >= Constants.PrecisionLowerLimit)
                    {
                        //System.Diagnostics.Debug.Assert(false);
                        isSymmetrix = false;
                        break;
                    }
                }
            }
            if (!isSymmetrix)
            {
                System.Diagnostics.Debug.WriteLine("!!!!!!!!!!matrix is NOT symmetric!!!!!!!!!!!!!!");
                //System.Diagnostics.Debug.Assert(false);
            }
            //MyMatrixUtil.printMatrix("matB", matB);

            // 残差ベクトルの作成
            Complex[] resVecB = new Complex[nodeCnt];
            if (isInputPort)
            {
                int imode = IncidentModeIndex;
                Complex betam = eigenValues[imode];
                Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigenVecs, (int)imode);
                Complex[] dfmdxVec = MyMatrixUtil.matrix_GetRowVec(eigen_dFdXs, (int)imode);
                Complex[] fmVec_Modify = new Complex[fmVec.Length];
                Complex betam_periodic = ToBetaPeriodic(betam, periodicDistance);
                for (uint inoB = 0; inoB < nodeCnt; inoB++)
                {
                    fmVec_Modify[inoB] = fmVec[inoB] - dfmdxVec[inoB] / (Complex.ImaginaryOne * betam_periodic);
                }

                // 2Dの境界積分
                //Complex[] veci = MyMatrixUtil.product(ryy_1d, fmVec);
                Complex[] veci = MyMatrixUtil.product(ryy_1d, fmVec_Modify);
                for (int inoB = 0; inoB < nodeCnt; inoB++)
                {
                    // H面、平行平板、E面
                    //Complex cvalue = 2.0 * Complex.ImaginaryOne * betam * veci[inoB];
                    Complex cvalue = 2.0 * Complex.ImaginaryOne * betam_periodic * veci[inoB];
                    resVecB[inoB].Real = cvalue.Real;
                    resVecB[inoB].Imaginary = cvalue.Imaginary;
                }
            }
            //printVec("resVecB", resVecB);

            // 2D節点番号→ソート済みリストインデックスのマップ
            Dictionary<int, int> toSorted = new Dictionary<int, int>();
            // 2D節点番号→ソート済みリストインデックスのマップ作成
            for (int i = 0; i < nodesRegion.Length; i++)
            {
                int nodeNumber = nodesRegion[i];
                if (!toSorted.ContainsKey(nodeNumber))
                {
                    toSorted.Add(nodeNumber, i);
                }
            }

            // 要素剛性行列にマージ
            //   この定式化では行列のスパース性は失われている(隣接していない要素の節点間にも関連がある)
            // 要素剛性行列にマージする
            for (int inoB = 0; inoB < nodeCnt; inoB++)
            {
                int iNodeNumber = nodesBoundary[inoB];
                if (ForceNodeNumberH.ContainsKey(iNodeNumber)) continue;
                int inoGlobal = toSorted[iNodeNumber];
                for (int jnoB = 0; jnoB < nodeCnt; jnoB++)
                {
                    int jNodeNumber = nodesBoundary[jnoB];
                    if (ForceNodeNumberH.ContainsKey(jNodeNumber)) continue;
                    int jnoGlobal = toSorted[jNodeNumber];

                    // Note: matBは一般行列 matはバンド行列
                    mat._body[mat.GetBufferIndex(inoGlobal, jnoGlobal)] += matB._body[inoB + jnoB * matB.RowSize];
                }
            }

            // 残差ベクトルにマージ
            for (int inoB = 0; inoB < nodeCnt; inoB++)
            {
                int iNodeNumber = nodesBoundary[inoB];
                if (ForceNodeNumberH.ContainsKey(iNodeNumber)) continue;
                int inoGlobal = toSorted[iNodeNumber];

                resVec[inoGlobal] += resVecB[inoB];
            }
        }
Ejemplo n.º 19
0
 private Complex getPeriodicWaveguidePortReflectionCoef(
     double waveLength,
     int iMode,
     bool isIncidentMode,
     int[] nodesBoundary,
     MyDoubleMatrix ryy_1d,
     Complex[] eigenValues,
     Complex[,] eigenVecs,
     Complex[,] eigen_dFdXs,
     int[] nodesRegion,
     Complex[] valuesAll)
 {
     Complex s11 = FemSolverPortPeriodic.GetWaveguidePortReflectionCoef(
         WaveModeDv,
         waveLength,
         LatticeA,
         iMode,
         isIncidentMode,
         nodesBoundary,
         ryy_1d,
         eigenValues,
         eigenVecs,
         eigen_dFdXs,
         nodesRegion,
         Elements,
         Medias,
         valuesAll
         );
     return s11;
 }
Ejemplo n.º 20
0
        private void solvePortPeriodicWaveguideEigen(
            int freqNo,
            string filename,
            double waveLength,
            int portNo,
            int maxModeSpecified,
            out int[] nodesBoundary,
            out MyDoubleMatrix ryy_1d,
            out Complex[] eigenValues,
            out Complex[,] eigenVecs,
            out Complex[,] eigen_dFdX)
        {
            System.Diagnostics.Debug.WriteLine("/////////// solvePortWaveguideEigen: {0}, {1}", waveLength, portNo);
            // ポート周期構造領域の変数(表示用、伝達問題には必要ない)
            IList<int> nodePeriodic = null;
            Dictionary<int, int> toNodePeriodic = null;
            IList<double[]> coordsPeriodic = null;
            KrdLab.clapack.Complex[][] eigenVecsPeriodic = null;

            // 周期構造導波路固有値解析
            FemSolverPortPeriodic.SolvePortWaveguideEigen(
                WaveModeDv,
                waveLength,
                LatticeA,
                maxModeSpecified,
                Nodes,
                EdgeToElementNoH,
                Elements,
                Medias,
                ForceNodeNumberH,
                Ports[portNo - 1],
                ElemNoPeriodicList[portNo - 1],
                NodePeriodicBList[portNo - 1],
                DefectNodePeriodicList[portNo - 1],
                out nodesBoundary,
                out ryy_1d,
                out eigenValues,
                out eigenVecs,
                out eigen_dFdX,
                out nodePeriodic,
                out toNodePeriodic,
                out coordsPeriodic,
                out eigenVecsPeriodic
                );

            // 周期構造領域のモード分布をファイルに格納する
            string periodicDatFilename = FemOutputPeriodicDatFile.GetOutputPeriodicDatFilename(filename);
            FemOutputPeriodicDatFile.AppendToFile(
                periodicDatFilename,
                freqNo,
                portNo,
                waveLength,
                nodePeriodic,
                toNodePeriodic,
                coordsPeriodic,
                eigenValues,
                eigenVecsPeriodic
                );
        }
 /// <summary>
 /// �w�肳�ꂽ�s���R�s�[���āC�V�����s���쐬����D
 /// </summary>
 /// <param name="m">�R�s�[�����s��</param>
 public MyDoubleMatrix(MyDoubleMatrix m)
 {
     CopyFrom(m);
 }
Ejemplo n.º 22
0
        /*
        /// <summary>
        /// 入出力ポート境界条件の追加
        /// </summary>
        /// <param name="waveLength"></param>
        /// <param name="isInputPort"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        /// <param name="eigenValues"></param>
        /// <param name="eigenVecs"></param>
        /// <param name="nodesRegion"></param>
        /// <param name="mat"></param>
        /// <param name="resVec"></param>
        private void addPortBC(
            double waveLength,
            bool isInputPort,
            int[] nodesBoundary,
            MyDoubleMatrix ryy_1d,
            Complex[] eigenValues,
            Complex[,] eigenVecs,
            int[] nodesRegion,
            MyComplexMatrix mat,
            Complex[] resVec)
        {
            FemSolverPort.AddPortBC(
                WaveModeDv,
                waveLength,
                isInputPort,
                IncidentModeIndex,
                nodesBoundary,
                ryy_1d,
                eigenValues,
                eigenVecs,
                nodesRegion,
                Elements,
                Medias,
                ForceNodeNumberH,
                mat,
                resVec
                );
        }

        /// <summary>
        /// 散乱行列の計算
        /// </summary>
        /// <param name="waveLength"></param>
        /// <param name="iMode"></param>
        /// <param name="isIncidentMode"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        /// <param name="eigenValues"></param>
        /// <param name="eigenVecs"></param>
        /// <param name="nodesRegion"></param>
        /// <param name="valuesAll"></param>
        /// <returns></returns>
        private Complex getWaveguidePortReflectionCoef(
            double waveLength,
            int iMode,
            bool isIncidentMode,
            int[] nodesBoundary,
            MyDoubleMatrix ryy_1d,
            Complex[] eigenValues,
            Complex[,] eigenVecs,
            int[] nodesRegion,
            Complex[] valuesAll)
        {
            Complex s11 = FemSolverPort.GetWaveguidePortReflectionCoef(
                WaveModeDv,
                waveLength,
                iMode,
                isIncidentMode,
                nodesBoundary,
                ryy_1d,
                eigenValues,
                eigenVecs,
                nodesRegion,
                Elements,
                Medias,
                valuesAll
                );
            return s11;
        }

        /// <summary>
        /// ポート固有値解析
        /// </summary>
        private void solvePortWaveguideEigen(
            double waveLength,
            int portNo,
            int maxModeSpecified,
            out int[] nodesBoundary,
            out MyDoubleMatrix ryy_1d,
            out Complex[] eigenValues,
            out Complex[,] eigenVecs)
        {
            FemSolverPort.SolvePortWaveguideEigen(
                WaveModeDv,
                waveLength,
                maxModeSpecified,
                Nodes,
                EdgeToElementNoH,
                Elements,
                Medias,
                ForceNodeNumberH,
                Ports[portNo - 1],
                out nodesBoundary,
                out ryy_1d,
                out eigenValues,
                out eigenVecs
                );
        }
         */
        ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 入出力ポート境界条件の追加
        /// </summary>
        /// <param name="waveLength"></param>
        /// <param name="isInputPort"></param>
        /// <param name="nodesBoundary"></param>
        /// <param name="ryy_1d"></param>
        /// <param name="eigenValues"></param>
        /// <param name="eigenVecs"></param>
        /// <param name="nodesRegion"></param>
        /// <param name="mat"></param>
        /// <param name="resVec"></param>
        private void addPeriodicPortBC(
            double waveLength,
            bool isInputPort,
            int[] nodesBoundary,
            MyDoubleMatrix ryy_1d,
            Complex[] eigenValues,
            Complex[,] eigenVecs,
            Complex[,] eigen_dFdX,
            int[] nodesRegion,
            MyComplexMatrix mat,
            Complex[] resVec)
        {
            FemSolverPortPeriodic.AddPortBC(
                WaveModeDv,
                waveLength,
                LatticeA,
                isInputPort,
                IncidentModeIndex,
                nodesBoundary,
                ryy_1d,
                eigenValues,
                eigenVecs,
                eigen_dFdX,
                nodesRegion,
                Elements,
                Medias,
                ForceNodeNumberH,
                mat,
                resVec
                );
        }
Ejemplo n.º 23
0
 // [X] = alpha * [A]
 public static MyDoubleMatrix product(double alpha, MyDoubleMatrix matA)
 {
     MyDoubleMatrix matX = new MyDoubleMatrix(matA.RowSize, matA.ColumnSize);
     for (int i = 0; i < matA.RowSize; i++)
     {
         for (int j = 0; j < matA.ColumnSize; j++)
         {
             matX[i, j] = alpha * matA[i, j];
         }
     }
     return matX;
 }
 /// <summary>
 /// ベースクラスのコピーI/F (無効)
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public override sealed MyDoubleMatrix CopyFrom(MyDoubleMatrix m)
 {
     System.Diagnostics.Debug.Assert(false);
     //return base.CopyFrom(m);
     return(this);
 }
Ejemplo n.º 25
0
 /// <summary>
 /// �x�[�X�N���X�̃R�s�[I/F (����)
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public override sealed MyDoubleMatrix CopyFrom(MyDoubleMatrix m)
 {
     System.Diagnostics.Debug.Assert(false);
     //return base.CopyFrom(m);
     return this;
 }
Ejemplo n.º 26
0
 public static void printMatrix(string tag, MyDoubleMatrix mat)
 {
     for (int i = 0; i < mat.RowSize; i++)
     {
         for (int j = 0; j < mat.ColumnSize; j++)
         {
             double val = mat[i, j];
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = " + val);
         }
     }
 }
Ejemplo n.º 27
0
 /*
 // x = sqrt(c)
 public static Complex complex_Sqrt(Complex c)
 {
     System.Numerics.Complex work = new System.Numerics.Complex(c.Real, c.Imaginary);
     work = System.Numerics.Complex.Sqrt(work);
     return new Complex(work.Real, work.Imaginary);
 }
 */
 // [X] = [A]t
 public static MyDoubleMatrix matrix_Transpose(MyDoubleMatrix matA)
 {
     MyDoubleMatrix matX = new MyDoubleMatrix(matA.ColumnSize, matA.RowSize);
     for (int i = 0; i < matX.RowSize; i++)
     {
         for (int j = 0; j < matX.ColumnSize; j++)
         {
             matX[i, j] = matA[j, i];
         }
     }
     return matX;
 }
Ejemplo n.º 28
0
 public static double[,] matrix_Inverse(double[,] matA)
 {
     MyDoubleMatrix matA_ = new MyDoubleMatrix(matA);
     matA_ = matrix_Inverse(matA_);
     return matA_.ToArray();
 }
Ejemplo n.º 29
0
        /// <summary>
        /// 1Dヘルムホルツ方程式固有値問題の要素行列を加算する
        /// </summary>
        /// <param name="waveLength">波長(E面の場合のみ使用する)</param>
        /// <param name="element">線要素</param>
        /// <param name="coords">座標リスト</param>
        /// <param name="toSorted">節点番号→ソート済み節点インデックスマップ</param>
        /// <param name="Medias">媒質情報リスト</param>
        /// <param name="WaveModeDv">計算する波のモード区分</param>
        /// <param name="txx_1d">txx行列</param>
        /// <param name="ryy_1d">ryy行列</param>
        /// <param name="uzz_1d">uzz行列</param>
        public static void AddElementMatOf1dEigenValueProblem(
            double waveLength,
            FemLineElement element,
            IList<double> coords,
            Dictionary<int, int> toSorted,
            MediaInfo[] Medias,
            FemSolver.WaveModeDV WaveModeDv,
            ref MyDoubleMatrix txx_1d, ref MyDoubleMatrix ryy_1d, ref MyDoubleMatrix uzz_1d)
        {
            // 定数
            const double pi = Constants.pi;
            const double c0 = Constants.c0;
            // 波数
            double k0 = 2.0 * pi / waveLength;
            // 角周波数
            double omega = k0 * c0;

            // 2次線要素
            const int nno = Constants.LineNodeCnt_SecondOrder; // 3;

            int[] nodeNumbers = element.NodeNumbers;
            System.Diagnostics.Debug.Assert(nno == nodeNumbers.Length);

            // 座標の取得
            double[] elementCoords = new double[nno];
            for (int n = 0; n < nno; n++)
            {
                int nodeIndex = nodeNumbers[n] - 1;
                elementCoords[n] = coords[nodeIndex];
            }
            // 線要素の長さ
            double elen = Math.Abs(elementCoords[1] - elementCoords[0]);
            // 媒質インデックス
            int mediaIndex = element.MediaIndex;
            // 媒質
            MediaInfo media = Medias[mediaIndex];
            double[,] media_P = null;
            double[,] media_Q = null;
            // ヘルムホルツ方程式のパラメータP,Qを取得する
            FemSolver.GetHelmholtzMediaPQ(
                k0,
                media,
                WaveModeDv,
                out media_P,
                out media_Q);

            double[,] integralN = new double[nno, nno]
                {
                    {  4.0 / 30.0 * elen, -1.0 / 30.0 * elen,  2.0 / 30.0 * elen },
                    { -1.0 / 30.0 * elen,  4.0 / 30.0 * elen,  2.0 / 30.0 * elen },
                    {  2.0 / 30.0 * elen,  2.0 / 30.0 * elen, 16.0 / 30.0 * elen },
                };
            double[,] integralDNDY = new double[nno, nno]
                {
                    {  7.0 / (3.0 * elen),  1.0 / (3.0 * elen), -8.0 / (3.0 * elen) },
                    {  1.0 / (3.0 * elen),  7.0 / (3.0 * elen), -8.0 / (3.0 * elen) },
                    { -8.0 / (3.0 * elen), -8.0 / (3.0 * elen), 16.0 / (3.0 * elen) },
                };

            for (int ino = 0; ino < nno; ino++)
            {
                int inoBoundary = nodeNumbers[ino];
                int inoSorted;
                if (!toSorted.ContainsKey(inoBoundary)) continue;
                inoSorted = toSorted[inoBoundary];
                for (int jno = 0; jno < nno; jno++)
                {
                    int jnoBoundary = nodeNumbers[jno];
                    int jnoSorted;
                    if (!toSorted.ContainsKey(jnoBoundary)) continue;
                    jnoSorted = toSorted[jnoBoundary];
                    // 対称バンド行列対応
                    if (ryy_1d is MyDoubleSymmetricBandMatrix && jnoSorted < inoSorted)
                    {
                        continue;
                    }

                    double e_txx_1d_inojno = media_P[0, 0] * integralDNDY[ino, jno];
                    double e_ryy_1d_inojno = media_P[1, 1] * integralN[ino, jno];
                    double e_uzz_1d_inojno = media_Q[2, 2] * integralN[ino, jno];
                    //txx_1d[inoSorted, jnoSorted] += e_txx_1d_inojno;
                    //ryy_1d[inoSorted, jnoSorted] += e_ryy_1d_inojno;
                    //uzz_1d[inoSorted, jnoSorted] += e_uzz_1d_inojno;
                    txx_1d._body[txx_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_txx_1d_inojno;
                    ryy_1d._body[ryy_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_ryy_1d_inojno;
                    uzz_1d._body[uzz_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_uzz_1d_inojno;
                }
            }
        }
Ejemplo n.º 30
0
 /*
 public static void printVec(string tag, ValueType[] vec)
 {
     for (int i = 0; i < vec.Length; i++)
     {
         Complex val = (Complex)vec[i];
         System.Diagnostics.Debug.WriteLine(tag + "(" + i + ")" + " = "
                            + "(" + val.Real + "," + val.Imaginary + ") " + Complex.Abs(val));
     }
 }
 */
 /*
 public static void compressVec(ref ValueType[] vec)
 {
     KrdLab.clapack.FunctionExt.CompressMatFor_zgesv(ref vec);
 }
  */
 public static double[] matrix_ToBuffer(MyDoubleMatrix mat, bool copyFlg = true)
 {
     double[] mat_ = null;
     if (copyFlg)
     {
         int size = mat._rsize * mat._csize;
         mat_ = new double[size];
         mat._body.CopyTo(mat_, 0);
     }
     else
     {
         mat_ = mat._body;
     }
     return mat_;
 }
        /*
         * /// <summary>
         * /// リサイズする.
         * /// </summary>
         * /// <param name="rowSize">新しい行数</param>
         * /// <param name="columnSize">新しい列数</param>
         * /// <param name="val">各要素の値</param>
         * /// <returns>リサイズ後の自身への参照</returns>
         * public MyDoubleMatrix Resize(int rowSize, int columnSize, double val)
         * {
         *  Resize(rowSize, columnSize);
         *  for (int i = 0; i < this._body.Length; ++i)
         *  {
         *      this._body[i] = val;
         *  }
         *  return this;
         * }
         */

        /// <summary>
        /// 指定された行列をコピーする.
        /// </summary>
        /// <param name="m">コピーされる行列</param>
        /// <returns>コピー後の自身への参照</returns>
        public virtual MyDoubleMatrix CopyFrom(MyDoubleMatrix m)
        {
            return(CopyFrom(m._body, m._rsize, m._csize));
        }
Ejemplo n.º 32
0
 // [X] = [A] + [B]
 public static MyDoubleMatrix plus(MyDoubleMatrix matA, MyDoubleMatrix matB)
 {
     System.Diagnostics.Debug.Assert(matA.RowSize == matB.RowSize);
     System.Diagnostics.Debug.Assert(matA.ColumnSize == matB.ColumnSize);
     MyDoubleMatrix matX = new MyDoubleMatrix(matA.RowSize, matA.ColumnSize);
     for (int i = 0; i < matA.RowSize; i++)
     {
         for (int j = 0; j < matA.ColumnSize; j++)
         {
             matX[i, j] = matA[i, j] + matB[i, j];
         }
     }
     return matX;
 }
 /// <summary>
 /// 指定された行列をコピーして,新しい行列を作成する.
 /// </summary>
 /// <param name="m">コピーされる行列</param>
 public MyDoubleMatrix(MyDoubleMatrix m)
 {
     CopyFrom(m);
 }
Ejemplo n.º 34
0
 public static void printMatrixNoZero(string tag, MyDoubleMatrix mat)
 {
     for (int i = 0; i < mat.RowSize; i++)
     {
         for (int j = 0; j < mat.ColumnSize; j++)
         {
             double val = mat[i, j];
             if (Math.Abs(val) < Constants.PrecisionLowerLimit) continue;
             System.Diagnostics.Debug.WriteLine(tag + "(" + i + ", " + j + ")" + " = " + val + " ");
         }
     }
 }
 /*
 /// <summary>
 /// ���T�C�Y����D
 /// </summary>
 /// <param name="rowSize">�V�����s��</param>
 /// <param name="columnSize">�V������</param>
 /// <param name="val">�e�v�f�̒l</param>
 /// <returns>���T�C�Y��̎��g�ւ̎Q��</returns>
 public MyDoubleMatrix Resize(int rowSize, int columnSize, double val)
 {
     Resize(rowSize, columnSize);
     for (int i = 0; i < this._body.Length; ++i)
     {
         this._body[i] = val;
     }
     return this;
 }
  */
 /// <summary>
 /// �w�肳�ꂽ�s���R�s�[����D
 /// </summary>
 /// <param name="m">�R�s�[�����s��</param>
 /// <returns>�R�s�[��̎��g�ւ̎Q��</returns>
 public virtual MyDoubleMatrix CopyFrom(MyDoubleMatrix m)
 {
     return CopyFrom(m._body, m._rsize, m._csize);
 }
Ejemplo n.º 36
0
 public static MyComplexMatrix product(MyDoubleMatrix matA, MyComplexMatrix matB)
 {
     System.Diagnostics.Debug.Assert(matA.ColumnSize == matB.RowSize);
     MyComplexMatrix matX = new MyComplexMatrix(matA.RowSize, matB.ColumnSize);
     for (int i = 0; i < matX.RowSize; i++)
     {
         for (int j = 0; j < matX.ColumnSize; j++)
         {
             matX[i, j] = 0.0;
             for (int k = 0; k < matA.ColumnSize; k++)
             {
                 matX[i, j] += matA[i, k] * matB[k, j];
             }
         }
     }
     return matX;
 }
        /// <summary>
        /// �]�u����D
        /// </summary>
        /// <returns>�]�u��̎��g�ւ̎Q��</returns>
        public virtual MyDoubleMatrix Transpose()
        {
            MyDoubleMatrix t = new MyDoubleMatrix(this._csize, this._rsize);

            for (int r = 0; r < this._rsize; ++r)
            {
                for (int c = 0; c < this._csize; ++c)
                {
                    t[c, r] = this[r, c];
                }
            }

            this.Clear();
            this._body = t._body;
            this._rsize = t._rsize;
            this._csize = t._csize;

            return this;
        }
Ejemplo n.º 38
0
        // {x} = [A]{v}
        public static Complex[] product(MyDoubleMatrix matA, Complex[] vec)
        {
            System.Diagnostics.Debug.Assert(matA.ColumnSize == vec.Length);
            //BUGFIX
            //Complex[] retVec = new Complex[vec.Length];
            Complex[] retVec = new Complex[matA.RowSize];

            for (int i = 0; i < matA.RowSize; i++)
            {
                retVec[i] = new Complex(0.0, 0.0);
                for (int k = 0; k < matA.ColumnSize; k++)
                {
                    retVec[i] += matA[i, k] * vec[k];
                }
            }
            return retVec;
        }
        /// <summary>
        /// 1Dヘルムホルツ方程式固有値問題の要素行列を加算する
        /// </summary>
        /// <param name="element">線要素</param>
        /// <param name="coords">座標リスト</param>
        /// <param name="toSorted">節点番号→ソート済み節点インデックスマップ</param>
        /// <param name="Medias">媒質情報リスト</param>
        /// <param name="WaveModeDv">計算する波のモード区分</param>
        /// <param name="txx_1d">txx行列</param>
        /// <param name="ryy_1d">ryy行列</param>
        /// <param name="uzz_1d">uzz行列</param>
        public static void AddElementMatOf1dEigenValueProblem(
            FemLineElement element,
            IList<double> coords,
            Dictionary<int, int> toSorted,
            MediaInfo[] Medias,
            FemSolver.WaveModeDV WaveModeDv,
            ref MyDoubleMatrix txx_1d, ref MyDoubleMatrix ryy_1d, ref MyDoubleMatrix uzz_1d)
        {
            // 1次線要素
            const int nno = Constants.LineNodeCnt_FirstOrder; // 2;

            int[] nodeNumbers = element.NodeNumbers;
            System.Diagnostics.Debug.Assert(nno == nodeNumbers.Length);

            // 座標の取得
            double[] elementCoords = new double[nno];
            for (int n = 0; n < nno; n++)
            {
                int nodeIndex = nodeNumbers[n] - 1;
                elementCoords[n] = coords[nodeIndex];
            }
            // 線要素の長さ
            double elen = Math.Abs(elementCoords[1] - elementCoords[0]);
            // 媒質インデックス
            int mediaIndex = element.MediaIndex;
            // 媒質
            MediaInfo media = Medias[mediaIndex];
            double[,] media_P = null;
            double[,] media_Q = null;
            if (WaveModeDv == FemSolver.WaveModeDV.TE)
            {
                media_P = media.P;
                media_Q = media.Q;
            }
            else if (WaveModeDv == FemSolver.WaveModeDV.TM)
            {
                media_P = media.Q;
                media_Q = media.P;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }
            media_P = MyMatrixUtil.matrix_Inverse(media_P);

            double[,] integralN = new double[nno, nno]
                {
                    { elen / 3.0, elen / 6.0 },
                    { elen / 6.0, elen / 3.0 },
                };
            double[,] integralDNDY = new double[nno, nno]
                {
                    {  1.0 / elen, -1.0 / elen },
                    { -1.0 / elen,  1.0 / elen },
                };
            for (int ino = 0; ino < nno; ino++)
            {
                int inoBoundary = nodeNumbers[ino];
                int inoSorted;
                if (!toSorted.ContainsKey(inoBoundary)) continue;
                inoSorted = toSorted[inoBoundary];
                for (int jno = 0; jno < nno; jno++)
                {
                    int jnoBoundary = nodeNumbers[jno];
                    int jnoSorted;
                    if (!toSorted.ContainsKey(jnoBoundary)) continue;
                    jnoSorted = toSorted[jnoBoundary];
                    // 対称バンド行列対応
                    if (ryy_1d is MyDoubleSymmetricBandMatrix && jnoSorted < inoSorted)
                    {
                        continue;
                    }

                    double e_txx_1d_inojno = media_P[0, 0] * integralDNDY[ino, jno];
                    double e_ryy_1d_inojno = media_P[1, 1] * integralN[ino, jno];
                    double e_uzz_1d_inojno = media_Q[2, 2] * integralN[ino, jno];
                    //txx_1d[inoSorted, jnoSorted] += e_txx_1d_inojno;
                    //ryy_1d[inoSorted, jnoSorted] += e_ryy_1d_inojno;
                    //uzz_1d[inoSorted, jnoSorted] += e_uzz_1d_inojno;
                    txx_1d._body[txx_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_txx_1d_inojno;
                    ryy_1d._body[ryy_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_ryy_1d_inojno;
                    uzz_1d._body[uzz_1d.GetBufferIndex(inoSorted, jnoSorted)] += e_uzz_1d_inojno;
                }
            }
        }