equilibelem.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_EQUILIB_H
00023 #define MECHSYS_FEM_EQUILIB_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 "util/string.h"
00034 #include "models/equilibmodel.h"
00035 #include "fem/ele/element.h"
00036 #include "tensors/tensors.h"
00037 #include "tensors/functions.h"
00038 #include "util/numstreams.h"
00039 #include "linalg/laexpr.h"
00040 
00041 using Tensors::Stress_p_q_S_sin3th; // Mean and deviatoric Cambridge stress invariants
00042 using Tensors::Strain_Ev_Ed;        // Volumetric and deviatoric strain invariants
00043 
00044 namespace FEM
00045 {
00046 
00047 class EquilibElem : public virtual Element
00048 {
00049 
00050 public:
00051     // EquilibElem constants {{{    
00052     static int    NDIM;
00053     static int    NSTRESSCOMPS;
00054     static String DUX;
00055     static String DUY;
00056     static String DUZ;
00057     static String DFX;
00058     static String DFY;
00059     static String DFZ;
00060     static String DTX;
00061     static String DTY;
00062     static String DTZ;
00063     // }}}
00064     
00065     // Destructor
00066     virtual ~EquilibElem() {}
00067 
00068     // Virtual Methods
00069     virtual void   ReAllocateModel     (String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData);
00070     virtual bool   IsEssential         (String const & DOFName) const;
00071     virtual void   Stiffness           (LinAlg::Matrix<REAL> & Ke, Array<size_t> & EqMap) const;
00072     virtual void   B_Matrix            (LinAlg::Matrix<REAL> const & derivs, LinAlg::Matrix<REAL> const & J, LinAlg::Matrix<REAL> & B) const;
00073     virtual void   NodalDOFs           (int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const;
00074     virtual void   SetProperties       (Array<REAL> const & EleProps) { _unit_weight=EleProps[0]; }
00075     virtual String OutCenter           (bool PrintCaptionOnly) const;
00076             void   OutNodes            (LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const;
00077     virtual void   UpdateState         (REAL TimeInc);
00078     virtual void   CalcFaceNodalValues (String            const & FaceDOFName  ,         // In:  Face DOF Name, ex.: "Dtx, Dty, Dtz"
00079                                         REAL              const   FaceDOFValue ,         // In:  Face DOF Value, ex.: 10 kPa, 20 kPa
00080                                         Array<FEM::Node*> const & APtrFaceNodes,         // In:  Array of ptrs to face nodes
00081                                         String                  & NodalDOFName ,         // Out: Nodal DOF Name, ex.: "Dfx, Dfy, Dfz"
00082                                         LinAlg::Vector<REAL>    & NodalValues  ) const;  // Out: Vector of nodal values
00083     virtual void Deactivate();
00084 
00085     // Methods
00086     void BackupState();
00087     void RestoreState();
00088     // Functions to assemble DAS matrices
00089     virtual size_t nOrder1Matrices() const { return 1; };
00090     virtual void   Order1Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const;
00091     // Output
00092     void OutTensor1 (String & Str) const; // Stress
00093     void OutTensor2 (String & Str) const; // Strain
00094     REAL OutScalar2 ()             const; // Ed
00095 
00096 private:
00097     // Data
00098     Array<EquilibModel*> _a_model;
00099     REAL                 _unit_weight;
00100 
00101     // Methods
00102     void _set_node_vars                (int iNode);
00103     void _calc_initial_internal_forces ();
00104 
00105 }; // class EquilibElem
00106 
00107 // EquilibElem constants {{{    
00108 int    EquilibElem::NDIM         = 3;
00109 int    EquilibElem::NSTRESSCOMPS = 6;
00110 String EquilibElem::DUX          = _T("Dux");
00111 String EquilibElem::DUY          = _T("Duy");
00112 String EquilibElem::DUZ          = _T("Duz");
00113 String EquilibElem::DFX          = _T("Dfx");
00114 String EquilibElem::DFY          = _T("Dfy");
00115 String EquilibElem::DFZ          = _T("Dfz");
00116 String EquilibElem::DTX          = _T("Dtx");
00117 String EquilibElem::DTY          = _T("Dty");
00118 String EquilibElem::DTZ          = _T("Dtz");
00119 // }}}
00120 
00121 
00123 
00124     
00125 inline void EquilibElem::_set_node_vars(int iNode) // {{{
00126 {
00127     // Add Degree of Freedom to a node (Essential, Natural)
00128     _connects[iNode]->AddDOF(DUX, DFX);
00129     _connects[iNode]->AddDOF(DUY, DFY);
00130     _connects[iNode]->AddDOF(DUZ, DFZ);
00131 
00132     // Set vectors
00133     _connects[iNode]->SetEssentialVector(DUX, DUY, DUZ);
00134     _connects[iNode]->SetNaturalVector  (DFX, DFY, DFZ);
00135 } // }}}
00136 
00137 inline void EquilibElem::Deactivate() //{{{
00138 {
00139     if (_is_active==false) return; // the element was already inactive
00140     _is_active = false; 
00141     //dereferencing nodes:
00142     for (int i_node=0; i_node<_n_nodes; i_node++)
00143     {
00144         _connects[i_node]->Refs()--;
00145     }
00146     //verifying if element is in the boundary of excavation
00147     bool in_boundary = false;
00148     for (int i_node=0; i_node<_n_nodes; i_node++)
00149         if (_connects[i_node]->Refs()>0) 
00150         {
00151             in_boundary=true;
00152             break;
00153         }
00154     //calculate internal forces for element on boudary
00155     if (in_boundary)
00156     {
00157         LinAlg::Vector<REAL> F(NDIM*_n_nodes);
00158         F.SetValues(0.0);
00159         
00160         for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00161         {
00162             // Temporary Integration Points
00163             REAL r = _a_int_pts[i_ip].r;
00164             REAL s = _a_int_pts[i_ip].s;
00165             REAL t = _a_int_pts[i_ip].t;
00166             REAL w = _a_int_pts[i_ip].w;
00167             // Calculate Derivatives of Shape functions w.r.t local coordinate system
00168             LinAlg::Matrix<REAL> derivs; // size = NumLocalCoords(ex.: r,s,t) x _n_nodes
00169             Derivs(r,s,t, derivs);
00170 
00171             // Calculate J (Jacobian) matrix for i_ip Integration Point
00172             LinAlg::Matrix<REAL> J;
00173             Jacobian(derivs, J);
00174             REAL det_J = J.Det();
00175 
00176             // Calculate B matrix for i_ip Integration Point
00177             LinAlg::Matrix<REAL> B;
00178             B_Matrix(derivs,J, B);
00179                 
00180             // Get tensor for accumulate stress
00181             Tensors::Tensor2 sig;
00182             sig = _a_model[i_ip]->Sig();
00183 
00184             // Calculate internal force vector;
00185             for (int i=0; i<F.Size(); ++i)
00186                 for (int j=0; j<B.Rows(); ++j)
00187                     F(i) += B(j,i)*sig(j)*det_J*w; // dF = Sum(Bt*sig*det_J*w)
00188         }   
00189 
00190         // adding to boudary values of node if Refs()>0
00191         for (int i_node=0; i_node<_n_nodes; i_node++)
00192             if (_connects[i_node]->Refs()>0) 
00193             {
00194                 _connects[i_node]->DOFVar(DFX).NaturalBry += F(i_node*NDIM  );
00195                 _connects[i_node]->DOFVar(DFY).NaturalBry += F(i_node*NDIM+1);
00196                 _connects[i_node]->DOFVar(DFZ).NaturalBry += F(i_node*NDIM+2);
00197             }
00198             else // eliminate dofs from nodes with no references
00199             {
00200                 _connects[i_node]->ClearDOF();
00201 
00202             }
00203         //delete IP information 
00204     }
00205 } //}}}
00206 
00207 inline void EquilibElem::ReAllocateModel(String const & ModelName, Array<REAL> const & ModelPrms, Array<Array<REAL> > const & AIniData) // {{{
00208 {
00209     // Check size of AIniData
00210     if (!(AIniData.size()==1 || static_cast<int>(AIniData.size())==_n_int_pts))
00211         throw new Fatal(_("EquilibElem::ReAllocateModel: Array of array of initial data must have size==1 or size==%d"),_n_int_pts);
00212 
00213     // If pointers to model was not already defined => No model was allocated
00214     if (_a_model.size()==0)
00215     {
00216         // Resize the array of model pointers
00217         _a_model.resize(_n_int_pts);
00218 
00219         // Loop along integration points
00220         for (int i=0; i<_n_int_pts; ++i)
00221         {
00222             // Allocate a new model and set parameters
00223             if (AIniData.size()==1) _a_model[i] = AllocEquilibModel(ModelName, ModelPrms, AIniData[0]);
00224             else                    _a_model[i] = AllocEquilibModel(ModelName, ModelPrms, AIniData[i]);
00225         }
00226 
00227         // Calculate initial internal forces
00228         _calc_initial_internal_forces();
00229     }
00230     else // Model objects already defined (allocated)
00231     {
00232         // Loop along integration points
00233         for (int i=0; i<_n_int_pts; ++i)
00234         {
00235             if (_a_model[i]->Name()!=ModelName) // Do re-allocate
00236             {
00237                 // Delete old model
00238                 delete _a_model[i];
00239 
00240                 // Allocate a new model and set parameters
00241                 if (AIniData.size()==1) _a_model[i] = AllocEquilibModel(ModelName, ModelPrms, AIniData[0]);
00242                 else                    _a_model[i] = AllocEquilibModel(ModelName, ModelPrms, AIniData[i]);
00243             }
00244             // else: Do NOT re-allocate => Model not changed (don't do anything)
00245         }
00246     }
00247 } // }}}
00248 
00249 inline bool EquilibElem::IsEssential(String const & DOFName) const // {{{
00250 {
00251     if (DOFName==DUX || DOFName==DUY || DOFName==DUZ) return true;
00252     else return false;
00253 } // }}}
00254 
00255 inline void EquilibElem::CalcFaceNodalValues(String            const & FaceDOFName  , // {{{
00256                                              REAL              const   FaceDOFValue ,
00257                                              Array<FEM::Node*> const & APtrFaceNodes,
00258                                              String                  & NodalDOFName ,
00259                                              LinAlg::Vector<REAL>    & NodalValues  ) const
00260 {
00261     if (FaceDOFName==DTX || FaceDOFName==DTY || FaceDOFName==DTZ)
00262     {
00263         if (FaceDOFName==DTX) NodalDOFName=DFX;
00264         if (FaceDOFName==DTY) NodalDOFName=DFY;
00265         if (FaceDOFName==DTZ) NodalDOFName=DFZ;
00266         _distrib_val_to_face_nodal_vals(APtrFaceNodes, FaceDOFValue, NodalValues);
00267     }
00268     else
00269     {
00270         std::ostringstream oss; oss << "Face nodes coordinates:\n";
00271         for (size_t i_node=0; i_node<APtrFaceNodes.size(); ++i_node)
00272             oss << "X=" << APtrFaceNodes[i_node]->X() << ", Y=" << APtrFaceNodes[i_node]->Y() << ", Z=" << APtrFaceNodes[i_node]->Z() << std::endl;
00273         throw new Fatal(_("EquilibElem::CalcFaceNodalValues: This method must only be called for FaceDOFName< %s > equal to Dtx, Dty or Dtz.\n %s"),
00274                 FaceDOFName.c_str(), oss.str().c_str());
00275     }
00276 } // }}}
00277 
00278 inline void EquilibElem::Stiffness(LinAlg::Matrix<REAL> & Ke, Array<size_t> & EqMap) const // {{{
00279 {
00280     // Resize Ke
00281     Ke.Resize(NDIM*_n_nodes, NDIM*_n_nodes); // sum(Bt*D*B*det(J)*w)
00282     Ke.SetValues(0.0);
00283 
00284     // Allocate entities used for every integration point
00285     LinAlg::Matrix<REAL> derivs; // size = NumLocalCoords(ex.: r,s,t) x _n_nodes
00286     LinAlg::Matrix<REAL> J;      // Jacobian matrix
00287     LinAlg::Matrix<REAL> B;      // strain-displacement matrix
00288     Tensors::Tensor4     tsrD;   // Fourth order constitutive tensor
00289     LinAlg::Matrix<REAL> D;      // Constitutive matrix
00290 
00291     // Loop along integration points
00292     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00293     {
00294         // Temporary Integration Points
00295         REAL r = _a_int_pts[i_ip].r;
00296         REAL s = _a_int_pts[i_ip].s;
00297         REAL t = _a_int_pts[i_ip].t;
00298         REAL w = _a_int_pts[i_ip].w;
00299 
00300         Derivs(r,s,t, derivs);        // Calculate Derivatives of Shape functions w.r.t local coordinate system
00301         Jacobian(derivs, J);          // Calculate J (Jacobian) matrix for i_ip Integration Point
00302         B_Matrix(derivs,J, B);        // Calculate B matrix for i_ip Integration Point
00303 
00304         // Constitutive tensor 
00305         _a_model[i_ip]->TgStiffness(tsrD); Copy(tsrD, D);
00306 
00307         // Calculate Tangent Stiffness
00308         Ke += trn(B)*D*B*det(J)*w;
00309     }
00310     
00311     //Mounting a map of positions from Ke to Global
00312     int idx_Ke=0; // position (idx) inside Ke matrix
00313     EqMap.resize(Ke.Rows()); // size=Ke.Rows()=Ke.Cols()
00314     for (int i_node=0; i_node<_n_nodes; ++i_node)
00315     {
00316         // Fill map of Ke position to K position of DOFs components
00317         EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUX).EqID; 
00318         EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUY).EqID; 
00319         EqMap[idx_Ke++] = _connects[i_node]->DOFVar(DUZ).EqID; 
00320     }
00321 } // }}}
00322 
00323 inline void EquilibElem::NodalDOFs(int iNode, Array<FEM::Node::DOFVarsStruct*> & DOFs) const // {{{
00324 {
00325     // Create a structure to hold the DOFs information of Node [j_node] inside Element [i_ele]
00326     // These DOFs are the only ones that Element [i_ele] uses => NOT the global ones
00327 
00328     // Resize DOFs array with 3 = 3D
00329     DOFs.resize(3);
00330 
00331     // Set DOFs array with pointers to DOFVarsStruct inside this element Node [iNode]
00332     DOFs[0] = &_connects[iNode]->DOFVar(DUX);
00333     DOFs[1] = &_connects[iNode]->DOFVar(DUY);
00334     DOFs[2] = &_connects[iNode]->DOFVar(DUZ);
00335 
00336 } // }}}
00337 
00338 inline void EquilibElem::B_Matrix(LinAlg::Matrix<REAL> const & derivs, LinAlg::Matrix<REAL> const & J, LinAlg::Matrix<REAL> & B) const // {{{
00339 {
00340     /* OBS.:
00341      *       1) This B matrix considers Mandel representation of stress components,
00342      *          for this reason, some of its components are divided by sqrt(2).
00343      *          Ex.: Sig = {S11  S22  S33  sqrt(2)*S12  sqrt(2)*S23  sqrt(2)*S13}^(T)
00344      *               Eps = {E11  E22  E33  sqrt(2)*E12  sqrt(2)*E23  sqrt(2)*E13}^(T)
00345      *       2) This B matrix considers Soil Mechanics sign convention of stress and strains
00346      *          Ex.: Compressive stresses/strains are positive
00347      */
00348     
00349     // Resize B matrix
00350     B.Resize(NSTRESSCOMPS,NDIM*_n_nodes);
00351 
00352     // Inverse of Jacobian
00353     LinAlg::Matrix<REAL> inv_J(J.Rows(),J.Cols());
00354     J.Inv(inv_J);
00355 
00356     // Cartesian derivatives
00357     LinAlg::Matrix<REAL> cart_derivs;
00358     cart_derivs.Resize(J.Rows(), derivs.Cols());
00359     LinAlg::Gemm(1.0,inv_J,derivs, 0.0,cart_derivs); // cart_derivs <- inv_J*derivs
00360 
00361     // Loop along all nodes of the element
00362     REAL sq2 = sqrt(2.0);
00363     REAL dNdX,dNdY,dNdZ;
00364     int  j=0; // j column of B
00365     for (int i=0; i<_n_nodes; ++i) // i row of B
00366     {
00367         // Assemble B matrix
00368         j=i*NDIM;
00369         dNdX=-cart_derivs(0,i);  dNdY=-cart_derivs(1,i);  dNdZ=-cart_derivs(2,i); // Negative values => Soil mechanics convention
00370         B(0,0+j) =     dNdX;     B(0,1+j) =      0.0;     B(0,2+j) =      0.0;
00371         B(1,0+j) =      0.0;     B(1,1+j) =     dNdY;     B(1,2+j) =      0.0;
00372         B(2,0+j) =      0.0;     B(2,1+j) =      0.0;     B(2,2+j) =     dNdZ;
00373         B(3,0+j) = dNdY/sq2;     B(3,1+j) = dNdX/sq2;     B(3,2+j) =      0.0; // sq2 => Mandel representation
00374         B(4,0+j) =      0.0;     B(4,1+j) = dNdZ/sq2;     B(4,2+j) = dNdY/sq2; // sq2 => Mandel representation
00375         B(5,0+j) = dNdZ/sq2;     B(5,1+j) =      0.0;     B(5,2+j) = dNdX/sq2; // sq2 => Mandel representation
00376     }
00377 } // }}}
00378 
00379 inline void EquilibElem::BackupState() // {{{
00380 {
00381     for (int i=0; i<_n_int_pts; ++i)
00382         _a_model[i]->BackupState();
00383 } // }}}
00384 
00385 inline void EquilibElem::UpdateState(REAL TimeInc) // Read nodal values _IncEssential and write to _IncNatural  {{{
00386 {
00387     // Read nodal values _IncEssential and write to _IncNatural
00388 
00389     // Allocate (local/element) displacements vector
00390     LinAlg::Vector<REAL> dU(NDIM*_n_nodes); // Delta disp. of this element
00391     
00392     // Loop along nodes
00393     for (int i_node=0; i_node<_n_nodes; ++i_node)
00394     {
00395         // Assemble (local/element) displacements vector. OBS.: NDIM=3
00396         dU(i_node*NDIM  ) = _connects[i_node]->DOFVar(DUX)._IncEssenVal;
00397         dU(i_node*NDIM+1) = _connects[i_node]->DOFVar(DUY)._IncEssenVal;
00398         dU(i_node*NDIM+2) = _connects[i_node]->DOFVar(DUZ)._IncEssenVal;
00399     }
00400     
00401     // Allocate (local/element) internal force vector
00402     LinAlg::Vector<REAL> dF(NDIM*_n_nodes); // Delta internal force of this element
00403     dF.SetValues(0.0);
00404     
00405     // Allocate entities used for every integration point
00406     LinAlg::Matrix<REAL> derivs;  // size = NumLocalCoords(ex.: r,s,t) x _n_nodes
00407     LinAlg::Matrix<REAL> J;       // Jacobian matrix
00408     LinAlg::Matrix<REAL> B;       // strain-displacement matrix
00409     Tensors::Tensor2     tsrDEps; // Strain tensor  tsrDEps(NSTRESSCOMPS=6) = B(NSTRESSCOMPS=6,NDIM*_n_nodes) * dU(NDIM*_n_nodes)
00410     Tensors::Tensor2     tsrDSig; // Stress tensor
00411     LinAlg::Vector<REAL> DEps;    // Strain vector in Mandel's notation 
00412     LinAlg::Vector<REAL> DSig;    // Stress vector in Mandel's notation 
00413 
00414     // Loop along integration points
00415     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00416     {
00417         // Temporary Integration Points
00418         REAL r = _a_int_pts[i_ip].r;
00419         REAL s = _a_int_pts[i_ip].s;
00420         REAL t = _a_int_pts[i_ip].t;
00421         REAL w = _a_int_pts[i_ip].w;
00422 
00423         Derivs(r,s,t, derivs);        // Calculate Derivatives of Shape functions w.r.t local coordinate system
00424         Jacobian(derivs, J);          // Calculate J (Jacobian) matrix for i_ip Integration Point
00425         B_Matrix(derivs, J, B);       // Calculate B matrix for i_ip Integration Point
00426 
00427         // Calculate a tensor for the increments of strain
00428         DEps = B*dU;
00429         Copy(DEps, tsrDEps);  // tsrDEps = B*dU
00430         
00431         // Update model
00432         _a_model[i_ip]->StressUpdate(tsrDEps, tsrDSig);
00433         Copy(tsrDSig, DSig);
00434 
00435         // Calculate internal force vector;
00436         dF += trn(B)*DSig*det(J)*w;
00437     }
00438 
00439     // Update nodal _IncNaturVals
00440     for (int i_node=0; i_node<_n_nodes; ++i_node)
00441     {
00442         // Assemble (local/element) displacements vector. OBS.: NDIM=3
00443         _connects[i_node]->DOFVar(DFX)._IncNaturVal += dF(i_node*NDIM  );
00444         _connects[i_node]->DOFVar(DFY)._IncNaturVal += dF(i_node*NDIM+1);
00445         _connects[i_node]->DOFVar(DFZ)._IncNaturVal += dF(i_node*NDIM+2);
00446 
00447         // Update natural vars state
00448         _connects[i_node]->DOFVar(DFX).NaturalVal += dF(i_node*NDIM  );
00449         _connects[i_node]->DOFVar(DFY).NaturalVal += dF(i_node*NDIM+1);
00450         _connects[i_node]->DOFVar(DFZ).NaturalVal += dF(i_node*NDIM+2);
00451     }
00452 } // }}}
00453 
00454 inline void EquilibElem::RestoreState() // {{{
00455 {
00456     for (int i=0; i<_n_int_pts; ++i)
00457         _a_model[i]->RestoreState();
00458 } // }}}
00459 
00460 inline String EquilibElem::OutCenter(bool PrintCaptionOnly=false) const // {{{
00461 {
00462     // Auxiliar variables
00463     std::ostringstream oss;
00464 
00465     // Number of state values
00466     int n_int_state_vals = _a_model[0]->nInternalStateValues();
00467     
00468     // Print caption
00469     if (PrintCaptionOnly)
00470     {
00471         // Stress and strains
00472         oss << _8s()<< "p"  << _8s()<< "q"  << _8s()<< "sin3th" << _8s()<< "Ev"  << _8s()<< "Ed";
00473         oss << _8s()<< "Sx" << _8s()<< "Sy" << _8s()<< "Sz" << _8s()<< "Sxy" << _8s()<< "Syz" << _8s()<< "Sxz";
00474         oss << _8s()<< "Ex" << _8s()<< "Ey" << _8s()<< "Ez" << _8s()<< "Exy" << _8s()<< "Eyz" << _8s()<< "Exz";
00475 
00476         // Internal state values
00477         Array<String> str_state_names;   _a_model[0]->InternalStateNames(str_state_names);
00478         for (int i=0; i<n_int_state_vals; ++i)
00479             oss << _8s()<< str_state_names[i];
00480         oss << std::endl;
00481     }
00482     else
00483     {
00484         // Stress, strains and internal state values evaluated at the center of the element
00485         Tensors::Tensor2 sig_cen(0.0);
00486         Tensors::Tensor2 eps_cen(0.0);
00487         Array<REAL>      int_state_vals_cen;   int_state_vals_cen.assign(n_int_state_vals,0.0);
00488 
00489         // Loop over integration points
00490         for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00491         {
00492             // Stress and strains
00493             sig_cen += _a_model[i_ip]->Sig();
00494             eps_cen += _a_model[i_ip]->Eps();
00495 
00496             // Internal state values
00497             Array<REAL> int_state_vals;    _a_model[i_ip]->InternalStateValues(int_state_vals);
00498             for (int j=0; j<n_int_state_vals; ++j)
00499                 int_state_vals_cen[j] += int_state_vals[j];
00500         }
00501         
00502         // Average stress and strains
00503         sig_cen = sig_cen / _n_int_pts;
00504         eps_cen = eps_cen / _n_int_pts;
00505         
00506         // Average internal state values
00507         for (int j=0; j<n_int_state_vals; ++j)
00508             int_state_vals_cen[j] = int_state_vals_cen[j] / _n_int_pts;;
00509 
00510         // Calculate stress invariants
00511         REAL              p,q,sin3th;
00512         Tensors::Tensor2  S;
00513         Stress_p_q_S_sin3th(sig_cen,p,q,S,sin3th);
00514 
00515         // Calculate strain invariants
00516         REAL     Ev,Ed;
00517         Strain_Ev_Ed(eps_cen,Ev,Ed);
00518 
00519         // Output
00520         REAL sq2 = sqrt(2.0);
00521         oss << _8s()<< p          << _8s()<< q          << _8s()<< sin3th << _8s()<< Ev*100.0       << _8s()<< Ed*100.0;
00522         oss << _8s()<< sig_cen(0) << _8s()<< sig_cen(1) << _8s()<< sig_cen(2)         << _8s()<< sig_cen(3)/sq2 << _8s()<< sig_cen(4)/sq2 << _8s()<< sig_cen(5)/sq2;
00523         oss << _8s()<< eps_cen(0) << _8s()<< eps_cen(1) << _8s()<< eps_cen(2)         << _8s()<< eps_cen(3)/sq2 << _8s()<< eps_cen(4)/sq2 << _8s()<< eps_cen(5)/sq2;
00524         for (int j=0; j<n_int_state_vals; ++j)
00525             oss << _8s()<< int_state_vals_cen[j];
00526         oss << std::endl;
00527     }
00528 
00529     return oss.str(); 
00530 } // }}}
00531 
00532 inline void EquilibElem::OutNodes(LinAlg::Matrix<REAL> & Values, Array<String> & Labels) const // {{{
00533 {
00534     int const DATA_COMPS=18;
00535     Values.Resize(_n_nodes,DATA_COMPS);
00536     Labels.resize(DATA_COMPS);
00537     Labels[ 0] = DUX ; Labels[ 1] = DUY ; Labels[ 2] = DUZ; 
00538     Labels[ 3] = DFX ; Labels[ 4] = DFY ; Labels[ 5] = DFZ;
00539     Labels[ 6] = "Ex"; Labels[ 7] = "Ey"; Labels[ 8] = "Ez"; Labels[ 9] = "Exy"; Labels[10] = "Eyz"; Labels[11] = "Exz";
00540     Labels[12] = "Sx"; Labels[13] = "Sy"; Labels[14] = "Sz"; Labels[15] = "Sxy"; Labels[16] = "Syz"; Labels[17] = "Sxz";
00541     for (int i_node=0; i_node<_n_nodes; i_node++)
00542     {
00543         Values(i_node,0) = _connects[i_node]->DOFVar(DUX).EssentialVal;
00544         Values(i_node,1) = _connects[i_node]->DOFVar(DUY).EssentialVal;
00545         Values(i_node,2) = _connects[i_node]->DOFVar(DUZ).EssentialVal;
00546         Values(i_node,3) = _connects[i_node]->DOFVar(DFX).NaturalVal;
00547         Values(i_node,4) = _connects[i_node]->DOFVar(DFY).NaturalVal;
00548         Values(i_node,5) = _connects[i_node]->DOFVar(DFZ).NaturalVal;
00549     }
00550 
00551     //Extrapolation
00552     LinAlg::Vector<REAL> ip_values(_n_int_pts);
00553     LinAlg::Vector<REAL> nodal_values(_n_nodes);
00554     
00555     // Strains
00556     for (int i_comp=0; i_comp<NSTRESSCOMPS; i_comp++)
00557     {
00558         for (int j_ip=0; j_ip<_n_int_pts; j_ip++)
00559         {
00560             Tensors::Tensor2 const & eps = _a_model[j_ip]->Eps();
00561             ip_values(j_ip) = eps(i_comp); //getting IP values
00562         }
00563         _extrapolate(ip_values, nodal_values);
00564         for (int j_node=0; j_node<_n_nodes; j_node++)
00565             Values(j_node,i_comp+6) = nodal_values(j_node);
00566     }
00567     
00568     // Stresses
00569     for (int i_comp=0; i_comp<NSTRESSCOMPS; i_comp++)
00570     {
00571         for (int j_ip=0; j_ip<_n_int_pts; j_ip++)
00572         {
00573             Tensors::Tensor2 const & sig = _a_model[j_ip]->Sig();
00574             ip_values(j_ip) = sig(i_comp); //getting IP values
00575         }
00576         _extrapolate(ip_values, nodal_values);
00577         for (int j_node=0; j_node<_n_nodes; j_node++)
00578             Values(j_node,i_comp+12) = nodal_values(j_node);
00579     }
00580 } // }}}
00581 
00582 inline void EquilibElem::_calc_initial_internal_forces() // {{{
00583 {
00584     // Allocate (local/element) internal force vector
00585     LinAlg::Vector<REAL> F(NDIM*_n_nodes);
00586     F.SetValues(0.0);
00587 
00588     // Allocate entities used for every integration point
00589     LinAlg::Matrix<REAL> derivs;  // size = NumLocalCoords(ex.: r,s,t) x _n_nodes
00590     LinAlg::Matrix<REAL> J;       // Jacobian matrix
00591     LinAlg::Matrix<REAL> B;       // strain-displacement matrix
00592     LinAlg::Vector<REAL> Sig;     // Stress vector in Mandel's notation 
00593 
00594     // Loop along integration points
00595     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00596     {
00597         // Temporary Integration Points
00598         REAL r = _a_int_pts[i_ip].r;
00599         REAL s = _a_int_pts[i_ip].s;
00600         REAL t = _a_int_pts[i_ip].t;
00601         REAL w = _a_int_pts[i_ip].w;
00602 
00603         Derivs(r,s,t, derivs);        // Calculate Derivatives of Shape functions w.r.t local coordinate system
00604         Jacobian(derivs, J);          // Calculate J (Jacobian) matrix for i_ip Integration Point
00605         B_Matrix(derivs, J, B);       // Calculate B matrix for i_ip Integration Point
00606 
00607         Tensors::Tensor2 const & tsrSig = _a_model[i_ip]->Sig(); // Declare a reference to the actual (initial) stress tensor inside EquilibModel
00608         Copy(tsrSig, Sig);
00609 
00610         // Calculate internal force vector;
00611         F += trn(B)*Sig*det(J)*w;
00612     }
00613 
00614     // Update nodal NaturVals
00615     for (int i_node=0; i_node<_n_nodes; ++i_node)
00616     {
00617         // Assemble (local/element) displacements vector. OBS.: NDIM=3
00618         _connects[i_node]->DOFVar(DFX).NaturalVal += F(i_node*NDIM  ); // NaturalVal must be set to zero during AddDOF routine
00619         _connects[i_node]->DOFVar(DFY).NaturalVal += F(i_node*NDIM+1);
00620         _connects[i_node]->DOFVar(DFZ).NaturalVal += F(i_node*NDIM+2);
00621     }
00622 } // }}}
00623 
00624 inline void EquilibElem::Order1Matrix(size_t index, LinAlg::Matrix<REAL> & M, Array<size_t> & RowsMap, Array<size_t> & ColsMap) const // {{{
00625 {
00626     assert(index == 0);
00627     Stiffness(M, RowsMap);
00628     ColsMap.resize(RowsMap.size());
00629     for (size_t i=0; i<RowsMap.size(); i++) ColsMap[i] = RowsMap[i];
00630 } // }}}
00631     
00632 inline void EquilibElem::OutTensor1(String & Str) const // {{{
00633 {
00634     // Stress evaluated at the center of the element
00635     Tensors::Tensor2 s(0.0);
00636 
00637     // Loop over integration points
00638     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00639         s += _a_model[i_ip]->Sig();
00640     
00641     // Average stress
00642     s = s / _n_int_pts;
00643 
00644     // Output
00645     REAL sq2 = sqrt(2.0);
00646     Str.Printf(_(" %e %e %e  %e %e %e  %e %e %e "), s(0),s(3)/sq2,s(5)/sq2,  s(3)/sq2,s(1),s(4)/sq2,  s(5)/sq2,s(4)/sq2,s(2));
00647 
00648 } // }}}
00649 
00650 inline void EquilibElem::OutTensor2(String & Str) const // {{{
00651 {
00652     // Strains evaluated at the center of the element
00653     Tensors::Tensor2 e(0.0);
00654 
00655     // Loop over integration points
00656     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00657         e += 100.0*_a_model[i_ip]->Eps();
00658     
00659     // Average strains
00660     e = e / _n_int_pts;
00661 
00662     // Output
00663     REAL sq2 = sqrt(2.0);
00664     Str.Printf(_(" %e %e %e  %e %e %e  %e %e %e "), e(0),e(3)/sq2,e(5)/sq2,  e(3)/sq2,e(1),e(4)/sq2,  e(5)/sq2,e(4)/sq2,e(2));
00665 
00666 } // }}}
00667 
00668 inline REAL EquilibElem::OutScalar2() const // {{{
00669 {
00670     // Strains evaluated at the center of the element
00671     Tensors::Tensor2 e(0.0);
00672 
00673     // Loop over integration points
00674     for (int i_ip=0; i_ip<_n_int_pts; ++i_ip)
00675         e += 100.0*_a_model[i_ip]->Eps();
00676     
00677     // Average strains
00678     e = e / _n_int_pts;
00679 
00680     // Calculate strain invariants
00681     REAL   Ev,Ed;
00682     Strain_Ev_Ed(e,Ev,Ed);
00683 
00684     // Output
00685     return Ed;
00686 
00687 } // }}}
00688 
00689 
00691 
00692 
00693 // Register the DOF information of EquilibElement into DOFInfoMap
00694 int EquilibDOFInfoRegister() // {{{
00695 {
00696     // Temporary 
00697     DOFInfo D; 
00698 
00699     // Nodal
00700     D.NodeEssential.push_back(EquilibElem::DUX + _("@Nodal displacement increment in x direction"));
00701     D.NodeEssential.push_back(EquilibElem::DUY + _("@Nodal displacement increment in y direction"));
00702     D.NodeEssential.push_back(EquilibElem::DUZ + _("@Nodal displacement increment in z direction"));
00703     D.NodeNatural  .push_back(EquilibElem::DFX + _("@Nodal force increment in x direction"));
00704     D.NodeNatural  .push_back(EquilibElem::DFY + _("@Nodal force increment in y direction"));
00705     D.NodeNatural  .push_back(EquilibElem::DFZ + _("@Nodal force increment in z direction"));
00706 
00707     // Face
00708     D.FaceEssential.push_back(EquilibElem::DUX + _("@Displacement increment in x direction on face"));
00709     D.FaceEssential.push_back(EquilibElem::DUY + _("@Displacement increment in y direction on face"));
00710     D.FaceEssential.push_back(EquilibElem::DUZ + _("@Displacement increment in z direction on face"));
00711     D.FaceNatural  .push_back(EquilibElem::DTX + _("@Traction increment in x direction on face"));
00712     D.FaceNatural  .push_back(EquilibElem::DTY + _("@Traction increment in y direction on face"));
00713     D.FaceNatural  .push_back(EquilibElem::DTZ + _("@Traction increment in z direction on face"));
00714 
00715     // Insert into DOFInfoMap
00716     DOFInfoMap["Equilibrium"] = D;
00717 
00718     return 0;
00719 } // }}}
00720 
00721 // Execute the autoregistration
00722 int __EquilibElemDOFInfo_dummy_int  = EquilibDOFInfoRegister();
00723 
00724 }; // namespace FEM
00725 
00726 #endif // MECHSYS_FEM_EQUILIB_H
00727 
00728 // vim:fdm=marker

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