示例#1
0
        private void SetLine(FEWorld world, uint valueId)
        {
            System.Diagnostics.Debug.Assert(Type == ElementType.Line);
            if (Type != ElementType.Line)
            {
                return;
            }

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

            {
                uint feId = world.GetLineFEIdFromMesh(quantityId, MeshId, 0); // 先頭の要素
                System.Diagnostics.Debug.Assert(feId != 0);
                LineFE lineFE = world.GetLineFE(quantityId, feId);
                feOrder     = lineFE.Order;
                ElemPtCount = lineFE.NodeCount;
            }

            Indexs = new uint[ElemPtCount * ElemCount];
            for (int iEdge = 0; iEdge < ElemCount; iEdge++)
            {
                uint feId = world.GetLineFEIdFromMesh(quantityId, MeshId, (uint)iEdge);
                System.Diagnostics.Debug.Assert(feId != 0);
                LineFE lineFE = world.GetLineFE(quantityId, feId);
                for (int iPt = 0; iPt < ElemPtCount; iPt++)
                {
                    Indexs[iEdge * ElemPtCount + iPt] = (uint)lineFE.NodeCoordIds[iPt];
                }
            }
        }
示例#2
0
        // 接触解析のMaster/Slave線要素を準備する
        private void SetupContactMasterSlaveLineElements(FEWorld world)
        {
            Mesher2D mesh = world.Mesh;

            IList <uint> feIds = LineFEArray.GetObjectIds();

            foreach (var feId in feIds)
            {
                LineFE lineFE = LineFEArray.GetObject(feId);
                uint   cadId;
                {
                    uint     meshId = lineFE.MeshId;
                    uint     elemCnt;
                    MeshType meshType;
                    int      loc;
                    mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId);
                    System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
                }
                if (ContactSlaveEIds.Contains(cadId))
                {
                    // Slave上の線要素
                    ContactSlaveLineFEIds.Add(feId);
                }
                if (ContactMasterEIds.Contains(cadId))
                {
                    // Master上の線要素
                    ContactMasterLineFEIds.Add(feId);
                }
            }
        }
示例#3
0
        private void CalcMatrixs()
        {
            int          nodeCnt = (int)World.GetPortNodeCount(QuantityId, PortId);
            IList <uint> feIds   = World.GetPortLineFEIds(QuantityId, PortId);

            Txx = new IvyFEM.Lapack.DoubleMatrix(nodeCnt, nodeCnt);
            Ryy = new IvyFEM.Lapack.DoubleMatrix(nodeCnt, nodeCnt);
            Uzz = new IvyFEM.Lapack.DoubleMatrix(nodeCnt, nodeCnt);

            foreach (uint feId in feIds)
            {
                LineFE lineFE      = World.GetLineFE(QuantityId, feId);
                uint   elemNodeCnt = lineFE.NodeCount;
                int[]  nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = lineFE.NodeCoordIds[iNode];
                    int nodeId = World.PortCoord2Node(QuantityId, PortId, coId);
                    nodes[iNode] = nodeId;
                }

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

                double[,] sNN   = lineFE.CalcSNN();
                double[,] sNyNy = lineFE.CalcSNxNx();
                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 txxVal = (1.0 / ma.Muxx) * sNyNy[row, col];
                        double ryyVal = (1.0 / ma.Muyy) * sNN[row, col];
                        double uzzVal = ma.Epzz * sNN[row, col];

                        Txx[rowNodeId, colNodeId] += txxVal;
                        Ryy[rowNodeId, colNodeId] += ryyVal;
                        Uzz[rowNodeId, colNodeId] += uzzVal;
                    }
                }
            }
        }
示例#4
0
        // ポート上の線要素の節点ナンバリング
        private void NumberPortNodes(FEWorld world, IList <int> zeroCoordIds)
        {
            Mesher2D mesh = world.Mesh;

            // ポート上の線要素の抽出と節点ナンバリング
            uint portCnt = GetPortCount();

            for (int portId = 0; portId < portCnt; portId++)
            {
                PortCondition portCondition = PortConditions[portId];
                IList <uint>  portEIds      = portCondition.EIds;
                var           lineFEIds     = new List <uint>();
                PortLineFEIdss.Add(lineFEIds);

                var portCo2Node = new Dictionary <int, int>();
                PortCo2Nodes.Add(portCo2Node);
                int portNodeId = 0;

                IList <uint> feIds = LineFEArray.GetObjectIds();
                foreach (var feId in feIds)
                {
                    LineFE lineFE = LineFEArray.GetObject(feId);
                    uint   cadId;
                    {
                        uint     meshId = lineFE.MeshId;
                        uint     elemCnt;
                        MeshType meshType;
                        int      loc;
                        mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId);
                        System.Diagnostics.Debug.Assert(meshType == MeshType.Bar);
                    }
                    if (portEIds.Contains(cadId))
                    {
                        // ポート上の線要素
                        lineFEIds.Add(feId);

                        int[] coIds = lineFE.NodeCoordIds;

                        foreach (int coId in coIds)
                        {
                            if (!portCo2Node.ContainsKey(coId) &&
                                zeroCoordIds.IndexOf(coId) == -1)
                            {
                                portCo2Node[coId] = portNodeId;
                                portNodeId++;
                            }
                        }
                    }
                }
            }
        }
