TriangularQuadraticSpringsForceField.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 #include <sofa/component/forcefield/TriangularQuadraticSpringsForceField.h>
00026 #include <fstream> // for reading the file
00027 #include <iostream> //for debugging
00028 #include <sofa/helper/gl/template.h>
00029 #include <sofa/component/topology/TriangleSetGeometryAlgorithms.h>
00030 #include <sofa/component/topology/TriangleData.inl>
00031 #include <sofa/component/topology/EdgeData.inl>
00032 
00033 namespace sofa
00034 {
00035 
00036 namespace component
00037 {
00038 
00039 namespace forcefield
00040 {
00041 
00042 using namespace sofa::defaulttype;
00043 using namespace sofa::component::topology;
00044 using namespace core::componentmodel::topology;
00045 
00046 using std::cerr;
00047 using std::cout;
00048 using std::endl;
00049 
00050 template< class DataTypes>
00051 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSEdgeCreationFunction(int edgeIndex, void* param, EdgeRestInformation &ei,
00052                             const Edge& ,  const sofa::helper::vector< unsigned int > &,
00053                               const sofa::helper::vector< double >&)
00054 {
00055     TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00056     if (ff) {
00057 
00058         sofa::component::topology::TriangleSetGeometryAlgorithms<DataTypes>* triangleGeo; 
00059         ff->getContext()->get(triangleGeo);
00060 
00061         // store the rest length of the edge created 
00062         ei.restLength=triangleGeo->computeRestEdgeLength(edgeIndex);
00063         ei.stiffness=0;
00064     }
00065 }
00066 
00067 
00068 
00069 template< class DataTypes>
00070 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSTriangleCreationFunction (int triangleIndex, void* param, 
00071                             TriangleRestInformation &tinfo,
00072                             const Triangle& , 
00073                               const sofa::helper::vector< unsigned int > &,
00074                               const sofa::helper::vector< double >&)
00075 {
00076     TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00077     if (ff) {
00078         unsigned int j,k,l;
00079 
00080         EdgeData<typename TriangularQuadraticSpringsForceField<DataTypes>::EdgeRestInformation> &edgeInfo=ff->getEdgeInfo();
00081         typename DataTypes::Real area,squareRestLength[3],restLength[3],cotangent[3];
00082         typename DataTypes::Real lambda=ff->getLambda();
00083         typename DataTypes::Real mu=ff->getMu();
00084 
00086         const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleIndex);
00087         // store square rest length
00088         for(j=0;j<3;++j) {
00089             restLength[j]=edgeInfo[te[j]].restLength;
00090             squareRestLength[j]= restLength[j]*restLength[j];
00091         }
00092         // compute rest area based on Heron's formula
00093         area=0;
00094         for(j=0;j<3;++j) {
00095             area+=squareRestLength[j]*(squareRestLength[(j+1)%3] +squareRestLength[(j+2)%3]-squareRestLength[j]);
00096         }
00097         area=sqrt(area)/4;
00098 
00099         for(j=0;j<3;++j) {
00100             cotangent[j]=(squareRestLength[(j+1)%3] +squareRestLength[(j+2)%3]-squareRestLength[j])/(4*area);
00101             /*  if (cotangent[j]<0) 
00102             std::cerr<<"negative cotangent["<<i<<"]["<<j<<"]"<<std::endl;
00103             else
00104             std::cerr<<"cotangent="<<cotangent[j]<<std::endl;*/
00105 
00106         }
00107         for(j=0;j<3;++j){
00108             k=(j+1)%3;
00109             l=(j+2)%3;
00110             tinfo.gamma[j]=restLength[k]*restLength[l]*(2*cotangent[k]*cotangent[l]*(lambda+mu)-mu)/(8*area);
00111             tinfo.stiffness[j]=restLength[j]*restLength[j]*(2*cotangent[j]*cotangent[j]*(lambda+mu)+mu)/(8*area);
00112             edgeInfo[te[j]].stiffness+=tinfo.stiffness[j];
00113         }
00114 
00115     }
00116 
00117 } 
00118 
00119 
00120 template< class DataTypes>
00121 void TriangularQuadraticSpringsForceField<DataTypes>::TRQSTriangleDestroyFunction(int triangleIndex, void* param, typename TriangularQuadraticSpringsForceField<DataTypes>::TriangleRestInformation &tinfo)
00122 {
00123     TriangularQuadraticSpringsForceField<DataTypes> *ff= (TriangularQuadraticSpringsForceField<DataTypes> *)param;
00124     if (ff) {
00125         unsigned int j;
00126         
00127         EdgeData<typename TriangularQuadraticSpringsForceField<DataTypes>::EdgeRestInformation> &edgeInfo=ff->getEdgeInfo();
00128 
00130         const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleIndex);
00131         // store square rest length
00132         for(j=0;j<3;++j) {
00133             edgeInfo[te[j]].stiffness -= tinfo.stiffness[j]; 
00134         }
00135 
00136     }
00137 } 
00138 template <class DataTypes> TriangularQuadraticSpringsForceField<DataTypes>::TriangularQuadraticSpringsForceField() 
00139 : _initialPoints(initData(&_initialPoints,"initialPoints", "Initial Position"))
00140 , updateMatrix(true)
00141 , f_poissonRatio(initData(&f_poissonRatio,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00142 , f_youngModulus(initData(&f_youngModulus,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00143 , f_dampingRatio(initData(&f_dampingRatio,(Real)0.,"dampingRatio","Ratio damping/stiffness"))
00144 , f_useAngularSprings(initData(&f_useAngularSprings,true,"useAngularSprings","If Angular Springs should be used or not"))
00145 , lambda(0)
00146 , mu(0)
00147     {
00148     }
00149 
00150 template <class DataTypes> void TriangularQuadraticSpringsForceField<DataTypes>::handleTopologyChange()
00151 {
00152     std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00153     std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00154 
00155     edgeInfo.handleTopologyEvents(itBegin,itEnd);
00156     triangleInfo.handleTopologyEvents(itBegin,itEnd);
00157 }
00158 
00159 template <class DataTypes> TriangularQuadraticSpringsForceField<DataTypes>::~TriangularQuadraticSpringsForceField()
00160 {
00161 
00162 }
00163 
00164 template <class DataTypes> void TriangularQuadraticSpringsForceField<DataTypes>::init()
00165 {
00166     std::cerr << "initializing TriangularQuadraticSpringsForceField" << std::endl;
00167     this->Inherited::init();
00168 
00169     _topology = getContext()->getMeshTopology();
00170 
00171     if (_topology->getNbTriangles()==0)
00172     {
00173         std::cerr << "ERROR(TriangularQuadraticSpringsForceField): object must have a Triangular Set Topology.\n";
00174         return;
00175     }
00176     updateLameCoefficients();
00177 
00179     triangleInfo.resize(_topology->getNbTriangles());
00181     edgeInfo.resize(_topology->getNbEdges());
00182 
00183     if (_initialPoints.getValue().size() == 0)
00184     {
00185     // get restPosition
00186       VecCoord& p = *this->mstate->getX0();
00187       _initialPoints.setValue(p);
00188     }
00189     int i;
00190     for (i=0;i<_topology->getNbEdges();++i) {
00191         TRQSEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00192             _topology->getEdge(i),  (const sofa::helper::vector< unsigned int > )0,
00193             (const sofa::helper::vector< double >)0);
00194     }
00195     for (i=0;i<_topology->getNbTriangles();++i) {
00196         TRQSTriangleCreationFunction(i, (void*) this, triangleInfo[i],
00197             _topology->getTriangle(i),  (const sofa::helper::vector< unsigned int > )0,
00198             (const sofa::helper::vector< double >)0);
00199     }
00200 
00201     edgeInfo.setCreateFunction(TRQSEdgeCreationFunction);
00202     triangleInfo.setCreateFunction(TRQSTriangleCreationFunction);
00203     triangleInfo.setDestroyFunction(TRQSTriangleDestroyFunction);
00204     edgeInfo.setCreateParameter( (void *) this );
00205     edgeInfo.setDestroyParameter( (void *) this );
00206     triangleInfo.setCreateParameter( (void *) this );
00207     triangleInfo.setDestroyParameter( (void *) this );
00208 
00209 }
00210 
00211 
00212 template <class DataTypes> 
00213     double TriangularQuadraticSpringsForceField<DataTypes>::getPotentialEnergy(const VecCoord& /*x*/)
00214 {
00215     std::cerr<<"TriangularQuadraticSpringsForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00216     return 0;
00217 }
00218 template <class DataTypes> 
00219 void TriangularQuadraticSpringsForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& v)
00220 {
00221     unsigned int j,k,l,v0,v1;
00222     int nbEdges=_topology->getNbEdges();
00223     int nbTriangles=_topology->getNbTriangles();
00224 
00225     Real val,L;
00226     TriangleRestInformation *tinfo;
00227     EdgeRestInformation *einfo;
00228 
00229     assert(this->mstate);
00230 
00231     Deriv force;
00232     Coord dp,dv;
00233     Real _dampingRatio=f_dampingRatio.getValue();
00234 
00235 
00236     for(int i=0; i<nbEdges; i++ )
00237     {
00238         einfo=&edgeInfo[i];
00239         v0=_topology->getEdge(i)[0];
00240         v1=_topology->getEdge(i)[1];
00241         dp=x[v0]-x[v1];
00242         dv=v[v0]-v[v1];
00243         L=einfo->currentLength=dp.norm();
00244         einfo->dl=einfo->currentLength-einfo->restLength +_dampingRatio*dot(dv,dp)/L;
00245         /*if (i==0) {
00246             cerr << "dl= " <<  einfo->dl<<std::endl;
00247             cerr << "damping= " <<  (_dampingRatio*dot(dv,dp)*einfo->restLength/(L*L))<<std::endl;
00248         }*/
00249         val=einfo->stiffness*(einfo->dl)/L;
00250         f[v1]+=dp*val;
00251         f[v0]-=dp*val;
00252     //  std::cerr << "einfo->stiffness= "<<einfo->stiffness<<std::endl;
00253     }
00254     if (f_useAngularSprings.getValue()==true) {
00255         for(int i=0; i<nbTriangles; i++ )
00256         {
00257             tinfo=&triangleInfo[i];
00259             const TriangleEdges &tea= _topology->getEdgeTriangleShell(i);
00261             const Triangle &ta= _topology->getTriangle(i);
00262 
00263             // store points
00264             for(j=0;j<3;++j) {
00265                 k=(j+1)%3;
00266                 l=(j+2)%3;
00267                 force=(x[ta[k]] - x[ta[l]])*
00268                     (edgeInfo[tea[k]].dl * tinfo->gamma[l] +edgeInfo[tea[l]].dl * tinfo->gamma[k])/edgeInfo[tea[j]].currentLength;
00269                 f[ta[l]]+=force;
00270                 f[ta[k]]-=force;            
00271             }
00272     }
00273     //  std::cerr << "tinfo->gamma[0] "<<tinfo->gamma[0]<<std::endl;
00274 
00275     }
00276     
00277     updateMatrix=true;
00278     //std::cerr << "end addForce" << std::endl;
00279 }
00280 
00281 
00282 template <class DataTypes> 
00283 void TriangularQuadraticSpringsForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00284 {
00285     unsigned int i,j,k; 
00286     int nbTriangles=_topology->getNbTriangles();    
00287 
00288     TriangleRestInformation *tinfo;
00289 
00290 //  std::cerr << "start addDForce" << std::endl;
00291 
00292 
00293     assert(this->mstate);
00294     VecDeriv& x = *this->mstate->getX();
00295 
00296 
00297     Deriv deltax,res;
00298 
00299     if (updateMatrix) {
00300         int u,v;
00301         Real val1,val2,vali,valj,valk;
00302         Coord dpj,dpk,dpi;
00303     
00304     //  std::cerr <<"updating matrix"<<std::endl;
00305         updateMatrix=false;
00306         for(int l=0; l<nbTriangles; l++ )
00307         {
00308             tinfo=&triangleInfo[l];
00310             const TriangleEdges &tea= _topology->getEdgeTriangleShell(l);
00312             const Triangle &ta= _topology->getTriangle(l);
00313 
00314             // store points
00315             for(k=0;k<3;++k) {
00316                 i=(k+1)%3;
00317                 j=(k+2)%3;
00318                 Mat3 &m=tinfo->DfDx[k];
00319                 dpk = x[ta[i]]- x[ta[j]];
00320 
00321                 if (f_useAngularSprings.getValue()==false) {
00322                     val1 = -tinfo->stiffness[k]*edgeInfo[tea[k]].dl;
00323                     val1/=edgeInfo[tea[k]].currentLength;
00324 
00325                     val2= -tinfo->stiffness[k]*edgeInfo[tea[k]].restLength;
00326                     val2/=edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength;
00327 
00328                     for (u=0;u<3;++u) {
00329                         for (v=0;v<3;++v) {
00330                             m[u][v]=dpk[u]*dpk[v]*val2;
00331                         }
00332                         m[u][u]+=val1;
00333                     }
00334 
00335                 } else {
00336                     dpj = x[ta[i]]- x[ta[k]];
00337                     dpi = x[ta[j]]- x[ta[k]];
00338 
00339                     val1 = -(tinfo->stiffness[k]*edgeInfo[tea[k]].dl+
00340                         tinfo->gamma[i]*edgeInfo[tea[j]].dl+
00341                         tinfo->gamma[j]*edgeInfo[tea[i]].dl);
00342 
00343                     val2= -val1 - tinfo->stiffness[k]*edgeInfo[tea[k]].restLength;
00344                     val1/=edgeInfo[tea[k]].currentLength;
00345                     val2/=edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength*edgeInfo[tea[k]].currentLength;
00346                     valk=tinfo->gamma[k]/(edgeInfo[tea[j]].currentLength*
00347                         edgeInfo[tea[i]].currentLength);
00348                     vali=tinfo->gamma[i]/(edgeInfo[tea[j]].currentLength*
00349                         edgeInfo[tea[k]].currentLength);
00350                     valj=tinfo->gamma[j]/(edgeInfo[tea[k]].currentLength*
00351                         edgeInfo[tea[i]].currentLength);
00352 
00353 
00354                     for (u=0;u<3;++u) {
00355                         for (v=0;v<3;++v) {
00356                             m[u][v]=dpk[u]*dpk[v]*val2
00357                                 +dpj[u]*dpi[v]*valk
00358                                 -dpj[u]*dpk[v]*vali
00359                                 +dpk[u]*dpi[v]*valj;
00360 
00361                         }
00362                         m[u][u]+=val1;
00363                     }
00364                 }
00365             }
00366         }
00367 
00368     } 
00369 
00370     for(int l=0; l<nbTriangles; l++ )
00371         {
00372             tinfo=&triangleInfo[l];
00374             const Triangle &ta= _topology->getTriangle(l);
00375 
00376             // store points
00377             for(k=0;k<3;++k) {
00378                 i=(k+1)%3;
00379                 j=(k+2)%3;
00380                 deltax= dx[ta[i]] -dx[ta[j]];
00381                 res=tinfo->DfDx[k]*deltax;
00382                 df[ta[i]]+=res;
00383                 df[ta[j]]-= tinfo->DfDx[k].transposeMultiply(deltax);
00384             }
00385         }
00386 }
00387 
00388 
00389 template<class DataTypes>
00390 void TriangularQuadraticSpringsForceField<DataTypes>::updateLameCoefficients()
00391 {
00392     lambda= f_youngModulus.getValue()*f_poissonRatio.getValue()/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00393     mu = f_youngModulus.getValue()*(1-f_poissonRatio.getValue())/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00394 //  std::cerr << "initialized Lame coef : lambda=" <<lambda<< " mu="<<mu<<std::endl;
00395 }
00396 
00397 
00398 template<class DataTypes>
00399 void TriangularQuadraticSpringsForceField<DataTypes>::draw()
00400 {
00401     if (!getContext()->getShowForceFields()) return;
00402     if (!this->mstate) return;
00403 
00404     if (getContext()->getShowWireFrame())
00405         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00406 
00407     VecCoord& x = *this->mstate->getX();
00408     int nbTriangles=_topology->getNbTriangles();
00409 
00410     glDisable(GL_LIGHTING);
00411 
00412     glBegin(GL_TRIANGLES);
00413     for(int i=0;i<nbTriangles; ++i)
00414     {
00415         int a = _topology->getTriangle(i)[0];
00416         int b = _topology->getTriangle(i)[1];
00417         int c = _topology->getTriangle(i)[2];
00418 
00419         glColor4f(0,1,0,1);
00420         helper::gl::glVertexT(x[a]);
00421         glColor4f(0,0.5,0.5,1);
00422         helper::gl::glVertexT(x[b]);
00423         glColor4f(0,0,1,1);
00424         helper::gl::glVertexT(x[c]);
00425     }
00426     glEnd();
00427 
00428 
00429     if (getContext()->getShowWireFrame())
00430         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00431 }
00432 
00433 } // namespace forcefield
00434 
00435 } // namespace Components
00436 
00437 } // namespace Sofa

Generated on Sun Nov 23 03:20:20 2008 for Sofa by  doxygen 1.5.7.1