linearelasticityassembler.hh

Go to the documentation of this file.
00001 #ifndef DUNE_P1_LINEAR_ELASTICITY_ASSEMBLER_HH
00002 #define DUNE_P1_LINEAR_ELASTICITY_ASSEMBLER_HH
00003 
00004 #include<map>
00005 #include<iostream>
00006 #include<iomanip>
00007 #include<fstream>
00008 #include<vector>
00009 #include<sstream>
00010 
00011 #include<dune/common/fvector.hh>
00012 #include<dune/common/fmatrix.hh>
00013 #include<dune/common/exceptions.hh>
00014 #include<dune/grid/common/grid.hh>
00015 #include<dune/grid/common/referenceelements.hh>
00016 #include<dune/istl/operators.hh>
00017 #include<dune/istl/bvector.hh>
00018 
00019 #include<dune/grid/common/quadraturerules.hh>
00020 #include<dune/disc/operators/localstiffness.hh>
00021 #include<dune/disc/shapefunctions/lagrangeshapefunctions.hh>
00022 #include<dune/disc/operators/boundaryconditions.hh>
00023 
00031 namespace Dune
00032 {
00043 
00044 
00059   template<class GridView, class RT>
00060   class LinearElasticityLocalStiffness 
00061     : public LinearLocalStiffness<GridView,RT,GridView::dimension>
00062   {
00063         // grid types
00064       typedef typename GridView::Grid::ctype DT;
00065         typedef typename GridView::template Codim<0>::Entity Entity;
00066 
00067         // some other sizes
00068         enum {dim=GridView::dimension};
00069 
00071       typedef FieldVector<double, (dim+1)*dim/2> SymmTensor;
00072 
00073   public:
00074         // define the number of components of your system, this is used outside
00075         // to allocate the correct size of (dense) blocks with a FieldMatrix
00076         enum {m=dim};
00077 
00078         // types for matrics, vectors and boundary conditions
00079         typedef FieldMatrix<RT,m,m> MBlockType; // one entry in the stiffness matrix
00080         typedef FieldVector<RT,m> VBlockType;   // one entry in the global vectors
00081         typedef array<BoundaryConditions::Flags,m> BCBlockType;     // componentwise boundary conditions
00082         // /////////////////////////////////
00083         //   The material parameters
00084         // /////////////////////////////////
00085         
00086         // Young's modulus
00087         double E_;
00088 
00089         // Poisson ratio
00090         double nu_;
00091 
00092       typedef std::map<std::pair<GeometryType, int>, std::vector<FieldVector<DT,dim> > > CacheType;
00093       CacheType gradientCache_;
00094       
00096       LinearElasticityLocalStiffness ()
00097       {}
00098 
00100       LinearElasticityLocalStiffness (double E, double nu, bool procBoundaryAsDirichlet_=true)
00101           : E_(E), nu_(nu)
00102       {
00103           procBoundaryAsDirichlet = procBoundaryAsDirichlet_;
00104       }
00105 
00107       void setEandNu(double E, double nu)
00108       {
00109           E_  = E;
00110           nu_ = nu;
00111       }
00112       
00114 
00123       void assemble (const Entity& e, int k=1)
00124       {
00125           // extract some important parameters
00126           GeometryType gt = e.type();
00127           const typename LagrangeShapeFunctionSetContainer<DT,RT,dim>::value_type& sfs
00128               = LagrangeShapeFunctions<DT,RT,dim>::general(gt,k);
00129           
00130           // clear assemble data
00131           setcurrentsize(sfs.size());
00132 
00133           for (int i=0; i<sfs.size(); i++)
00134               {
00135                   this->b[i] = 0;
00136                   for (int j=0; j<this->bctype[i].size(); j++)
00137                       this->bctype[i][j] = BoundaryConditions::neumann;
00138                   for (int j=0; j<sfs.size(); j++) 
00139                       this->A[i][j] = 0;
00140               }
00141           
00142           // Compute suitable quadrature order
00143           int p = (gt.isSimplex()) 
00144               ? 2*(k-1)
00145               : 2*(k*dim-1);
00146 
00147           const std::vector<FieldVector<DT,dim> >* shapeGradients = NULL;
00148 
00149           typename CacheType::iterator shapeFunctionGradients = gradientCache_.find(std::make_pair(gt,p));
00150 
00151           if (shapeFunctionGradients == gradientCache_.end()) {
00152 
00153               std::vector<FieldVector<DT,dim> > newGradientSet(sfs.size() * QuadratureRules<DT,dim>::rule(gt,p).size());
00154               
00155               for (size_t g=0; g<Dune::QuadratureRules<DT,dim>::rule(gt,p).size(); ++g) {
00156 
00157                   // pos of integration point
00158                   const Dune::FieldVector<DT,dim>& quadPos = Dune::QuadratureRules<DT,dim>::rule(gt,p)[g].position();
00159 
00160                   for (int i=0; i<sfs.size(); i++) {
00161                   
00162                       for (int l=0; l<dim; l++) 
00163                           newGradientSet[sfs.size()*g + i][l] = sfs[i].evaluateDerivative(0,l,quadPos);
00164                       
00165                   }
00166 
00167               }
00168 
00169               gradientCache_.insert(std::make_pair(std::make_pair(gt,p), newGradientSet));
00170 
00171           }
00172 
00173           shapeGradients = &gradientCache_.find(std::make_pair(gt,p))->second;
00174 
00175 
00176           for (size_t g=0; g<Dune::QuadratureRules<DT,dim>::rule(gt,p).size(); ++g) {
00177               
00178               // pos of integration point
00179               const Dune::FieldVector<DT,dim>& local = Dune::QuadratureRules<DT,dim>::rule(gt,p)[g].position();
00180               
00181               // eval jacobian inverse
00182               const Dune::FieldMatrix<DT,dim,dim>& jac = e.geometry().jacobianInverseTransposed(local);
00183 
00184               // weight of quadrature point
00185               double weight = Dune::QuadratureRules<DT,dim>::rule(gt,p)[g].weight();
00186               
00187               // determinant of jacobian
00188               DT detjac = e.geometry().integrationElement(local);
00189 
00190               // evaluate gradients at Gauss points
00191               Dune::FieldVector<DT,dim> grad[sfs.size()], temp, gv;
00192               for (int i=0; i<sfs.size(); i++) {
00193                   grad[i] = 0;
00194                   jac.umv((*shapeGradients)[sfs.size()*g + i],grad[i]); // transform gradient to global coordinates
00195               }
00196               
00197               // /////////////////////////////////////////////
00198               //   Compute strain for all shape functions
00199               // /////////////////////////////////////////////
00200               std::vector<array<SymmTensor,dim> > strain(sfs.size());
00201               
00202               for (int i=0; i<sfs.size(); i++) 
00203                   for (int k=0; k<dim; k++) {
00204                       
00205                       // The deformation gradient of the shape function
00206                       FieldMatrix<double, dim, dim> deformationGradient(0);
00207                       deformationGradient[k] = grad[i];
00208                  
00209                       /* Computes the linear strain tensor from the deformation gradient*/
00210                       computeStrain(deformationGradient,strain[i][k]);
00211                       
00212                   }
00213               
00214               // loop over test function number
00215               for (int row=0; row<sfs.size(); row++) {
00216                   
00217                   for (int rcomp=0; rcomp<dim; rcomp++) {
00218                       
00219                       SymmTensor stress = hookeTimesStrain(strain[row][rcomp]);
00220                       
00221                       for (int col=0; col<=row; col++) {
00222                           
00223                           for (int ccomp=0; ccomp<dim; ccomp++) {
00224                               
00225                               this->A[row][col][rcomp][ccomp] += stress*strain[col][ccomp] * weight * detjac;
00226 
00227                           }
00228                       }
00229                   }    
00230 
00231               }
00232               
00233           }
00234 
00235           for (int row=0; row<sfs.size(); row++)
00236               for (int col=0; col<=row; col++) {
00237                   
00238                   // Complete the symmetric matrix by copying the lower left triangular matrix
00239                   // to the upper right one
00240                   if (row!=col) {
00241                       for (int rcomp=0; rcomp<dim; rcomp++)
00242                           for (int ccomp=0; ccomp<dim; ccomp++)
00243                               this->A[col][row][ccomp][rcomp] = this->A[row][col][rcomp][ccomp];
00244                   }
00245               }
00246 
00247       }
00248 
00249       // computes the linear strain from the deformation gradient
00250       void computeStrain(const FieldMatrix<double, dim, dim>& grad, 
00251                          SymmTensor& strain) const
00252       {
00253           
00254           if (dim==2) {
00255               
00256               strain[0] = grad[0][0];
00257               strain[1] = grad[1][1];
00258               strain[2] = grad[0][1] + grad[1][0];
00259               
00260           } else if (dim==3) {
00261               
00262               strain[0] = grad[0][0];
00263               strain[1] = grad[1][1];
00264               strain[2] = grad[2][2];
00265               strain[3] = grad[0][1] + grad[1][0];
00266               strain[4] = grad[0][2] + grad[2][0];
00267               strain[5] = grad[2][1] + grad[1][2];
00268               
00269           } else
00270                 DUNE_THROW(NotImplemented, "No elasticity assembler for " << dim << "-dimensional problems");
00271       }
00272       
00273       
00274       SymmTensor hookeTimesStrain(const SymmTensor& strain) const {
00275           
00276           if (dim==3) {
00277               
00278               // compute Hooke Tensor
00279               FieldMatrix<double, 6, 6> hookeTensor;
00280               
00281               hookeTensor = 0;
00282               
00283               hookeTensor[0][0] = 1-nu_;
00284               hookeTensor[0][1] = nu_;
00285               hookeTensor[0][2] = nu_;
00286               
00287               hookeTensor[1][0] = nu_;
00288               hookeTensor[1][1] = 1-nu_;
00289               hookeTensor[1][2] = nu_;
00290               
00291               hookeTensor[2][0] = nu_;
00292               hookeTensor[2][1] = nu_;
00293               hookeTensor[2][2] = 1-nu_;
00294               
00295               hookeTensor[3][3] = 0.5 -nu_;
00296               hookeTensor[4][4] = 0.5 -nu_;
00297               hookeTensor[5][5] = 0.5 -nu_;
00298               
00299               hookeTensor *= (E_/(1+nu_)/(1-2*nu_));
00300               
00301               // compute stress
00302               SymmTensor stress;
00303               stress = 0;
00304               hookeTensor.umv(strain, stress);
00305               
00306               return stress;
00307               
00308           } else if (dim==2) {
00309               
00310               // compute Hooke Tensor
00311               FieldMatrix<double, 3, 3> hookeTensor;
00312               
00313               hookeTensor = 0;
00314               
00315               hookeTensor[0][0] = 1-nu_;
00316               hookeTensor[0][1] = nu_;
00317               
00318               hookeTensor[1][0] = nu_;
00319               hookeTensor[1][1] = 1-nu_;
00320               
00321               hookeTensor[2][2] = 0.5 -nu_;
00322               
00323               hookeTensor *= (E_/(1+nu_)/(1-2*nu_));
00324               
00325               // compute stress
00326               SymmTensor stress;
00327               stress = 0;
00328               hookeTensor.umv(strain, stress);
00329               
00330               return stress;
00331               
00332           } else
00333               DUNE_THROW(NotImplemented, "No elasticity assembler for " << dim << "-dimensional problems");
00334           
00335       }
00336 
00338         void assembleBoundaryCondition (const Entity& e, int k=1)
00339         {
00340         }
00341 
00342   private:
00343 
00344         // parameters given in constructor
00345         bool procBoundaryAsDirichlet;
00346 
00347   };
00348 
00350 }
00351 #endif

Generated on 6 Jan 2009 with Doxygen (ver 1.5.1) [logfile].