示例#5
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);
                }
            }
        }
示例#6
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);
        }
示例#7
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);
        }
示例#8
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);
                    }
                }
            }
        }
        /*
         * private void CalcTwoBodyContactMortarSegmentationQuantityAB(
         *  uint cQuantityId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
         * {
         *  uint uQuantityId = 0;
         *  System.Diagnostics.Debug.Assert(World.GetFEOrder(uQuantityId) == 1);
         *  System.Diagnostics.Debug.Assert(World.GetCoordCount(uQuantityId) ==
         *      World.GetCoordCount(cQuantityId));
         *  System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2);
         *  System.Diagnostics.Debug.Assert(World.GetDof(cQuantityId) == 2);
         *  int uDof = 2;
         *  int cDof = 2;
         *  int uNodeCnt = (int)World.GetNodeCount(uQuantityId);
         *  int cNodeCnt = (int)World.GetNodeCount(cQuantityId);
         *  int offset = GetOffset(cQuantityId);
         *
         *  // 線要素の変位を更新
         *  UpdateLineFEDisplacements(uQuantityId, uDof, cQuantityId);
         *
         *  // 節点法線ベクトルの計算
         *  Dictionary<int, double[]> co2Normal = GetSlaveLineFECo2Normal(uQuantityId, uDof, cQuantityId);
         *
         *  // MasterからSlaveに垂らした点を計算する
         *  Dictionary<uint, IList<double>> slaveFEL2s = GetSlavePointFromMasterNodes(
         *      co2Normal,
         *      uQuantityId, uDof, cQuantityId);
         *
         *  bool[] lConstraintNodeIds = new bool[cNodeCnt];
         *  IList<uint> slaveFEIds = World.GetContactSlaveLineFEIds(cQuantityId);
         *  foreach (uint slaveFEId in slaveFEIds)
         *  {
         *      LineFE lineFE = World.GetLineFE(uQuantityId, slaveFEId);
         *      uint elemNodeCnt = lineFE.NodeCount;
         *      int[] nodes = new int[elemNodeCnt];
         *      for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *      {
         *          int coId = lineFE.NodeCoordIds[iNode];
         *          int nodeId = World.Coord2Node(uQuantityId, coId);
         *          nodes[iNode] = nodeId;
         *      }
         *
         *      LineFE lLineFE = World.GetLineFE(cQuantityId, slaveFEId);
         *      int[] lNodes = new int[elemNodeCnt];
         *      for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *      {
         *          int coId = lLineFE.NodeCoordIds[iNode];
         *          int lNodeId = World.Coord2Node(cQuantityId, coId);
         *          lNodes[iNode] = lNodeId;
         *      }
         *
         *      double[][] curNodeCoord = new double[elemNodeCnt][];
         *      for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *      {
         *          int coId = lineFE.NodeCoordIds[iNode];
         *          double[] coord = World.GetCoord(uQuantityId, coId);
         *          int iNodeId = nodes[iNode];
         *          curNodeCoord[iNode] = new double[uDof];
         *          if (iNodeId == -1)
         *          {
         *              for (int iDof = 0; iDof < uDof; iDof++)
         *              {
         *                  curNodeCoord[iNode][iDof] = coord[iDof];
         *              }
         *          }
         *          else
         *          {
         *              for (int iDof = 0; iDof < uDof; iDof++)
         *              {
         *                  curNodeCoord[iNode][iDof] = coord[iDof] + U[iNodeId * uDof + iDof];
         *              }
         *          }
         *      }
         *
         *      //IntegrationPoints ip = LineFE.GetIntegrationPoints(LineIntegrationPointCount.Point3);
         *      //System.Diagnostics.Debug.Assert(ip.Ls.Length == 3);
         *      IntegrationPoints ip = LineFE.GetIntegrationPoints(LineIntegrationPointCount.Point5);
         *      System.Diagnostics.Debug.Assert(ip.Ls.Length == 5);
         *
         *      IList<double> L2s = new List<double>();
         *      L2s.Add(0.0);
         *      if (slaveFEL2s.ContainsKey(slaveFEId))
         *      {
         *          foreach (double L2 in slaveFEL2s[slaveFEId])
         *          {
         *              L2s.Add(L2);
         *          }
         *      }
         *      L2s.Add(1.0);
         *      int segCnt = L2s.Count - 1;
         *      for (int iSeg = 0; iSeg < segCnt; iSeg++)
         *      {
         *          double sL2 = L2s[iSeg];
         *          double eL2 = L2s[iSeg + 1];
         *          OpenTK.Vector2d sPt = new OpenTK.Vector2d(
         *              (1.0 - sL2) * curNodeCoord[0][0] + sL2 * curNodeCoord[1][0],
         *              (1.0 - sL2) * curNodeCoord[0][1] + sL2 * curNodeCoord[1][1]
         *          );
         *          OpenTK.Vector2d ePt = new OpenTK.Vector2d(
         *              (1.0 - eL2) * curNodeCoord[0][0] + eL2 * curNodeCoord[1][0],
         *              (1.0 - eL2) * curNodeCoord[0][1] + eL2 * curNodeCoord[1][1]
         *          );
         *          double segLen = (ePt - sPt).Length;
         *          for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
         *          {
         *              double[] segL = ip.Ls[ipPt];
         *              double weight = ip.Weights[ipPt];
         *              double L2 = segL[0] * sL2 + segL[1] * eL2;
         *              double[] L = { 1.0 - L2, L2 };
         *              double[] N = lineFE.CalcN(L);
         *              double[] lN = lLineFE.CalcN(L);
         *              double detJWeight = (segLen / 2.0) * weight;
         *              // 現在の位置
         *              double[] curCoord = new double[uDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  for (int iDof = 0; iDof < uDof; iDof++)
         *                  {
         *                      curCoord[iDof] += curNodeCoord[iNode][iDof] * N[iNode];
         *                  }
         *              }
         *              // 連続な近似法線ベクトルを計算する
         *              double[] normal = new double[uDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  int coId = lineFE.NodeCoordIds[iNode];
         *                  double[] nodeNormal = co2Normal[coId];
         *                  for (int iDof = 0; iDof < uDof; iDof++)
         *                  {
         *                      normal[iDof] += nodeNormal[iDof] * N[iNode];
         *                  }
         *              }
         *              normal = IvyFEM.Lapack.Utils.NormalizeDoubleVector(normal);
         *              double[] tangent = { normal[1], -normal[0] };
         *
         *              // 対応するMasterの点を取得する
         *              uint masterFEId;
         *              double[] masterL;
         *              GetMasterLineFEPoint(
         *                  curCoord, normal,
         *                  uQuantityId, uDof, cQuantityId,
         *                  out masterFEId, out masterL);
         *              if (masterFEId == 0)
         *              {
         *                  // 対応するMasterの点がない
         *                  continue;
         *              }
         *              LineFE masterLineFE = World.GetLineFE(uQuantityId, masterFEId);
         *              System.Diagnostics.Debug.Assert(masterLineFE.NodeCount == elemNodeCnt);
         *              double[] masterN = masterLineFE.CalcN(masterL);
         *              int[] masterNodes = new int[elemNodeCnt];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  int coId = masterLineFE.NodeCoordIds[iNode];
         *                  int nodeId = World.Coord2Node(uQuantityId, coId);
         *                  masterNodes[iNode] = nodeId;
         *              }
         *              // 現在の位置
         *              double[] masterCurCoord = new double[uDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  int coId = masterLineFE.NodeCoordIds[iNode];
         *                  double[] coord = World.GetCoord(uQuantityId, coId);
         *                  int iNodeId = masterNodes[iNode];
         *                  if (iNodeId == -1)
         *                  {
         *                      for (int iDof = 0; iDof < uDof; iDof++)
         *                      {
         *                          masterCurCoord[iDof] += coord[iDof] * masterN[iNode];
         *                      }
         *                  }
         *                  else
         *                  {
         *                      for (int iDof = 0; iDof < uDof; iDof++)
         *                      {
         *                          masterCurCoord[iDof] +=
         *                              (coord[iDof] + U[iNodeId * uDof + iDof]) * masterN[iNode];
         *                      }
         *                  }
         *              }
         *
         *              // ギャップの計算
         *              double gap = 0;
         *              for (int iDof = 0; iDof < uDof; iDof++)
         *              {
         *                  gap += -normal[iDof] * (curCoord[iDof] - masterCurCoord[iDof]);
         *              }
         *
         *              // ラグランジュの未定乗数
         *              double[] l = new double[cDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  int iNodeId = lNodes[iNode];
         *                  if (iNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int iDof = 0; iDof < cDof; iDof++)
         *                  {
         *                      l[iDof] += U[offset + iNodeId * cDof + iDof] * lN[iNode];
         *                  }
         *              }
         *              double ln = 0;
         *              for (int iDof = 0; iDof < cDof; iDof++)
         *              {
         *                  ln += normal[iDof] * l[iDof];
         *              }
         *              double lt = 0;
         *              for (int iDof = 0; iDof < cDof; iDof++)
         *              {
         *                  lt += tangent[iDof] * l[iDof];
         *              }
         *
         *              // Karush-Kuhn-Tucker条件
         *              double tolerance = IvyFEM.Linear.Constants.ConvRatioTolerance;
         *              if (ln <= tolerance &&
         *                  Math.Abs(lt) <= tolerance &&
         *                  gap >= -tolerance)
         *              {
         *                  // 拘束しない
         *                  continue;
         *              }
         *
         *              ////////////////////////////////////////
         *              // これ以降、条件を付加する処理
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  int iNodeId = lNodes[iNode];
         *                  if (iNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  lConstraintNodeIds[iNodeId] = true;
         *              }
         *
         *              // Slave
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = nodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int col = 0; col < elemNodeCnt; col++)
         *                  {
         *                      int colNodeId = lNodes[col];
         *                      if (colNodeId == -1)
         *                      {
         *                          continue;
         *                      }
         *
         *                      double[,] kul = new double[uDof, cDof];
         *                      double[,] klu = new double[cDof, uDof];
         *                      for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                      {
         *                          kul[rowDof, rowDof] +=
         *                              detJWeight * N[row] * lN[col];
         *                          klu[rowDof, rowDof] +=
         *                              detJWeight * N[row] * lN[col];
         *                      }
         *
         *                      for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                      {
         *                          for (int colDof = 0; colDof < cDof; colDof++)
         *                          {
         *                              A[rowNodeId * uDof + rowDof, offset + colNodeId * cDof + colDof] +=
         *                                  kul[rowDof, colDof];
         *                              A[offset + colNodeId * cDof + colDof, rowNodeId * uDof + rowDof] +=
         *                                  klu[colDof, rowDof];
         *                              B[rowNodeId * uDof + rowDof] +=
         *                                  kul[rowDof, colDof] * U[offset + colNodeId * cDof + colDof];
         *                              B[offset + colNodeId * cDof + colDof] +=
         *                                  klu[colDof, rowDof] * U[rowNodeId * uDof + rowDof];
         *                          }
         *                      }
         *                  }
         *              }
         *
         *              // Master
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = masterNodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int col = 0; col < elemNodeCnt; col++)
         *                  {
         *                      int colNodeId = lNodes[col];
         *                      if (colNodeId == -1)
         *                      {
         *                          continue;
         *                      }
         *
         *                      double[,] kul = new double[uDof, cDof];
         *                      double[,] klu = new double[cDof, uDof];
         *                      for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                      {
         *                          kul[rowDof, rowDof] +=
         *                              -detJWeight * masterN[row] * lN[col];
         *                          klu[rowDof, rowDof] +=
         *                              -detJWeight * masterN[row] * lN[col];
         *                      }
         *
         *                      for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                      {
         *                          for (int colDof = 0; colDof < cDof; colDof++)
         *                          {
         *                              A[rowNodeId * uDof + rowDof, offset + colNodeId * cDof + colDof] +=
         *                                  kul[rowDof, colDof];
         *                              A[offset + colNodeId * cDof + colDof, rowNodeId * uDof + rowDof] +=
         *                                  klu[colDof, rowDof];
         *                              B[rowNodeId * uDof + rowDof] +=
         *                                  kul[rowDof, colDof] * U[offset + colNodeId * cDof + colDof];
         *                              B[offset + colNodeId * cDof + colDof] +=
         *                                  klu[colDof, rowDof] * U[rowNodeId * uDof + rowDof];
         *                          }
         *                      }
         *                  }
         *              }
         *
         *              // Slave
         *              double[,] qu = new double[elemNodeCnt, uDof];
         *              double[,] ql = new double[elemNodeCnt, cDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  for (int iDof = 0; iDof < uDof; iDof++)
         *                  {
         *                      qu[iNode, iDof] += detJWeight * l[iDof] * N[iNode];
         *                  }
         *              }
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  for (int iDof = 0; iDof < cDof; iDof++)
         *                  {
         *                      ql[iNode, iDof] += detJWeight * lN[iNode] * curCoord[iDof];
         *                  }
         *              }
         *
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = nodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                  {
         *                      B[rowNodeId * uDof + rowDof] += -qu[row, rowDof];
         *                  }
         *              }
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = lNodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int rowDof = 0; rowDof < cDof; rowDof++)
         *                  {
         *                      B[offset + rowNodeId * cDof + rowDof] += -ql[row, rowDof];
         *                  }
         *              }
         *
         *              // Master
         *              double[,] masterQu = new double[elemNodeCnt, uDof];
         *              double[,] masterQl = new double[elemNodeCnt, cDof];
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  for (int iDof = 0; iDof < uDof; iDof++)
         *                  {
         *                      masterQu[iNode, iDof] += -detJWeight * l[iDof] * masterN[iNode];
         *                  }
         *              }
         *              for (int iNode = 0; iNode < elemNodeCnt; iNode++)
         *              {
         *                  for (int iDof = 0; iDof < uDof; iDof++)
         *                  {
         *                      masterQl[iNode, iDof] += -detJWeight * lN[iNode] * masterCurCoord[iDof];
         *                  }
         *              }
         *
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = masterNodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int rowDof = 0; rowDof < uDof; rowDof++)
         *                  {
         *                      B[rowNodeId * uDof + rowDof] += -masterQu[row, rowDof];
         *                  }
         *              }
         *              for (int row = 0; row < elemNodeCnt; row++)
         *              {
         *                  int rowNodeId = lNodes[row];
         *                  if (rowNodeId == -1)
         *                  {
         *                      continue;
         *                  }
         *                  for (int rowDof = 0; rowDof < cDof; rowDof++)
         *                  {
         *                      B[offset + rowNodeId * cDof + rowDof] += -masterQl[row, rowDof];
         *                  }
         *              }
         *          }
         *      }
         *  }
         *
         *  // 条件をセットしなかった節点
         *  for (int iNodeId = 0; iNodeId < cNodeCnt; iNodeId++)
         *  {
         *      if (lConstraintNodeIds[iNodeId])
         *      {
         *          continue;
         *      }
         *      for (int iDof = 0; iDof < cDof; iDof++)
         *      {
         *          A[offset + iNodeId * cDof + iDof, offset + iNodeId * cDof + iDof] = 1.0;
         *          B[offset + iNodeId * cDof + iDof] = 0;
         *      }
         *  }
         * }
         */
        private void CalcTwoBodyContactMortarSegmentationQuantityAB(
            uint cQuantityId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B)
        {
            uint uQuantityId = 0;

            System.Diagnostics.Debug.Assert(World.GetFEOrder(uQuantityId) == 1);
            System.Diagnostics.Debug.Assert(World.GetCoordCount(uQuantityId) ==
                                            World.GetCoordCount(cQuantityId));
            System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2);
            System.Diagnostics.Debug.Assert(World.GetDof(cQuantityId) == 2);
            int uDof     = 2;
            int cDof     = 2;
            int uNodeCnt = (int)World.GetNodeCount(uQuantityId);
            int cNodeCnt = (int)World.GetNodeCount(cQuantityId);
            int offset   = GetOffset(cQuantityId);

            // 線要素の変位を更新
            UpdateLineFEDisplacements(uQuantityId, uDof, cQuantityId);

            // 節点法線ベクトルの計算
            Dictionary <int, double[]> co2Normal = GetSlaveLineFECo2Normal(uQuantityId, uDof, cQuantityId);

            // MasterからSlaveに垂らした点を計算する
            Dictionary <uint, IList <double> > slaveFEL2s = GetSlavePointFromMasterNodes(
                co2Normal,
                uQuantityId, uDof, cQuantityId);

            bool[]       lConstraintNodeIds = new bool[cNodeCnt];
            IList <uint> slaveFEIds         = World.GetContactSlaveLineFEIds(cQuantityId);

            foreach (uint slaveFEId in slaveFEIds)
            {
                LineFE lineFE      = World.GetLineFE(uQuantityId, slaveFEId);
                uint   elemNodeCnt = lineFE.NodeCount;
                int[]  nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId   = lineFE.NodeCoordIds[iNode];
                    int nodeId = World.Coord2Node(uQuantityId, coId);
                    nodes[iNode] = nodeId;
                }

                LineFE lLineFE = World.GetLineFE(cQuantityId, slaveFEId);
                int[]  lNodes  = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId    = lLineFE.NodeCoordIds[iNode];
                    int lNodeId = World.Coord2Node(cQuantityId, coId);
                    lNodes[iNode] = lNodeId;
                }

                double[][] curNodeCoord = new double[elemNodeCnt][];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int      coId    = lineFE.NodeCoordIds[iNode];
                    double[] coord   = World.GetCoord(uQuantityId, coId);
                    int      iNodeId = nodes[iNode];
                    curNodeCoord[iNode] = new double[uDof];
                    if (iNodeId == -1)
                    {
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            curNodeCoord[iNode][iDof] = coord[iDof];
                        }
                    }
                    else
                    {
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            curNodeCoord[iNode][iDof] = coord[iDof] + U[iNodeId * uDof + iDof];
                        }
                    }
                }

                //IntegrationPoints ip = LineFE.GetIntegrationPoints(LineIntegrationPointCount.Point3);
                //System.Diagnostics.Debug.Assert(ip.Ls.Length == 3);
                IntegrationPoints ip = LineFE.GetIntegrationPoints(LineIntegrationPointCount.Point5);
                System.Diagnostics.Debug.Assert(ip.Ls.Length == 5);

                IList <double> L2s = new List <double>();
                L2s.Add(0.0);
                if (slaveFEL2s.ContainsKey(slaveFEId))
                {
                    foreach (double L2 in slaveFEL2s[slaveFEId])
                    {
                        L2s.Add(L2);
                    }
                }
                L2s.Add(1.0);
                int segCnt = L2s.Count - 1;
                for (int iSeg = 0; iSeg < segCnt; iSeg++)
                {
                    double          sL2 = L2s[iSeg];
                    double          eL2 = L2s[iSeg + 1];
                    OpenTK.Vector2d sPt = new OpenTK.Vector2d(
                        (1.0 - sL2) * curNodeCoord[0][0] + sL2 * curNodeCoord[1][0],
                        (1.0 - sL2) * curNodeCoord[0][1] + sL2 * curNodeCoord[1][1]
                        );
                    OpenTK.Vector2d ePt = new OpenTK.Vector2d(
                        (1.0 - eL2) * curNodeCoord[0][0] + eL2 * curNodeCoord[1][0],
                        (1.0 - eL2) * curNodeCoord[0][1] + eL2 * curNodeCoord[1][1]
                        );
                    double segLen = (ePt - sPt).Length;
                    for (int ipPt = 0; ipPt < ip.PointCount; ipPt++)
                    {
                        double[] segL       = ip.Ls[ipPt];
                        double   weight     = ip.Weights[ipPt];
                        double   L2         = segL[0] * sL2 + segL[1] * eL2;
                        double[] L          = { 1.0 - L2, L2 };
                        double[] N          = lineFE.CalcN(L);
                        double[] lN         = lLineFE.CalcN(L);
                        double   detJWeight = (segLen / 2.0) * weight;
                        // 現在の位置
                        double[] curCoord = new double[uDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            for (int iDof = 0; iDof < uDof; iDof++)
                            {
                                curCoord[iDof] += curNodeCoord[iNode][iDof] * N[iNode];
                            }
                        }
                        // 連続な近似法線ベクトルを計算する
                        double[] normal = new double[uDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            int      coId       = lineFE.NodeCoordIds[iNode];
                            double[] nodeNormal = co2Normal[coId];
                            for (int iDof = 0; iDof < uDof; iDof++)
                            {
                                normal[iDof] += nodeNormal[iDof] * N[iNode];
                            }
                        }
                        normal = IvyFEM.Lapack.Utils.NormalizeDoubleVector(normal);
                        double[] tangent = { normal[1], -normal[0] };

                        // 対応するMasterの点を取得する
                        uint     masterFEId;
                        double[] masterL;
                        GetMasterLineFEPoint(
                            curCoord, normal,
                            uQuantityId, uDof, cQuantityId,
                            out masterFEId, out masterL);
                        if (masterFEId == 0)
                        {
                            // 対応するMasterの点がない
                            continue;
                        }
                        LineFE masterLineFE = World.GetLineFE(uQuantityId, masterFEId);
                        System.Diagnostics.Debug.Assert(masterLineFE.NodeCount == elemNodeCnt);
                        double[] masterN     = masterLineFE.CalcN(masterL);
                        int[]    masterNodes = new int[elemNodeCnt];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            int coId   = masterLineFE.NodeCoordIds[iNode];
                            int nodeId = World.Coord2Node(uQuantityId, coId);
                            masterNodes[iNode] = nodeId;
                        }
                        // 現在の位置
                        double[] masterCurCoord = new double[uDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            int      coId    = masterLineFE.NodeCoordIds[iNode];
                            double[] coord   = World.GetCoord(uQuantityId, coId);
                            int      iNodeId = masterNodes[iNode];
                            if (iNodeId == -1)
                            {
                                for (int iDof = 0; iDof < uDof; iDof++)
                                {
                                    masterCurCoord[iDof] += coord[iDof] * masterN[iNode];
                                }
                            }
                            else
                            {
                                for (int iDof = 0; iDof < uDof; iDof++)
                                {
                                    masterCurCoord[iDof] +=
                                        (coord[iDof] + U[iNodeId * uDof + iDof]) * masterN[iNode];
                                }
                            }
                        }

                        // ギャップの計算
                        double gap = 0;
                        for (int iDof = 0; iDof < uDof; iDof++)
                        {
                            gap += -normal[iDof] * (curCoord[iDof] - masterCurCoord[iDof]);
                        }

                        // ラグランジュの未定乗数
                        double[] l = new double[cDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            int iNodeId = lNodes[iNode];
                            if (iNodeId == -1)
                            {
                                continue;
                            }
                            for (int iDof = 0; iDof < cDof; iDof++)
                            {
                                l[iDof] += U[offset + iNodeId * cDof + iDof] * lN[iNode];
                            }
                        }
                        // Karush-Kuhn-Tucker条件
                        double tolerance = IvyFEM.Linear.Constants.ConvRatioTolerance;
                        if (l[0] <= tolerance &&
                            Math.Abs(l[1]) <= tolerance &&
                            gap >= -tolerance)
                        {
                            // 拘束しない
                            continue;
                        }

                        ////////////////////////////////////////
                        // これ以降、条件を付加する処理
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            int iNodeId = lNodes[iNode];
                            if (iNodeId == -1)
                            {
                                continue;
                            }
                            lConstraintNodeIds[iNodeId] = true;
                        }

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

                                double[,] kul = new double[uDof, cDof];
                                double[,] klu = new double[cDof, uDof];
                                for (int rowDof = 0; rowDof < uDof; rowDof++)
                                {
                                    kul[rowDof, 0] +=
                                        detJWeight * normal[rowDof] * N[row] * lN[col];
                                    klu[0, rowDof] +=
                                        detJWeight * normal[rowDof] * N[row] * lN[col];
                                    kul[rowDof, 1] +=
                                        detJWeight * tangent[rowDof] * N[row] * lN[col];
                                    klu[1, rowDof] +=
                                        detJWeight * tangent[rowDof] * N[row] * lN[col];
                                }

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

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

                                double[,] kul = new double[uDof, cDof];
                                double[,] klu = new double[cDof, uDof];
                                for (int rowDof = 0; rowDof < uDof; rowDof++)
                                {
                                    kul[rowDof, 0] +=
                                        -detJWeight * normal[rowDof] * masterN[row] * lN[col];
                                    klu[0, rowDof] +=
                                        -detJWeight * normal[rowDof] * masterN[row] * lN[col];
                                    kul[rowDof, 1] +=
                                        -detJWeight * tangent[rowDof] * masterN[row] * lN[col];
                                    klu[1, rowDof] +=
                                        -detJWeight * tangent[rowDof] * masterN[row] * lN[col];
                                }

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

                        // Slave
                        double[,] qu = new double[elemNodeCnt, uDof];
                        double[,] ql = new double[elemNodeCnt, cDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            for (int iDof = 0; iDof < uDof; iDof++)
                            {
                                qu[iNode, iDof] +=
                                    detJWeight * (l[0] * normal[iDof] + l[1] * tangent[iDof]) * N[iNode];
                            }
                        }
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            for (int iDof = 0; iDof < cDof; iDof++)
                            {
                                ql[iNode, 0] +=
                                    detJWeight * lN[iNode] * normal[iDof] * curCoord[iDof];
                                ql[iNode, 1] +=
                                    detJWeight * lN[iNode] * tangent[iDof] * curCoord[iDof];
                            }
                        }

                        for (int row = 0; row < elemNodeCnt; row++)
                        {
                            int rowNodeId = nodes[row];
                            if (rowNodeId == -1)
                            {
                                continue;
                            }
                            for (int rowDof = 0; rowDof < uDof; rowDof++)
                            {
                                B[rowNodeId * uDof + rowDof] += -qu[row, rowDof];
                            }
                        }
                        for (int row = 0; row < elemNodeCnt; row++)
                        {
                            int rowNodeId = lNodes[row];
                            if (rowNodeId == -1)
                            {
                                continue;
                            }
                            for (int rowDof = 0; rowDof < cDof; rowDof++)
                            {
                                B[offset + rowNodeId * cDof + rowDof] += -ql[row, rowDof];
                            }
                        }

                        // Master
                        double[,] masterQu = new double[elemNodeCnt, uDof];
                        double[,] masterQl = new double[elemNodeCnt, cDof];
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            for (int iDof = 0; iDof < uDof; iDof++)
                            {
                                masterQu[iNode, iDof] +=
                                    -detJWeight * (l[0] * normal[iDof] + l[1] * tangent[iDof]) * masterN[iNode];
                            }
                        }
                        for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                        {
                            for (int iDof = 0; iDof < uDof; iDof++)
                            {
                                masterQl[iNode, 0] +=
                                    -detJWeight * lN[iNode] * normal[iDof] * masterCurCoord[iDof];
                                masterQl[iNode, 1] +=
                                    -detJWeight * lN[iNode] * tangent[iDof] * masterCurCoord[iDof];
                            }
                        }

                        for (int row = 0; row < elemNodeCnt; row++)
                        {
                            int rowNodeId = masterNodes[row];
                            if (rowNodeId == -1)
                            {
                                continue;
                            }
                            for (int rowDof = 0; rowDof < uDof; rowDof++)
                            {
                                B[rowNodeId * uDof + rowDof] += -masterQu[row, rowDof];
                            }
                        }
                        for (int row = 0; row < elemNodeCnt; row++)
                        {
                            int rowNodeId = lNodes[row];
                            if (rowNodeId == -1)
                            {
                                continue;
                            }
                            for (int rowDof = 0; rowDof < cDof; rowDof++)
                            {
                                B[offset + rowNodeId * cDof + rowDof] += -masterQl[row, rowDof];
                            }
                        }
                    }
                }
            }

            // 条件をセットしなかった節点
            for (int iNodeId = 0; iNodeId < cNodeCnt; iNodeId++)
            {
                if (lConstraintNodeIds[iNodeId])
                {
                    continue;
                }
                for (int iDof = 0; iDof < cDof; iDof++)
                {
                    A[offset + iNodeId * cDof + iDof, offset + iNodeId * cDof + iDof] = 1.0;
                    B[offset + iNodeId * cDof + iDof] = 0;
                }
            }
        }
