/// <summary> /// <c>S_Matrix</c> returns stress matrix required to compute nonlinear part of K matrix /// </summary> private MatrixST Stress_Matrix(int inc, int GaussPoint) { // __ __ __ __ __ __ // | s 0 0 | | s11 s12 s13 | | s0 s3 s5 | // S = | 0 s 0 | where s = | s21 s22 s23 | => | s3 s1 s4 | // | 0 0 s | | s31 s32 s33 | | s5 s4 s2 | // --- --- --- --- --- --- MatrixST S = new MatrixST(9, 9); for (int i = 0; i < 3; i++) { S.SetFast(3 * i + 0, 3 * i + 0, Stress[inc].GetFast(GaussPoint, 0) + dS[GaussPoint].GetFast(0, 0)); S.SetFast(3 * i + 1, 3 * i + 0, Stress[inc].GetFast(GaussPoint, 3) + dS[GaussPoint].GetFast(3, 0)); S.SetFast(3 * i + 2, 3 * i + 0, Stress[inc].GetFast(GaussPoint, 5) + dS[GaussPoint].GetFast(5, 0)); S.SetFast(3 * i + 0, 3 * i + 1, Stress[inc].GetFast(GaussPoint, 3) + dS[GaussPoint].GetFast(3, 0)); S.SetFast(3 * i + 1, 3 * i + 1, Stress[inc].GetFast(GaussPoint, 1) + dS[GaussPoint].GetFast(1, 0)); S.SetFast(3 * i + 2, 3 * i + 1, Stress[inc].GetFast(GaussPoint, 4) + dS[GaussPoint].GetFast(4, 0)); S.SetFast(3 * i + 0, 3 * i + 2, Stress[inc].GetFast(GaussPoint, 5) + dS[GaussPoint].GetFast(5, 0)); S.SetFast(3 * i + 1, 3 * i + 2, Stress[inc].GetFast(GaussPoint, 4) + dS[GaussPoint].GetFast(4, 0)); S.SetFast(3 * i + 2, 3 * i + 2, Stress[inc].GetFast(GaussPoint, 2) + dS[GaussPoint].GetFast(2, 0)); } return(S); }
/// <summary> /// Inverse of 3x3 matrix. Designed for Jacobian matrix. /// </summary> /// <returns>Inverse of this matrix if size is 3x3 and determinant is not 0. /// <br>Otherwise returns empty 3x3 matrix</br></returns> public MatrixST Inverse() { double det = Det3(); if (det != 0 && Rows == 3 && Cols == 3) { MatrixST Inv = new MatrixST(3, 3); double X = 1.0 / det; Inv.SetFast(0, 0, X * (GetFast(1, 1) * GetFast(2, 2) - GetFast(1, 2) * GetFast(2, 1))); Inv.SetFast(0, 1, X * (GetFast(0, 2) * GetFast(2, 1) - GetFast(0, 1) * GetFast(2, 2))); Inv.SetFast(0, 2, X * (GetFast(0, 1) * GetFast(1, 2) - GetFast(0, 2) * GetFast(1, 1))); Inv.SetFast(1, 0, X * (GetFast(1, 2) * GetFast(2, 0) - GetFast(1, 0) * GetFast(2, 2))); Inv.SetFast(1, 1, X * (GetFast(0, 0) * GetFast(2, 2) - GetFast(0, 2) * GetFast(2, 0))); Inv.SetFast(1, 2, X * (GetFast(0, 2) * GetFast(1, 0) - GetFast(0, 0) * GetFast(1, 2))); Inv.SetFast(2, 0, X * (GetFast(1, 0) * GetFast(2, 1) - GetFast(1, 1) * GetFast(2, 0))); Inv.SetFast(2, 1, X * (GetFast(0, 1) * GetFast(2, 0) - GetFast(0, 0) * GetFast(2, 1))); Inv.SetFast(2, 2, X * (GetFast(0, 0) * GetFast(1, 1) - GetFast(0, 1) * GetFast(1, 0))); return(Inv); } else { throw new System.ArgumentException("Inverse matrix error: Matrix size in not 3x3 or det=0", "Inverse"); } }
/// <summary> /// <c>BL0_Matrix</c> returns linear strain-displacement transformation matrix without initial displacement effect /// </summary> private MatrixST BL0_Matrix(MatrixST dN) { // Strain vector: e = { e_xx e_yy e_zz e_xy e_yz e_xz } // // BL0 is linear strain-displacement matrix: // __ __ // | dNi/dx 0 0 | // | 0 dNi/dy 0 | // | 0 0 dNi/dz | // BL0 = L*N = | dNi/dy dNi/dx 0 ... | // | 0 dNi/dz dNi/dy | // | dNi/dz 0 dNi/dx | // --- --- // Strain-displacement Matrix BL0 MatrixST BL0 = new MatrixST(6, 3 * NList.Count); for (int i = 0; i < NList.Count; i++) { BL0.SetFast(0, 3 * i + 0, dN.GetFast(0, i)); BL0.SetFast(1, 3 * i + 1, dN.GetFast(1, i)); BL0.SetFast(2, 3 * i + 2, dN.GetFast(2, i)); BL0.SetFast(3, 3 * i + 0, dN.GetFast(1, i)); BL0.SetFast(3, 3 * i + 1, dN.GetFast(0, i)); BL0.SetFast(4, 3 * i + 1, dN.GetFast(2, i)); BL0.SetFast(4, 3 * i + 2, dN.GetFast(1, i)); BL0.SetFast(5, 3 * i + 0, dN.GetFast(2, i)); BL0.SetFast(5, 3 * i + 2, dN.GetFast(0, i)); } return(BL0); }
/// <summary> /// <c>BNL_Matrix</c> returns non-linear strain-displacement transformation matrix /// </summary> private MatrixST BNL_Matrix(MatrixST dN) { // __ __ ___ ___ // | B 0 0 | | dN1/dx 0 0 dN2/dx dNi/dx | // BNL = | 0 B 0 | where B = | dN1/dy 0 0 dN2/dy ... dNi/dy | // | 0 0 B | | dN1/dz 0 0 dN2/dz dNi/dz | // --- --- --- --- // // | dN1/dx dN2/dx dNk/dx | // Input: dN = | dN1/dy dN2/dy ... dNk/dy | // | dN1/dz dN2/dz dNk/dz | // // Strain-displacement Matrix MatrixST BNL = new MatrixST(9, 3 * NList.Count); for (int i = 0; i < NList.Count; i++) { BNL.SetFast(0, 3 * i + 0, dN.GetFast(0, i)); BNL.SetFast(1, 3 * i + 0, dN.GetFast(1, i)); BNL.SetFast(2, 3 * i + 0, dN.GetFast(2, i)); BNL.SetFast(3, 3 * i + 1, dN.GetFast(0, i)); BNL.SetFast(4, 3 * i + 1, dN.GetFast(1, i)); BNL.SetFast(5, 3 * i + 1, dN.GetFast(2, i)); BNL.SetFast(6, 3 * i + 2, dN.GetFast(0, i)); BNL.SetFast(7, 3 * i + 2, dN.GetFast(1, i)); BNL.SetFast(8, 3 * i + 2, dN.GetFast(2, i)); } return(BNL); }
/// <summary> /// Add nodal value to List /// <list> /// <item><c>nid</c></item> /// <description> - Node ID</description> /// <item><c>direction</c></item> /// <description> - X=0; Y=1; Z=2</description> /// <item><c>value</c></item> /// <description> - Value of BC (double for Force BC, 0 or 1 for Fix BC)</description> /// <item><c>NodeLib</c></item> /// <description> - Database Node library</description> /// </list> /// </summary> public void Add(int nid, double[] value, Dictionary <int, Node> NodeLib) { if (NodeLib.ContainsKey(nid)) { MatrixST nVal = new MatrixST(3, 1); nVal.SetFast(0, 0, value[0]); nVal.SetFast(1, 0, value[1]); nVal.SetFast(2, 0, value[2]); NodalValues.Add(nid, nVal); } }
// ==================== Finite Element Matrix methods =================================== /// <summary> /// <c>Jacobian</c> returns Jacobian matrix in Gauss Point. /// </summary> public MatrixST Jacobian(Dictionary <int, Node> NodeLib, MatrixST dN_dLocal) { // | dN1/d_xi dN2/d_xi ... | |x1 y1 z1| // J = | dN1/d_eta dN2/d_eta ... | * |x2 y2 z2| // | dN1/d_zeta dN2/d_zeta ... | |x3 y3 z3| // | ... | MatrixST Nodal_Coord = new MatrixST(NList.Count, 3); for (int i = 0; i < NList.Count; i++) { Nodal_Coord.SetFast(i, 0, NodeLib[NList[i]].X); Nodal_Coord.SetFast(i, 1, NodeLib[NList[i]].Y); Nodal_Coord.SetFast(i, 2, NodeLib[NList[i]].Z); } MatrixST J = dN_dLocal * Nodal_Coord; return(J); }
public MatrixST Vector2Tensor(double[] v) { MatrixST T = new MatrixST(3, 3); T.SetFast(0, 0, v[0]); T.SetFast(0, 1, v[3]); T.SetFast(0, 2, v[5]); T.SetFast(1, 0, v[3]); T.SetFast(1, 1, v[1]); T.SetFast(1, 2, v[4]); T.SetFast(2, 0, v[5]); T.SetFast(2, 1, v[4]); T.SetFast(2, 2, v[2]); return(T); }
/// <summary> /// <c>BL1_Matrix</c> returns intial displacement part of BL matrix in Total Lagrangian framework /// </summary> private MatrixST BL1_Matrix(MatrixST dN, MatrixST dU) { // Strain vector: e = { e_xx e_yy e_zz e_xy e_yz e_xz } // __ __ // | F11 * dNi/dx F21 * dNi/dx F31 * dNi/dx | // | F12 * dNi/dy F22 * dNi/dy F32 * dNi/dy | // | F13 * dNi/dy F23 * dNi/dy F33 * dNi/dy | // BL1 = | F11*dNi/dy + F12*dNi/dx F21*dNi/dy + F22*dNi/dx F11*dNi/dy + F12*dNi/dx ... | // | F12*dNi/dz + F13*dNi/dy F22*dNi/dz + F23*dNi/dy F12*dNi/dz + F13*dNi/dy | // | F11*dNi/dz + F13*dNi/dx F21*dNi/dz + F23*dNi/dx F11*dNi/dz + F13*dNi/dx | // --- --- // // | x1 y1 z1 | | dN1/dx dN2/dx dNk/dx | // F(i,j) = summ ( dN[j, k] * U[k, i] ) where U = | ... | dN = | dN1/dy dN2/dy ... dNk/dy | // | xk yk zk | | dN1/dz dN2/dz dNk/dz | // MatrixST F = dN * dU; MatrixST BL1 = new MatrixST(6, 3 * NList.Count); for (int i = 0; i < NList.Count; i++) { for (int j = 0; j < 3; j++) { BL1.SetFast(0, 3 * i + j, F.GetFast(j, 0) * dN.GetFast(0, i)); BL1.SetFast(1, 3 * i + j, F.GetFast(j, 1) * dN.GetFast(1, i)); BL1.SetFast(2, 3 * i + j, F.GetFast(j, 2) * dN.GetFast(2, i)); BL1.SetFast(3, 3 * i + j, F.GetFast(j, 0) * dN.GetFast(1, i) + F.GetFast(j, 1) * dN.GetFast(0, i)); BL1.SetFast(4, 3 * i + j, F.GetFast(j, 1) * dN.GetFast(2, i) + F.GetFast(j, 2) * dN.GetFast(1, i)); BL1.SetFast(5, 3 * i + j, F.GetFast(j, 0) * dN.GetFast(2, i) + F.GetFast(j, 2) * dN.GetFast(0, i)); } } return(BL1); }
/// <summary> /// Multiply all element of this matrix by scalar s /// </summary> /// <returns> /// Matrix-Scalar product /// </returns> public MatrixST MultiplyScalar(double s) { MatrixST C = new MatrixST(Rows, Cols); for (int i = 0; i < Rows; i++) { for (int j = 0; j < Cols; j++) { C.SetFast(i, j, GetFast(i, j) * s); } } return(C); }
/// <returns> /// Transposition of this matrix /// </returns> public MatrixST Transpose() { MatrixST C = new MatrixST(Cols, Rows); for (int r = 0; r < Rows; r++) { for (int c = 0; c < Cols; c++) { C.SetFast(c, r, GetFast(r, c)); } } return(C); }
/// <summary> /// Calculate Tangent stiffness matrix /// </summary> public MatrixST K_Tangent(int inc, Database DB) { // Element Matrix Initialization MatrixST K = new MatrixST(NList.Count * 3, NList.Count * 3); // Loop thorugh all Gauss Points for (int g = 0; g < GaussPointNumb; g++) { // Jacobian Matrix at Gauss Point J[g] = Jacobian(DB.NodeLib, DB.FELib.FE[Type].dN_dLocal[g]); // Shape function derivatives in Global Coordinates System MatrixST dN = J[g].Inverse() * DB.FELib.FE[Type].dN_dLocal[g]; // ------ Linear strain-displacement matrix --------------------------------- // Initial displacement effect - BL1 Matrix MatrixST U = new MatrixST(NList.Count, 3); for (int i = 0; i < NList.Count; i++) { for (int j = 0; j < 3; j++) { U.SetFast(i, j, DB.NodeLib[NList[i]].GetDisp(inc, j)); } } BL[g] = BL0_Matrix(dN) + BL1_Matrix(dN, U); // BL = BL0 + BL1 // ------ Constitutive Matrix --------------------------------- MatrixST D = DB.MatLib[MatID].GetElastic(); // --- LINEAR PART OF STIFFNESS MATRIX ------------------------------------------- // Add K components to Element K matrix (sum from all Gauss points) K += (BL[g].Transpose() * D * BL[g]).MultiplyScalar(J[g].Det3() * DB.FELib.FE[Type].GaussWeight); // --- NONLINEAR PART OF STIFFNESS MATRIX ------------------------------------------------------------ // Nonlinear Strain-displacement matrix MatrixST BNL = BNL_Matrix(dN); // Initial Stress matrix MatrixST S = Stress_Matrix(inc, g); // Nonlinear part of Element Stiffness Matrix K += (BNL.Transpose() * S * BNL).MultiplyScalar(J[g].Det3() * DB.FELib.FE[Type].GaussWeight); } return(K); }
/// <summary> /// Get row of this matrix /// </summary> /// <returns> Row of this matrix as MatrixST with size 1 x ColumnNumber </returns> public MatrixST GetRow_MatrixST(int index) { if (index >= 0 && index < Rows) { MatrixST row = new MatrixST(1, Cols); for (int i = 0; i < Cols; i++) { row.SetFast(0, i, GetFast(index, i)); } return(row); } else { throw new System.ArgumentException("GetRow error: Matrix doesn't have specified row", "Index"); } }
public void SetElastic(double Young, double PoissonRatio) { // Set elastic properties E = Young; Poisson = PoissonRatio; // Calculate elastic D matrix ElasticMatrix = new MatrixST(6, 6); double lambda = (E * Poisson) / ((1 - 2 * Poisson) * (1 + Poisson)); double G = (0.5 * E) / (1 + Poisson); ElasticMatrix.SetFast(0, 0, lambda + (2 * G)); ElasticMatrix.SetFast(0, 1, lambda); ElasticMatrix.SetFast(0, 2, lambda); ElasticMatrix.SetFast(1, 0, lambda); ElasticMatrix.SetFast(1, 1, lambda + (2 * G)); ElasticMatrix.SetFast(1, 2, lambda); ElasticMatrix.SetFast(2, 0, lambda); ElasticMatrix.SetFast(2, 1, lambda); ElasticMatrix.SetFast(2, 2, lambda + (2 * G)); ElasticMatrix.SetFast(3, 3, G); ElasticMatrix.SetFast(4, 4, G); ElasticMatrix.SetFast(5, 5, G); }
/// <summary> /// Finite Element type: /// <br>Tetrahedral, 4 node, Isoparametric</br> /// <br><c>Gauss_Point</c> - Integration point natural coordinates {xi, eta, zeta}</br> /// </summary> /// <returns>Matrix with partial derivatives (natural) of shape functions in Gauss point /// <br></br></returns> private MatrixST TET4_Diff_ShapeFunctions() { // Input: Gauss_Point = { xi, eta, zeta} // | dN1/d_xi dN2/d_xi dN8/d_xi | // Output: dN_dLocal = | dN1/d_eta dN2/d_eta ... dN8/d_eta | // | dN1/d_zeta dN2/d_zeta dN8/d_zeta | // Shape function of TET4 element: // N1 = 1 - xi - eta - zeta // N2 = xi // N3 = eta // N4 = zeta // Initialize Matrix with shape function derivatives in local coordinate system MatrixST dN_dLocal = new MatrixST(3, 4); // dN/d_xi dN_dLocal.SetFast(0, 0, -1); dN_dLocal.SetFast(0, 1, 1); dN_dLocal.SetFast(0, 2, 0); dN_dLocal.SetFast(0, 3, 0); // dN/d_eta dN_dLocal.SetFast(1, 0, -1); dN_dLocal.SetFast(1, 1, 0); dN_dLocal.SetFast(1, 2, 1); dN_dLocal.SetFast(1, 3, 0); // dN/d_zeta dN_dLocal.SetFast(2, 0, -1); dN_dLocal.SetFast(2, 1, 0); dN_dLocal.SetFast(2, 2, 0); dN_dLocal.SetFast(2, 3, 1); return(dN_dLocal); }
/// <summary> /// Finite Element type: /// <br>Hexahedral, 8 node, Isoparametric</br> /// <br><c>Gauss_Point</c> - Integration point natural coordinates {xi, eta, zeta}</br> /// </summary> /// <returns>Matrix with partial derivatives (natural) of shape functions in Gauss point /// <br></br></returns> private MatrixST HEX8_Diff_ShapeFunctions(double[] Gauss_Point) { // Input: Gauss_Point = { xi, eta, zeta} // | dN1/d_xi dN2/d_xi dN8/d_xi | // Output: dN_dLocal = | dN1/d_eta dN2/d_eta ... dN8/d_eta | // | dN1/d_zeta dN2/d_zeta dN8/d_zeta | // Shape function of HEX8 element: // N1 = 1 / 8 * (1 - xi) * (1 - eta) * (1 - zeta) // N2 = 1 / 8 * (1 + xi) * (1 - eta) * (1 - zeta) // N3 = 1 / 8 * (1 + xi) * (1 + eta) * (1 - zeta) // N4 = 1 / 8 * (1 - xi) * (1 + eta) * (1 - zeta) // N5 = 1 / 8 * (1 - xi) * (1 - eta) * (1 + zeta) // N6 = 1 / 8 * (1 + xi) * (1 - eta) * (1 + zeta) // N7 = 1 / 8 * (1 + xi) * (1 + eta) * (1 + zeta) // N8 = 1 / 8 * (1 - xi) * (1 + eta) * (1 + zeta) // Table with signs: // // 1 xi eta zeta xi*eta eta*zeta xi*zeta xi*eta*zeta // N1 + - - - + + + - // N2 + + - - - + - + // N3 + + + - + - - - // N4 + - + - - - + + // N5 + - - + + - - + // N6 + + - + - - + - // N7 + + + + + + + + // N8 + - + + - + - - // Gauss point coordinates double xi = Gauss_Point[0]; double eta = Gauss_Point[1]; double zeta = Gauss_Point[2]; // Initialize Matrix with shape function derivatives in local coordinate system MatrixST dN_dLocal = new MatrixST(3, 8); // dN/d_xi dN_dLocal.SetFast(0, 0, 1.0 / 8.0 * (-1 + eta + zeta - eta * zeta)); dN_dLocal.SetFast(0, 1, 1.0 / 8.0 * (1 - eta - zeta + eta * zeta)); dN_dLocal.SetFast(0, 2, 1.0 / 8.0 * (1 + eta - zeta - eta * zeta)); dN_dLocal.SetFast(0, 3, 1.0 / 8.0 * (-1 - eta + zeta + eta * zeta)); dN_dLocal.SetFast(0, 4, 1.0 / 8.0 * (-1 + eta - zeta + eta * zeta)); dN_dLocal.SetFast(0, 5, 1.0 / 8.0 * (1 - eta + zeta - eta * zeta)); dN_dLocal.SetFast(0, 6, 1.0 / 8.0 * (1 + eta + zeta + eta * zeta)); dN_dLocal.SetFast(0, 7, 1.0 / 8.0 * (-1 - eta - zeta - eta * zeta)); // dN/d_eta dN_dLocal.SetFast(1, 0, 1.0 / 8.0 * (-1 + xi + zeta - xi * zeta)); dN_dLocal.SetFast(1, 1, 1.0 / 8.0 * (-1 - xi + zeta + xi * zeta)); dN_dLocal.SetFast(1, 2, 1.0 / 8.0 * (1 + xi - zeta - xi * zeta)); dN_dLocal.SetFast(1, 3, 1.0 / 8.0 * (1 - xi - zeta + xi * zeta)); dN_dLocal.SetFast(1, 4, 1.0 / 8.0 * (-1 + xi - zeta + xi * zeta)); dN_dLocal.SetFast(1, 5, 1.0 / 8.0 * (-1 - xi - zeta - xi * zeta)); dN_dLocal.SetFast(1, 6, 1.0 / 8.0 * (1 + xi + zeta + xi * zeta)); dN_dLocal.SetFast(1, 7, 1.0 / 8.0 * (1 - xi + zeta - xi * zeta)); // dN/d_zeta dN_dLocal.SetFast(2, 0, 1.0 / 8.0 * (-1 + xi + eta - xi * eta)); dN_dLocal.SetFast(2, 1, 1.0 / 8.0 * (-1 - xi + eta + xi * eta)); dN_dLocal.SetFast(2, 2, 1.0 / 8.0 * (-1 - xi - eta - xi * eta)); dN_dLocal.SetFast(2, 3, 1.0 / 8.0 * (-1 + xi - eta + xi * eta)); dN_dLocal.SetFast(2, 4, 1.0 / 8.0 * (1 - xi - eta + xi * eta)); dN_dLocal.SetFast(2, 5, 1.0 / 8.0 * (1 + xi - eta - xi * eta)); dN_dLocal.SetFast(2, 6, 1.0 / 8.0 * (1 + xi + eta + xi * eta)); dN_dLocal.SetFast(2, 7, 1.0 / 8.0 * (1 - xi + eta - xi * eta)); return(dN_dLocal); }