TriangularTensorMassForceField.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/TriangularTensorMassForceField.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 
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 using core::componentmodel::topology::BaseMeshTopology;
00051 typedef BaseMeshTopology::TriangleEdges TriangleEdges;
00052 
00053 template< class DataTypes>
00054 void TriangularTensorMassForceField<DataTypes>::TriangularTMEdgeCreationFunction(int /*edgeIndex*/, void* param, EdgeRestInformation &ei,
00055                                                                                  const Edge& ,  const sofa::helper::vector< unsigned int > &,
00056                                                                                  const sofa::helper::vector< double >&)
00057 {
00058     TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00059     if (ff) {
00060 
00061         unsigned int u,v;
00063         for (u=0;u<3;++u) {
00064             for (v=0;v<3;++v) {
00065                 ei.DfDx[u][v]=0;
00066             }
00067         }
00068 
00069     }
00070 }
00071 
00072 template< class DataTypes>
00073 void TriangularTensorMassForceField<DataTypes>::TriangularTMTriangleCreationFunction (const sofa::helper::vector<unsigned int> &triangleAdded, 
00074                                                                                       void* param, vector<EdgeRestInformation> &edgeData)
00075 {
00076     TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00077     if (ff) {
00078         
00079         unsigned int i,j,k,l,u,v;
00080 
00081         typename DataTypes::Real val1,area,restSquareLength[3],cotangent[3];
00082         typename DataTypes::Real lambda=ff->getLambda();
00083         typename DataTypes::Real mu=ff->getMu();
00084         typename DataTypes::Real lambdastar, mustar;
00085         typename DataTypes::Coord point[3],dpk,dpl;
00086         
00087         const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00088 
00089         for (i=0;i<triangleAdded.size();++i) {
00090 
00092             const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleAdded[i]);
00094             const Triangle &t= ff->_topology->getTriangle(triangleAdded[i]);
00095             // store points
00096             for(j=0;j<3;++j)
00097                 point[j]=(*restPosition)[t[j]];
00098             // store square rest length
00099             for(j=0;j<3;++j) {
00100                 restSquareLength[j]= (point[(j+1)%3] -point[(j+2)%3]).norm2();
00101             }
00102             // compute rest area based on Heron's formula
00103             area=0;
00104             for(j=0;j<3;++j) {
00105                 area+=restSquareLength[j]*(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j]);
00106             }
00107             area=sqrt(area)/4;
00108             lambdastar=lambda/(4*area);
00109             mustar=mu/(8*area);
00110 
00111             for(j=0;j<3;++j) {
00112                 cotangent[j]=(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j])/(4*area);
00113                 if (ff->f_printLog.getValue()) {
00114                     if (cotangent[j]<0) 
00115                         std::cerr<<"negative cotangent["<<triangleAdded[i]<<"]["<<j<<"]"<<std::endl;
00116                 }
00117             }
00118             for(j=0;j<3;++j){
00119                 k=(j+1)%3;
00120                 l=(j+2)%3;
00121                 Mat3 &m=edgeData[te[j]].DfDx;
00122                 dpl= point[j]-point[k];
00123                 dpk= point[j]-point[l];
00124                 val1= -cotangent[j]*(lambda+mu)/2;
00125 
00126                 if (ff->_topology->getEdge(te[j])[0]==t[l]) {
00127                     for (u=0;u<3;++u) {
00128                         for (v=0;v<3;++v) {
00129                             m[u][v]+= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00130                         }
00131                         m[u][u]+=val1;
00132                     }
00133                 } else {
00134                     for (u=0;u<3;++u) {
00135                         for (v=0;v<3;++v) {
00136                             m[v][u]+= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00137                         }
00138                         m[u][u]+=val1;
00139                     }
00140                 }
00141             }
00142 
00143         }
00144 
00145     }
00146 }
00147 
00148 template< class DataTypes>
00149 void TriangularTensorMassForceField<DataTypes>::TriangularTMTriangleDestructionFunction (const sofa::helper::vector<unsigned int> &triangleRemoved, 
00150                                                                                       void* param, vector<EdgeRestInformation> &edgeData)
00151 {
00152     TriangularTensorMassForceField<DataTypes> *ff= (TriangularTensorMassForceField<DataTypes> *)param;
00153     if (ff) {
00154         
00155         unsigned int i,j,k,l,u,v;
00156 
00157         typename DataTypes::Real val1,area,restSquareLength[3],cotangent[3];
00158         typename DataTypes::Real lambda=ff->getLambda();
00159         typename DataTypes::Real mu=ff->getMu();
00160         typename DataTypes::Real lambdastar, mustar;
00161         typename DataTypes::Coord point[3],dpk,dpl;
00162         
00163         const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00164 
00165         for (i=0;i<triangleRemoved.size();++i) {
00166 
00168             const TriangleEdges &te= ff->_topology->getEdgeTriangleShell(triangleRemoved[i]);
00170             const Triangle &t= ff->_topology->getTriangle(triangleRemoved[i]);
00171             // store points
00172             for(j=0;j<3;++j)
00173                 point[j]=(*restPosition)[t[j]];
00174             // store square rest length
00175             for(j=0;j<3;++j) {
00176                 restSquareLength[j]= (point[(j+1)%3] -point[(j+2)%3]).norm2();
00177             }
00178             // compute rest area based on Heron's formula
00179             area=0;
00180             for(j=0;j<3;++j) {
00181                 area+=restSquareLength[j]*(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j]);
00182             }
00183             area=sqrt(area)/4;
00184             lambdastar=lambda/(4*area);
00185             mustar=mu/(8*area);
00186 
00187             for(j=0;j<3;++j) {
00188                 cotangent[j]=(restSquareLength[(j+1)%3] +restSquareLength[(j+2)%3]-restSquareLength[j])/(4*area);
00189                 if (ff->f_printLog.getValue()) {
00190                     if (cotangent[j]<0) 
00191                         std::cerr<<"negative cotangent["<<triangleRemoved[i]<<"]["<<j<<"]"<<std::endl;
00192                 }
00193             }
00194             for(j=0;j<3;++j){
00195                 k=(j+1)%3;
00196                 l=(j+2)%3;
00197                 Mat3 &m=edgeData[te[j]].DfDx;
00198                 dpl= point[j]-point[k];
00199                 dpk= point[j]-point[l];
00200                 val1= -cotangent[j]*(lambda+mu)/2;
00201 
00202                 if (ff->_topology->getEdge(te[j])[0]==t[l]) {
00203                     for (u=0;u<3;++u) {
00204                         for (v=0;v<3;++v) {
00205                             m[u][v]-= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00206                         }
00207                         m[u][u]-=val1;
00208                     }
00209                 } else {
00210                     for (u=0;u<3;++u) {
00211                         for (v=0;v<3;++v) {
00212                             m[v][u]-= lambdastar*dpl[u]*dpk[v]+mustar*dpk[u]*dpl[v];
00213                         }
00214                         m[u][u]-=val1;
00215                     }
00216                 }
00217             }
00218 
00219         }
00220 
00221     }
00222 }
00223 
00224 
00225 template <class DataTypes> TriangularTensorMassForceField<DataTypes>::TriangularTensorMassForceField() 
00226 : _initialPoints(0) 
00227 , updateMatrix(true)
00228 , f_poissonRatio(initData(&f_poissonRatio,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00229 , f_youngModulus(initData(&f_youngModulus,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00230 , lambda(0)
00231 , mu(0)
00232     {
00233     }
00234 
00235 template <class DataTypes> void TriangularTensorMassForceField<DataTypes>::handleTopologyChange()
00236 {
00237     std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00238     std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00239 
00240     edgeInfo.handleTopologyEvents(itBegin,itEnd);
00241 }
00242 
00243 template <class DataTypes> TriangularTensorMassForceField<DataTypes>::~TriangularTensorMassForceField()
00244 {
00245 
00246 }
00247 
00248 template <class DataTypes> void TriangularTensorMassForceField<DataTypes>::init()
00249 {
00250     std::cerr << "initializing TriangularTensorMassForceField" << std::endl;
00251     this->Inherited::init();
00252 
00253     _topology = getContext()->getMeshTopology();    
00254 
00255     if (_topology->getNbTriangles()==0)
00256     {
00257         std::cerr << "ERROR(TriangularTensorMassForceField): object must have a Triangular Set Topology.\n";
00258         return;
00259     }
00260     updateLameCoefficients();
00261 
00263     edgeInfo.resize(_topology->getNbEdges());
00264 
00265     if (_initialPoints.size() == 0)
00266     {
00267     // get restPosition
00268       VecCoord& p = *this->mstate->getX0();
00269       _initialPoints=p;
00270     }
00271 
00272     int i;
00273     // set edge tensor to 0
00274     for (i=0;i<_topology->getNbEdges();++i) {
00275         TriangularTMEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00276             _topology->getEdge(i),  (const sofa::helper::vector< unsigned int > )0,
00277             (const sofa::helper::vector< double >)0);
00278     }
00279     // create edge tensor by calling the triangle creation function
00280     sofa::helper::vector<unsigned int> triangleAdded;
00281     for (i=0;i<_topology->getNbTriangles();++i)
00282         triangleAdded.push_back(i);
00283     TriangularTMTriangleCreationFunction(triangleAdded,(void*) this,
00284         edgeInfo);
00285 
00286 
00287     edgeInfo.setCreateFunction(TriangularTMEdgeCreationFunction);
00288     edgeInfo.setCreateTriangleFunction(TriangularTMTriangleCreationFunction);
00289     edgeInfo.setDestroyTriangleFunction(TriangularTMTriangleDestructionFunction);
00290     edgeInfo.setCreateParameter( (void *) this );
00291     edgeInfo.setDestroyParameter( (void *) this );
00292 
00293 }
00294 
00295 
00296 template <class DataTypes> 
00297     double TriangularTensorMassForceField<DataTypes>::getPotentialEnergy(const VecCoord& /*x*/)
00298 {
00299     std::cerr<<"TriangularTensorMassForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00300     return 0;
00301 }
00302 template <class DataTypes> 
00303 void TriangularTensorMassForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& /*v*/)
00304 {
00305     unsigned int i,v0,v1;
00306     unsigned int nbEdges=_topology->getNbEdges();
00307 
00308     EdgeRestInformation *einfo;
00309 
00310     Deriv force;
00311     Coord dp0,dp1,dp;
00312 
00313 
00314     for(i=0; i<nbEdges; i++ )
00315     {
00316         einfo=&edgeInfo[i];
00317         v0=_topology->getEdge(i)[0];
00318         v1=_topology->getEdge(i)[1];
00319         dp0=x[v0]-_initialPoints[v0];
00320         dp1=x[v1]-_initialPoints[v1];
00321         dp = dp1-dp0;
00322 
00323         f[v1]+=einfo->DfDx*dp;
00324         f[v0]-=einfo->DfDx.transposeMultiply(dp);
00325     }
00326 
00327 }
00328 
00329 
00330 template <class DataTypes> 
00331 void TriangularTensorMassForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00332 {
00333     unsigned int v0,v1;
00334     int nbEdges=_topology->getNbEdges();
00335 
00336     EdgeRestInformation *einfo;
00337 
00338 
00339     Deriv force;
00340     Coord dp0,dp1,dp;
00341 
00342     for(int i=0; i<nbEdges; i++ )
00343     {
00344         einfo=&edgeInfo[i];
00345         v0=_topology->getEdge(i)[0];
00346         v1=_topology->getEdge(i)[1];
00347         dp0=dx[v0];
00348         dp1=dx[v1];
00349         dp = dp1-dp0;
00350 
00351         df[v1]+=einfo->DfDx*dp;
00352         df[v0]-=einfo->DfDx.transposeMultiply(dp);
00353     }
00354 
00355 }
00356 
00357 
00358 template<class DataTypes>
00359 void TriangularTensorMassForceField<DataTypes>::updateLameCoefficients()
00360 {
00361     lambda= f_youngModulus.getValue()*f_poissonRatio.getValue()/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00362     mu = f_youngModulus.getValue()*(1-f_poissonRatio.getValue())/(1-f_poissonRatio.getValue()*f_poissonRatio.getValue());
00363 //  std::cerr << "initialized Lame coef : lambda=" <<lambda<< " mu="<<mu<<std::endl;
00364 }
00365 
00366 
00367 template<class DataTypes>
00368 void TriangularTensorMassForceField<DataTypes>::draw()
00369 {
00370     int i;
00371     if (!getContext()->getShowForceFields()) return;
00372     if (!this->mstate) return;
00373 
00374     if (getContext()->getShowWireFrame())
00375         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00376 
00377     VecCoord& x = *this->mstate->getX();    
00378     int nbTriangles=_topology->getNbTriangles();
00379 
00380     glDisable(GL_LIGHTING);
00381 
00382     glBegin(GL_TRIANGLES);
00383     for(i=0;i<nbTriangles; ++i)
00384     {
00385         int a = _topology->getTriangle(i)[0];
00386         int b = _topology->getTriangle(i)[1];
00387         int c = _topology->getTriangle(i)[2];
00388 
00389         glColor4f(0,1,0,1);
00390         helper::gl::glVertexT(x[a]);
00391         glColor4f(0,0.5,0.5,1);
00392         helper::gl::glVertexT(x[b]);
00393         glColor4f(0,0,1,1);
00394         helper::gl::glVertexT(x[c]);
00395     }
00396     glEnd();
00397 
00398 
00399     if (getContext()->getShowWireFrame())
00400         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00401 }
00402 
00403 } // namespace forcefield
00404 
00405 } // namespace Components
00406 
00407 } // namespace Sofa

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