00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sofa/component/forcefield/TetrahedralTensorMassForceField.h>
00026 #include <fstream>
00027 #include <iostream>
00028 #include <sofa/helper/gl/template.h>
00029 #include <sofa/component/topology/TetrahedronData.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
00052 typedef BaseMeshTopology::Tetra Tetra;
00053 typedef BaseMeshTopology::TetraEdges TetraEdges;
00054
00055 typedef Tetra Tetrahedron;
00056 typedef TetraEdges TetrahedronEdges;
00057
00058
00059 template< class DataTypes>
00060 void TetrahedralTensorMassForceField<DataTypes>::TetrahedralTMEdgeCreationFunction(int , void* param, EdgeRestInformation &ei,
00061 const Edge& , const helper::vector< unsigned int > &,
00062 const helper::vector< double >&)
00063 {
00064 TetrahedralTensorMassForceField<DataTypes> *ff= (TetrahedralTensorMassForceField<DataTypes> *)param;
00065 if (ff) {
00066
00067 unsigned int u,v;
00069 for (u=0;u<3;++u) {
00070 for (v=0;v<3;++v) {
00071 ei.DfDx[u][v]=0;
00072 }
00073 }
00074
00075 }
00076 }
00077
00078 template< class DataTypes>
00079 void TetrahedralTensorMassForceField<DataTypes>::TetrahedralTMTetrahedronCreationFunction (const helper::vector<unsigned int> &tetrahedronAdded,
00080 void* param, helper::vector<EdgeRestInformation> &edgeData)
00081 {
00082 TetrahedralTensorMassForceField<DataTypes> *ff= (TetrahedralTensorMassForceField<DataTypes> *)param;
00083 if (ff) {
00084
00085 unsigned int i,j,k,l,u,v;
00086
00087 typename DataTypes::Real val1,volume;
00088 typename DataTypes::Real lambda=ff->getLambda();
00089 typename DataTypes::Real mu=ff->getMu();
00090 typename DataTypes::Real lambdastar, mustar;
00091 typename DataTypes::Coord point[4],shapeVector[4];
00092
00093 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00094
00095 for (i=0;i<tetrahedronAdded.size();++i) {
00096
00098 const TetrahedronEdges &te= ff->_topology->getEdgeTetraShell(tetrahedronAdded[i]);
00100 const Tetrahedron &t= ff->_topology->getTetra(tetrahedronAdded[i]);
00101
00102 for(j=0;j<4;++j)
00103 point[j]=(*restPosition)[t[j]];
00105 volume=dot(cross(point[1]-point[0],point[2]-point[0]),point[0]-point[3]);
00106
00107 for(j=0;j<4;++j) {
00108 if ((j%2)==0)
00109 shapeVector[j]=cross(point[(j+2)%4] - point[(j+1)%4],point[(j+3)%4] - point[(j+1)%4])/volume;
00110 else
00111 shapeVector[j]= -cross(point[(j+2)%4] - point[(j+1)%4],point[(j+3)%4] - point[(j+1)%4])/volume;
00112 }
00113
00114 lambdastar=lambda*fabs(volume)/6;
00115 mustar=mu*fabs(volume)/6;
00116
00117
00118 for(j=0;j<6;++j){
00120 k = ff->_topology->getLocalTetrahedronEdges(j)[0];
00121 l = ff->_topology->getLocalTetrahedronEdges(j)[1];
00122
00123 Mat3 &m=edgeData[te[j]].DfDx;
00124
00125 val1= dot(shapeVector[k],shapeVector[l])*mustar;
00126
00127 if (ff->f_printLog.getValue()) {
00128 if (val1<0)
00129 std::cerr<<"negative cotangent["<<tetrahedronAdded[i]<<"]["<<j<<"]"<<std::endl;
00130 }
00131
00132 if (ff->_topology->getEdge(te[j])[0]!=t[l]) {
00133 for (u=0;u<3;++u) {
00134 for (v=0;v<3;++v) {
00135 m[u][v]+= lambdastar*shapeVector[l][u]*shapeVector[k][v]+mustar*shapeVector[k][u]*shapeVector[l][v];
00136 }
00137 m[u][u]+=val1;
00138 }
00139 } else {
00140 for (u=0;u<3;++u) {
00141 for (v=0;v<3;++v) {
00142 m[v][u]+= lambdastar*shapeVector[l][u]*shapeVector[k][v]+mustar*shapeVector[k][u]*shapeVector[l][v];
00143 }
00144 m[u][u]+=val1;
00145 }
00146 }
00147
00148
00149 }
00150 }
00151
00152 }
00153 }
00154
00155 template< class DataTypes>
00156 void TetrahedralTensorMassForceField<DataTypes>::TetrahedralTMTetrahedronDestructionFunction (const helper::vector<unsigned int> &tetrahedronRemoved,
00157 void* param, helper::vector<EdgeRestInformation> &edgeData)
00158 {
00159 TetrahedralTensorMassForceField<DataTypes> *ff= (TetrahedralTensorMassForceField<DataTypes> *)param;
00160 if (ff) {
00161
00162 unsigned int i,j,k,l,u,v;
00163
00164 typename DataTypes::Real val1,volume;
00165 typename DataTypes::Real lambda=ff->getLambda();
00166 typename DataTypes::Real mu=ff->getMu();
00167 typename DataTypes::Real lambdastar, mustar;
00168 typename DataTypes::Coord point[4],shapeVector[4];
00169
00170 const typename DataTypes::VecCoord *restPosition=ff->mstate->getX0();
00171
00172 for (i=0;i<tetrahedronRemoved.size();++i) {
00173
00175 const TetrahedronEdges &te= ff->_topology->getEdgeTetraShell(tetrahedronRemoved[i]);
00177 const Tetrahedron &t= ff->_topology->getTetra(tetrahedronRemoved[i]);
00178
00179 for(j=0;j<4;++j)
00180 point[j]=(*restPosition)[t[j]];
00182 volume=dot(cross(point[1]-point[0],point[2]-point[0]),point[0]-point[3]);
00183
00184 for(j=0;j<4;++j) {
00185 if ((j%2)==0)
00186 shapeVector[j]=cross(point[(j+2)%4] - point[(j+1)%4],point[(j+3)%4] - point[(j+1)%4])/volume;
00187 else
00188 shapeVector[j]= -cross(point[(j+2)%4] - point[(j+1)%4],point[(j+3)%4] - point[(j+1)%4])/volume;
00189 }
00190
00191 lambdastar=lambda*fabs(volume)/6;
00192 mustar=mu*fabs(volume)/6;
00193
00194
00195 for(j=0;j<6;++j){
00197 k = ff->_topology->getLocalTetrahedronEdges(j)[0];
00198 l = ff->_topology->getLocalTetrahedronEdges(j)[1];
00199
00200 Mat3 &m=edgeData[te[j]].DfDx;
00201
00202 val1= dot(shapeVector[k],shapeVector[l])*mustar;
00203
00204 if (ff->f_printLog.getValue()) {
00205 if (val1<0)
00206 std::cerr<<"negative cotangent["<<tetrahedronRemoved[i]<<"]["<<j<<"]"<<std::endl;
00207 }
00208
00209 if (ff->_topology->getEdge(te[j])[0]!=t[l]) {
00210 for (u=0;u<3;++u) {
00211 for (v=0;v<3;++v) {
00212 m[u][v]-= lambdastar*shapeVector[l][u]*shapeVector[k][v]+mustar*shapeVector[k][u]*shapeVector[l][v];
00213 }
00214 m[u][u]-=val1;
00215 }
00216 } else {
00217 for (u=0;u<3;++u) {
00218 for (v=0;v<3;++v) {
00219 m[v][u]-= lambdastar*shapeVector[l][u]*shapeVector[k][v]+mustar*shapeVector[k][u]*shapeVector[l][v];
00220 }
00221 m[u][u]-=val1;
00222 }
00223 }
00224
00225
00226 }
00227
00228 }
00229
00230 }
00231 }
00232
00233
00234 template <class DataTypes> TetrahedralTensorMassForceField<DataTypes>::TetrahedralTensorMassForceField()
00235 : _initialPoints(0)
00236 , updateMatrix(true)
00237 , f_poissonRatio(initData(&f_poissonRatio,(Real)0.3,"poissonRatio","Poisson ratio in Hooke's law"))
00238 , f_youngModulus(initData(&f_youngModulus,(Real)1000.,"youngModulus","Young modulus in Hooke's law"))
00239 , lambda(0)
00240 , mu(0)
00241 {
00242 }
00243
00244 template <class DataTypes> void TetrahedralTensorMassForceField<DataTypes>::handleTopologyChange()
00245 {
00246 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00247 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00248
00249 edgeInfo.handleTopologyEvents(itBegin,itEnd);
00250 }
00251
00252 template <class DataTypes> TetrahedralTensorMassForceField<DataTypes>::~TetrahedralTensorMassForceField()
00253 {
00254
00255 }
00256
00257 template <class DataTypes> void TetrahedralTensorMassForceField<DataTypes>::init()
00258 {
00259 std::cerr << "initializing TetrahedralTensorMassForceField" << std::endl;
00260 this->Inherited::init();
00261
00262 _topology = getContext()->getMeshTopology();
00263
00264 if (_topology->getNbTetras()==0)
00265 {
00266 std::cerr << "ERROR(TetrahedralTensorMassForceField): object must have a Tetrahedral Set Topology.\n";
00267 return;
00268 }
00269 updateLameCoefficients();
00270
00272 edgeInfo.resize(_topology->getNbEdges());
00273
00274 if (_initialPoints.size() == 0)
00275 {
00276
00277 VecCoord& p = *this->mstate->getX0();
00278 _initialPoints=p;
00279 }
00280
00281 int i;
00282
00283 for (i=0;i<_topology->getNbEdges();++i) {
00284 TetrahedralTMEdgeCreationFunction(i, (void*) this, edgeInfo[i],
00285 _topology->getEdge(i), (const std::vector< unsigned int > )0,
00286 (const std::vector< double >)0);
00287 }
00288
00289 std::vector<unsigned int> tetrahedronAdded;
00290 for (i=0;i<_topology->getNbTetras();++i)
00291 tetrahedronAdded.push_back(i);
00292 TetrahedralTMTetrahedronCreationFunction(tetrahedronAdded,(void*) this,
00293 edgeInfo);
00294
00295
00296 edgeInfo.setCreateFunction(TetrahedralTMEdgeCreationFunction);
00297 edgeInfo.setCreateTetrahedronFunction(TetrahedralTMTetrahedronCreationFunction);
00298 edgeInfo.setDestroyTetrahedronFunction(TetrahedralTMTetrahedronDestructionFunction);
00299 edgeInfo.setCreateParameter( (void *) this );
00300 edgeInfo.setDestroyParameter( (void *) this );
00301
00302 }
00303
00304
00305 template <class DataTypes>
00306 double TetrahedralTensorMassForceField<DataTypes>::getPotentialEnergy(const VecCoord& )
00307 {
00308 std::cerr<<"TetrahedralTensorMassForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00309 return 0;
00310 }
00311 template <class DataTypes>
00312 void TetrahedralTensorMassForceField<DataTypes>::addForce(VecDeriv& f, const VecCoord& x, const VecDeriv& )
00313 {
00314 unsigned int v0,v1;
00315 int nbEdges=_topology->getNbEdges();
00316
00317 EdgeRestInformation *einfo;
00318
00319 Deriv force;
00320 Coord dp0,dp1,dp;
00321
00322
00323 for(int i=0; i<nbEdges; i++ )
00324 {
00325 einfo=&edgeInfo[i];
00326 v0=_topology->getEdge(i)[0];
00327 v1=_topology->getEdge(i)[1];
00328 dp0=x[v0]-_initialPoints[v0];
00329 dp1=x[v1]-_initialPoints[v1];
00330 dp = dp1-dp0;
00331
00332 f[v1]+=einfo->DfDx*dp;
00333 f[v0]-=einfo->DfDx.transposeMultiply(dp);
00334 }
00335
00336 }
00337
00338
00339 template <class DataTypes>
00340 void TetrahedralTensorMassForceField<DataTypes>::addDForce(VecDeriv& df, const VecDeriv& dx)
00341 {
00342 unsigned int v0,v1;
00343 int nbEdges=_topology->getNbEdges();
00344
00345 EdgeRestInformation *einfo;
00346
00347
00348 Deriv force;
00349 Coord dp0,dp1,dp;
00350
00351 for(int i=0; i<nbEdges; i++ )
00352 {
00353 einfo=&edgeInfo[i];
00354 v0=_topology->getEdge(i)[0];
00355 v1=_topology->getEdge(i)[1];
00356 dp0=dx[v0];
00357 dp1=dx[v1];
00358 dp = dp1-dp0;
00359
00360 df[v1]+=einfo->DfDx*dp;
00361 df[v0]-=einfo->DfDx.transposeMultiply(dp);
00362 }
00363
00364 }
00365
00366
00367 template<class DataTypes>
00368 void TetrahedralTensorMassForceField<DataTypes>::updateLameCoefficients()
00369 {
00370 lambda= f_youngModulus.getValue()*f_poissonRatio.getValue()/((1-2*f_poissonRatio.getValue())*(1+f_poissonRatio.getValue()));
00371 mu = f_youngModulus.getValue()/(2*(1+f_poissonRatio.getValue()));
00372
00373 }
00374
00375
00376 template<class DataTypes>
00377 void TetrahedralTensorMassForceField<DataTypes>::draw()
00378 {
00379 if (!getContext()->getShowForceFields()) return;
00380 if (!this->mstate) return;
00381
00382 if (getContext()->getShowWireFrame())
00383 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 if (getContext()->getShowWireFrame())
00409 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00410 }
00411
00412 }
00413
00414 }
00415
00416 }