element.h

00001 /*************************************************************************************
00002  * MechSys - A C++ library to simulate (Continuum) Mechanical Systems                *
00003  * Copyright (C) 2005 Dorival de Moraes Pedroso <dorival.pedroso at gmail.com>       *
00004  * Copyright (C) 2005 Raul Dario Durand Farfan  <raul.durand at gmail.com>           *
00005  *                                                                                   *
00006  * This file is part of MechSys.                                                     *
00007  *                                                                                   *
00008  * MechSys is free software; you can redistribute it and/or modify it under the      *
00009  * terms of the GNU General Public License as published by the Free Software         *
00010  * Foundation; either version 2 of the License, or (at your option) any later        *
00011  * version.                                                                          *
00012  *                                                                                   *
00013  * MechSys is distributed in the hope that it will be useful, but WITHOUT ANY        *
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A   *
00015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.          *
00016  *                                                                                   *
00017  * You should have received a copy of the GNU General Public License along with      *
00018  * MechSys; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
00019  * Fifth Floor, Boston, MA 02110-1301, USA                                           *
00020  *************************************************************************************/
00021 
00022 #ifndef MECHSYS_FEM_ELEMENT_H
00023 #define MECHSYS_FEM_ELEMENT_H
00024 
00025 #ifdef HAVE_CONFIG_H
00026   #include "config.h"
00027 #else
00028   #ifndef REAL
00029     #define REAL double
00030   #endif
00031 #endif
00032 
00033 #include <map>
00034 
00035 #include "util/string.h"
00036 #include "fem/node.h"
00037 #include "linalg/vector.h"
00038 #include "linalg/matrix.h"
00039 #include "linalg/lawrap.h"
00040 #include "linalg/laexpr.h"
00041 
00042 namespace FEM
00043 {
00044 
00046 class Element
00047 {
00048 public:
00049     // Destructor
00050     virtual ~Element() {}
00051     // Auxiliar structure
00052     struct IntegPoint
00053     {
00054         REAL r; 
00055         REAL s; 
00056         REAL t; 
00057         REAL w; 
00058     };
00059     int Number; //auxiliar variable
00060     virtual String Name() const=0;
00061     // Local methods
00062     void SetNode(int iNode, FEM::Node * ptrNode); // Copy a pointer of node iNode to the internal connects array
00063     // Virtual methods
00064     virtual bool IsEssential(String const & DOFName) const =0;
00065     virtual void CalcFaceNodalValues(String            const & FaceDOFName  , // In:  Face DOF Name, ex.: "tx, ty, tz"
00066                                      REAL              const   FaceDOFValue , // In:  Face DOF Value, ex.: 10 kPa, 20 kPa
00067                                      Array<FEM::Node*> const & APtrFaceNodes, // In:  Array of ptrs to face nodes
00068                                      String                  & NodalDOFName , // Out: Nodal DOF Name, ex.: "fx, fy, fz"
00069                                      LinAlg::Vector<REAL>    & NodalValues    // Out: Vector of nodal values
00070     ) const =0;
00071     virtual void ReAllocateModel(String      const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData) =0;
00072     void Activate()   { _is_active = true; }
00073     virtual void Deactivate() { _is_active = false; }
00074     virtual int  VTKCellType() const =0;
00075 
00076     bool     IsActive() const { return _is_active; }
00077     int        nNodes() const { return _n_nodes;   }
00078     size_t nIntPoints() const { return _n_int_pts; }
00079 
00080     // Create a structure to hold the DOFs information of Node [j_node] inside Element [i_ele]
00081     // These DOFs are the only ones that Element [i_ele] uses => NOT the global ones
00082     virtual void NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const =0;
00083     Array<Node*> const & Connects() const; // Return ana array containing pointers to nodes
00084             void IntegPoints(IntegPoint const * & IPs) const { IPs = _a_int_pts; }; // Return a pointer to the array of integration points
00085     virtual void BackupState() =0;
00086     virtual void UpdateState(REAL TimeInc=0) =0; // Read nodal values _IncEssential and write to _IncNatural
00087     virtual void RestoreState() =0;
00088 
00089     virtual void SetProperties(Array<REAL> const & EleProps) =0;
00090 
00091     virtual String OutCenter(bool PrintCaptionOnly=false) const =0;
00092     virtual void    OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const { };
00093     virtual void       Shape(REAL r, REAL s, REAL t, LinAlg::Vector<REAL> & Shape) const =0;
00094     virtual void      Derivs(REAL r, REAL s, REAL t, LinAlg::Matrix<REAL> & Derivs) const =0;
00095     virtual void    Jacobian(REAL r, REAL s, REAL t, LinAlg::Matrix<REAL> & J) const;
00096     virtual void    Jacobian(LinAlg::Matrix<REAL> const & derivs, LinAlg::Matrix<REAL> & J) const;
00097     virtual void      Coords(LinAlg::Matrix<REAL> & coords) const;
00098     virtual void   InverseMap(REAL x, REAL y, REAL z, REAL & r, REAL & s, REAL & t) const;
00099             bool   IsInside(REAL x, REAL y, REAL z) const;
00100     virtual REAL   BoundDistance(REAL r, REAL s, REAL t) const { return -1; };
00101 
00102     // Functions to assemble DAS matrices
00103     virtual size_t nOrder0Matrices() const { return 0; };
00104     virtual size_t nOrder1Matrices() const { return 0; };
00105     virtual void      RHSVector(size_t index, LinAlg::Vector<REAL> & V, Array<size_t> &     Map) const { };
00106     virtual void   Order0Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const { };
00107     virtual void   Order1Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const { };
00108     
00109     // Output Scalars and Tensors
00110     virtual REAL OutScalar1 ()             const { return 0;                               }; // to be overriden.  for example, Pore-pressure
00111     virtual REAL OutScalar2 ()             const { return 0;                               }; // to be overriden.  for example, Ed
00112     virtual void OutTensor1 (String & Str) const { Str.Printf(_(" 0 0 0  0 0 0  0 0 0 ")); }; // to be overriden.  for example, Stress
00113     virtual void OutTensor2 (String & Str) const { Str.Printf(_(" 0 0 0  0 0 0  0 0 0 ")); }; // to be overriden.  for example, Strain
00114     virtual void OutTensor3 (String & Str) const { Str.Printf(_(" 0 0 0  0 0 0  0 0 0 ")); }; // to be overriden.  for example, Plastic Strain
00115 protected:
00116     // Data
00117     int           _n_nodes;
00118     int           _n_int_pts;
00119     int           _n_face_nodes;   // Number of nodes of a face
00120     int           _n_face_int_pts; // Number of integ points of a a face
00121     Array<Node*>  _connects;       // Connectivity (ptr to nodes of this element). size=_n_nodes
00122     bool          _is_active;      // Flag for active/inactive condition
00123     IntegPoint const * _a_int_pts; // Array of Integration Points
00124     // Methods
00125     virtual void _set_node_vars(int iNode)=0; // Setup nodal variables (dx,dy, etc.) for node [iNode]
00126     virtual void _face_shape(REAL r, REAL s, LinAlg::Vector<REAL> & AFaceShape) const =0;
00127     void         _face_jacobian(Array<FEM::Node*> const & FaceConnects, REAL const r, REAL const s, LinAlg::Matrix<REAL> & J) const;
00128     virtual void _distrib_val_to_face_nodal_vals(Array<Node*>         const & FaceConnects, // In:  Array of ptrs to face nodes
00129                                                   REAL                const   FaceValue   , // In:  A value applied on a face to be converted to nodes
00130                                                   LinAlg::Vector<REAL>      & NodalValues   // Out: The resultant nodal values
00131     ) const =0;
00132     virtual void _face_derivs(REAL r, REAL s,         LinAlg::Matrix<REAL> & AFaceDerivs) const =0;
00133     virtual void _extrapolate(LinAlg::Vector<REAL> & IPValues, LinAlg::Vector<REAL> & NodalValues) const;
00134 }; // class Element
00135 
00136 
00138 
00139 
00140 inline void Element::SetNode(int iNode, FEM::Node * ptrNode) // {{{
00141 {
00142     // Check
00143     if (_connects.size()<=0)                       throw new Fatal(_("Element::SetNode: _connects.size (=%d) must be greater than zero iNode=%d"),iNode,_connects.size());
00144     if (iNode<0)                                   throw new Fatal(_("Element::SetNode: iNode (=%d) must be greater than or equal to zero"),iNode);
00145     if (iNode>=static_cast<int>(_connects.size())) throw new Fatal(_("Element::SetNode: iNode (=%d) must be smaller than _connects.size (=%d)"),iNode,_connects.size());
00146     if (ptrNode==NULL)                             throw new Fatal(_("Element::SetNode: ptrNode is NULL! (iNode=%d)"),iNode);
00147 
00148     // Connects
00149     _connects[iNode] = ptrNode;
00150 
00151     // Nodal vars
00152     _set_node_vars(iNode);
00153 }
00154 
00155 // }}}
00156 
00157 inline Array<Node*> const & Element::Connects() const // {{{
00158 {
00159     return _connects;
00160 } // }}}
00161 
00162 void Element::InverseMap(REAL x, REAL y, REAL z, REAL & r, REAL & s, REAL & t) const //{{{
00163 {
00164     LinAlg::Vector<REAL> shape;
00165     LinAlg::Matrix<REAL> derivs;
00166     LinAlg::Matrix<REAL> J; //Jacobian matrix
00167     //LinAlg::Matrix<REAL> inv_jacobian;
00168     //LinAlg::Matrix<REAL> trn_inv_jacobian;
00169     LinAlg::Vector<REAL> f(3);
00170     LinAlg::Vector<REAL> delta(3);
00171     REAL tx, ty, tz; //x, y, z trial
00172     REAL norm_f;
00173     r = s = t =0; // first suposition for natural coordinates
00174     int k=0;
00175     do
00176     {
00177         k++;
00178         Shape (r, s, t, shape);
00179         Derivs(r, s, t, derivs);
00180         Jacobian(derivs, J);
00181         tx = ty = tz = 0; 
00182         //calculate trial of real coordinates
00183         for (int j=0; j<_n_nodes; j++) 
00184         {
00185             tx += shape(j)*_connects[j]->X(); //ok
00186             ty += shape(j)*_connects[j]->Y(); //ok
00187             tz += shape(j)*_connects[j]->Z(); //ok
00188         }
00189         
00190         // calculate the error
00191         f(0) = tx - x;
00192         f(1) = ty - y;
00193         f(2) = tz - z;
00194         
00195         //jacobian.Inv(inv_jacobian);
00196         //inv_jacobian.Trn(trn_inv_jacobian);
00197         delta = trn(inv(J))*f;
00198         //Gemv(1.0, trn_inv_jacobian, f, 0.0, delta);
00199         
00200         r -= delta(0);
00201         s -= delta(1);
00202         t -= delta(2);
00203 
00204         //norm_f = sqrt(f(0)*f(0)+f(1)*f(1)+f(2)*f(2));
00205         norm_f = sqrt(trn(f)*f);
00206         if (k>25) break;
00207     } while(norm_f>1e-4);
00208 } 
00209 
00210 bool Element::IsInside(REAL x, REAL y, REAL z) const //{{{
00211 {
00212     REAL tiny = 1e-4;
00213     REAL huge = 1e+20;
00214     REAL max, min;
00215     
00216     //fast search in X -----------------------------------------------------------------------
00217     max = -huge;
00218     for (int i=0; i < nNodes(); i++) if (_connects[i]->X() > max) max=_connects[i]->X();
00219     if ( x > max ) return false;
00220     min = +huge;
00221     for (int i=0; i < nNodes(); i++) if (_connects[i]->X() < min) min=_connects[i]->X();
00222     if ( x < min ) return false;
00223 
00224     //fast search in Y -----------------------------------------------------------------------
00225     max = -huge;
00226     for (int i=0; i < nNodes(); i++) if (_connects[i]->Y() > max) max=_connects[i]->Y();
00227     if ( y > max ) return false;
00228     min = +huge;
00229     for (int i=0; i < nNodes(); i++) if (_connects[i]->Y() < min) min=_connects[i]->Y();
00230     if ( y < min ) return false;
00231     
00232     //fast search in Z -----------------------------------------------------------------------
00233     max = -huge;
00234     for (int i=0; i < nNodes(); i++) if (_connects[i]->Z() > max) max=_connects[i]->Z();
00235     if ( z > max ) return false;
00236     min = +huge;
00237     for (int i=0; i < nNodes(); i++) if (_connects[i]->Z() < min) min=_connects[i]->Z();
00238     if ( z < min ) return false;
00239     
00240     REAL r, s, t;
00241     InverseMap(x,y,z,r,s,t);
00242     if (BoundDistance(r,s,t)>-tiny) return true;
00243     else return false;
00244 } // }}}
00245 
00246 inline void Element::_face_jacobian(Array<FEM::Node*> const & FaceConnects, REAL const r, REAL const s, LinAlg::Matrix<REAL> & J) const // {{{
00247 {
00248     // Calculate the shape function derivatives for a face
00249     LinAlg::Matrix<REAL> m_face_derivs;
00250     _face_derivs(r, s, m_face_derivs);
00251 
00252     // Get the face coordinates
00253     LinAlg::Matrix<REAL> m_face_coords(_n_face_nodes,3);
00254     for (int i=0; i<_n_face_nodes; i++)
00255     {
00256         m_face_coords(i,0) = FaceConnects[i]->X();
00257         m_face_coords(i,1) = FaceConnects[i]->Y();
00258         m_face_coords(i,2) = FaceConnects[i]->Z();
00259     }
00260 
00261     // Determine face jacobian
00262     J.Resize(2,3);
00263     //LinAlg::Gemm(1, m_face_derivs, m_face_coords, 0, J);
00264     J = m_face_derivs*m_face_coords;
00265 } // }}}
00266 
00267 inline void Element::Coords(LinAlg::Matrix<REAL> & coords) const // {{{
00268 {
00269     // Calculate a matrix with nodal coordinates
00270     coords.Resize(_n_nodes,3);   // 3 => X,Y,Z (all nodes have X,Y and Z)
00271 
00272     // Loop along all nodes of this element
00273     for (int i=0; i<_n_nodes; i++)
00274     {
00275         coords(i,0) = _connects[i]->X();
00276         coords(i,1) = _connects[i]->Y();
00277         coords(i,2) = _connects[i]->Z();
00278     }
00279 } // }}}
00280 
00281 inline void Element::Jacobian(LinAlg::Matrix<REAL> const & derivs, LinAlg::Matrix<REAL> & J) const // {{{
00282 {
00283     // Calculate a matrix with nodal coordinates
00284     LinAlg::Matrix<REAL> cmatrix; // size = _n_nodes x 3
00285     cmatrix.Resize(_n_nodes,3);   // 3 => X,Y,Z (all nodes have X,Y and Z)
00286 
00287     // Loop along all nodes of this element
00288     for (int i=0; i<_n_nodes; i++)
00289     {
00290         cmatrix(i,0) = _connects[i]->X();
00291         cmatrix(i,1) = _connects[i]->Y();
00292         cmatrix(i,2) = _connects[i]->Z();
00293     }
00294 
00295     // Calculate the Jacobian; Size = NumLocalCoords x 3
00296     J = derivs * cmatrix;
00297 } // }}}
00298 
00299 inline void Element::Jacobian(REAL r, REAL s, REAL t, LinAlg::Matrix<REAL> & J) const // {{{
00300 {
00301     LinAlg::Matrix<REAL> derivs; Derivs(r, s, t, derivs);
00302     LinAlg::Matrix<REAL> coords; Coords(coords);
00303     J = derivs*coords;
00304 } // }}}
00305 
00306 void Element::_extrapolate(LinAlg::Vector<REAL> & IPValues, LinAlg::Vector<REAL> & NodalValues) const  // {{{
00307 {
00308     //Extrapolation:
00309     //                  IPValues = E * NodalValues;
00310     //  where:
00311     //                              t           t
00312     //                         E = N * inv(N * N )
00313     //
00314     //  and            N = [shape functions matrix]
00315     //                        1     2       ...     nNodes
00316     //                 1    [[N_11 N_12
00317     //                 2     [N_21
00318     //                 :     [
00319     //                nIP    [N_ ...                    ]]
00320 
00321     LinAlg::Matrix<REAL> N(_n_int_pts, _n_nodes);  // matrix of all IP shape functions
00322     LinAlg::Matrix<REAL> E(_n_nodes, _n_int_pts);  // Extrapolator matrix
00323     LinAlg::Vector<REAL> shape(_n_nodes);
00324     
00325     //filling N matrix
00326     for (int i_ip=0; i_ip<_n_int_pts; i_ip++)
00327     {
00328         REAL r = _a_int_pts[i_ip].r;
00329         REAL s = _a_int_pts[i_ip].s;
00330         REAL t = _a_int_pts[i_ip].t;
00331         Shape(r, s, t, shape);
00332         for (int j_node=0; j_node<_n_nodes; j_node++)
00333             N(i_ip, j_node) = shape(j_node);
00334     }
00335 
00336     //calculate extrapolator matrix
00337     assert(_n_nodes>=_n_int_pts); // TODO: replace with trow
00338     E = trn(N)*inv(N*trn(N));
00339 
00340     //perform extrapolation
00341     NodalValues = E*IPValues;
00342     
00343 }; 
00344 
00346 
00347 
00348 // Define a pointer to a function that makes (allocate) a new element
00349 typedef Element * (*ElementMakerPtr)();
00350 
00351 // Typdef of the array map that contains all the pointers to the functions that makes elements
00352 typedef std::map<String, ElementMakerPtr, std::less<String> > ElementFactory_t;
00353 
00354 // Instantiate the array map that contains all the pointers to the functions that makes elements
00355 ElementFactory_t ElementFactory;
00356 
00357 // Allocate a new element according to a string giving the name of the element
00358 Element * AllocElement(String const & ElementName) // {{{
00359 {
00360     ElementMakerPtr ptr=NULL;
00361     ptr = ElementFactory[ElementName];
00362     if (ptr==NULL)
00363         throw new Fatal(_("FEM::AllocElement: There is no < %s > implemented in this library"), ElementName.c_str());
00364     return (*ptr)();
00365 } // }}}
00366 
00367 }; // namespace FEM
00368 
00369 
00371 
00372 
00373 // Define a structure to contain dof information from derivate elements
00374 struct DOFInfo
00375 {
00376     Array<String> NodeEssential;
00377     Array<String> NodeNatural;
00378     Array<String> FaceEssential;
00379     Array<String> FaceNatural;
00380 };
00381 
00382 // Typdef of the map that contains all dof info from problem type elements
00383 typedef std::map<String, DOFInfo, std::less<String> > DOFInfoMap_t;
00384 
00385 // Instantiate the map that contains all dof info from problem type elements
00386 DOFInfoMap_t DOFInfoMap;
00387 
00388 #endif // MECHSYS_FEM_ELEMENT
00389 
00390 // vim:fdm=marker

Generated on Wed Jan 24 15:56:25 2007 for MechSys by  doxygen 1.4.7