MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/fem/node.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand                   *
00004  * Copyright (C) 2009 Sergio Galindo                                    *
00005  *                                                                      *
00006  * This program is free software: you can redistribute it and/or modify *
00007  * it under the terms of the GNU General Public License as published by *
00008  * the Free Software Foundation, either version 3 of the License, or    *
00009  * any later version.                                                   *
00010  *                                                                      *
00011  * This program is distributed in the hope that it will be useful,      *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00014  * GNU General Public License for more details.                         *
00015  *                                                                      *
00016  * You should have received a copy of the GNU General Public License    *
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00018  ************************************************************************/
00019 
00020 #ifndef MECHSYS_FEM_NODE_H
00021 #define MECHSYS_FEM_NODE_H
00022 
00023 // Std Lib
00024 #include <sstream> // for istringstream, ostringstream
00025 #include <map>
00026 
00027 // MechSys
00028 #include <mechsys/mesh/mesh.h>
00029 #include <mechsys/util/maps.h>
00030 #include <mechsys/util/fatal.h>
00031 #include <mechsys/util/numstreams.h>
00032 #include <mechsys/linalg/matvec.h>
00033 #include <mechsys/linalg/sparse_triplet.h>
00034 
00035 namespace FEM
00036 {
00037 
00039 class BCFuncs
00040 {
00041 public:
00042     virtual ~BCFuncs () {}
00043     virtual double u  (double Time) { return 0; } 
00044     virtual double v  (double Time) { return 0; } 
00045     virtual double a  (double Time) { return 0; } 
00046     virtual double fm (double Time) { return 0; } 
00047 };
00048 
00049 class Node
00050 {
00051 public:
00052     // Constructor
00053     Node (Mesh::Vertex const & TheVert) : Vert(TheVert), NShares(0), _has_incsup(false) {}
00054 
00055     // Methods
00056     void           AddDOF  (char const * StrU, char const * StrF);                      
00057     size_t         NDOF    ()                      const { return _eq.Size();         } 
00058     double         U       (char   const * UKey  ) const { return _U(UKey);           } 
00059     double         F       (char   const * FKey  ) const { return _F(FKey);           } 
00060     double       & U       (String const & UKey  )       { return _U(UKey);           } 
00061     double       & F       (String const & FKey  )       { return _F(FKey);           } 
00062     double       & U       (char   const * UKey  )       { return _U(UKey);           } 
00063     double       & F       (char   const * FKey  )       { return _F(FKey);           } 
00064     double       & V       (size_t         IdxDOF)       { return _V(UKey(IdxDOF));   } 
00065     double       & U       (size_t         IdxDOF)       { return _U(UKey(IdxDOF));   } 
00066     double       & F       (size_t         IdxDOF)       { return _F(FKey(IdxDOF));   } 
00067     double         UOrZero (String const & UKey  ) const { return _U.ValOrZero(UKey); } 
00068     double         VOrZero (String const & UKey  ) const { return _V.ValOrZero(UKey); } 
00069     double         FOrZero (String const & FKey  ) const { return _F.ValOrZero(FKey); } 
00070     void           TrySetU (String const & UKey, double Val) { if (_U.HasKey(UKey)) _U(UKey)=Val; } 
00071     void           TrySetF (String const & FKey, double Val) { if (_F.HasKey(FKey)) _F(FKey)=Val; } 
00072     int            Eq      (char   const * UKey  ) const { return _eq[_U2IDOF(UKey)]; } 
00073     int            Eq      (String const & UKey  ) const { return _eq[_U2IDOF(UKey)]; } 
00074     int            Eq      (size_t         IdxDOF) const { return _eq[IdxDOF];        } 
00075     int          & Eq      (size_t         IdxDOF)       { return _eq[IdxDOF];        } 
00076     String const & UKey    (size_t         IdxDOF) const { return _U.Keys[IdxDOF];    } 
00077     String const & FKey    (size_t         IdxDOF) const { return _F.Keys[IdxDOF];    } 
00078     bool           pU      (size_t         IdxDOF) const { return _pU[IdxDOF];        } 
00079     void           SetUF   (Vec_t const & UVec, Vec_t const & FVec);                    
00080     void           SetUVF  (Vec_t const & UVec, Vec_t const & VVec, Vec_t const & FVec);
00081     void           GetUF   (Vec_t       & UVec, Vec_t       & FVec);                    
00082     void           Clear   ();                                                          
00083     void           ClearU  () { _U.SetValues (0.0); }                                   
00084 
00085     // Methods to set/access prescribed U values
00086     void           SetPU     (String const & UKey, double Val, BCFuncs * BCF=NULL);                      
00087     void           SetMPU    (size_t IdxPU, BCFuncs * BCF=NULL){ _MPU[IdxPU] = BCF; }                    
00088     size_t         NPU       ()                          const { return _PU.Keys.Size(); }               
00089     int            EqPU      (size_t IdxPU)              const { return _eq[_U2IDOF(_PU.Keys[IdxPU])]; } 
00090     void           DelPUs    ()                                { _PU.clear(); _MPU.Resize(0); }          
00091     String const & PUKey     (size_t IdxPU)              const { return _PU.Keys[IdxPU]; }               
00092     double         PU        (size_t IdxPU, double Time) const;                                          
00093     double         PV        (size_t IdxPU, double Time) const;                                          
00094     double         PA        (size_t IdxPU, double Time) const;                                          
00095     double         PUIdxDOF  (size_t IdxDOF, double Time) const { return PU(_PU.IdxKey(UKey(IdxDOF)),Time); } 
00096     double         PVIdxDOF  (size_t IdxDOF, double Time) const { return PV(_PU.IdxKey(UKey(IdxDOF)),Time); } 
00097     double         PAIdxDOF  (size_t IdxDOF, double Time) const { return PA(_PU.IdxKey(UKey(IdxDOF)),Time); } 
00098 
00099     // Methods to set/access prescribed F values
00100     void           AddToPF   (String const & FKey, double Val, BCFuncs * BCF=NULL);                      
00101     void           SetMPF    (size_t IdxPF, BCFuncs * BCF=NULL){ _MPF[IdxPF] = BCF; }                    
00102     size_t         NPF       ()                          const { return _PF.Keys.Size(); }               
00103     int            EqPF      (size_t IdxPF)              const { return _eq[_F2IDOF(_PF.Keys[IdxPF])]; } 
00104     void           DelPFs    ()                                { _PF.clear(); _MPF.Resize(0); }          
00105     String const & PFKey     (size_t IdxPF)              const { return _PF.Keys[IdxPF]; }               
00106     double         PF        (size_t IdxPF, double Time) const;                                          
00107     double         PFOrZero  (size_t IdxDOF, double Time) const { int idxpf=_PF.IdxKey(FKey(IdxDOF)); return (idxpf<0 ? 0.0 : PF(idxpf,Time)); } 
00108     void           AccumPF   ();                                                                         
00109     void           Reactions (std::map<String,double> & R) const;                                        
00110 
00111     // Pins
00112     void SetPin    (Array<Node*> const & ConnectedNodes) { _pin_nodes=ConnectedNodes; } 
00113     void SetLagPin (int & EqLag, Sparse::Triplet<double,int> & A) const;                
00114     void ClrRPin   (int & EqLag, Vec_t & R)                       const;                
00115 
00116     // Inclined supports: 2D
00117     void SetIncSup    (double Alpha);                                            
00118     void DelIncSup    ()             { _has_incsup=false; }                      
00119     bool HasIncSup    () const       { return _has_incsup; }                     
00120     void SetLagIncSup (int & EqLag, Sparse::Triplet<double,int> & A) const;      
00121     void ClrRIncSup   (int & EqLag, Vec_t & R)                       const;      
00122 
00123     // Data
00124     Mesh::Vertex const & Vert;    
00125     long                 NShares; 
00126 
00127 private:
00128     // Data at every node
00129     SDPair     _V;      
00130     SDPair     _U;      
00131     SDPair     _F;      
00132     SIPair     _U2IDOF; 
00133     SIPair     _F2IDOF; 
00134     Array<int> _eq;     
00135     Array<bool> _pU;    
00136 
00137     // Data at nodes with prescribed values
00138     SDPair          _PU;  
00139     SDPair          _PF;  
00140     SDPair          _aPF; 
00141     Array<BCFuncs*> _MPU; 
00142     Array<BCFuncs*> _MPF; 
00143 
00144     // Data for pins
00145     Array<Node*> _pin_nodes; 
00146 
00147     // Data at nodes with inclined supports
00148     double _incsup_alpha; 
00149     bool   _has_incsup;   
00150 
00151 friend std::ostream & operator<< (std::ostream & os, Node const & N);
00152 };
00153 
00154 
00156 
00157 
00158 inline void Node::AddDOF (char const * StrU, char const * StrF)
00159 {
00160     std::istringstream u_iss(StrU);
00161     std::istringstream f_iss(StrF);
00162     String u_key, f_key;
00163     while ((u_iss>>u_key) && (f_iss>>f_key))
00164     {
00165         if (!_U.HasKey(u_key)) // add only if not found
00166         {
00167             _V.Set      (u_key.CStr(), 0.0);
00168             _U.Set      (u_key.CStr(), 0.0);
00169             _F.Set      (f_key.CStr(), 0.0);
00170             _U2IDOF.Set (u_key.CStr(), _eq.Size());
00171             _F2IDOF.Set (f_key.CStr(), _eq.Size());
00172             _eq.Push    (-1);
00173             _pU.Push    (false);
00174         }
00175         else
00176         {
00177             if (!_F.HasKey(f_key)) throw new Fatal("FEM::Node: __internal_error__ Node has UKey=%s but not FKey=%s",u_key.CStr(),f_key.CStr());
00178         }
00179     }
00180 }
00181 
00182 inline void Node::Clear ()
00183 {
00184     _U .SetValues (0.0);
00185     _V .SetValues (0.0);
00186     _F .SetValues (0.0);
00187     _eq.SetValues (-1);
00188     _pU.SetValues (false);
00189     DelPUs ();
00190     DelPFs ();
00191     _has_incsup = false;
00192 }
00193 
00194 inline void Node::SetUF (Vec_t const & UVec, Vec_t const & FVec)
00195 {
00196     for (size_t idof=0; idof<NDOF(); ++idof)
00197     {
00198         int eq = Eq(idof);
00199         _U(UKey(idof)) = UVec(eq);
00200         _F(FKey(idof)) = FVec(eq);
00201     }
00202 }
00203 
00204 inline void Node::SetUVF (Vec_t const & UVec, Vec_t const & VVec, Vec_t const & FVec)
00205 {
00206     for (size_t idof=0; idof<NDOF(); ++idof)
00207     {
00208         int eq = Eq(idof);
00209         _U(UKey(idof)) = UVec(eq);
00210         _V(UKey(idof)) = VVec(eq);
00211         _F(FKey(idof)) = FVec(eq);
00212     }
00213 }
00214 
00215 inline void Node::GetUF (Vec_t & UVec, Vec_t & FVec)
00216 {
00217     for (size_t idof=0; idof<NDOF(); ++idof)
00218     {
00219         int eq = Eq(idof);
00220         UVec(eq) = _U(UKey(idof));
00221         FVec(eq) = _F(FKey(idof));
00222     }
00223 }
00224 
00225 inline void Node::SetPU (String const & UKey, double Val, BCFuncs * BCF)
00226 {
00227     size_t idx_pu = _PU.ReSet (UKey.CStr(), Val);
00228     if (idx_pu==_MPU.Size()) _MPU.Push (BCF);
00229     else                     _MPU[idx_pu] = BCF;
00230     _has_incsup = false;
00231     _pU[_U2IDOF(UKey)] = true;
00232 }
00233 
00234 inline void Node::AddToPF (String const & FKey, double Val, BCFuncs * BCF)
00235 {
00236     size_t idx_pf = _PF.AddVal (FKey.CStr(), Val);
00237     if (idx_pf==_MPF.Size()) _MPF.Push (BCF);
00238     else                     _MPF[idx_pf] = BCF;
00239 }
00240 
00241 inline double Node::PU (size_t IdxPU, double Time) const
00242 {
00243     if (_MPU[IdxPU]==NULL) return _PU(_PU.Keys[IdxPU]);
00244     else                   return _MPU[IdxPU]->u(Time);
00245 }
00246 
00247 inline double Node::PV (size_t IdxPU, double Time) const
00248 {
00249     if (_MPU[IdxPU]==NULL) return 0.0;
00250     else                   return _MPU[IdxPU]->v(Time);
00251 }
00252 
00253 inline double Node::PA (size_t IdxPU, double Time) const
00254 {
00255     if (_MPU[IdxPU]==NULL) return 0.0;
00256     else                   return _MPU[IdxPU]->a(Time);
00257 }
00258 
00259 inline double Node::PF (size_t IdxPF, double Time) const
00260 {
00261     if (_MPF[IdxPF]==NULL) return _PF(_PF.Keys[IdxPF]);
00262     else                   return _PF(_PF.Keys[IdxPF]) * _MPF[IdxPF]->fm(Time);
00263 }
00264 
00265 inline void Node::AccumPF ()
00266 {
00267     for (StrDbl_t::iterator it=_PF.begin(); it!=_PF.end(); ++it)
00268         _aPF.AddVal (it->first.CStr(), it->second);
00269 }
00270 
00271 inline void Node::Reactions (std::map<String,double> & R) const
00272 {
00273     for (size_t i=0; i<_PU.Keys.Size(); ++i)
00274     {
00275         String const & ukey = _PU.Keys[i];
00276         int            idof = _U2IDOF(ukey);
00277         String const & fkey = _F.Keys[idof];
00278         double         reac = _F(fkey);
00279         if (_aPF.HasKey(fkey)) reac -= _aPF(fkey);
00280         R[ukey] = reac;
00281     }
00282 }
00283 
00284 inline void Node::SetLagPin (int & EqLag, Sparse::Triplet<double,int> & A) const
00285 {
00286     for (size_t i=0; i<_pin_nodes.Size(); ++i)
00287     {
00288         for (size_t j=0; j<_U.Keys.Size(); ++j)
00289         {
00290             if (_U.Keys[j]=="ux" || _U.Keys[j]=="uy" || _U.Keys[j]=="uz")
00291             {
00292                 int eq0 =                Eq(_U.Keys[j]);
00293                 int eq1 = _pin_nodes[i]->Eq(_U.Keys[j]);
00294                 A.PushEntry (eq0,EqLag,1.0);   A.PushEntry (eq1,EqLag,-1.0);
00295                 A.PushEntry (EqLag,eq0,1.0);   A.PushEntry (EqLag,eq1,-1.0);
00296                 EqLag++; // each pin adds one equation per DOF
00297             }
00298         }
00299     }
00300 }
00301 
00302 inline void Node::ClrRPin (int & EqLag, Vec_t & R) const
00303 {
00304     for (size_t i=0; i<_pin_nodes.Size(); ++i)
00305     {
00306         for (size_t j=0; j<_U.Keys.Size(); ++j)
00307         {
00308             if (_U.Keys[j]=="ux" || _U.Keys[j]=="uy" || _U.Keys[j]=="uz")
00309             {
00310                 int eq0 =                Eq(_U.Keys[j]);
00311                 int eq1 = _pin_nodes[i]->Eq(_U.Keys[j]);
00312                 R(eq0) = 0.0;
00313                 R(eq1) = 0.0;
00314                 EqLag++; // each pin adds one equation per DOF
00315             }
00316         }
00317     }
00318 }
00319 
00320 inline void Node::SetIncSup (double Alpha)
00321 {
00322     if (NPU()>0) return; // skip if this node has prescribed U already
00323     _incsup_alpha = Alpha*Util::PI/180.0;
00324     _has_incsup   = true; 
00325 }
00326 
00327 inline void Node::SetLagIncSup (int & EqLag, Sparse::Triplet<double,int> & A) const
00328 {
00329     double s   = sin(_incsup_alpha);
00330     double c   = cos(_incsup_alpha);
00331     int    eq0 = Eq("ux");
00332     int    eq1 = Eq("uy");
00333     A.PushEntry (EqLag, eq0,  s);
00334     A.PushEntry (EqLag, eq1, -c);
00335     A.PushEntry (eq0, EqLag,  s);
00336     A.PushEntry (eq1, EqLag, -c);
00337     EqLag++; // each inclined support adds one equation
00338 }
00339 
00340 inline void Node::ClrRIncSup (int & EqLag, Vec_t & R) const
00341 {
00342     int eq0 = Eq("ux");
00343     int eq1 = Eq("uy");
00344     R(eq0) = 0.0;
00345     R(eq1) = 0.0;
00346     EqLag++; // each inclined support adds one equation
00347 }
00348 
00349 std::ostream & operator<< (std::ostream & os, Node const & N)
00350 {
00351     os << Util::_4 << N.Vert.ID << " " << Util::_4 << N.Vert.Tag << " ";
00352     for (size_t i=0; i<N.NDOF(); ++i)
00353     {
00354         os << N.UKey(i) << " ";
00355         os << N.FKey(i) << " ";
00356         if (i!=N.NDOF()-1) os << " ";
00357     }
00358     os << " NShares=" << (N.NShares>0?TERM_GREEN:TERM_RED) << N.NShares << TERM_RST;
00359     os << " EQ=[";
00360     for (size_t i=0; i<N.NDOF(); ++i)
00361     {
00362         os << N.Eq(i);
00363         if (i!=N.NDOF()-1) os << ",";
00364         else               os << "]";
00365     }
00366     os << " (";
00367     for (int j=0; j<3; ++j)
00368     {
00369         os << Util::_6_3 << N.Vert.C[j];
00370         if (j==2) os << ")";
00371         else      os << ", ";
00372     }
00373     if (N._pin_nodes.Size()>0)
00374     {
00375         os << TERM_GREEN <<" PIN:[";
00376         for (size_t i=0; i<N._pin_nodes.Size(); ++i) os << N._pin_nodes[i]->Vert.ID << (i==N._pin_nodes.Size()-1?"]":",");
00377         os << TERM_RST;
00378     }
00379     if (N._has_incsup)         os << " INCSUP";
00380     os << TERM_CLR4 << Util::_reset << " PU=[";
00381     for (size_t i=0; i<N.NPU(); ++i)
00382     {
00383         os << N._PU.Keys[i] << "=" << N._PU(N._PU.Keys[i]);
00384         if (N._MPU[i]!=NULL) os << "*";
00385         if (i!=N.NPU()-1) os << " ";
00386     }
00387     os << "]" << TERM_CLR5 << " PF=[";
00388     for (size_t i=0; i<N.NPF(); ++i)
00389     {
00390         os << N._PF.Keys[i] << "=" << N._PF(N._PF.Keys[i]);
00391         if (N._MPF[i]!=NULL) os << "*";
00392         if (i!=N.NPF()-1) os << " ";
00393     }
00394     os << "]" << TERM_RST;
00395     return os;
00396 }
00397 
00398 }; //namespace FEM
00399 
00400 #endif // MECHSYS_FEM_NODE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines