예제 #1
0
        private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint         quantityId = 0;
            IList <uint> feIds      = World.GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = World.GetTriangleFE(quantityId, feId);
                uint       elemNodeCnt = triFE.NodeCount;
                int[]      nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = triFE.NodeCoordIds[iNode];
                    int nodeId = World.Coord2Node(quantityId, coId);
                    nodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(triFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is PoissonMaterial);
                var    ma = ma0 as PoissonMaterial;
                double k  = ma.Alpha;
                double f  = ma.F;

                double[,] sNN       = triFE.CalcSNN();
                double[, ][,] sNuNv = triFE.CalcSNuNv();
                double[,] sNxNx     = sNuNv[0, 0];
                double[,] sNyNx     = sNuNv[1, 0];
                double[,] sNxNy     = sNuNv[0, 1];
                double[,] sNyNy     = sNuNv[1, 1];
                double[] sN = triFE.CalcSN();
                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < elemNodeCnt; col++)
                    {
                        int colNodeId = nodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }
                        double a = k * (sNxNx[row, col] + sNyNy[row, col]);

                        A[rowNodeId, colNodeId] += a;
                    }
                }
                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    B[rowNodeId] += f * sN[row];
                }
            }
        }
예제 #2
0
        private void SetTri(FEWorld world, uint valueId)
        {
            System.Diagnostics.Debug.Assert(Type == ElementType.Tri);
            if (Type != ElementType.Tri)
            {
                return;
            }

            FieldValue fv         = world.GetFieldValue(valueId);
            uint       quantityId = fv.QuantityId;
            int        feOrder;

            {
                uint feId = world.GetTriangleFEIdFromMesh(quantityId, MeshId, 0); // 先頭の要素
                System.Diagnostics.Debug.Assert(feId != 0);
                TriangleFE triFE = world.GetTriangleFE(quantityId, feId);
                feOrder     = triFE.Order;
                ElemPtCount = triFE.NodeCount;
            }

            Indexs = new uint[ElemPtCount * ElemCount];
            for (int iTri = 0; iTri < ElemCount; iTri++)
            {
                uint feId = world.GetTriangleFEIdFromMesh(quantityId, MeshId, (uint)iTri);
                System.Diagnostics.Debug.Assert(feId != 0);
                TriangleFE triFE = world.GetTriangleFE(quantityId, feId);
                for (int iPt = 0; iPt < ElemPtCount; iPt++)
                {
                    Indexs[iTri * ElemPtCount + iPt] = (uint)triFE.NodeCoordIds[iPt];
                }
            }
        }
예제 #3
0
        private void MakeCo2AndEdgeCos2TriangleFE()
        {
            Co2TriangleFE.Clear();
            IList <uint> feIds = GetTriangleFEIds();

            foreach (uint feId in feIds)
            {
                TriangleFE triFE = GetTriangleFE(feId);
                // 節点→要素
                {
                    int[] coIds = triFE.NodeCoordIds;
                    for (int i = 0; i < coIds.Length; i++)
                    {
                        int          coId      = coIds[i];
                        IList <uint> targetIds = null;
                        if (Co2TriangleFE.ContainsKey(coId))
                        {
                            targetIds = Co2TriangleFE[coId];
                        }
                        else
                        {
                            targetIds           = new List <uint>();
                            Co2TriangleFE[coId] = targetIds;
                        }
                        targetIds.Add(feId);
                    }
                }
                // 辺(頂点1-頂点2)→要素
                {
                    int[] coIds = triFE.VertexCoordIds;
                    for (int i = 0; i < coIds.Length; i++)
                    {
                        int v1 = coIds[i];
                        int v2 = coIds[(i + 1) % coIds.Length];
                        if (v1 > v2)
                        {
                            int tmp = v1;
                            v1 = v2;
                            v2 = tmp;
                        }
                        string       edgeKey   = v1 + "_" + v2;
                        IList <uint> targetIds = null;
                        if (EdgeCos2TriangleFE.ContainsKey(edgeKey))
                        {
                            targetIds = EdgeCos2TriangleFE[edgeKey];
                        }
                        else
                        {
                            targetIds = new List <uint>();
                            EdgeCos2TriangleFE[edgeKey] = targetIds;
                        }
                        targetIds.Add(feId);
                    }
                }
            }
        }
예제 #4
0
파일: FEWorld.cs 프로젝트: lulzzz/IvyFEM
        public void UpdateBubbleFieldValueValuesFromNodeValues(
            uint valueId, FieldDerivativeType dt, double[] nodeValues)
        {
            System.Diagnostics.Debug.Assert(FieldValueArray.IsObjectId(valueId));
            FieldValue fv         = FieldValueArray.GetObject(valueId);
            uint       quantityId = fv.QuantityId;
            uint       dof        = fv.Dof;

            System.Diagnostics.Debug.Assert(fv.Dof == GetDof(quantityId));
            double[] values     = fv.GetDoubleValues(dt);
            uint     coCnt      = GetCoordCount(quantityId);
            uint     offsetNode = 0;

            for (uint qId = 0; qId < quantityId; qId++)
            {
                offsetNode += GetNodeCount(qId) * GetDof(qId);
            }

            IList <uint> feIds = GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = GetTriangleFE(quantityId, feId);
                int[]      coIds       = triFE.NodeCoordIds;
                uint       elemNodeCnt = triFE.NodeCount;
                double[]   bubbleValue = new double[dof];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = coIds[iNode];
                    int nodeId = Coord2Node(quantityId, coId);
                    if (nodeId == -1)
                    {
                        //for (int iDof = 0; iDof < dof; iDof++)
                        //{
                        //    bubbleValue[iDof] += 0;
                        //}
                    }
                    else
                    {
                        for (int iDof = 0; iDof < dof; iDof++)
                        {
                            bubbleValue[iDof] += nodeValues[offsetNode + nodeId * dof + iDof];
                        }
                    }
                }
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    bubbleValue[iDof] /= (double)elemNodeCnt;
                }

                for (int iDof = 0; iDof < dof; iDof++)
                {
                    values[(feId - 1) * dof + iDof] = bubbleValue[iDof];
                }
            }
        }
예제 #5
0
        private void CalcAB(double k0,
                            IvyFEM.Linear.ComplexSparseMatrix A, System.Numerics.Complex[] B)
        {
            IList <uint> feIds = World.GetTriangleFEIds(QuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = World.GetTriangleFE(QuantityId, feId);
                uint       elemNodeCnt = triFE.NodeCount;
                int[]      nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = triFE.NodeCoordIds[iNode];
                    int nodeId = World.Coord2Node(QuantityId, coId);
                    nodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(triFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is DielectricMaterial);
                var ma = ma0 as DielectricMaterial;

                double[,] sNN       = triFE.CalcSNN();
                double[, ][,] sNuNv = triFE.CalcSNuNv();
                double[,] sNxNx     = sNuNv[0, 0];
                double[,] sNyNx     = sNuNv[1, 0];
                double[,] sNxNy     = sNuNv[0, 1];
                double[,] sNyNy     = sNuNv[1, 1];
                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < elemNodeCnt; col++)
                    {
                        int colNodeId = nodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }
                        double a = (1.0 / ma.Muxx) * sNyNy[row, col] + (1.0 / ma.Muyy) * sNxNx[row, col] -
                                   (k0 * k0 * ma.Epzz) * sNN[row, col];

                        A[rowNodeId, colNodeId] += (System.Numerics.Complex)a;
                    }
                }
            }
        }
예제 #6
0
파일: FEWorld.cs 프로젝트: lulzzz/IvyFEM
        public void UpdateBubbleFieldValueValuesFromCoordValues(
            uint valueId, FieldDerivativeType dt, double[] coordValues)
        {
            System.Diagnostics.Debug.Assert(FieldValueArray.IsObjectId(valueId));
            FieldValue fv         = FieldValueArray.GetObject(valueId);
            uint       quantityId = fv.QuantityId;
            uint       dof        = fv.Dof;

            double[] values = fv.GetDoubleValues(dt);
            uint     coCnt  = GetCoordCount(quantityId);

            System.Diagnostics.Debug.Assert(coCnt * dof == coordValues.Length);

            IList <uint> feIds = GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = GetTriangleFE(quantityId, feId);
                int[]      coIds       = triFE.NodeCoordIds;
                uint       elemNodeCnt = triFE.NodeCount;
                double[]   bubbleValue = new double[dof];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId = coIds[iNode];
                    for (int iDof = 0; iDof < dof; iDof++)
                    {
                        bubbleValue[iDof] += coordValues[coId * dof + iDof];
                    }
                }
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    bubbleValue[iDof] /= (double)elemNodeCnt;
                }

                for (int iDof = 0; iDof < dof; iDof++)
                {
                    values[(feId - 1) * dof + iDof] = bubbleValue[iDof];
                }
            }
        }
예제 #7
0
        // 三角形要素の節点ナンバリング
        private void NumberTriangleNodes(FEWorld world, IList <int> zeroCoordIds)
        {
            Mesher2D mesh = world.Mesh;

            // ナンバリング
            int          nodeId = 0;
            IList <uint> feIds  = TriangleFEArray.GetObjectIds();

            foreach (uint feId in feIds)
            {
                TriangleFE fe        = TriangleFEArray.GetObject(feId);
                int        elemPtCnt = fe.NodeCoordIds.Length;
                int[]      coIds     = fe.NodeCoordIds;
                for (int iPt = 0; iPt < elemPtCnt; iPt++)
                {
                    int coId = coIds[iPt];
                    if (!Co2Node.ContainsKey(coId) &&
                        zeroCoordIds.IndexOf(coId) == -1)
                    {
                        Co2Node[coId] = nodeId;
                        nodeId++;
                    }
                }

                uint     meshId = fe.MeshId;
                int      iElem  = fe.MeshElemId;
                uint     elemCnt;
                MeshType meshType;
                int      loc;
                uint     cadId;
                mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId);
                System.Diagnostics.Debug.Assert(meshType == MeshType.Tri);
                var triArray = mesh.GetTriArrays();
                var tri      = triArray[loc].Tris[iElem];
                tri.FEId = (int)feId;

                string key = string.Format(meshId + "_" + iElem);
                Mesh2TriangleFE.Add(key, feId);
            }
        }
