Пример #1
0
        /// <summary>
        /// 1次線要素を作成する(固有値問題用)
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="EdgeToElementNoH"></param>
        /// <param name="Elements"></param>
        /// <param name="elements"></param>
        public static void MkElements(
            IList <int> nodes,
            Dictionary <string, IList <int> > EdgeToElementNoH,
            IList <FemElement> Elements,
            ref IList <FemLineElement> elements)
        {
            // 要素内節点数
            const int nno = Constants.LineNodeCnt_FirstOrder; //2; // 1次線要素

            // 要素リスト作成
            int elemCnt = (nodes.Count - 1); // 1次線要素

            for (int elemIndex = 0; elemIndex < elemCnt; elemIndex++)
            {
                // 線要素の要素内節点
                // 節点番号はポート上の1D節点番号(1起点の番号)
                //  1   2
                //  +---+
                FemLineElement element = new FemLineElement();
                element.No             = elemIndex + 1;
                element.NodeNumbers    = new int[nno];
                element.NodeNumbers[0] = elemIndex + 1;
                element.NodeNumbers[1] = elemIndex + 1 + 1;
                element.MediaIndex     = 0;
                elements.Add(element);
            }

            // 要素を1辺とする2D領域の要素番号を取得
            for (int elemIndex = 0; elemIndex < elements.Count; elemIndex++)
            {
                FemElement element     = elements[elemIndex];
                int[]      nodeNumbers = element.NodeNumbers;

                // 1辺だけ調べればよい(1-2をチェック)
                int    stNodeNumber = nodes[nodeNumbers[0] - 1];
                int    edNodeNumber = nodes[nodeNumbers[1] - 1];
                string edgeKey      = "";
                if (stNodeNumber < edNodeNumber)
                {
                    edgeKey = string.Format("{0}_{1}", stNodeNumber, edNodeNumber);
                }
                else
                {
                    edgeKey = string.Format("{0}_{1}", edNodeNumber, stNodeNumber);
                }
                if (!EdgeToElementNoH.ContainsKey(edgeKey))
                {
                    System.Diagnostics.Debug.WriteLine("logical error: Not find edge {0}", edgeKey);
                }
                else
                {
                    // 隣接する2Dの要素を1つ取得する
                    int        elemNo2d  = EdgeToElementNoH[edgeKey][0];
                    FemElement element2d = Elements[elemNo2d - 1];

                    // 媒質インデックスをセット
                    element.MediaIndex = element2d.MediaIndex;
                }
            }
        }
Пример #2
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;
                }
            }
        }