示例#10
0
 public LineFE(LineFE src)
 {
     Copy(src);
 }
示例#11
0
        private void SetABC(IvyFEM.Linear.ComplexSparseMatrix A, System.Numerics.Complex[] B)
        {
            uint quantityId = 0;

            if (World.GetPortCount(quantityId) == 0)
            {
                return;
            }
            System.Diagnostics.Debug.Assert(World.GetPortCount(quantityId) == 1);
            IList <PortCondition> portConditions = World.GetPortConditions(quantityId);
            PortCondition         portCondition  = portConditions[0];
            IList <uint>          abcEIds        = portCondition.EIds;
            IList <uint>          feIds          = World.GetLineFEIds(quantityId);

            foreach (uint feId in feIds)
            {
                LineFE lineFE = World.GetLineFE(quantityId, 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 (abcEIds.Contains(eId))
                {
                    // ABCを適用する辺
                }
                else
                {
                    continue;
                }

                // ABC
                uint  elemNodeCnt = lineFE.NodeCount;
                int[] coIds       = lineFE.NodeCoordIds;
                int[] nodes       = new int[elemNodeCnt];
                for (int iNode = 0; iNode < elemNodeCnt; iNode++)
                {
                    int coId = coIds[iNode];
                    nodes[iNode] = World.Coord2Node(quantityId, coId);
                }
                Material ma0 = World.GetMaterial(lineFE.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   = lineFE.CalcSNN();
                double[,] sNxNx = lineFE.CalcSNxNx();
                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;
                        }

                        System.Numerics.Complex a =
                            System.Numerics.Complex.ImaginaryOne * k * sNN[row, col] -
                            System.Numerics.Complex.ImaginaryOne / (2.0 * k) * sNxNx[row, col];
                        A[rowNodeId, colNodeId] += a;
                    }
                }
            }
        }
