00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00050 virtual ~Element() {}
00051
00052 struct IntegPoint
00053 {
00054 REAL r;
00055 REAL s;
00056 REAL t;
00057 REAL w;
00058 };
00059 int Number;
00060 virtual String Name() const=0;
00061
00062 void SetNode(int iNode, FEM::Node * ptrNode);
00063
00064 virtual bool IsEssential(String const & DOFName) const =0;
00065 virtual void CalcFaceNodalValues(String const & FaceDOFName ,
00066 REAL const FaceDOFValue ,
00067 Array<FEM::Node*> const & APtrFaceNodes,
00068 String & NodalDOFName ,
00069 LinAlg::Vector<REAL> & NodalValues
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
00081
00082 virtual void NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const =0;
00083 Array<Node*> const & Connects() const;
00084 void IntegPoints(IntegPoint const * & IPs) const { IPs = _a_int_pts; };
00085 virtual void BackupState() =0;
00086 virtual void UpdateState(REAL TimeInc=0) =0;
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
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
00110 virtual REAL OutScalar1 () const { return 0; };
00111 virtual REAL OutScalar2 () const { return 0; };
00112 virtual void OutTensor1 (String & Str) const { Str.Printf(_(" 0 0 0 0 0 0 0 0 0 ")); };
00113 virtual void OutTensor2 (String & Str) const { Str.Printf(_(" 0 0 0 0 0 0 0 0 0 ")); };
00114 virtual void OutTensor3 (String & Str) const { Str.Printf(_(" 0 0 0 0 0 0 0 0 0 ")); };
00115 protected:
00116
00117 int _n_nodes;
00118 int _n_int_pts;
00119 int _n_face_nodes;
00120 int _n_face_int_pts;
00121 Array<Node*> _connects;
00122 bool _is_active;
00123 IntegPoint const * _a_int_pts;
00124
00125 virtual void _set_node_vars(int iNode)=0;
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,
00129 REAL const FaceValue ,
00130 LinAlg::Vector<REAL> & NodalValues
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 };
00135
00136
00138
00139
00140 inline void Element::SetNode(int iNode, FEM::Node * ptrNode)
00141 {
00142
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
00149 _connects[iNode] = ptrNode;
00150
00151
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;
00167
00168
00169 LinAlg::Vector<REAL> f(3);
00170 LinAlg::Vector<REAL> delta(3);
00171 REAL tx, ty, tz;
00172 REAL norm_f;
00173 r = s = t =0;
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
00183 for (int j=0; j<_n_nodes; j++)
00184 {
00185 tx += shape(j)*_connects[j]->X();
00186 ty += shape(j)*_connects[j]->Y();
00187 tz += shape(j)*_connects[j]->Z();
00188 }
00189
00190
00191 f(0) = tx - x;
00192 f(1) = ty - y;
00193 f(2) = tz - z;
00194
00195
00196
00197 delta = trn(inv(J))*f;
00198
00199
00200 r -= delta(0);
00201 s -= delta(1);
00202 t -= delta(2);
00203
00204
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
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
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
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
00249 LinAlg::Matrix<REAL> m_face_derivs;
00250 _face_derivs(r, s, m_face_derivs);
00251
00252
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
00262 J.Resize(2,3);
00263
00264 J = m_face_derivs*m_face_coords;
00265 }
00266
00267 inline void Element::Coords(LinAlg::Matrix<REAL> & coords) const
00268 {
00269
00270 coords.Resize(_n_nodes,3);
00271
00272
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
00284 LinAlg::Matrix<REAL> cmatrix;
00285 cmatrix.Resize(_n_nodes,3);
00286
00287
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
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
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 LinAlg::Matrix<REAL> N(_n_int_pts, _n_nodes);
00322 LinAlg::Matrix<REAL> E(_n_nodes, _n_int_pts);
00323 LinAlg::Vector<REAL> shape(_n_nodes);
00324
00325
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
00337 assert(_n_nodes>=_n_int_pts);
00338 E = trn(N)*inv(N*trn(N));
00339
00340
00341 NodalValues = E*IPValues;
00342
00343 };
00344
00346
00347
00348
00349 typedef Element * (*ElementMakerPtr)();
00350
00351
00352 typedef std::map<String, ElementMakerPtr, std::less<String> > ElementFactory_t;
00353
00354
00355 ElementFactory_t ElementFactory;
00356
00357
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 };
00368
00369
00371
00372
00373
00374 struct DOFInfo
00375 {
00376 Array<String> NodeEssential;
00377 Array<String> NodeNatural;
00378 Array<String> FaceEssential;
00379 Array<String> FaceNatural;
00380 };
00381
00382
00383 typedef std::map<String, DOFInfo, std::less<String> > DOFInfoMap_t;
00384
00385
00386 DOFInfoMap_t DOFInfoMap;
00387
00388 #endif // MECHSYS_FEM_ELEMENT
00389
00390