예제 #8
0
        private bool HasNonLinearElasticMaterial()
        {
            bool         hasNonlinear = false;
            uint         quantityId   = 0; // Note: 複数変数のときでも要素Idは同じはずなので0指定
            IList <uint> feIds        = World.GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE = World.GetTriangleFE(quantityId, feId);
                Material   ma    = World.GetMaterial(triFE.MaterialId);
                if (ma is LinearElasticMaterial)
                {
                    // linear
                }
                else
                {
                    hasNonlinear = true;
                    break;
                }
            }
            return(hasNonlinear);
        }
        private void CalcGLSNavierStokesByPicardAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint vQuantityId = 0;
            uint pQuantityId = 1;
            int  vDof        = 2;
            int  pDof        = 1;
            int  vNodeCnt    = (int)World.GetNodeCount(vQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = vNodeCnt * vDof;

            IList <uint> feIds = World.GetTriangleFEIds(vQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE vTriFE    = World.GetTriangleFE(vQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = vTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] vCoIds       = vTriFE.NodeCoordIds;
                uint  vElemNodeCnt = vTriFE.NodeCount;
                int[] vNodes       = new int[vElemNodeCnt];
                for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                {
                    int coId   = vCoIds[iNode];
                    int nodeId = World.Coord2Node(vQuantityId, coId);
                    vNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(vTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double   nu  = mu / rho;
                double[] g   = { ma.GravityX, ma.GravityY };

                double[][] velos = new double[vElemNodeCnt][];
                for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                {
                    double[] velo   = new double[vDof];
                    int      nodeId = vNodes[iNode];
                    if (nodeId == -1)
                    {
                        // 0
                    }
                    else
                    {
                        for (int iDof = 0; iDof < vDof; iDof++)
                        {
                            velo[iDof] = U[nodeId * vDof + iDof];
                        }
                    }
                    velos[iNode] = velo;
                }

                /*
                 * double taum = 0;
                 * double tauc = 0;
                 * {
                 *  double[] aveVelo = {
                 *      (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0,
                 *      (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0
                 *  };
                 *  double veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]);
                 *  double Ae = vTriFE.GetArea();
                 *  double h = 2.0 * Math.Sqrt(Ae / Math.PI);
                 *  double sqinvtaum1 = 0;
                 *  double sqinvtaum2 = (2.0 * 2.0 * veloNorm * veloNorm) / (h * h);
                 *  double sqinvtaum3 = (4.0 * 4.0 * nu * nu) / (h * h * h * h);
                 *  double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3;
                 *  taum = 1.0 / Math.Sqrt(sqinvtaum);
                 *
                 *  double re = veloNorm * h / (2.0 * nu);
                 *  if (re < 3.0)
                 *  {
                 *      tauc = (1.0 / 2.0) * h * veloNorm * re / 3.0;
                 *  }
                 *  else
                 *  {
                 *      tauc = (1.0 / 2.0) * h * veloNorm;
                 *  }
                 * }
                 */
                double taum = 0;
                double tauc = 0;
                {
                    double[] aveVelo =
                    {
                        (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0,
                        (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0
                    };
                    double     veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]);
                    double[][] Lu       = new double[vDof][];
                    {
                        double[] a;
                        double[] b;
                        double[] c;
                        vTriFE.CalcTransMatrix(out a, out b, out c);
                        // Lx
                        Lu[0] = b;
                        // Ly
                        Lu[1] = c;
                    }
                    IvyFEM.Lapack.DoubleMatrix GMat = new IvyFEM.Lapack.DoubleMatrix(vDof, vDof);
                    double[] gVec = new double[vDof];
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        for (int jDof = 0; jDof < vDof; jDof++)
                        {
                            for (int kDof = 0; kDof < vDof; kDof++)
                            {
                                GMat[iDof, jDof] += Lu[iDof][kDof] * Lu[jDof][kDof];
                            }
                        }
                    }
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        for (int kDof = 0; kDof < vDof; kDof++)
                        {
                            gVec[iDof] += Lu[iDof][kDof];
                        }
                    }

                    double sqinvtaum1 = 0;
                    double sqinvtaum2 = 0;
                    {
                        double[] tmpVec = GMat * aveVelo;
                        sqinvtaum2 = IvyFEM.Lapack.Functions.ddot(aveVelo, tmpVec);
                    }
                    double sqinvtaum3 = 0;
                    {
                        IvyFEM.Lapack.DoubleMatrix GMatT = new Lapack.DoubleMatrix(GMat);
                        GMatT.Transpose();
                        double GMatDoubleDot = IvyFEM.Lapack.DoubleMatrix.DoubleDot(GMat, GMatT);
                        sqinvtaum3 = 30.0 * nu * nu * GMatDoubleDot;
                    }
                    double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3;
                    taum = 1.0 / Math.Sqrt(sqinvtaum);

                    double gDot = IvyFEM.Lapack.Functions.ddot(gVec, gVec);
                    tauc = 1.0 / (taum * gDot);
                }

                double[]          vSN = vTriFE.CalcSN();
                IntegrationPoints ip  = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]     L    = ip.Ls[ipPt];
                    double[]     vN   = vTriFE.CalcN(L);
                    double[][]   vNu  = vTriFE.CalcNu(L);
                    double[]     vNx  = vNu[0];
                    double[]     vNy  = vNu[1];
                    double[, ][] vNuv = vTriFE.CalcNuv(L);
                    double[]     pN   = pTriFE.CalcN(L);
                    double[][]   pNu  = pTriFE.CalcNu(L);
                    double[]     pNx  = pNu[0];
                    double[]     pNy  = pNu[1];

                    double detJ       = vTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    double[] v   = new double[vDof];
                    double[] vx  = new double[vDof];
                    double[] vy  = new double[vDof];
                    double[] vxx = new double[vDof];
                    double[] vxy = new double[vDof];
                    double[] vyx = new double[vDof];
                    double[] vyy = new double[vDof];
                    double   p   = 0;
                    double   px  = 0;
                    double   py  = 0;
                    for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                    {
                        int nodeId = vNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        for (int iDof = 0; iDof < vDof; iDof++)
                        {
                            double vValue = U[nodeId * vDof + iDof];
                            v[iDof]   += vValue * vN[iNode];
                            vx[iDof]  += vValue * vNx[iNode];
                            vy[iDof]  += vValue * vNy[iNode];
                            vxx[iDof] += vValue * vNuv[0, 0][iNode];
                            vxy[iDof] += vValue * vNuv[0, 1][iNode];
                            vyx[iDof] += vValue * vNuv[1, 0][iNode];
                            vyy[iDof] += vValue * vNuv[1, 1][iNode];
                        }
                    }
                    for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                    {
                        int nodeId = pNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double pValue = U[offset + nodeId];
                        p  += pValue * pN[iNode];
                        px += pValue * pNx[iNode];
                        py += pValue * pNy[iNode];
                    }
                    double[][] vu = new double[vDof][];
                    vu[0] = vx;
                    vu[1] = vy;
                    double[, ][] vuv = new double[vDof, vDof][];
                    vuv[0, 0] = vxx;
                    vuv[0, 1] = vxy;
                    vuv[1, 0] = vyx;
                    vuv[1, 1] = vyy;
                    double[] pu = new double[vDof];
                    pu[0] = px;
                    pu[1] = py;

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < vElemNodeCnt; col++)
                        {
                            int colNodeId = vNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvv1 = new double[vDof, vDof];
                            kvv1[0, 0]     = detJWeight * mu * (vNx[row] * vNx[col] +
                                                                vNx[row] * vNx[col] + vNy[row] * vNy[col]);
                            kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col];
                            kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col];
                            kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] +
                                                            vNx[row] * vNx[col] + vNy[row] * vNy[col]);

                            double[,] kvv2 = new double[vDof, vDof];
                            //kvv2[0, 0] = detJWeight * rho * vN[row] * (
                            //    vN[col] * vx[0] + v[0] * vNx[col] + v[1] * vNy[col]);
                            //kvv2[0, 1] = detJWeight * rho * vN[row] * vN[col] * vy[0];
                            //kvv2[1, 0] = detJWeight * rho * vN[row] * vN[col] * vx[1];
                            //kvv2[1, 1] = detJWeight * rho * vN[row] * (
                            //    vN[col] * vy[1] + v[0] * vNx[col] + v[1] * vNy[col]);
                            // Picard
                            kvv2[0, 0] = detJWeight * rho * vN[row] * (v[0] * vNx[col] + v[1] * vNy[col]);
                            kvv2[0, 1] = 0;
                            kvv2[1, 0] = 0;
                            kvv2[1, 1] = detJWeight * rho * vN[row] * (v[0] * vNx[col] + v[1] * vNy[col]);

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] +=
                                        kvv1[rowDof, colDof] + kvv2[rowDof, colDof];

                                    //B[rowNodeId * vDof + rowDof] +=
                                    //    kvv2[rowDof, colDof] * U[colNodeId * vDof + colDof];
                                    // Picard
                                    // nothing
                                }
                            }
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvp = new double[vDof, pDof];
                            kvp[0, 0]     = -detJWeight * vNx[row] * pN[col];
                            kvp[1, 0]     = -detJWeight * vNy[row] * pN[col];

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0];
                                A[offset + colNodeId, rowNodeId *vDof + rowDof]  += kvp[rowDof, 0];
                            }
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double[] q2 = new double[vDof];
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            //q2[rowDof] = detJWeight * rho * vN[row] * (v[0] * vx[rowDof] + v[1] * vy[rowDof]);
                            // Picard
                            // nothing
                        }
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            B[rowNodeId * vDof + rowDof] += -q2[rowDof];
                        }
                    }

                    //////////////////////////////////////////////////////////////
                    // SUPG
                    double[] rmi = new double[vDof];
                    double[,,] rmivj = new double[vDof, vDof, vElemNodeCnt];
                    double[,] rmip   = new double[vDof, pElemNodeCnt];
                    double rc = 0;
                    double[,] rcvj = new double[vDof, vElemNodeCnt];
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        rmi[iDof] =
                            -mu * (vuv[0, 0][iDof] + vuv[1, 1][iDof]) +
                            rho * (v[0] * vx[iDof] + v[1] * vy[iDof]) +
                            pu[iDof] - rho * g[iDof];

                        for (int jDof = 0; jDof < vDof; jDof++)
                        {
                            for (int jNode = 0; jNode < vElemNodeCnt; jNode++)
                            {
                                int jNodeId = vNodes[jNode];
                                if (jNodeId == -1)
                                {
                                    continue;
                                }

                                rmivj[iDof, jDof, jNode] = 0;
                                if (iDof == jDof)
                                {
                                    rmivj[iDof, jDof, jNode] +=
                                        -mu * (vNuv[0, 0][jNode] + vNuv[1, 1][jNode]);
                                }
                                //rmivj[iDof, jDof, jNode] +=
                                //    rho * vN[jNode] * vu[jDof][iDof];
                                // Picard
                                // nothing
                                if (iDof == jDof)
                                {
                                    rmivj[iDof, jDof, jNode] +=
                                        rho * (v[0] * vNu[0][jNode] + v[1] * vNu[1][jNode]);
                                }
                            }
                        }

                        for (int jNode = 0; jNode < pElemNodeCnt; jNode++)
                        {
                            int jNodeId = pNodes[jNode];
                            if (jNodeId == -1)
                            {
                                continue;
                            }
                            rmip[iDof, jNode] = pNu[iDof][jNode];
                        }
                    }
                    {
                        rc = vx[0] + vy[1];
                        for (int jDof = 0; jDof < vDof; jDof++)
                        {
                            for (int jNode = 0; jNode < vElemNodeCnt; jNode++)
                            {
                                int jNodeId = vNodes[jNode];
                                if (jNodeId == -1)
                                {
                                    continue;
                                }
                                rcvj[jDof, jNode] = vNu[jDof][jNode];
                            }
                        }
                    }
                    // kvv
                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < vElemNodeCnt; col++)
                        {
                            int colNodeId = vNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvv1       = new double[vDof, vDof];
                            double[,] kvv1GLSAdd = new double[vDof, vDof];
                            double[,] kvv2       = new double[vDof, vDof];
                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    // Picard
                                    kvv1[rowDof, colDof] =
                                        detJWeight * taum * (v[0] * vNu[0][row] + v[1] * vNu[1][row]) *
                                        rmivj[rowDof, colDof, col];
                                    kvv2[rowDof, colDof] =
                                        detJWeight * tauc * rho * vNu[rowDof][row] * rcvj[colDof, col];
                                }
                            }
                            //  GLS追加項
                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    kvv1GLSAdd[rowDof, colDof] =
                                        -detJWeight * (1.0 / rho) * taum * mu * (vNuv[0, 0][row] + vNuv[1, 1][row]) *
                                        rmivj[rowDof, colDof, col];
                                }
                            }

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] +=
                                        kvv1[rowDof, colDof] + kvv2[rowDof, colDof] + kvv1GLSAdd[rowDof, colDof];

                                    // Picard
                                    // nothing
                                }
                            }
                        }
                    }
                    // kvp
                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvp       = new double[vDof, pDof];
                            double[,] kvpGLSAdd = new double[vDof, pDof];
                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                kvp[rowDof, 0] =
                                    detJWeight * taum *
                                    (v[0] * vNu[0][row] + v[1] * vNu[1][row]) * rmip[rowDof, col];
                            }
                            // GLS追加項
                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                kvpGLSAdd[rowDof, 0] =
                                    -detJWeight * (1.0 / rho) * taum * mu *
                                    (vNuv[0, 0][row] + vNuv[1, 1][row]) * rmip[rowDof, col];
                            }

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                A[rowNodeId * vDof + rowDof, offset + colNodeId] +=
                                    kvp[rowDof, 0] + kvpGLSAdd[rowDof, 0];

                                // Picard
                                // nothing
                            }
                        }
                    }
                    // kpv
                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < vElemNodeCnt; col++)
                        {
                            int colNodeId = vNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kpv = new double[pDof, vDof];
                            for (int colDof = 0; colDof < vDof; colDof++)
                            {
                                kpv[0, colDof] =
                                    -detJWeight * (1.0 / rho) * taum *
                                    (pNu[0][row] * rmivj[0, colDof, col] + pNu[1][row] * rmivj[1, colDof, col]);
                            }

                            for (int colDof = 0; colDof < vDof; colDof++)
                            {
                                A[offset + rowNodeId, colNodeId *vDof + colDof] += kpv[0, colDof];

                                // Picard
                                // nothing
                            }
                        }
                    }
                    // kpp
                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kpp = new double[pDof, pDof];
                            kpp[0, 0]     =
                                -detJWeight * (1.0 / rho) * taum *
                                (pNu[0][row] * rmip[0, col] + pNu[1][row] * rmip[1, col]);

                            A[offset + rowNodeId, offset + colNodeId] += kpp[0, 0];

                            // Picard
                            // nothing
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double[] qv1 = new double[vDof];
                        double[] qv2 = new double[vDof];
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            // Picard
                            // nothing
                        }
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            B[rowNodeId * vDof + rowDof] += -(qv1[rowDof] + qv2[rowDof]);
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double[] qp = new double[pDof];
                        // Picard
                        // nothing
                        B[offset + rowNodeId] += -qp[0];
                    }
                }

                for (int row = 0; row < vElemNodeCnt; row++)
                {
                    int rowNodeId = vNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int rowDof = 0; rowDof < vDof; rowDof++)
                    {
                        B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row];
                    }
                }
            }
        }
        protected void CalcMooneyRivlinHyperelasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint uQuantityId = 0;
            uint lQuantityId = 1;

            System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2);
            System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1);
            int uDof     = 2;
            int lDof     = 1;
            int uNodeCnt = (int)World.GetNodeCount(uQuantityId);
            int lNodeCnt = (int)World.GetNodeCount(lQuantityId);
            //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength);
            int offset = GetOffset(lQuantityId);

            System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof);

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    uFV   = World.GetFieldValue(UValueId);

            TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId);
            TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId);
            Material   ma0    = World.GetMaterial(uTriFE.MaterialId);

            if (!(ma0 is MooneyRivlinHyperelasticMaterial))
            {
                return;
            }

            uint vertexCnt = uTriFE.VertexCount;

            for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
            {
                System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]);
            }
            int[] uCoIds       = uTriFE.NodeCoordIds;
            uint  uElemNodeCnt = uTriFE.NodeCount;

            int[] uNodes = new int[uElemNodeCnt];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                int coId   = uCoIds[iNode];
                int nodeId = World.Coord2Node(uQuantityId, coId);
                uNodes[iNode] = nodeId;
            }
            int[] lCoIds       = lTriFE.NodeCoordIds;
            uint  lElemNodeCnt = lTriFE.NodeCount;

            int[] lNodes = new int[lElemNodeCnt];
            for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
            {
                int coId   = lCoIds[iNode];
                int nodeId = World.Coord2Node(lQuantityId, coId);
                lNodes[iNode] = nodeId;
            }

            var    ma             = ma0 as MooneyRivlinHyperelasticMaterial;
            bool   isCompressible = ma.IsCompressible;
            double d1             = ma.D1;
            double c1             = ma.C1;
            double c2             = ma.C2;
            double rho            = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] uSN = uTriFE.CalcSN();
            double[,] uSNN = uTriFE.CalcSNN();
            double[,] lSNN = lTriFE.CalcSNN();
            System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3);
            IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);

            System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount);

            double[,] qu = new double[uElemNodeCnt, uDof];
            double[] ql = new double[lElemNodeCnt];

            for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
            {
                double[]   L          = ip.Ls[ipPt];
                double[]   uN         = uTriFE.CalcN(L);
                double[]   lN         = lTriFE.CalcN(L);
                double[][] uNu        = uTriFE.CalcNu(L);
                double     detJ       = uTriFE.GetDetJacobian(L);
                double     weight     = ip.Weights[ipPt];
                double     detJWeight = (1.0 / 2.0) * weight * detJ;

                // 変位の微分
                double[,] uu = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                        {
                            int iNodeId = uNodes[iNode];
                            if (iNodeId == -1)
                            {
                                continue;
                            }
                            uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode];
                        }
                    }
                }

                // ラグランジュの未定乗数
                double l = 0;
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    int iNodeId = lNodes[iNode];
                    if (iNodeId == -1)
                    {
                        continue;
                    }
                    l += U[offset + iNodeId] * lN[iNode];
                }

                // Green-Lagrangeのひずみ
                double[,] e = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]);
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                }

                // 右Cauchy-Green変形テンソル
                double[,] c = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof];
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                    c[iDof, iDof] += 1.0;
                }

                // Cのテンソル不変量
                double I1      = c[0, 0] + c[1, 1] + 1.0;
                double I2      = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0];
                double I3      = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0];
                double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0);
                double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0);
                double[,] invC = new double[uDof, uDof];
                {
                    double invI3 = 1.0 / I3;
                    invC[0, 0] = invI3 * c[1, 1];
                    invC[0, 1] = -invI3 * c[0, 1];
                    invC[1, 0] = -invI3 * c[1, 0];
                    invC[1, 1] = invI3 * c[0, 0];
                }

                // 第2Piola-Kirchhoff応力
                double[,] s = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        s[iDof, jDof] -=
                            2.0 * c2 * inv23I3 * c[iDof, jDof] +
                            (2.0 / 3.0) * (c1 * I1 * inv13I3 + c2 * 2.0 * I2 * inv23I3) * invC[iDof, jDof];
                    }
                }
                {
                    double tmp = 2.0 * c1 * inv13I3 + 2.0 * c2 * inv23I3 * I1;
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        s[iDof, iDof] += tmp;
                    }
                }
                // Lagrangeの未定乗数の寄与項
                {
                    double tmp = 2.0 * l * I3;
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int jDof = 0; jDof < uDof; jDof++)
                        {
                            s[iDof, jDof] += tmp * invC[iDof, jDof];
                        }
                    }
                }

                // 構成則テンソル
                double[,,,] c4 = new double[uDof, uDof, uDof, uDof];
                // 圧力構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                c4[gDof, hDof, eDof, fDof] +=
                                    4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] -
                                    2.0 * l * I3 * (
                                        invC[gDof, eDof] * invC[fDof, hDof] +
                                        invC[gDof, fDof] * invC[eDof, hDof]);
                            }
                        }
                    }
                }
                // 変位構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                c4[gDof, hDof, eDof, fDof] +=
                                    4.0 * c1 * inv13I3 / 3.0 * (
                                        invC[gDof, hDof] * invC[eDof, fDof] * I1 / 3.0 +
                                        invC[gDof, eDof] * invC[fDof, hDof] * I1 / 2.0 +
                                        invC[gDof, fDof] * invC[eDof, hDof] * I1 / 2.0) +
                                    4.0 * c2 * inv23I3 * 2.0 / 3.0 * (
                                        invC[gDof, hDof] * invC[eDof, fDof] * I2 * (2.0 / 3.0) +
                                        c[gDof, hDof] * invC[eDof, fDof] +
                                        invC[gDof, hDof] * c[eDof, fDof] +
                                        invC[gDof, eDof] * invC[fDof, hDof] * I2 / 2.0 +
                                        invC[gDof, fDof] * invC[eDof, hDof] * I2 / 2.0);
                            }
                        }

                        double tmp = 4.0 * c1 * inv13I3 / 3.0 * invC[gDof, hDof] +
                                     4.0 * c2 * inv23I3 * I1 * (2.0 / 3.0) * invC[gDof, hDof];
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            c4[gDof, hDof, eDof, eDof] -= tmp;
                            c4[eDof, eDof, gDof, hDof] -= tmp;
                        }
                        c4[gDof, gDof, hDof, hDof] += 4.0 * c2 * inv23I3;
                        c4[gDof, hDof, hDof, gDof] -= 2.0 * c2 * inv23I3;
                        c4[gDof, hDof, gDof, hDof] -= 2.0 * c2 * inv23I3;
                    }
                }

                double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof];
                {
                    double[,] f = new double[uDof, uDof];
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int jDof = 0; jDof < uDof; jDof++)
                        {
                            f[iDof, jDof] = uu[iDof, jDof];
                        }
                        f[iDof, iDof] += 1.0;
                    }
                    for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                    {
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof];
                                }
                            }
                        }
                    }
                }

                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < uElemNodeCnt; col++)
                    {
                        int colNodeId = uNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kuu = new double[uDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                double tmp1 = 0.0;
                                for (int gDof = 0; gDof < uDof; gDof++)
                                {
                                    for (int hDof = 0; hDof < uDof; hDof++)
                                    {
                                        for (int eDof = 0; eDof < uDof; eDof++)
                                        {
                                            for (int fDof = 0; fDof < uDof; fDof++)
                                            {
                                                tmp1 += c4[gDof, hDof, eDof, fDof] *
                                                        b[row, rowDof, eDof, fDof] *
                                                        b[col, colDof, gDof, hDof];
                                            }
                                        }
                                    }
                                }
                                kuu[rowDof, colDof] += detJWeight * tmp1;
                            }
                        }
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col];
                                }
                            }
                            for (int rowDof = 0; rowDof < uDof; rowDof++)
                            {
                                kuu[rowDof, rowDof] += detJWeight * tmp;
                            }
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] +=
                                    kuu[rowDof, colDof];
                                B[rowNodeId * uDof + rowDof] +=
                                    kuu[rowDof, colDof] * U[colNodeId * uDof + colDof];
                            }
                        }
                    }
                }
                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < lElemNodeCnt; col++)
                    {
                        int colNodeId = lNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kul = new double[uDof, lDof];
                        double[,] klu = new double[lDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof];
                                }
                            }

                            kul[rowDof, 0] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                            klu[0, rowDof] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0];
                            A[offset + colNodeId, rowNodeId *uDof + rowDof]  += klu[0, rowDof];
                            B[rowNodeId * uDof + rowDof] +=
                                kul[rowDof, 0] * U[offset + colNodeId];
                            B[offset + colNodeId] +=
                                klu[0, rowDof] * U[rowNodeId * uDof + rowDof];
                        }
                    }
                }

                // Note: kllは数値積分しなくて求められる

                for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                {
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int gDof = 0; gDof < uDof; gDof++)
                        {
                            for (int hDof = 0; hDof < uDof; hDof++)
                            {
                                qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof];
                            }
                        }
                    }
                }
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    if (isCompressible)
                    {
                        ql[iNode] += detJWeight * lN[iNode] * ((I3 - 1) - l / d1);
                    }
                    else
                    {
                        ql[iNode] += detJWeight * lN[iNode] * (I3 - 1);
                    }
                }
            }

            if (isCompressible)
            {
                for (int row = 0; row < lElemNodeCnt; row++)
                {
                    int rowNodeId = lNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < lElemNodeCnt; col++)
                    {
                        int colNodeId = lNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double kll = -(1.0 / d1) * lSNN[row, col];
                        A[offset + rowNodeId, offset + colNodeId] += kll;
                        B[offset + rowNodeId] += kll * U[offset + colNodeId];
                    }
                }
            }

            for (int row = 0; row < uElemNodeCnt; row++)
            {
                int rowNodeId = uNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int col = 0; col < uElemNodeCnt; col++)
                {
                    int colNodeId = uNodes[col];
                    if (colNodeId == -1)
                    {
                        continue;
                    }

                    int      colCoId = uCoIds[col];
                    double[] u       = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                    double[] velU    = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                    double[] accU    = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);
                    double[,] m = new double[2, 2];

                    m[0, 0] = rho * uSNN[row, col];
                    m[1, 0] = 0.0;
                    m[0, 1] = 0.0;
                    m[1, 1] = rho * uSNN[row, col];
                    for (int rowDof = 0; rowDof < uDof; rowDof++)
                    {
                        for (int colDof = 0; colDof < uDof; colDof++)
                        {
                            A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] +=
                                (1.0 / (beta * dt * dt)) * m[rowDof, colDof];
                            B[rowNodeId * uDof + rowDof] +=
                                m[rowDof, colDof] * (
                                    (1.0 / (beta * dt * dt)) * u[colDof] +
                                    (1.0 / (beta * dt)) * velU[colDof] +
                                    (1.0 / (2.0 * beta) - 1.0) * accU[colDof]);
                        }
                    }
                }
            }

            double[,] fg = new double[uElemNodeCnt, uDof];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    fg[iNode, iDof] = rho * g[iDof] * uSN[iNode];
                }
            }

            for (int row = 0; row < uElemNodeCnt; row++)
            {
                int rowNodeId = uNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < uDof; rowDof++)
                {
                    B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof];
                }
            }
            for (int row = 0; row < lElemNodeCnt; row++)
            {
                int rowNodeId = lNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                B[offset + rowNodeId] += -ql[row];
            }
        }