Пример #3
0
        /// <summary>
        /// 2次線要素を作成する(固有値問題用)
        /// </summary>
        /// <param name="nodes"></param>
        /// <param name="EdgeToElementNoH"></param>
        /// <param name="Elements"></param>
        /// <param name="elements"></param>
        public static void MkElements(
            IList<int> nodes,
            Dictionary<string, IList<int>> EdgeToElementNoH,
            IList<FemElement> Elements,
            ref IList<FemLineElement> elements)
        {
            // 要素内節点数
            const int nno = Constants.LineNodeCnt_SecondOrder; //3; // 2次線要素

            // 要素リスト作成
            int elemCnt = (nodes.Count - 1) / 2; // 2次線要素
            for (int elemIndex = 0; elemIndex < elemCnt; elemIndex++)
            {
                // 線要素の要素内節点
                // 節点番号はポート上の1D節点番号(1起点の番号)
                //  1   3   2
                //  +---+---+   並びに注意:頂点→内部の点
                FemLineElement element = new FemLineElement();
                element.No = elemIndex + 1;
                element.NodeNumbers = new int[nno];
                element.NodeNumbers[0] = 2 * elemIndex + 1;
                element.NodeNumbers[1] = 2 * elemIndex + 2 + 1;
                element.NodeNumbers[2] = 2 * elemIndex + 1 + 1;
                element.MediaIndex = 0;
                elements.Add(element);
            }

            // 要素を1辺とする2D領域の要素番号を取得
            for (int elemIndex = 0; elemIndex < elements.Count; elemIndex++)
            {
                FemElement element = elements[elemIndex];
                int[] nodeNumbers = element.NodeNumbers;

                // 1辺だけ調べればよい(1-3をチェック)
                int stNodeNumber = nodes[nodeNumbers[0] - 1];
                int edNodeNumber = nodes[nodeNumbers[2] - 1];
                string edgeKey = "";
                if (stNodeNumber < edNodeNumber)
                {
                    edgeKey = string.Format("{0}_{1}", stNodeNumber, edNodeNumber);
                }
                else
                {
                    edgeKey = string.Format("{0}_{1}", edNodeNumber, stNodeNumber);
                }
                if (!EdgeToElementNoH.ContainsKey(edgeKey))
                {
                    System.Diagnostics.Debug.WriteLine("logical error: Not find edge {0}", edgeKey);
                }
                else
                {
                    // 隣接する2Dの要素を1つ取得する
                    int elemNo2d = EdgeToElementNoH[edgeKey][0];
                    FemElement element2d = Elements[elemNo2d - 1];

                    // 媒質インデックスをセット
                    element.MediaIndex = element2d.MediaIndex;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// ポート固有値解析
        /// </summary>
        public static void SolvePortWaveguideEigen(
            FemSolver.WaveModeDV WaveModeDv,
            double waveLength,
            int maxModeSpecified,
            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,
            out Complex[] eigenValues,
            out Complex[,] eigenVecs)
        {
            //System.Diagnostics.Debug.WriteLine("solvePortWaveguideEigen: {0},{1}", waveLength, portNo);
            nodesBoundary = null;
            ryy_1d        = null;
            eigenValues   = null;
            eigenVecs     = 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;
                GetMatNonzeroPatternForEigen(elements, toSorted, out matPattern);
                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;
            // 固有値、固有ベクトル
            int maxMode = maxModeSpecified;

            if (maxMode > nodeCnt)
            {
                maxMode = nodeCnt;
            }
            eigenValues = new Complex[maxMode];
            eigenVecs   = new Complex[maxMode, nodeCnt];
            // 固有モード解析でのみ使用する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);
                }
            }

            // [A] = [Txx] - k0 * k0 *[Uzz]
            //メモリ節約
            //MyDoubleMatrix matA = new MyDoubleMatrix(nodeCnt, nodeCnt);
            MyDoubleSymmetricBandMatrix matA = new MyDoubleSymmetricBandMatrix(nodeCnt, subdiaSize, superdiaSize);

            for (int ino = 0; ino < nodeCnt; ino++)
            {
                for (int jno = 0; jno < nodeCnt; jno++)
                {
                    // 対称バンド行列対応
                    if (matA is MyDoubleSymmetricBandMatrix && ino > jno)
                    {
                        continue;
                    }
                    // 剛性行列
                    //matA[ino, jno] = txx_1d[ino, jno] - (k0 * k0) * uzz_1d[ino, jno];
                    //  質量行列matBが正定値行列となるように剛性行列matAの方の符号を反転する
                    matA[ino, jno] = -(txx_1d[ino, jno] - (k0 * k0) * uzz_1d[ino, jno]);
                }
            }

            // ( [txx] - k0^2[uzz] + β^2[ryy]){Ez} = {0}より
            // [A]{x} = λ[B]{x}としたとき、λ = β^2 とすると[B] = -[ryy]
            //MyDoubleMatrix matB = MyMatrixUtil.product(-1.0, ryy_1d);
            // 質量行列が正定値となるようにするため、上記符号反転を剛性行列の方に反映し、質量行列はryy_1dをそのまま使用する
            //MyDoubleMatrix matB = new MyDoubleMatrix(ryy_1d);
            MyDoubleSymmetricBandMatrix matB = new MyDoubleSymmetricBandMatrix((MyDoubleSymmetricBandMatrix)ryy_1d);

            // 一般化固有値問題を解く
            Complex[] evals = null;
            Complex[,] evecs = null;
            try
            {
                // 固有値、固有ベクトルを求める
                solveEigen(matA, matB, out evals, out evecs);
                // 固有値のソート
                Sort1DEigenMode(k0, evals, evecs);
            }
            catch (Exception exception)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                System.Diagnostics.Debug.Assert(false);
            }
            for (int imode = 0; imode < evecs.GetLength(0); imode++)
            {
                KrdLab.clapack.Complex phaseShift = 1.0;
                double maxAbs = double.MinValue;
                KrdLab.clapack.Complex fValueAtMaxAbs = 0.0;
                {
                    // 境界上で位相調整する
                    for (int ino = 0; ino < evecs.GetLength(1); ino++)
                    {
                        KrdLab.clapack.Complex cvalue = evecs[imode, ino];
                        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 ino = 0; ino < evecs.GetLength(1); ino++)
                {
                    evecs[imode, ino] /= phaseShift;
                }
            }

            for (int imode = 0; imode < maxMode; imode++)
            {
                eigenValues[imode] = 0;
            }
            for (int tagtModeIdx = evals.Length - 1, imode = 0; tagtModeIdx >= 0 && imode < maxMode; tagtModeIdx--)
            {
                // 伝搬定数は固有値のsqrt
                Complex betam = Complex.Sqrt(evals[tagtModeIdx]);
                // 定式化BUGFIX
                //   減衰定数は符号がマイナス(β = -jα)
                bool isConjugateMode = false;
                if (betam.Imaginary >= 0.0)
                {
                    betam           = new Complex(betam.Real, -betam.Imaginary);
                    isConjugateMode = true;
                }
                // 固有ベクトル
                Complex[] evec = MyMatrixUtil.matrix_GetRowVec(evecs, tagtModeIdx);
                if (isConjugateMode)
                {
                    evec = MyMatrixUtil.vector_Conjugate(evec);
                }
                // 規格化定数を求める
                // 実数の場合 [ryy]*t = [ryy]t ryyは対称行列より[ryy]t = [ryy]
                Complex[] workVec = MyMatrixUtil.product(ryy_1d, evec);
                Complex   dm      = MyMatrixUtil.vector_Dot(MyMatrixUtil.vector_Conjugate(evec), workVec);
                {
                    // H面、平行平板
                    if (WaveModeDv == FemSolver.WaveModeDV.TM)
                    {
                        dm = Complex.Sqrt(omega * eps0 / Complex.Abs(betam) / dm);
                    }
                    else
                    {
                        dm = Complex.Sqrt(omega * mu0 / Complex.Abs(betam) / dm);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("dm = " + dm);

                // 伝搬定数の格納
                eigenValues[imode] = betam;
                // check
                if (imode < 5)
                {
                    //System.Diagnostics.Debug.WriteLine("eigenValues [ " + imode + "] = " + betam.Real + " + " + betam.Imaginary + " i " + " tagtModeIdx :" + tagtModeIdx + " " );
                    System.Diagnostics.Debug.WriteLine("β/k0 [ " + imode + "] = " + betam.Real / k0 + " + " + betam.Imaginary / k0 + " i " + " tagtModeIdx :" + tagtModeIdx + " ");
                }
                // 固有ベクトルの格納(規格化定数を掛ける)
                for (int inoSorted = 0; inoSorted < nodeCnt; inoSorted++)
                {
                    Complex fm = dm * evec[inoSorted];
                    eigenVecs[imode, inoSorted] = fm;
                    //System.Diagnostics.Debug.WriteLine("eigenVecs [ " + imode + ", " + inoSorted + "] = " + fm.Real + " + " + fm.Imaginary + " i  Abs:" + Complex.Abs(fm));
                }
                imode++;
            }
        }
Пример #5
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;
                }
            }
        }