Esempio n. 1
0
 /// <summary>
 /// �w�肳�ꂽ�s���R�s�[���āC�V�����s���쐬����D
 /// </summary>
 /// <param name="m">�R�s�[�����s��</param>
 public MyDoubleBandMatrix(MyDoubleBandMatrix m)
 {
     CopyFrom(m);
 }
Esempio n. 2
0
 /// <summary>
 /// �w�肳�ꂽ�s���R�s�[����D
 /// </summary>
 /// <param name="m">�R�s�[�����s��</param>
 /// <returns>�R�s�[��̎��g�ւ̎Q��</returns>
 public virtual MyDoubleBandMatrix CopyFrom(MyDoubleBandMatrix m)
 {
     return CopyFrom(m._body, m._rowcolSize, m._subdiaSize, m._superdiaSize);
 }
Esempio n. 3
0
        /// <summary>
        /// �]�u����D(�x�[�X�N���X��I/F�̃I�[�o�[���C�h)
        /// </summary>
        /// <returns>�]�u��̎��g�ւ̎Q��</returns>
        public override MyDoubleMatrix Transpose()
        {
            //return base.Transpose();

            int rowcolSize = this._rowcolSize;
            int subdiaSize = 0;
            int superdiaSize = 0;
            // �]�u���subdiaSize, superdiaSize��擾����
            // r��c������ւ���Ă��邱�Ƃɒ���
            for (int r = 0; r < rowcolSize; r++)
            {
                if (r < rowcolSize - 1)
                {
                    int cnt = 0;
                    for (int c = rowcolSize - 1; c >= r + 1; c--)
                    {
                        // ��O�v�f�����‚������甲����
                        if (Math.Abs(this[c, r]) >= Constants.PrecisionLowerLimit)
                        {
                            cnt = c - r;
                            break;
                        }
                    }
                    if (cnt > subdiaSize)
                    {
                        subdiaSize = cnt;
                    }
                }
                if (r > 0)
                {
                    int cnt = 0;
                    for (int c = 0; c <= r - 1; c++)
                    {
                        // ��O�v�f�����‚������甲����
                        if (Math.Abs(this[c, r]) >= Constants.PrecisionLowerLimit)
                        {
                            cnt = r - c;
                            break;
                        }
                    }
                    if (cnt > superdiaSize)
                    {
                        superdiaSize = cnt;
                    }
                }
            }

            MyDoubleBandMatrix t = new MyDoubleBandMatrix(rowcolSize, subdiaSize, superdiaSize);
            for (int r = 0; r < this._rsize; ++r)
            {
                for (int c = 0; c < this._csize; ++c)
                {
                    t._body[(c - r) + t._subdiaSize + t._superdiaSize + r * t._rsize] = this._body[(r - c) + this._subdiaSize + this._superdiaSize + c * this._rsize];
                }
            }

            this.Clear();
            this._body = t._body;
            this._rsize = t._rsize;
            this._csize = t._csize;
            this._rowcolSize = t._rowcolSize;
            this._subdiaSize = t._subdiaSize;
            this._superdiaSize = t._superdiaSize;

            return this;
        }