예제 #11
0
        private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint         quantityId = 0;
            var          veloFV     = World.GetFieldValue(VeloValueId);
            IList <uint> feIds      = World.GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = World.GetTriangleFE(quantityId, feId);
                uint       elemNodeCnt = triFE.NodeCount;
                int[]      nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = triFE.NodeCoordIds[iNode];
                    int nodeId = World.Coord2Node(quantityId, coId);
                    nodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(triFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is DiffusionMaterial);
                var        ma    = ma0 as DiffusionMaterial;
                double     nu    = ma.DiffusionCoef;
                double     f     = ma.F;
                double[][] velos = new double[elemNodeCnt][];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int nodeId = nodes[iNode];
                    if (nodeId == -1)
                    {
                        continue;
                    }
                    int      coId = World.Node2Coord(quantityId, nodeId);
                    double[] velo = veloFV.GetDoubleValue(coId, FieldDerivativeType.Value);
                    velos[iNode] = velo;
                }

                double tau;
                {
                    double[] aveVelo =
                    {
                        (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0,
                        (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0
                    };
                    double   veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]);
                    double[] veloDir  = { aveVelo[0] / veloNorm, aveVelo[1] / veloNorm };
                    double   h;
                    {
                        double[]   L   = new double[] { 1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0 };
                        double[][] Nu  = triFE.CalcNu(L);
                        double[]   Nx  = Nu[0];
                        double[]   Ny  = Nu[1];
                        double     tmp = 0;
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            tmp += Math.Abs(veloDir[0] * Nx[iNode] + veloDir[1] * Ny[iNode]);
                        }
                        h = 2.0 / tmp;
                    }
                    double lambda = (1.0 / 2.0) * veloNorm * h / nu;

                    //tau = (1.0 / 2.0) * (h / veloNorm) * (1.0 / Math.Tanh(lambda) - 1.0 / lambda);
                    if (nu > 1.0e-20)
                    {
                        if (lambda < 3.0)
                        {
                            tau = (1.0 / 2.0) * h / veloNorm * lambda / 3.0;
                        }
                        else
                        {
                            tau = (1.0 / 2.0) * h / veloNorm;
                        }
                    }
                    else
                    {
                        tau = (1.0 / 2.0) * h / veloNorm;
                    }
                }

                double[]          sN = triFE.CalcSN();
                IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]   L          = ip.Ls[ipPt];
                    double[]   N          = triFE.CalcN(L);
                    double[][] Nu         = triFE.CalcNu(L);
                    double[]   Nx         = Nu[0];
                    double[]   Ny         = Nu[1];
                    double     detJ       = triFE.GetDetJacobian(L);
                    double     weight     = ip.Weights[ipPt];
                    double     detJWeight = (1.0 / 2.0) * weight * detJ;

                    double[] velo = new double[2];
                    for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                    {
                        for (int iDof = 0; iDof < 2; iDof++)
                        {
                            velo[iDof] += N[iNode] * velos[iNode][iDof];
                        }
                    }

                    for (int row = 0; row < elemNodeCnt; row++)
                    {
                        int rowNodeId = nodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < elemNodeCnt; col++)
                        {
                            int colNodeId = nodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }
                            double k = detJWeight * nu * (Nx[row] * Nx[col] + Ny[row] * Ny[col]);
                            double c = detJWeight *
                                       (N[row] + tau * (velo[0] * Nx[row] + velo[1] * Ny[row])) *
                                       (velo[0] * Nx[col] + velo[1] * Ny[col]);

                            A[rowNodeId, colNodeId] += k + c;
                        }
                    }
                }

                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    B[rowNodeId] += f * sN[row];
                }
            }
        }
예제 #12
0
        /*
         * // Taylor級数展開 3次までの項を考慮
         * protected void SetVorticityDirichletBCOfVorticityForTangentFlow(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
         * {
         *  uint wQuantityId = 0;
         *  uint pQuantityId = 1;
         *  int wNodeCnt = (int)World.GetNodeCount(wQuantityId);
         *  int pNodeCnt = (int)World.GetNodeCount(pQuantityId);
         *  int offset = wNodeCnt;
         *
         *  if (World.GetPortCount(wQuantityId) == 0)
         *  {
         *      return;
         *  }
         *  uint portCnt = World.GetPortCount(wQuantityId);
         *  IList<PortCondition> portConditions = World.GetPortConditions(wQuantityId);
         *  IList<uint> feIds = World.GetLineFEIds(wQuantityId);
         *  for (int portId = 0; portId < portCnt; portId++)
         *  {
         *      PortCondition portCondition = portConditions[portId];
         *      //IList<int> intParam = portCondition.IntAdditionalParameters;
         *      //System.Diagnostics.Debug.Assert(intParam.Count == 0);
         *      IList<uint> bcEIds = portCondition.EIds;
         *      IList<double> param = portCondition.DoubleAdditionalParameters;
         *      System.Diagnostics.Debug.Assert(param.Count == 2); // 0: dψ/dx 1: dψ/dy
         *      double pxValue = param[0];
         *      double pyValue = param[1];
         *
         *      foreach (uint feId in feIds)
         *      {
         *          LineFE lineFE = World.GetLineFE(wQuantityId, feId);
         *          uint meshId = lineFE.MeshId;
         *          //int meshElemId = lineFE.MeshElemId;
         *          uint eId;
         *          {
         *              uint elemCount;
         *              MeshType meshType;
         *              int loc;
         *              uint cadId;
         *              World.Mesh.GetMeshInfo(meshId, out elemCount, out meshType, out loc, out cadId);
         *              System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
         *              eId = cadId;
         *          }
         *          if (bcEIds.Contains(eId))
         *          {
         *              // BCを適用する辺
         *          }
         *          else
         *          {
         *              continue;
         *          }
         *
         *          // BC
         *          uint elemNodeCnt = lineFE.NodeCount;
         *          int[] wCoIds = lineFE.NodeCoordIds;
         *          int[] wNodes = new int[elemNodeCnt];
         *          int[] pNodes = new int[elemNodeCnt];
         *          for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *          {
         *              int coId = wCoIds[iNode];
         *              wNodes[iNode] = World.Coord2Node(wQuantityId, coId);
         *              pNodes[iNode] = World.Coord2Node(pQuantityId, coId);
         *          }
         *
         *          Material ma0 = World.GetMaterial(lineFE.MaterialId);
         *          System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
         *          var ma = ma0 as NewtonFluidMaterial;
         *          double rho = ma.MassDensity;
         *          double mu = ma.Mu;
         *          double[] g = { ma.GravityX, ma.GravityY };
         *
         *          double[] normal = lineFE.GetNormal();
         *
         *          int coId1 = wCoIds[0];
         *          int coId2 = wCoIds[1];
         *          int adjCoId = -1; // adjacent
         *          {
         *              IList<uint> triFEIds = World.GetTriangleFEIdsFromEdgeCoord(wQuantityId, coId1, coId2);
         *              uint triFEId = triFEIds[0];
         *              TriangleFE triFE = World.GetTriangleFE(wQuantityId, triFEId);
         *              int[] triFECoIds = triFE.NodeCoordIds;
         *              foreach (int coId in triFECoIds)
         *              {
         *                  if (coId != coId1 && coId != coId2)
         *                  {
         *                      adjCoId = coId;
         *                      break;
         *                  }
         *              }
         *              System.Diagnostics.Debug.Assert(adjCoId != -1);
         *          }
         *          int wAdjNodeId = -1;
         *          wAdjNodeId = World.Coord2Node(wQuantityId, adjCoId); // 特殊な場合-1はありえる
         *          int pAdjNodeId = -1;
         *          pAdjNodeId = World.Coord2Node(pQuantityId, adjCoId); // 特殊な場合-1はありえる
         *          double[] pt1 = World.GetCoord(wQuantityId, coId1);
         *          double[] pt2 = World.GetCoord(wQuantityId, coId2);
         *          double[] adjPt = World.GetCoord(wQuantityId, adjCoId);
         *          double hn = IvyFEM.CadUtils.TriHeight(
         *              new OpenTK.Vector2d(adjPt[0], adjPt[1]), // 点
         *              new OpenTK.Vector2d(pt1[0], pt1[1]), // 辺の点1
         *              new OpenTK.Vector2d(pt2[0], pt2[1]) // 辺の点2
         *              );
         *
         *          for (int row = 0; row < elemNodeCnt; row++)
         *          {
         *              int rowCoId = wCoIds[row];
         *              int rowNodeId = wNodes[row];
         *              if (rowNodeId == -1)
         *              {
         *                  continue;
         *              }
         *              for (int colNodeId = 0; colNodeId < wNodeCnt; colNodeId++)
         *              {
         *                  int colCoId = World.Node2Coord(wQuantityId, colNodeId);
         *                  if (colCoId == rowCoId)
         *                  {
         *                      A[rowNodeId, colNodeId] = 1.0;
         *                  }
         *                  else if (wAdjNodeId != -1 && colNodeId == wAdjNodeId)
         *                  {
         *                      A[rowNodeId, colNodeId] = -1.0 / 2.0;
         *                  }
         *                  else
         *                  {
         *                      A[rowNodeId, colNodeId] = 0;
         *                  }
         *              }
         *              for (int colNodeId = 0; colNodeId < pNodeCnt; colNodeId++)
         *              {
         *                  int colCoId = World.Node2Coord(pQuantityId, colNodeId);
         *                  if (colCoId == rowCoId)
         *                  {
         *                      A[rowNodeId, offset + colNodeId] = -3.0 / (hn * hn);
         *                  }
         *                  else if (pAdjNodeId != -1 && colNodeId == pAdjNodeId)
         *                  {
         *                      A[rowNodeId, offset + colNodeId] = 3.0 / (hn * hn);
         *                  }
         *                  else
         *                  {
         *                      A[rowNodeId, offset + colNodeId] = 0;
         *                  }
         *              }
         *              B[rowNodeId] = -(normal[0] * pxValue + normal[1] * pyValue) * (3.0 / hn);
         *          }
         *      }
         *  }
         * }
         */
        /*
         * // Taylor級数展開 3次までの項を考慮 境界積分評価
         * protected void SetVorticityDirichletBCOfVorticityForTangentFlow(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
         * {
         *  uint wQuantityId = 0;
         *  uint pQuantityId = 1;
         *  int wNodeCnt = (int)World.GetNodeCount(wQuantityId);
         *  int pNodeCnt = (int)World.GetNodeCount(pQuantityId);
         *  int offset = wNodeCnt;
         *
         *  if (World.GetPortCount(wQuantityId) == 0)
         *  {
         *      return;
         *  }
         *  uint portCnt = World.GetPortCount(wQuantityId);
         *  IList<PortCondition> portConditions = World.GetPortConditions(wQuantityId);
         *  IList<uint> feIds = World.GetLineFEIds(wQuantityId);
         *  for (int portId = 0; portId < portCnt; portId++)
         *  {
         *      PortCondition portCondition = portConditions[portId];
         *      //IList<int> intParam = portCondition.IntAdditionalParameters;
         *      //System.Diagnostics.Debug.Assert(intParam.Count == 0);
         *      IList<uint> bcEIds = portCondition.EIds;
         *      IList<double> param = portCondition.DoubleAdditionalParameters;
         *      System.Diagnostics.Debug.Assert(param.Count == 2); // 0: dψ/dx 1: dψ/dy
         *      double pxValue = param[0];
         *      double pyValue = param[1];
         *
         *      foreach (uint feId in feIds)
         *      {
         *          LineFE lineFE = World.GetLineFE(wQuantityId, feId);
         *          uint meshId = lineFE.MeshId;
         *          //int meshElemId = lineFE.MeshElemId;
         *          uint eId;
         *          {
         *              uint elemCount;
         *              MeshType meshType;
         *              int loc;
         *              uint cadId;
         *              World.Mesh.GetMeshInfo(meshId, out elemCount, out meshType, out loc, out cadId);
         *              System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
         *              eId = cadId;
         *          }
         *          if (bcEIds.Contains(eId))
         *          {
         *              // BCを適用する辺
         *          }
         *          else
         *          {
         *              continue;
         *          }
         *
         *          // BC
         *          uint elemNodeCnt = lineFE.NodeCount;
         *          int[] wCoIds = lineFE.NodeCoordIds;
         *          int[] wNodes = new int[elemNodeCnt];
         *          int[] pNodes = new int[elemNodeCnt];
         *          for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *          {
         *              int coId = wCoIds[iNode];
         *              wNodes[iNode] = World.Coord2Node(wQuantityId, coId);
         *              pNodes[iNode] = World.Coord2Node(pQuantityId, coId);
         *          }
         *
         *          Material ma0 = World.GetMaterial(lineFE.MaterialId);
         *          System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
         *          var ma = ma0 as NewtonFluidMaterial;
         *          double rho = ma.MassDensity;
         *          double mu = ma.Mu;
         *          double[] g = { ma.GravityX, ma.GravityY };
         *
         *          double[] normal = lineFE.GetNormal();
         *          double[] sN = lineFE.CalcSN();
         *
         *          int coId1 = wCoIds[0];
         *          int coId2 = wCoIds[1];
         *          int adjCoId = -1; // adjacent
         *          {
         *              IList<uint> triFEIds = World.GetTriangleFEIdsFromEdgeCoord(wQuantityId, coId1, coId2);
         *              uint triFEId = triFEIds[0];
         *              TriangleFE triFE = World.GetTriangleFE(wQuantityId, triFEId);
         *              int[] triFECoIds = triFE.NodeCoordIds;
         *              foreach (int coId in triFECoIds)
         *              {
         *                  if (coId != coId1 && coId != coId2)
         *                  {
         *                      adjCoId = coId;
         *                      break;
         *                  }
         *              }
         *              System.Diagnostics.Debug.Assert(adjCoId != -1);
         *          }
         *          int wAdjNodeId = -1;
         *          wAdjNodeId = World.Coord2Node(wQuantityId, adjCoId); // 特殊な場合-1はありえる
         *          int pAdjNodeId = -1;
         *          pAdjNodeId = World.Coord2Node(pQuantityId, adjCoId); // 特殊な場合-1はありえる
         *          double[] pt1 = World.GetCoord(wQuantityId, coId1);
         *          double[] pt2 = World.GetCoord(wQuantityId, coId2);
         *          double[] adjPt = World.GetCoord(wQuantityId, adjCoId);
         *          double hn = IvyFEM.CadUtils.TriHeight(
         *              new OpenTK.Vector2d(adjPt[0], adjPt[1]), // 点
         *              new OpenTK.Vector2d(pt1[0], pt1[1]), // 辺の点1
         *              new OpenTK.Vector2d(pt2[0], pt2[1]) // 辺の点2
         *              );
         *
         *          for (int row = 0; row < elemNodeCnt; row++)
         *          {
         *              int rowCoId = wCoIds[row];
         *              int rowNodeId = wNodes[row];
         *              if (rowNodeId == -1)
         *              {
         *                  continue;
         *              }
         *              for (int colNodeId = 0; colNodeId < wNodeCnt; colNodeId++)
         *              {
         *                  int colCoId = World.Node2Coord(wQuantityId, colNodeId);
         *                  if (colCoId == rowCoId)
         *                  {
         *                      A[rowNodeId, colNodeId] += -mu * (3.0 / hn) * sN[row];
         *                  }
         *              }
         *              for (int colNodeId = 0; colNodeId < pNodeCnt; colNodeId++)
         *              {
         *                  int colCoId = World.Node2Coord(pQuantityId, colNodeId);
         *                  if (colCoId == rowCoId)
         *                  {
         *                      A[rowNodeId, offset + colNodeId] += mu * (6.0 / (hn * hn * hn)) * sN[row];
         *                  }
         *                  else if (pAdjNodeId != -1 && colNodeId == pAdjNodeId)
         *                  {
         *                      A[rowNodeId, offset + colNodeId] += -mu * (6.0 / (hn * hn * hn)) * sN[row];
         *                  }
         *              }
         *              B[rowNodeId] += mu * (normal[0] * pxValue + normal[1] * pyValue) * (6.0 / (hn * hn)) * sN[row];
         *          }
         *      }
         *  }
         * }
         */

        protected void GetVelocityFromVorticityStream()
        {
            uint wQuantityId = 0;
            uint pQuantityId = 1;
            int  wNodeCnt    = (int)World.GetNodeCount(wQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = wNodeCnt;
            int  wCoCnt      = (int)World.GetCoordCount(wQuantityId);
            int  pCoCnt      = (int)World.GetCoordCount(pQuantityId);

            int vDof = 2;

            CoordV = new double[pCoCnt * vDof]; // nodeでなくcoord

            IList <uint> feIds = World.GetTriangleFEIds(pQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId);

                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(pTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double[] g   = { ma.GravityX, ma.GravityY };

                for (int row = 0; row < pElemNodeCnt; row++)
                {
                    int        rowCoId = pCoIds[row];
                    double[]   L       = pTriFE.GetNodeL(row);
                    double[]   pN      = pTriFE.CalcN(L);
                    double[][] pNu     = pTriFE.CalcNu(L);
                    double[]   pNx     = pNu[0];
                    double[]   pNy     = pNu[1];
                    double     p       = 0;
                    double     px      = 0;
                    double     py      = 0;
                    for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                    {
                        int nodeId = pNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double pValue = U[offset + nodeId];
                        p  += pValue * pN[iNode];
                        px += pValue * pNx[iNode];
                        py += pValue * pNy[iNode];
                    }
                    double[] v = new double[2];
                    v[0] = py;
                    v[1] = -px;

                    for (int rowDof = 0; rowDof < vDof; rowDof++)
                    {
                        CoordV[rowCoId * vDof + rowDof] = v[rowDof];
                    }
                }
            }
        }
예제 #13
0
 public TriangleFE(TriangleFE src)
 {
     Copy(src);
 }
예제 #14
0
        protected void CalcLinearElasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint quantityId = 0;
            int  nodeCnt    = (int)World.GetNodeCount(quantityId);

            System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2);
            int dof = 2;

            TriangleFE triFE = World.GetTriangleFE(quantityId, feId);
            Material   ma0   = World.GetMaterial(triFE.MaterialId);

            if (!(ma0 is LinearElasticMaterial))
            {
                return;
            }
            int[] coIds       = triFE.NodeCoordIds;
            uint  elemNodeCnt = triFE.NodeCount;

            int[] nodes = new int[elemNodeCnt];
            for (int iNode = 0; iNode < elemNodeCnt; iNode++)
            {
                int coId   = coIds[iNode];
                int nodeId = World.Coord2Node(quantityId, coId);
                nodes[iNode] = nodeId;
            }

            var    ma     = ma0 as LinearElasticMaterial;
            double lambda = ma.LameLambda;
            double mu     = ma.LameMu;
            double rho    = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] sN = triFE.CalcSN();
            double[,] sNN       = triFE.CalcSNN();
            double[, ][,] sNuNv = triFE.CalcSNuNv();
            double[,] sNxNx     = sNuNv[0, 0];
            double[,] sNyNx     = sNuNv[1, 0];
            double[,] sNxNy     = sNuNv[0, 1];
            double[,] sNyNy     = sNuNv[1, 1];

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int col = 0; col < elemNodeCnt; col++)
                {
                    int colNodeId = nodes[col];
                    if (colNodeId == -1)
                    {
                        continue;
                    }

                    double[,] k = new double[dof, dof];
                    double[,] m = new double[dof, dof];
                    k[0, 0]     = (lambda + mu) * sNxNx[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]);
                    k[1, 0]     = lambda * sNyNx[row, col] + mu * sNxNy[row, col];
                    k[0, 1]     = lambda * sNxNy[row, col] + mu * sNyNx[row, col];
                    k[1, 1]     = (lambda + mu) * sNyNy[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]);

                    for (int rowDof = 0; rowDof < dof; rowDof++)
                    {
                        for (int colDof = 0; colDof < dof; colDof++)
                        {
                            A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] +=
                                k[rowDof, colDof];
                        }
                    }
                }
            }

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < dof; rowDof++)
                {
                    B[rowNodeId * dof + rowDof] += rho * g[rowDof] * sN[row];
                }
            }
        }
