/// <summary>
        /// ヘルムホルツの方程式 Sommerfelt放射条件(要素アレイ単位)
        /// </summary>
        /// <param name="ls"></param>
        /// <param name="waveLength"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="eaId"></param>
        /// <param name="tmpBuffer"></param>
        /// <returns></returns>
        private static bool AddLinSys_SommerfeltRadiationBC_EachElementAry(CZLinearSystem ls, double waveLength, CFieldWorld world, uint fieldValId, uint eaId, int[] tmpBuffer)
        {
            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.LINE);
            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 = 2;
            // 座標の次元
            uint ndim = 2;
            // 要素節点の全体節点番号
            uint[] no_c = new uint[nno];
            // 要素節点の値
            Complex[] value_c = new Complex[nno];
            // 要素節点の座標
            double[][] coord_c = new double[nno][];
            for (int inoes = 0; inoes < nno; inoes++)
            {
                coord_c[inoes] = new double[ndim];
            }
            // 要素剛性行列 (i, j) --> (i * RowSize + j)
            Complex[] ematBuffer = new Complex[nno * nno];
            // 要素節点等価内力、外力、残差ベクトル
            Complex[] eres_c = new Complex[nno];
            // 要素剛性行列(コーナ-コーナー)
            CZMatDia_BlkCrs_Ptr mat_cc = ls.GetMatrixPtr(fieldValId, ELSEG_TYPE.CORNER, world);
            // 要素残差ベクトル(コーナー)
            CZVector_Blk_Ptr res_c = ls.GetResidualPtr(fieldValId, ELSEG_TYPE.CORNER, world);

            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 elen = Math.Sqrt((coord_c[0][0] - coord_c[1][0]) * (coord_c[0][0] - coord_c[1][0]) + (coord_c[0][1] - coord_c[1][1]) * (coord_c[0][1] - coord_c[1][1]));

                double k = 2.0 * pi / waveLength;
                Complex tmp_val1 = (k / 6.0 * elen) * (new Complex(0, 1));
                Complex tmp_val2 = -1 / (2.0 * elen * k) * (new Complex(0, 1));
                //emat[0, 0]
                ematBuffer[0] = tmp_val1 * 2 + tmp_val2;
                //emat[0, 1]
                ematBuffer[1] = tmp_val1 - tmp_val2;
                //emat[1, 0]
                ematBuffer[nno] = tmp_val1 - tmp_val2;
                //emat[1, 1]
                ematBuffer[nno + 1] = tmp_val1 * 2 + tmp_val2;

                // 要素節点等価内力ベクトルを求める
                for (int ino = 0; ino < nno; ino++)
                {
                    eres_c[ino] = new Complex(0.0);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        eres_c[ino] -= ematBuffer[ino * nno + jno] * value_c[jno];
                    }
                }

                // 要素剛性行列にマージする
                mat_cc.Mearge(nno, no_c, nno, no_c, 1, ematBuffer, ref tmpBuffer);

                // 残差ベクトルにマージする
                for (int inoes = 0; inoes < nno; inoes++)
                {
                    res_c.AddValue(no_c[inoes], 0, eres_c[inoes]);
                }
            }
            return true;
        }
        /// <summary>
        /// ヘルムホルツの方程式 剛性行列 残差ベクトルの追加(要素アレイ単位)
        /// </summary>
        /// <param name="ls"></param>
        /// <param name="waveLength"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="eaId"></param>
        /// <param name="tmpBuffer"></param>
        /// <returns></returns>
        private static bool AddLinSysHelmholtz_EachElementAry(CZLinearSystem ls, double waveLength, CFieldWorld world, uint fieldValId, uint eaId, int[] tmpBuffer)
        {
            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][];
            for (int inoes = 0; inoes < nno; inoes++)
            {
                coord_c[inoes] = new double[ndim];
            }
            // 要素剛性行列のバッファ (i, j) --> (i * rowSize + j)
            Complex[] ematBuffer = new Complex[nno * nno];
            // 要素節点等価内力、外力、残差ベクトル
            Complex[] eres_c = new Complex[nno];
            // 要素剛性行列(コーナ-コーナー)
            CZMatDia_BlkCrs_Ptr mat_cc = ls.GetMatrixPtr(fieldValId, ELSEG_TYPE.CORNER, world);
            // 要素残差ベクトル(コーナー)
            CZVector_Blk_Ptr res_c = ls.GetResidualPtr(fieldValId, ELSEG_TYPE.CORNER, world);

            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];
                    }
                    //Console.WriteLine("coord_c [" + no_c[inoes] + " ] = " + coord_c[inoes, 0] + " " +  coord_c[inoes, 1]);
                }
                // 節点の値を取って来る
                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];
                    //Console.WriteLine("value_c [" + no_c[inoes] + " ] = " + tmpval[0].Real + " " +  tmpval[0].Imag);
                }

                // 節点座標
                double[] p1 = coord_c[0];
                double[] p2 = coord_c[1];
                double[] p3 = coord_c[2];
                // 面積を求める
                double area = CKerEMatTri.TriArea(p1, p2, p3);

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

                // 要素剛性行列を作る
                for (int ino = 0; ino < nno; ino++)
                {
                    for (int jno = 0; jno < nno; jno++)
                    {
                        //emat[ino, jno]
                        ematBuffer[ino * nno + jno] = area * (dldx[ino, 0] * dldx[jno, 0] + dldx[ino, 1] * dldx[jno, 1]);
                    }
                }
                double k0 = 2 * pi / waveLength;
                double tmp_val = k0 * k0 * area / 12.0;
                for (int ino = 0; ino < nno; ino++)
                {
                    //emat[ino, ino]
                    ematBuffer[ino * nno + ino] -= new Complex(tmp_val);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        //emat[ino, jno]
                        ematBuffer[ino * nno + jno] -= new Complex(tmp_val);
                    }
                }
                // 要素節点等価内力ベクトルを求める
                for (int ino = 0; ino < nno; ino++)
                {
                    eres_c[ino] = new Complex(0.0);
                    for (int jno = 0; jno < nno; jno++)
                    {
                        eres_c[ino] -= ematBuffer[ino * nno + jno] * value_c[jno];
                    }
                }
                // 要素剛性行列にマージする
                mat_cc.Mearge(nno, no_c, nno, no_c, 1, ematBuffer, ref tmpBuffer);

                // 残差ベクトルにマージする
                for (int inoes = 0; inoes < nno; inoes++)
                {
                    res_c.AddValue(no_c[inoes], 0, eres_c[inoes]);
                }
            }

            return true;
        }