Esempio n. 4
0
        /// <summary>
        /// ヘルムホルツの方程式 PML要素の全体行列の追加(要素アレイ単位)
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">値のフィールドID</param>
        /// <param name="pmlStPosX">PML媒質開始位置X座標</param>
        /// <param name="pmlLength">PML長さ</param>
        /// <param name="dt">時刻刻み幅</param>
        /// <param name="newmarkBeta">Newmark法β</param>
        /// <param name="media">媒質</param>
        /// <param name="eaId">要素アレイID</param>
        /// <param name="node_cnt">解析領域全体の節点数</param>
        /// <param name="free_node_cnt">解析領域全体の自由節点数(強制境界を除いた節点数)</param>
        /// <param name="toSorted">節点番号→ソート済み(強制境界を除いた)節点リストのインデックスマップ</param>
        /// <param name="AMat">全体行列</param>
        /// <returns></returns>
        private static bool addPmlMat_EachElementAry(
            CFieldWorld world,
            uint fieldValId,
            bool isPmlYDirection,
            double pmlStPosX,
            double pmlLength,
            double dt,
            double newmarkBeta,
            MediaInfo media,
            uint eaId,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            ref MyDoubleBandMatrix AMat)
        {
            System.Diagnostics.Debug.Assert(free_node_cnt == AMat.RowSize && free_node_cnt == AMat.ColumnSize);
            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            // 要素アレイを取得
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.TRI);
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            // 値のフィールドを取得
            CField valField = world.GetField(fieldValId);
            // 値の要素セグメント(コーナー)を取得
            CElemAry.CElemSeg es_c_va = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, true, world);
            // 座標の要素セグメント(コーナー)を取得
            CElemAry.CElemSeg es_c_co = valField.GetElemSeg(eaId, ELSEG_TYPE.CORNER, false, world);

            uint nno = 3;
            uint ndim = 2;
            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の値
            Complex[] value_c = new Complex[nno];
            // 要素節点の座標
            double[,] coord_c = new double[nno, ndim];
            // 要素行列
            double[,] eMMat = new double[nno, nno];
            double[,] eKXMat = new double[nno, nno];
            double[,] eKYMat = new double[nno, nno];

            CNodeAry.CNodeSeg ns_c_val = valField.GetNodeSeg(ELSEG_TYPE.CORNER, true, world);
            CNodeAry.CNodeSeg ns_c_co = valField.GetNodeSeg(ELSEG_TYPE.CORNER, false, world);

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);
                // 座標を取得
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    double[] tmpval = null;
                    ns_c_co.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == ndim);
                    for (int i = 0; i < tmpval.Length; i++)
                    {
                        coord_c[inoes, i] = tmpval[i];
                    }
                }

                // 節点の値を取って来る
                es_c_va.GetNodes(ielem, no_c);
                for (uint inoes = 0; inoes < nno; inoes++)
                {
                    Complex[] tmpval = null;
                    ns_c_val.GetValue(no_c[inoes], out tmpval);
                    System.Diagnostics.Debug.Assert(tmpval.Length == 1);
                    value_c[inoes] = tmpval[0];
                }

                // 節点座標
                double[] p1 = new double[ndim];
                double[] p2 = new double[ndim];
                double[] p3 = new double[ndim];
                for (int i = 0; i < ndim; i++)
                {
                    p1[i] = coord_c[0, i];
                    p2[i] = coord_c[1, i];
                    p3[i] = coord_c[2, i];
                }
                // 面積を求める
                double area = CKerEMatTri.TriArea(p1, p2, p3);

                // 形状関数の微分を求める
                double[,] dldx = null;
                double[] const_term = null;
                CKerEMatTri.TriDlDx(out dldx, out const_term, p1, p2, p3);

                // ∫(dLi/dx)(dLj/dx) dxdy
                double[,] integralDLDX = new double[3, 3];
                // ∫(dLi/dy)(dLj/dy) dxdy
                double[,] integralDLDY = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDX[ino, jno] = area * dldx[ino, 0] * dldx[jno, 0];
                    }
                }
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDY[ino, jno] = area * dldx[ino, 1] * dldx[jno, 1];
                    }
                }
                /*
                // ∫(dLi/dx)Lj dxdy
                double[,] integralDLDXL = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDXL[ino, jno] = area * dldx[ino, 0] / 3.0;
                    }
                }
                // ∫(dLi/dy)Lj dxdy
                double[,] integralDLDYL = new double[3, 3];
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        integralDLDYL[ino, jno] = area * dldx[ino, 1] / 3.0;
                    }
                }
                 */
                // ∫LiLj dxdy
                double[,] integralL = new double[3, 3]
                {
                    { area / 6.0 , area / 12.0, area / 12.0 },
                    { area / 12.0, area /  6.0, area / 12.0 },
                    { area / 12.0, area / 12.0, area /  6.0 },

                };

                // 要素剛性行列、要素質量行列を作る
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        // 要素剛性行列
                        eKXMat[ino, jno] = media.P[1, 1] * integralDLDX[ino, jno];
                        eKYMat[ino, jno] = media.P[0, 0] * integralDLDY[ino, jno];
                        // 要素質量行列
                        eMMat[ino, jno] = eps0 * myu0 * media.Q[2, 2] * integralL[ino, jno];
                    }
                }

                // PML媒質パラメータ
                double posXG = (p1[0] + p2[0] + p3[0]) / 3.0;
                if (isPmlYDirection)
                {
                    posXG = (p1[1] + p2[1] + p3[1]) / 3.0;
                }
                double sigmaX_e = 0.0;
                double c1_F_e = 0.0;
                double c1_G_e = 0.0;
                double c3_G_e = 0.0;
                GetPmlParameter(
                    posXG,
                    pmlStPosX,
                    pmlLength,
                    dt,
                    out sigmaX_e,
                    out c1_F_e,
                    out c1_G_e,
                    out c3_G_e);

                // 要素剛性行列にマージする
                double[,] work_eKXMat = eKXMat;
                double[,] work_eKYMat = eKYMat;
                if (isPmlYDirection)
                {
                    work_eKXMat = eKYMat;
                    work_eKYMat = eKXMat;
                }
                for (int ino = 0; ino < nno; ino++)
                {
                    uint iNodeNumber = no_c[ino];
                    if (!toSorted.ContainsKey(iNodeNumber)) continue;
                    int inoGlobal = (int)toSorted[iNodeNumber];
                    for (int jno = 0; jno < nno; jno++)
                    {
                        uint jNodeNumber = no_c[jno];
                        if (!toSorted.ContainsKey(jNodeNumber)) continue;
                        int jnoGlobal = (int)toSorted[jNodeNumber];

                        // clapack形式の行列格納方法で格納(バンド行列)
                        AMat._body[AMat.GetBufferIndex(inoGlobal, jnoGlobal)] +=
                            (sigmaX_e / eps0) * (1.0 / (2.0 * dt)) * eMMat[ino, jno]
                            + c1_F_e * newmarkBeta * work_eKYMat[ino, jno]
                            + c1_G_e * newmarkBeta * work_eKXMat[ino, jno];
                    }
                }
            }

            return true;
        }
