// ポート上の線要素の節点ナンバリング 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++; } } } } } }
public void Copy(PortCondition src) { EIds = new List <uint>(src.EIds); ValueType = src.ValueType; Dof = src.Dof; FixedDofIndexs = new List <uint>(src.FixedDofIndexs); DoubleValues = null; if (src.DoubleValues != null) { DoubleValues = new double[src.DoubleValues.Length]; src.DoubleValues.CopyTo(DoubleValues, 0); } ComplexValues = null; if (src.ComplexValues != null) { ComplexValues = new System.Numerics.Complex[src.ComplexValues.Length]; src.ComplexValues.CopyTo(ComplexValues, 0); } IntAdditionalParameters = new List <int>(src.IntAdditionalParameters); DoubleAdditionalParameters = new List <double>(src.DoubleAdditionalParameters); ComplexAdditionalParameters = new List <System.Numerics.Complex>(src.ComplexAdditionalParameters); }
// 境界が流線方向と同じとき // ψの法線成分(速度の接線成分に比例)がある // ψ = 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 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; } } } }
public PortCondition(PortCondition src) { Copy(src); }