/// <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; } } }
/// <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; } } }