Esempio n. 5
0
        ////////////////////////////////////////////////////////////////////////
        // 型
        ////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// ヘルムホルツの方程式 PML要素の全体行列の追加
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">値のフィールドID</param>
        /// <param name="pmlStPosX">PML媒質開始位置X座標</param>
        /// <param name="pmlLength">PML長さ</param>
        /// <param name="dt">時刻刻み幅</param>
        /// <param name="newmarkBeta">Newmark法 β</param>
        /// <param name="medias">媒質リスト</param>
        /// <param name="loopDic">ループID→ループ情報マップ</param>
        /// <param name="node_cnt">解析領域全体の節点数</param>
        /// <param name="free_node_cnt">解析領域全体の自由節点数(強制境界を除いた節点数)</param>
        /// <param name="toSorted">節点番号→ソート済み(強制境界を除いた)節点リストのインデックスマップ</param>
        /// <param name="AMat">全体行列</param>
        /// <returns></returns>
        public static bool AddPmlMat(
            CFieldWorld world,
            uint fieldValId,
            bool isPmlYDirection,
            double pmlStPosX,
            double pmlLength,
            double dt,
            double newmarkBeta,
            IList<MediaInfo> medias,
            Dictionary<uint, World.Loop> loopDic,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            ref MyDoubleBandMatrix AMat)
        {
            // 値のフィールドIDかチェック
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            // 値のフィールドを取得する
            CField valField = world.GetField(fieldValId);
            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return false;
            }

            // 要素アレイのリストを取得する
            IList<uint> aIdEA = valField.GetAryIdEA();
            foreach (uint eaId in aIdEA)
            {
                if (valField.GetInterpolationType(eaId, world) == INTERPOLATION_TYPE.TRI11)
                {
                    // 媒質を取得する
                    MediaInfo media = new MediaInfo();
                    {
                        // ループのIDのはず
                        uint lId = eaId;
                        if (loopDic.ContainsKey(lId))
                        {
                            World.Loop loop = loopDic[lId];
                            media = medias[loop.MediaIndex];
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    bool res = addPmlMat_EachElementAry(
                        world,
                        fieldValId,
                        isPmlYDirection,
                        pmlStPosX,
                        pmlLength,
                        dt,
                        newmarkBeta,
                        media,
                        eaId,
                        node_cnt,
                        free_node_cnt,
                        toSorted,
                        ref AMat
                        );
                    if (!res)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
Esempio n. 6
0
        //////////////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// ヘルムホルツの方程式 剛性行列、質量行列の作成
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">値のフィールドID</param>
        /// <param name="medias">媒質リスト</param>
        /// <param name="loopDic">ループID→ループ情報マップ</param>
        /// <param name="node_cnt">解析領域全体の節点数</param>
        /// <param name="free_node_cnt">解析領域全体の自由節点数(強制境界を除いた節点数)</param>
        /// <param name="toSorted">節点番号→ソート済み(強制境界を除いた)節点リストのインデックスマップ</param>
        /// <param name="KMat">剛性行列</param>
        /// <param name="MMat">質量行列</param>
        /// <returns></returns>
        public static bool MkHelmholtzMat(
            CFieldWorld world,
            uint fieldValId,
            IList<MediaInfo> medias,
            Dictionary<uint, World.Loop> loopDic,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            int subdiaSize,
            int superdiaSize,
            out MyDoubleBandMatrix KMat,
            out MyDoubleBandMatrix MMat)
        {
            KMat = null;
            MMat = null;

            // 値のフィールドIDかチェック
            if (!world.IsIdField(fieldValId))
            {
                return false;
            }
            // 値のフィールドを取得する
            CField valField = world.GetField(fieldValId);
            if (valField.GetFieldType() != FIELD_TYPE.ZSCALAR)
            {
                return false;
            }
            KMat = new MyDoubleBandMatrix((int)free_node_cnt, subdiaSize, superdiaSize);
            MMat = new MyDoubleBandMatrix((int)free_node_cnt, subdiaSize, superdiaSize);

            // 要素アレイのリストを取得する
            IList<uint> aIdEA = valField.GetAryIdEA();
            foreach (uint eaId in aIdEA)
            {
                if (valField.GetInterpolationType(eaId, world) == INTERPOLATION_TYPE.TRI11)
                {
                    // 媒質を取得する
                    MediaInfo media = new MediaInfo();
                    {
                        // ループのIDのはず
                        uint lId = eaId;
                        if (loopDic.ContainsKey(lId))
                        {
                            World.Loop loop = loopDic[lId];
                            media = medias[loop.MediaIndex];
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    bool res = MkHelmholtzMat_EachElementAry(
                        world,
                        fieldValId,
                        media,
                        eaId,
                        node_cnt,
                        free_node_cnt,
                        toSorted,
                        ref KMat,
                        ref MMat
                        );
                    if (!res)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
Esempio n. 7
0
        // {x} = [A]{v}
        public static double[] product(MyDoubleBandMatrix matAB, double[] vec, int vec_row)
        {
            int a_row = matAB.RowSize;
            int a_col = matAB.ColumnSize;
            int subdiaSize = matAB.SubdiaSize;
            int superdiaSize = matAB.SuperdiaSize;
            System.Diagnostics.Debug.Assert(a_col == vec_row);
            double[] retVec = new double[a_row];

            /*
            for (int i = 0; i < a_row; i++)
            {
                retVec[i] = 0.0;
                for (int k = 0; k < a_col; k++)
                {
                    if (Math.Max(0, k - superdiaSize) <= i && i <= Math.Min((a_row - 1), k + subdiaSize))
                    {
                        retVec[i] += matAB._body[matAB.GetBufferIndex(i, k)] * vec[k];
                    }
                }
            }
             */

            for (int k = 0; k < a_col; k++)
            {
                // 対角成分
                retVec[k] += matAB._body[matAB.GetBufferIndex(k, k)] * vec[k];

                // subdiagonal成分
                if (k < a_col - 1)
                {
                    for (int i = k + 1; i <= k + subdiaSize && i < a_row; i++)
                    {
                        retVec[i] += matAB._body[matAB.GetBufferIndex(i, k)] * vec[k];
                    }
                }
                if (k > 0)
                {
                    for (int i = k - 1; i >= k - superdiaSize && i >= 0; i--)
                    {
                        retVec[i] += matAB._body[matAB.GetBufferIndex(i, k)] * vec[k];
                    }
                }
            }

            return retVec;
        }
Esempio n. 8
0
        // バンド行列
        public static double[] matrix_Inverse_NoCopy(MyDoubleBandMatrix matAB)
        {
            int n = matAB.RowSize;
            System.Diagnostics.Debug.Assert(matAB.RowSize == matAB.ColumnSize);

            // バンド行列
            double[] matAB_ = matAB._body; // コピーしない
            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 + i * n] = 1.0;
            }
            // [A][X] = [B]
            //  [B]の内容が書き換えられるので、matXを新たに生成せず、matBを出力に指定している
            int x_row = 0;
            int x_col = 0;
            int kl = matAB.SubdiaSize;
            int ku = matAB.SuperdiaSize;
            double[] matX = null;
            KrdLab.clapack.FunctionExt.dgbsv(ref matX, ref x_row, ref x_col, matAB_, n, n, kl, ku, matB_, n, n);

            return matX;
        }
Esempio n. 9
0
        /// <summary>
        /// FEM行列の作成
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="newmarkBeta"></param>
        /// <param name="timeDelta"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPmlLoopIdList"></param>
        /// <param name="PmlStPosXList"></param>
        /// <param name="PmlLengthList"></param>
        /// <param name="FieldPortSrcBcId"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="node_cnt"></param>
        /// <param name="sortedNodes"></param>
        /// <param name="toSorted"></param>
        /// <param name="sortedNodes_PortSrc"></param>
        /// <param name="toSorted_PortSrc"></param>
        /// <param name="KMat"></param>
        /// <param name="MMat"></param>
        /// <param name="QbMatSrc"></param>
        /// <param name="betaXSrc"></param>
        /// <param name="profileSrc"></param>
        /// <param name="AMat"></param>
        /// <param name="Ez"></param>
        /// <param name="Ez_Prev"></param>
        /// <param name="Ez_Prev2"></param>
        /// <param name="EzTimeAryPort1"></param>
        /// <param name="EzTimeAryPort2"></param>
        /// <returns></returns>
        private static bool mkFEMMat(
            int probNo,
            double newmarkBeta,
            double timeDelta,
            double NormalizedFreqSrc,
            double WaveguideWidth,
            bool isPCWaveguide,
            double latticeA,
            WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList<uint> FieldPmlLoopIdList,
            IList<bool> IsPmlYDirectionList,
            IList<double> PmlStPosXList,
            IList<double> PmlLengthList,
            uint FieldPortSrcBcId,
            IList<uint> VIdRefList,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref int node_cnt,
            ref IList<uint> sortedNodes,
            ref Dictionary<uint, uint> toSorted,
            ref IList<uint> sortedNodes_PortSrc,
            ref Dictionary<uint, uint> toSorted_PortSrc,
            ref MyDoubleBandMatrix KMat,
            ref MyDoubleBandMatrix MMat,
            ref double[] QbMatSrc,
            ref double betaXSrc,
            ref double[] profileSrc,
            ref double[] AMat,
            ref double[] Ez,
            ref double[] Ez_Prev,
            ref double[] Ez_Prev2,
            ref double[][][][] W2_F_e_List,
            ref double[][][][] W2_G_e_List,
            ref IList<double> EzTimeAryPort1,
            ref IList<double> EzTimeAryPort2
            )
        {
            System.Diagnostics.Debug.WriteLine("mkFEMMat");
            bool success = false;
            node_cnt = 0;
            sortedNodes = null;
            toSorted = null;
            sortedNodes_PortSrc = null;
            toSorted_PortSrc = null;
            KMat = null;
            MMat = null;
            QbMatSrc = null;
            betaXSrc = 0.0;
            profileSrc = null;
            AMat = null;
            Ez = null;
            Ez_Prev = null;
            Ez_Prev2 = null;
            W2_F_e_List = null;
            W2_G_e_List = null;
            if (EzTimeAryPort1 != null)
            {
                EzTimeAryPort1.Clear();
            }
            if (EzTimeAryPort2 != null)
            {
                EzTimeAryPort2.Clear();
            }

            try
            {
                // 全節点数を取得する
                //uint node_cnt = 0;
                node_cnt = 0;
                //node_cnt = WgUtilForPeriodicEigen.GetNodeCnt(World, FieldLoopId);
                double[][] coord_c_all = null;
                {
                    uint[] no_c_all_tmp = null;
                    Dictionary<uint, uint> to_no_all_tmp = null;
                    double[][] coord_c_all_tmp = null;
                    WgUtilForTD.GetLoopCoordList(World, FieldLoopId, out no_c_all_tmp, out to_no_all_tmp, out coord_c_all_tmp);
                    node_cnt = no_c_all_tmp.Length;

                    // 座標リストを節点番号順に並び替えて格納
                    coord_c_all = new double[node_cnt][];
                    for (int ino = 0; ino < node_cnt; ino++)
                    {
                        uint nodeNumber = no_c_all_tmp[ino];
                        double[] coord = coord_c_all_tmp[ino];
                        coord_c_all[nodeNumber] = coord;
                    }
                }

                System.Diagnostics.Debug.WriteLine("node_cnt: {0}", node_cnt);

                // 境界の節点リストを取得する
                uint[] no_c_all_fieldForceBcId = null;
                Dictionary<uint, uint> to_no_boundary_fieldForceBcId = null;
                if (FieldForceBcId != 0)
                {
                    WgUtil.GetBoundaryNodeList(World, FieldForceBcId, out no_c_all_fieldForceBcId, out to_no_boundary_fieldForceBcId);
                }
                // ポート数
                int portCnt = FieldPmlLoopIdList.Count;
                uint[] no_c_all_fieldPortSrcBcId = null;
                Dictionary<uint, uint> to_no_boundary_fieldPortSrcBcId = null;

                {
                    uint workFieldPortBcId = FieldPortSrcBcId;
                    uint[] work_no_c_all_fieldPortBcId = null;
                    Dictionary<uint, uint> work_to_no_boundary_fieldPortBcId = null;

                    WgUtil.GetBoundaryNodeList(World, workFieldPortBcId, out work_no_c_all_fieldPortBcId, out work_to_no_boundary_fieldPortBcId);

                    no_c_all_fieldPortSrcBcId = work_no_c_all_fieldPortBcId;
                    to_no_boundary_fieldPortSrcBcId = work_to_no_boundary_fieldPortBcId;
                }
                //強制境界を除いた節点
                //IList<IList<uint>> sortedNodes_Port_List = new List<IList<uint>>();
                //IList<Dictionary<uint, uint>> toSorted_Port_List = new List<Dictionary<uint, uint>>();
                sortedNodes_PortSrc = null;
                toSorted_PortSrc = null;
                {
                    uint[] no_c_all_fieldPortBcId = no_c_all_fieldPortSrcBcId;
                    IList<uint> sortedNodes_Port = new List<uint>();
                    Dictionary<uint, uint> toSorted_Port = new Dictionary<uint, uint>();
                    int nodeCntB = no_c_all_fieldPortBcId.Length;
                    for (int ino = 0; ino < nodeCntB; ino++)
                    {
                        uint nodeNumber = no_c_all_fieldPortBcId[ino];
                        if (FieldForceBcId != 0)
                        {
                            // 強制境界を除く
                            if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumber)) continue;
                        }
                        sortedNodes_Port.Add(nodeNumber);
                        toSorted_Port.Add(nodeNumber, (uint)(sortedNodes_Port.Count - 1));
                    }
                    sortedNodes_PortSrc = sortedNodes_Port;
                    toSorted_PortSrc = toSorted_Port;
                }

                // 節点のソート
                //IList<uint> sortedNodes = new List<uint>();
                //Dictionary<uint, int> toSorted = new Dictionary<uint, int>();
                sortedNodes = new List<uint>();
                toSorted = new Dictionary<uint, uint>();
                for (uint nodeNumber = 0; nodeNumber < node_cnt; nodeNumber++)
                {
                    if (FieldForceBcId != 0)
                    {
                        // 強制境界を除く
                        if (to_no_boundary_fieldForceBcId.ContainsKey(nodeNumber)) continue;
                    }
                    sortedNodes.Add(nodeNumber);
                    toSorted.Add(nodeNumber, (uint)(sortedNodes.Count - 1));
                }
                uint free_node_cnt = (uint)sortedNodes.Count;

                //------------------------------------------------------
                // バンド行列パターンを作成する
                //------------------------------------------------------
                // 非0パターンを作成する
                bool[,] matPattern = null;
                WgUtilForTD.MkMatPattern(
                    World,
                    FieldLoopId,
                    Medias,
                    LoopDic,
                    (uint)node_cnt,
                    free_node_cnt,
                    toSorted,
                    out matPattern);
                /*
                int rowColSize = 0;
                int subdiaSize = 0;
                int superdiaSize = 0;
                WgUtilForTD.GetBandMatrixSubDiaSizeAndSuperDiaSize(
                    matPattern,
                    out rowColSize,
                    out subdiaSize,
                    out superdiaSize
                    );
                System.Diagnostics.Debug.Assert(rowColSize == free_node_cnt);
                 */
                // バンド行列のバンド幅を縮小する
                IList<uint> optNodesGlobal = null;
                Dictionary<uint, uint> toOptNodes = null;
                WgUtilForTD.GetOptBandMatNodes(
                    matPattern,
                    sortedNodes,
                    out optNodesGlobal,
                    out toOptNodes);
                bool[,] matPatternOpt = new bool[free_node_cnt, free_node_cnt];
                for (int i = 0; i < free_node_cnt; i++)
                {
                    uint inoGlobal = sortedNodes[i];
                    uint inoOpt = toOptNodes[inoGlobal];
                    for (int j = 0; j < free_node_cnt; j++)
                    {
                        uint jnoGlobal = sortedNodes[j];
                        uint jnoOpt = toOptNodes[jnoGlobal];
                        matPatternOpt[inoOpt, jnoOpt] = matPattern[i, j];
                    }
                }
                int rowColSizeOpt = 0;
                int subdiaSizeOpt = 0;
                int superdiaSizeOpt = 0;
                WgUtilForTD.GetBandMatrixSubDiaSizeAndSuperDiaSize(
                    matPatternOpt,
                    out rowColSizeOpt,
                    out subdiaSizeOpt,
                    out superdiaSizeOpt
                    );
                System.Diagnostics.Debug.WriteLine("rowColSizeOpt : {0}", rowColSizeOpt);
                System.Diagnostics.Debug.WriteLine("subdiaSizeOpt : {0}", subdiaSizeOpt);
                System.Diagnostics.Debug.WriteLine("superdiaSizeOpt : {0}", superdiaSizeOpt);
                // ソート済み節点を最適化したものに更新
                sortedNodes = optNodesGlobal;
                toSorted = toOptNodes;

                WgUtil.GC_Collect();

                //------------------------------------------------------
                // 剛性行列、質量行列を作成
                //------------------------------------------------------
                WgUtilForTD.MkHelmholtzMat(
                    World,
                    FieldLoopId,
                    Medias,
                    LoopDic,
                    (uint)node_cnt,
                    free_node_cnt,
                    toSorted,
                    subdiaSizeOpt,
                    superdiaSizeOpt,
                    out KMat,
                    out MMat);

                //------------------------------------------------------
                // モード分布計算
                //------------------------------------------------------
                // 波数
                double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
                // 波長
                double waveLengthSrc = 2.0 * pi / k0Src;
                // 周波数
                double freqSrc = c0 / waveLengthSrc;
                // 角周波数
                double omegaSrc = 2.0 * pi * freqSrc;

                bool retPort = false;

                // 境界の界に導波路開口条件を追加
                {
                    uint workFieldPortBcId = FieldPortSrcBcId;
                    double[,] ryy_1d_port1 = null;
                    double[,] txx_1d_port1 = null;
                    double[,] uzz_1d_port1 = null;
                    Complex[] eigen_values_port1 = null;
                    Complex[,] eigen_vecs_port1 = null;
                    retPort = WgUtil.SolvePortWaveguideEigen(
                        waveLengthSrc,
                        WaveModeDv,
                        World,
                        workFieldPortBcId,
                        no_c_all_fieldForceBcId,
                        Medias,
                        EdgeDic,
                        out ryy_1d_port1,
                        out txx_1d_port1,
                        out uzz_1d_port1,
                        out eigen_values_port1,
                        out eigen_vecs_port1);

                    // 境界節点数 (強制境界を含む)
                    uint[] no_c_all_fieldPortBcId = no_c_all_fieldPortSrcBcId;
                    int nodeCntB = no_c_all_fieldPortBcId.Length;
                    Dictionary<uint, uint> toSorted_Port = toSorted_PortSrc;
                    // 強制境界を除いた節点数
                    int nodeCntB_f = toSorted_Port.Count;

                    // 境界質量行列
                    double[] ryy_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(ryy_1d_port1);
                    double[] txx_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(txx_1d_port1);
                    double[] uzz_1d_port1_Buffer = MyMatrixUtil.matrix_ToBuffer(uzz_1d_port1);
                    double[] ryy_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    double[] txx_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    double[] uzz_1d_port1_Buffer_f = new double[nodeCntB_f * nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB; ino++)
                    {
                        uint ino_global = no_c_all_fieldPortBcId[ino];
                        if (!toSorted_Port.ContainsKey(ino_global))
                        {
                            continue;
                        }
                        uint ino_f = toSorted_Port[ino_global];
                        for (int jno = 0; jno < nodeCntB; jno++)
                        {
                            uint jno_global = no_c_all_fieldPortBcId[jno];
                            if (!toSorted_Port.ContainsKey(jno_global))
                            {
                                continue;
                            }
                            uint jno_f = toSorted_Port[jno_global];
                            ryy_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = ryy_1d_port1_Buffer[ino + nodeCntB * jno];
                            txx_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = txx_1d_port1_Buffer[ino + nodeCntB * jno];
                            uzz_1d_port1_Buffer_f[ino_f + nodeCntB_f * jno_f] = uzz_1d_port1_Buffer[ino + nodeCntB * jno];
                        }
                    }
                    QbMatSrc = ryy_1d_port1_Buffer_f;

                    // 基本モード
                    uint imode = 0;
                    if (isPCWaveguide)
                    {
                        /*
                        // TEST
                        System.Diagnostics.Debug.WriteLine("!!!!!!!!!!!!!!! search DBR mode");
                        Console.WriteLine("!!!!!!!!!!!!!!! search DBR mode");
                        for (int imode_tmp = 0; imode_tmp < eigen_values_port1.Length; imode_tmp++)
                        {
                            if (Math.Abs(eigen_values_port1[imode_tmp].Real) >= Constants.PrecisionLowerLimit
                                && Math.Abs(eigen_values_port1[imode_tmp].Real / k0Src) < 1.0)
                            {
                                imode = (uint)imode_tmp;
                                Console.WriteLine("DBR mode: imode = {0}", imode);
                                System.Diagnostics.Debug.WriteLine("DBR mode: imode = {0}", imode);
                                break;
                            }
                        }
                         */
                    }
                    Complex betam = eigen_values_port1[imode];
                    Complex[] fmVec = MyMatrixUtil.matrix_GetRowVec(eigen_vecs_port1, (int)imode); // 強制境界を含む
                    // 実数部を取得する
                    double betamReal = betam.Real;
                    double[] fmVecReal_f = new double[nodeCntB_f]; // 強制境界を除く
                    for (int ino = 0; ino < fmVec.Length; ino++)
                    {
                        uint ino_global = no_c_all_fieldPortBcId[ino];
                        if (!toSorted_Port.ContainsKey(ino_global))
                        {
                            continue;
                        }
                        uint ino_f = toSorted_Port[ino_global];

                        fmVecReal_f[ino_f] = fmVec[ino].Real;
                        //System.Diagnostics.Debug.WriteLine("{0}", fmVecReal_f[ino_f]);
                    }
                    betaXSrc = betamReal;
                    profileSrc = fmVecReal_f;
                    if (Math.Abs(betamReal) < Constants.PrecisionLowerLimit)
                    {
                        return false;
                    }
                }

                /////////////////////////////////////////////////////////

                //------------------------------------------------------
                // 電界
                //-----------------------------------------------------
                uint free_node_cnt_all = free_node_cnt;
                Ez = new double[free_node_cnt_all];
                Ez_Prev = new double[free_node_cnt_all];
                Ez_Prev2 = new double[free_node_cnt_all];
                W2_F_e_List = new double[portCnt][][][];
                W2_G_e_List = new double[portCnt][][][];

                //------------------------------------------------------
                // 全体係数行列の作成
                //------------------------------------------------------
                MyDoubleBandMatrix AMatB = new MyDoubleBandMatrix((int)free_node_cnt_all, subdiaSizeOpt, superdiaSizeOpt);
                double dt = timeDelta;
                for (int bufferIndex = 0; bufferIndex < AMatB._body.Length; bufferIndex++)
                {
                    AMatB._body[bufferIndex] =
                        (1.0 / (dt * dt)) * MMat._body[bufferIndex]
                        + newmarkBeta * KMat._body[bufferIndex];
                }

                // PML領域内のみの係数行列を加算する
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    uint fieldPmlLoopId = FieldPmlLoopIdList[portIndex];
                    bool isPmlYDirection = IsPmlYDirectionList[portIndex];
                    double pmlStPosX = PmlStPosXList[portIndex];
                    double pmlLength = PmlLengthList[portIndex];
                    WgUtilForTDPml.AddPmlMat(
                        World,
                        fieldPmlLoopId,
                        isPmlYDirection,
                        pmlStPosX,
                        pmlLength,
                        dt,
                        newmarkBeta,
                        Medias,
                        LoopDic,
                        (uint)node_cnt,
                        free_node_cnt,
                        toSorted,
                        ref AMatB
                        );
                }

                // 逆行列を計算
                System.Diagnostics.Debug.WriteLine("calc [A]-1");
                Console.Write("calc [A]-1 ....");
                AMat = MyMatrixUtil.matrix_Inverse_NoCopy(AMatB);
                Console.WriteLine(" done");

                WgUtil.GC_Collect();

                success = true;

            }
            catch (Exception exception)
            {
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                success = false;
            }
            System.Diagnostics.Debug.WriteLine("mkFEMMat done ret: {0}", success);
            System.Diagnostics.Debug.WriteLine("dt:{0}", timeDelta);
            return success;
        }
Esempio n. 10
0
        /// <summary>
        /// 問題を解く
        /// </summary>
        /// <param name="probNo">問題番号</param>
        /// <param name="timeIndex">時刻のインデックス</param>
        /// <param name="timeLoopCnt">時間計算回数</param>
        /// <param name="newmarkBeta">Newmarkβ法のβ</param>
        /// <param name="timeDelta">時刻刻み</param>
        /// <param name="gaussianT0">ガウシアンパルスの遅延時間</param>
        /// <param name="gaussianTp">ガウシアンパルスの時間幅</param>
        /// <param name="NormalizedFreqSrc">励振するモードの規格化周波数</param>
        /// <param name="VIdRefList">観測点の頂点ID(= 節点番号 + 1)</param>
        /// <param name="NormalizedFreq1">開始規格化周波数</param>
        /// <param name="NormalizedFreq2">終了規格化周波数</param>
        /// <param name="initFlg">カメラ初期化フラグ</param>
        /// <param name="WaveguideWidth">導波路幅</param>
        /// <param name="WaveModeDv">波のモード区分</param>
        /// <param name="World">ワールド座標系</param>
        /// <param name="FieldValId">値のフィールドID</param>
        /// <param name="FieldLoopId">ループのフィールドID</param>
        /// <param name="FieldForceBcId">強制境界のフィールドID</param>
        /// <param name="FieldPortBcIdList">ポート1、ポート2、励振面の境界のフィールドID</param>
        /// <param name="Medias">媒質リスト</param>
        /// <param name="LoopDic">ループID→ループ情報マップ</param>
        /// <param name="EdgeDic">エッジID→エッジ情報マップ</param>
        /// <param name="IsShowAbsField">絶対値表示する?</param>
        /// <param name="node_cnt">節点数(強制境界を含む)</param>
        /// <param name="sortedNodes">ソート済み節点番号リスト</param>
        /// <param name="toSorted">節点番号→ソート済み節点インデックスマップ</param>
        /// <param name="sortedNodes_Port_List">境界のソート済み節点番号リスト(ポート1,ポート2,励振面)</param>
        /// <param name="toSorted_Port_List">境界の節点番号→ソート済み節点インデックスマップ(ポート1,ポート2,励振面)</param>
        /// <param name="KMat">剛性行列</param>
        /// <param name="MMat">質量行列</param>
        /// <param name="QbMatSrc">境界質量行列(励振面)</param>
        /// <param name="betaXSrc">境界の伝搬定数(励振面)</param>
        /// <param name="profileSrc">境界のモード分布(励振面)</param>
        /// <param name="AMat">係数行列(逆行列)</param>
        /// <param name="Ez">電界分布(現在)</param>
        /// <param name="Ez_Prev">電界分布(1つ前)</param>
        /// <param name="Ez_Prev2">電界分布(2つ前)</param>
        /// <param name="EzTimeAryPort1">ポート1観測点の電界リスト(時間変化)</param>
        /// <param name="EzTimeAryPort2">ポート2観測点の電界リスト(時間変化)</param>
        /// <param name="DrawerAry">描画オブジェクトアレイ</param>
        /// <param name="Camera">カメラ</param>
        /// <returns></returns>
        private static bool solveProblem(
            int probNo,
            bool IsSolveStraightWg,
            ref int timeIndex,
            int timeLoopCnt,
            double newmarkBeta,
            double timeDelta,
            double gaussianT0,
            double gaussianTp,
            double NormalizedFreqSrc,
            double NormalizedFreq1,
            double NormalizedFreq2,
            bool initFlg,
            double WaveguideWidth,
            bool isPCWaveguide,
            double latticeA,
            WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            uint FieldValId,
            uint FieldLoopId,
            uint FieldForceBcId,
            IList<uint> FieldPmlLoopIdList,
            IList<bool> IsPmlYDirectionList,
            IList<double> PmlStPosXList,
            IList<double> PmlLengthList,
            uint FieldPortSrcBcId,
            IList<uint> VIdRefList,
            IList<MediaInfo> Medias,
            Dictionary<uint, wg2d.World.Loop> LoopDic,
            Dictionary<uint, wg2d.World.Edge> EdgeDic,
            bool IsShowAbsField,
            int node_cnt,
            IList<uint> sortedNodes,
            Dictionary<uint, uint> toSorted,
            IList<uint> sortedNodes_PortSrc,
            Dictionary<uint, uint> toSorted_PortSrc,
            MyDoubleBandMatrix KMat,
            MyDoubleBandMatrix MMat,
            double[] QbMatSrc,
            double betaXSrc,
            double[] profileSrc,
            double[] AMat,
            ref double[] Ez,
            ref double[] Ez_Prev,
            ref double[] Ez_Prev2,
            ref double[][][][] W2_F_e_List,
            ref double[][][][] W2_G_e_List,
            ref IList<double> EzTimeAryPort1,
            ref IList<double> EzTimeAryPort2,
            ref CDrawerArrayField DrawerAry,
            CCamera Camera)
        {
            //long memorySize1 = GC.GetTotalMemory(false);
            //Console.WriteLine("    total memory: {0}", memorySize1);

            bool success = false;

            // ポート数
            int portCnt = FieldPmlLoopIdList.Count;

            // 時刻の取得
            if (timeIndex == -1)
            {
                return success;
            }
            if (timeIndex >= timeLoopCnt)
            {
                timeIndex = -1;
                return success;
            }
            // 以下curTimeIndexに対する計算
            double curTime = timeIndex * timeDelta;

            double dt = timeDelta;

            try
            {
                // ワールド座標系のフィールド値をクリア
                WgUtil.ClearFieldValues(World, FieldValId);

                // 励振源のパラメータ
                // 波数
                double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
                // 波長
                double waveLengthSrc = 2.0 * pi / k0Src;
                // 周波数
                double freqSrc = c0 / waveLengthSrc;
                // 角周波数
                double omegaSrc = 2.0 * pi * freqSrc;

                //--------------------------------------------------------------
                // 電界
                //--------------------------------------------------------------
                uint free_node_cnt = (uint)sortedNodes.Count;
                uint free_node_cnt_all = free_node_cnt;
                System.Diagnostics.Debug.Assert(Ez.Length == free_node_cnt_all);

                Ez_Prev.CopyTo(Ez_Prev2, 0);
                Ez.CopyTo(Ez_Prev, 0);
                for (int ino = 0; ino < free_node_cnt_all; ino++)
                {
                    Ez[ino] = 0.0;
                }

                //--------------------------------------------------------------
                // 残差
                //--------------------------------------------------------------
                double[] vec_MMat = new double[free_node_cnt];
                double[] vec_KMat = new double[free_node_cnt];
                for (int ino = 0; ino < free_node_cnt; ino++)
                {
                    vec_MMat[ino] = (2.0 / (dt * dt)) * Ez_Prev[ino] - (1.0 / (dt * dt)) * Ez_Prev2[ino];
                    vec_KMat[ino] = -(1.0 - 2.0 * newmarkBeta) * Ez_Prev[ino] - newmarkBeta * Ez_Prev2[ino];
                }
                vec_MMat = MyMatrixUtil.product(
                    MMat,
                    vec_MMat, (int)free_node_cnt);
                vec_KMat = MyMatrixUtil.product(
                    KMat,
                    vec_KMat, (int)free_node_cnt);

                double[] resVec = MyMatrixUtil.plus(vec_MMat, vec_KMat);
                System.Diagnostics.Debug.Assert(resVec.Length == free_node_cnt_all);

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    uint workFieldPmlLoopId =FieldPmlLoopIdList[portIndex];
                    bool workIsPmlYDirection = IsPmlYDirectionList[portIndex];
                    double workPmlPosX = PmlStPosXList[portIndex];
                    double workPmlLength = PmlLengthList[portIndex];
                    double[][][] work_w2_F_e_list = W2_F_e_List[portIndex];
                    double[][][] work_w2_G_e_list = W2_G_e_List[portIndex];
                    WgUtilForTDPml.AddPmlResVec(
                        timeIndex,
                        World,
                        workFieldPmlLoopId,
                        workIsPmlYDirection,
                        workPmlPosX,
                        workPmlLength,
                        dt,
                        newmarkBeta,
                        Medias,
                        LoopDic,
                        (uint)node_cnt,
                        free_node_cnt,
                        toSorted,
                        Ez_Prev,
                        Ez_Prev2,
                        ref work_w2_F_e_list,
                        ref work_w2_G_e_list,
                        ref resVec
                        );
                    // 再格納
                    W2_F_e_List[portIndex] = work_w2_F_e_list;
                    W2_G_e_List[portIndex] = work_w2_G_e_list;
                }

                //--------------------------------------------------------------
                // 励振源
                //--------------------------------------------------------------
                {
                    int portIndex = portCnt; // ポートリストの最後の要素が励振境界
                    // 境界の節点番号リスト
                    IList<uint> sortedNodes_Port = sortedNodes_PortSrc;
                    // 境界の節点数(強制境界を含まない)
                    int nodeCntB_f = sortedNodes_Port.Count;
                    double[] QbMat = QbMatSrc;

                    if (isPCWaveguide)
                    {

                        //////////
                        //TEST 中央に点波源を置く
                        profileSrc = new double[profileSrc.Length];
                        profileSrc[profileSrc.Length / 2] = 1.0;

                        /*
                        ///////////
                        // TEST: 欠陥部を平面波励振する
                        //betaXSrc = k0Src;
                        profileSrc = new double[profileSrc.Length];
                        for (int i = 0; i < 5; i++)
                        {
                            profileSrc[profileSrc.Length / 2 - 2 + i] = 1.0;
                        }
                         */
                    }

                    double srcF1 = 0.0;
                    double srcF2 = 0.0;
                    double srcF0 = 0.0;

                    int n = timeIndex;
                    // ガウシアンパルス
                    if ((n * dt) <= (2.0 * gaussianT0 + dt))
                    {
                        /*
                        // ガウシアンパルス
                        srcF1 = Math.Exp(-1.0 * ((n + 1) * dt - gaussianT0) * ((n + 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF2 = Math.Exp(-1.0 * ((n - 1) * dt - gaussianT0) * ((n - 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF0 = Math.Exp(-1.0 * ((n) * dt - gaussianT0) * ((n) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                         */

                        // 正弦波変調ガウシアンパルス
                        srcF1 = Math.Cos(omegaSrc * ((n + 1) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n + 1) * dt - gaussianT0) * ((n + 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF2 = Math.Cos(omegaSrc * ((n - 1) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n - 1) * dt - gaussianT0) * ((n - 1) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));
                        srcF0 = Math.Cos(omegaSrc * ((n) * dt - gaussianT0))
                                * Math.Exp(-1.0 * ((n) * dt - gaussianT0) * ((n) * dt - gaussianT0) / (2.0 * gaussianTp * gaussianTp));

                    }

                    /*
                    // 正弦波
                    srcF1 = Math.Sin(omegaSrc * (n + 1) * dt);
                    srcF2 = Math.Sin(omegaSrc * (n - 1) * dt);
                    srcF0 = Math.Sin(omegaSrc * (n) * dt);
                     */

                    // 境界積分
                    double[] srcdFdt = new double[nodeCntB_f];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        double normalizeFactor = -1.0;
                        srcdFdt[ino] = normalizeFactor * profileSrc[ino] * (srcF1 - srcF2) / (2.0 * dt);
                    }
                    double vpx = omegaSrc / betaXSrc;
                    double[] vec_QbMat = MyMatrixUtil.product((-2.0 / vpx), srcdFdt);
                    vec_QbMat = MyMatrixUtil.product_native(
                        QbMat, nodeCntB_f, nodeCntB_f,
                        vec_QbMat, nodeCntB_f);
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            // 強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        resVec[ino_f] += vec_QbMat[ino];
                    }

                    /*
                    // 領域積分
                    double[] srcdFdt2_f = new double[free_node_cnt];
                    double[] srcF_f = new double[free_node_cnt];
                    for (int ino = 0; ino < nodeCntB_f; ino++)
                    {
                        uint ino_global = sortedNodes_Port[ino];
                        if (!toSorted.ContainsKey(ino_global))
                        {
                            // 強制境界は除外済み
                            System.Diagnostics.Debug.Assert(false);
                            continue;
                        }
                        int ino_f = (int)toSorted[ino_global];
                        double normalizeFactor = -1.0;
                        //double normalizeFactor = -omegaSrc * myu0 / betaXSrc;
                        srcF_f[ino_f] = normalizeFactor * profileSrc[ino] * srcF0;
                        srcdFdt2_f[ino_f] = normalizeFactor * profileSrc[ino] * (srcF1 - 2.0 * srcF0 + srcF2) / (dt * dt);
                    }
                    double[] vec_MMatSrc = MyMatrixUtil.product_native(
                        MMat, (int)free_node_cnt, (int)free_node_cnt,
                        srcdFdt2_f, (int)free_node_cnt
                        );
                    double[] vec_KMatSrc = MyMatrixUtil.product_native(
                        KMat, (int)free_node_cnt, (int)free_node_cnt,
                        srcF_f, (int)free_node_cnt
                        );
                    for (int ino = 0; ino < free_node_cnt; ino++)
                    {
                        resVec[ino] += vec_MMatSrc[ino] + vec_KMatSrc[ino];
                    }
                     */
                }

                //------------------------------------------------------------------
                // Ezを求める
                //------------------------------------------------------------------
                /*
                // 連立方程式を解く
                {
                    int matLen = (int)free_node_cnt_all;
                    double[] A = new double[matLen * matLen];
                    AMat.CopyTo(A, 0); // コピーを取る
                    double[] B = resVec;

                    double[] X = null;
                    int x_row = matLen;
                    int x_col = 1;
                    int a_row = matLen;
                    int a_col = matLen;
                    int b_row = matLen;
                    int b_col = 1;
                    KrdLab.clapack.Function.dgesv(ref X, ref x_row, ref x_col, A, a_row, a_col, B, b_row, b_col);

                    X.CopyTo(Ez, 0);
                }
                 */

                // 逆行列を用いる
                Ez = MyMatrixUtil.product_native(
                    AMat, (int)free_node_cnt_all, (int)free_node_cnt_all,
                    resVec, (int)free_node_cnt_all
                    );

                // 観測点
                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    // 頂点IDから1を引いたものが節点番号
                    uint nodeNumber = VIdRefList[portIndex] - 1;
                    int ino_f = (int)toSorted[nodeNumber];
                    double fVal = Ez[ino_f];
                    if (portIndex == 0)
                    {
                        if (EzTimeAryPort1 != null)
                        {
                            EzTimeAryPort1.Add(fVal);
                        }
                    }
                    else if (portIndex == 1)
                    {
                        if (EzTimeAryPort2 != null)
                        {
                            EzTimeAryPort2.Add(fVal);
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                }

                // 解ベクトルをワールド座標系にセット
                WgUtil.SetFieldValueForDisplay(World, FieldValId, Ez, toSorted);

                if ((timeIndex + 1) % 50 == 0)
                {
                    Console.WriteLine("{0}", (timeIndex + 1));
                }

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

                    // 表示位置調整
                    setupPanAndScale(probNo, IsSolveStraightWg, Camera);
                }
                success = true;

            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
                System.Diagnostics.Debug.WriteLine(exception.Message + " " + exception.StackTrace);
            }
            return success;
        }