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

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