예제 #15
0
        // 境界が流線方向と同じとき
        // ψの法線成分(速度の接線成分に比例)がある
        // ψ = const or 0
        // Taylor級数展開 2次までの項を考慮
        protected void SetVorticityDirichletBCOfVorticityForTangentFlow(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint wQuantityId = 0;
            uint pQuantityId = 1;
            int  wNodeCnt    = (int)World.GetNodeCount(wQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = wNodeCnt;

            if (World.GetPortCount(wQuantityId) == 0)
            {
                return;
            }
            uint portCnt = World.GetPortCount(wQuantityId);
            IList <PortCondition> portConditions = World.GetPortConditions(wQuantityId);
            IList <uint>          feIds          = World.GetLineFEIds(wQuantityId);

            for (int portId = 0; portId < portCnt; portId++)
            {
                PortCondition portCondition = portConditions[portId];
                //IList<int> intParam = portCondition.IntAdditionalParameters;
                //System.Diagnostics.Debug.Assert(intParam.Count == 0);
                IList <uint>   bcEIds = portCondition.EIds;
                IList <double> param  = portCondition.DoubleAdditionalParameters;
                System.Diagnostics.Debug.Assert(param.Count == 2); // 0: dψ/dx 1: dψ/dy
                double pxValue = param[0];
                double pyValue = param[1];

                foreach (uint feId in feIds)
                {
                    LineFE lineFE = World.GetLineFE(wQuantityId, feId);
                    uint   meshId = lineFE.MeshId;
                    //int meshElemId = lineFE.MeshElemId;
                    uint eId;
                    {
                        uint     elemCount;
                        MeshType meshType;
                        int      loc;
                        uint     cadId;
                        World.Mesh.GetMeshInfo(meshId, out elemCount, out meshType, out loc, out cadId);
                        System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
                        eId = cadId;
                    }
                    if (bcEIds.Contains(eId))
                    {
                        // BCを適用する辺
                    }
                    else
                    {
                        continue;
                    }

                    // BC
                    uint  elemNodeCnt = lineFE.NodeCount;
                    int[] wCoIds      = lineFE.NodeCoordIds;
                    int[] wNodes      = new int[elemNodeCnt];
                    int[] pNodes      = new int[elemNodeCnt];
                    for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                    {
                        int coId = wCoIds[iNode];
                        wNodes[iNode] = World.Coord2Node(wQuantityId, coId);
                        pNodes[iNode] = World.Coord2Node(pQuantityId, coId);
                    }

                    Material ma0 = World.GetMaterial(lineFE.MaterialId);
                    System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                    var      ma  = ma0 as NewtonFluidMaterial;
                    double   rho = ma.MassDensity;
                    double   mu  = ma.Mu;
                    double[] g   = { ma.GravityX, ma.GravityY };

                    double[] normal = lineFE.GetNormal();

                    int coId1   = wCoIds[0];
                    int coId2   = wCoIds[1];
                    int adjCoId = -1; // adjacent
                    {
                        IList <uint> triFEIds   = World.GetTriangleFEIdsFromEdgeCoord(wQuantityId, coId1, coId2);
                        uint         triFEId    = triFEIds[0];
                        TriangleFE   triFE      = World.GetTriangleFE(wQuantityId, triFEId);
                        int[]        triFECoIds = triFE.NodeCoordIds;
                        foreach (int coId in triFECoIds)
                        {
                            if (coId != coId1 && coId != coId2)
                            {
                                adjCoId = coId;
                                break;
                            }
                        }
                        System.Diagnostics.Debug.Assert(adjCoId != -1);
                    }
                    //int wAdjNodeId = -1;
                    //wAdjNodeId = World.Coord2Node(wQuantityId, adjCoId); // 特殊な場合-1はありえる
                    int pAdjNodeId = -1;
                    pAdjNodeId = World.Coord2Node(pQuantityId, adjCoId); // 特殊な場合-1はありえる
                    double[] pt1   = World.GetCoord(wQuantityId, coId1);
                    double[] pt2   = World.GetCoord(wQuantityId, coId2);
                    double[] adjPt = World.GetCoord(wQuantityId, adjCoId);
                    double   hn    = IvyFEM.CadUtils.TriHeight(
                        new OpenTK.Vector2d(adjPt[0], adjPt[1]), // 点
                        new OpenTK.Vector2d(pt1[0], pt1[1]),     // 辺の点1
                        new OpenTK.Vector2d(pt2[0], pt2[1])      // 辺の点2
                        );

                    for (int row = 0; row < elemNodeCnt; row++)
                    {
                        int rowCoId   = wCoIds[row];
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int colNodeId = 0; colNodeId < wNodeCnt; colNodeId++)
                        {
                            int colCoId = World.Node2Coord(wQuantityId, colNodeId);
                            if (colCoId == rowCoId)
                            {
                                A[rowNodeId, colNodeId] = 1.0;
                            }
                            else
                            {
                                A[rowNodeId, colNodeId] = 0;
                            }
                        }
                        for (int colNodeId = 0; colNodeId < pNodeCnt; colNodeId++)
                        {
                            int colCoId = World.Node2Coord(pQuantityId, colNodeId);
                            if (colCoId == rowCoId)
                            {
                                A[rowNodeId, offset + colNodeId] = -2.0 / (hn * hn);
                            }
                            else if (pAdjNodeId != -1 && colNodeId == pAdjNodeId)
                            {
                                A[rowNodeId, offset + colNodeId] = 2.0 / (hn * hn);
                            }
                            else
                            {
                                A[rowNodeId, offset + colNodeId] = 0;
                            }
                        }
                        B[rowNodeId] = -(normal[0] * pxValue + normal[1] * pyValue) * (2.0 / hn);
                    }
                }
            }
        }
예제 #16
0
        // 座標、三角形要素と線要素を生成する
        private void MakeCoordsAndElements(
            FEWorld world,
            IList <double> vertexCoords,
            Dictionary <uint, uint> cadLoop2Material,
            Dictionary <uint, uint> cadEdge2Material)
        {
            Mesher2D mesh = world.Mesh;

            System.Diagnostics.Debug.Assert(mesh != null);

            if (FEOrder == 1)
            {
                Coords = new List <double>(vertexCoords);
            }
            else if (FEOrder == 2)
            {
                Coords = new List <double>(vertexCoords);
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            IList <uint> meshIds = mesh.GetIds();

            //////////////////////////////////////////////////
            // 領域の三角形要素
            // まず要素を作る
            // この順番で生成した要素は隣接していない
            Dictionary <string, IList <int> > edge2MidPt = new Dictionary <string, IList <int> >();

            foreach (uint meshId in meshIds)
            {
                uint     elemCnt;
                MeshType meshType;
                int      loc;
                uint     cadId;
                mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId);
                if (meshType != MeshType.Tri)
                {
                    continue;
                }

                if (!cadLoop2Material.ContainsKey(cadId))
                {
                    throw new IndexOutOfRangeException();
                }
                uint maId = cadLoop2Material[cadId];

                int elemVertexCnt = 3;
                int elemNodeCnt   = 0;
                if (FEOrder == 1)
                {
                    elemNodeCnt = 3;
                }
                else if (FEOrder == 2)
                {
                    elemNodeCnt = 6;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                MeshType dummyMeshType;
                int[]    vertexs;
                mesh.GetConnectivity(meshId, out dummyMeshType, out vertexs);
                System.Diagnostics.Debug.Assert(meshType == dummyMeshType);
                System.Diagnostics.Debug.Assert(elemVertexCnt * elemCnt == vertexs.Length);

                for (int iElem = 0; iElem < elemCnt; iElem++)
                {
                    int[] vertexCoIds = new int[elemVertexCnt];
                    for (int iPt = 0; iPt < elemVertexCnt; iPt++)
                    {
                        int coId = vertexs[iElem * elemVertexCnt + iPt];
                        vertexCoIds[iPt] = coId;
                    }
                    int[] nodeCoIds = new int[elemNodeCnt];
                    if (FEOrder == 1)
                    {
                        System.Diagnostics.Debug.Assert(nodeCoIds.Length == vertexCoIds.Length);
                        vertexCoIds.CopyTo(nodeCoIds, 0);
                    }
                    else if (FEOrder == 2)
                    {
                        for (int i = 0; i < elemVertexCnt; i++)
                        {
                            nodeCoIds[i] = vertexCoIds[i];

                            {
                                int v1 = vertexCoIds[i];
                                int v2 = vertexCoIds[(i + 1) % elemVertexCnt];
                                if (v1 > v2)
                                {
                                    int tmp = v1;
                                    v1 = v2;
                                    v2 = tmp;
                                }
                                string edgeKey   = v1 + "_" + v2;
                                int    midPtCoId = -1;
                                if (edge2MidPt.ContainsKey(edgeKey))
                                {
                                    midPtCoId = edge2MidPt[edgeKey][0];
                                }
                                else
                                {
                                    double[] vPt1  = world.GetVertexCoord(v1);
                                    double[] vPt2  = world.GetVertexCoord(v2);
                                    double[] midPt = { (vPt1[0] + vPt2[0]) / 2.0, (vPt1[1] + vPt2[1]) / 2.0 };
                                    midPtCoId = (int)(Coords.Count / Dimension);
                                    Coords.Add(midPt[0]);
                                    Coords.Add(midPt[1]);
                                    var list = new List <int>();
                                    list.Add(midPtCoId);
                                    edge2MidPt[edgeKey] = list;
                                }

                                nodeCoIds[i + elemVertexCnt] = midPtCoId;
                            }
                        }
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    TriangleFE fe = new TriangleFE((int)FEOrder);
                    fe.World = world;
                    fe.SetVertexCoordIds(vertexCoIds);
                    fe.SetNodeCoordIds(nodeCoIds);
                    fe.MaterialId = maId;
                    fe.MeshId     = meshId;
                    fe.MeshElemId = iElem;
                    // 仮登録
                    uint freeId = TriangleFEArray.GetFreeObjectId();
                    uint feId   = TriangleFEArray.AddObject(freeId, fe);
                    System.Diagnostics.Debug.Assert(feId == freeId);
                }
            }

            //////////////////////////////////////////////////
            // 境界の線要素
            foreach (uint meshId in meshIds)
            {
                uint     elemCnt;
                MeshType meshType;
                int      loc;
                uint     cadId;
                mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId);
                if (meshType != MeshType.Bar)
                {
                    continue;
                }

                int elemVertexCnt = 2;
                int elemNodeCnt   = 0;
                if (FEOrder == 1)
                {
                    elemNodeCnt = 2;
                }
                else if (FEOrder == 2)
                {
                    elemNodeCnt = 3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                MeshType dummyMeshType;
                int[]    vertexs;
                mesh.GetConnectivity(meshId, out dummyMeshType, out vertexs);
                System.Diagnostics.Debug.Assert(meshType == dummyMeshType);
                System.Diagnostics.Debug.Assert(elemVertexCnt * elemCnt == vertexs.Length);

                //System.Diagnostics.Debug.Assert(CadEdge2Material.ContainsKey(cadId));
                //if (!CadEdge2Material.ContainsKey(cadId))
                //{
                //    throw new IndexOutOfRangeException();
                //}
                // 未指定のマテリアルも許容する
                uint maId = cadEdge2Material.ContainsKey(cadId) ? cadEdge2Material[cadId] : 0;

                for (int iElem = 0; iElem < elemCnt; iElem++)
                {
                    int[] vertexCoIds = new int[elemVertexCnt];
                    for (int iPt = 0; iPt < elemVertexCnt; iPt++)
                    {
                        int coId = vertexs[iElem * elemVertexCnt + iPt];
                        vertexCoIds[iPt] = coId;
                    }
                    int[] nodeCoIds = new int[elemNodeCnt];
                    if (FEOrder == 1)
                    {
                        System.Diagnostics.Debug.Assert(nodeCoIds.Length == vertexCoIds.Length);
                        vertexCoIds.CopyTo(nodeCoIds, 0);
                    }
                    else if (FEOrder == 2)
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            nodeCoIds[i] = vertexCoIds[i];
                        }
                        // 線要素上の中点
                        int v1 = vertexCoIds[0];
                        int v2 = vertexCoIds[1];
                        if (v1 > v2)
                        {
                            int tmp = v1;
                            v1 = v2;
                            v2 = tmp;
                        }
                        string edgeKey = v1 + "_" + v2;
                        if (!edge2MidPt.ContainsKey(edgeKey))
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        int midPtCoId = edge2MidPt[edgeKey][0];
                        nodeCoIds[2] = midPtCoId;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    LineFE fe = new LineFE((int)FEOrder);
                    fe.World = world;
                    fe.SetVertexCoordIds(vertexCoIds);
                    fe.SetNodeCoordIds(nodeCoIds);
                    fe.MaterialId = maId;
                    fe.MeshId     = meshId;
                    fe.MeshElemId = iElem;
                    uint freeId = LineFEArray.GetFreeObjectId();
                    uint feId   = LineFEArray.AddObject(freeId, fe);
                    System.Diagnostics.Debug.Assert(feId == freeId);

                    string key = string.Format(meshId + "_" + iElem);
                    Mesh2LineFE.Add(key, feId);
                }
            }
        }
예제 #17
0
        protected void CalcOgdenHyperelasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint uQuantityId = 0;
            uint lQuantityId = 1;

            System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2);
            System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1);
            int uDof     = 2;
            int lDof     = 1;
            int uNodeCnt = (int)World.GetNodeCount(uQuantityId);
            int lNodeCnt = (int)World.GetNodeCount(lQuantityId);
            //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength);
            int offset = GetOffset(lQuantityId);

            System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof);

            TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId);
            TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId);
            Material   ma0    = World.GetMaterial(uTriFE.MaterialId);

            if (!(ma0 is OgdenHyperelasticMaterial))
            {
                return;
            }

            uint vertexCnt = uTriFE.VertexCount;

            for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
            {
                System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]);
            }
            int[] uCoIds       = uTriFE.NodeCoordIds;
            uint  uElemNodeCnt = uTriFE.NodeCount;

            int[] uNodes = new int[uElemNodeCnt];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                int coId   = uCoIds[iNode];
                int nodeId = World.Coord2Node(uQuantityId, coId);
                uNodes[iNode] = nodeId;
            }
            int[] lCoIds       = lTriFE.NodeCoordIds;
            uint  lElemNodeCnt = lTriFE.NodeCount;

            int[] lNodes = new int[lElemNodeCnt];
            for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
            {
                int coId   = lCoIds[iNode];
                int nodeId = World.Coord2Node(lQuantityId, coId);
                lNodes[iNode] = nodeId;
            }

            var    ma             = ma0 as OgdenHyperelasticMaterial;
            bool   isCompressible = ma.IsCompressible;
            double d1             = ma.D1;
            int    oOrder         = ma.Order;

            double[] oMus    = ma.Mus;
            double[] oAlphas = ma.Alphas;
            double   rho     = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] uSN = uTriFE.CalcSN();
            double[,] lSNN = lTriFE.CalcSNN();
            System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3);
            IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);

            System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount);

            double[,] qu = new double[uElemNodeCnt, uDof];
            double[] ql = new double[lElemNodeCnt];

            for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
            {
                double[]   L          = ip.Ls[ipPt];
                double[]   uN         = uTriFE.CalcN(L);
                double[]   lN         = lTriFE.CalcN(L);
                double[][] uNu        = uTriFE.CalcNu(L);
                double     detJ       = uTriFE.GetDetJacobian(L);
                double     weight     = ip.Weights[ipPt];
                double     detJWeight = (1.0 / 2.0) * weight * detJ;

                // 変位の微分
                double[,] uu = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                        {
                            int iNodeId = uNodes[iNode];
                            if (iNodeId == -1)
                            {
                                continue;
                            }
                            uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode];
                        }
                    }
                }

                // ラグランジュの未定乗数
                double l = 0;
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    int iNodeId = lNodes[iNode];
                    if (iNodeId == -1)
                    {
                        continue;
                    }
                    l += U[offset + iNodeId] * lN[iNode];
                }

                // Green-Lagrangeのひずみ
                double[,] e = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]);
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                }

                // 変形勾配テンソル
                double[,] f = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        f[iDof, jDof] = uu[iDof, jDof];
                    }
                    f[iDof, iDof] += 1.0;
                }

                // 右Cauchy-Green変形テンソル
                double[,] c = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof];
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                    c[iDof, iDof] += 1.0;
                }

                // Cのテンソル不変量
                double I1      = c[0, 0] + c[1, 1] + 1.0;
                double I2      = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0];
                double I3      = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0];
                double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0);
                double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0);
                double[,] invC = new double[uDof, uDof];
                {
                    double invI3 = 1.0 / I3;
                    invC[0, 0] = invI3 * c[1, 1];
                    invC[0, 1] = -invI3 * c[0, 1];
                    invC[1, 0] = -invI3 * c[1, 0];
                    invC[1, 1] = invI3 * c[0, 0];
                }

                // Cの主値の1/2乗と主軸
                // Note: これらは3次元
                int dim3 = 3;
                System.Numerics.Complex[]   fLambdas;
                System.Numerics.Complex[][] cNormals;
                SolvePrincipalValues(c, out fLambdas, out cNormals);
                double inv16I3 = 1.0 / Math.Pow(I3, 1.0 / 6.0);
                // 修正Cの主値
                System.Numerics.Complex[] barFLambdas = fLambdas.Select(a => a * inv16I3).ToArray();

                // 主第2Piola-Kirchhoff応力
                System.Numerics.Complex[] principalS = new System.Numerics.Complex[uDof];

                /*
                 * for (int kDof = 0; kDof < uDof; kDof++)
                 * {
                 *  for (int r = 0; r < oOrder; r++)
                 *  {
                 *      double mu = oMus[r];
                 *      double alpha = oAlphas[r];
                 *      principalS[kDof] += (mu / (fLambdas[kDof] * fLambdas[kDof])) * (
                 *          System.Numerics.Complex.Pow(barFLambdas[kDof], alpha) -
                 *          (1.0 / 3.0) * (
                 *          System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                 *          System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                 *          System.Numerics.Complex.Pow(barFLambdas[2], alpha)
                 *          ));
                 *  }
                 * }
                 */
                for (int kDof = 0; kDof < uDof; kDof++)
                {
                    for (int r = 0; r < oOrder; r++)
                    {
                        double mu    = oMus[r];
                        double alpha = oAlphas[r];
                        principalS[kDof] += (mu / (fLambdas[kDof] * fLambdas[kDof])) * (
                            System.Numerics.Complex.Pow(barFLambdas[kDof], alpha) -
                            (1.0 / 3.0) * (
                                System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                                System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                                Math.Pow(I3, -alpha / 6.0)
                                ));
                    }
                }

                // 第2Piola-Kirchhoff応力
                double[,] s = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            System.Numerics.Complex sij =
                                principalS[kDof] * cNormals[kDof][iDof] * cNormals[kDof][jDof];
                            s[iDof, jDof] += sij.Real;
                            //System.Diagnostics.Debug.Assert(
                            //    Math.Abs(sij.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit);
                        }
                    }
                }
                // Lagrangeの未定乗数の寄与項
                {
                    double tmp = 2.0 * l * I3;
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int jDof = 0; jDof < uDof; jDof++)
                        {
                            s[iDof, jDof] += tmp * invC[iDof, jDof];
                        }
                    }
                }

                // 主軸構成則テンソル(オリジナルの方)
                System.Numerics.Complex[,] principalC21st = new System.Numerics.Complex[uDof, uDof];
                System.Numerics.Complex[,] principalC22nd = new System.Numerics.Complex[uDof, uDof];

                /*
                 * for (int pDof = 0; pDof < uDof; pDof++)
                 * {
                 *  for (int qDof = 0; qDof < uDof; qDof++)
                 *  {
                 *      for (int r = 0; r < oOrder; r++)
                 *      {
                 *          double mu = oMus[r];
                 *          double alpha = oAlphas[r];
                 *          System.Numerics.Complex tmp1 = 0;
                 *          if (pDof == qDof)
                 *          {
                 *              tmp1 = -2.0 * (
                 *                  System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) -
                 *                  (1.0 / 3.0) * (
                 *                  System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                 *                  System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                 *                  System.Numerics.Complex.Pow(barFLambdas[2], alpha)
                 *                  ));
                 *          }
                 *          System.Numerics.Complex tmp2 = 0;
                 *          for (int mDof = 0; mDof < dim3; mDof++)
                 *          {
                 *              double dmp = mDof == pDof ? 1 : 0;
                 *              double dmq = mDof == qDof ? 1 : 0;
                 *              tmp2 += alpha *
                 *                  System.Numerics.Complex.Pow(barFLambdas[mDof], alpha) *
                 *                  (dmp - 1.0 / 3.0) *
                 *                  (dmq - 1.0 / 3.0);
                 *          }
                 *          principalC21st[pDof, qDof] +=
                 *              (mu / (fLambdas[pDof] * fLambdas[pDof] * fLambdas[qDof] * fLambdas[qDof])) *
                 *              (tmp1 + tmp2);
                 *      }
                 *  }
                 * }
                 * for (int pDof = 0; pDof < uDof; pDof++)
                 * {
                 *  for (int qDof = 0; qDof < uDof; qDof++)
                 *  {
                 *      for (int r = 0; r < oOrder; r++)
                 *      {
                 *          double mu = oMus[r];
                 *          double alpha = oAlphas[r];
                 *          System.Numerics.Complex tmp = 0;
                 *          if (pDof != qDof)
                 *          {
                 *              System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof];
                 *              if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit)
                 *              {
                 *                  // λp != λq
                 *                  System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof];
                 *                  System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof];
                 *                  tmp = (mu / (squareFLambdaP * squareFLambdaQ)) * (
                 *                      (
                 *                      squareFLambdaQ * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) -
                 *                      squareFLambdaP * System.Numerics.Complex.Pow(barFLambdas[qDof], alpha)
                 *                      ) / (squareFLambdaP - squareFLambdaQ) +
                 *                      (1.0 / 3.0) *
                 *                      (
                 *                      System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                 *                      System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                 *                      System.Numerics.Complex.Pow(barFLambdas[2], alpha)
                 *                      ));
                 *              }
                 *              else
                 *              {
                 *                  // λp == λq
                 *                  tmp = (mu /
                 *                      (fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof])) * (
                 *                      -((2.0 - alpha) / 2.0) *
                 *                      System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) +
                 *                      (1.0 / 3.0) * (
                 *                      System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                 *                      System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                 *                      System.Numerics.Complex.Pow(barFLambdas[2], alpha)
                 *                      ));
                 *              }
                 *              principalC22nd[pDof, qDof] += tmp;
                 *          }
                 *      }
                 *  }
                 * }
                 */
                uint dim2 = 2;
                for (int pDof = 0; pDof < uDof; pDof++)
                {
                    for (int qDof = 0; qDof < uDof; qDof++)
                    {
                        for (int r = 0; r < oOrder; r++)
                        {
                            double mu    = oMus[r];
                            double alpha = oAlphas[r];
                            System.Numerics.Complex tmp1 = 0;
                            if (pDof == qDof)
                            {
                                tmp1 = -2.0 * (
                                    System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) -
                                    (1.0 / 3.0) * (
                                        System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                                        System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                                        Math.Pow(I3, -alpha / 6.0)
                                        ));
                            }
                            System.Numerics.Complex tmp2 = 0;
                            for (int mDof = 0; mDof < dim2; mDof++)
                            {
                                double dmp = mDof == pDof ? 1 : 0;
                                double dmq = mDof == qDof ? 1 : 0;
                                tmp2 += alpha *
                                        System.Numerics.Complex.Pow(barFLambdas[mDof], alpha) *
                                        (dmp - 1.0 / 3.0) *
                                        (dmq - 1.0 / 3.0);
                            }
                            tmp2 += (alpha / 9.0) * Math.Pow(I3, -alpha / 6.0);
                            principalC21st[pDof, qDof] +=
                                (mu / (fLambdas[pDof] * fLambdas[pDof] * fLambdas[qDof] * fLambdas[qDof])) *
                                (tmp1 + tmp2);
                        }
                    }
                }
                for (int pDof = 0; pDof < uDof; pDof++)
                {
                    for (int qDof = 0; qDof < uDof; qDof++)
                    {
                        for (int r = 0; r < oOrder; r++)
                        {
                            double mu    = oMus[r];
                            double alpha = oAlphas[r];
                            if (pDof != qDof)
                            {
                                System.Numerics.Complex tmp         = 0;
                                System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof];
                                if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit)
                                {
                                    // λp != λq
                                    System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof];
                                    System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof];
                                    tmp = (mu / (squareFLambdaP * squareFLambdaQ)) * (
                                        (
                                            squareFLambdaQ * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) -
                                            squareFLambdaP * System.Numerics.Complex.Pow(barFLambdas[qDof], alpha)
                                        ) / (squareFLambdaP - squareFLambdaQ) +
                                        (1.0 / 3.0) *
                                        (
                                            System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                                            System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                                            System.Numerics.Complex.Pow(I3, -alpha / 6.0)
                                        ));
                                }
                                else
                                {
                                    // λp == λq
                                    tmp = (mu /
                                           (fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof])) * (
                                        -((2.0 - alpha) / 2.0) *
                                        System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) +
                                        (1.0 / 3.0) * (
                                            System.Numerics.Complex.Pow(barFLambdas[0], alpha) +
                                            System.Numerics.Complex.Pow(barFLambdas[1], alpha) +
                                            System.Numerics.Complex.Pow(I3, -alpha / 6.0)
                                            ));
                                }
                                principalC22nd[pDof, qDof] += tmp;
                            }
                        }
                    }
                }

                // 構成則テンソル(オリジナルの方)
                double[,,,] c4 = new double[uDof, uDof, uDof, uDof];
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                for (int pDof = 0; pDof < uDof; pDof++)
                                {
                                    for (int qDof = 0; qDof < uDof; qDof++)
                                    {
                                        System.Numerics.Complex c4ghef =
                                            principalC21st[pDof, qDof] *
                                            cNormals[pDof][gDof] * cNormals[pDof][hDof] *
                                            cNormals[qDof][eDof] * cNormals[qDof][fDof] +
                                            principalC22nd[pDof, qDof] *
                                            cNormals[pDof][gDof] * cNormals[qDof][hDof] *
                                            (
                                                cNormals[pDof][eDof] * cNormals[qDof][fDof] +
                                                cNormals[qDof][eDof] * cNormals[pDof][fDof]
                                            );
                                        c4[gDof, hDof, eDof, fDof] += c4ghef.Real;
                                        //System.Diagnostics.Debug.Assert(
                                        //    Math.Abs(c4ghef.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit);
                                    }
                                }
                            }
                        }
                    }
                }
                // 構成則テンソル
                double[,,,] barC4 = new double[uDof, uDof, uDof, uDof];
                // 圧力構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                barC4[gDof, hDof, eDof, fDof] +=
                                    4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] -
                                    2.0 * l * I3 * (
                                        invC[gDof, eDof] * invC[fDof, hDof] +
                                        invC[gDof, fDof] * invC[eDof, hDof]);
                            }
                        }
                    }
                }
                // 変位構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                barC4[gDof, hDof, eDof, fDof] +=
                                    (1.0 / 2.0) * (c4[gDof, hDof, eDof, fDof] + c4[gDof, hDof, fDof, eDof]);
                            }
                        }
                    }
                }

                double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof];
                {
                    for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                    {
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof];
                                }
                            }
                        }
                    }
                }

                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < uElemNodeCnt; col++)
                    {
                        int colNodeId = uNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kuu = new double[uDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                double tmp1 = 0.0;
                                for (int gDof = 0; gDof < uDof; gDof++)
                                {
                                    for (int hDof = 0; hDof < uDof; hDof++)
                                    {
                                        for (int eDof = 0; eDof < uDof; eDof++)
                                        {
                                            for (int fDof = 0; fDof < uDof; fDof++)
                                            {
                                                tmp1 += barC4[gDof, hDof, eDof, fDof] *
                                                        b[row, rowDof, eDof, fDof] *
                                                        b[col, colDof, gDof, hDof];
                                            }
                                        }
                                    }
                                }
                                kuu[rowDof, colDof] += detJWeight * tmp1;
                            }
                        }
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col];
                                }
                            }
                            for (int rowDof = 0; rowDof < uDof; rowDof++)
                            {
                                kuu[rowDof, rowDof] += detJWeight * tmp;
                            }
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] +=
                                    kuu[rowDof, colDof];
                                B[rowNodeId * uDof + rowDof] +=
                                    kuu[rowDof, colDof] * U[colNodeId * uDof + colDof];
                            }
                        }
                    }
                }
                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < lElemNodeCnt; col++)
                    {
                        int colNodeId = lNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kul = new double[uDof, lDof];
                        double[,] klu = new double[lDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof];
                                }
                            }

                            kul[rowDof, 0] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                            klu[0, rowDof] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0];
                            A[offset + colNodeId, rowNodeId *uDof + rowDof]  += klu[0, rowDof];
                            B[rowNodeId * uDof + rowDof] +=
                                kul[rowDof, 0] * U[offset + colNodeId];
                            B[offset + colNodeId] +=
                                klu[0, rowDof] * U[rowNodeId * uDof + rowDof];
                        }
                    }
                }

                // Note: kllは数値積分しなくて求められる

                for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                {
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int gDof = 0; gDof < uDof; gDof++)
                        {
                            for (int hDof = 0; hDof < uDof; hDof++)
                            {
                                qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof];
                            }
                        }
                    }
                }
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    if (isCompressible)
                    {
                        ql[iNode] += detJWeight * lN[iNode] * ((I3 - 1) - l / d1);
                    }
                    else
                    {
                        ql[iNode] += detJWeight * lN[iNode] * (I3 - 1);
                    }
                }
            }

            if (isCompressible)
            {
                for (int row = 0; row < lElemNodeCnt; row++)
                {
                    int rowNodeId = lNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < lElemNodeCnt; col++)
                    {
                        int colNodeId = lNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double kll = -(1.0 / d1) * lSNN[row, col];
                        A[offset + rowNodeId, offset + colNodeId] += kll;
                        B[offset + rowNodeId] += kll * U[offset + colNodeId];
                    }
                }
            }

            double[,] fg = new double[uElemNodeCnt, uDof];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    fg[iNode, iDof] = rho * g[iDof] * uSN[iNode];
                }
            }

            for (int row = 0; row < uElemNodeCnt; row++)
            {
                int rowNodeId = uNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < uDof; rowDof++)
                {
                    B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof];
                }
            }
            for (int row = 0; row < lElemNodeCnt; row++)
            {
                int rowNodeId = lNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                B[offset + rowNodeId] += -ql[row];
            }
        }
