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 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; } } } }
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]; } } }
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]; } }
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]; } }
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]; } } }
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]; } } }
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]; } }
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]; } } }
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; } } }