예제 #3
0
        /// <summary>
        /// PML媒質内の要素の残差ベクトルを加算する(要素アレイ単位)
        /// </summary>
        /// <param name="timeIndex"></param>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="pmlStPosX"></param>
        /// <param name="pmlLength"></param>
        /// <param name="dt"></param>
        /// <param name="newmarkBeta"></param>
        /// <param name="media"></param>
        /// <param name="eaId"></param>
        /// <param name="node_cnt"></param>
        /// <param name="free_node_cnt"></param>
        /// <param name="toSorted"></param>
        /// <param name="Ez_Prev"></param>
        /// <param name="Ez_Prev2"></param>
        /// <param name="w2_F_e_EA"></param>
        /// <param name="w2_G_e_EA"></param>
        /// <param name="resVec"></param>
        /// <returns></returns>
        private static bool addPmlResVec_EachElementAry(
            int timeIndex,
            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,
            double[] Ez_Prev,
            double[] Ez_Prev2,
            ref double[][] w2_F_e_EA,
            ref double[][] w2_G_e_EA,
            ref double[] resVec)
        {
            System.Diagnostics.Debug.Assert(free_node_cnt == resVec.Length);
            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);

            // 初回ステップ
            if (timeIndex == 0)
            {
                w2_F_e_EA = new double[ea.Size()][];
                w2_G_e_EA = new double[ea.Size()][];
                for (int ielem = 0; ielem < ea.Size(); ielem++)
                {
                    w2_F_e_EA[ielem] = new double[nno];
                    w2_G_e_EA[ielem] = new double[nno];
                }
            }

            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);

                // w2_F, w2_Gの更新
                double[] w2_F_e = w2_F_e_EA[(int)ielem];
                double[] w2_G_e = w2_G_e_EA[(int)ielem];
                for (int ino = 0; ino < nno; ino++)
                {
                    uint iNodeNumber = no_c[ino];
                    if (!toSorted.ContainsKey(iNodeNumber)) continue;
                    int inoGlobal = (int)toSorted[iNodeNumber];

                    w2_F_e[ino] = c1_F_e * Ez_Prev2[inoGlobal] + w2_F_e[ino];
                    w2_G_e[ino] = c1_G_e * Ez_Prev2[inoGlobal] + c3_G_e * w2_G_e[ino];
                }

                // 残差ベクトルにマージする
                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];
                    double resVec_inoGlobal = 0.0;
                    for (int jno = 0; jno < nno; jno++)
                    {
                        uint jNodeNumber = no_c[jno];
                        if (!toSorted.ContainsKey(jNodeNumber)) continue;
                        int jnoGlobal = (int)toSorted[jNodeNumber];

                        resVec_inoGlobal +=
                            (sigmaX_e / eps0) * (1.0 / (2.0 * dt)) * eMMat[ino, jno] * Ez_Prev2[jnoGlobal]
                            - 1.0 * work_eKYMat[ino, jno] * (
                                (1.0 - newmarkBeta) * c1_F_e * Ez_Prev[jnoGlobal]
                                + w2_F_e[jno]
                                )
                            - 1.0 * work_eKXMat[ino, jno] * (
                                (newmarkBeta * c3_G_e * c1_G_e + (1.0 - 2.0 * newmarkBeta) * c1_G_e) * Ez_Prev[jnoGlobal]
                                + (newmarkBeta * c3_G_e * c3_G_e + (1.0 - 2.0 * newmarkBeta) * c3_G_e + newmarkBeta) * w2_G_e[jno]
                                );
                    }
                    resVec[inoGlobal] += resVec_inoGlobal;
                }
            }

            return true;
        }