예제 #18
0
        public IList <LineFE> MakeBoundOfElements(FEWorld world)
        {
            IList <LineFE>   boundOfTriangelFEs = new List <LineFE>();
            HashSet <string> edges = new HashSet <string>();

            var feIds = GetTriangleFEIds();

            foreach (uint feId in feIds)
            {
                TriangleFE triFE = GetTriangleFE(feId);
                System.Diagnostics.Debug.Assert(triFE.Order == FEOrder);
                int[][] vertexCoIds =
                {
                    new int[] { triFE.VertexCoordIds[0], triFE.VertexCoordIds[1] },
                    new int[] { triFE.VertexCoordIds[1], triFE.VertexCoordIds[2] },
                    new int[] { triFE.VertexCoordIds[2], triFE.VertexCoordIds[0] }
                };
                int[][] nodeCoIds = null;
                if (triFE.Order == 1)
                {
                    int[][] nodeCoIds1 =
                    {
                        new int[] { triFE.NodeCoordIds[0], triFE.NodeCoordIds[1] },
                        new int[] { triFE.NodeCoordIds[1], triFE.NodeCoordIds[2] },
                        new int[] { triFE.NodeCoordIds[2], triFE.NodeCoordIds[0] }
                    };
                    nodeCoIds = nodeCoIds1;
                }
                else if (triFE.Order == 2)
                {
                    int[][] nodeCoIds2 =
                    {
                        new int[] { triFE.NodeCoordIds[0], triFE.NodeCoordIds[1], triFE.NodeCoordIds[3] },
                        new int[] { triFE.NodeCoordIds[1], triFE.NodeCoordIds[2], triFE.NodeCoordIds[4] },
                        new int[] { triFE.NodeCoordIds[2], triFE.NodeCoordIds[0], triFE.NodeCoordIds[5] }
                    };
                    nodeCoIds = nodeCoIds2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int iEdge = 0; iEdge < 3; iEdge++)
                {
                    int v1 = vertexCoIds[iEdge][0];
                    int v2 = vertexCoIds[iEdge][1];
                    if (v1 > v2)
                    {
                        int tmp = v1;
                        v1 = v2;
                        v2 = tmp;
                    }
                    string edgeKey = v1 + "_" + v2;
                    if (edges.Contains(edgeKey))
                    {
                        continue;
                    }
                    else
                    {
                        edges.Add(edgeKey);
                    }
                    var lineFE = new LineFE((int)FEOrder);
                    lineFE.World = world;
                    lineFE.SetVertexCoordIds(vertexCoIds[iEdge]);
                    lineFE.SetNodeCoordIds(nodeCoIds[iEdge]);
                    // MeshId等は対応するものがないのでセットしない
                    boundOfTriangelFEs.Add(lineFE);
                }
            }
            return(boundOfTriangelFEs);
        }
        protected void CalcOgdenOriginalRivlinIncompressibleHyperelasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint uQuantityId = 0;
            uint lQuantityId = 1;

            System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2);
            System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1);
            int uDof     = 2;
            int lDof     = 1;
            int uNodeCnt = (int)World.GetNodeCount(uQuantityId);
            int lNodeCnt = (int)World.GetNodeCount(lQuantityId);
            //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength);
            int offset = GetOffset(lQuantityId);

            System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof);

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    uFV   = World.GetFieldValue(UValueId);

            TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId);
            TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId);
            Material   ma0    = World.GetMaterial(uTriFE.MaterialId);

            if (!(ma0 is OgdenHyperelasticMaterial))
            {
                return;
            }

            uint vertexCnt = uTriFE.VertexCount;

            for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
            {
                System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]);
            }
            int[] uCoIds       = uTriFE.NodeCoordIds;
            uint  uElemNodeCnt = uTriFE.NodeCount;

            int[] uNodes = new int[uElemNodeCnt];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                int coId   = uCoIds[iNode];
                int nodeId = World.Coord2Node(uQuantityId, coId);
                uNodes[iNode] = nodeId;
            }
            int[] lCoIds       = lTriFE.NodeCoordIds;
            uint  lElemNodeCnt = lTriFE.NodeCount;

            int[] lNodes = new int[lElemNodeCnt];
            for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
            {
                int coId   = lCoIds[iNode];
                int nodeId = World.Coord2Node(lQuantityId, coId);
                lNodes[iNode] = nodeId;
            }

            var ma     = ma0 as OgdenHyperelasticMaterial;
            int oOrder = ma.Order;

            double[] oMus    = ma.Mus;
            double[] oAlphas = ma.Alphas;
            double   rho     = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] uSN = uTriFE.CalcSN();
            double[,] uSNN = uTriFE.CalcSNN();
            System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3);
            IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);

            System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount);

            double[,] qu = new double[uElemNodeCnt, uDof];
            double[] ql = new double[lElemNodeCnt];

            for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
            {
                double[]   L          = ip.Ls[ipPt];
                double[]   uN         = uTriFE.CalcN(L);
                double[]   lN         = lTriFE.CalcN(L);
                double[][] uNu        = uTriFE.CalcNu(L);
                double     detJ       = uTriFE.GetDetJacobian(L);
                double     weight     = ip.Weights[ipPt];
                double     detJWeight = (1.0 / 2.0) * weight * detJ;

                // 変位の微分
                double[,] uu = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                        {
                            int iNodeId = uNodes[iNode];
                            if (iNodeId == -1)
                            {
                                continue;
                            }
                            uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode];
                        }
                    }
                }

                // ラグランジュの未定乗数
                double l = 0;
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    int iNodeId = lNodes[iNode];
                    if (iNodeId == -1)
                    {
                        continue;
                    }
                    l += U[offset + iNodeId] * lN[iNode];
                }

                // Green-Lagrangeのひずみ
                double[,] e = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]);
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                }

                // 変形勾配テンソル
                double[,] f = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        f[iDof, jDof] = uu[iDof, jDof];
                    }
                    f[iDof, iDof] += 1.0;
                }

                // 右Cauchy-Green変形テンソル
                double[,] c = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof];
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof];
                        }
                    }
                    c[iDof, iDof] += 1.0;
                }

                // Cのテンソル不変量
                double I1      = c[0, 0] + c[1, 1] + 1.0;
                double I2      = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0];
                double I3      = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0];
                double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0);
                double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0);
                double[,] invC = new double[uDof, uDof];
                {
                    double invI3 = 1.0 / I3;
                    invC[0, 0] = invI3 * c[1, 1];
                    invC[0, 1] = -invI3 * c[0, 1];
                    invC[1, 0] = -invI3 * c[1, 0];
                    invC[1, 1] = invI3 * c[0, 0];
                }

                // Cの主値の1/2乗と主軸
                // Note: これらは3次元
                int dim3 = 3;
                System.Numerics.Complex[]   fLambdas;
                System.Numerics.Complex[][] cNormals;
                SolvePrincipalValues(c, out fLambdas, out cNormals);
                double inv16I3 = 1.0 / Math.Pow(I3, 1.0 / 6.0);

                // 主第2Piola-Kirchhoff応力
                System.Numerics.Complex[] principalS = new System.Numerics.Complex[uDof];
                for (int kDof = 0; kDof < uDof; kDof++)
                {
                    for (int r = 0; r < oOrder; r++)
                    {
                        double mu    = oMus[r];
                        double alpha = oAlphas[r];
                        principalS[kDof] += mu *
                                            System.Numerics.Complex.Pow(fLambdas[kDof], alpha - 2);
                    }
                }

                // 第2Piola-Kirchhoff応力
                double[,] s = new double[uDof, uDof];
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    for (int jDof = 0; jDof < uDof; jDof++)
                    {
                        for (int kDof = 0; kDof < uDof; kDof++)
                        {
                            System.Numerics.Complex sij =
                                principalS[kDof] * cNormals[kDof][iDof] * cNormals[kDof][jDof];
                            s[iDof, jDof] += sij.Real;
                            //System.Diagnostics.Debug.Assert(
                            //    Math.Abs(sij.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit);
                        }
                    }
                }
                // Lagrangeの未定乗数の寄与項
                {
                    double tmp = 2.0 * l * I3;
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int jDof = 0; jDof < uDof; jDof++)
                        {
                            s[iDof, jDof] += tmp * invC[iDof, jDof];
                        }
                    }
                }

                // 主軸構成則テンソル(オリジナルの方)
                System.Numerics.Complex[,] principalC21st = new System.Numerics.Complex[uDof, uDof];
                System.Numerics.Complex[,] principalC22nd = new System.Numerics.Complex[uDof, uDof];
                for (int pDof = 0; pDof < uDof; pDof++)
                {
                    for (int qDof = 0; qDof < uDof; qDof++)
                    {
                        for (int r = 0; r < oOrder; r++)
                        {
                            double mu    = oMus[r];
                            double alpha = oAlphas[r];
                            System.Numerics.Complex tmp = 0;
                            if (pDof == qDof)
                            {
                                tmp = mu * (alpha - 2) *
                                      System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 4);
                            }
                            principalC21st[pDof, qDof] += tmp;
                        }
                    }
                }
                for (int pDof = 0; pDof < uDof; pDof++)
                {
                    for (int qDof = 0; qDof < uDof; qDof++)
                    {
                        for (int r = 0; r < oOrder; r++)
                        {
                            double mu    = oMus[r];
                            double alpha = oAlphas[r];
                            if (pDof != qDof)
                            {
                                System.Numerics.Complex tmp         = 0;
                                System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof];
                                if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit)
                                {
                                    // λp != λq
                                    System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof];
                                    System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof];
                                    tmp = (mu /
                                           (squareFLambdaP - squareFLambdaQ)) * (
                                        System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 2) -
                                        System.Numerics.Complex.Pow(fLambdas[qDof], alpha - 2));
                                }
                                else
                                {
                                    // λp == λq
                                    tmp = (1.0 / 2.0) * mu * (alpha - 2.0) *
                                          System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 4);
                                }
                                principalC22nd[pDof, qDof] += tmp;
                            }
                        }
                    }
                }

                // 構成則テンソル(オリジナルの方)
                double[,,,] c4 = new double[uDof, uDof, uDof, uDof];
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                for (int pDof = 0; pDof < uDof; pDof++)
                                {
                                    for (int qDof = 0; qDof < uDof; qDof++)
                                    {
                                        System.Numerics.Complex c4ghef =
                                            principalC21st[pDof, qDof] *
                                            cNormals[pDof][gDof] * cNormals[pDof][hDof] *
                                            cNormals[qDof][eDof] * cNormals[qDof][fDof] +
                                            principalC22nd[pDof, qDof] *
                                            cNormals[pDof][gDof] * cNormals[qDof][hDof] *
                                            (
                                                cNormals[pDof][eDof] * cNormals[qDof][fDof] +
                                                cNormals[qDof][eDof] * cNormals[pDof][fDof]
                                            );
                                        c4[gDof, hDof, eDof, fDof] += c4ghef.Real;
                                        //System.Diagnostics.Debug.Assert(
                                        //    Math.Abs(c4ghef.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit);
                                    }
                                }
                            }
                        }
                    }
                }
                // 構成則テンソル
                double[,,,] barC4 = new double[uDof, uDof, uDof, uDof];
                // 圧力構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                barC4[gDof, hDof, eDof, fDof] +=
                                    4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] -
                                    2.0 * l * I3 * (
                                        invC[gDof, eDof] * invC[fDof, hDof] +
                                        invC[gDof, fDof] * invC[eDof, hDof]);
                            }
                        }
                    }
                }
                // 変位構成則テンソル
                for (int gDof = 0; gDof < uDof; gDof++)
                {
                    for (int hDof = 0; hDof < uDof; hDof++)
                    {
                        for (int eDof = 0; eDof < uDof; eDof++)
                        {
                            for (int fDof = 0; fDof < uDof; fDof++)
                            {
                                barC4[gDof, hDof, eDof, fDof] +=
                                    (1.0 / 2.0) * (c4[gDof, hDof, eDof, fDof] + c4[gDof, hDof, fDof, eDof]);
                            }
                        }
                    }
                }

                double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof];
                {
                    for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                    {
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof];
                                }
                            }
                        }
                    }
                }

                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < uElemNodeCnt; col++)
                    {
                        int colNodeId = uNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kuu = new double[uDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                double tmp1 = 0.0;
                                for (int gDof = 0; gDof < uDof; gDof++)
                                {
                                    for (int hDof = 0; hDof < uDof; hDof++)
                                    {
                                        for (int eDof = 0; eDof < uDof; eDof++)
                                        {
                                            for (int fDof = 0; fDof < uDof; fDof++)
                                            {
                                                tmp1 += barC4[gDof, hDof, eDof, fDof] *
                                                        b[row, rowDof, eDof, fDof] *
                                                        b[col, colDof, gDof, hDof];
                                            }
                                        }
                                    }
                                }
                                kuu[rowDof, colDof] += detJWeight * tmp1;
                            }
                        }
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col];
                                }
                            }
                            for (int rowDof = 0; rowDof < uDof; rowDof++)
                            {
                                kuu[rowDof, rowDof] += detJWeight * tmp;
                            }
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            for (int colDof = 0; colDof < uDof; colDof++)
                            {
                                A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] +=
                                    kuu[rowDof, colDof];
                                B[rowNodeId * uDof + rowDof] +=
                                    kuu[rowDof, colDof] * U[colNodeId * uDof + colDof];
                            }
                        }
                    }
                }
                for (int row = 0; row < uElemNodeCnt; row++)
                {
                    int rowNodeId = uNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < lElemNodeCnt; col++)
                    {
                        int colNodeId = lNodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        double[,] kul = new double[uDof, lDof];
                        double[,] klu = new double[lDof, uDof];
                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            double tmp = 0.0;
                            for (int gDof = 0; gDof < uDof; gDof++)
                            {
                                for (int hDof = 0; hDof < uDof; hDof++)
                                {
                                    tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof];
                                }
                            }

                            kul[rowDof, 0] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                            klu[0, rowDof] +=
                                detJWeight * tmp * 2.0 * lN[col] * I3;
                        }

                        for (int rowDof = 0; rowDof < uDof; rowDof++)
                        {
                            A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0];
                            A[offset + colNodeId, rowNodeId *uDof + rowDof]  += klu[0, rowDof];
                            B[rowNodeId * uDof + rowDof] +=
                                kul[rowDof, 0] * U[offset + colNodeId];
                            B[offset + colNodeId] +=
                                klu[0, rowDof] * U[rowNodeId * uDof + rowDof];
                        }
                    }
                }

                for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
                {
                    for (int iDof = 0; iDof < uDof; iDof++)
                    {
                        for (int gDof = 0; gDof < uDof; gDof++)
                        {
                            for (int hDof = 0; hDof < uDof; hDof++)
                            {
                                qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof];
                            }
                        }
                    }
                }
                for (int iNode = 0; iNode < lElemNodeCnt; iNode++)
                {
                    ql[iNode] += detJWeight * lN[iNode] * (I3 - 1);
                }
            }

            for (int row = 0; row < uElemNodeCnt; row++)
            {
                int rowNodeId = uNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int col = 0; col < uElemNodeCnt; col++)
                {
                    int colNodeId = uNodes[col];
                    if (colNodeId == -1)
                    {
                        continue;
                    }

                    int      colCoId = uCoIds[col];
                    double[] u       = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                    double[] velU    = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                    double[] accU    = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);
                    double[,] m = new double[2, 2];

                    m[0, 0] = rho * uSNN[row, col];
                    m[1, 0] = 0.0;
                    m[0, 1] = 0.0;
                    m[1, 1] = rho * uSNN[row, col];
                    for (int rowDof = 0; rowDof < uDof; rowDof++)
                    {
                        for (int colDof = 0; colDof < uDof; colDof++)
                        {
                            A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] +=
                                (1.0 / (beta * dt * dt)) * m[rowDof, colDof];
                            B[rowNodeId * uDof + rowDof] +=
                                m[rowDof, colDof] * (
                                    (1.0 / (beta * dt * dt)) * u[colDof] +
                                    (1.0 / (beta * dt)) * velU[colDof] +
                                    (1.0 / (2.0 * beta) - 1.0) * accU[colDof]);
                        }
                    }
                }
            }

            double[,] fg = new double[uElemNodeCnt, uDof];
            for (int iNode = 0; iNode < uElemNodeCnt; iNode++)
            {
                for (int iDof = 0; iDof < uDof; iDof++)
                {
                    fg[iNode, iDof] = rho * g[iDof] * uSN[iNode];
                }
            }

            for (int row = 0; row < uElemNodeCnt; row++)
            {
                int rowNodeId = uNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < uDof; rowDof++)
                {
                    B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof];
                }
            }
            for (int row = 0; row < lElemNodeCnt; row++)
            {
                int rowNodeId = lNodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                B[offset + rowNodeId] += -ql[row];
            }
        }
