Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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");
            }
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
 public void Compute_NodalForces(Database DB)
 {
     NodalForces = new MatrixST(3 * NList.Count, 1);
     for (int g = 0; g < GaussPointNumb; g++)
     {
         NodalForces += (BL[g].Transpose() * dS[g]).MultiplyScalar(J[g].Det3() * DB.FELib.FE[Type].GaussWeight);
     }
 }
Пример #7
0
        /// <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);
            }
        }
Пример #8
0
        public double[] Tensor2Vector(MatrixST T)
        {
            double[] v = new double[6];
            v[0] = T.GetFast(0, 0);
            v[1] = T.GetFast(1, 1);
            v[2] = T.GetFast(2, 2);
            v[3] = T.GetFast(0, 1);
            v[4] = T.GetFast(1, 2);
            v[5] = T.GetFast(0, 2);

            return(v);
        }
Пример #9
0
        /// <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);
        }
Пример #10
0
        /// <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);
        }
Пример #11
0
        /// <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);
        }
Пример #12
0
 /// <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");
     }
 }
Пример #13
0
        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);
        }
Пример #14
0
        //  ==================== 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);
        }
Пример #15
0
        /// <summary>
        /// Subtraction operator ( A - B )
        /// </summary>
        /// <returns>Difference of matrices A and B. First matrix provides the size.
        /// <br>If size B is bigger than size A: only common indices subtracted</br>
        /// <br>Size of B cannot be smaller than size of A !!!</br></returns>
        public static MatrixST operator -(MatrixST A, MatrixST B)
        {
            MatrixST C = new MatrixST(A.Rows, A.Cols);

            if (B.Rows >= A.Rows && B.Cols >= A.Cols)
            {
                for (int i = 0; i < A.Rows; i++)
                {
                    for (int j = 0; j < A.Cols; j++)
                    {
                        C.AddFast(i, j, A.GetFast(i, j) - B.GetFast(i, j));
                    }
                }
                return(C);
            }
            else
            {
                throw new System.ArgumentException("Subtraction error: B smaller than A", "Size");
            }
        }
Пример #16
0
        /// <summary>
        /// Strain and Stress initialization required at the begining of new increment
        /// </summary>
        public void Initialize_Increment(int inc)
        {
            // Assign Stress and Strain from last increment
            //Strain.Add(Strain[inc-1]);
            //Stress.Add(Stress[inc-1]);
            Strain.Add(new MatrixST(NList.Count, 6));
            Stress.Add(new MatrixST(NList.Count, 6));

            // Reset Stress and Strain increments
            dE = new MatrixST[NList.Count];
            dS = new MatrixST[NList.Count];

            for (int i = 0; i < NList.Count; i++)
            {
                dE[i] = new MatrixST(6, 1);  // Vector 6x1 in each Gauss Point
                dS[i] = new MatrixST(6, 1);  // Vector 6x1 in each Gauss Point
            }

            // Reset solver buffors
            J  = new MatrixST[GaussPointNumb];
            BL = new MatrixST[GaussPointNumb];
        }
Пример #17
0
        /// <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);
        }
Пример #18
0
        // ----- OPERATORS -----------------------------------------------------------------

        /// <summary>
        /// Matrix multiplication operator
        /// <para>Returns zero matrix if sizes of matrices don't match.</para>
        /// </summary>
        public static MatrixST operator *(MatrixST A, MatrixST B)
        {
            MatrixST C = new MatrixST(A.Rows, B.Cols);

            if (A.Cols == B.Rows)
            {
                for (int i = 0; i < A.Rows; i++)
                {
                    for (int j = 0; j < B.Cols; j++)
                    {
                        for (int k = 0; k < A.Cols; k++)
                        {
                            C.AddFast(i, j, A.GetFast(i, k) * B.GetFast(k, j));
                        }
                    }
                }

                return(C);
            }
            else
            {
                throw new System.ArgumentException("Multiplication error: A cols not equal to B rows", "Size");
            }
        }
Пример #19
0
        public void Recovery_Stress(Database DB)
        {
            // Nodal dU vector
            double[] dU = new double[NList.Count * 3];
            for (int i = 0; i < NList.Count; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    dU[i * 3 + j] = DB.NodeLib[NList[i]].dU_buffer[j];
                }
            }

            // Constitutive Matrix
            MatrixST D = DB.MatLib[MatID].GetElastic();

            // Loop thorugh all Gauss Points
            MatrixST dE_Gauss = new MatrixST(GaussPointNumb, 6);  // Matrix to store strain in Gauss Points
            MatrixST dS_Gauss = new MatrixST(GaussPointNumb, 6);  // Matrix to store stress in Gauss Points

            for (int g = 0; g < GaussPointNumb; g++)
            {
                // Add Stress and Strain vectors
                dE_Gauss.SetRow(g, BL[g].MultiplyVector(dU));
                dS_Gauss.SetRow(g, D.MultiplyVector(dE_Gauss.GetRow(g)));
            }

            // Extrapolate Stress and Strain from Gauss Points to Nodes
            for (int i = 0; i < NList.Count; i++)
            {
                for (int g = 0; g < GaussPointNumb; g++)
                {
                    dE[i] += dE_Gauss.GetRow_MatrixST(g).Transpose().MultiplyScalar(DB.FELib.FE[Type].N[i][g]);
                    dS[i] += dS_Gauss.GetRow_MatrixST(g).Transpose().MultiplyScalar(DB.FELib.FE[Type].N[i][g]);
                }
            }
        }
Пример #20
0
        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);
        }
Пример #21
0
        /// <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);
        }