예제 #4
0
        /// <summary>
        /// 非0パターンを作成する(要素アレイ単位)
        /// </summary>
        /// <param name="world"></param>
        /// <param name="fieldValId"></param>
        /// <param name="media"></param>
        /// <param name="eaId"></param>
        /// <param name="node_cnt"></param>
        /// <param name="free_node_cnt"></param>
        /// <param name="toSorted"></param>
        /// <param name="matPattern"></param>
        /// <returns></returns>
        private static bool MkMatPattern_EachElementAry(
            CFieldWorld world,
            uint fieldValId,
            MediaInfo media,
            uint eaId,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            ref bool[,] matPattern)
        {
            System.Diagnostics.Debug.Assert(free_node_cnt * free_node_cnt == matPattern.Length);
            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];

            for (uint ielem = 0; ielem < ea.Size(); ielem++)
            {
                // 要素配列から要素セグメントの節点番号を取り出す
                es_c_co.GetNodes(ielem, no_c);

                // 非0要素を設定する
                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形式の行列格納方法で格納
                        matPattern[inoGlobal, jnoGlobal] = true;
                    }
                }
            }

            return true;
        }
예제 #5
0
        /// <summary>
        /// ヘルムホルツの方程式 剛性行列 残差ベクトルの追加(要素アレイ単位)
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">値のフィールドID</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="KMat">剛性行列</param>
        /// <param name="MMat">質量行列</param>
        /// <returns></returns>
        private static bool MkHelmholtzMat_EachElementAry(
            CFieldWorld world,
            uint fieldValId,
            MediaInfo media,
            uint eaId,
            uint node_cnt,
            uint free_node_cnt,
            Dictionary<uint, uint> toSorted,
            ref MyDoubleBandMatrix KMat,
            ref MyDoubleBandMatrix MMat)
        {
            System.Diagnostics.Debug.Assert(free_node_cnt == KMat.RowSize && free_node_cnt == KMat.ColumnSize);
            System.Diagnostics.Debug.Assert(free_node_cnt == MMat.RowSize && free_node_cnt == MMat.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[,] eKMat = new double[nno, nno];
            // 要素結合行列
            double[,] eCMat = new double[nno, nno];
            // 要素質量行列
            double[,] eMMat = 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++)
                    {
                        // 要素剛性行列
                        eKMat[ino, jno] = media.P[0, 0] * integralDLDY[ino, jno] + media.P[1, 1] * integralDLDX[ino, jno];
                        // 要素質量行列
                        eMMat[ino, jno] = eps0 * myu0 * media.Q[2, 2] * integralL[ino, jno];
                    }
                }
                // 要素剛性行列にマージする
                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形式の行列格納方法で格納(バンド行列)
                        KMat._body[KMat.GetBufferIndex(inoGlobal,jnoGlobal)] += eKMat[ino, jno];
                        MMat._body[KMat.GetBufferIndex(inoGlobal, jnoGlobal)] += eMMat[ino, jno];
                    }
                }
            }

            return true;
        }
예제 #6
0
        /// <summary>
        /// 領域の界の値を取得する(要素アレイ単位)
        /// </summary>
        /// <param name="world">ワールド座標系</param>
        /// <param name="fieldValId">フィールド値ID</param>
        /// <param name="no_c_area">節点番号配列</param>
        /// <param name="to_no_area">節点番号→境界上節点番号マップ</param>
        /// <param name="eaId">要素アレイID</param>
        /// <param name="value_c_all">フィールド値配列</param>
        /// <returns></returns>
        private static bool getAreaFieldValueList_EachElementAry(CFieldWorld world, uint fieldValId, uint[] no_c_area, Dictionary<uint, uint> to_no_area, uint eaId, Complex[] value_c_all)
        {
            uint node_cnt = (uint)no_c_area.Length;

            System.Diagnostics.Debug.Assert(world.IsIdEA(eaId));
            CElemAry ea = world.GetEA(eaId);
            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.TRI);

            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][];
            //for (uint inoes = 0; inoes < ndim; inoes++)
            //{
            //    coord_c[inoes] = new double[ndim];
            //}
            // 節点の値の節点セグメント
            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];
                    //System.Diagnostics.Debug.Write( "(" + value_c[inoes].Real + "," + value_c[inoes].Imag + ")" );
                }

                for (uint ino = 0; ino < nno; ino++)
                {
                    System.Diagnostics.Debug.Assert(to_no_area.ContainsKey(no_c[ino]));
                    uint ino_boundary = to_no_area[no_c[ino]];
                    System.Diagnostics.Debug.Assert(ino_boundary < node_cnt);

                    value_c_all[ino_boundary] = value_c[ino];
                    //System.Diagnostics.Debug.WriteLine("value_c_all [ " + ino_boundary + " ] = " + "(" + value_c_all[ino_boundary].Real + ", " + value_c_all[ino_boundary].Imag + ") " + Complex.Norm(value_c_all[ino_boundary]));
                }
            }
            return true;
        }