예제 #20
0
        private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint         quantityId = 0;
            double       dt         = TimeStep;
            double       beta       = NewmarkBeta;
            double       gamma      = NewmarkGamma;
            var          FV         = World.GetFieldValue(ValueId);
            IList <uint> feIds      = World.GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE = World.GetTriangleFE(quantityId, feId);
                Material   ma0   = World.GetMaterial(triFE.MaterialId);

                int[] coIds       = triFE.NodeCoordIds;
                uint  elemNodeCnt = triFE.NodeCount;
                int[] nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = coIds[iNode];
                    int nodeId = World.Coord2Node(quantityId, coId);
                    nodes[iNode] = nodeId;
                }

                System.Diagnostics.Debug.Assert(ma0 is DiffusionMaterial);
                var    ma     = ma0 as DiffusionMaterial;
                double rho    = ma.MassDensity;
                double cap    = ma.Capacity;
                double lambda = ma.DiffusionCoef;
                double f      = ma.F;

                double[] sN = triFE.CalcSN();
                double[,] sNN       = triFE.CalcSNN();
                double[, ][,] sNuNv = triFE.CalcSNuNv();
                double[,] sNxNx     = sNuNv[0, 0];
                double[,] sNyNx     = sNuNv[1, 0];
                double[,] sNxNy     = sNuNv[0, 1];
                double[,] sNyNy     = sNuNv[1, 1];

                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }

                    for (int col = 0; col < elemNodeCnt; col++)
                    {
                        int colNodeId = nodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }

                        int      colCoId = coIds[col];
                        double[] u       = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                        double[] vel     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                        double[] acc     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);

                        double k = lambda * (sNxNx[row, col] + sNyNy[row, col]);
                        double m = rho * cap * sNN[row, col];

                        A[rowNodeId, colNodeId] +=
                            k + (gamma / (beta * dt)) * m;
                        B[rowNodeId] +=
                            m * (
                                (gamma / (beta * dt)) * u[0] -
                                (1.0 - gamma / beta) * vel[0] -
                                dt * (1.0 - gamma / (2.0 * beta)) * acc[0]
                                );
                    }
                }

                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    B[rowNodeId] += f * sN[row];
                }
            }
        }
예제 #21
0
        private void CalcStdGVorticityAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint wQuantityId = 0;
            uint pQuantityId = 1;
            int  wNodeCnt    = (int)World.GetNodeCount(wQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = wNodeCnt;

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    FV    = World.GetFieldValue(ValueId);

            IList <uint> feIds = World.GetTriangleFEIds(wQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE wTriFE    = World.GetTriangleFE(wQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = wTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] wCoIds       = wTriFE.NodeCoordIds;
                uint  wElemNodeCnt = wTriFE.NodeCount;
                int[] wNodes       = new int[wElemNodeCnt];
                for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                {
                    int coId   = wCoIds[iNode];
                    int nodeId = World.Coord2Node(wQuantityId, coId);
                    wNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(wTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double[] g   = { ma.GravityX, ma.GravityY };

                IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]   L   = ip.Ls[ipPt];
                    double[]   wN  = wTriFE.CalcN(L);
                    double[][] wNu = wTriFE.CalcNu(L);
                    double[]   wNx = wNu[0];
                    double[]   wNy = wNu[1];
                    double[]   pN  = pTriFE.CalcN(L);
                    double[][] pNu = pTriFE.CalcNu(L);
                    double[]   pNx = pNu[0];
                    double[]   pNy = pNu[1];

                    double detJ       = wTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    double w  = 0;
                    double wx = 0;
                    double wy = 0;
                    for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                    {
                        int nodeId = wNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double wValue = U[nodeId];
                        w  += wValue * wN[iNode];
                        wx += wValue * wNx[iNode];
                        wy += wValue * wNy[iNode];
                    }
                    double p  = 0;
                    double px = 0;
                    double py = 0;
                    for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                    {
                        int nodeId = pNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double pValue = U[offset + nodeId];
                        p  += pValue * pN[iNode];
                        px += pValue * pNx[iNode];
                        py += pValue * pNy[iNode];
                    }
                    double[] v = new double[2];
                    v[0] = py;
                    v[1] = -px;

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }
                            int colCoId = wCoIds[col];
                            // ω、dω/dt、d2ω/dt2
                            double[] u   = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                            double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                            double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);
                            System.Diagnostics.Debug.Assert(u.Length == 1);
                            System.Diagnostics.Debug.Assert(vel.Length == 1);
                            System.Diagnostics.Debug.Assert(acc.Length == 1);

                            double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]);
                            double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]);

                            double m = detJWeight * rho * wN[row] * wN[col];

                            A[rowNodeId, colNodeId] +=
                                kww1 + kww2 +
                                (gamma / (beta * dt)) * m;
                            // v = f(ψ) : kww2 Newton-Raphson
                            B[rowNodeId] += kww2 * U[colNodeId] +
                                            m * (
                                (gamma / (beta * dt)) * u[0] -
                                (1.0 - gamma / beta) * vel[0] -
                                dt * (1.0 - gamma / (2.0 * beta)) * acc[0]
                                );
                        }
                    }

                    // v = f(ψ): kwp Newton-Raphson
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy);
                            A[rowNodeId, offset + colNodeId] += kwp;
                            B[rowNodeId] += kwp * U[offset + colNodeId];
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpw = -detJWeight * pN[row] * wN[col];
                            A[offset + rowNodeId, colNodeId] += kpw;
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]);
                            A[offset + rowNodeId, offset + colNodeId] += kpp;
                        }
                    }

                    // v = f(ψ): qw Newton-Raphson
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy);
                        B[rowNodeId] += -qw;
                    }

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double f = 0;
                        for (int kNode = 0; kNode < wElemNodeCnt; kNode++)
                        {
                            int kNodeId = wNodes[kNode];
                            if (kNodeId == -1)
                            {
                                continue;
                            }
                            f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]);
                        }
                        B[rowNodeId] += f;
                    }
                }
            }
        }
        private void CalcStdGVorticityByPicardAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint wQuantityId = 0;
            uint pQuantityId = 1;
            int  wNodeCnt    = (int)World.GetNodeCount(wQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = wNodeCnt;

            IList <uint> feIds = World.GetTriangleFEIds(wQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE wTriFE    = World.GetTriangleFE(wQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = wTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] wCoIds       = wTriFE.NodeCoordIds;
                uint  wElemNodeCnt = wTriFE.NodeCount;
                int[] wNodes       = new int[wElemNodeCnt];
                for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                {
                    int coId   = wCoIds[iNode];
                    int nodeId = World.Coord2Node(wQuantityId, coId);
                    wNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(wTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double[] g   = { ma.GravityX, ma.GravityY };

                IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]   L   = ip.Ls[ipPt];
                    double[]   wN  = wTriFE.CalcN(L);
                    double[][] wNu = wTriFE.CalcNu(L);
                    double[]   wNx = wNu[0];
                    double[]   wNy = wNu[1];
                    double[]   pN  = pTriFE.CalcN(L);
                    double[][] pNu = pTriFE.CalcNu(L);
                    double[]   pNx = pNu[0];
                    double[]   pNy = pNu[1];

                    double detJ       = wTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    double w  = 0;
                    double wx = 0;
                    double wy = 0;
                    for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                    {
                        int nodeId = wNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double wValue = U[nodeId];
                        w  += wValue * wN[iNode];
                        wx += wValue * wNx[iNode];
                        wy += wValue * wNy[iNode];
                    }
                    double p  = 0;
                    double px = 0;
                    double py = 0;
                    for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                    {
                        int nodeId = pNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double pValue = U[offset + nodeId];
                        p  += pValue * pN[iNode];
                        px += pValue * pNx[iNode];
                        py += pValue * pNy[iNode];
                    }
                    double[] v = new double[2];
                    v[0] = py;
                    v[1] = -px;

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]);
                            double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]);
                            A[rowNodeId, colNodeId] +=
                                kww1 + kww2;
                            //Picard
                            //// v = f(ψ) : kww2 Newton-Raphson
                            ///B[rowNodeId] += kww2 * U[colNodeId];
                        }
                    }

                    // Picard
                    //// v = f(ψ): kwp Newton-Raphson
                    //for (int row = 0; row < wElemNodeCnt; row++)
                    //{
                    //    int rowNodeId = wNodes[row];
                    //    if (rowNodeId == -1)
                    //    {
                    //        continue;
                    //    }
                    //    for (int col = 0; col < pElemNodeCnt; col++)
                    //    {
                    //        int colNodeId = pNodes[col];
                    //        if (colNodeId == -1)
                    //        {
                    //            continue;
                    //        }
                    //
                    //        double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy);
                    //        A[rowNodeId, offset + colNodeId] += kwp;
                    //        B[rowNodeId] += kwp * U[offset + colNodeId];
                    //    }
                    //}

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpw = -detJWeight * pN[row] * wN[col];
                            A[offset + rowNodeId, colNodeId] += kpw;
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]);
                            A[offset + rowNodeId, offset + colNodeId] += kpp;
                        }
                    }

                    // Picard
                    //// v = f(ψ): qw Newton-Raphson
                    //for (int row = 0; row < wElemNodeCnt; row++)
                    //{
                    //    int rowNodeId = wNodes[row];
                    //    if (rowNodeId == -1)
                    //    {
                    //        continue;
                    //    }
                    //    double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy);
                    //    B[rowNodeId] += -qw;
                    //}

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double f = 0;
                        for (int kNode = 0; kNode < wElemNodeCnt; kNode++)
                        {
                            int kNodeId = wNodes[kNode];
                            if (kNodeId == -1)
                            {
                                continue;
                            }
                            f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]);
                        }
                        B[rowNodeId] += f;
                    }
                }
            }
        }
예제 #23
0
        private void CalcStokesAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint vQuantityId = 0;
            uint pQuantityId = 1;
            int  vDof        = 2;
            int  pDof        = 1;
            int  vNodeCnt    = (int)World.GetNodeCount(vQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = vNodeCnt * vDof;

            IList <uint> feIds = World.GetTriangleFEIds(vQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE vTriFE    = World.GetTriangleFE(vQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = vTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] vCoIds       = vTriFE.NodeCoordIds;
                uint  vElemNodeCnt = vTriFE.NodeCount;
                int[] vNodes       = new int[vElemNodeCnt];
                for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                {
                    int coId   = vCoIds[iNode];
                    int nodeId = World.Coord2Node(vQuantityId, coId);
                    vNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(vTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double[] g   = { ma.GravityX, ma.GravityY };

                double[]          vSN = vTriFE.CalcSN();
                IntegrationPoints ip  = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]   L   = ip.Ls[ipPt];
                    double[]   vN  = vTriFE.CalcN(L);
                    double[][] vNu = vTriFE.CalcNu(L);
                    double[]   vNx = vNu[0];
                    double[]   vNy = vNu[1];
                    double[]   pN  = pTriFE.CalcN(L);
                    double[][] pNu = pTriFE.CalcNu(L);
                    double[]   pNx = pNu[0];
                    double[]   pNy = pNu[1];

                    double detJ       = vTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < vElemNodeCnt; col++)
                        {
                            int colNodeId = vNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvv1 = new double[vDof, vDof];
                            kvv1[0, 0]     = detJWeight * mu * (vNx[row] * vNx[col] +
                                                                vNx[row] * vNx[col] + vNy[row] * vNy[col]);
                            kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col];
                            kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col];
                            kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] +
                                                            vNx[row] * vNx[col] + vNy[row] * vNy[col]);

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] +=
                                        kvv1[rowDof, colDof];
                                }
                            }
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvp = new double[vDof, pDof];
                            kvp[0, 0]     = -detJWeight * vNx[row] * pN[col];
                            kvp[1, 0]     = -detJWeight * vNy[row] * pN[col];

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0];
                                A[offset + colNodeId, rowNodeId *vDof + rowDof]  += kvp[rowDof, 0];
                            }
                        }
                    }
                }

                for (int row = 0; row < vElemNodeCnt; row++)
                {
                    int rowNodeId = vNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int rowDof = 0; rowDof < vDof; rowDof++)
                    {
                        B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row];
                    }
                }
            }
        }