示例#12
0
        private void Set(uint valueId, FieldDerivativeType valueDt,
                         bool isntDisplacementValue,
                         bool isDrawInnerEdge,
                         FEWorld world)
        {
            var mesh = world.Mesh;

            if (!world.IsFieldValueId(valueId))
            {
                throw new ArgumentException();
                //return;
            }

            ValueId = valueId;
            ValueDt = valueDt;
            IsntDisplacementValue = isntDisplacementValue;

            var fv = world.GetFieldValue(ValueId);

            // 線要素を生成
            uint quantityId = fv.QuantityId;

            if (isDrawInnerEdge)
            {
                // 内部の全ての辺を描画
                LineFEs = world.MakeBoundOfElements(quantityId);
            }
            else
            {
                // 境界の辺だけ描画
                LineFEs = new List <LineFE>();
                IList <MeshBarArray> barArrays = mesh.GetBarArrays();
                foreach (MeshBarArray barArray in barArrays)
                {
                    uint        eCadId   = barArray.ECadId;
                    IList <int> allCoIds = world.GetCoordIdsFromCadId(quantityId, eCadId, CadElementType.Edge);

                    for (int i = 0; i < (allCoIds.Count - 1); i++)
                    {
                        int    workFEOrder = 1;
                        LineFE lineFE      = new LineFE(workFEOrder);
                        {
                            int[] coIds = { allCoIds[i], allCoIds[i + 1] };
                            lineFE.SetVertexCoordIds(coIds);
                            lineFE.SetNodeCoordIds(coIds);
                        }
                        LineFEs.Add(lineFE);
                    }
                }
            }

            int feOrder;
            {
                LineFE lineFE = LineFEs[0]; // 先頭の要素
                feOrder     = lineFE.Order;
                LinePtCount = lineFE.NodeCount;
            }

            uint ptCnt = LineCount * LinePtCount;
            uint dim   = world.Dimension;

            uint drawDim;

            if (!IsntDisplacementValue &&
                dim == 2 &&
                (fv.Type == FieldValueType.Scalar || fv.Type == FieldValueType.ZScalar))
            {
                drawDim = 3;
            }
            else
            {
                drawDim = dim;
            }
            VertexArray.SetSize(ptCnt, drawDim);

            if (drawDim == 2)
            {
                SutableRotMode = RotMode.RotMode2D;
            }
            else if (dim == 3)
            {
                SutableRotMode = RotMode.RotMode3D;
            }
            else
            {
                SutableRotMode = RotMode.RotMode2DH;
            }


            Update(world);
        }
