Ejemplo n.º 1
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;
        }
Ejemplo n.º 2
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;
        }