예제 #24
0
        // Linear / Saint Venant
        public void SetStressValue(
            uint displacementValueId, uint stressValueId, uint equivStressValueId)
        {
            System.Diagnostics.Debug.Assert(World.IsFieldValueId(displacementValueId));
            FieldValue uFV         = World.GetFieldValue(displacementValueId);
            uint       uQuantityId = uFV.QuantityId;

            FieldValue sigmaFV = null;

            if (stressValueId != 0)
            {
                System.Diagnostics.Debug.Assert(World.IsFieldValueId(stressValueId));
                sigmaFV = World.GetFieldValue(stressValueId);
                System.Diagnostics.Debug.Assert(sigmaFV.Type == FieldValueType.SymmetricTensor2);
                System.Diagnostics.Debug.Assert(sigmaFV.Dof == 3);
            }
            FieldValue eqSigmaFV = null;

            if (equivStressValueId != 0)
            {
                System.Diagnostics.Debug.Assert(World.IsFieldValueId(equivStressValueId));
                eqSigmaFV = World.GetFieldValue(equivStressValueId);
                System.Diagnostics.Debug.Assert(eqSigmaFV.Type == FieldValueType.Scalar);
                System.Diagnostics.Debug.Assert(eqSigmaFV.Dof == 1);
            }

            IList <uint> feIds = World.GetTriangleFEIds(uQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE  = World.GetTriangleFE(uQuantityId, feId);
                int[]      coIds  = triFE.NodeCoordIds;
                Material   ma     = World.GetMaterial(triFE.MaterialId);
                double     lambda = 0;
                double     mu     = 0;
                if (ma is LinearElasticMaterial)
                {
                    var ma1 = ma as LinearElasticMaterial;
                    lambda = ma1.LameLambda;
                    mu     = ma1.LameMu;
                }
                else if (ma is SaintVenantHyperelasticMaterial)
                {
                    var ma1 = ma as SaintVenantHyperelasticMaterial;
                    lambda = ma1.LameLambda;
                    mu     = ma1.LameMu;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                    throw new NotImplementedException();
                }

                var ip = TriangleFE.GetIntegrationPoints(TriangleIntegrationPointCount.Point1);
                System.Diagnostics.Debug.Assert(ip.PointCount == 1);
                double[]   L  = ip.Ls[0];
                double[][] Nu = triFE.CalcNu(L);
                double[]   Nx = Nu[0];
                double[]   Ny = Nu[1];
                double[,] uu = new double[2, 2];
                for (int iNode = 0; iNode < coIds.Length; iNode++)
                {
                    int      coId = coIds[iNode];
                    double[] u    = uFV.GetDoubleValue(coId, FieldDerivativeType.Value);
                    uu[0, 0] += u[0] * Nx[iNode];
                    uu[0, 1] += u[0] * Ny[iNode];
                    uu[1, 0] += u[1] * Nx[iNode];
                    uu[1, 1] += u[1] * Ny[iNode];
                }

                //ε strain
                double[,] eps = new double[2, 2];
                if (ma is LinearElasticMaterial)
                {
                    eps[0, 0] = (1.0 / 2.0) * (uu[0, 0] + uu[0, 0]);
                    eps[0, 1] = (1.0 / 2.0) * (uu[0, 1] + uu[1, 0]);
                    eps[1, 0] = (1.0 / 2.0) * (uu[1, 0] + uu[0, 1]);
                    eps[1, 1] = (1.0 / 2.0) * (uu[1, 1] + uu[1, 1]);
                }
                else if (ma is SaintVenantHyperelasticMaterial)
                {
                    eps[0, 0] = (1.0 / 2.0) * (uu[0, 0] + uu[0, 0] + uu[0, 0] * uu[0, 0] + uu[1, 0] * uu[1, 0]);
                    eps[0, 1] = (1.0 / 2.0) * (uu[0, 1] + uu[1, 0] + uu[0, 0] * uu[0, 1] + uu[1, 1] * uu[1, 0]);
                    eps[1, 0] = (1.0 / 2.0) * (uu[1, 0] + uu[0, 1] + uu[0, 1] * uu[0, 0] + uu[1, 0] * uu[1, 1]);
                    eps[1, 1] = (1.0 / 2.0) * (uu[1, 1] + uu[1, 1] + uu[0, 1] * uu[0, 1] + uu[1, 1] * uu[1, 1]);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                // σ stress
                double[,] sigma = new double[2, 2];
                {
                    sigma[0, 0] = mu * eps[0, 0];
                    sigma[0, 1] = mu * eps[0, 1];
                    sigma[1, 0] = mu * eps[1, 0];
                    sigma[1, 1] = mu * eps[1, 1];
                    double tmp = lambda * (eps[0, 0] + eps[1, 1]);
                    sigma[0, 0] += tmp;
                    sigma[1, 1] += tmp;
                }

                double misesStress = Math.Sqrt(
                    (1.0 / 2.0) * (
                        sigma[0, 0] * sigma[0, 0] + sigma[1, 1] * sigma[1, 1] +
                        (sigma[1, 1] - sigma[0, 0]) * (sigma[1, 1] - sigma[0, 0])
                        ) +
                    3.0 * sigma[0, 1] * sigma[0, 1]);
                if (stressValueId != 0)
                {
                    double[] Sigma = sigmaFV.GetDoubleValues(FieldDerivativeType.Value);
                    uint     dof   = sigmaFV.Dof;
                    Sigma[(feId - 1) * dof + 0] = sigma[0, 0]; // σxx
                    Sigma[(feId - 1) * dof + 1] = sigma[1, 1]; // σyy
                    Sigma[(feId - 1) * dof + 2] = sigma[0, 1]; // τxy
                }
                if (equivStressValueId != 0)
                {
                    double[] EqSigma = eqSigmaFV.GetDoubleValues(FieldDerivativeType.Value);
                    EqSigma[feId - 1] = misesStress;
                }
            }
        }
예제 #25
0
        public IList <int> GetCoordIdsFromCadId(FEWorld world, uint cadId, CadElementType cadElemType)
        {
            Mesher2D    mesh  = world.Mesh;
            IList <int> coIds = null;

            if (cadElemType == CadElementType.Vertex)
            {
                uint     meshId = mesh.GetIdFromCadId(cadId, cadElemType);
                uint     elemCnt;
                MeshType meshType;
                int      loc;
                uint     cadIdTmp;
                mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadIdTmp);
                MeshType dummyMeshType;
                int[]    vertexs;
                mesh.GetConnectivity(meshId, out dummyMeshType, out vertexs);
                System.Diagnostics.Debug.Assert(meshType == dummyMeshType);

                coIds = vertexs.ToList();
            }
            else if (cadElemType == CadElementType.Edge)
            {
                coIds = new List <int>();
                IList <uint> feIds = LineFEArray.GetObjectIds();
                foreach (uint feId in feIds)
                {
                    LineFE lineFE = LineFEArray.GetObject(feId);
                    uint   cadIdTmp;
                    {
                        uint     meshId = lineFE.MeshId;
                        uint     elemCnt;
                        MeshType meshType;
                        int      loc;
                        mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadIdTmp);
                        System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
                    }
                    if (cadIdTmp == cadId)
                    {
                        foreach (int coId in lineFE.NodeCoordIds)
                        {
                            if (coIds.IndexOf(coId) == -1)
                            {
                                coIds.Add(coId);
                            }
                        }
                    }
                }
            }
            else if (cadElemType == CadElementType.Loop)
            {
                coIds = new List <int>();
                IList <uint> feIds = TriangleFEArray.GetObjectIds();
                foreach (uint feId in feIds)
                {
                    TriangleFE triFE = TriangleFEArray.GetObject(feId);
                    uint       cadIdTmp;
                    {
                        uint     meshId = triFE.MeshId;
                        uint     elemCnt;
                        MeshType meshType;
                        int      loc;
                        mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadIdTmp);
                        System.Diagnostics.Debug.Assert(meshType == MeshType.Tri);
                    }
                    if (cadIdTmp == cadId)
                    {
                        foreach (int coId in triFE.NodeCoordIds)
                        {
                            if (coIds.IndexOf(coId) == -1)
                            {
                                coIds.Add(coId);
                            }
                        }
                    }
                }
            }
            else
            {
                throw new InvalidOperationException();
            }

            return(coIds);
        }
예제 #26
0
        private void CalcStdGNavierStokesAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint vQuantityId = 0;
            uint pQuantityId = 1;
            int  vDof        = 2;
            int  pDof        = 1;
            int  vNodeCnt    = (int)World.GetNodeCount(vQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = vNodeCnt * vDof;

            double       dt    = TimeStep;
            double       beta  = NewmarkBeta;
            double       gamma = NewmarkGamma;
            var          FV    = World.GetFieldValue(ValueId);
            IList <uint> feIds = World.GetTriangleFEIds(vQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE vTriFE    = World.GetTriangleFE(vQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = vTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] vCoIds       = vTriFE.NodeCoordIds;
                uint  vElemNodeCnt = vTriFE.NodeCount;
                int[] vNodes       = new int[vElemNodeCnt];
                for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                {
                    int coId   = vCoIds[iNode];
                    int nodeId = World.Coord2Node(vQuantityId, coId);
                    vNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(vTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double[] g   = { ma.GravityX, ma.GravityY };

                double[]          vSN = vTriFE.CalcSN();
                IntegrationPoints ip  = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]   L   = ip.Ls[ipPt];
                    double[]   vN  = vTriFE.CalcN(L);
                    double[][] vNu = vTriFE.CalcNu(L);
                    double[]   vNx = vNu[0];
                    double[]   vNy = vNu[1];
                    double[]   pN  = pTriFE.CalcN(L);
                    double[][] pNu = pTriFE.CalcNu(L);
                    double[]   pNx = pNu[0];
                    double[]   pNy = pNu[1];

                    double detJ       = vTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    double[] v  = new double[vDof];
                    double[] vx = new double[vDof];
                    double[] vy = new double[vDof];
                    for (int iNode = 0; iNode < vElemNodeCnt; iNode++)
                    {
                        int nodeId = vNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        for (int iDof = 0; iDof < vDof; iDof++)
                        {
                            double vValue = U[nodeId * vDof + iDof];
                            v[iDof]  += vValue * vN[iNode];
                            vx[iDof] += vValue * vNx[iNode];
                            vy[iDof] += vValue * vNy[iNode];
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < vElemNodeCnt; col++)
                        {
                            int colNodeId = vNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }
                            int      colCoId = vCoIds[col];
                            double[] u       = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                            double[] vel     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                            double[] acc     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);

                            double[,] kvv1 = new double[vDof, vDof];
                            kvv1[0, 0]     = detJWeight * mu * (vNx[row] * vNx[col] +
                                                                vNx[row] * vNx[col] + vNy[row] * vNy[col]);
                            kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col];
                            kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col];
                            kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] +
                                                            vNx[row] * vNx[col] + vNy[row] * vNy[col]);

                            double[,] kvv2 = new double[vDof, vDof];
                            kvv2[0, 0]     = detJWeight * rho * vN[row] * (
                                vN[col] * vx[0] + v[0] * vNx[col] + v[1] * vNy[col]);
                            kvv2[0, 1] = detJWeight * rho * vN[row] * vN[col] * vy[0];
                            kvv2[1, 0] = detJWeight * rho * vN[row] * vN[col] * vx[1];
                            kvv2[1, 1] = detJWeight * rho * vN[row] * (
                                vN[col] * vy[1] + v[0] * vNx[col] + v[1] * vNy[col]);

                            double[,] m = new double[vDof, vDof];
                            m[0, 0]     = detJWeight * rho * vN[row] * vN[col];
                            m[1, 1]     = detJWeight * rho * vN[row] * vN[col];

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                for (int colDof = 0; colDof < vDof; colDof++)
                                {
                                    A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] +=
                                        kvv1[rowDof, colDof] + kvv2[rowDof, colDof] +
                                        (gamma / (beta * dt)) * m[rowDof, colDof];

                                    B[rowNodeId * vDof + rowDof] +=
                                        kvv2[rowDof, colDof] * U[colNodeId * vDof + colDof] +
                                        m[rowDof, colDof] * (
                                            (gamma / (beta * dt)) * u[colDof] -
                                            (1.0 - gamma / beta) * vel[colDof] -
                                            dt * (1.0 - gamma / (2.0 * beta)) * acc[colDof]
                                            );
                                }
                            }
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double[,] kvp = new double[vDof, pDof];
                            kvp[0, 0]     = -detJWeight * vNx[row] * pN[col];
                            kvp[1, 0]     = -detJWeight * vNy[row] * pN[col];

                            for (int rowDof = 0; rowDof < vDof; rowDof++)
                            {
                                A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0];
                                A[offset + colNodeId, rowNodeId *vDof + rowDof]  += kvp[rowDof, 0];
                            }
                        }
                    }

                    for (int row = 0; row < vElemNodeCnt; row++)
                    {
                        int rowNodeId = vNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double[] q2 = new double[vDof];
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            q2[rowDof] = detJWeight * rho * vN[row] * (v[0] * vx[rowDof] + v[1] * vy[rowDof]);
                        }
                        for (int rowDof = 0; rowDof < vDof; rowDof++)
                        {
                            B[rowNodeId * vDof + rowDof] += -q2[rowDof];
                        }
                    }
                }

                for (int row = 0; row < vElemNodeCnt; row++)
                {
                    int rowNodeId = vNodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int rowDof = 0; rowDof < vDof; rowDof++)
                    {
                        B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row];
                    }
                }
            }
        }
