private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; IList <uint> feIds = World.GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(quantityId, feId); uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = triFE.NodeCoordIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(triFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is PoissonMaterial); var ma = ma0 as PoissonMaterial; double k = ma.Alpha; double f = ma.F; double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; double[] sN = triFE.CalcSN(); for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } double a = k * (sNxNx[row, col] + sNyNy[row, col]); A[rowNodeId, colNodeId] += a; } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } B[rowNodeId] += f * sN[row]; } } }
private void SetTri(FEWorld world, uint valueId) { System.Diagnostics.Debug.Assert(Type == ElementType.Tri); if (Type != ElementType.Tri) { return; } FieldValue fv = world.GetFieldValue(valueId); uint quantityId = fv.QuantityId; int feOrder; { uint feId = world.GetTriangleFEIdFromMesh(quantityId, MeshId, 0); // 先頭の要素 System.Diagnostics.Debug.Assert(feId != 0); TriangleFE triFE = world.GetTriangleFE(quantityId, feId); feOrder = triFE.Order; ElemPtCount = triFE.NodeCount; } Indexs = new uint[ElemPtCount * ElemCount]; for (int iTri = 0; iTri < ElemCount; iTri++) { uint feId = world.GetTriangleFEIdFromMesh(quantityId, MeshId, (uint)iTri); System.Diagnostics.Debug.Assert(feId != 0); TriangleFE triFE = world.GetTriangleFE(quantityId, feId); for (int iPt = 0; iPt < ElemPtCount; iPt++) { Indexs[iTri * ElemPtCount + iPt] = (uint)triFE.NodeCoordIds[iPt]; } } }
private void MakeCo2AndEdgeCos2TriangleFE() { Co2TriangleFE.Clear(); IList <uint> feIds = GetTriangleFEIds(); foreach (uint feId in feIds) { TriangleFE triFE = GetTriangleFE(feId); // 節点→要素 { int[] coIds = triFE.NodeCoordIds; for (int i = 0; i < coIds.Length; i++) { int coId = coIds[i]; IList <uint> targetIds = null; if (Co2TriangleFE.ContainsKey(coId)) { targetIds = Co2TriangleFE[coId]; } else { targetIds = new List <uint>(); Co2TriangleFE[coId] = targetIds; } targetIds.Add(feId); } } // 辺(頂点1-頂点2)→要素 { int[] coIds = triFE.VertexCoordIds; for (int i = 0; i < coIds.Length; i++) { int v1 = coIds[i]; int v2 = coIds[(i + 1) % coIds.Length]; if (v1 > v2) { int tmp = v1; v1 = v2; v2 = tmp; } string edgeKey = v1 + "_" + v2; IList <uint> targetIds = null; if (EdgeCos2TriangleFE.ContainsKey(edgeKey)) { targetIds = EdgeCos2TriangleFE[edgeKey]; } else { targetIds = new List <uint>(); EdgeCos2TriangleFE[edgeKey] = targetIds; } targetIds.Add(feId); } } } }
public void UpdateBubbleFieldValueValuesFromNodeValues( uint valueId, FieldDerivativeType dt, double[] nodeValues) { System.Diagnostics.Debug.Assert(FieldValueArray.IsObjectId(valueId)); FieldValue fv = FieldValueArray.GetObject(valueId); uint quantityId = fv.QuantityId; uint dof = fv.Dof; System.Diagnostics.Debug.Assert(fv.Dof == GetDof(quantityId)); double[] values = fv.GetDoubleValues(dt); uint coCnt = GetCoordCount(quantityId); uint offsetNode = 0; for (uint qId = 0; qId < quantityId; qId++) { offsetNode += GetNodeCount(qId) * GetDof(qId); } IList <uint> feIds = GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = GetTriangleFE(quantityId, feId); int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; double[] bubbleValue = new double[dof]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; int nodeId = Coord2Node(quantityId, coId); if (nodeId == -1) { //for (int iDof = 0; iDof < dof; iDof++) //{ // bubbleValue[iDof] += 0; //} } else { for (int iDof = 0; iDof < dof; iDof++) { bubbleValue[iDof] += nodeValues[offsetNode + nodeId * dof + iDof]; } } } for (int iDof = 0; iDof < dof; iDof++) { bubbleValue[iDof] /= (double)elemNodeCnt; } for (int iDof = 0; iDof < dof; iDof++) { values[(feId - 1) * dof + iDof] = bubbleValue[iDof]; } } }
private void CalcAB(double k0, IvyFEM.Linear.ComplexSparseMatrix A, System.Numerics.Complex[] B) { IList <uint> feIds = World.GetTriangleFEIds(QuantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(QuantityId, feId); uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = triFE.NodeCoordIds[iNode]; int nodeId = World.Coord2Node(QuantityId, coId); nodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(triFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is DielectricMaterial); var ma = ma0 as DielectricMaterial; double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } double a = (1.0 / ma.Muxx) * sNyNy[row, col] + (1.0 / ma.Muyy) * sNxNx[row, col] - (k0 * k0 * ma.Epzz) * sNN[row, col]; A[rowNodeId, colNodeId] += (System.Numerics.Complex)a; } } } }
public void UpdateBubbleFieldValueValuesFromCoordValues( uint valueId, FieldDerivativeType dt, double[] coordValues) { System.Diagnostics.Debug.Assert(FieldValueArray.IsObjectId(valueId)); FieldValue fv = FieldValueArray.GetObject(valueId); uint quantityId = fv.QuantityId; uint dof = fv.Dof; double[] values = fv.GetDoubleValues(dt); uint coCnt = GetCoordCount(quantityId); System.Diagnostics.Debug.Assert(coCnt * dof == coordValues.Length); IList <uint> feIds = GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = GetTriangleFE(quantityId, feId); int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; double[] bubbleValue = new double[dof]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; for (int iDof = 0; iDof < dof; iDof++) { bubbleValue[iDof] += coordValues[coId * dof + iDof]; } } for (int iDof = 0; iDof < dof; iDof++) { bubbleValue[iDof] /= (double)elemNodeCnt; } for (int iDof = 0; iDof < dof; iDof++) { values[(feId - 1) * dof + iDof] = bubbleValue[iDof]; } } }
// 三角形要素の節点ナンバリング private void NumberTriangleNodes(FEWorld world, IList <int> zeroCoordIds) { Mesher2D mesh = world.Mesh; // ナンバリング int nodeId = 0; IList <uint> feIds = TriangleFEArray.GetObjectIds(); foreach (uint feId in feIds) { TriangleFE fe = TriangleFEArray.GetObject(feId); int elemPtCnt = fe.NodeCoordIds.Length; int[] coIds = fe.NodeCoordIds; for (int iPt = 0; iPt < elemPtCnt; iPt++) { int coId = coIds[iPt]; if (!Co2Node.ContainsKey(coId) && zeroCoordIds.IndexOf(coId) == -1) { Co2Node[coId] = nodeId; nodeId++; } } uint meshId = fe.MeshId; int iElem = fe.MeshElemId; uint elemCnt; MeshType meshType; int loc; uint cadId; mesh.GetMeshInfo(meshId, out elemCnt, out meshType, out loc, out cadId); System.Diagnostics.Debug.Assert(meshType == MeshType.Tri); var triArray = mesh.GetTriArrays(); var tri = triArray[loc].Tris[iElem]; tri.FEId = (int)feId; string key = string.Format(meshId + "_" + iElem); Mesh2TriangleFE.Add(key, feId); } }
private bool HasNonLinearElasticMaterial() { bool hasNonlinear = false; uint quantityId = 0; // Note: 複数変数のときでも要素Idは同じはずなので0指定 IList <uint> feIds = World.GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(quantityId, feId); Material ma = World.GetMaterial(triFE.MaterialId); if (ma is LinearElasticMaterial) { // linear } else { hasNonlinear = true; break; } } return(hasNonlinear); }
private void CalcGLSNavierStokesByPicardAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint vQuantityId = 0; uint pQuantityId = 1; int vDof = 2; int pDof = 1; int vNodeCnt = (int)World.GetNodeCount(vQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = vNodeCnt * vDof; IList <uint> feIds = World.GetTriangleFEIds(vQuantityId); foreach (uint feId in feIds) { TriangleFE vTriFE = World.GetTriangleFE(vQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = vTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] vCoIds = vTriFE.NodeCoordIds; uint vElemNodeCnt = vTriFE.NodeCount; int[] vNodes = new int[vElemNodeCnt]; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { int coId = vCoIds[iNode]; int nodeId = World.Coord2Node(vQuantityId, coId); vNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(vTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double nu = mu / rho; double[] g = { ma.GravityX, ma.GravityY }; double[][] velos = new double[vElemNodeCnt][]; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { double[] velo = new double[vDof]; int nodeId = vNodes[iNode]; if (nodeId == -1) { // 0 } else { for (int iDof = 0; iDof < vDof; iDof++) { velo[iDof] = U[nodeId * vDof + iDof]; } } velos[iNode] = velo; } /* * double taum = 0; * double tauc = 0; * { * double[] aveVelo = { * (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0, * (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0 * }; * double veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]); * double Ae = vTriFE.GetArea(); * double h = 2.0 * Math.Sqrt(Ae / Math.PI); * double sqinvtaum1 = 0; * double sqinvtaum2 = (2.0 * 2.0 * veloNorm * veloNorm) / (h * h); * double sqinvtaum3 = (4.0 * 4.0 * nu * nu) / (h * h * h * h); * double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3; * taum = 1.0 / Math.Sqrt(sqinvtaum); * * double re = veloNorm * h / (2.0 * nu); * if (re < 3.0) * { * tauc = (1.0 / 2.0) * h * veloNorm * re / 3.0; * } * else * { * tauc = (1.0 / 2.0) * h * veloNorm; * } * } */ double taum = 0; double tauc = 0; { double[] aveVelo = { (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0, (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0 }; double veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]); double[][] Lu = new double[vDof][]; { double[] a; double[] b; double[] c; vTriFE.CalcTransMatrix(out a, out b, out c); // Lx Lu[0] = b; // Ly Lu[1] = c; } IvyFEM.Lapack.DoubleMatrix GMat = new IvyFEM.Lapack.DoubleMatrix(vDof, vDof); double[] gVec = new double[vDof]; for (int iDof = 0; iDof < vDof; iDof++) { for (int jDof = 0; jDof < vDof; jDof++) { for (int kDof = 0; kDof < vDof; kDof++) { GMat[iDof, jDof] += Lu[iDof][kDof] * Lu[jDof][kDof]; } } } for (int iDof = 0; iDof < vDof; iDof++) { for (int kDof = 0; kDof < vDof; kDof++) { gVec[iDof] += Lu[iDof][kDof]; } } double sqinvtaum1 = 0; double sqinvtaum2 = 0; { double[] tmpVec = GMat * aveVelo; sqinvtaum2 = IvyFEM.Lapack.Functions.ddot(aveVelo, tmpVec); } double sqinvtaum3 = 0; { IvyFEM.Lapack.DoubleMatrix GMatT = new Lapack.DoubleMatrix(GMat); GMatT.Transpose(); double GMatDoubleDot = IvyFEM.Lapack.DoubleMatrix.DoubleDot(GMat, GMatT); sqinvtaum3 = 30.0 * nu * nu * GMatDoubleDot; } double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3; taum = 1.0 / Math.Sqrt(sqinvtaum); double gDot = IvyFEM.Lapack.Functions.ddot(gVec, gVec); tauc = 1.0 / (taum * gDot); } double[] vSN = vTriFE.CalcSN(); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] vN = vTriFE.CalcN(L); double[][] vNu = vTriFE.CalcNu(L); double[] vNx = vNu[0]; double[] vNy = vNu[1]; double[, ][] vNuv = vTriFE.CalcNuv(L); double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = vTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double[] v = new double[vDof]; double[] vx = new double[vDof]; double[] vy = new double[vDof]; double[] vxx = new double[vDof]; double[] vxy = new double[vDof]; double[] vyx = new double[vDof]; double[] vyy = new double[vDof]; double p = 0; double px = 0; double py = 0; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { int nodeId = vNodes[iNode]; if (nodeId == -1) { continue; } for (int iDof = 0; iDof < vDof; iDof++) { double vValue = U[nodeId * vDof + iDof]; v[iDof] += vValue * vN[iNode]; vx[iDof] += vValue * vNx[iNode]; vy[iDof] += vValue * vNy[iNode]; vxx[iDof] += vValue * vNuv[0, 0][iNode]; vxy[iDof] += vValue * vNuv[0, 1][iNode]; vyx[iDof] += vValue * vNuv[1, 0][iNode]; vyy[iDof] += vValue * vNuv[1, 1][iNode]; } } for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int nodeId = pNodes[iNode]; if (nodeId == -1) { continue; } double pValue = U[offset + nodeId]; p += pValue * pN[iNode]; px += pValue * pNx[iNode]; py += pValue * pNy[iNode]; } double[][] vu = new double[vDof][]; vu[0] = vx; vu[1] = vy; double[, ][] vuv = new double[vDof, vDof][]; vuv[0, 0] = vxx; vuv[0, 1] = vxy; vuv[1, 0] = vyx; vuv[1, 1] = vyy; double[] pu = new double[vDof]; pu[0] = px; pu[1] = py; for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < vElemNodeCnt; col++) { int colNodeId = vNodes[col]; if (colNodeId == -1) { continue; } double[,] kvv1 = new double[vDof, vDof]; kvv1[0, 0] = detJWeight * mu * (vNx[row] * vNx[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col]; kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col]; kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); double[,] kvv2 = new double[vDof, vDof]; //kvv2[0, 0] = detJWeight * rho * vN[row] * ( // vN[col] * vx[0] + v[0] * vNx[col] + v[1] * vNy[col]); //kvv2[0, 1] = detJWeight * rho * vN[row] * vN[col] * vy[0]; //kvv2[1, 0] = detJWeight * rho * vN[row] * vN[col] * vx[1]; //kvv2[1, 1] = detJWeight * rho * vN[row] * ( // vN[col] * vy[1] + v[0] * vNx[col] + v[1] * vNy[col]); // Picard kvv2[0, 0] = detJWeight * rho * vN[row] * (v[0] * vNx[col] + v[1] * vNy[col]); kvv2[0, 1] = 0; kvv2[1, 0] = 0; kvv2[1, 1] = detJWeight * rho * vN[row] * (v[0] * vNx[col] + v[1] * vNy[col]); for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] += kvv1[rowDof, colDof] + kvv2[rowDof, colDof]; //B[rowNodeId * vDof + rowDof] += // kvv2[rowDof, colDof] * U[colNodeId * vDof + colDof]; // Picard // nothing } } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double[,] kvp = new double[vDof, pDof]; kvp[0, 0] = -detJWeight * vNx[row] * pN[col]; kvp[1, 0] = -detJWeight * vNy[row] * pN[col]; for (int rowDof = 0; rowDof < vDof; rowDof++) { A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0]; A[offset + colNodeId, rowNodeId *vDof + rowDof] += kvp[rowDof, 0]; } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } double[] q2 = new double[vDof]; for (int rowDof = 0; rowDof < vDof; rowDof++) { //q2[rowDof] = detJWeight * rho * vN[row] * (v[0] * vx[rowDof] + v[1] * vy[rowDof]); // Picard // nothing } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += -q2[rowDof]; } } ////////////////////////////////////////////////////////////// // SUPG double[] rmi = new double[vDof]; double[,,] rmivj = new double[vDof, vDof, vElemNodeCnt]; double[,] rmip = new double[vDof, pElemNodeCnt]; double rc = 0; double[,] rcvj = new double[vDof, vElemNodeCnt]; for (int iDof = 0; iDof < vDof; iDof++) { rmi[iDof] = -mu * (vuv[0, 0][iDof] + vuv[1, 1][iDof]) + rho * (v[0] * vx[iDof] + v[1] * vy[iDof]) + pu[iDof] - rho * g[iDof]; for (int jDof = 0; jDof < vDof; jDof++) { for (int jNode = 0; jNode < vElemNodeCnt; jNode++) { int jNodeId = vNodes[jNode]; if (jNodeId == -1) { continue; } rmivj[iDof, jDof, jNode] = 0; if (iDof == jDof) { rmivj[iDof, jDof, jNode] += -mu * (vNuv[0, 0][jNode] + vNuv[1, 1][jNode]); } //rmivj[iDof, jDof, jNode] += // rho * vN[jNode] * vu[jDof][iDof]; // Picard // nothing if (iDof == jDof) { rmivj[iDof, jDof, jNode] += rho * (v[0] * vNu[0][jNode] + v[1] * vNu[1][jNode]); } } } for (int jNode = 0; jNode < pElemNodeCnt; jNode++) { int jNodeId = pNodes[jNode]; if (jNodeId == -1) { continue; } rmip[iDof, jNode] = pNu[iDof][jNode]; } } { rc = vx[0] + vy[1]; for (int jDof = 0; jDof < vDof; jDof++) { for (int jNode = 0; jNode < vElemNodeCnt; jNode++) { int jNodeId = vNodes[jNode]; if (jNodeId == -1) { continue; } rcvj[jDof, jNode] = vNu[jDof][jNode]; } } } // kvv for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < vElemNodeCnt; col++) { int colNodeId = vNodes[col]; if (colNodeId == -1) { continue; } double[,] kvv1 = new double[vDof, vDof]; double[,] kvv1GLSAdd = new double[vDof, vDof]; double[,] kvv2 = new double[vDof, vDof]; for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { // Picard kvv1[rowDof, colDof] = detJWeight * taum * (v[0] * vNu[0][row] + v[1] * vNu[1][row]) * rmivj[rowDof, colDof, col]; kvv2[rowDof, colDof] = detJWeight * tauc * rho * vNu[rowDof][row] * rcvj[colDof, col]; } } // GLS追加項 for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { kvv1GLSAdd[rowDof, colDof] = -detJWeight * (1.0 / rho) * taum * mu * (vNuv[0, 0][row] + vNuv[1, 1][row]) * rmivj[rowDof, colDof, col]; } } for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] += kvv1[rowDof, colDof] + kvv2[rowDof, colDof] + kvv1GLSAdd[rowDof, colDof]; // Picard // nothing } } } } // kvp for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double[,] kvp = new double[vDof, pDof]; double[,] kvpGLSAdd = new double[vDof, pDof]; for (int rowDof = 0; rowDof < vDof; rowDof++) { kvp[rowDof, 0] = detJWeight * taum * (v[0] * vNu[0][row] + v[1] * vNu[1][row]) * rmip[rowDof, col]; } // GLS追加項 for (int rowDof = 0; rowDof < vDof; rowDof++) { kvpGLSAdd[rowDof, 0] = -detJWeight * (1.0 / rho) * taum * mu * (vNuv[0, 0][row] + vNuv[1, 1][row]) * rmip[rowDof, col]; } for (int rowDof = 0; rowDof < vDof; rowDof++) { A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0] + kvpGLSAdd[rowDof, 0]; // Picard // nothing } } } // kpv for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < vElemNodeCnt; col++) { int colNodeId = vNodes[col]; if (colNodeId == -1) { continue; } double[,] kpv = new double[pDof, vDof]; for (int colDof = 0; colDof < vDof; colDof++) { kpv[0, colDof] = -detJWeight * (1.0 / rho) * taum * (pNu[0][row] * rmivj[0, colDof, col] + pNu[1][row] * rmivj[1, colDof, col]); } for (int colDof = 0; colDof < vDof; colDof++) { A[offset + rowNodeId, colNodeId *vDof + colDof] += kpv[0, colDof]; // Picard // nothing } } } // kpp for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double[,] kpp = new double[pDof, pDof]; kpp[0, 0] = -detJWeight * (1.0 / rho) * taum * (pNu[0][row] * rmip[0, col] + pNu[1][row] * rmip[1, col]); A[offset + rowNodeId, offset + colNodeId] += kpp[0, 0]; // Picard // nothing } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } double[] qv1 = new double[vDof]; double[] qv2 = new double[vDof]; for (int rowDof = 0; rowDof < vDof; rowDof++) { // Picard // nothing } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += -(qv1[rowDof] + qv2[rowDof]); } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } double[] qp = new double[pDof]; // Picard // nothing B[offset + rowNodeId] += -qp[0]; } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row]; } } } }
protected void CalcMooneyRivlinHyperelasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint uQuantityId = 0; uint lQuantityId = 1; System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2); System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1); int uDof = 2; int lDof = 1; int uNodeCnt = (int)World.GetNodeCount(uQuantityId); int lNodeCnt = (int)World.GetNodeCount(lQuantityId); //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength); int offset = GetOffset(lQuantityId); System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof); double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var uFV = World.GetFieldValue(UValueId); TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId); TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId); Material ma0 = World.GetMaterial(uTriFE.MaterialId); if (!(ma0 is MooneyRivlinHyperelasticMaterial)) { return; } uint vertexCnt = uTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]); } int[] uCoIds = uTriFE.NodeCoordIds; uint uElemNodeCnt = uTriFE.NodeCount; int[] uNodes = new int[uElemNodeCnt]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int coId = uCoIds[iNode]; int nodeId = World.Coord2Node(uQuantityId, coId); uNodes[iNode] = nodeId; } int[] lCoIds = lTriFE.NodeCoordIds; uint lElemNodeCnt = lTriFE.NodeCount; int[] lNodes = new int[lElemNodeCnt]; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int coId = lCoIds[iNode]; int nodeId = World.Coord2Node(lQuantityId, coId); lNodes[iNode] = nodeId; } var ma = ma0 as MooneyRivlinHyperelasticMaterial; bool isCompressible = ma.IsCompressible; double d1 = ma.D1; double c1 = ma.C1; double c2 = ma.C2; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] uSN = uTriFE.CalcSN(); double[,] uSNN = uTriFE.CalcSNN(); double[,] lSNN = lTriFE.CalcSNN(); System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount); System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount); double[,] qu = new double[uElemNodeCnt, uDof]; double[] ql = new double[lElemNodeCnt]; for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] uN = uTriFE.CalcN(L); double[] lN = lTriFE.CalcN(L); double[][] uNu = uTriFE.CalcNu(L); double detJ = uTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; // 変位の微分 double[,] uu = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int iNodeId = uNodes[iNode]; if (iNodeId == -1) { continue; } uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode]; } } } // ラグランジュの未定乗数 double l = 0; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int iNodeId = lNodes[iNode]; if (iNodeId == -1) { continue; } l += U[offset + iNodeId] * lN[iNode]; } // Green-Lagrangeのひずみ double[,] e = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]); for (int kDof = 0; kDof < uDof; kDof++) { e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof]; } } } // 右Cauchy-Green変形テンソル double[,] c = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof]; for (int kDof = 0; kDof < uDof; kDof++) { c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof]; } } c[iDof, iDof] += 1.0; } // Cのテンソル不変量 double I1 = c[0, 0] + c[1, 1] + 1.0; double I2 = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0]; double I3 = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0]; double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0); double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0); double[,] invC = new double[uDof, uDof]; { double invI3 = 1.0 / I3; invC[0, 0] = invI3 * c[1, 1]; invC[0, 1] = -invI3 * c[0, 1]; invC[1, 0] = -invI3 * c[1, 0]; invC[1, 1] = invI3 * c[0, 0]; } // 第2Piola-Kirchhoff応力 double[,] s = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { s[iDof, jDof] -= 2.0 * c2 * inv23I3 * c[iDof, jDof] + (2.0 / 3.0) * (c1 * I1 * inv13I3 + c2 * 2.0 * I2 * inv23I3) * invC[iDof, jDof]; } } { double tmp = 2.0 * c1 * inv13I3 + 2.0 * c2 * inv23I3 * I1; for (int iDof = 0; iDof < uDof; iDof++) { s[iDof, iDof] += tmp; } } // Lagrangeの未定乗数の寄与項 { double tmp = 2.0 * l * I3; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { s[iDof, jDof] += tmp * invC[iDof, jDof]; } } } // 構成則テンソル double[,,,] c4 = new double[uDof, uDof, uDof, uDof]; // 圧力構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { c4[gDof, hDof, eDof, fDof] += 4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] - 2.0 * l * I3 * ( invC[gDof, eDof] * invC[fDof, hDof] + invC[gDof, fDof] * invC[eDof, hDof]); } } } } // 変位構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { c4[gDof, hDof, eDof, fDof] += 4.0 * c1 * inv13I3 / 3.0 * ( invC[gDof, hDof] * invC[eDof, fDof] * I1 / 3.0 + invC[gDof, eDof] * invC[fDof, hDof] * I1 / 2.0 + invC[gDof, fDof] * invC[eDof, hDof] * I1 / 2.0) + 4.0 * c2 * inv23I3 * 2.0 / 3.0 * ( invC[gDof, hDof] * invC[eDof, fDof] * I2 * (2.0 / 3.0) + c[gDof, hDof] * invC[eDof, fDof] + invC[gDof, hDof] * c[eDof, fDof] + invC[gDof, eDof] * invC[fDof, hDof] * I2 / 2.0 + invC[gDof, fDof] * invC[eDof, hDof] * I2 / 2.0); } } double tmp = 4.0 * c1 * inv13I3 / 3.0 * invC[gDof, hDof] + 4.0 * c2 * inv23I3 * I1 * (2.0 / 3.0) * invC[gDof, hDof]; for (int eDof = 0; eDof < uDof; eDof++) { c4[gDof, hDof, eDof, eDof] -= tmp; c4[eDof, eDof, gDof, hDof] -= tmp; } c4[gDof, gDof, hDof, hDof] += 4.0 * c2 * inv23I3; c4[gDof, hDof, hDof, gDof] -= 2.0 * c2 * inv23I3; c4[gDof, hDof, gDof, hDof] -= 2.0 * c2 * inv23I3; } } double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof]; { double[,] f = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { f[iDof, jDof] = uu[iDof, jDof]; } f[iDof, iDof] += 1.0; } for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof]; } } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < uElemNodeCnt; col++) { int colNodeId = uNodes[col]; if (colNodeId == -1) { continue; } double[,] kuu = new double[uDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { double tmp1 = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { tmp1 += c4[gDof, hDof, eDof, fDof] * b[row, rowDof, eDof, fDof] * b[col, colDof, gDof, hDof]; } } } } kuu[rowDof, colDof] += detJWeight * tmp1; } } { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col]; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { kuu[rowDof, rowDof] += detJWeight * tmp; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] += kuu[rowDof, colDof]; B[rowNodeId * uDof + rowDof] += kuu[rowDof, colDof] * U[colNodeId * uDof + colDof]; } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < lElemNodeCnt; col++) { int colNodeId = lNodes[col]; if (colNodeId == -1) { continue; } double[,] kul = new double[uDof, lDof]; double[,] klu = new double[lDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof]; } } kul[rowDof, 0] += detJWeight * tmp * 2.0 * lN[col] * I3; klu[0, rowDof] += detJWeight * tmp * 2.0 * lN[col] * I3; } for (int rowDof = 0; rowDof < uDof; rowDof++) { A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0]; A[offset + colNodeId, rowNodeId *uDof + rowDof] += klu[0, rowDof]; B[rowNodeId * uDof + rowDof] += kul[rowDof, 0] * U[offset + colNodeId]; B[offset + colNodeId] += klu[0, rowDof] * U[rowNodeId * uDof + rowDof]; } } } // Note: kllは数値積分しなくて求められる for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof]; } } } } for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { if (isCompressible) { ql[iNode] += detJWeight * lN[iNode] * ((I3 - 1) - l / d1); } else { ql[iNode] += detJWeight * lN[iNode] * (I3 - 1); } } } if (isCompressible) { for (int row = 0; row < lElemNodeCnt; row++) { int rowNodeId = lNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < lElemNodeCnt; col++) { int colNodeId = lNodes[col]; if (colNodeId == -1) { continue; } double kll = -(1.0 / d1) * lSNN[row, col]; A[offset + rowNodeId, offset + colNodeId] += kll; B[offset + rowNodeId] += kll * U[offset + colNodeId]; } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < uElemNodeCnt; col++) { int colNodeId = uNodes[col]; if (colNodeId == -1) { continue; } int colCoId = uCoIds[col]; double[] u = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] velU = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] accU = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double[,] m = new double[2, 2]; m[0, 0] = rho * uSNN[row, col]; m[1, 0] = 0.0; m[0, 1] = 0.0; m[1, 1] = rho * uSNN[row, col]; for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] += (1.0 / (beta * dt * dt)) * m[rowDof, colDof]; B[rowNodeId * uDof + rowDof] += m[rowDof, colDof] * ( (1.0 / (beta * dt * dt)) * u[colDof] + (1.0 / (beta * dt)) * velU[colDof] + (1.0 / (2.0 * beta) - 1.0) * accU[colDof]); } } } } double[,] fg = new double[uElemNodeCnt, uDof]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { fg[iNode, iDof] = rho * g[iDof] * uSN[iNode]; } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < uDof; rowDof++) { B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof]; } } for (int row = 0; row < lElemNodeCnt; row++) { int rowNodeId = lNodes[row]; if (rowNodeId == -1) { continue; } B[offset + rowNodeId] += -ql[row]; } }
private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; var veloFV = World.GetFieldValue(VeloValueId); IList <uint> feIds = World.GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(quantityId, feId); uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = triFE.NodeCoordIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(triFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is DiffusionMaterial); var ma = ma0 as DiffusionMaterial; double nu = ma.DiffusionCoef; double f = ma.F; double[][] velos = new double[elemNodeCnt][]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int nodeId = nodes[iNode]; if (nodeId == -1) { continue; } int coId = World.Node2Coord(quantityId, nodeId); double[] velo = veloFV.GetDoubleValue(coId, FieldDerivativeType.Value); velos[iNode] = velo; } double tau; { double[] aveVelo = { (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0, (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0 }; double veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]); double[] veloDir = { aveVelo[0] / veloNorm, aveVelo[1] / veloNorm }; double h; { double[] L = new double[] { 1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0 }; double[][] Nu = triFE.CalcNu(L); double[] Nx = Nu[0]; double[] Ny = Nu[1]; double tmp = 0; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { tmp += Math.Abs(veloDir[0] * Nx[iNode] + veloDir[1] * Ny[iNode]); } h = 2.0 / tmp; } double lambda = (1.0 / 2.0) * veloNorm * h / nu; //tau = (1.0 / 2.0) * (h / veloNorm) * (1.0 / Math.Tanh(lambda) - 1.0 / lambda); if (nu > 1.0e-20) { if (lambda < 3.0) { tau = (1.0 / 2.0) * h / veloNorm * lambda / 3.0; } else { tau = (1.0 / 2.0) * h / veloNorm; } } else { tau = (1.0 / 2.0) * h / veloNorm; } } double[] sN = triFE.CalcSN(); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] N = triFE.CalcN(L); double[][] Nu = triFE.CalcNu(L); double[] Nx = Nu[0]; double[] Ny = Nu[1]; double detJ = triFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double[] velo = new double[2]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { for (int iDof = 0; iDof < 2; iDof++) { velo[iDof] += N[iNode] * velos[iNode][iDof]; } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } double k = detJWeight * nu * (Nx[row] * Nx[col] + Ny[row] * Ny[col]); double c = detJWeight * (N[row] + tau * (velo[0] * Nx[row] + velo[1] * Ny[row])) * (velo[0] * Nx[col] + velo[1] * Ny[col]); A[rowNodeId, colNodeId] += k + c; } } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } B[rowNodeId] += f * sN[row]; } } }
/* * // Taylor級数展開 3次までの項を考慮 * protected void SetVorticityDirichletBCOfVorticityForTangentFlow(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) * { * uint wQuantityId = 0; * uint pQuantityId = 1; * int wNodeCnt = (int)World.GetNodeCount(wQuantityId); * int pNodeCnt = (int)World.GetNodeCount(pQuantityId); * int offset = wNodeCnt; * * if (World.GetPortCount(wQuantityId) == 0) * { * return; * } * uint portCnt = World.GetPortCount(wQuantityId); * IList<PortCondition> portConditions = World.GetPortConditions(wQuantityId); * IList<uint> feIds = World.GetLineFEIds(wQuantityId); * for (int portId = 0; portId < portCnt; portId++) * { * PortCondition portCondition = portConditions[portId]; * //IList<int> intParam = portCondition.IntAdditionalParameters; * //System.Diagnostics.Debug.Assert(intParam.Count == 0); * IList<uint> bcEIds = portCondition.EIds; * IList<double> param = portCondition.DoubleAdditionalParameters; * System.Diagnostics.Debug.Assert(param.Count == 2); // 0: dψ/dx 1: dψ/dy * double pxValue = param[0]; * double pyValue = param[1]; * * foreach (uint feId in feIds) * { * LineFE lineFE = World.GetLineFE(wQuantityId, feId); * uint meshId = lineFE.MeshId; * //int meshElemId = lineFE.MeshElemId; * uint eId; * { * uint elemCount; * MeshType meshType; * int loc; * uint cadId; * World.Mesh.GetMeshInfo(meshId, out elemCount, out meshType, out loc, out cadId); * System.Diagnostics.Debug.Assert(meshType == MeshType.Bar); * eId = cadId; * } * if (bcEIds.Contains(eId)) * { * // BCを適用する辺 * } * else * { * continue; * } * * // BC * uint elemNodeCnt = lineFE.NodeCount; * int[] wCoIds = lineFE.NodeCoordIds; * int[] wNodes = new int[elemNodeCnt]; * int[] pNodes = new int[elemNodeCnt]; * for (int iNode = 0; iNode < elemNodeCnt; iNode++) * { * int coId = wCoIds[iNode]; * wNodes[iNode] = World.Coord2Node(wQuantityId, coId); * pNodes[iNode] = World.Coord2Node(pQuantityId, coId); * } * * Material ma0 = World.GetMaterial(lineFE.MaterialId); * System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); * var ma = ma0 as NewtonFluidMaterial; * double rho = ma.MassDensity; * double mu = ma.Mu; * double[] g = { ma.GravityX, ma.GravityY }; * * double[] normal = lineFE.GetNormal(); * * int coId1 = wCoIds[0]; * int coId2 = wCoIds[1]; * int adjCoId = -1; // adjacent * { * IList<uint> triFEIds = World.GetTriangleFEIdsFromEdgeCoord(wQuantityId, coId1, coId2); * uint triFEId = triFEIds[0]; * TriangleFE triFE = World.GetTriangleFE(wQuantityId, triFEId); * int[] triFECoIds = triFE.NodeCoordIds; * foreach (int coId in triFECoIds) * { * if (coId != coId1 && coId != coId2) * { * adjCoId = coId; * break; * } * } * System.Diagnostics.Debug.Assert(adjCoId != -1); * } * int wAdjNodeId = -1; * wAdjNodeId = World.Coord2Node(wQuantityId, adjCoId); // 特殊な場合-1はありえる * int pAdjNodeId = -1; * pAdjNodeId = World.Coord2Node(pQuantityId, adjCoId); // 特殊な場合-1はありえる * double[] pt1 = World.GetCoord(wQuantityId, coId1); * double[] pt2 = World.GetCoord(wQuantityId, coId2); * double[] adjPt = World.GetCoord(wQuantityId, adjCoId); * double hn = IvyFEM.CadUtils.TriHeight( * new OpenTK.Vector2d(adjPt[0], adjPt[1]), // 点 * new OpenTK.Vector2d(pt1[0], pt1[1]), // 辺の点1 * new OpenTK.Vector2d(pt2[0], pt2[1]) // 辺の点2 * ); * * for (int row = 0; row < elemNodeCnt; row++) * { * int rowCoId = wCoIds[row]; * int rowNodeId = wNodes[row]; * if (rowNodeId == -1) * { * continue; * } * for (int colNodeId = 0; colNodeId < wNodeCnt; colNodeId++) * { * int colCoId = World.Node2Coord(wQuantityId, colNodeId); * if (colCoId == rowCoId) * { * A[rowNodeId, colNodeId] = 1.0; * } * else if (wAdjNodeId != -1 && colNodeId == wAdjNodeId) * { * A[rowNodeId, colNodeId] = -1.0 / 2.0; * } * else * { * A[rowNodeId, colNodeId] = 0; * } * } * for (int colNodeId = 0; colNodeId < pNodeCnt; colNodeId++) * { * int colCoId = World.Node2Coord(pQuantityId, colNodeId); * if (colCoId == rowCoId) * { * A[rowNodeId, offset + colNodeId] = -3.0 / (hn * hn); * } * else if (pAdjNodeId != -1 && colNodeId == pAdjNodeId) * { * A[rowNodeId, offset + colNodeId] = 3.0 / (hn * hn); * } * else * { * A[rowNodeId, offset + colNodeId] = 0; * } * } * B[rowNodeId] = -(normal[0] * pxValue + normal[1] * pyValue) * (3.0 / hn); * } * } * } * } */ /* * // Taylor級数展開 3次までの項を考慮 境界積分評価 * protected void SetVorticityDirichletBCOfVorticityForTangentFlow(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) * { * uint wQuantityId = 0; * uint pQuantityId = 1; * int wNodeCnt = (int)World.GetNodeCount(wQuantityId); * int pNodeCnt = (int)World.GetNodeCount(pQuantityId); * int offset = wNodeCnt; * * if (World.GetPortCount(wQuantityId) == 0) * { * return; * } * uint portCnt = World.GetPortCount(wQuantityId); * IList<PortCondition> portConditions = World.GetPortConditions(wQuantityId); * IList<uint> feIds = World.GetLineFEIds(wQuantityId); * for (int portId = 0; portId < portCnt; portId++) * { * PortCondition portCondition = portConditions[portId]; * //IList<int> intParam = portCondition.IntAdditionalParameters; * //System.Diagnostics.Debug.Assert(intParam.Count == 0); * IList<uint> bcEIds = portCondition.EIds; * IList<double> param = portCondition.DoubleAdditionalParameters; * System.Diagnostics.Debug.Assert(param.Count == 2); // 0: dψ/dx 1: dψ/dy * double pxValue = param[0]; * double pyValue = param[1]; * * foreach (uint feId in feIds) * { * LineFE lineFE = World.GetLineFE(wQuantityId, feId); * uint meshId = lineFE.MeshId; * //int meshElemId = lineFE.MeshElemId; * uint eId; * { * uint elemCount; * MeshType meshType; * int loc; * uint cadId; * World.Mesh.GetMeshInfo(meshId, out elemCount, out meshType, out loc, out cadId); * System.Diagnostics.Debug.Assert(meshType == MeshType.Bar); * eId = cadId; * } * if (bcEIds.Contains(eId)) * { * // BCを適用する辺 * } * else * { * continue; * } * * // BC * uint elemNodeCnt = lineFE.NodeCount; * int[] wCoIds = lineFE.NodeCoordIds; * int[] wNodes = new int[elemNodeCnt]; * int[] pNodes = new int[elemNodeCnt]; * for (int iNode = 0; iNode < elemNodeCnt; iNode++) * { * int coId = wCoIds[iNode]; * wNodes[iNode] = World.Coord2Node(wQuantityId, coId); * pNodes[iNode] = World.Coord2Node(pQuantityId, coId); * } * * Material ma0 = World.GetMaterial(lineFE.MaterialId); * System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); * var ma = ma0 as NewtonFluidMaterial; * double rho = ma.MassDensity; * double mu = ma.Mu; * double[] g = { ma.GravityX, ma.GravityY }; * * double[] normal = lineFE.GetNormal(); * double[] sN = lineFE.CalcSN(); * * int coId1 = wCoIds[0]; * int coId2 = wCoIds[1]; * int adjCoId = -1; // adjacent * { * IList<uint> triFEIds = World.GetTriangleFEIdsFromEdgeCoord(wQuantityId, coId1, coId2); * uint triFEId = triFEIds[0]; * TriangleFE triFE = World.GetTriangleFE(wQuantityId, triFEId); * int[] triFECoIds = triFE.NodeCoordIds; * foreach (int coId in triFECoIds) * { * if (coId != coId1 && coId != coId2) * { * adjCoId = coId; * break; * } * } * System.Diagnostics.Debug.Assert(adjCoId != -1); * } * int wAdjNodeId = -1; * wAdjNodeId = World.Coord2Node(wQuantityId, adjCoId); // 特殊な場合-1はありえる * int pAdjNodeId = -1; * pAdjNodeId = World.Coord2Node(pQuantityId, adjCoId); // 特殊な場合-1はありえる * double[] pt1 = World.GetCoord(wQuantityId, coId1); * double[] pt2 = World.GetCoord(wQuantityId, coId2); * double[] adjPt = World.GetCoord(wQuantityId, adjCoId); * double hn = IvyFEM.CadUtils.TriHeight( * new OpenTK.Vector2d(adjPt[0], adjPt[1]), // 点 * new OpenTK.Vector2d(pt1[0], pt1[1]), // 辺の点1 * new OpenTK.Vector2d(pt2[0], pt2[1]) // 辺の点2 * ); * * for (int row = 0; row < elemNodeCnt; row++) * { * int rowCoId = wCoIds[row]; * int rowNodeId = wNodes[row]; * if (rowNodeId == -1) * { * continue; * } * for (int colNodeId = 0; colNodeId < wNodeCnt; colNodeId++) * { * int colCoId = World.Node2Coord(wQuantityId, colNodeId); * if (colCoId == rowCoId) * { * A[rowNodeId, colNodeId] += -mu * (3.0 / hn) * sN[row]; * } * } * for (int colNodeId = 0; colNodeId < pNodeCnt; colNodeId++) * { * int colCoId = World.Node2Coord(pQuantityId, colNodeId); * if (colCoId == rowCoId) * { * A[rowNodeId, offset + colNodeId] += mu * (6.0 / (hn * hn * hn)) * sN[row]; * } * else if (pAdjNodeId != -1 && colNodeId == pAdjNodeId) * { * A[rowNodeId, offset + colNodeId] += -mu * (6.0 / (hn * hn * hn)) * sN[row]; * } * } * B[rowNodeId] += mu * (normal[0] * pxValue + normal[1] * pyValue) * (6.0 / (hn * hn)) * sN[row]; * } * } * } * } */ protected void GetVelocityFromVorticityStream() { uint wQuantityId = 0; uint pQuantityId = 1; int wNodeCnt = (int)World.GetNodeCount(wQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = wNodeCnt; int wCoCnt = (int)World.GetCoordCount(wQuantityId); int pCoCnt = (int)World.GetCoordCount(pQuantityId); int vDof = 2; CoordV = new double[pCoCnt * vDof]; // nodeでなくcoord IList <uint> feIds = World.GetTriangleFEIds(pQuantityId); foreach (uint feId in feIds) { TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(pTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double[] g = { ma.GravityX, ma.GravityY }; for (int row = 0; row < pElemNodeCnt; row++) { int rowCoId = pCoIds[row]; double[] L = pTriFE.GetNodeL(row); double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double p = 0; double px = 0; double py = 0; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int nodeId = pNodes[iNode]; if (nodeId == -1) { continue; } double pValue = U[offset + nodeId]; p += pValue * pN[iNode]; px += pValue * pNx[iNode]; py += pValue * pNy[iNode]; } double[] v = new double[2]; v[0] = py; v[1] = -px; for (int rowDof = 0; rowDof < vDof; rowDof++) { CoordV[rowCoId * vDof + rowDof] = v[rowDof]; } } } }
public TriangleFE(TriangleFE src) { Copy(src); }
protected void CalcLinearElasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; int nodeCnt = (int)World.GetNodeCount(quantityId); System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2); int dof = 2; TriangleFE triFE = World.GetTriangleFE(quantityId, feId); Material ma0 = World.GetMaterial(triFE.MaterialId); if (!(ma0 is LinearElasticMaterial)) { return; } int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } var ma = ma0 as LinearElasticMaterial; double lambda = ma.LameLambda; double mu = ma.LameMu; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] sN = triFE.CalcSN(); double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } double[,] k = new double[dof, dof]; double[,] m = new double[dof, dof]; k[0, 0] = (lambda + mu) * sNxNx[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]); k[1, 0] = lambda * sNyNx[row, col] + mu * sNxNy[row, col]; k[0, 1] = lambda * sNxNy[row, col] + mu * sNyNx[row, col]; k[1, 1] = (lambda + mu) * sNyNy[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]); for (int rowDof = 0; rowDof < dof; rowDof++) { for (int colDof = 0; colDof < dof; colDof++) { A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] += k[rowDof, colDof]; } } } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < dof; rowDof++) { B[rowNodeId * dof + rowDof] += rho * g[rowDof] * sN[row]; } } }
// 境界が流線方向と同じとき // ψの法線成分(速度の接線成分に比例)がある // ψ = 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 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); } } }
protected void CalcOgdenHyperelasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint uQuantityId = 0; uint lQuantityId = 1; System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2); System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1); int uDof = 2; int lDof = 1; int uNodeCnt = (int)World.GetNodeCount(uQuantityId); int lNodeCnt = (int)World.GetNodeCount(lQuantityId); //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength); int offset = GetOffset(lQuantityId); System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof); TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId); TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId); Material ma0 = World.GetMaterial(uTriFE.MaterialId); if (!(ma0 is OgdenHyperelasticMaterial)) { return; } uint vertexCnt = uTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]); } int[] uCoIds = uTriFE.NodeCoordIds; uint uElemNodeCnt = uTriFE.NodeCount; int[] uNodes = new int[uElemNodeCnt]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int coId = uCoIds[iNode]; int nodeId = World.Coord2Node(uQuantityId, coId); uNodes[iNode] = nodeId; } int[] lCoIds = lTriFE.NodeCoordIds; uint lElemNodeCnt = lTriFE.NodeCount; int[] lNodes = new int[lElemNodeCnt]; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int coId = lCoIds[iNode]; int nodeId = World.Coord2Node(lQuantityId, coId); lNodes[iNode] = nodeId; } var ma = ma0 as OgdenHyperelasticMaterial; bool isCompressible = ma.IsCompressible; double d1 = ma.D1; int oOrder = ma.Order; double[] oMus = ma.Mus; double[] oAlphas = ma.Alphas; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] uSN = uTriFE.CalcSN(); double[,] lSNN = lTriFE.CalcSNN(); System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount); System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount); double[,] qu = new double[uElemNodeCnt, uDof]; double[] ql = new double[lElemNodeCnt]; for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] uN = uTriFE.CalcN(L); double[] lN = lTriFE.CalcN(L); double[][] uNu = uTriFE.CalcNu(L); double detJ = uTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; // 変位の微分 double[,] uu = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int iNodeId = uNodes[iNode]; if (iNodeId == -1) { continue; } uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode]; } } } // ラグランジュの未定乗数 double l = 0; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int iNodeId = lNodes[iNode]; if (iNodeId == -1) { continue; } l += U[offset + iNodeId] * lN[iNode]; } // Green-Lagrangeのひずみ double[,] e = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]); for (int kDof = 0; kDof < uDof; kDof++) { e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof]; } } } // 変形勾配テンソル double[,] f = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { f[iDof, jDof] = uu[iDof, jDof]; } f[iDof, iDof] += 1.0; } // 右Cauchy-Green変形テンソル double[,] c = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof]; for (int kDof = 0; kDof < uDof; kDof++) { c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof]; } } c[iDof, iDof] += 1.0; } // Cのテンソル不変量 double I1 = c[0, 0] + c[1, 1] + 1.0; double I2 = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0]; double I3 = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0]; double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0); double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0); double[,] invC = new double[uDof, uDof]; { double invI3 = 1.0 / I3; invC[0, 0] = invI3 * c[1, 1]; invC[0, 1] = -invI3 * c[0, 1]; invC[1, 0] = -invI3 * c[1, 0]; invC[1, 1] = invI3 * c[0, 0]; } // Cの主値の1/2乗と主軸 // Note: これらは3次元 int dim3 = 3; System.Numerics.Complex[] fLambdas; System.Numerics.Complex[][] cNormals; SolvePrincipalValues(c, out fLambdas, out cNormals); double inv16I3 = 1.0 / Math.Pow(I3, 1.0 / 6.0); // 修正Cの主値 System.Numerics.Complex[] barFLambdas = fLambdas.Select(a => a * inv16I3).ToArray(); // 主第2Piola-Kirchhoff応力 System.Numerics.Complex[] principalS = new System.Numerics.Complex[uDof]; /* * for (int kDof = 0; kDof < uDof; kDof++) * { * for (int r = 0; r < oOrder; r++) * { * double mu = oMus[r]; * double alpha = oAlphas[r]; * principalS[kDof] += (mu / (fLambdas[kDof] * fLambdas[kDof])) * ( * System.Numerics.Complex.Pow(barFLambdas[kDof], alpha) - * (1.0 / 3.0) * ( * System.Numerics.Complex.Pow(barFLambdas[0], alpha) + * System.Numerics.Complex.Pow(barFLambdas[1], alpha) + * System.Numerics.Complex.Pow(barFLambdas[2], alpha) * )); * } * } */ for (int kDof = 0; kDof < uDof; kDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; principalS[kDof] += (mu / (fLambdas[kDof] * fLambdas[kDof])) * ( System.Numerics.Complex.Pow(barFLambdas[kDof], alpha) - (1.0 / 3.0) * ( System.Numerics.Complex.Pow(barFLambdas[0], alpha) + System.Numerics.Complex.Pow(barFLambdas[1], alpha) + Math.Pow(I3, -alpha / 6.0) )); } } // 第2Piola-Kirchhoff応力 double[,] s = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { for (int kDof = 0; kDof < uDof; kDof++) { System.Numerics.Complex sij = principalS[kDof] * cNormals[kDof][iDof] * cNormals[kDof][jDof]; s[iDof, jDof] += sij.Real; //System.Diagnostics.Debug.Assert( // Math.Abs(sij.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit); } } } // Lagrangeの未定乗数の寄与項 { double tmp = 2.0 * l * I3; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { s[iDof, jDof] += tmp * invC[iDof, jDof]; } } } // 主軸構成則テンソル(オリジナルの方) System.Numerics.Complex[,] principalC21st = new System.Numerics.Complex[uDof, uDof]; System.Numerics.Complex[,] principalC22nd = new System.Numerics.Complex[uDof, uDof]; /* * for (int pDof = 0; pDof < uDof; pDof++) * { * for (int qDof = 0; qDof < uDof; qDof++) * { * for (int r = 0; r < oOrder; r++) * { * double mu = oMus[r]; * double alpha = oAlphas[r]; * System.Numerics.Complex tmp1 = 0; * if (pDof == qDof) * { * tmp1 = -2.0 * ( * System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) - * (1.0 / 3.0) * ( * System.Numerics.Complex.Pow(barFLambdas[0], alpha) + * System.Numerics.Complex.Pow(barFLambdas[1], alpha) + * System.Numerics.Complex.Pow(barFLambdas[2], alpha) * )); * } * System.Numerics.Complex tmp2 = 0; * for (int mDof = 0; mDof < dim3; mDof++) * { * double dmp = mDof == pDof ? 1 : 0; * double dmq = mDof == qDof ? 1 : 0; * tmp2 += alpha * * System.Numerics.Complex.Pow(barFLambdas[mDof], alpha) * * (dmp - 1.0 / 3.0) * * (dmq - 1.0 / 3.0); * } * principalC21st[pDof, qDof] += * (mu / (fLambdas[pDof] * fLambdas[pDof] * fLambdas[qDof] * fLambdas[qDof])) * * (tmp1 + tmp2); * } * } * } * for (int pDof = 0; pDof < uDof; pDof++) * { * for (int qDof = 0; qDof < uDof; qDof++) * { * for (int r = 0; r < oOrder; r++) * { * double mu = oMus[r]; * double alpha = oAlphas[r]; * System.Numerics.Complex tmp = 0; * if (pDof != qDof) * { * System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof]; * if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit) * { * // λp != λq * System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof]; * System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof]; * tmp = (mu / (squareFLambdaP * squareFLambdaQ)) * ( * ( * squareFLambdaQ * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) - * squareFLambdaP * System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) * ) / (squareFLambdaP - squareFLambdaQ) + * (1.0 / 3.0) * * ( * System.Numerics.Complex.Pow(barFLambdas[0], alpha) + * System.Numerics.Complex.Pow(barFLambdas[1], alpha) + * System.Numerics.Complex.Pow(barFLambdas[2], alpha) * )); * } * else * { * // λp == λq * tmp = (mu / * (fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof])) * ( * -((2.0 - alpha) / 2.0) * * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) + * (1.0 / 3.0) * ( * System.Numerics.Complex.Pow(barFLambdas[0], alpha) + * System.Numerics.Complex.Pow(barFLambdas[1], alpha) + * System.Numerics.Complex.Pow(barFLambdas[2], alpha) * )); * } * principalC22nd[pDof, qDof] += tmp; * } * } * } * } */ uint dim2 = 2; for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; System.Numerics.Complex tmp1 = 0; if (pDof == qDof) { tmp1 = -2.0 * ( System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) - (1.0 / 3.0) * ( System.Numerics.Complex.Pow(barFLambdas[0], alpha) + System.Numerics.Complex.Pow(barFLambdas[1], alpha) + Math.Pow(I3, -alpha / 6.0) )); } System.Numerics.Complex tmp2 = 0; for (int mDof = 0; mDof < dim2; mDof++) { double dmp = mDof == pDof ? 1 : 0; double dmq = mDof == qDof ? 1 : 0; tmp2 += alpha * System.Numerics.Complex.Pow(barFLambdas[mDof], alpha) * (dmp - 1.0 / 3.0) * (dmq - 1.0 / 3.0); } tmp2 += (alpha / 9.0) * Math.Pow(I3, -alpha / 6.0); principalC21st[pDof, qDof] += (mu / (fLambdas[pDof] * fLambdas[pDof] * fLambdas[qDof] * fLambdas[qDof])) * (tmp1 + tmp2); } } } for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; if (pDof != qDof) { System.Numerics.Complex tmp = 0; System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof]; if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit) { // λp != λq System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof]; System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof]; tmp = (mu / (squareFLambdaP * squareFLambdaQ)) * ( ( squareFLambdaQ * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) - squareFLambdaP * System.Numerics.Complex.Pow(barFLambdas[qDof], alpha) ) / (squareFLambdaP - squareFLambdaQ) + (1.0 / 3.0) * ( System.Numerics.Complex.Pow(barFLambdas[0], alpha) + System.Numerics.Complex.Pow(barFLambdas[1], alpha) + System.Numerics.Complex.Pow(I3, -alpha / 6.0) )); } else { // λp == λq tmp = (mu / (fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof] * fLambdas[pDof])) * ( -((2.0 - alpha) / 2.0) * System.Numerics.Complex.Pow(barFLambdas[pDof], alpha) + (1.0 / 3.0) * ( System.Numerics.Complex.Pow(barFLambdas[0], alpha) + System.Numerics.Complex.Pow(barFLambdas[1], alpha) + System.Numerics.Complex.Pow(I3, -alpha / 6.0) )); } principalC22nd[pDof, qDof] += tmp; } } } } // 構成則テンソル(オリジナルの方) double[,,,] c4 = new double[uDof, uDof, uDof, uDof]; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { System.Numerics.Complex c4ghef = principalC21st[pDof, qDof] * cNormals[pDof][gDof] * cNormals[pDof][hDof] * cNormals[qDof][eDof] * cNormals[qDof][fDof] + principalC22nd[pDof, qDof] * cNormals[pDof][gDof] * cNormals[qDof][hDof] * ( cNormals[pDof][eDof] * cNormals[qDof][fDof] + cNormals[qDof][eDof] * cNormals[pDof][fDof] ); c4[gDof, hDof, eDof, fDof] += c4ghef.Real; //System.Diagnostics.Debug.Assert( // Math.Abs(c4ghef.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit); } } } } } } // 構成則テンソル double[,,,] barC4 = new double[uDof, uDof, uDof, uDof]; // 圧力構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { barC4[gDof, hDof, eDof, fDof] += 4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] - 2.0 * l * I3 * ( invC[gDof, eDof] * invC[fDof, hDof] + invC[gDof, fDof] * invC[eDof, hDof]); } } } } // 変位構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { barC4[gDof, hDof, eDof, fDof] += (1.0 / 2.0) * (c4[gDof, hDof, eDof, fDof] + c4[gDof, hDof, fDof, eDof]); } } } } double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof]; { for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof]; } } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < uElemNodeCnt; col++) { int colNodeId = uNodes[col]; if (colNodeId == -1) { continue; } double[,] kuu = new double[uDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { double tmp1 = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { tmp1 += barC4[gDof, hDof, eDof, fDof] * b[row, rowDof, eDof, fDof] * b[col, colDof, gDof, hDof]; } } } } kuu[rowDof, colDof] += detJWeight * tmp1; } } { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col]; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { kuu[rowDof, rowDof] += detJWeight * tmp; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] += kuu[rowDof, colDof]; B[rowNodeId * uDof + rowDof] += kuu[rowDof, colDof] * U[colNodeId * uDof + colDof]; } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < lElemNodeCnt; col++) { int colNodeId = lNodes[col]; if (colNodeId == -1) { continue; } double[,] kul = new double[uDof, lDof]; double[,] klu = new double[lDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof]; } } kul[rowDof, 0] += detJWeight * tmp * 2.0 * lN[col] * I3; klu[0, rowDof] += detJWeight * tmp * 2.0 * lN[col] * I3; } for (int rowDof = 0; rowDof < uDof; rowDof++) { A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0]; A[offset + colNodeId, rowNodeId *uDof + rowDof] += klu[0, rowDof]; B[rowNodeId * uDof + rowDof] += kul[rowDof, 0] * U[offset + colNodeId]; B[offset + colNodeId] += klu[0, rowDof] * U[rowNodeId * uDof + rowDof]; } } } // Note: kllは数値積分しなくて求められる for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof]; } } } } for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { if (isCompressible) { ql[iNode] += detJWeight * lN[iNode] * ((I3 - 1) - l / d1); } else { ql[iNode] += detJWeight * lN[iNode] * (I3 - 1); } } } if (isCompressible) { for (int row = 0; row < lElemNodeCnt; row++) { int rowNodeId = lNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < lElemNodeCnt; col++) { int colNodeId = lNodes[col]; if (colNodeId == -1) { continue; } double kll = -(1.0 / d1) * lSNN[row, col]; A[offset + rowNodeId, offset + colNodeId] += kll; B[offset + rowNodeId] += kll * U[offset + colNodeId]; } } } double[,] fg = new double[uElemNodeCnt, uDof]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { fg[iNode, iDof] = rho * g[iDof] * uSN[iNode]; } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < uDof; rowDof++) { B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof]; } } for (int row = 0; row < lElemNodeCnt; row++) { int rowNodeId = lNodes[row]; if (rowNodeId == -1) { continue; } B[offset + rowNodeId] += -ql[row]; } }
public IList <LineFE> MakeBoundOfElements(FEWorld world) { IList <LineFE> boundOfTriangelFEs = new List <LineFE>(); HashSet <string> edges = new HashSet <string>(); var feIds = GetTriangleFEIds(); foreach (uint feId in feIds) { TriangleFE triFE = GetTriangleFE(feId); System.Diagnostics.Debug.Assert(triFE.Order == FEOrder); int[][] vertexCoIds = { new int[] { triFE.VertexCoordIds[0], triFE.VertexCoordIds[1] }, new int[] { triFE.VertexCoordIds[1], triFE.VertexCoordIds[2] }, new int[] { triFE.VertexCoordIds[2], triFE.VertexCoordIds[0] } }; int[][] nodeCoIds = null; if (triFE.Order == 1) { int[][] nodeCoIds1 = { new int[] { triFE.NodeCoordIds[0], triFE.NodeCoordIds[1] }, new int[] { triFE.NodeCoordIds[1], triFE.NodeCoordIds[2] }, new int[] { triFE.NodeCoordIds[2], triFE.NodeCoordIds[0] } }; nodeCoIds = nodeCoIds1; } else if (triFE.Order == 2) { int[][] nodeCoIds2 = { new int[] { triFE.NodeCoordIds[0], triFE.NodeCoordIds[1], triFE.NodeCoordIds[3] }, new int[] { triFE.NodeCoordIds[1], triFE.NodeCoordIds[2], triFE.NodeCoordIds[4] }, new int[] { triFE.NodeCoordIds[2], triFE.NodeCoordIds[0], triFE.NodeCoordIds[5] } }; nodeCoIds = nodeCoIds2; } else { System.Diagnostics.Debug.Assert(false); } for (int iEdge = 0; iEdge < 3; iEdge++) { int v1 = vertexCoIds[iEdge][0]; int v2 = vertexCoIds[iEdge][1]; if (v1 > v2) { int tmp = v1; v1 = v2; v2 = tmp; } string edgeKey = v1 + "_" + v2; if (edges.Contains(edgeKey)) { continue; } else { edges.Add(edgeKey); } var lineFE = new LineFE((int)FEOrder); lineFE.World = world; lineFE.SetVertexCoordIds(vertexCoIds[iEdge]); lineFE.SetNodeCoordIds(nodeCoIds[iEdge]); // MeshId等は対応するものがないのでセットしない boundOfTriangelFEs.Add(lineFE); } } return(boundOfTriangelFEs); }
protected void CalcOgdenOriginalRivlinIncompressibleHyperelasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint uQuantityId = 0; uint lQuantityId = 1; System.Diagnostics.Debug.Assert(World.GetDof(uQuantityId) == 2); System.Diagnostics.Debug.Assert(World.GetDof(lQuantityId) == 1); int uDof = 2; int lDof = 1; int uNodeCnt = (int)World.GetNodeCount(uQuantityId); int lNodeCnt = (int)World.GetNodeCount(lQuantityId); //System.Diagnostics.Debug.Assert(uNodeCnt * uDof + lNodeCnt * lDof == A.RowLength); int offset = GetOffset(lQuantityId); System.Diagnostics.Debug.Assert(offset == uNodeCnt * uDof); double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var uFV = World.GetFieldValue(UValueId); TriangleFE uTriFE = World.GetTriangleFE(uQuantityId, feId); TriangleFE lTriFE = World.GetTriangleFE(lQuantityId, feId); Material ma0 = World.GetMaterial(uTriFE.MaterialId); if (!(ma0 is OgdenHyperelasticMaterial)) { return; } uint vertexCnt = uTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(uTriFE.VertexCoordIds[iVertex] == lTriFE.VertexCoordIds[iVertex]); } int[] uCoIds = uTriFE.NodeCoordIds; uint uElemNodeCnt = uTriFE.NodeCount; int[] uNodes = new int[uElemNodeCnt]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int coId = uCoIds[iNode]; int nodeId = World.Coord2Node(uQuantityId, coId); uNodes[iNode] = nodeId; } int[] lCoIds = lTriFE.NodeCoordIds; uint lElemNodeCnt = lTriFE.NodeCount; int[] lNodes = new int[lElemNodeCnt]; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int coId = lCoIds[iNode]; int nodeId = World.Coord2Node(lQuantityId, coId); lNodes[iNode] = nodeId; } var ma = ma0 as OgdenHyperelasticMaterial; int oOrder = ma.Order; double[] oMus = ma.Mus; double[] oAlphas = ma.Alphas; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] uSN = uTriFE.CalcSN(); double[,] uSNN = uTriFE.CalcSNN(); System.Diagnostics.Debug.Assert((int)World.TriIntegrationPointCount >= 3); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount); System.Diagnostics.Debug.Assert(ip.Ls.Length == (int)World.TriIntegrationPointCount); double[,] qu = new double[uElemNodeCnt, uDof]; double[] ql = new double[lElemNodeCnt]; for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] uN = uTriFE.CalcN(L); double[] lN = lTriFE.CalcN(L); double[][] uNu = uTriFE.CalcNu(L); double detJ = uTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; // 変位の微分 double[,] uu = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { int iNodeId = uNodes[iNode]; if (iNodeId == -1) { continue; } uu[iDof, jDof] += U[iNodeId * uDof + iDof] * uNu[jDof][iNode]; } } } // ラグランジュの未定乗数 double l = 0; for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { int iNodeId = lNodes[iNode]; if (iNodeId == -1) { continue; } l += U[offset + iNodeId] * lN[iNode]; } // Green-Lagrangeのひずみ double[,] e = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]); for (int kDof = 0; kDof < uDof; kDof++) { e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof]; } } } // 変形勾配テンソル double[,] f = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { f[iDof, jDof] = uu[iDof, jDof]; } f[iDof, iDof] += 1.0; } // 右Cauchy-Green変形テンソル double[,] c = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { c[iDof, jDof] = uu[iDof, jDof] + uu[jDof, iDof]; for (int kDof = 0; kDof < uDof; kDof++) { c[iDof, jDof] += uu[kDof, iDof] * uu[kDof, jDof]; } } c[iDof, iDof] += 1.0; } // Cのテンソル不変量 double I1 = c[0, 0] + c[1, 1] + 1.0; double I2 = c[0, 0] * c[1, 1] + c[0, 0] + c[1, 1] - c[0, 1] * c[1, 0]; double I3 = c[0, 0] * c[1, 1] - c[0, 1] * c[1, 0]; double inv13I3 = 1.0 / Math.Pow(I3, 1.0 / 3.0); double inv23I3 = 1.0 / Math.Pow(I3, 2.0 / 3.0); double[,] invC = new double[uDof, uDof]; { double invI3 = 1.0 / I3; invC[0, 0] = invI3 * c[1, 1]; invC[0, 1] = -invI3 * c[0, 1]; invC[1, 0] = -invI3 * c[1, 0]; invC[1, 1] = invI3 * c[0, 0]; } // Cの主値の1/2乗と主軸 // Note: これらは3次元 int dim3 = 3; System.Numerics.Complex[] fLambdas; System.Numerics.Complex[][] cNormals; SolvePrincipalValues(c, out fLambdas, out cNormals); double inv16I3 = 1.0 / Math.Pow(I3, 1.0 / 6.0); // 主第2Piola-Kirchhoff応力 System.Numerics.Complex[] principalS = new System.Numerics.Complex[uDof]; for (int kDof = 0; kDof < uDof; kDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; principalS[kDof] += mu * System.Numerics.Complex.Pow(fLambdas[kDof], alpha - 2); } } // 第2Piola-Kirchhoff応力 double[,] s = new double[uDof, uDof]; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { for (int kDof = 0; kDof < uDof; kDof++) { System.Numerics.Complex sij = principalS[kDof] * cNormals[kDof][iDof] * cNormals[kDof][jDof]; s[iDof, jDof] += sij.Real; //System.Diagnostics.Debug.Assert( // Math.Abs(sij.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit); } } } // Lagrangeの未定乗数の寄与項 { double tmp = 2.0 * l * I3; for (int iDof = 0; iDof < uDof; iDof++) { for (int jDof = 0; jDof < uDof; jDof++) { s[iDof, jDof] += tmp * invC[iDof, jDof]; } } } // 主軸構成則テンソル(オリジナルの方) System.Numerics.Complex[,] principalC21st = new System.Numerics.Complex[uDof, uDof]; System.Numerics.Complex[,] principalC22nd = new System.Numerics.Complex[uDof, uDof]; for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; System.Numerics.Complex tmp = 0; if (pDof == qDof) { tmp = mu * (alpha - 2) * System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 4); } principalC21st[pDof, qDof] += tmp; } } } for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { for (int r = 0; r < oOrder; r++) { double mu = oMus[r]; double alpha = oAlphas[r]; if (pDof != qDof) { System.Numerics.Complex tmp = 0; System.Numerics.Complex diffFLambda = fLambdas[pDof] - fLambdas[qDof]; if (diffFLambda.Magnitude >= IvyFEM.Constants.PrecisionLowerLimit) { // λp != λq System.Numerics.Complex squareFLambdaP = fLambdas[pDof] * fLambdas[pDof]; System.Numerics.Complex squareFLambdaQ = fLambdas[qDof] * fLambdas[qDof]; tmp = (mu / (squareFLambdaP - squareFLambdaQ)) * ( System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 2) - System.Numerics.Complex.Pow(fLambdas[qDof], alpha - 2)); } else { // λp == λq tmp = (1.0 / 2.0) * mu * (alpha - 2.0) * System.Numerics.Complex.Pow(fLambdas[pDof], alpha - 4); } principalC22nd[pDof, qDof] += tmp; } } } } // 構成則テンソル(オリジナルの方) double[,,,] c4 = new double[uDof, uDof, uDof, uDof]; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { for (int pDof = 0; pDof < uDof; pDof++) { for (int qDof = 0; qDof < uDof; qDof++) { System.Numerics.Complex c4ghef = principalC21st[pDof, qDof] * cNormals[pDof][gDof] * cNormals[pDof][hDof] * cNormals[qDof][eDof] * cNormals[qDof][fDof] + principalC22nd[pDof, qDof] * cNormals[pDof][gDof] * cNormals[qDof][hDof] * ( cNormals[pDof][eDof] * cNormals[qDof][fDof] + cNormals[qDof][eDof] * cNormals[pDof][fDof] ); c4[gDof, hDof, eDof, fDof] += c4ghef.Real; //System.Diagnostics.Debug.Assert( // Math.Abs(c4ghef.Imaginary) < IvyFEM.Constants.PrecisionLowerLimit); } } } } } } // 構成則テンソル double[,,,] barC4 = new double[uDof, uDof, uDof, uDof]; // 圧力構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { barC4[gDof, hDof, eDof, fDof] += 4.0 * l * I3 * invC[gDof, hDof] * invC[eDof, fDof] - 2.0 * l * I3 * ( invC[gDof, eDof] * invC[fDof, hDof] + invC[gDof, fDof] * invC[eDof, hDof]); } } } } // 変位構成則テンソル for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { barC4[gDof, hDof, eDof, fDof] += (1.0 / 2.0) * (c4[gDof, hDof, eDof, fDof] + c4[gDof, hDof, fDof, eDof]); } } } } double[,,,] b = new double[uElemNodeCnt, uDof, uDof, uDof]; { for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { b[iNode, iDof, gDof, hDof] = uNu[hDof][iNode] * f[iDof, gDof]; } } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < uElemNodeCnt; col++) { int colNodeId = uNodes[col]; if (colNodeId == -1) { continue; } double[,] kuu = new double[uDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { double tmp1 = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { for (int eDof = 0; eDof < uDof; eDof++) { for (int fDof = 0; fDof < uDof; fDof++) { tmp1 += barC4[gDof, hDof, eDof, fDof] * b[row, rowDof, eDof, fDof] * b[col, colDof, gDof, hDof]; } } } } kuu[rowDof, colDof] += detJWeight * tmp1; } } { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += s[gDof, hDof] * uNu[gDof][row] * uNu[hDof][col]; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { kuu[rowDof, rowDof] += detJWeight * tmp; } } for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] += kuu[rowDof, colDof]; B[rowNodeId * uDof + rowDof] += kuu[rowDof, colDof] * U[colNodeId * uDof + colDof]; } } } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < lElemNodeCnt; col++) { int colNodeId = lNodes[col]; if (colNodeId == -1) { continue; } double[,] kul = new double[uDof, lDof]; double[,] klu = new double[lDof, uDof]; for (int rowDof = 0; rowDof < uDof; rowDof++) { double tmp = 0.0; for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { tmp += invC[gDof, hDof] * b[row, rowDof, gDof, hDof]; } } kul[rowDof, 0] += detJWeight * tmp * 2.0 * lN[col] * I3; klu[0, rowDof] += detJWeight * tmp * 2.0 * lN[col] * I3; } for (int rowDof = 0; rowDof < uDof; rowDof++) { A[rowNodeId * uDof + rowDof, offset + colNodeId] += kul[rowDof, 0]; A[offset + colNodeId, rowNodeId *uDof + rowDof] += klu[0, rowDof]; B[rowNodeId * uDof + rowDof] += kul[rowDof, 0] * U[offset + colNodeId]; B[offset + colNodeId] += klu[0, rowDof] * U[rowNodeId * uDof + rowDof]; } } } for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { for (int gDof = 0; gDof < uDof; gDof++) { for (int hDof = 0; hDof < uDof; hDof++) { qu[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof]; } } } } for (int iNode = 0; iNode < lElemNodeCnt; iNode++) { ql[iNode] += detJWeight * lN[iNode] * (I3 - 1); } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < uElemNodeCnt; col++) { int colNodeId = uNodes[col]; if (colNodeId == -1) { continue; } int colCoId = uCoIds[col]; double[] u = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] velU = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] accU = uFV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double[,] m = new double[2, 2]; m[0, 0] = rho * uSNN[row, col]; m[1, 0] = 0.0; m[0, 1] = 0.0; m[1, 1] = rho * uSNN[row, col]; for (int rowDof = 0; rowDof < uDof; rowDof++) { for (int colDof = 0; colDof < uDof; colDof++) { A[rowNodeId * uDof + rowDof, colNodeId *uDof + colDof] += (1.0 / (beta * dt * dt)) * m[rowDof, colDof]; B[rowNodeId * uDof + rowDof] += m[rowDof, colDof] * ( (1.0 / (beta * dt * dt)) * u[colDof] + (1.0 / (beta * dt)) * velU[colDof] + (1.0 / (2.0 * beta) - 1.0) * accU[colDof]); } } } } double[,] fg = new double[uElemNodeCnt, uDof]; for (int iNode = 0; iNode < uElemNodeCnt; iNode++) { for (int iDof = 0; iDof < uDof; iDof++) { fg[iNode, iDof] = rho * g[iDof] * uSN[iNode]; } } for (int row = 0; row < uElemNodeCnt; row++) { int rowNodeId = uNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < uDof; rowDof++) { B[rowNodeId * uDof + rowDof] += fg[row, rowDof] - qu[row, rowDof]; } } for (int row = 0; row < lElemNodeCnt; row++) { int rowNodeId = lNodes[row]; if (rowNodeId == -1) { continue; } B[offset + rowNodeId] += -ql[row]; } }
private void CalcAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); IList <uint> feIds = World.GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(quantityId, feId); Material ma0 = World.GetMaterial(triFE.MaterialId); int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } System.Diagnostics.Debug.Assert(ma0 is DiffusionMaterial); var ma = ma0 as DiffusionMaterial; double rho = ma.MassDensity; double cap = ma.Capacity; double lambda = ma.DiffusionCoef; double f = ma.F; double[] sN = triFE.CalcSN(); double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } int colCoId = coIds[col]; double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double k = lambda * (sNxNx[row, col] + sNyNy[row, col]); double m = rho * cap * sNN[row, col]; A[rowNodeId, colNodeId] += k + (gamma / (beta * dt)) * m; B[rowNodeId] += m * ( (gamma / (beta * dt)) * u[0] - (1.0 - gamma / beta) * vel[0] - dt * (1.0 - gamma / (2.0 * beta)) * acc[0] ); } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } B[rowNodeId] += f * sN[row]; } } }
private void CalcStdGVorticityAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint wQuantityId = 0; uint pQuantityId = 1; int wNodeCnt = (int)World.GetNodeCount(wQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = wNodeCnt; double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); IList <uint> feIds = World.GetTriangleFEIds(wQuantityId); foreach (uint feId in feIds) { TriangleFE wTriFE = World.GetTriangleFE(wQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = wTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] wCoIds = wTriFE.NodeCoordIds; uint wElemNodeCnt = wTriFE.NodeCount; int[] wNodes = new int[wElemNodeCnt]; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int coId = wCoIds[iNode]; int nodeId = World.Coord2Node(wQuantityId, coId); wNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(wTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double[] g = { ma.GravityX, ma.GravityY }; IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] wN = wTriFE.CalcN(L); double[][] wNu = wTriFE.CalcNu(L); double[] wNx = wNu[0]; double[] wNy = wNu[1]; double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = wTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double w = 0; double wx = 0; double wy = 0; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int nodeId = wNodes[iNode]; if (nodeId == -1) { continue; } double wValue = U[nodeId]; w += wValue * wN[iNode]; wx += wValue * wNx[iNode]; wy += wValue * wNy[iNode]; } double p = 0; double px = 0; double py = 0; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int nodeId = pNodes[iNode]; if (nodeId == -1) { continue; } double pValue = U[offset + nodeId]; p += pValue * pN[iNode]; px += pValue * pNx[iNode]; py += pValue * pNy[iNode]; } double[] v = new double[2]; v[0] = py; v[1] = -px; for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } int colCoId = wCoIds[col]; // ω、dω/dt、d2ω/dt2 double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); System.Diagnostics.Debug.Assert(u.Length == 1); System.Diagnostics.Debug.Assert(vel.Length == 1); System.Diagnostics.Debug.Assert(acc.Length == 1); double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]); double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]); double m = detJWeight * rho * wN[row] * wN[col]; A[rowNodeId, colNodeId] += kww1 + kww2 + (gamma / (beta * dt)) * m; // v = f(ψ) : kww2 Newton-Raphson B[rowNodeId] += kww2 * U[colNodeId] + m * ( (gamma / (beta * dt)) * u[0] - (1.0 - gamma / beta) * vel[0] - dt * (1.0 - gamma / (2.0 * beta)) * acc[0] ); } } // v = f(ψ): kwp Newton-Raphson for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy); A[rowNodeId, offset + colNodeId] += kwp; B[rowNodeId] += kwp * U[offset + colNodeId]; } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } double kpw = -detJWeight * pN[row] * wN[col]; A[offset + rowNodeId, colNodeId] += kpw; } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]); A[offset + rowNodeId, offset + colNodeId] += kpp; } } // v = f(ψ): qw Newton-Raphson for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy); B[rowNodeId] += -qw; } for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double f = 0; for (int kNode = 0; kNode < wElemNodeCnt; kNode++) { int kNodeId = wNodes[kNode]; if (kNodeId == -1) { continue; } f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]); } B[rowNodeId] += f; } } } }
private void CalcStdGVorticityByPicardAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint wQuantityId = 0; uint pQuantityId = 1; int wNodeCnt = (int)World.GetNodeCount(wQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = wNodeCnt; IList <uint> feIds = World.GetTriangleFEIds(wQuantityId); foreach (uint feId in feIds) { TriangleFE wTriFE = World.GetTriangleFE(wQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = wTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] wCoIds = wTriFE.NodeCoordIds; uint wElemNodeCnt = wTriFE.NodeCount; int[] wNodes = new int[wElemNodeCnt]; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int coId = wCoIds[iNode]; int nodeId = World.Coord2Node(wQuantityId, coId); wNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(wTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double[] g = { ma.GravityX, ma.GravityY }; IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] wN = wTriFE.CalcN(L); double[][] wNu = wTriFE.CalcNu(L); double[] wNx = wNu[0]; double[] wNy = wNu[1]; double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = wTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double w = 0; double wx = 0; double wy = 0; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int nodeId = wNodes[iNode]; if (nodeId == -1) { continue; } double wValue = U[nodeId]; w += wValue * wN[iNode]; wx += wValue * wNx[iNode]; wy += wValue * wNy[iNode]; } double p = 0; double px = 0; double py = 0; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int nodeId = pNodes[iNode]; if (nodeId == -1) { continue; } double pValue = U[offset + nodeId]; p += pValue * pN[iNode]; px += pValue * pNx[iNode]; py += pValue * pNy[iNode]; } double[] v = new double[2]; v[0] = py; v[1] = -px; for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]); double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]); A[rowNodeId, colNodeId] += kww1 + kww2; //Picard //// v = f(ψ) : kww2 Newton-Raphson ///B[rowNodeId] += kww2 * U[colNodeId]; } } // Picard //// v = f(ψ): kwp Newton-Raphson //for (int row = 0; row < wElemNodeCnt; row++) //{ // int rowNodeId = wNodes[row]; // if (rowNodeId == -1) // { // continue; // } // for (int col = 0; col < pElemNodeCnt; col++) // { // int colNodeId = pNodes[col]; // if (colNodeId == -1) // { // continue; // } // // double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy); // A[rowNodeId, offset + colNodeId] += kwp; // B[rowNodeId] += kwp * U[offset + colNodeId]; // } //} for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } double kpw = -detJWeight * pN[row] * wN[col]; A[offset + rowNodeId, colNodeId] += kpw; } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]); A[offset + rowNodeId, offset + colNodeId] += kpp; } } // Picard //// v = f(ψ): qw Newton-Raphson //for (int row = 0; row < wElemNodeCnt; row++) //{ // int rowNodeId = wNodes[row]; // if (rowNodeId == -1) // { // continue; // } // double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy); // B[rowNodeId] += -qw; //} for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double f = 0; for (int kNode = 0; kNode < wElemNodeCnt; kNode++) { int kNodeId = wNodes[kNode]; if (kNodeId == -1) { continue; } f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]); } B[rowNodeId] += f; } } } }
private void CalcStokesAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint vQuantityId = 0; uint pQuantityId = 1; int vDof = 2; int pDof = 1; int vNodeCnt = (int)World.GetNodeCount(vQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = vNodeCnt * vDof; IList <uint> feIds = World.GetTriangleFEIds(vQuantityId); foreach (uint feId in feIds) { TriangleFE vTriFE = World.GetTriangleFE(vQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = vTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] vCoIds = vTriFE.NodeCoordIds; uint vElemNodeCnt = vTriFE.NodeCount; int[] vNodes = new int[vElemNodeCnt]; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { int coId = vCoIds[iNode]; int nodeId = World.Coord2Node(vQuantityId, coId); vNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(vTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double[] g = { ma.GravityX, ma.GravityY }; double[] vSN = vTriFE.CalcSN(); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] vN = vTriFE.CalcN(L); double[][] vNu = vTriFE.CalcNu(L); double[] vNx = vNu[0]; double[] vNy = vNu[1]; double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = vTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < vElemNodeCnt; col++) { int colNodeId = vNodes[col]; if (colNodeId == -1) { continue; } double[,] kvv1 = new double[vDof, vDof]; kvv1[0, 0] = detJWeight * mu * (vNx[row] * vNx[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col]; kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col]; kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] += kvv1[rowDof, colDof]; } } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double[,] kvp = new double[vDof, pDof]; kvp[0, 0] = -detJWeight * vNx[row] * pN[col]; kvp[1, 0] = -detJWeight * vNy[row] * pN[col]; for (int rowDof = 0; rowDof < vDof; rowDof++) { A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0]; A[offset + colNodeId, rowNodeId *vDof + rowDof] += kvp[rowDof, 0]; } } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row]; } } } }
// Linear / Saint Venant public void SetStressValue( uint displacementValueId, uint stressValueId, uint equivStressValueId) { System.Diagnostics.Debug.Assert(World.IsFieldValueId(displacementValueId)); FieldValue uFV = World.GetFieldValue(displacementValueId); uint uQuantityId = uFV.QuantityId; FieldValue sigmaFV = null; if (stressValueId != 0) { System.Diagnostics.Debug.Assert(World.IsFieldValueId(stressValueId)); sigmaFV = World.GetFieldValue(stressValueId); System.Diagnostics.Debug.Assert(sigmaFV.Type == FieldValueType.SymmetricTensor2); System.Diagnostics.Debug.Assert(sigmaFV.Dof == 3); } FieldValue eqSigmaFV = null; if (equivStressValueId != 0) { System.Diagnostics.Debug.Assert(World.IsFieldValueId(equivStressValueId)); eqSigmaFV = World.GetFieldValue(equivStressValueId); System.Diagnostics.Debug.Assert(eqSigmaFV.Type == FieldValueType.Scalar); System.Diagnostics.Debug.Assert(eqSigmaFV.Dof == 1); } IList <uint> feIds = World.GetTriangleFEIds(uQuantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(uQuantityId, feId); int[] coIds = triFE.NodeCoordIds; Material ma = World.GetMaterial(triFE.MaterialId); double lambda = 0; double mu = 0; if (ma is LinearElasticMaterial) { var ma1 = ma as LinearElasticMaterial; lambda = ma1.LameLambda; mu = ma1.LameMu; } else if (ma is SaintVenantHyperelasticMaterial) { var ma1 = ma as SaintVenantHyperelasticMaterial; lambda = ma1.LameLambda; mu = ma1.LameMu; } else { System.Diagnostics.Debug.Assert(false); throw new NotImplementedException(); } var ip = TriangleFE.GetIntegrationPoints(TriangleIntegrationPointCount.Point1); System.Diagnostics.Debug.Assert(ip.PointCount == 1); double[] L = ip.Ls[0]; double[][] Nu = triFE.CalcNu(L); double[] Nx = Nu[0]; double[] Ny = Nu[1]; double[,] uu = new double[2, 2]; for (int iNode = 0; iNode < coIds.Length; iNode++) { int coId = coIds[iNode]; double[] u = uFV.GetDoubleValue(coId, FieldDerivativeType.Value); uu[0, 0] += u[0] * Nx[iNode]; uu[0, 1] += u[0] * Ny[iNode]; uu[1, 0] += u[1] * Nx[iNode]; uu[1, 1] += u[1] * Ny[iNode]; } //ε strain double[,] eps = new double[2, 2]; if (ma is LinearElasticMaterial) { eps[0, 0] = (1.0 / 2.0) * (uu[0, 0] + uu[0, 0]); eps[0, 1] = (1.0 / 2.0) * (uu[0, 1] + uu[1, 0]); eps[1, 0] = (1.0 / 2.0) * (uu[1, 0] + uu[0, 1]); eps[1, 1] = (1.0 / 2.0) * (uu[1, 1] + uu[1, 1]); } else if (ma is SaintVenantHyperelasticMaterial) { eps[0, 0] = (1.0 / 2.0) * (uu[0, 0] + uu[0, 0] + uu[0, 0] * uu[0, 0] + uu[1, 0] * uu[1, 0]); eps[0, 1] = (1.0 / 2.0) * (uu[0, 1] + uu[1, 0] + uu[0, 0] * uu[0, 1] + uu[1, 1] * uu[1, 0]); eps[1, 0] = (1.0 / 2.0) * (uu[1, 0] + uu[0, 1] + uu[0, 1] * uu[0, 0] + uu[1, 0] * uu[1, 1]); eps[1, 1] = (1.0 / 2.0) * (uu[1, 1] + uu[1, 1] + uu[0, 1] * uu[0, 1] + uu[1, 1] * uu[1, 1]); } else { System.Diagnostics.Debug.Assert(false); } // σ stress double[,] sigma = new double[2, 2]; { sigma[0, 0] = mu * eps[0, 0]; sigma[0, 1] = mu * eps[0, 1]; sigma[1, 0] = mu * eps[1, 0]; sigma[1, 1] = mu * eps[1, 1]; double tmp = lambda * (eps[0, 0] + eps[1, 1]); sigma[0, 0] += tmp; sigma[1, 1] += tmp; } double misesStress = Math.Sqrt( (1.0 / 2.0) * ( sigma[0, 0] * sigma[0, 0] + sigma[1, 1] * sigma[1, 1] + (sigma[1, 1] - sigma[0, 0]) * (sigma[1, 1] - sigma[0, 0]) ) + 3.0 * sigma[0, 1] * sigma[0, 1]); if (stressValueId != 0) { double[] Sigma = sigmaFV.GetDoubleValues(FieldDerivativeType.Value); uint dof = sigmaFV.Dof; Sigma[(feId - 1) * dof + 0] = sigma[0, 0]; // σxx Sigma[(feId - 1) * dof + 1] = sigma[1, 1]; // σyy Sigma[(feId - 1) * dof + 2] = sigma[0, 1]; // τxy } if (equivStressValueId != 0) { double[] EqSigma = eqSigmaFV.GetDoubleValues(FieldDerivativeType.Value); EqSigma[feId - 1] = misesStress; } } }
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); }
private void CalcStdGNavierStokesAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint vQuantityId = 0; uint pQuantityId = 1; int vDof = 2; int pDof = 1; int vNodeCnt = (int)World.GetNodeCount(vQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = vNodeCnt * vDof; double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); IList <uint> feIds = World.GetTriangleFEIds(vQuantityId); foreach (uint feId in feIds) { TriangleFE vTriFE = World.GetTriangleFE(vQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = vTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(vTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] vCoIds = vTriFE.NodeCoordIds; uint vElemNodeCnt = vTriFE.NodeCount; int[] vNodes = new int[vElemNodeCnt]; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { int coId = vCoIds[iNode]; int nodeId = World.Coord2Node(vQuantityId, coId); vNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(vTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double[] g = { ma.GravityX, ma.GravityY }; double[] vSN = vTriFE.CalcSN(); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] vN = vTriFE.CalcN(L); double[][] vNu = vTriFE.CalcNu(L); double[] vNx = vNu[0]; double[] vNy = vNu[1]; double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = vTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double[] v = new double[vDof]; double[] vx = new double[vDof]; double[] vy = new double[vDof]; for (int iNode = 0; iNode < vElemNodeCnt; iNode++) { int nodeId = vNodes[iNode]; if (nodeId == -1) { continue; } for (int iDof = 0; iDof < vDof; iDof++) { double vValue = U[nodeId * vDof + iDof]; v[iDof] += vValue * vN[iNode]; vx[iDof] += vValue * vNx[iNode]; vy[iDof] += vValue * vNy[iNode]; } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < vElemNodeCnt; col++) { int colNodeId = vNodes[col]; if (colNodeId == -1) { continue; } int colCoId = vCoIds[col]; double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double[,] kvv1 = new double[vDof, vDof]; kvv1[0, 0] = detJWeight * mu * (vNx[row] * vNx[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); kvv1[0, 1] = detJWeight * mu * vNy[row] * vNx[col]; kvv1[1, 0] = detJWeight * mu * vNx[row] * vNy[col]; kvv1[1, 1] = detJWeight * mu * (vNy[row] * vNy[col] + vNx[row] * vNx[col] + vNy[row] * vNy[col]); double[,] kvv2 = new double[vDof, vDof]; kvv2[0, 0] = detJWeight * rho * vN[row] * ( vN[col] * vx[0] + v[0] * vNx[col] + v[1] * vNy[col]); kvv2[0, 1] = detJWeight * rho * vN[row] * vN[col] * vy[0]; kvv2[1, 0] = detJWeight * rho * vN[row] * vN[col] * vx[1]; kvv2[1, 1] = detJWeight * rho * vN[row] * ( vN[col] * vy[1] + v[0] * vNx[col] + v[1] * vNy[col]); double[,] m = new double[vDof, vDof]; m[0, 0] = detJWeight * rho * vN[row] * vN[col]; m[1, 1] = detJWeight * rho * vN[row] * vN[col]; for (int rowDof = 0; rowDof < vDof; rowDof++) { for (int colDof = 0; colDof < vDof; colDof++) { A[rowNodeId * vDof + rowDof, colNodeId *vDof + colDof] += kvv1[rowDof, colDof] + kvv2[rowDof, colDof] + (gamma / (beta * dt)) * m[rowDof, colDof]; B[rowNodeId * vDof + rowDof] += kvv2[rowDof, colDof] * U[colNodeId * vDof + colDof] + m[rowDof, colDof] * ( (gamma / (beta * dt)) * u[colDof] - (1.0 - gamma / beta) * vel[colDof] - dt * (1.0 - gamma / (2.0 * beta)) * acc[colDof] ); } } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double[,] kvp = new double[vDof, pDof]; kvp[0, 0] = -detJWeight * vNx[row] * pN[col]; kvp[1, 0] = -detJWeight * vNy[row] * pN[col]; for (int rowDof = 0; rowDof < vDof; rowDof++) { A[rowNodeId * vDof + rowDof, offset + colNodeId] += kvp[rowDof, 0]; A[offset + colNodeId, rowNodeId *vDof + rowDof] += kvp[rowDof, 0]; } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } double[] q2 = new double[vDof]; for (int rowDof = 0; rowDof < vDof; rowDof++) { q2[rowDof] = detJWeight * rho * vN[row] * (v[0] * vx[rowDof] + v[1] * vy[rowDof]); } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += -q2[rowDof]; } } } for (int row = 0; row < vElemNodeCnt; row++) { int rowNodeId = vNodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < vDof; rowDof++) { B[rowNodeId * vDof + rowDof] += rho * g[rowDof] * vSN[row]; } } } }
private void CalcSUPGVorticityAB(IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint wQuantityId = 0; uint pQuantityId = 1; int wNodeCnt = (int)World.GetNodeCount(wQuantityId); int pNodeCnt = (int)World.GetNodeCount(pQuantityId); int offset = wNodeCnt; int vDof = 2; // 速度 double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); IList <uint> feIds = World.GetTriangleFEIds(wQuantityId); foreach (uint feId in feIds) { TriangleFE wTriFE = World.GetTriangleFE(wQuantityId, feId); TriangleFE pTriFE = World.GetTriangleFE(pQuantityId, feId); uint vertexCnt = wTriFE.VertexCount; for (int iVertex = 0; iVertex < vertexCnt; iVertex++) { System.Diagnostics.Debug.Assert(wTriFE.VertexCoordIds[iVertex] == pTriFE.VertexCoordIds[iVertex]); } int[] wCoIds = wTriFE.NodeCoordIds; uint wElemNodeCnt = wTriFE.NodeCount; int[] wNodes = new int[wElemNodeCnt]; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int coId = wCoIds[iNode]; int nodeId = World.Coord2Node(wQuantityId, coId); wNodes[iNode] = nodeId; } int[] pCoIds = pTriFE.NodeCoordIds; uint pElemNodeCnt = pTriFE.NodeCount; int[] pNodes = new int[pElemNodeCnt]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; int nodeId = World.Coord2Node(pQuantityId, coId); pNodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(wTriFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is NewtonFluidMaterial); var ma = ma0 as NewtonFluidMaterial; double rho = ma.MassDensity; double mu = ma.Mu; double nu = mu / rho; double[] g = { ma.GravityX, ma.GravityY }; double[][] velos = new double[pElemNodeCnt][]; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int coId = pCoIds[iNode]; double[] velo = new double[vDof]; for (int iDof = 0; iDof < vDof; iDof++) { velo[iDof] = CoordV[coId * vDof + iDof]; } velos[iNode] = velo; } double taum = 0; double tauc = 0; { double[] aveVelo = { (velos[0][0] + velos[1][0] + velos[2][0]) / 3.0, (velos[0][1] + velos[1][1] + velos[2][1]) / 3.0 }; double veloNorm = Math.Sqrt(aveVelo[0] * aveVelo[0] + aveVelo[1] * aveVelo[1]); double[][] Lu = new double[vDof][]; { double[] a; double[] b; double[] c; wTriFE.CalcTransMatrix(out a, out b, out c); // Lx Lu[0] = b; // Ly Lu[1] = c; } IvyFEM.Lapack.DoubleMatrix GMat = new IvyFEM.Lapack.DoubleMatrix(vDof, vDof); double[] gVec = new double[vDof]; for (int iDof = 0; iDof < vDof; iDof++) { for (int jDof = 0; jDof < vDof; jDof++) { for (int kDof = 0; kDof < vDof; kDof++) { GMat[iDof, jDof] += Lu[iDof][kDof] * Lu[jDof][kDof]; } } } for (int iDof = 0; iDof < vDof; iDof++) { for (int kDof = 0; kDof < vDof; kDof++) { gVec[iDof] += Lu[iDof][kDof]; } } double sqinvtaum1 = 0; double sqinvtaum2 = 0; { double[] tmpVec = GMat * aveVelo; sqinvtaum2 = IvyFEM.Lapack.Functions.ddot(aveVelo, tmpVec); } double sqinvtaum3 = 0; { IvyFEM.Lapack.DoubleMatrix GMatT = new Lapack.DoubleMatrix(GMat); GMatT.Transpose(); double GMatDoubleDot = IvyFEM.Lapack.DoubleMatrix.DoubleDot(GMat, GMatT); sqinvtaum3 = nu * nu * GMatDoubleDot; } double sqinvtaum = sqinvtaum1 + sqinvtaum2 + sqinvtaum3; taum = 1.0 / Math.Sqrt(sqinvtaum); double gDot = IvyFEM.Lapack.Functions.ddot(gVec, gVec); tauc = 1.0 / (taum * gDot); } IntegrationPoints ip = TriangleFE.GetIntegrationPoints(World.TriIntegrationPointCount);//Point7 for (int ipPt = 0; ipPt < ip.PointCount; ipPt++) { double[] L = ip.Ls[ipPt]; double[] wN = wTriFE.CalcN(L); double[][] wNu = wTriFE.CalcNu(L); double[] wNx = wNu[0]; double[] wNy = wNu[1]; double[, ][] wNuv = wTriFE.CalcNuv(L); double[] pN = pTriFE.CalcN(L); double[][] pNu = pTriFE.CalcNu(L); double[] pNx = pNu[0]; double[] pNy = pNu[1]; double detJ = wTriFE.GetDetJacobian(L); double weight = ip.Weights[ipPt]; double detJWeight = (1.0 / 2.0) * weight * detJ; double w = 0; double wx = 0; double wy = 0; double wxx = 0; double wxy = 0; double wyx = 0; double wyy = 0; double velow = 0; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int nodeId = wNodes[iNode]; if (nodeId == -1) { continue; } double wValue = U[nodeId]; w += wValue * wN[iNode]; wx += wValue * wNx[iNode]; wy += wValue * wNy[iNode]; wxx += wValue * wNuv[0, 0][iNode]; wxy += wValue * wNuv[0, 1][iNode]; wyx += wValue * wNuv[1, 0][iNode]; wyy += wValue * wNuv[1, 1][iNode]; int coId = wCoIds[iNode]; double[] prevU = FV.GetDoubleValue(coId, FieldDerivativeType.Value); double[] prevVel = FV.GetDoubleValue(coId, FieldDerivativeType.Velocity); double[] prevAcc = FV.GetDoubleValue(coId, FieldDerivativeType.Acceleration); System.Diagnostics.Debug.Assert(prevU.Length == 1); System.Diagnostics.Debug.Assert(prevVel.Length == 1); System.Diagnostics.Debug.Assert(prevAcc.Length == 1); double vel = 0; vel = (gamma / (beta * dt)) * (wValue - prevU[0]) + (1.0 - gamma / beta) * prevVel[0] + dt * (1.0 - gamma / (2.0 * beta)) * prevAcc[0]; velow += vel * wN[iNode]; } double p = 0; double px = 0; double py = 0; for (int iNode = 0; iNode < pElemNodeCnt; iNode++) { int nodeId = pNodes[iNode]; if (nodeId == -1) { continue; } double pValue = U[offset + nodeId]; p += pValue * pN[iNode]; px += pValue * pNx[iNode]; py += pValue * pNy[iNode]; } // dg/du double[] gx = new double[2]; double[] gy = new double[2]; for (int iNode = 0; iNode < wElemNodeCnt; iNode++) { int nodeId = wNodes[iNode]; if (nodeId == -1) { continue; } for (int iDof = 0; iDof < 2; iDof++) { double gValue = g[iDof]; gx[iDof] += gValue * wNx[iNode]; gy[iDof] += gValue * wNy[iNode]; } } double[] v = new double[2]; v[0] = py; v[1] = -px; for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } int colCoId = wCoIds[col]; // ω、dω/dt、d2ω/dt2 double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); System.Diagnostics.Debug.Assert(u.Length == 1); System.Diagnostics.Debug.Assert(vel.Length == 1); System.Diagnostics.Debug.Assert(acc.Length == 1); double kww1 = detJWeight * mu * (wNx[row] * wNx[col] + wNy[row] * wNy[col]); double kww2 = detJWeight * rho * wN[row] * (v[0] * wNx[col] + v[1] * wNy[col]); double m = detJWeight * rho * wN[row] * wN[col]; A[rowNodeId, colNodeId] += kww1 + kww2 + (gamma / (beta * dt)) * m; // v = f(ψ) : kww2 Newton-Raphson B[rowNodeId] += kww2 * U[colNodeId] + m * ( (gamma / (beta * dt)) * u[0] - (1.0 - gamma / beta) * vel[0] - dt * (1.0 - gamma / (2.0 * beta)) * acc[0] ); } } // v = f(ψ): kwp Newton-Raphson for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kwp = detJWeight * rho * wN[row] * (pNy[col] * wx - pNx[col] * wy); A[rowNodeId, offset + colNodeId] += kwp; B[rowNodeId] += kwp * U[offset + colNodeId]; } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } double kpw = -detJWeight * pN[row] * wN[col]; A[offset + rowNodeId, colNodeId] += kpw; } } for (int row = 0; row < pElemNodeCnt; row++) { int rowNodeId = pNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kpp = detJWeight * (pNx[row] * pNx[col] + pNy[row] * pNy[col]); A[offset + rowNodeId, offset + colNodeId] += kpp; } } // v = f(ψ): qw Newton-Raphson for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double qw = detJWeight * rho * wN[row] * (v[0] * wx + v[1] * wy); B[rowNodeId] += -qw; } for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double f = 0; for (int kNode = 0; kNode < wElemNodeCnt; kNode++) { int kNodeId = wNodes[kNode]; if (kNodeId == -1) { continue; } f += detJWeight * rho * (wNx[kNode] * g[1] - wNy[kNode] * g[0]); } B[rowNodeId] += f; } ////////////////////////////////////////////////////////////// // SUPG double rm = 0; double[] rmw = new double[wElemNodeCnt]; double[] rmp = new double[pElemNodeCnt]; { rm = rho * velow + -mu * (wxx + wyy) + rho * (v[0] * wx + v[1] * wy) + -rho * (gx[1] - gy[0]); for (int jNode = 0; jNode < wElemNodeCnt; jNode++) { int jNodeId = wNodes[jNode]; if (jNodeId == -1) { continue; } rmw[jNode] = rho * (gamma / (beta * dt)) * wN[jNode] + -mu * (wNuv[0, 0][jNode] + wNuv[1, 1][jNode]) + rho * (v[0] * wNu[0][jNode] + v[1] * wNu[1][jNode]); } for (int jNode = 0; jNode < pElemNodeCnt; jNode++) { int jNodeId = pNodes[jNode]; if (jNodeId == -1) { continue; } rmp[jNode] = rho * (pNu[1][jNode] * wx - pNu[0][jNode] * wy); } } // kww for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < wElemNodeCnt; col++) { int colNodeId = wNodes[col]; if (colNodeId == -1) { continue; } double kww = detJWeight * taum * (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rmw[col]; A[rowNodeId, colNodeId] += kww; B[rowNodeId] += kww * U[colNodeId]; } } // kwp for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < pElemNodeCnt; col++) { int colNodeId = pNodes[col]; if (colNodeId == -1) { continue; } double kwp = detJWeight * taum * (pNu[1][col] * wNu[0][row] - pNu[0][col] * wNu[1][row]) * rm + detJWeight * taum * (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rmp[col]; A[rowNodeId, offset + colNodeId] += kwp; B[rowNodeId] += kwp * U[offset + colNodeId]; } } for (int row = 0; row < wElemNodeCnt; row++) { int rowNodeId = wNodes[row]; if (rowNodeId == -1) { continue; } double qw = detJWeight * taum * (v[0] * wNu[0][row] + v[1] * wNu[1][row]) * rm; B[rowNodeId] += -qw; } } } }
protected void CalcLinearElasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; int nodeCnt = (int)World.GetNodeCount(quantityId); System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2); int dof = 2; double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); TriangleFE triFE = World.GetTriangleFE(quantityId, feId); Material ma0 = World.GetMaterial(triFE.MaterialId); if (!(ma0 is LinearElasticMaterial)) { return; } int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } var ma = ma0 as LinearElasticMaterial; double lambda = ma.LameLambda; double mu = ma.LameMu; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] sN = triFE.CalcSN(); double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } int colCoId = coIds[col]; double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double[,] k = new double[dof, dof]; double[,] m = new double[dof, dof]; k[0, 0] = (lambda + mu) * sNxNx[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]); k[1, 0] = lambda * sNyNx[row, col] + mu * sNxNy[row, col]; k[0, 1] = lambda * sNxNy[row, col] + mu * sNyNx[row, col]; k[1, 1] = (lambda + mu) * sNyNy[row, col] + mu * (sNxNx[row, col] + sNyNy[row, col]); m[0, 0] = rho * sNN[row, col]; m[1, 0] = 0.0; m[0, 1] = 0.0; m[1, 1] = rho * sNN[row, col]; for (int rowDof = 0; rowDof < dof; rowDof++) { for (int colDof = 0; colDof < dof; colDof++) { A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] += (1.0 / (beta * dt * dt)) * m[rowDof, colDof] + k[rowDof, colDof]; B[rowNodeId * dof + rowDof] += m[rowDof, colDof] * ( (1.0 / (beta * dt * dt)) * u[colDof] + (1.0 / (beta * dt)) * vel[colDof] + (1.0 / (2.0 * beta) - 1.0) * acc[colDof]); } } } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < dof; rowDof++) { B[rowNodeId * dof + rowDof] += rho * g[rowDof] * sN[row]; } } }
protected void CalcSaintVenantHyperelasticElementAB( uint feId, IvyFEM.Linear.DoubleSparseMatrix A, double[] B) { uint quantityId = 0; System.Diagnostics.Debug.Assert(World.GetDof(quantityId) == 2); int dof = 2; int nodeCnt = (int)World.GetNodeCount(quantityId); double dt = TimeStep; double beta = NewmarkBeta; double gamma = NewmarkGamma; var FV = World.GetFieldValue(ValueId); TriangleFE triFE = World.GetTriangleFE(quantityId, feId); Material ma0 = World.GetMaterial(triFE.MaterialId); if (!(ma0 is SaintVenantHyperelasticMaterial)) { return; } int[] coIds = triFE.NodeCoordIds; uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = coIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } var ma = ma0 as SaintVenantHyperelasticMaterial; double lambda = ma.LameLambda; double mu = ma.LameMu; double rho = ma.MassDensity; double[] g = { ma.GravityX, ma.GravityY }; double[] sN = triFE.CalcSN(); double[,] sNN = triFE.CalcSNN(); IntegrationPoints ip = TriangleFE.GetIntegrationPoints(TriangleIntegrationPointCount.Point1); System.Diagnostics.Debug.Assert(ip.Ls.Length == 1); double[] L = ip.Ls[0]; double[][] Nu = triFE.CalcNu(L); double detJ = triFE.GetDetJacobian(L); double weight = ip.Weights[0]; double detJWeight = (1.0 / 2.0) * weight * detJ; double[,] uu = new double[dof, dof]; for (int iDof = 0; iDof < dof; iDof++) { for (int jDof = 0; jDof < dof; jDof++) { for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int iNodeId = nodes[iNode]; if (iNodeId == -1) { continue; } uu[iDof, jDof] += U[iNodeId * dof + iDof] * Nu[jDof][iNode]; } } } double[,] e = new double[dof, dof]; for (int iDof = 0; iDof < dof; iDof++) { for (int jDof = 0; jDof < dof; jDof++) { e[iDof, jDof] = (1.0 / 2.0) * (uu[iDof, jDof] + uu[jDof, iDof]); for (int kDof = 0; kDof < dof; kDof++) { e[iDof, jDof] += (1.0 / 2.0) * uu[kDof, iDof] * uu[kDof, jDof]; } } } double[,,,] b = new double[elemNodeCnt, dof, dof, dof]; { double[,] f = new double[dof, dof]; for (int iDof = 0; iDof < dof; iDof++) { for (int jDof = 0; jDof < dof; jDof++) { f[iDof, jDof] = uu[iDof, jDof]; } f[iDof, iDof] += 1.0; } for (int iNode = 0; iNode < elemNodeCnt; iNode++) { for (int iDof = 0; iDof < dof; iDof++) { for (int gDof = 0; gDof < dof; gDof++) { for (int hDof = 0; hDof < dof; hDof++) { b[iNode, iDof, gDof, hDof] = Nu[hDof][iNode] * f[iDof, gDof]; } } } } } double[,] s = new double[dof, dof]; { double tmp = 0.0; for (int iDof = 0; iDof < dof; iDof++) { for (int jDof = 0; jDof < dof; jDof++) { s[iDof, jDof] = 2.0 * mu * e[iDof, jDof]; } tmp += e[iDof, iDof]; } for (int iDof = 0; iDof < dof; iDof++) { s[iDof, iDof] += lambda * tmp; } } double[,] q = new double[elemNodeCnt, dof]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { for (int iDof = 0; iDof < dof; iDof++) { for (int gDof = 0; gDof < dof; gDof++) { for (int hDof = 0; hDof < dof; hDof++) { q[iNode, iDof] += detJWeight * s[gDof, hDof] * b[iNode, iDof, gDof, hDof]; } } } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } int colCoId = coIds[col]; double[] u = FV.GetDoubleValue(colCoId, FieldDerivativeType.Value); double[] vel = FV.GetDoubleValue(colCoId, FieldDerivativeType.Velocity); double[] acc = FV.GetDoubleValue(colCoId, FieldDerivativeType.Acceleration); double[,] k = new double[dof, dof]; double[,] m = new double[dof, dof]; for (int rowDof = 0; rowDof < dof; rowDof++) { for (int colDof = 0; colDof < dof; colDof++) { { double tmp1 = 0.0; double tmp2 = 0.0; for (int gDof = 0; gDof < dof; gDof++) { tmp1 += b[row, rowDof, gDof, gDof]; tmp2 += b[col, colDof, gDof, gDof]; } k[rowDof, colDof] += detJWeight * lambda * tmp1 * tmp2; } { double tmp = 0.0; for (int gDof = 0; gDof < dof; gDof++) { for (int hDof = 0; hDof < dof; hDof++) { tmp += b[row, rowDof, gDof, hDof] * b[col, colDof, gDof, hDof] + b[row, rowDof, gDof, hDof] * b[col, colDof, hDof, gDof]; } } k[rowDof, colDof] += detJWeight * mu * tmp; } } } { double tmp = 0.0; for (int gDof = 0; gDof < dof; gDof++) { for (int hDof = 0; hDof < dof; hDof++) { tmp += s[gDof, hDof] * Nu[hDof][row] * Nu[gDof][col]; } } for (int rowDof = 0; rowDof < dof; rowDof++) { k[rowDof, rowDof] += detJWeight * tmp; } } m[0, 0] = rho * sNN[row, col]; m[1, 0] = 0.0; m[0, 1] = 0.0; m[1, 1] = rho * sNN[row, col]; for (int rowDof = 0; rowDof < dof; rowDof++) { for (int colDof = 0; colDof < dof; colDof++) { A[rowNodeId * dof + rowDof, colNodeId *dof + colDof] += (1.0 / (beta * dt * dt)) * m[rowDof, colDof] + k[rowDof, colDof]; B[rowNodeId * dof + rowDof] += k[rowDof, colDof] * U[colNodeId * dof + colDof] + m[rowDof, colDof] * ( (1.0 / (beta * dt * dt)) * u[colDof] + (1.0 / (beta * dt)) * vel[colDof] + (1.0 / (2.0 * beta) - 1.0) * acc[colDof]); } } } } double[,] fg = new double[elemNodeCnt, dof]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { for (int iDof = 0; iDof < dof; iDof++) { fg[iNode, iDof] += rho * g[iDof] * sN[iNode]; } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int rowDof = 0; rowDof < dof; rowDof++) { B[rowNodeId * dof + rowDof] += fg[row, rowDof] - q[row, rowDof]; } } }
private void CalcAB(IvyFEM.Linear.ComplexSparseMatrix A, System.Numerics.Complex[] B) { uint quantityId = 0; IList <uint> feIds = World.GetTriangleFEIds(quantityId); foreach (uint feId in feIds) { TriangleFE triFE = World.GetTriangleFE(quantityId, feId); uint elemNodeCnt = triFE.NodeCount; int[] nodes = new int[elemNodeCnt]; for (int iNode = 0; iNode < elemNodeCnt; iNode++) { int coId = triFE.NodeCoordIds[iNode]; int nodeId = World.Coord2Node(quantityId, coId); nodes[iNode] = nodeId; } Material ma0 = World.GetMaterial(triFE.MaterialId); System.Diagnostics.Debug.Assert(ma0 is HelmholtzMaterial); var ma = ma0 as HelmholtzMaterial; double v = ma.Velocity; System.Numerics.Complex f = ma.F; double omega = 2.0 * Math.PI * Frequency; double k = omega / v; double[,] sNN = triFE.CalcSNN(); double[, ][,] sNuNv = triFE.CalcSNuNv(); double[,] sNxNx = sNuNv[0, 0]; double[,] sNyNx = sNuNv[1, 0]; double[,] sNxNy = sNuNv[0, 1]; double[,] sNyNy = sNuNv[1, 1]; double[] sN = triFE.CalcSN(); for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } for (int col = 0; col < elemNodeCnt; col++) { int colNodeId = nodes[col]; if (colNodeId == -1) { continue; } double a = sNxNx[row, col] + sNyNy[row, col] - k * k * sNN[row, col]; A[rowNodeId, colNodeId] += a; } } for (int row = 0; row < elemNodeCnt; row++) { int rowNodeId = nodes[row]; if (rowNodeId == -1) { continue; } System.Numerics.Complex b = f * sN[row]; B[rowNodeId] += b; } } }