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]; } } }
// 接触解析の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); } } }
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; } } } }
// ポート上の線要素の節点ナンバリング 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++; } } } } } }
// 座標、三角形要素と線要素を生成する 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); } } }
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); }
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); }
// 境界が流線方向と同じとき // ψの法線成分(速度の接線成分に比例)がある // ψ = 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; } } }
public LineFE(LineFE src) { Copy(src); }
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; } } } }
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); }
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; } } } } } }