예제 #27
0
        private void CalcSUPGVorticityAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint wQuantityId = 0;
            uint pQuantityId = 1;
            int  wNodeCnt    = (int)World.GetNodeCount(wQuantityId);
            int  pNodeCnt    = (int)World.GetNodeCount(pQuantityId);
            int  offset      = wNodeCnt;
            int  vDof        = 2; // 速度

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    FV    = World.GetFieldValue(ValueId);

            IList <uint> feIds = World.GetTriangleFEIds(wQuantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE wTriFE    = World.GetTriangleFE(wQuantityId, feId);
                TriangleFE pTriFE    = World.GetTriangleFE(pQuantityId, feId);
                uint       vertexCnt = wTriFE.VertexCount;
                for (int iVertex = 0; iVertex < vertexCnt; iVertex++)
                {
                    System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]);
                }

                int[] wCoIds       = wTriFE.NodeCoordIds;
                uint  wElemNodeCnt = wTriFE.NodeCount;
                int[] wNodes       = new int[wElemNodeCnt];
                for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                {
                    int coId   = wCoIds[iNode];
                    int nodeId = World.Coord2Node(wQuantityId, coId);
                    wNodes[iNode] = nodeId;
                }
                int[] pCoIds       = pTriFE.NodeCoordIds;
                uint  pElemNodeCnt = pTriFE.NodeCount;
                int[] pNodes       = new int[pElemNodeCnt];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int coId   = pCoIds[iNode];
                    int nodeId = World.Coord2Node(pQuantityId, coId);
                    pNodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(wTriFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial);
                var      ma  = ma0 as NewtonFluidMaterial;
                double   rho = ma.MassDensity;
                double   mu  = ma.Mu;
                double   nu  = mu / rho;
                double[] g   = { ma.GravityX, ma.GravityY };

                double[][] velos = new double[pElemNodeCnt][];
                for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                {
                    int      coId = pCoIds[iNode];
                    double[] velo = new double[vDof];
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        velo[iDof] = CoordV[coId * vDof + iDof];
                    }
                    velos[iNode] = velo;
                }

                double taum = 0;
                double tauc = 0;
                {
                    double[] aveVelo =
                    {
                        (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0,
                        (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0
                    };
                    double     veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]);
                    double[][] Lu       = new double[vDof][];
                    {
                        double[] a;
                        double[] b;
                        double[] c;
                        wTriFE.CalcTransMatrix(out a, out b, out c);
                        // Lx
                        Lu[0] = b;
                        // Ly
                        Lu[1] = c;
                    }
                    IvyFEM.Lapack.DoubleMatrix GMat = new IvyFEM.Lapack.DoubleMatrix(vDof, vDof);
                    double[] gVec = new double[vDof];
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        for (int jDof = 0; jDof < vDof; jDof++)
                        {
                            for (int kDof = 0; kDof < vDof; kDof++)
                            {
                                GMat[iDof, jDof] += Lu[iDof][kDof] * Lu[jDof][kDof];
                            }
                        }
                    }
                    for (int iDof = 0; iDof < vDof; iDof++)
                    {
                        for (int kDof = 0; kDof < vDof; kDof++)
                        {
                            gVec[iDof] += Lu[iDof][kDof];
                        }
                    }

                    double sqinvtaum1 = 0;
                    double sqinvtaum2 = 0;
                    {
                        double[] tmpVec = GMat * aveVelo;
                        sqinvtaum2 = IvyFEM.Lapack.Functions.ddot(aveVelo, tmpVec);
                    }
                    double sqinvtaum3 = 0;
                    {
                        IvyFEM.Lapack.DoubleMatrix GMatT = new Lapack.DoubleMatrix(GMat);
                        GMatT.Transpose();
                        double GMatDoubleDot = IvyFEM.Lapack.DoubleMatrix.DoubleDot(GMat, GMatT);
                        sqinvtaum3 = nu * nu * GMatDoubleDot;
                    }
                    double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3;
                    taum = 1.0 / Math.Sqrt(sqinvtaum);

                    double gDot = IvyFEM.Lapack.Functions.ddot(gVec, gVec);
                    tauc = 1.0 / (taum * gDot);
                }

                IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7
                for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                {
                    double[]     L    = ip.Ls[ipPt];
                    double[]     wN   = wTriFE.CalcN(L);
                    double[][]   wNu  = wTriFE.CalcNu(L);
                    double[]     wNx  = wNu[0];
                    double[]     wNy  = wNu[1];
                    double[, ][] wNuv = wTriFE.CalcNuv(L);
                    double[]     pN   = pTriFE.CalcN(L);
                    double[][]   pNu  = pTriFE.CalcNu(L);
                    double[]     pNx  = pNu[0];
                    double[]     pNy  = pNu[1];

                    double detJ       = wTriFE.GetDetJacobian(L);
                    double weight     = ip.Weights[ipPt];
                    double detJWeight = (1.0 / 2.0) * weight * detJ;

                    double w     = 0;
                    double wx    = 0;
                    double wy    = 0;
                    double wxx   = 0;
                    double wxy   = 0;
                    double wyx   = 0;
                    double wyy   = 0;
                    double velow = 0;
                    for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                    {
                        int nodeId = wNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double wValue = U[nodeId];
                        w   += wValue * wN[iNode];
                        wx  += wValue * wNx[iNode];
                        wy  += wValue * wNy[iNode];
                        wxx += wValue * wNuv[0, 0][iNode];
                        wxy += wValue * wNuv[0, 1][iNode];
                        wyx += wValue * wNuv[1, 0][iNode];
                        wyy += wValue * wNuv[1, 1][iNode];

                        int      coId    = wCoIds[iNode];
                        double[] prevU   = FV.GetDoubleValue(coId, FieldDerivativeType.Value);
                        double[] prevVel = FV.GetDoubleValue(coId, FieldDerivativeType.Velocity);
                        double[] prevAcc = FV.GetDoubleValue(coId, FieldDerivativeType.Acceleration);
                        System.Diagnostics.Debug.Assert(prevU.Length == 1);
                        System.Diagnostics.Debug.Assert(prevVel.Length == 1);
                        System.Diagnostics.Debug.Assert(prevAcc.Length == 1);
                        double vel = 0;
                        vel = (gamma / (beta * dt)) * (wValue - prevU[0]) +
                              (1.0 - gamma / beta) * prevVel[0] +
                              dt * (1.0 - gamma / (2.0 * beta)) * prevAcc[0];
                        velow += vel * wN[iNode];
                    }
                    double p  = 0;
                    double px = 0;
                    double py = 0;
                    for (int iNode = 0; iNode < pElemNodeCnt; iNode++)
                    {
                        int nodeId = pNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        double pValue = U[offset + nodeId];
                        p  += pValue * pN[iNode];
                        px += pValue * pNx[iNode];
                        py += pValue * pNy[iNode];
                    }
                    // dg/du
                    double[] gx = new double[2];
                    double[] gy = new double[2];
                    for (int iNode = 0; iNode < wElemNodeCnt; iNode++)
                    {
                        int nodeId = wNodes[iNode];
                        if (nodeId == -1)
                        {
                            continue;
                        }
                        for (int iDof = 0; iDof < 2; iDof++)
                        {
                            double gValue = g[iDof];
                            gx[iDof] += gValue * wNx[iNode];
                            gy[iDof] += gValue * wNy[iNode];
                        }
                    }
                    double[] v = new double[2];
                    v[0] = py;
                    v[1] = -px;

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }
                            int colCoId = wCoIds[col];
                            // ω、dω/dt、d2ω/dt2
                            double[] u   = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                            double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                            double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);
                            System.Diagnostics.Debug.Assert(u.Length == 1);
                            System.Diagnostics.Debug.Assert(vel.Length == 1);
                            System.Diagnostics.Debug.Assert(acc.Length == 1);

                            double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]);
                            double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]);

                            double m = detJWeight * rho * wN[row] * wN[col];

                            A[rowNodeId, colNodeId] +=
                                kww1 + kww2 +
                                (gamma / (beta * dt)) * m;
                            // v = f(ψ) : kww2 Newton-Raphson
                            B[rowNodeId] += kww2 * U[colNodeId] +
                                            m * (
                                (gamma / (beta * dt)) * u[0] -
                                (1.0 - gamma / beta) * vel[0] -
                                dt * (1.0 - gamma / (2.0 * beta)) * acc[0]
                                );
                        }
                    }

                    // v = f(ψ): kwp Newton-Raphson
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy);
                            A[rowNodeId, offset + colNodeId] += kwp;
                            B[rowNodeId] += kwp * U[offset + colNodeId];
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpw = -detJWeight * pN[row] * wN[col];
                            A[offset + rowNodeId, colNodeId] += kpw;
                        }
                    }

                    for (int row = 0; row < pElemNodeCnt; row++)
                    {
                        int rowNodeId = pNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]);
                            A[offset + rowNodeId, offset + colNodeId] += kpp;
                        }
                    }

                    // v = f(ψ): qw Newton-Raphson
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy);
                        B[rowNodeId] += -qw;
                    }

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        double f = 0;
                        for (int kNode = 0; kNode < wElemNodeCnt; kNode++)
                        {
                            int kNodeId = wNodes[kNode];
                            if (kNodeId == -1)
                            {
                                continue;
                            }
                            f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]);
                        }
                        B[rowNodeId] += f;
                    }

                    //////////////////////////////////////////////////////////////
                    // SUPG
                    double   rm  = 0;
                    double[] rmw = new double[wElemNodeCnt];
                    double[] rmp = new double[pElemNodeCnt];
                    {
                        rm =
                            rho * velow +
                            -mu * (wxx + wyy) +
                            rho * (v[0] * wx + v[1] * wy) +
                            -rho * (gx[1] - gy[0]);

                        for (int jNode = 0; jNode < wElemNodeCnt; jNode++)
                        {
                            int jNodeId = wNodes[jNode];
                            if (jNodeId == -1)
                            {
                                continue;
                            }

                            rmw[jNode] =
                                rho * (gamma / (beta * dt)) * wN[jNode] +
                                -mu * (wNuv[0, 0][jNode] + wNuv[1, 1][jNode]) +
                                rho * (v[0] * wNu[0][jNode] + v[1] * wNu[1][jNode]);
                        }

                        for (int jNode = 0; jNode < pElemNodeCnt; jNode++)
                        {
                            int jNodeId = pNodes[jNode];
                            if (jNodeId == -1)
                            {
                                continue;
                            }
                            rmp[jNode] = rho * (pNu[1][jNode] * wx - pNu[0][jNode] * wy);
                        }
                    }
                    // kww
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < wElemNodeCnt; col++)
                        {
                            int colNodeId = wNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kww =
                                detJWeight * taum * (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rmw[col];

                            A[rowNodeId, colNodeId] += kww;

                            B[rowNodeId] +=
                                kww * U[colNodeId];
                        }
                    }
                    // kwp
                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }
                        for (int col = 0; col < pElemNodeCnt; col++)
                        {
                            int colNodeId = pNodes[col];
                            if (colNodeId == -1)
                            {
                                continue;
                            }

                            double kwp =
                                detJWeight * taum * (pNu[1][col] * wNu[0][row] - pNu[0][col] * wNu[1][row]) * rm +
                                detJWeight * taum * (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rmp[col];

                            A[rowNodeId, offset + colNodeId] += kwp;

                            B[rowNodeId] +=
                                kwp * U[offset + colNodeId];
                        }
                    }

                    for (int row = 0; row < wElemNodeCnt; row++)
                    {
                        int rowNodeId = wNodes[row];
                        if (rowNodeId == -1)
                        {
                            continue;
                        }

                        double qw = detJWeight * taum *
                                    (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rm;

                        B[rowNodeId] += -qw;
                    }
                }
            }
        }
예제 #28
0
        protected void CalcLinearElasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint quantityId = 0;
            int  nodeCnt    = (int)World.GetNodeCount(quantityId);

            System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2);
            int dof = 2;

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    FV    = World.GetFieldValue(ValueId);

            TriangleFE triFE = World.GetTriangleFE(quantityId, feId);
            Material   ma0   = World.GetMaterial(triFE.MaterialId);

            if (!(ma0 is LinearElasticMaterial))
            {
                return;
            }

            int[] coIds       = triFE.NodeCoordIds;
            uint  elemNodeCnt = triFE.NodeCount;

            int[] nodes = new int[elemNodeCnt];
            for (int iNode = 0; iNode < elemNodeCnt; iNode++)
            {
                int coId   = coIds[iNode];
                int nodeId = World.Coord2Node(quantityId, coId);
                nodes[iNode] = nodeId;
            }

            var    ma     = ma0 as LinearElasticMaterial;
            double lambda = ma.LameLambda;
            double mu     = ma.LameMu;
            double rho    = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] sN = triFE.CalcSN();
            double[,] sNN       = triFE.CalcSNN();
            double[, ][,] sNuNv = triFE.CalcSNuNv();
            double[,] sNxNx     = sNuNv[0, 0];
            double[,] sNyNx     = sNuNv[1, 0];
            double[,] sNxNy     = sNuNv[0, 1];
            double[,] sNyNy     = sNuNv[1, 1];

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }

                for (int col = 0; col < elemNodeCnt; col++)
                {
                    int colNodeId = nodes[col];
                    if (colNodeId == -1)
                    {
                        continue;
                    }

                    int      colCoId = coIds[col];
                    double[] u       = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                    double[] vel     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                    double[] acc     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);

                    double[,] k = new double[dof, dof];
                    double[,] m = new double[dof, dof];
                    k[0, 0]     = (lambda + mu) * sNxNx[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]);
                    k[1, 0]     = lambda * sNyNx[row, col] + mu * sNxNy[row, col];
                    k[0, 1]     = lambda * sNxNy[row, col] + mu * sNyNx[row, col];
                    k[1, 1]     = (lambda + mu) * sNyNy[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]);

                    m[0, 0] = rho * sNN[row, col];
                    m[1, 0] = 0.0;
                    m[0, 1] = 0.0;
                    m[1, 1] = rho * sNN[row, col];

                    for (int rowDof = 0; rowDof < dof; rowDof++)
                    {
                        for (int colDof = 0; colDof < dof; colDof++)
                        {
                            A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] +=
                                (1.0 / (beta * dt * dt)) * m[rowDof, colDof] +
                                k[rowDof, colDof];

                            B[rowNodeId * dof + rowDof] +=
                                m[rowDof, colDof] * (
                                    (1.0 / (beta * dt * dt)) * u[colDof] +
                                    (1.0 / (beta * dt)) * vel[colDof] +
                                    (1.0 / (2.0 * beta) - 1.0) * acc[colDof]);
                        }
                    }
                }
            }

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < dof; rowDof++)
                {
                    B[rowNodeId * dof + rowDof] += rho * g[rowDof] * sN[row];
                }
            }
        }
        protected void CalcSaintVenantHyperelasticElementAB(
            uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint quantityId = 0;

            System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2);
            int dof     = 2;
            int nodeCnt = (int)World.GetNodeCount(quantityId);

            double dt    = TimeStep;
            double beta  = NewmarkBeta;
            double gamma = NewmarkGamma;
            var    FV    = World.GetFieldValue(ValueId);

            TriangleFE triFE = World.GetTriangleFE(quantityId, feId);
            Material   ma0   = World.GetMaterial(triFE.MaterialId);

            if (!(ma0 is SaintVenantHyperelasticMaterial))
            {
                return;
            }
            int[] coIds       = triFE.NodeCoordIds;
            uint  elemNodeCnt = triFE.NodeCount;

            int[] nodes = new int[elemNodeCnt];
            for (int iNode = 0; iNode < elemNodeCnt; iNode++)
            {
                int coId   = coIds[iNode];
                int nodeId = World.Coord2Node(quantityId, coId);
                nodes[iNode] = nodeId;
            }

            var    ma     = ma0 as SaintVenantHyperelasticMaterial;
            double lambda = ma.LameLambda;
            double mu     = ma.LameMu;
            double rho    = ma.MassDensity;

            double[] g = { ma.GravityX, ma.GravityY };

            double[] sN = triFE.CalcSN();
            double[,] sNN = triFE.CalcSNN();
            IntegrationPoints ip = TriangleFE.GetIntegrationPoints(TriangleIntegrationPointCount.Point1);

            System.Diagnostics.Debug.Assert(ip.Ls.Length == 1);
            double[]   L          = ip.Ls[0];
            double[][] Nu         = triFE.CalcNu(L);
            double     detJ       = triFE.GetDetJacobian(L);
            double     weight     = ip.Weights[0];
            double     detJWeight = (1.0 / 2.0) * weight * detJ;

            double[,] uu = new double[dof, dof];
            for (int iDof = 0; iDof < dof; iDof++)
            {
                for (int jDof = 0; jDof < dof; jDof++)
                {
                    for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                    {
                        int iNodeId = nodes[iNode];
                        if (iNodeId == -1)
                        {
                            continue;
                        }
                        uu[iDof, jDof] += U[iNodeId * dof + iDof] * Nu[jDof][iNode];
                    }
                }
            }

            double[,] e = new double[dof, dof];
            for (int iDof = 0; iDof < dof; iDof++)
            {
                for (int jDof = 0; jDof < dof; jDof++)
                {
                    e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]);
                    for (int kDof = 0; kDof < dof; kDof++)
                    {
                        e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof];
                    }
                }
            }

            double[,,,] b = new double[elemNodeCnt, dof, dof, dof];
            {
                double[,] f = new double[dof, dof];
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    for (int jDof = 0; jDof < dof; jDof++)
                    {
                        f[iDof, jDof] = uu[iDof, jDof];
                    }
                    f[iDof, iDof] += 1.0;
                }
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    for (int iDof = 0; iDof < dof; iDof++)
                    {
                        for (int gDof = 0; gDof < dof; gDof++)
                        {
                            for (int hDof = 0; hDof < dof; hDof++)
                            {
                                b[iNode, iDof, gDof, hDof] = Nu[hDof][iNode] * f[iDof, gDof];
                            }
                        }
                    }
                }
            }

            double[,] s = new double[dof, dof];
            {
                double tmp = 0.0;
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    for (int jDof = 0; jDof < dof; jDof++)
                    {
                        s[iDof, jDof] = 2.0 * mu * e[iDof, jDof];
                    }
                    tmp += e[iDof, iDof];
                }
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    s[iDof, iDof] += lambda * tmp;
                }
            }

            double[,] q = new double[elemNodeCnt, dof];
            for (int iNode = 0; iNode < elemNodeCnt; iNode++)
            {
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    for (int gDof = 0; gDof < dof; gDof++)
                    {
                        for (int hDof = 0; hDof < dof; hDof++)
                        {
                            q[iNode, iDof] +=
                                detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof];
                        }
                    }
                }
            }

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int col = 0; col < elemNodeCnt; col++)
                {
                    int colNodeId = nodes[col];
                    if (colNodeId == -1)
                    {
                        continue;
                    }

                    int      colCoId = coIds[col];
                    double[] u       = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value);
                    double[] vel     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity);
                    double[] acc     = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration);

                    double[,] k = new double[dof, dof];
                    double[,] m = new double[dof, dof];
                    for (int rowDof = 0; rowDof < dof; rowDof++)
                    {
                        for (int colDof = 0; colDof < dof; colDof++)
                        {
                            {
                                double tmp1 = 0.0;
                                double tmp2 = 0.0;
                                for (int gDof = 0; gDof < dof; gDof++)
                                {
                                    tmp1 += b[row, rowDof, gDof, gDof];
                                    tmp2 += b[col, colDof, gDof, gDof];
                                }
                                k[rowDof, colDof] += detJWeight * lambda * tmp1 * tmp2;
                            }
                            {
                                double tmp = 0.0;
                                for (int gDof = 0; gDof < dof; gDof++)
                                {
                                    for (int hDof = 0; hDof < dof; hDof++)
                                    {
                                        tmp +=
                                            b[row, rowDof, gDof, hDof] * b[col, colDof, gDof, hDof] +
                                            b[row, rowDof, gDof, hDof] * b[col, colDof, hDof, gDof];
                                    }
                                }
                                k[rowDof, colDof] += detJWeight * mu * tmp;
                            }
                        }
                    }

                    {
                        double tmp = 0.0;
                        for (int gDof = 0; gDof < dof; gDof++)
                        {
                            for (int hDof = 0; hDof < dof; hDof++)
                            {
                                tmp += s[gDof, hDof] * Nu[hDof][row] * Nu[gDof][col];
                            }
                        }
                        for (int rowDof = 0; rowDof < dof; rowDof++)
                        {
                            k[rowDof, rowDof] += detJWeight * tmp;
                        }
                    }

                    m[0, 0] = rho * sNN[row, col];
                    m[1, 0] = 0.0;
                    m[0, 1] = 0.0;
                    m[1, 1] = rho * sNN[row, col];

                    for (int rowDof = 0; rowDof < dof; rowDof++)
                    {
                        for (int colDof = 0; colDof < dof; colDof++)
                        {
                            A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] +=
                                (1.0 / (beta * dt * dt)) * m[rowDof, colDof] +
                                k[rowDof, colDof];
                            B[rowNodeId * dof + rowDof] +=
                                k[rowDof, colDof] * U[colNodeId * dof + colDof] +
                                m[rowDof, colDof] * (
                                    (1.0 / (beta * dt * dt)) * u[colDof] +
                                    (1.0 / (beta * dt)) * vel[colDof] +
                                    (1.0 / (2.0 * beta) - 1.0) * acc[colDof]);
                        }
                    }
                }
            }

            double[,] fg = new double[elemNodeCnt, dof];
            for (int iNode = 0; iNode < elemNodeCnt; iNode++)
            {
                for (int iDof = 0; iDof < dof; iDof++)
                {
                    fg[iNode, iDof] += rho * g[iDof] * sN[iNode];
                }
            }

            for (int row = 0; row < elemNodeCnt; row++)
            {
                int rowNodeId = nodes[row];
                if (rowNodeId == -1)
                {
                    continue;
                }
                for (int rowDof = 0; rowDof < dof; rowDof++)
                {
                    B[rowNodeId * dof + rowDof] += fg[row, rowDof] - q[row, rowDof];
                }
            }
        }
예제 #30
0
        private void CalcAB(IvyFEM.Linear.ComplexSparseMatrix A, System.Numerics.Complex[] B)
        {
            uint         quantityId = 0;
            IList <uint> feIds      = World.GetTriangleFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                TriangleFE triFE       = World.GetTriangleFE(quantityId, feId);
                uint       elemNodeCnt = triFE.NodeCount;
                int[]      nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = triFE.NodeCoordIds[iNode];
                    int nodeId = World.Coord2Node(quantityId, coId);
                    nodes[iNode] = nodeId;
                }

                Material ma0 = World.GetMaterial(triFE.MaterialId);
                System.Diagnostics.Debug.Assert(ma0 is HelmholtzMaterial);
                var    ma = ma0 as HelmholtzMaterial;
                double v  = ma.Velocity;
                System.Numerics.Complex f = ma.F;
                double omega = 2.0 * Math.PI * Frequency;
                double k     = omega / v;

                double[,] sNN       = triFE.CalcSNN();
                double[, ][,] sNuNv = triFE.CalcSNuNv();
                double[,] sNxNx     = sNuNv[0, 0];
                double[,] sNyNx     = sNuNv[1, 0];
                double[,] sNxNy     = sNuNv[0, 1];
                double[,] sNyNy     = sNuNv[1, 1];
                double[] sN = triFE.CalcSN();
                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    for (int col = 0; col < elemNodeCnt; col++)
                    {
                        int colNodeId = nodes[col];
                        if (colNodeId == -1)
                        {
                            continue;
                        }
                        double a = sNxNx[row, col] + sNyNy[row, col] - k * k * sNN[row, col];

                        A[rowNodeId, colNodeId] += a;
                    }
                }
                for (int row = 0; row < elemNodeCnt; row++)
                {
                    int rowNodeId = nodes[row];
                    if (rowNodeId == -1)
                    {
                        continue;
                    }
                    System.Numerics.Complex b = f * sN[row];
                    B[rowNodeId] += b;
                }
            }
        }