示例#13
0
        public void Update(FEWorld world)
        {
            FieldValue fv         = world.GetFieldValue(ValueId);
            uint       quantityId = fv.QuantityId;
            uint       dim        = world.Dimension;
            uint       ptCnt      = LineCount * LinePtCount;
            uint       lineCnt    = LineCount;
            uint       drawDim    = VertexArray.Dimension;

            if (IsntDisplacementValue)
            {
                System.Diagnostics.Debug.Assert(drawDim == 2); // いまはそうなってる
                for (int iEdge = 0; iEdge < lineCnt; iEdge++)
                {
                    LineFE lineFE = LineFEs[iEdge];
                    for (int iPt = 0; iPt < LinePtCount; iPt++)
                    {
                        int      coId = lineFE.NodeCoordIds[iPt];
                        double[] co   = world.GetCoord(quantityId, coId);
                        VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + 0] = co[0];
                        VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + 1] = co[1];
                    }
                }
            }
            else
            {
                // 変位を伴う場合

                if (dim == 2 && drawDim == 3)
                {
                    for (int iEdge = 0; iEdge < LineCount; iEdge++)
                    {
                        LineFE lineFE = LineFEs[iEdge];
                        System.Diagnostics.Debug.Assert(lineFE.NodeCoordIds.Length == LinePtCount);
                        for (int iPt = 0; iPt < LinePtCount; iPt++)
                        {
                            int                 coId  = lineFE.NodeCoordIds[iPt];
                            double[]            coord = world.GetCoord(quantityId, coId);
                            FieldDerivativeType dt    = ValueDt;
                            double              value = fv.GetShowValue(coId, 0, dt);
                            VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + 0] = coord[0];
                            VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + 1] = coord[1];
                            VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + 2] = value;
                        }
                    }
                }
                else
                {
                    for (int iEdge = 0; iEdge < lineCnt; iEdge++)
                    {
                        LineFE lineFE = LineFEs[iEdge];
                        System.Diagnostics.Debug.Assert(lineFE.NodeCoordIds.Length == LinePtCount);
                        for (int iPt = 0; iPt < LinePtCount; iPt++)
                        {
                            int                 coId  = lineFE.NodeCoordIds[iPt];
                            double[]            coord = world.GetCoord(quantityId, coId);
                            FieldDerivativeType dt    = ValueDt;
                            for (int iDim = 0; iDim < drawDim; iDim++)
                            {
                                double value = fv.GetShowValue(coId, iDim, dt);
                                VertexArray.VertexCoordArray[(iEdge * LinePtCount + iPt) * drawDim + iDim] =
                                    coord[iDim] + value;
                            }
                        }
                    }
                }
            }
        }