HexahedronFEMForceField.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_COMPONENT_FORCEFIELD_HEXAHEDRONFEMFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_HEXAHEDRONFEMFORCEFIELD_INL
00027 
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include <sofa/component/forcefield/HexahedronFEMForceField.h>
00030 #include <sofa/helper/PolarDecompose.h>
00031 #include <sofa/helper/gl/template.h>
00032 #include <assert.h>
00033 #include <iostream>
00034 #include <set>
00035 
00036 using std::cerr;
00037 using std::endl;
00038 using std::set;
00039 
00040 
00041 
00042 // WARNING: indices ordering is different than in topology node
00043 //
00044 //     Y  7---------6
00045 //     ^ /         /|
00046 //     |/    Z    / |
00047 //     3----^----2  |
00048 //     |   /     |  |
00049 //     |  4------|--5
00050 //     | /       | /
00051 //     |/        |/
00052 //     0---------1-->X
00053 
00054 
00055 
00056 
00057 
00058 namespace sofa
00059 {
00060 
00061 namespace component
00062 {
00063 
00064 namespace forcefield
00065 {
00066 
00067 using namespace sofa::defaulttype;
00068 
00069 #ifndef SOFA_NEW_HEXA
00070 template<class DataTypes> const int HexahedronFEMForceField<DataTypes>::_indices[8] = {0,1,3,2,4,5,7,6};
00071 // template<class DataTypes> const int HexahedronFEMForceField<DataTypes>::_indices[8] = {4,5,7,6,0,1,3,2};
00072 #endif
00073 
00074 template<class DataTypes>
00075 void HexahedronFEMForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00076 {
00077     this->core::componentmodel::behavior::ForceField<DataTypes>::parse(arg);
00078     
00079 }
00080 
00081 template <class DataTypes>
00082 void HexahedronFEMForceField<DataTypes>::init()
00083 {
00084     if(_alreadyInit)return;
00085     else _alreadyInit=true;
00086     
00087     this->core::componentmodel::behavior::ForceField<DataTypes>::init();
00088     if( this->getContext()->getMeshTopology()==NULL )
00089     {
00090         std::cerr << "ERROR(HexahedronFEMForceField): object must have a Topology.\n";
00091         return;
00092     }
00093     
00094     _mesh = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(this->getContext()->getMeshTopology());
00095     if ( _mesh==NULL)
00096     {
00097         std::cerr << "ERROR(HexahedronFEMForceField): object must have a MeshTopology.\n";
00098         return;
00099     }
00100 #ifdef SOFA_NEW_HEXA
00101     else if( _mesh->getNbHexas()<=0 )
00102 #else
00103     else if( _mesh->getNbCubes()<=0 )
00104 #endif
00105     {
00106         std::cerr << "ERROR(HexahedronFEMForceField): object must have a hexahedric MeshTopology.\n";
00107         std::cerr << _mesh->getName()<<std::endl;
00108         std::cerr << _mesh->getTypeName()<<std::endl;
00109         cerr<<_mesh->getNbPoints()<<endl;
00110         return;
00111     }
00112 //  if (!_mesh->getCubes().empty())
00113 //  else
00114 //  {
00115 #ifdef SOFA_NEW_HEXA
00116         _indexedElements = & (_mesh->getHexas());
00117 #else
00118         _indexedElements = & (_mesh->getCubes());
00119 #endif
00120 //  }
00121     _sparseGrid = dynamic_cast<topology::SparseGridTopology*>(_mesh);
00122     
00123 
00124     
00125     if (_initialPoints.getValue().size() == 0)
00126     {
00127       VecCoord& p = *this->mstate->getX();
00128       _initialPoints.setValue(p);
00129     }
00130     
00131     _materialsStiffnesses.resize(_indexedElements->size() );
00132     _rotations.resize( _indexedElements->size() );
00133     _rotatedInitialElements.resize(_indexedElements->size());
00134     
00135     
00136     
00137     
00138 //  if( _elementStiffnesses.getValue().empty() )
00139 //      _elementStiffnesses.beginEdit()->resize(_indexedElements->size());
00140     //  _stiffnesses.resize( _initialPoints.getValue().size()*3 ); // assembly ?
00141     
00142     reinit();
00143     
00144     
00145     
00146 //  unsigned int i=0;
00147 //  typename VecElement::const_iterator it;
00148 //  for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00149 //  {
00150 //      Element c = *it;
00151 //      for(int w=0;w<8;++w)
00152 //      {
00153 //          cerr<<"sparse w : "<<c[w]<<"    "<<_initialPoints.getValue()[c[w]]<<endl;
00154 //      }
00155 //      cerr<<"------\n";
00156 //  }
00157     
00158 
00159     
00160 }
00161 
00162 
00163 template <class DataTypes>
00164         void HexahedronFEMForceField<DataTypes>::reinit()
00165 {
00166   if (f_method.getValue() == "large")
00167     this->setMethod(LARGE);
00168   else if (f_method.getValue() == "polar")
00169     this->setMethod(POLAR);
00170   
00171     switch(method)
00172     {
00173         case LARGE :
00174         {
00175             unsigned int i=0;
00176             typename VecElement::const_iterator it;
00177             for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00178             {
00179                 computeMaterialStiffness(i);
00180                 initLarge(i,*it);
00181             }
00182             break;
00183         }
00184         case POLAR :
00185         {
00186             unsigned int i=0;
00187             typename VecElement::const_iterator it;
00188             for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00189             {
00190                 computeMaterialStiffness(i);
00191                 initPolar(i,*it);
00192             }
00193             break;
00194         }
00195     }
00196 }
00197 
00198 
00199 
00203 
00204 
00205 
00206 
00207 template<class DataTypes>
00208 void HexahedronFEMForceField<DataTypes>::addForce (VecDeriv& f, const VecCoord& p, const VecDeriv& /*v*/)
00209 {
00210     f.resize(p.size());
00211 
00212     unsigned int i=0;
00213     typename VecElement::const_iterator it;
00214     
00215     
00216     
00217     switch(method)
00218     {
00219         case LARGE :
00220         {
00221             for(it=_indexedElements->begin();it!=_indexedElements->end();++it,++i)
00222             {
00223                 accumulateForceLarge( f, p, i, *it );
00224             }
00225             break;
00226         }
00227         case POLAR :
00228         {
00229             for(it=_indexedElements->begin();it!=_indexedElements->end();++it,++i)
00230             {
00231                 accumulateForcePolar( f, p, i, *it );
00232             }
00233             break;
00234         }
00235     }
00236     
00237 
00238 }
00239 
00240 template<class DataTypes>
00241 void HexahedronFEMForceField<DataTypes>::addDForce (VecDeriv& v, const VecDeriv& x)
00242 {
00243     if( v.size()!=x.size() ) v.resize(x.size());
00244 
00245     
00246         unsigned int i=0;
00247         typename VecElement::const_iterator it;
00248         
00249                 for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00250                 {
00251                     
00252                     Transformation R_0_2;
00253                     R_0_2.transpose(_rotations[i]);
00254 
00255                     Displacement X;
00256                     
00257                     for(int w=0;w<8;++w)
00258                     {
00259                         Coord x_2;
00260 #ifndef SOFA_NEW_HEXA
00261                         x_2 = R_0_2 * x[(*it)[_indices[w]]];
00262 #else
00263                         x_2 = R_0_2 * x[(*it)[w]];
00264 #endif
00265                         X[w*3] = x_2[0];
00266                         X[w*3+1] = x_2[1];
00267                         X[w*3+2] = x_2[2];
00268                     }
00269                     
00270                     Displacement F;
00271                     computeForce( F, X, _elementStiffnesses.getValue()[i] );
00272                     
00273                     for(int w=0;w<8;++w)
00274 #ifndef SOFA_NEW_HEXA
00275                         v[(*it)[_indices[w]]] -= _rotations[i] * Deriv( F[w*3],  F[w*3+1],  F[w*3+2]  );
00276 #else
00277                         v[(*it)[w]] -= _rotations[i] * Deriv( F[w*3],  F[w*3+1],  F[w*3+2]  );
00278 #endif
00279                 }
00280                 
00281 }
00282 
00283 template <class DataTypes> 
00284     double HexahedronFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00285 {
00286     std::cerr<<"HexahedronFEMForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00287     return 0;
00288 }
00289 
00290 
00291 
00292 
00293 
00297 
00298 
00299 
00300 
00301 // enable to use generic matrix computing code instead of the original optimized code specific to parallelepipeds
00302 #define GENERIC_STIFFNESS_MATRIX
00303 // enable to use the full content of the MaterialStiffness matrix, instead of only the 3x3 upper bloc
00304 #define MAT_STIFFNESS_USE_W
00305 // enable to use J when computing qx/qy/qz, instead of computing the matrix relative to (x1,x2,x3) and pre/post multiply by J^-1 afterward.
00306 // note that this does not matter if the element is a cube.
00307 #define DN_USE_J
00308 
00309 
00310 template<class DataTypes>
00311 void HexahedronFEMForceField<DataTypes>::computeElementStiffness( ElementStiffness &K, const MaterialStiffness &M, const helper::fixed_array<Coord,8> &nodes, const int elementIndice, double stiffnessFactor)
00312 {
00313 //  cerr<<"HexahedronFEMForceField<DataTypes>::computeElementStiffnessAsFinest\n";
00314     
00315     const bool verbose = this->f_printLog.getValue() && (elementIndice==0);
00316     // X = n0 (1-x1)(1-x2)(1-x3)/8 + n1 (1+x1)(1-x2)(1-x3)/8 + n2 (1+x1)(1+x2)(1-x3)/8 + n3 (1-x1)(1+x2)(1-x3)/8 + n4 (1-x1)(1-x2)(1+x3)/8 + n5 (1+x1)(1-x2)(1+x3)/8 + n6 (1+x1)(1+x2)(1+x3)/8 + n7 (1-x1)(1+x2)(1+x3)/8
00317     // J = [ DXi / xj ] = [ (n1i-n0i)(1-x2)(1-x3)/8+(n2i-n3i)(1+x2)(1-x3)/8+(n5i-n4i)(1-x2)(1+x3)/8+(n6i-n7i)(1+x2)(1+x3)/8  (n3i-n0i)(1-x1)(1-x3)/8+(n2i-n1i)(1+x1)(1-x3)/8+(n7i-n4i)(1-x1)(1+x3)/8+(n6i-n5i)(1+x1)(1+x3)/8  (n4i-n0i)(1-x1)(1-x2)/8+(n5i-n1i)(1+x1)(1-x2)/8+(n6i-n2i)(1+x1)(1+x2)/8+(n7i-n3i)(1-x1)(1+x2)/8 ]
00318     // if it is an orthogonal regular hexahedra: J = [ [ l0/2 0 0 ] [ 0 l1/2 0 ] [ 0 0 l2/2 ] ] det(J) = l0l1l2/8 = vol/8
00319     //
00320     // Ke = integralV(BtEBdv) = integral(BtEB det(J) dx1 dx2 dx3)
00321     // B = DN = [ qx 0  0  ]
00322     //          [ 0  qy 0  ]
00323     //          [ 0  0  qz ]
00324     //          [ qy qx 0  ]
00325     //          [ 0  qz qy ]
00326     //          [ qz 0  qx ]
00327     // with qx = [ dN1/dx ... dN8/dx ] qy = [ dN1/dy ... dN8/dy ] qz = [ dN1/dz ... dN8/dz ]
00328     // The submatrix Kij of K linking nodes i and j can then be computed as: Kij = integralV(Bjt E Bi det(J) dx1 dx2 dx3)
00329     // with Bi = part of B related to node i: Bi = [ [ dNi/dx 0 0 ] [ 0 dNi/dy 0 ] [ 0 0 dNi/dz ] [ dNi/dy dNi/dx 0 ] [ 0 dNi/dz dNi/dy ] [ dNi/dz 0 dNi/dx ] ]
00330     // This integral can be estimated using 8 gauss quadrature points (x1,x2,x3)=(+-1/sqrt(3),+-1/sqrt(3),+-sqrt(3))
00331     K.fill( 0.0 );
00332     Mat33 J; // J[i][j] = dXi/dxj
00333     Mat33 J_1; // J_1[i][j] = dxi/dXj
00334     Mat33 J_1t;
00335     Real detJ = (Real)1.0;
00336     // check if the hexaedra is a parallelepiped
00337     Coord lx = nodes[1]-nodes[0];
00338     Coord ly = nodes[3]-nodes[0];
00339     Coord lz = nodes[4]-nodes[0];
00340     bool isParallel = false;
00341     if ((nodes[3]+lx-nodes[2]).norm() < lx.norm()*0.001 && (nodes[0]+lz-nodes[4]).norm() < lz.norm()*0.001 && (nodes[1]+lz-nodes[5]).norm() < lz.norm()*0.001 && (nodes[2]+lz-nodes[6]).norm() < lz.norm()*0.001 && (nodes[3]+lz-nodes[7]).norm() < lz.norm()*0.001)
00342     {
00343         isParallel = true;
00344         for (int c=0;c<3;++c)
00345         {
00346             J[c][0] = lx[c]/2;
00347             J[c][1] = ly[c]/2;
00348             J[c][2] = lz[c]/2;
00349         }
00350         detJ = defaulttype::determinant(J);
00351         J_1.invert(J);
00352         J_1t.transpose(J_1);
00353         if (verbose)
00354         {
00355             std::cout << "J = "<<J<<std::endl;
00356             std::cout << "invJ = "<<J_1<<std::endl;
00357             std::cout << "detJ = "<<detJ<<std::endl;
00358         }
00359     }
00360 //     else
00361 //         std::cout << "Hexa "<<elementIndice<<" is NOT a parallelepiped.\n";
00362     
00363     const Real U = M[0][0];
00364     const Real V = M[0][1];
00365 #ifdef MAT_STIFFNESS_USE_W
00366     const Real W = M[3][3];
00367 #else
00368     const Real W = M[2][2];
00369 #endif
00370     const double inv_sqrt3 = 1.0/sqrt(3.0);
00371     for (int gx1=-1;gx1<=1;gx1+=2)
00372     for (int gx2=-1;gx2<=1;gx2+=2)
00373     for (int gx3=-1;gx3<=1;gx3+=2)
00374     {
00375         double x1 = gx1*inv_sqrt3;
00376         double x2 = gx2*inv_sqrt3;
00377         double x3 = gx3*inv_sqrt3;
00378         // compute jacobian matrix
00379         //Mat33 J; // J[i][j] = dXi/dxj
00380         //Mat33 J_1; // J_1[i][j] = dxi/dXj
00381         if (!isParallel)
00382         {
00383             for (int c=0;c<3;++c)
00384             {
00385                 J[c][0] = (Real)( (nodes[1][c]-nodes[0][c])*(1-x2)*(1-x3)/8+(nodes[2][c]-nodes[3][c])*(1+x2)*(1-x3)/8+(nodes[5][c]-nodes[4][c])*(1-x2)*(1+x3)/8+(nodes[6][c]-nodes[7][c])*(1+x2)*(1+x3)/8);
00386         J[c][1] =(Real)( (nodes[3][c]-nodes[0][c])*(1-x1)*(1-x3)/8+(nodes[2][c]-nodes[1][c])*(1+x1)*(1-x3)/8+(nodes[7][c]-nodes[4][c])*(1-x1)*(1+x3)/8+(nodes[6][c]-nodes[5][c])*(1+x1)*(1+x3)/8);
00387         J[c][2] =(Real)( (nodes[4][c]-nodes[0][c])*(1-x1)*(1-x2)/8+(nodes[5][c]-nodes[1][c])*(1+x1)*(1-x2)/8+(nodes[6][c]-nodes[2][c])*(1+x1)*(1+x2)/8+(nodes[7][c]-nodes[3][c])*(1-x1)*(1+x2)/8);
00388             }
00389             detJ = defaulttype::determinant(J);
00390             J_1.invert(J);
00391             J_1t.transpose(J_1);
00392             if (verbose)
00393             {
00394                 std::cout << "J = "<<J<<std::endl;
00395                 std::cout << "invJ = "<<J_1<<std::endl;
00396                 std::cout << "detJ = "<<detJ<<std::endl;
00397             }
00398         }
00399         Real qx[8];
00400     Real qy[8];
00401     Real qz[8];
00402         for(int i=0;i<8;++i)
00403         {
00404             // Ni = 1/8 (1+_coef[i][0]x1)(1+_coef[i][1]x2)(1+_coef[i][2]x3)
00405             // qxi = dNi/dx = dNi/dx1 dx1/dx + dNi/dx2 dx2/dx + dNi/dx3 dx3/dx
00406       Real dNi_dx1 =(Real)( (_coef[i][0])*(1+_coef[i][1]*x2)*(1+_coef[i][2]*x3)/8.0);
00407       Real dNi_dx2 =(Real)((1+_coef[i][0]*x1)*(_coef[i][1])*(1+_coef[i][2]*x3)/8.0);
00408       Real dNi_dx3 =(Real)((1+_coef[i][0]*x1)*(1+_coef[i][1]*x2)*(_coef[i][2])/8.0);
00409             if (verbose) std::cout << "dN"<<i<<"/dxi = "<<dNi_dx1<<" "<<dNi_dx2<<" "<<dNi_dx3<<"\n";
00410 #ifdef DN_USE_J
00411             qx[i] = dNi_dx1*J_1[0][0] + dNi_dx2*J_1[1][0] + dNi_dx3*J_1[2][0];
00412             qy[i] = dNi_dx1*J_1[0][1] + dNi_dx2*J_1[1][1] + dNi_dx3*J_1[2][1];
00413             qz[i] = dNi_dx1*J_1[0][2] + dNi_dx2*J_1[1][2] + dNi_dx3*J_1[2][2];
00414             if (verbose) std::cout << "q"<<i<<" = "<<qx[i]<<" "<<qy[i]<<" "<<qz[i]<<"\n";
00415 #else
00416             qx[i] = dNi_dx1;
00417             qy[i] = dNi_dx2;
00418             qz[i] = dNi_dx3;
00419 #endif
00420         }
00421         for(int i=0;i<8;++i)
00422         {
00423             Mat<6,3,Real> MBi;
00424             //MBi[0][0] = M[0][0] * qx[i]; MBi[0][1] = M[0][1] * qy[i]; MBi[0][2] = M[0][2] * qz[i];
00425             //MBi[1][0] = M[1][0] * qx[i]; MBi[1][1] = M[1][1] * qy[i]; MBi[1][2] = M[1][2] * qz[i];
00426             //MBi[2][0] = M[2][0] * qx[i]; MBi[2][1] = M[2][1] * qy[i]; MBi[2][2] = M[2][2] * qz[i];
00427             //MBi[3][0] = M[3][3] * qy[i]; MBi[3][1] = M[3][3] * qx[i]; MBi[3][2] = 0;
00428             //MBi[4][0] = 0;               MBi[4][1] = M[4][4] * qz[i]; MBi[4][2] = M[4][4] * qy[i];
00429             //MBi[5][0] = M[5][5] * qz[i]; MBi[5][1] = 0;               MBi[5][2] = M[5][5] * qx[i];
00430             MBi[0][0] = U * qx[i]; MBi[0][1] = V * qy[i]; MBi[0][2] = V * qz[i];
00431             MBi[1][0] = V * qx[i]; MBi[1][1] = U * qy[i]; MBi[1][2] = V * qz[i];
00432             MBi[2][0] = V * qx[i]; MBi[2][1] = V * qy[i]; MBi[2][2] = U * qz[i];
00433         MBi[3][0] = W * qy[i]; MBi[3][1] = W * qx[i]; MBi[3][2] = (Real)0;
00434         MBi[4][0] = (Real)0;   MBi[4][1] = W * qz[i]; MBi[4][2] = W * qy[i];
00435         MBi[5][0] = W * qz[i]; MBi[5][1] = (Real)0;   MBi[5][2] = W * qx[i];
00436             if (verbose) std::cout << "MB"<<i<<" = "<<MBi<<"\n";
00437             for(int j=i;j<8;++j)
00438             {
00439                 Mat33 k; // k = BjtMBi
00440                 k[0][0] = qx[j]*MBi[0][0]   + qy[j]*MBi[3][0]   + qz[j]*MBi[5][0];
00441                 k[0][1] = qx[j]*MBi[0][1]   + qy[j]*MBi[3][1] /*+ qz[j]*MBi[5][1]*/;
00442                 k[0][2] = qx[j]*MBi[0][2] /*+ qy[j]*MBi[3][2]*/ + qz[j]*MBi[5][2];
00443                 
00444                 k[1][0] = qy[j]*MBi[1][0]   + qx[j]*MBi[3][0] /*+ qz[j]*MBi[4][0]*/;
00445                 k[1][1] = qy[j]*MBi[1][1]   + qx[j]*MBi[3][1]   + qz[j]*MBi[4][1];
00446                 k[1][2] = qy[j]*MBi[1][2] /*+ qx[j]*MBi[3][2]*/ + qz[j]*MBi[4][2];
00447                 
00448                 k[2][0] = qz[j]*MBi[2][0] /*+ qy[j]*MBi[4][0]*/ + qx[j]*MBi[5][0];
00449                 k[2][1] = qz[j]*MBi[2][1]   + qy[j]*MBi[4][1] /*+ qx[j]*MBi[5][1]*/;
00450                 k[2][2] = qz[j]*MBi[2][2]   + qy[j]*MBi[4][2]   + qx[j]*MBi[5][2];
00451 #ifndef DN_USE_J
00452                 k = J_1t*k*J_1;
00453 #endif
00454                 if (verbose) std::cout << "K"<<i<<j<<" += "<<k<<" * "<<detJ<<"\n";
00455                 k *= detJ;
00456                 for(int m=0;m<3;++m)
00457                     for(int l=0;l<3;++l)
00458                     {
00459                         K[i*3+m][j*3+l] += k[l][m];
00460                     }
00461             }
00462         }
00463     }
00464     for(int i=0;i<24;++i)
00465         for(int j=i+1;j<24;++j)
00466         {
00467             K[j][i] = K[i][j];
00468         }
00469     ElementStiffness K1 = K;
00470     K.fill( 0.0 );
00471     
00472     
00473     
00474     
00475     
00476     //Mat33 J_1; // only accurate for orthogonal regular hexa
00477     J_1.fill( 0.0 );
00478     Coord l = nodes[6] - nodes[0];
00479     J_1[0][0]=2.0f / l[0];
00480     J_1[1][1]=2.0f / l[1];
00481     J_1[2][2]=2.0f / l[2];
00482     
00483 
00484     Real vol = ((nodes[1]-nodes[0]).norm()*(nodes[3]-nodes[0]).norm()*(nodes[4]-nodes[0]).norm());
00485         //vol *= vol;
00486     vol /= 8.0; // ???
00487     
00488     K.clear();
00489     
00490     
00491     for(int i=0;i<8;++i)
00492     {
00493         Mat33 k = vol*integrateStiffness(  _coef[i][0], _coef[i][1],_coef[i][2],  _coef[i][0], _coef[i][1],_coef[i][2], M[0][0], M[0][1],M[3][3], J_1  );
00494         
00495         
00496         for(int m=0;m<3;++m)
00497             for(int l=0;l<3;++l)
00498         {
00499                 K[i*3+m][i*3+l] += k[m][l];
00500         }       
00501         
00502                     
00503     
00504         for(int j=i+1;j<8;++j)
00505         {
00506             Mat33 k = vol*integrateStiffness(  _coef[i][0], _coef[i][1],_coef[i][2],  _coef[j][0], _coef[j][1],_coef[j][2], M[0][0], M[0][1],M[3][3], J_1  );
00507             
00508     
00509             for(int m=0;m<3;++m)
00510                 for(int l=0;l<3;++l)
00511             {
00512                 K[i*3+m][j*3+l] += k[m][l];
00513 //                  K[j*3+l][i*3+m] += k[m][l];
00514             }
00515         }
00516     }
00517 
00518     for(int i=0;i<24;++i)
00519         for(int j=i+1;j<24;++j)
00520     {
00521         K[j][i] = K[i][j];
00522     }
00523 //  if (elementIndice==0)
00524 //  {
00525 //      std::cout << "nodes = "<<nodes[0]<<"  "<<nodes[1]<<"  "<<nodes[2]<<"  "<<nodes[3]<<"  "<<nodes[4]<<"  "<<nodes[5]<<"  "<<nodes[6]<<"  "<<nodes[7]<<std::endl;
00526 //      std::cout << "M = "<<M<<std::endl;
00527 //      std::cout << "K = "<<std::endl;
00528 //      for (int i=0;i<24;i++)
00529 //          std::cout << K[i] << std::endl;
00530 //      std::cout << "K1 = "<<std::endl;
00531 //      for (int i=0;i<24;i++)
00532 //          std::cout << K1[i] << std::endl;
00533 //  }
00534 #ifdef GENERIC_STIFFNESS_MATRIX
00535     K=K1;
00536 #endif
00537     
00538       K *= (Real)stiffnessFactor;
00539 
00540 }
00541 
00542 
00543 
00544 
00545 template<class DataTypes>
00546 typename HexahedronFEMForceField<DataTypes>::Mat33 HexahedronFEMForceField<DataTypes>::integrateStiffness( int signx0, int signy0, int signz0, int signx1, int signy1, int signz1, const Real u, const Real v, const Real w, const Mat33& J_1  )
00547 {
00548 //  Real xmax=1,ymax=1,zmax=1,xmin=-1,ymin=-1,zmin=-1;
00549 //  Real t1 = (Real)(signx0*signy0);
00550 //  Real t2 = signz0*w;
00551 //  Real t3 = t2*signx1;
00552 //  Real t4 = t1*t3;
00553 //  Real t5 = xmax-xmin;
00554 //  Real t6 = t5*signy1/2.0f;
00555 //  Real t7 = ymax-ymin;
00556 //  Real t8 = t6*t7/2.0f;
00557 //  Real t9 = zmax-zmin;
00558 //  Real t10 = signz1*t9/2.0f;
00559 //  Real t12 = t8*t10*J_1[0][0];
00560 //  Real t15 = signz0*u;
00561 //  Real t17 = t1*t15*signx1;
00562 //  Real t20 = (Real)(signy0*signz0);
00563 //  Real t23 = 1.0f+signx1*(xmax+xmin)/2.0f;
00564 //  Real t24 = w*t23;
00565 //  Real t26 = signy1*t7/2.0f;
00566 //  Real t27 = t26*t10;
00567 //  Real t28 = t20*t24*t27;
00568 //  Real t29 = (Real)(signx0*signz0);
00569 //  Real t30 = u*signx1;
00570 //  Real t34 = 1.0f+signy1*(ymax+ymin)/2.0f;
00571 //  Real t35 = t5*t34/2.0f;
00572 //  Real t36 = t35*t10;
00573 //  Real t37 = t29*t30*t36;
00574 //  Real t44 = 1.0f+signz1*(zmax+zmin)/2.0f;
00575 //  Real t46 = t6*t7*t44/2.0f;
00576 //  Real t47 = t1*t30*t46;
00577 //  Real t53 = t35*t44;
00578 //  Real t55 = t2*t23;
00579 //  Real t57 = t34*signz1*t9/2.0f;
00580 //  Real t58 = t55*t57;
00581 //  Real t59 = signy0*w;
00582 //  Real t60 = t59*t23;
00583 //  Real t61 = t26*t44;
00584 //  Real t62 = t60*t61;
00585 //  Real t66 = w*signx1;
00586 //  Real t67 = t1*t66;
00587 //  Real t68 = t67*t46;
00588 //  Real t69 = t29*t66;
00589 //  Real t70 = t69*t36;
00590 //  Real t75 = v*t23;
00591 //  Real t78 = t20*t66;
00592 //  Real t84 = signx0*v*t23;
00593 //  Real t104 = v*signx1;
00594 //  Real t105 = t20*t104;
00595 //  Real t112 = signy0*v;
00596 //  Real t115 = signx0*w;
00597 //  Real t116 = t115*t23;
00598 //  Real t123 = t8*t10*J_1[1][1];
00599 //  Real t130 = t20*u*t23*t27;
00600 //  Real t141 = t115*signx1*t53;
00601 //  Real t168 = signz0*v;
00602 //  Real t190 = t8*t10*J_1[2][2];
00603 //  Mat33 K;
00604 //  K[0][0] = t4*t12/36.0f+t17*t12/72.0f+(t28+t37)*J_1[0][0]/24.0f+(t47+t28)*J_1[0][0]/
00605 //          24.0f+(signx0*u*signx1*t53+t58+t62)*J_1[0][0]/8.0f+(t68+t70)*J_1[0][0]/24.0f;
00606 //  K[0][1] = (t29*t75*t27+t78*t36)*J_1[1][1]/24.0f+(t84*t61+t59*signx1*t53)*J_1[1][1]
00607 // /8.0f;
00608 //  K[0][2] = (t1*t75*t27+t78*t46)*J_1[2][2]/24.0f+(t84*t57+t3*t53)*J_1[2][2]/8.0f;
00609 //  K[1][0] = (t105*t36+t29*t24*t27)*J_1[0][0]/24.0f+(t112*signx1*t53+t116*t61)
00610 //          *J_1[0][0]/8.0f;
00611 //  K[1][1] = t17*t123/72.0f+t4*t123/36.0f+(t70+t130)*J_1[1][1]/24.0f+(t68+t28)*
00612 //          J_1[1][1]/24.0f+(signy0*u*t23*t61+t58+t141)*J_1[1][1]/8.0f+(t47+t70)*J_1[1][1]/24.0f;
00613 //  K[1][2] = (t1*t104*t36+t69*t46)*J_1[2][2]/24.0f+(t112*t23*t57+t55*t61)*J_1[2][2]/
00614 //          8.0f;
00615 //  K[2][0] = (t105*t46+t1*t24*t27)*J_1[0][0]/24.0f+(t168*signx1*t53+t116*t57)*
00616 //          J_1[0][0]/8.0f;
00617 //  K[2][1] = (t29*t104*t46+t67*t36)*J_1[1][1]/24.0f+(t168*t23*t61+t60*t57)*J_1[1][1]/
00618 //          8.0f;
00619 //  K[2][2] = t4*t190/36.0f+(t28+t70)*J_1[2][2]/24.0f+t17*t190/72.0f+(t68+t130)*
00620 //          J_1[2][2]/24.0f+(t15*t23*t57+t62+t141)*J_1[2][2]/8.0f+(t68+t37)*J_1[2][2]/24.0f;
00621 // 
00622 //  return J_1 * K;
00623     
00624     Mat33 K;
00625     
00626     Real t1 = J_1[0][0]*J_1[0][0];                // m^-2            (J0J0             )
00627     Real t2 = t1*signx0;                          // m^-2            (J0J0    sx0      )
00628     Real t3 = (Real)(signy0*signz0);              //                 (           sy0sz0)
00629     Real t4 = t2*t3;                              // m^-2            (J0J0    sx0sy0sz0)
00630     Real t5 = w*signx1;                           // kg m^-4 s^-2    (W       sx1      )
00631     Real t6 = (Real)(signy1*signz1);              //                 (           sy1sz1)
00632     Real t7 = t5*t6;                              // kg m^-4 s^-2    (W       sx1sy1sz1)
00633     Real t10 = t1*signy0;                         // m^-2            (J0J0       sy0   )
00634     Real t12 = w*signy1;                          // kg m^-4 s^-2    (W          sy1   )
00635     Real t13 = t12*signz1;                        // kg m^-4 s^-2    (W          sy1sz1)
00636     Real t16 = t2*signz0;                         // m^-2            (J0J0    sx0   sz0)
00637     Real t17 = u*signx1;                          // kg m^-4 s^-2    (U       sx1      )
00638     Real t18 = t17*signz1;                        // kg m^-4 s^-2    (U       sx1   sz1)
00639     Real t21 = t17*t6;                            // kg m^-4 s^-2    (U       sx1sy1sz1)
00640     Real t24 = t2*signy0;                         // m^-2            (J0J0    sx0sy0   )
00641     Real t25 = t17*signy1;                        // kg m^-4 s^-2    (U       sx1sy1   )
00642     Real t28 = t5*signy1;                         // kg m^-4 s^-2    (W       sx1sy1   )
00643     Real t32 = w*signz1;                          // kg m^-4 s^-2    (W             sz1)
00644     Real t37 = t5*signz1;                         // kg m^-4 s^-2    (W       sx1   sz1)
00645     Real t43 = J_1[0][0]*signx0;                  // m^-1            (J0      sx0      )
00646     Real t45 = v*J_1[1][1];                       // kg m^-5 s^-2    (VJ1              )
00647     Real t49 = J_1[0][0]*signy0;                  // m^-1            (J0         sy0   )
00648     Real t50 = t49*signz0;                        // m^-1            (J0         sy0sz0)
00649     Real t51 = w*J_1[1][1];                       // kg m^-5 s^-2    (WJ1              )
00650     Real t52 = (Real)(signx1*signz1);             //                 (        sx1   sz1)
00651     Real t53 = t51*t52;                           // kg m^-5 s^-2    (WJ1     sx1   sz1)
00652     Real t56 = t45*signy1;                        // kg m^-5 s^-2    (VJ1        sy1   )
00653     Real t64 = v*J_1[2][2];                       // kg m^-5 s^-2    (VJ2              )
00654     Real t68 = w*J_1[2][2];                       // kg m^-5 s^-2    (WJ2              )
00655         Real t69 = (Real)(signx1*signy1);             //                 (        sx1sy1   )
00656     Real t70 = t68*t69;                           // kg m^-5 s^-2    (WJ2     sx1sy1   )
00657     Real t73 = t64*signz1;                        // kg m^-5 s^-2    (VJ2           sz1)
00658     Real t81 = J_1[1][1]*signy0;                  // m^-1            (J1         sy0   )
00659     Real t83 = v*J_1[0][0];                       // kg m^-5 s^-2    (VJ0              )
00660     Real t87 = J_1[1][1]*signx0;                  // m^-1            (J1      sx0      )
00661     Real t88 = t87*signz0;                        // m^-1            (J1      sx0   sz0)
00662     Real t89 = w*J_1[0][0];                       // kg m^-5 s^-2    (WJ0              )
00663     Real t90 = t89*t6;                            // kg m^-5 s^-2    (WJ0        sy1sz1)
00664     Real t93 = t83*signx1;                        // kg m^-5 s^-2    (VJ0     sx1      )
00665     Real t100 = J_1[1][1]*J_1[1][1];              // m^-2            (J1J1             )
00666     Real t101 = t100*signx0;                      // m^-2            (J1J1    sx0      )
00667     Real t102 = t101*t3;                          // m^-2            (J1J1    sx0sy0sz0)
00668     Real t110 = t100*signy0;                      // m^-2            (J1J1       sy0   )
00669     Real t111 = t110*signz0;                      // m^-2            (J1J1       sy0sz0)
00670     Real t112 = u*signy1;                         // kg m^-4 s^-2    (U          sy1   )
00671     Real t113 = t112*signz1;                      // kg m^-4 s^-2    (U          sy1sz1)
00672     Real t116 = t101*signy0;                      // m^-2            (J1J1    sx0sy0   )
00673     Real t144 = J_1[2][2]*signy0;                 // m^-1            (J2         sy0   )
00674     Real t149 = J_1[2][2]*signx0;                 // m^-1            (J2      sx0      )
00675     Real t150 = t149*signy0;                      // m^-1            (J2      sx0sy0   )
00676     Real t153 = J_1[2][2]*signz0;                 // m^-1            (J2            sz0)
00677     Real t172 = J_1[2][2]*J_1[2][2];              // m^-2            (J2J2             )
00678     Real t173 = t172*signx0;                      // m^-2            (J2J2    sx0      )
00679     Real t174 = t173*t3;                          // m^-2            (J2J2    sx0sy0sz0)
00680     Real t177 = t173*signz0;                      // m^-2            (J2J2    sx0   sz0)
00681     Real t180 = t172*signy0;                      // m^-2            (J2J2       sy0   )
00682     Real t181 = t180*signz0;                      // m^-2            (J2J2       sy0sz0)
00683         // kg m^-6 s^-2
00684     K[0][0] = (float)(t4*t7/36.0+t10*signz0*t13/12.0+t16*t18/24.0+t4*t21/72.0+
00685             t24*t25/24.0+t24*t28/24.0+t1*signz0*t32/8.0+t10*t12/8.0+t16*t37/24.0+t2*t17/8.0);
00686         // K00 = (J0J0    sx0sy0sz0)(W       sx1sy1sz1)/36
00687         //     + (J0J0       sy0sz0)(W          sy1sz1)/12
00688         //     + (J0J0    sx0   sz0)(U       sx1   sz1)/24
00689         //     + (J0J0    sx0sy0sz0)(U       sx1sy1sz1)/72
00690         //     + (J0J0    sx0sy0   )(U       sx1sy1   )/24
00691         //     + (J0J0    sx0sy0   )(W       sx1sy1   )/24
00692         //     + (J0J0          sz0)(W             sz1)/8
00693         //     + (J0J0       sy0   )(W          sy1   )/8
00694         //     + (J0J0    sx0   sz0)(W       sx1   sz1)/24
00695         //     + (J0J0    sx0      )(U       sx1      )/8
00696         K[0][1] = (float)(t43*signz0*t45*t6/24.0+t50*t53/24.0+t43*t56/8.0+t49*t51*
00697             signx1/8.0);
00698         // K01 = (J0      sx0   sz0)(VJ1        sy1sz1)/24
00699         //     + (J0         sy0sz0)(WJ1     sx1   sz1)/24
00700         //     + (J0      sx0      )(VJ1        sy1   )/8
00701         //     + (J0         sy0   )(WJ1     sx1      )/8
00702         K[0][2] = (float)(t43*signy0*t64*t6/24.0+t50*t70/24.0+t43*t73/8.0+J_1[0][0]*signz0
00703             *t68*signx1/8.0);
00704         // K02 = (J0      sx0sy0   )(VJ2        sy1sz1)/24
00705         //     + (J0         sy0sz0)(WJ2     sx1sy1   )/24
00706         //     + (J0      sx0      )(VJ2           sz1)/8
00707         //     + (J0            sz0)(WJ2     sx1      )/8
00708         K[1][0] = (float)(t81*signz0*t83*t52/24.0+t88*t90/24.0+t81*t93/8.0+t87*t89*
00709             signy1/8.0);
00710         // K10 = (J1         sy0sz0)(VJ0     sx1   sz1)/24
00711         //     + (J1      sx0   sz0)(WJ0        sy1sz1)/24
00712         //     + (J1         sy0   )(VJ0     sx1      )/8
00713         //     + (J1      sx0      )(WJ0        sy1   )/8
00714         K[1][1] = (float)(t102*t7/36.0+t102*t21/72.0+t101*signz0*t37/12.0+t111*t113
00715             /24.0+t116*t28/24.0+t100*signz0*t32/8.0+t111*t13/24.0+t116*t25/24.0+t110*t112/
00716             8.0+t101*t5/8.0);
00717         // K11 = (J1J1    sx0sy0sz0)(W       sx1sy1sz1)/36
00718         //     + (J1J1    sx0sy0sz0)(U       sx1sy1sz1)/72
00719         //     + (J1J1    sx0   sz0)(W       sx1   sz1)/12
00720         //     + (J1J1       sy0sz0)(U          sy1sz1)/24
00721         //     + (J1J1    sx0sy0   )(W       sx1sy1   )/24
00722         //     + (J1J1          sz0)(W             sz1)/8
00723         //     + (J1J1       sy0sz0)(W          sy1sz1)/24
00724         //     + (J1J1    sx0sy0   )(U       sx1sy1   )/24
00725         //     + (J1J1       sy0   )(U          sy1   )/8
00726         //     + (J1J1    sx0      )(W       sx1      )/8
00727         K[1][2] = (float)(t87*signy0*t64*t52/24.0+t88*t70/24.0+t81*t73/8.0+J_1[1][1]*
00728             signz0*t68*signy1/8.0);
00729         // K12 = (J1      sx0sy0   )(VJ2     sx1   sz1)/24
00730         //     + (J1      sx0   sz0)(WJ2     sx1sy1   )/24
00731         //     + (J1         sy0   )(VJ2           sz1)/8
00732         //     + (J1            sz0)(WJ2        sy1   )/8
00733         K[2][0] = (float)(t144*signz0*t83*t69/24.0+t150*t90/24.0+t153*t93/8.0+t149*
00734             t89*signz1/8.0);
00735         // K20 = (J2         sy0sz0)(VJ0     sx1sy1   )/24
00736         //     + (J2      sx0sy0   )(WJ0        sy1sz1)/24
00737         //     + (J2            sz0)(VJ0     sx1      )/8
00738         //     + (J2      sx0      )(WJ0           sz1)/8
00739         K[2][1] = (float)(t149*signz0*t45*t69/24.0+t150*t53/24.0+t153*t56/8.0+t144*
00740             t51*signz1/8.0);
00741         // K21 = (J2      sx0   sz0)(VJ1     sx1sy1   )/24
00742         //     + (J2      sx0sy0   )(WJ1     sx1   sz1)/24
00743         //     + (J2            sz0)(VJ1        sy1   )/8
00744         //     + (J2         sy0   )(WJ1           sz1)/8
00745         K[2][2] = (float)(t174*t7/36.0+t177*t37/24.0+t181*t13/24.0+t174*t21/72.0+
00746             t173*signy0*t28/12.0+t180*t12/8.0+t181*t113/24.0+t177*t18/24.0+t172*signz0*u*
00747             signz1/8.0+t173*t5/8.0);
00748         // K22 = (J2J2    sx0sy0sz0)(W       sx1sy1sz1)/36
00749         //     + (J2J2    sx0   sz0)(W       sx1   sz1)/24
00750         //     + (J2J2       sy0sz0)(W          sy1sz1)/24
00751         //     + (J2J2    sx0sy0sz0)(U       sx1sy1sz1)/72
00752         //     + (J2J2    sx0sy0   )(W       sx1sy1   )/12
00753         //     + (J2J2       sy0   )(W          sy1   )/8
00754         //     + (J2J2       sy0sz0)(U          sy1sz1)/24
00755         //     + (J2J2    sx0   sz0)(U       sx1   sz1)/24
00756         //     + (J2J2          sz0)(U             sz1)/8
00757         //     + (J2J2    sx0      )(W       sx1      )/8
00758 
00759     return K /*/(J_1[0][0]*J_1[1][1]*J_1[2][2])*/;
00760         
00761         // K = J_1t E J_1
00762         // E00 = Usx0sx1(sy0sz0sy1sz1/9 + sz0sz1/3 + sy0sy1/3 + 1)/8 + W(2sx0sy0sz0sx1sy1sz1/9 + 2sy0sz0sy1sz1/3 + sx0sy0sx1sy1/3 + sx0sz0sx1sz1/3 + sz0sz1 + sy0sy1)/8
00763         // E00 = Usx0sx1(1+sz0sz1/3)(1+sy0sy1/3)/8 + W(1+sx0sx1/3)(2sy0sy1sz0sz1/3+sz0sz1+sy0sy1)/8
00764         // E01 = Vsx0sy1(1+sz0sz1/3)/8             + Wsy0sx1(1+sz0sz1/3)/8
00765         // E02 = Vsx0sz1(1+sy0sy1/3)/8             + Wsz0sx1(1+sy0sy1/3)/8
00766         // E10 = Vsy0sx1(1+sz0sz1/3)/8             + Wsx0sy1(1+sz0sz1/3)/8
00767         // E11 = Usy0sy1(1+sz0sz1/3)(1+sx0sx1/3)/8 + W(1+sy0sy1/3)(2sx0sx1sz0sz1/3+sx0sx1+sz0sz1)/8
00768         // E12 = Vsy0sz1(1+sx0sx1/3)/8             + Wsz0sy1(1+sx0sx1/3)/8
00769         // E20 = Vsz0sx1(1+sy0sy1/3)/8             + Wsx0sz1(1+sy0sy1/3)/8
00770         // E21 = Vsz0sy1(1+sx0sx1/3)/8             + Wsy0sz1(1+sx0sx1/3)/8
00771         // E22 = Usz0sz1(1+sy0sy1/3)(1+sx0sx1/3)/8 + W(1+sz0sz1/3)(2sx0sx1sy0sy1/3+sx0sx1+sy0sy1)/8
00772     
00773 }
00774 
00775 
00776 
00777 template<class DataTypes>
00778 void HexahedronFEMForceField<DataTypes>::computeMaterialStiffness(int i)
00779 {
00780     _materialsStiffnesses[i][0][0] = _materialsStiffnesses[i][1][1] = _materialsStiffnesses[i][2][2] = 1;
00781     _materialsStiffnesses[i][0][1] = _materialsStiffnesses[i][0][2] = _materialsStiffnesses[i][1][0]
00782             = _materialsStiffnesses[i][1][2] = _materialsStiffnesses[i][2][0] =
00783             _materialsStiffnesses[i][2][1] = f_poissonRatio.getValue()/(1-f_poissonRatio.getValue());
00784     _materialsStiffnesses[i][0][3] = _materialsStiffnesses[i][0][4] =   _materialsStiffnesses[i][0][5] = 0;
00785     _materialsStiffnesses[i][1][3] = _materialsStiffnesses[i][1][4] =   _materialsStiffnesses[i][1][5] = 0;
00786     _materialsStiffnesses[i][2][3] = _materialsStiffnesses[i][2][4] =   _materialsStiffnesses[i][2][5] = 0;
00787     _materialsStiffnesses[i][3][0] = _materialsStiffnesses[i][3][1] = _materialsStiffnesses[i][3][2] = _materialsStiffnesses[i][3][4] = _materialsStiffnesses[i][3][5] = 0;
00788     _materialsStiffnesses[i][4][0] = _materialsStiffnesses[i][4][1] = _materialsStiffnesses[i][4][2] = _materialsStiffnesses[i][4][3] = _materialsStiffnesses[i][4][5] = 0;
00789     _materialsStiffnesses[i][5][0] = _materialsStiffnesses[i][5][1] = _materialsStiffnesses[i][5][2] = _materialsStiffnesses[i][5][3] = _materialsStiffnesses[i][5][4] = 0;
00790     _materialsStiffnesses[i][3][3] = _materialsStiffnesses[i][4][4] = _materialsStiffnesses[i][5][5] = (1-2*f_poissonRatio.getValue())/(2*(1-f_poissonRatio.getValue()));
00791     _materialsStiffnesses[i] *= (f_youngModulus.getValue()*(1-f_poissonRatio.getValue()))/((1+f_poissonRatio.getValue())*(1-2*f_poissonRatio.getValue()));
00792         // S = [ U V V 0 0 0 ]
00793         //     [ V U V 0 0 0 ]
00794         //     [ V V U 0 0 0 ]
00795         //     [ 0 0 0 W 0 0 ]
00796         //     [ 0 0 0 0 W 0 ]
00797         //     [ 0 0 0 0 0 W ]
00798         // with U = y * (1-p)/( (1+p)(1-2p))
00799         //      V = y *    p /( (1+p)(1-2p))
00800         //      W = y *  1   /(2(1+p)) = (U-V)/2
00801 }
00802 
00803 template<class DataTypes>
00804         void HexahedronFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const ElementStiffness &K )
00805 {
00806     // 576*multiplications+1176*subscripts+552*additions+24*storage+24*assignments
00807     F = K*Depl;
00808 }
00809 
00810 
00811 
00812 
00813 
00818 
00819 
00820 template<class DataTypes>
00821 void HexahedronFEMForceField<DataTypes>::initLarge(int i, const Element &elem)
00822 {
00823         // Rotation matrix (initial Tetrahedre/world)
00824         // edges mean on 3 directions
00825         
00826     Vec<8,Coord> nodes;
00827     for(int w=0;w<8;++w)
00828 #ifndef SOFA_NEW_HEXA   
00829         nodes[w] = _initialPoints.getValue()[elem[_indices[w]]];
00830 #else
00831         nodes[w] = _initialPoints.getValue()[elem[w]];
00832 #endif  
00833     
00834         Coord horizontal;
00835         horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00836         Coord vertical;
00837         vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00838         Transformation R_0_1;
00839         computeRotationLarge( R_0_1, horizontal,vertical);
00840         
00841     for(int w=0;w<8;++w)
00842 #ifndef SOFA_NEW_HEXA   
00843         _rotatedInitialElements[i][w] = R_0_1*_initialPoints.getValue()[elem[_indices[w]]];
00844 #else
00845         _rotatedInitialElements[i][w] = R_0_1*_initialPoints.getValue()[elem[w]];
00846 #endif      
00847     
00848     if( _elementStiffnesses.getValue().size() <= (unsigned)i )
00849     {
00850       _elementStiffnesses.beginEdit()->resize( _elementStiffnesses.getValue().size()+1 );
00851           computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], _rotatedInitialElements[i], i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00852     }
00853     
00854 
00855 }
00856 
00857 template<class DataTypes>
00858 void HexahedronFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, Coord &edgex, Coord &edgey)
00859 {
00860 
00861     edgex.normalize();
00862     edgey.normalize();
00863 
00864     Coord edgez = cross( edgex, edgey );
00865     edgez.normalize();
00866 
00867     edgey = cross( edgez, edgex );
00868     edgey.normalize();
00869 
00870     r[0][0] = edgex[0];
00871     r[0][1] = edgex[1];
00872     r[0][2] = edgex[2];
00873     r[1][0] = edgey[0];
00874     r[1][1] = edgey[1];
00875     r[1][2] = edgey[2];
00876     r[2][0] = edgez[0];
00877     r[2][1] = edgez[1];
00878     r[2][2] = edgez[2];
00879     
00880     
00881 //  r[0][0] = 1;
00882 //  r[0][1] = 0;
00883 //  r[0][2] = 0;
00884 //  r[1][0] = 0;
00885 //  r[1][1] = 1;
00886 //  r[1][2] = 0;
00887 //  r[2][0] = 0;
00888 //  r[2][1] = 0;
00889 //  r[2][2] = 1;
00890 }
00891 
00892 template<class DataTypes>
00893 void HexahedronFEMForceField<DataTypes>::accumulateForceLarge( Vector& f, const Vector & p, int i, const Element&elem )
00894 {
00895     Vec<8,Coord> nodes;
00896     for(int w=0;w<8;++w)
00897 #ifndef SOFA_NEW_HEXA   
00898         nodes[w] = p[elem[_indices[w]]];
00899 #else
00900         nodes[w] = p[elem[w]];
00901 #endif      
00902     
00903     Coord horizontal;
00904     horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00905     Coord vertical;
00906     vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00907     
00908     Transformation R_0_2; // Rotation matrix (deformed and displaced Tetrahedron/world)
00909     computeRotationLarge( R_0_2, horizontal,vertical);
00910         
00911     _rotations[i].transpose(R_0_2);
00912     
00913     // positions of the deformed and displaced Tetrahedre in its frame
00914     Vec<8,Coord> deformed;
00915     for(int w=0;w<8;++w)
00916         deformed[w] = R_0_2 * nodes[w];
00917     
00918     
00919     // displacement
00920     Displacement D;
00921     for(int k=0 ; k<8 ; ++k )
00922     {
00923         int indice = k*3;
00924         for(int j=0 ; j<3 ; ++j )   
00925             D[indice+j] = _rotatedInitialElements[i][k][j] - deformed[k][j];
00926     }
00927     
00928     
00929     if(f_updateStiffnessMatrix.getValue())
00930 //      computeElementStiffness( _elementStiffnesses[i], _materialsStiffnesses[i], deformed );
00931       computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], deformed, i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00932 
00933     
00934     Displacement F; //forces
00935     computeForce( F, D, _elementStiffnesses.getValue()[i] ); // compute force on element
00936 
00937     for(int w=0;w<8;++w)
00938 #ifndef SOFA_NEW_HEXA   
00939     f[elem[_indices[w]]] += _rotations[i] * Deriv( F[w*3],  F[w*3+1],   F[w*3+2]  );
00940 #else
00941     f[elem[w]] += _rotations[i] * Deriv( F[w*3],  F[w*3+1],   F[w*3+2]  );
00942 #endif  
00943 }
00944 
00945 
00946 
00947 
00948 
00949 
00950 
00955 
00956 
00957 
00958 template<class DataTypes>
00959 void HexahedronFEMForceField<DataTypes>::initPolar(int i, const Element& elem)
00960 {
00961     Vec<8,Coord> nodes;
00962     for(int j=0;j<8;++j)
00963 #ifndef SOFA_NEW_HEXA   
00964         nodes[j] = _initialPoints.getValue()[elem[_indices[j]]];
00965 #else
00966         nodes[j] = _initialPoints.getValue()[elem[j]];
00967 #endif      
00968     
00969     Transformation R_0_1; // Rotation matrix (deformed and displaced Tetrahedron/world)
00970     computeRotationPolar( R_0_1, nodes );
00971     
00972 
00973     for(int j=0;j<8;++j)
00974     {
00975         _rotatedInitialElements[i][j] = R_0_1 * nodes[j];
00976     }
00977         
00978 
00979     if( _elementStiffnesses.getValue().size() <= (unsigned)i )
00980     {
00981         _elementStiffnesses.beginEdit()->resize( _elementStiffnesses.getValue().size()+1 );
00982         computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], _rotatedInitialElements[i], i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00983     }
00984 }
00985 
00986 
00987 
00988 template<class DataTypes>
00989 void HexahedronFEMForceField<DataTypes>::computeRotationPolar( Transformation &r, Vec<8,Coord> &nodes)
00990 {
00991     Transformation A;
00992     Coord Edge =(nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00993         //Edge.normalize();
00994     A[0][0] = Edge[0];
00995     A[0][1] = Edge[1];
00996     A[0][2] = Edge[2];
00997     Edge = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00998         //Edge.normalize();
00999     A[1][0] = Edge[0];
01000     A[1][1] = Edge[1];
01001     A[1][2] = Edge[2];
01002     Edge = (nodes[4]-nodes[0] + nodes[5]-nodes[1] + nodes[7]-nodes[3] + nodes[6]-nodes[2])*.25;
01003         //Edge.normalize();
01004     A[2][0] = Edge[0];
01005     A[2][1] = Edge[1];
01006     A[2][2] = Edge[2];
01007         
01008     Mat33 HT;
01009     for(int k=0;k<3;++k) 
01010         for(int j=0;j<3;++j) 
01011             HT[k][j]=A[k][j];
01012     //HT[3][0] = HT[3][1] = HT[3][2] = HT[0][3] = HT[1][3] = HT[2][3] = 0;
01013     //HT[3][3] = 1;
01014     Mat33 S;
01015     
01016     polar_decomp(HT, r, S);
01017 }
01018 
01019 
01020 template<class DataTypes>
01021 void HexahedronFEMForceField<DataTypes>::accumulateForcePolar( Vector& f, const Vector & p, int i, const Element&elem )
01022 {
01023     Vec<8,Coord> nodes;
01024     for(int j=0;j<8;++j)
01025 #ifndef SOFA_NEW_HEXA       
01026         nodes[j] = p[elem[_indices[j]]];
01027 #else
01028         nodes[j] = p[elem[j]];
01029 #endif  
01030         
01031     Transformation R_0_2; // Rotation matrix (deformed and displaced Tetrahedron/world)
01032     computeRotationPolar( R_0_2, nodes );
01033         
01034     _rotations[i].transpose( R_0_2 );
01035     
01036     
01037     // positions of the deformed and displaced Tetrahedre in its frame
01038     Vec<8,Coord> deformed;
01039     for(int j=0;j<8;++j)
01040         deformed[j] = R_0_2 * nodes[j];
01041     
01042     
01043     
01044     // displacement
01045     Displacement D;
01046     for(int k=0 ; k<8 ; ++k )
01047     {
01048         int indice = k*3;
01049         for(int j=0 ; j<3 ; ++j )   
01050             D[indice+j] = _rotatedInitialElements[i][k][j] - deformed[k][j];
01051     }
01052             
01053     //forces        
01054     Displacement F;
01055     
01056     if(f_updateStiffnessMatrix.getValue())
01057 //      computeElementStiffness( _elementStiffnesses[i], _materialsStiffnesses[i], deformed );
01058       computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], deformed, i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
01059 
01060     // compute force on element
01061     computeForce( F, D, _elementStiffnesses.getValue()[i] );
01062         
01063 
01064     for(int j=0;j<8;++j)
01065 #ifndef SOFA_NEW_HEXA   
01066         f[elem[_indices[j]]] += _rotations[i] * Deriv( F[j*3],  F[j*3+1],   F[j*3+2]  );
01067 #else
01068         f[elem[j]] += _rotations[i] * Deriv( F[j*3],  F[j*3+1],   F[j*3+2]  );
01069 #endif
01070 }
01071 
01072 
01073 
01074 
01075 
01079 
01080 
01081 template<class DataTypes>
01082     void HexahedronFEMForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix *mat, SReal k, unsigned int &offset)
01083 {
01084     // Build Matrix Block for this ForceField
01085     int i,j,n1, n2, e;
01086 
01087     typename VecElement::const_iterator it;
01088 
01089     Index node1, node2;
01090 
01091     for(it = _indexedElements->begin(), e=0 ; it != _indexedElements->end() ; ++it,++e)
01092     {
01093         const ElementStiffness &Ke = _elementStiffnesses.getValue()[e];
01094         const Transformation& Rt = _rotations[e];
01095         Transformation R; R.transpose(Rt);
01096 
01097         // find index of node 1
01098         for (n1=0; n1<8; n1++)
01099         {
01100 #ifndef SOFA_NEW_HEXA           
01101             node1 = (*it)[_indices[n1]];
01102 #else
01103             node1 = (*it)[n1];
01104 #endif            
01105             // find index of node 2
01106             for (n2=0; n2<8; n2++)
01107             {
01108 #ifndef SOFA_NEW_HEXA               
01109                 node2 = (*it)[_indices[n2]];
01110 #else
01111                 node2 = (*it)[n2];
01112 #endif                
01113                 Mat33 tmp = Rt * Mat33(Coord(Ke[3*n1+0][3*n2+0],Ke[3*n1+0][3*n2+1],Ke[3*n1+0][3*n2+2]),
01114                                      Coord(Ke[3*n1+1][3*n2+0],Ke[3*n1+1][3*n2+1],Ke[3*n1+1][3*n2+2]),
01115                                      Coord(Ke[3*n1+2][3*n2+0],Ke[3*n1+2][3*n2+1],Ke[3*n1+2][3*n2+2])) * R;
01116                 for(i=0; i<3; i++)
01117                     for (j=0; j<3; j++)
01118                         mat->add(offset+3*node1+i, offset+3*node2+j, - tmp[i][j]*k);
01119             }
01120         }
01121     }
01122 }
01123 
01124 
01125 
01126 
01127 template<class DataTypes>
01128 void HexahedronFEMForceField<DataTypes>::draw()
01129 {
01130 //  cerr<<"HexahedronFEMForceField<DataTypes>::draw()\n";
01131     if (!getContext()->getShowForceFields()) return;
01132     if (!this->mstate) return;
01133     
01134 
01135     const VecCoord& x = *this->mstate->getX();
01136 
01137     if (getContext()->getShowWireFrame())
01138         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01139 
01140     glDisable(GL_LIGHTING);
01141 
01142     typename VecElement::const_iterator it;
01143     int i;
01144     for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01145     {
01146         Index a = (*it)[0];
01147         Index b = (*it)[1];
01148 #ifndef SOFA_NEW_HEXA
01149         Index d = (*it)[2];
01150         Index c = (*it)[3];
01151 #else
01152         Index d = (*it)[3];
01153         Index c = (*it)[2];
01154 #endif
01155         Index e = (*it)[4];
01156         Index f = (*it)[5];
01157 #ifndef SOFA_NEW_HEXA
01158         Index h = (*it)[6];
01159         Index g = (*it)[7];
01160 #else
01161         Index h = (*it)[7];
01162         Index g = (*it)[6];
01163 #endif
01164 
01165 //      Coord center = (x[a]+x[b]+x[c]+x[d]+x[e]+x[g]+x[f]+x[h])*0.0625;
01166 //      Real percentage = 0.666667;
01167 //      Coord pa = (x[a]+center)*percentage;
01168 //      Coord pb = (x[b]+center)*percentage;
01169 //      Coord pc = (x[c]+center)*percentage;
01170 //      Coord pd = (x[d]+center)*percentage;
01171 //      Coord pe = (x[e]+center)*percentage;
01172 //      Coord pf = (x[f]+center)*percentage;
01173 //      Coord pg = (x[g]+center)*percentage;
01174 //      Coord ph = (x[h]+center)*percentage;
01175         
01176         Coord center = (x[a]+x[b]+x[c]+x[d]+x[e]+x[g]+x[f]+x[h])*0.125;
01177         Real percentage = (Real) 0.15;
01178         Coord pa = x[a]-(x[a]-center)*percentage;
01179         Coord pb = x[b]-(x[b]-center)*percentage;
01180         Coord pc = x[c]-(x[c]-center)*percentage;
01181         Coord pd = x[d]-(x[d]-center)*percentage;
01182         Coord pe = x[e]-(x[e]-center)*percentage;
01183         Coord pf = x[f]-(x[f]-center)*percentage;
01184         Coord pg = x[g]-(x[g]-center)*percentage;
01185         Coord ph = x[h]-(x[h]-center)*percentage;
01186 
01187 
01188         
01189         
01190         if(_sparseGrid )
01191         {
01192             glEnable(GL_BLEND);
01193             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01194         }
01195         
01196         
01197 //      if( _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY )
01198 //          continue;
01199         
01200     glColor4f(0.7f, 0.7f, 0.1f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01201         glBegin(GL_POLYGON);
01202         helper::gl::glVertexT(pa);
01203         helper::gl::glVertexT(pb);
01204         helper::gl::glVertexT(pc);
01205         helper::gl::glVertexT(pd);
01206         glEnd();
01207         glColor4f(0.7f, 0, 0, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01208         glBegin(GL_POLYGON);
01209         helper::gl::glVertexT(pe);
01210         helper::gl::glVertexT(pf);
01211         helper::gl::glVertexT(pg);
01212         helper::gl::glVertexT(ph);
01213         glEnd(); 
01214         glColor4f(0, 0.7f, 0, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01215         glBegin(GL_POLYGON);
01216         helper::gl::glVertexT(pc);
01217         helper::gl::glVertexT(pd);
01218         helper::gl::glVertexT(ph);
01219         helper::gl::glVertexT(pg);
01220         glEnd(); 
01221         glColor4f(0, 0, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01222         glBegin(GL_POLYGON);
01223         helper::gl::glVertexT(pa);
01224         helper::gl::glVertexT(pb);
01225         helper::gl::glVertexT(pf);
01226         helper::gl::glVertexT(pe);
01227         glEnd();
01228         glColor4f(0.1f, 0.7f, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01229         glBegin(GL_POLYGON);
01230         helper::gl::glVertexT(pa);
01231         helper::gl::glVertexT(pd);
01232         helper::gl::glVertexT(ph);
01233         helper::gl::glVertexT(pe);
01234         glEnd();
01235         glColor4f(0.7f, 0.1f, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01236         glBegin(GL_POLYGON);
01237         helper::gl::glVertexT(pb);
01238         helper::gl::glVertexT(pc);
01239         helper::gl::glVertexT(pg);
01240         helper::gl::glVertexT(pf);
01241         glEnd();
01242     }
01243     
01244     if (getContext()->getShowWireFrame())
01245         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01246     
01247     if(_sparseGrid )
01248         glDisable(GL_BLEND);
01249 }
01250 
01251 
01252 } // namespace forcefield
01253 
01254 } // namespace component
01255 
01256 } // namespace sofa
01257 
01258 #endif

Generated on Sun Nov 23 02:57:51 2008 for Sofa by  doxygen 1.5.7.1