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 #ifndef SOFA_COMPONENT_FORCEFIELD_TETRAHEDRONFEMFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_TETRAHEDRONFEMFORCEFIELD_INL
00027
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include <sofa/component/forcefield/TetrahedralCorotationalFEMForceField.h>
00030 #include <sofa/component/topology/GridTopology.h>
00031 #include <sofa/helper/PolarDecompose.h>
00032 #include <sofa/helper/gl/template.h>
00033 #include <sofa/component/topology/TetrahedronData.inl>
00034 #include <assert.h>
00035 #include <iostream>
00036 #include <set>
00037
00038 using std::cerr;
00039 using std::endl;
00040 using std::set;
00041
00042
00043 namespace sofa
00044 {
00045
00046 namespace component
00047 {
00048
00049 namespace forcefield
00050 {
00051
00052 using namespace sofa::defaulttype;
00053 using namespace sofa::component::topology;
00054 using namespace core::componentmodel::topology;
00055
00056 template< class DataTypes>
00057 void TetrahedralCorotationalFEMForceField<DataTypes>::CFTetrahedronCreationFunction (int tetrahedronIndex, void* param,
00058 TetrahedronInformation &,
00059 const Tetrahedron& ,
00060 const helper::vector< unsigned int > &,
00061 const helper::vector< double >&)
00062 {
00063 TetrahedralCorotationalFEMForceField<DataTypes> *ff= (TetrahedralCorotationalFEMForceField<DataTypes> *)param;
00064 if (ff) {
00065
00066 const Tetrahedron &t=ff->_topology->getTetra(tetrahedronIndex);
00067 Index a = t[0];
00068 Index b = t[1];
00069 Index c = t[2];
00070 Index d = t[3];
00071
00072 switch(ff->method)
00073 {
00074 case SMALL :
00075 ff->computeMaterialStiffness(tetrahedronIndex,a,b,c,d);
00076 ff->initSmall(tetrahedronIndex,a,b,c,d);
00077 break;
00078 case LARGE :
00079 ff->computeMaterialStiffness(tetrahedronIndex,a,b,c,d);
00080 ff->initLarge(tetrahedronIndex,a,b,c,d);
00081
00082 break;
00083 case POLAR :
00084 ff->computeMaterialStiffness(tetrahedronIndex,a,b,c,d);
00085 ff->initPolar(tetrahedronIndex,a,b,c,d);
00086 break;
00087 }
00088 }
00089 }
00090
00091 template<class DataTypes>
00092 void TetrahedralCorotationalFEMForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00093 {
00094 this->core::componentmodel::behavior::ForceField<DataTypes>::parse(arg);
00095
00096 this->setComputeGlobalMatrix(std::string(arg->getAttribute("computeGlobalMatrix","false"))=="true");
00097 }
00098
00099 template <class DataTypes> void TetrahedralCorotationalFEMForceField<DataTypes>::handleTopologyChange()
00100 {
00101 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00102 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00103
00104
00105 tetrahedronInfo.handleTopologyEvents(itBegin,itEnd);
00106
00107 }
00108
00109 template <class DataTypes>
00110 void TetrahedralCorotationalFEMForceField<DataTypes>::init()
00111 {
00112 f_poissonRatio.beginEdit();
00113 f_youngModulus.beginEdit();
00114 f_localStiffnessFactor.beginEdit();
00115 f_updateStiffnessMatrix.beginEdit();
00116 f_assembling.beginEdit();
00117
00118
00119 this->core::componentmodel::behavior::ForceField<DataTypes>::init();
00120
00121 _topology = getContext()->getMeshTopology();
00122
00123 if (_topology->getNbTetras()==0)
00124 {
00125 std::cerr << "ERROR(TetrahedralCorotationalFEMForceField): object must have a Tetrahedral Set Topology.\n";
00126 return;
00127 }
00128
00129 reinit();
00130
00131 }
00132
00133
00134 template <class DataTypes>
00135 void TetrahedralCorotationalFEMForceField<DataTypes>::reinit()
00136 {
00137
00138 if (f_method.getValue() == "small")
00139 this->setMethod(SMALL);
00140 else if (f_method.getValue() == "polar")
00141 this->setMethod(POLAR);
00142 else this->setMethod(LARGE);
00143
00144 tetrahedronInfo.resize(_topology->getNbTetras());
00145
00146 for (int i=0;i<_topology->getNbTetras();++i) {
00147 CFTetrahedronCreationFunction(i, (void*) this, tetrahedronInfo[i],
00148 _topology->getTetra(i), (const std::vector< unsigned int > )0,
00149 (const std::vector< double >)0);
00150 }
00151
00152 tetrahedronInfo.setCreateFunction(CFTetrahedronCreationFunction);
00153 tetrahedronInfo.setCreateParameter( (void *) this );
00154 tetrahedronInfo.setDestroyParameter( (void *) this );
00155
00156 }
00157
00158
00159 template<class DataTypes>
00160 void TetrahedralCorotationalFEMForceField<DataTypes>::addForce (VecDeriv& f, const VecCoord& p, const VecDeriv& )
00161 {
00162
00163 switch(method)
00164 {
00165 case SMALL :
00166 {
00167 for(int i = 0 ; i<_topology->getNbTetras();++i)
00168 {
00169 accumulateForceSmall( f, p, i );
00170 }
00171 break;
00172 }
00173 case LARGE :
00174 {
00175 for(int i = 0 ; i<_topology->getNbTetras();++i)
00176 {
00177 accumulateForceLarge( f, p, i );
00178 }
00179 break;
00180 }
00181 case POLAR :
00182 {
00183 for(int i = 0 ; i<_topology->getNbTetras();++i)
00184 {
00185 accumulateForcePolar( f, p, i );
00186 }
00187 break;
00188 }
00189 }
00190 }
00191
00192 template<class DataTypes>
00193 void TetrahedralCorotationalFEMForceField<DataTypes>::addDForce (VecDeriv& v, const VecDeriv& x)
00194 {
00195 switch(method)
00196 {
00197 case SMALL :
00198 {
00199 for(int i = 0 ; i<_topology->getNbTetras();++i)
00200 {
00201 const Tetrahedron &t=_topology->getTetra(i);
00202 Index a = t[0];
00203 Index b = t[1];
00204 Index c = t[2];
00205 Index d = t[3];
00206
00207 applyStiffnessSmall( v,x, i, a,b,c,d );
00208 }
00209 break;
00210 }
00211 case LARGE :
00212 {
00213 for(int i = 0 ; i<_topology->getNbTetras();++i)
00214 {
00215 const Tetrahedron &t=_topology->getTetra(i);
00216 Index a = t[0];
00217 Index b = t[1];
00218 Index c = t[2];
00219 Index d = t[3];
00220
00221 applyStiffnessLarge( v,x, i, a,b,c,d );
00222 }
00223 break;
00224 }
00225 case POLAR :
00226 {
00227 for(int i = 0 ; i<_topology->getNbTetras();++i)
00228 {
00229 const Tetrahedron &t=_topology->getTetra(i);
00230 Index a = t[0];
00231 Index b = t[1];
00232 Index c = t[2];
00233 Index d = t[3];
00234
00235 applyStiffnessPolar( v,x, i, a,b,c,d );
00236 }
00237 break;
00238 }
00239 }
00240 }
00241
00242 template <class DataTypes>
00243 double TetrahedralCorotationalFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00244 {
00245 cerr<<"TetrahedralCorotationalFEMForceField::getPotentialEnergy-not-implemented !!!"<<endl;
00246 return 0;
00247 }
00248
00249 template<class DataTypes>
00250 void TetrahedralCorotationalFEMForceField<DataTypes>::computeStrainDisplacement( StrainDisplacement &J, Coord a, Coord b, Coord c, Coord d )
00251 {
00252
00253 Mat<2, 3, Real> M;
00254
00255 M[0][0] = b[1];
00256 M[0][1] = c[1];
00257 M[0][2] = d[1];
00258 M[1][0] = b[2];
00259 M[1][1] = c[2];
00260 M[1][2] = d[2];
00261 J[0][0] = J[1][3] = J[2][5] = - peudo_determinant_for_coef( M );
00262 M[0][0] = b[0];
00263 M[0][1] = c[0];
00264 M[0][2] = d[0];
00265 J[0][3] = J[1][1] = J[2][4] = peudo_determinant_for_coef( M );
00266 M[1][0] = b[1];
00267 M[1][1] = c[1];
00268 M[1][2] = d[1];
00269 J[0][5] = J[1][4] = J[2][2] = - peudo_determinant_for_coef( M );
00270
00271 M[0][0] = c[1];
00272 M[0][1] = d[1];
00273 M[0][2] = a[1];
00274 M[1][0] = c[2];
00275 M[1][1] = d[2];
00276 M[1][2] = a[2];
00277 J[3][0] = J[4][3] = J[5][5] = peudo_determinant_for_coef( M );
00278 M[0][0] = c[0];
00279 M[0][1] = d[0];
00280 M[0][2] = a[0];
00281 J[3][3] = J[4][1] = J[5][4] = - peudo_determinant_for_coef( M );
00282 M[1][0] = c[1];
00283 M[1][1] = d[1];
00284 M[1][2] = a[1];
00285 J[3][5] = J[4][4] = J[5][2] = peudo_determinant_for_coef( M );
00286
00287 M[0][0] = d[1];
00288 M[0][1] = a[1];
00289 M[0][2] = b[1];
00290 M[1][0] = d[2];
00291 M[1][1] = a[2];
00292 M[1][2] = b[2];
00293 J[6][0] = J[7][3] = J[8][5] = - peudo_determinant_for_coef( M );
00294 M[0][0] = d[0];
00295 M[0][1] = a[0];
00296 M[0][2] = b[0];
00297 J[6][3] = J[7][1] = J[8][4] = peudo_determinant_for_coef( M );
00298 M[1][0] = d[1];
00299 M[1][1] = a[1];
00300 M[1][2] = b[1];
00301 J[6][5] = J[7][4] = J[8][2] = - peudo_determinant_for_coef( M );
00302
00303 M[0][0] = a[1];
00304 M[0][1] = b[1];
00305 M[0][2] = c[1];
00306 M[1][0] = a[2];
00307 M[1][1] = b[2];
00308 M[1][2] = c[2];
00309 J[9][0] = J[10][3] = J[11][5] = peudo_determinant_for_coef( M );
00310 M[0][0] = a[0];
00311 M[0][1] = b[0];
00312 M[0][2] = c[0];
00313 J[9][3] = J[10][1] = J[11][4] = - peudo_determinant_for_coef( M );
00314 M[1][0] = a[1];
00315 M[1][1] = b[1];
00316 M[1][2] = c[1];
00317 J[9][5] = J[10][4] = J[11][2] = peudo_determinant_for_coef( M );
00318
00319
00320
00321 J[0][1] = J[0][2] = J[0][4] = J[1][0] = J[1][2] = J[1][5] = J[2][0] = J[2][1] = J[2][3] = 0;
00322 J[3][1] = J[3][2] = J[3][4] = J[4][0] = J[4][2] = J[4][5] = J[5][0] = J[5][1] = J[5][3] = 0;
00323 J[6][1] = J[6][2] = J[6][4] = J[7][0] = J[7][2] = J[7][5] = J[8][0] = J[8][1] = J[8][3] = 0;
00324 J[9][1] = J[9][2] = J[9][4] = J[10][0] = J[10][2] = J[10][5] = J[11][0] = J[11][1] = J[11][3] = 0;
00325
00326
00327 }
00328
00329 template<class DataTypes>
00330 typename TetrahedralCorotationalFEMForceField<DataTypes>::Real TetrahedralCorotationalFEMForceField<DataTypes>::peudo_determinant_for_coef ( const Mat<2, 3, Real>& M )
00331 {
00332 return M[0][1]*M[1][2] - M[1][1]*M[0][2] - M[0][0]*M[1][2] + M[1][0]*M[0][2] + M[0][0]*M[1][1] - M[1][0]*M[0][1];
00333 }
00334
00335 template<class DataTypes>
00336 void TetrahedralCorotationalFEMForceField<DataTypes>::computeStiffnessMatrix( StiffnessMatrix& S,StiffnessMatrix& SR,const MaterialStiffness &K, const StrainDisplacement &J, const Transformation& Rot )
00337 {
00338 MatNoInit<6, 12, Real> Jt;
00339 Jt.transpose( J );
00340
00341 MatNoInit<12, 12, Real> JKJt;
00342 JKJt = J*K*Jt;
00343
00344 MatNoInit<12, 12, Real> RR,RRt;
00345 RR.clear();
00346 RRt.clear();
00347 for(int i=0;i<3;++i)
00348 for(int j=0;j<3;++j)
00349 {
00350 RR[i][j]=RR[i+3][j+3]=RR[i+6][j+6]=RR[i+9][j+9]=Rot[i][j];
00351 RRt[i][j]=RRt[i+3][j+3]=RRt[i+6][j+6]=RRt[i+9][j+9]=Rot[j][i];
00352 }
00353
00354 S = RR*JKJt;
00355 SR = S*RRt;
00356 }
00357
00358 template<class DataTypes>
00359 void TetrahedralCorotationalFEMForceField<DataTypes>::computeMaterialStiffness(int i, Index&a, Index&b, Index&c, Index&d)
00360 {
00361
00362 const VecReal& localStiffnessFactor = _localStiffnessFactor;
00363 const Real youngModulus = (localStiffnessFactor.empty() ? 1.0f : localStiffnessFactor[i*localStiffnessFactor.size()/_topology->getNbTetras()])*_youngModulus;
00364 const Real poissonRatio = _poissonRatio;
00365
00366 tetrahedronInfo[i].materialMatrix[0][0] = tetrahedronInfo[i].materialMatrix[1][1] = tetrahedronInfo[i].materialMatrix[2][2] = 1;
00367 tetrahedronInfo[i].materialMatrix[0][1] = tetrahedronInfo[i].materialMatrix[0][2] = tetrahedronInfo[i].materialMatrix[1][0]
00368 = tetrahedronInfo[i].materialMatrix[1][2] = tetrahedronInfo[i].materialMatrix[2][0] =
00369 tetrahedronInfo[i].materialMatrix[2][1] = poissonRatio/(1-poissonRatio);
00370 tetrahedronInfo[i].materialMatrix[0][3] = tetrahedronInfo[i].materialMatrix[0][4] = tetrahedronInfo[i].materialMatrix[0][5] = 0;
00371 tetrahedronInfo[i].materialMatrix[1][3] = tetrahedronInfo[i].materialMatrix[1][4] = tetrahedronInfo[i].materialMatrix[1][5] = 0;
00372 tetrahedronInfo[i].materialMatrix[2][3] = tetrahedronInfo[i].materialMatrix[2][4] = tetrahedronInfo[i].materialMatrix[2][5] = 0;
00373 tetrahedronInfo[i].materialMatrix[3][0] = tetrahedronInfo[i].materialMatrix[3][1] = tetrahedronInfo[i].materialMatrix[3][2] = tetrahedronInfo[i].materialMatrix[3][4] = tetrahedronInfo[i].materialMatrix[3][5] = 0;
00374 tetrahedronInfo[i].materialMatrix[4][0] = tetrahedronInfo[i].materialMatrix[4][1] = tetrahedronInfo[i].materialMatrix[4][2] = tetrahedronInfo[i].materialMatrix[4][3] = tetrahedronInfo[i].materialMatrix[4][5] = 0;
00375 tetrahedronInfo[i].materialMatrix[5][0] = tetrahedronInfo[i].materialMatrix[5][1] = tetrahedronInfo[i].materialMatrix[5][2] = tetrahedronInfo[i].materialMatrix[5][3] = tetrahedronInfo[i].materialMatrix[5][4] = 0;
00376 tetrahedronInfo[i].materialMatrix[3][3] = tetrahedronInfo[i].materialMatrix[4][4] = tetrahedronInfo[i].materialMatrix[5][5] = (1-2*poissonRatio)/(2*(1-poissonRatio));
00377 tetrahedronInfo[i].materialMatrix *= (youngModulus*(1-poissonRatio))/((1+poissonRatio)*(1-2*poissonRatio));
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 const VecCoord *X0=this->mstate->getX0();
00394
00395 Coord A = (*X0)[b] - (*X0)[a];
00396 Coord B = (*X0)[c] - (*X0)[a];
00397 Coord C = (*X0)[d] - (*X0)[a];
00398 Coord AB = cross(A, B);
00399 Real volumes6 = fabs( dot( AB, C ) );
00400 if (volumes6<0)
00401 {
00402 std::cerr << "ERROR: Negative volume for tetra "<<i<<" <"<<a<<','<<b<<','<<c<<','<<d<<"> = "<<volumes6/6<<std::endl;
00403 }
00404 tetrahedronInfo[i].materialMatrix /= volumes6;
00405 }
00406
00407 template<class DataTypes>
00408 inline void TetrahedralCorotationalFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const MaterialStiffness &K, const StrainDisplacement &J )
00409 {
00410 #if 0
00411 F = J*(K*(J.multTranspose(Depl)));
00412
00413 #else
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 VecNoInit<6,Real> JtD;
00438 JtD[0] = J[ 0][0]*Depl[ 0]+
00439 J[ 3][0]*Depl[ 3]+
00440 J[ 6][0]*Depl[ 6]+
00441 J[ 9][0]*Depl[ 9] ;
00442 JtD[1] = J[ 1][1]*Depl[ 1]+
00443 J[ 4][1]*Depl[ 4]+
00444 J[ 7][1]*Depl[ 7]+
00445 J[10][1]*Depl[10] ;
00446 JtD[2] = J[ 2][2]*Depl[ 2]+
00447 J[ 5][2]*Depl[ 5]+
00448 J[ 8][2]*Depl[ 8]+
00449 J[11][2]*Depl[11] ;
00450 JtD[3] = J[ 0][3]*Depl[ 0]+ J[ 1][3]*Depl[ 1]+
00451 J[ 3][3]*Depl[ 3]+ J[ 4][3]*Depl[ 4]+
00452 J[ 6][3]*Depl[ 6]+ J[ 7][3]*Depl[ 7]+
00453 J[ 9][3]*Depl[ 9]+ J[10][3]*Depl[10] ;
00454 JtD[4] = J[ 1][4]*Depl[ 1]+ J[ 2][4]*Depl[ 2]+
00455 J[ 4][4]*Depl[ 4]+ J[ 5][4]*Depl[ 5]+
00456 J[ 7][4]*Depl[ 7]+ J[ 8][4]*Depl[ 8]+
00457 J[10][4]*Depl[10]+ J[11][4]*Depl[11] ;
00458 JtD[5] = J[ 0][5]*Depl[ 0]+ J[ 2][5]*Depl[ 2]+
00459 J[ 3][5]*Depl[ 3]+ J[ 5][5]*Depl[ 5]+
00460 J[ 6][5]*Depl[ 6]+ J[ 8][5]*Depl[ 8]+
00461 J[ 9][5]*Depl[ 9]+ J[11][5]*Depl[11];
00462
00463
00464
00465 Vec<6,Real> KJtD;
00466 KJtD[0] = K[0][0]*JtD[0]+ K[0][1]*JtD[1]+ K[0][2]*JtD[2]
00467 ;
00468 KJtD[1] = K[1][0]*JtD[0]+ K[1][1]*JtD[1]+ K[1][2]*JtD[2]
00469 ;
00470 KJtD[2] = K[2][0]*JtD[0]+ K[2][1]*JtD[1]+ K[2][2]*JtD[2]
00471 ;
00472 KJtD[3] =
00473 K[3][3]*JtD[3] ;
00474 KJtD[4] =
00475 K[4][4]*JtD[4] ;
00476 KJtD[5] =
00477 K[5][5]*JtD[5] ;
00478
00479 F[ 0] = J[ 0][0]*KJtD[0]+
00480 J[ 0][3]*KJtD[3]+J[ 0][5]*KJtD[5] ;
00481 F[ 1] = J[ 1][1]*KJtD[1]+
00482 J[ 1][3]*KJtD[3]+ J[ 1][4]*KJtD[4] ;
00483 F[ 2] = J[ 2][2]*KJtD[2]+
00484 J[ 2][4]*KJtD[4]+ J[ 2][5]*KJtD[5] ;
00485 F[ 3] = J[ 3][0]*KJtD[0]+
00486 J[ 3][3]*KJtD[3]+J[ 3][5]*KJtD[5] ;
00487 F[ 4] = J[ 4][1]*KJtD[1]+
00488 J[ 4][3]*KJtD[3]+ J[ 4][4]*KJtD[4] ;
00489 F[ 5] = J[ 5][2]*KJtD[2]+
00490 J[ 5][4]*KJtD[4]+ J[ 5][5]*KJtD[5] ;
00491 F[ 6] = J[ 6][0]*KJtD[0]+
00492 J[ 6][3]*KJtD[3]+J[ 6][5]*KJtD[5] ;
00493 F[ 7] = J[ 7][1]*KJtD[1]+
00494 J[ 7][3]*KJtD[3]+ J[ 7][4]*KJtD[4] ;
00495 F[ 8] = J[ 8][2]*KJtD[2]+
00496 J[ 8][4]*KJtD[4]+ J[ 8][5]*KJtD[5] ;
00497 F[ 9] = J[ 9][0]*KJtD[0]+
00498 J[ 9][3]*KJtD[3]+J[ 9][5]*KJtD[5] ;
00499 F[10] = J[10][1]*KJtD[1]+
00500 J[10][3]*KJtD[3]+ J[10][4]*KJtD[4] ;
00501 F[11] = J[11][2]*KJtD[2]+
00502 J[11][4]*KJtD[4]+ J[11][5]*KJtD[5] ;
00503 #endif
00504 }
00505
00509
00510 template<class DataTypes>
00511 void TetrahedralCorotationalFEMForceField<DataTypes>::initSmall(int i, Index&a, Index&b, Index&c, Index&d)
00512 {
00513 const VecCoord *X0=this->mstate->getX0();
00514
00515 computeStrainDisplacement(tetrahedronInfo[i].strainDisplacementMatrix, (*X0)[a], (*X0)[b], (*X0)[c], (*X0)[d] );
00516 }
00517
00518 template<class DataTypes>
00519 void TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall( Vector& f, const Vector & p,Index elementIndex )
00520 {
00521
00522
00523 const Tetrahedron &t=_topology->getTetra(elementIndex);
00524 const VecCoord *X0=this->mstate->getX0();
00525
00526
00527 Index a = t[0];
00528 Index b = t[1];
00529 Index c = t[2];
00530 Index d = t[3];
00531
00532
00533 Displacement D;
00534 D[0] = 0;
00535 D[1] = 0;
00536 D[2] = 0;
00537 D[3] = (*X0)[b][0] - (*X0)[a][0] - p[b][0]+p[a][0];
00538 D[4] = (*X0)[b][1] - (*X0)[a][1] - p[b][1]+p[a][1];
00539 D[5] = (*X0)[b][2] - (*X0)[a][2] - p[b][2]+p[a][2];
00540 D[6] = (*X0)[c][0] - (*X0)[a][0] - p[c][0]+p[a][0];
00541 D[7] = (*X0)[c][1] - (*X0)[a][1] - p[c][1]+p[a][1];
00542 D[8] = (*X0)[c][2] - (*X0)[a][2] - p[c][2]+p[a][2];
00543 D[9] = (*X0)[d][0] - (*X0)[a][0] - p[d][0]+p[a][0];
00544 D[10] = (*X0)[d][1] - (*X0)[a][1] - p[d][1]+p[a][1];
00545 D[11] = (*X0)[d][2] - (*X0)[a][2] - p[d][2]+p[a][2];
00546
00547
00548
00549
00550
00551 Displacement F;
00552
00553 if(!_assembling)
00554 {
00555 computeForce( F, D,tetrahedronInfo[elementIndex].materialMatrix,tetrahedronInfo[elementIndex].strainDisplacementMatrix );
00556
00557 }
00558 else
00559 {
00560 Transformation Rot;
00561 Rot[0][0]=Rot[1][1]=Rot[2][2]=1;
00562 Rot[0][1]=Rot[0][2]=0;
00563 Rot[1][0]=Rot[1][2]=0;
00564 Rot[2][0]=Rot[2][1]=0;
00565
00566
00567 StiffnessMatrix JKJt,tmp;
00568 computeStiffnessMatrix(JKJt,tmp,tetrahedronInfo[elementIndex].materialMatrix,tetrahedronInfo[elementIndex].strainDisplacementMatrix,Rot);
00569
00570
00571 if(elementIndex==0)
00572 {
00573 for(unsigned int i=0;i<_stiffnesses.size();++i)
00574 {
00575 _stiffnesses[i].resize(0);
00576 }
00577 }
00578
00579 for(int i=0;i<12;++i)
00580 {
00581 int row = t[i/3]*3+i%3;
00582
00583 for(int j=0;j<12;++j)
00584 {
00585 if(JKJt[i][j]!=0)
00586 {
00587
00588 int col = t[j/3]*3+j%3;
00589
00590
00591
00592
00593
00594
00595 typename CompressedValue::iterator result = _stiffnesses[row].end();
00596 for(typename CompressedValue::iterator it=_stiffnesses[row].begin();it!=_stiffnesses[row].end()&&result==_stiffnesses[row].end();++it)
00597 {
00598 if( (*it).first == col )
00599 result = it;
00600 }
00601
00602 if( result==_stiffnesses[row].end() )
00603 _stiffnesses[row].push_back( Col_Value(col,JKJt[i][j] ) );
00604 else
00605 (*result).second += JKJt[i][j];
00606 }
00607 }
00608 }
00609
00610
00611
00612
00613
00614 F = JKJt * D;
00615 }
00616
00617 f[a] += Deriv( F[0], F[1], F[2] );
00618 f[b] += Deriv( F[3], F[4], F[5] );
00619 f[c] += Deriv( F[6], F[7], F[8] );
00620 f[d] += Deriv( F[9], F[10], F[11] );
00621 }
00622
00623 template<class DataTypes>
00624 void TetrahedralCorotationalFEMForceField<DataTypes>::applyStiffnessSmall( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d )
00625 {
00626 Displacement X;
00627
00628 X[0] = x[a][0];
00629 X[1] = x[a][1];
00630 X[2] = x[a][2];
00631
00632 X[3] = x[b][0];
00633 X[4] = x[b][1];
00634 X[5] = x[b][2];
00635
00636 X[6] = x[c][0];
00637 X[7] = x[c][1];
00638 X[8] = x[c][2];
00639
00640 X[9] = x[d][0];
00641 X[10] = x[d][1];
00642 X[11] = x[d][2];
00643
00644 Displacement F;
00645 computeForce( F, X,tetrahedronInfo[i].materialMatrix,tetrahedronInfo[i].strainDisplacementMatrix);
00646
00647 f[a] += Deriv( -F[0], -F[1], -F[2] );
00648 f[b] += Deriv( -F[3], -F[4], -F[5] );
00649 f[c] += Deriv( -F[6], -F[7], -F[8] );
00650 f[d] += Deriv( -F[9], -F[10], -F[11] );
00651 }
00652
00656
00657 template<class DataTypes>
00658 inline void TetrahedralCorotationalFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, const Vector &p, const Index &a, const Index &b, const Index &c)
00659 {
00660
00661
00662
00663
00664 Coord edgex = p[b]-p[a];
00665 edgex.normalize();
00666
00667 Coord edgey = p[c]-p[a];
00668 edgey.normalize();
00669
00670 Coord edgez = cross( edgex, edgey );
00671 edgez.normalize();
00672
00673 edgey = cross( edgez, edgex );
00674 edgey.normalize();
00675
00676 r[0][0] = edgex[0];
00677 r[0][1] = edgex[1];
00678 r[0][2] = edgex[2];
00679 r[1][0] = edgey[0];
00680 r[1][1] = edgey[1];
00681 r[1][2] = edgey[2];
00682 r[2][0] = edgez[0];
00683 r[2][1] = edgez[1];
00684 r[2][2] = edgez[2];
00685 }
00686
00687 template<class DataTypes>
00688 void TetrahedralCorotationalFEMForceField<DataTypes>::initLarge(int i, Index&a, Index&b, Index&c, Index&d)
00689 {
00690
00691
00692
00693
00694 const VecCoord *X0=this->mstate->getX0();
00695
00696 Transformation R_0_1;
00697 computeRotationLarge( R_0_1, (*X0), a, b, c);
00698
00699 tetrahedronInfo[i].rotatedInitialElements[0] = R_0_1*(*X0)[a];
00700 tetrahedronInfo[i].rotatedInitialElements[1] = R_0_1*(*X0)[b];
00701 tetrahedronInfo[i].rotatedInitialElements[2] = R_0_1*(*X0)[c];
00702 tetrahedronInfo[i].rotatedInitialElements[3] = R_0_1*(*X0)[d];
00703
00704
00705
00706
00707
00708 tetrahedronInfo[i].rotatedInitialElements[1] -= tetrahedronInfo[i].rotatedInitialElements[0];
00709 tetrahedronInfo[i].rotatedInitialElements[2] -= tetrahedronInfo[i].rotatedInitialElements[0];
00710 tetrahedronInfo[i].rotatedInitialElements[3] -= tetrahedronInfo[i].rotatedInitialElements[0];
00711 tetrahedronInfo[i].rotatedInitialElements[0] = Coord(0,0,0);
00712
00713
00714
00715 computeStrainDisplacement( tetrahedronInfo[i].strainDisplacementMatrix,tetrahedronInfo[i].rotatedInitialElements[0], tetrahedronInfo[i].rotatedInitialElements[1],tetrahedronInfo[i].rotatedInitialElements[2],tetrahedronInfo[i].rotatedInitialElements[3] );
00716 }
00717
00718 template<class DataTypes>
00719 void TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceLarge( Vector& f, const Vector & p, Index elementIndex )
00720 {
00721 const Tetrahedron &t=_topology->getTetra(elementIndex);
00722
00723
00724 Transformation R_0_2;
00725 computeRotationLarge( R_0_2, p, t[0],t[1],t[2]);
00726 tetrahedronInfo[elementIndex].rotation.transpose(R_0_2);
00727
00728
00729
00730 helper::fixed_array<Coord,4> deforme;
00731 for(int i=0;i<4;++i)
00732 deforme[i] = R_0_2*p[t[i]];
00733
00734 deforme[1][0] -= deforme[0][0];
00735 deforme[2][0] -= deforme[0][0];
00736 deforme[2][1] -= deforme[0][1];
00737 deforme[3] -= deforme[0];
00738
00739
00740 Displacement D;
00741 D[0] = 0;
00742 D[1] = 0;
00743 D[2] = 0;
00744 D[3] = tetrahedronInfo[elementIndex].rotatedInitialElements[1][0] - deforme[1][0];
00745 D[4] = 0;
00746 D[5] = 0;
00747 D[6] = tetrahedronInfo[elementIndex].rotatedInitialElements[2][0] - deforme[2][0];
00748 D[7] = tetrahedronInfo[elementIndex].rotatedInitialElements[2][1] - deforme[2][1];
00749 D[8] = 0;
00750 D[9] = tetrahedronInfo[elementIndex].rotatedInitialElements[3][0] - deforme[3][0];
00751 D[10] = tetrahedronInfo[elementIndex].rotatedInitialElements[3][1] - deforme[3][1];
00752 D[11] =tetrahedronInfo[elementIndex].rotatedInitialElements[3][2] - deforme[3][2];
00753
00754
00755
00756 Displacement F;
00757 if(_updateStiffnessMatrix)
00758 {
00759 tetrahedronInfo[elementIndex].strainDisplacementMatrix[0][0] = ( - deforme[2][1]*deforme[3][2] );
00760 tetrahedronInfo[elementIndex].strainDisplacementMatrix[1][1] = ( deforme[2][0]*deforme[3][2] - deforme[1][0]*deforme[3][2] );
00761 tetrahedronInfo[elementIndex].strainDisplacementMatrix[2][2] = ( deforme[2][1]*deforme[3][0] - deforme[2][0]*deforme[3][1] + deforme[1][0]*deforme[3][1] - deforme[1][0]*deforme[2][1] );
00762
00763 tetrahedronInfo[elementIndex].strainDisplacementMatrix[3][0] = ( deforme[2][1]*deforme[3][2] );
00764 tetrahedronInfo[elementIndex].strainDisplacementMatrix[4][1] = ( - deforme[2][0]*deforme[3][2] );
00765 tetrahedronInfo[elementIndex].strainDisplacementMatrix[5][2] = ( - deforme[2][1]*deforme[3][0] + deforme[2][0]*deforme[3][1] );
00766
00767 tetrahedronInfo[elementIndex].strainDisplacementMatrix[7][1] = ( deforme[1][0]*deforme[3][2] );
00768 tetrahedronInfo[elementIndex].strainDisplacementMatrix[8][2] = ( - deforme[1][0]*deforme[3][1] );
00769
00770 tetrahedronInfo[elementIndex].strainDisplacementMatrix[11][2] = ( deforme[1][0]*deforme[2][1] );
00771 }
00772
00773 if(!_assembling)
00774 {
00775
00776 computeForce( F, D, tetrahedronInfo[elementIndex].materialMatrix, tetrahedronInfo[elementIndex].strainDisplacementMatrix);
00777 for(int i=0;i<12;i+=3)
00778 f[t[i/3]] += tetrahedronInfo[elementIndex].rotation * Deriv( F[i], F[i+1], F[i+2] );
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 }
00790 else
00791 {
00792 tetrahedronInfo[elementIndex].strainDisplacementMatrix[6][0] = 0;
00793 tetrahedronInfo[elementIndex].strainDisplacementMatrix[9][0] = 0;
00794 tetrahedronInfo[elementIndex].strainDisplacementMatrix[10][1] = 0;
00795
00796 StiffnessMatrix RJKJt, RJKJtRt;
00797 computeStiffnessMatrix(RJKJt,RJKJtRt,tetrahedronInfo[elementIndex].materialMatrix, tetrahedronInfo[elementIndex].strainDisplacementMatrix,tetrahedronInfo[elementIndex].rotation);
00798
00799
00800
00801 if(elementIndex==0)
00802 {
00803 for(unsigned int i=0;i<_stiffnesses.size();++i)
00804 {
00805 _stiffnesses[i].resize(0);
00806 }
00807 }
00808
00809 for(int i=0;i<12;++i)
00810 {
00811 int row = t[i/3]*3+i%3;
00812
00813 for(int j=0;j<12;++j)
00814 {
00815 int col = t[j/3]*3+j%3;
00816
00817
00818 typename CompressedValue::iterator result = _stiffnesses[row].end();
00819 for(typename CompressedValue::iterator it=_stiffnesses[row].begin();it!=_stiffnesses[row].end()&&result==_stiffnesses[row].end();++it)
00820 {
00821 if( (*it).first == col )
00822 {
00823 result = it;
00824 }
00825 }
00826
00827 if( result==_stiffnesses[row].end() )
00828 {
00829 _stiffnesses[row].push_back( Col_Value(col,RJKJtRt[i][j] ) );
00830 }
00831 else
00832 {
00833 (*result).second += RJKJtRt[i][j];
00834 }
00835 }
00836 }
00837
00838 F = RJKJt*D;
00839
00840 for(int i=0;i<12;i+=3)
00841 f[t[i/3]] += Deriv( F[i], F[i+1], F[i+2] );
00842 }
00843 }
00844
00845 template<class DataTypes>
00846 void TetrahedralCorotationalFEMForceField<DataTypes>::applyStiffnessLarge( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d )
00847 {
00848 Transformation R_0_2;
00849 R_0_2.transpose(tetrahedronInfo[i].rotation);
00850
00851 Displacement X;
00852 Coord x_2;
00853
00854 x_2 = R_0_2*x[a];
00855 X[0] = x_2[0];
00856 X[1] = x_2[1];
00857 X[2] = x_2[2];
00858
00859 x_2 = R_0_2*x[b];
00860 X[3] = x_2[0];
00861 X[4] = x_2[1];
00862 X[5] = x_2[2];
00863
00864 x_2 = R_0_2*x[c];
00865 X[6] = x_2[0];
00866 X[7] = x_2[1];
00867 X[8] = x_2[2];
00868
00869 x_2 = R_0_2*x[d];
00870 X[9] = x_2[0];
00871 X[10] = x_2[1];
00872 X[11] = x_2[2];
00873
00874 Displacement F;
00875
00876
00877
00878 computeForce( F, X,tetrahedronInfo[i].materialMatrix, tetrahedronInfo[i].strainDisplacementMatrix);
00879
00880
00881
00882 f[a] += tetrahedronInfo[i].rotation * Deriv( -F[0], -F[1], -F[2] );
00883 f[b] += tetrahedronInfo[i].rotation * Deriv( -F[3], -F[4], -F[5] );
00884 f[c] += tetrahedronInfo[i].rotation * Deriv( -F[6], -F[7], -F[8] );
00885 f[d] += tetrahedronInfo[i].rotation * Deriv( -F[9], -F[10], -F[11] );
00886 }
00887
00891
00892 template<class DataTypes>
00893 void TetrahedralCorotationalFEMForceField<DataTypes>::initPolar(int i, Index& a, Index&b, Index&c, Index&d)
00894 {
00895 const VecCoord *X0=this->mstate->getX0();
00896
00897 Transformation A;
00898 A[0] = (*X0)[b]-(*X0)[a];
00899 A[1] = (*X0)[c]-(*X0)[a];
00900 A[2] = (*X0)[d]-(*X0)[a];
00901 tetrahedronInfo[i].initialTransformation = A;
00902
00903 Transformation R_0_1;
00904 MatNoInit<3,3,Real> S;
00905 polar_decomp(A, R_0_1, S);
00906
00907 tetrahedronInfo[i].rotatedInitialElements[0] = R_0_1*(*X0)[a];
00908 tetrahedronInfo[i].rotatedInitialElements[1] = R_0_1*(*X0)[b];
00909 tetrahedronInfo[i].rotatedInitialElements[2] = R_0_1*(*X0)[c];
00910 tetrahedronInfo[i].rotatedInitialElements[3] = R_0_1*(*X0)[d];
00911
00912 computeStrainDisplacement( tetrahedronInfo[i].strainDisplacementMatrix,tetrahedronInfo[i].rotatedInitialElements[0], tetrahedronInfo[i].rotatedInitialElements[1],tetrahedronInfo[i].rotatedInitialElements[2],tetrahedronInfo[i].rotatedInitialElements[3] );
00913 }
00914
00915 template<class DataTypes>
00916 void TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForcePolar( Vector& f, const Vector & p, Index elementIndex )
00917 {
00918 const Tetrahedron &t=_topology->getTetra(elementIndex);
00919
00920 Transformation A;
00921 A[0] = p[t[1]]-p[t[0]];
00922 A[1] = p[t[2]]-p[t[0]];
00923 A[2] = p[t[3]]-p[t[0]];
00924
00925 Transformation R_0_2;
00926 MatNoInit<3,3,Real> S;
00927 polar_decomp(A, R_0_2, S);
00928
00929 tetrahedronInfo[elementIndex].rotation.transpose( R_0_2 );
00930
00931
00932 helper::fixed_array<Coord, 4> deforme;
00933 for(int i=0;i<4;++i)
00934 deforme[i] = R_0_2 * p[t[i]];
00935
00936
00937 Displacement D;
00938 D[0] = tetrahedronInfo[elementIndex].rotatedInitialElements[0][0] - deforme[0][0];
00939 D[1] = tetrahedronInfo[elementIndex].rotatedInitialElements[0][1] - deforme[0][1];
00940 D[2] = tetrahedronInfo[elementIndex].rotatedInitialElements[0][2] - deforme[0][2];
00941 D[3] = tetrahedronInfo[elementIndex].rotatedInitialElements[1][0] - deforme[1][0];
00942 D[4] = tetrahedronInfo[elementIndex].rotatedInitialElements[1][1] - deforme[1][1];
00943 D[5] = tetrahedronInfo[elementIndex].rotatedInitialElements[1][2] - deforme[1][2];
00944 D[6] = tetrahedronInfo[elementIndex].rotatedInitialElements[2][0] - deforme[2][0];
00945 D[7] = tetrahedronInfo[elementIndex].rotatedInitialElements[2][1] - deforme[2][1];
00946 D[8] = tetrahedronInfo[elementIndex].rotatedInitialElements[2][2] - deforme[2][2];
00947 D[9] = tetrahedronInfo[elementIndex].rotatedInitialElements[3][0] - deforme[3][0];
00948 D[10] = tetrahedronInfo[elementIndex].rotatedInitialElements[3][1] - deforme[3][1];
00949 D[11] = tetrahedronInfo[elementIndex].rotatedInitialElements[3][2] - deforme[3][2];
00950
00951
00952 Displacement F;
00953 if(_updateStiffnessMatrix)
00954 {
00955
00956 computeStrainDisplacement( tetrahedronInfo[elementIndex].strainDisplacementMatrix, deforme[0],deforme[1],deforme[2],deforme[3] );
00957 }
00958
00959 if(!_assembling)
00960 {
00961 computeForce( F, D, tetrahedronInfo[elementIndex].materialMatrix, tetrahedronInfo[elementIndex].strainDisplacementMatrix );
00962 for(int i=0;i<12;i+=3)
00963 f[t[i/3]] += tetrahedronInfo[elementIndex].rotation * Deriv( F[i], F[i+1], F[i+2] );
00964 }
00965 else
00966 {
00967 std::cerr << "TODO(TetrahedralCorotationalFEMForceField): support for assembling system matrix when using polar method.\n";
00968 }
00969 }
00970
00971 template<class DataTypes>
00972 void TetrahedralCorotationalFEMForceField<DataTypes>::applyStiffnessPolar( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d )
00973 {
00974 Transformation R_0_2;
00975 R_0_2.transpose( tetrahedronInfo[i].rotation );
00976
00977 Displacement X;
00978 Coord x_2;
00979
00980 x_2 = R_0_2*x[a];
00981 X[0] = x_2[0];
00982 X[1] = x_2[1];
00983 X[2] = x_2[2];
00984
00985 x_2 = R_0_2*x[b];
00986 X[3] = x_2[0];
00987 X[4] = x_2[1];
00988 X[5] = x_2[2];
00989
00990 x_2 = R_0_2*x[c];
00991 X[6] = x_2[0];
00992 X[7] = x_2[1];
00993 X[8] = x_2[2];
00994
00995 x_2 = R_0_2*x[d];
00996 X[9] = x_2[0];
00997 X[10] = x_2[1];
00998 X[11] = x_2[2];
00999
01000 Displacement F;
01001
01002
01003
01004 computeForce( F, X, tetrahedronInfo[i].materialMatrix, tetrahedronInfo[i].strainDisplacementMatrix);
01005
01006
01007
01008 f[a] -= tetrahedronInfo[i].rotation * Deriv( F[0], F[1], F[2] );
01009 f[b] -= tetrahedronInfo[i].rotation * Deriv( F[3], F[4], F[5] );
01010 f[c] -= tetrahedronInfo[i].rotation * Deriv( F[6], F[7], F[8] );
01011 f[d] -= tetrahedronInfo[i].rotation * Deriv( F[9], F[10], F[11] );
01012 }
01013
01017
01018 template<class DataTypes>
01019 void TetrahedralCorotationalFEMForceField<DataTypes>::draw()
01020 {
01021 if (!getContext()->getShowForceFields()) return;
01022 if (!this->mstate) return;
01023
01024 const VecCoord& x = *this->mstate->getX();
01025
01026 if (getContext()->getShowWireFrame())
01027 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01028
01029 glDisable(GL_LIGHTING);
01030
01031 glBegin(GL_TRIANGLES);
01032
01033 for(int i = 0 ; i<_topology->getNbTetras();++i)
01034 {
01035 const Tetrahedron &t=_topology->getTetra(i);
01036
01037 Index a = t[0];
01038 Index b = t[1];
01039 Index c = t[2];
01040 Index d = t[3];
01041 Coord center = (x[a]+x[b]+x[c]+x[d])*0.125;
01042 Coord pa = (x[a]+center)*(Real)0.666667;
01043 Coord pb = (x[b]+center)*(Real)0.666667;
01044 Coord pc = (x[c]+center)*(Real)0.666667;
01045 Coord pd = (x[d]+center)*(Real)0.666667;
01046
01047 glColor4f(0,0,1,1);
01048 helper::gl::glVertexT(pa);
01049 helper::gl::glVertexT(pb);
01050 helper::gl::glVertexT(pc);
01051
01052 glColor4f(0,0.5,1,1);
01053 helper::gl::glVertexT(pb);
01054 helper::gl::glVertexT(pc);
01055 helper::gl::glVertexT(pd);
01056
01057 glColor4f(0,1,1,1);
01058 helper::gl::glVertexT(pc);
01059 helper::gl::glVertexT(pd);
01060 helper::gl::glVertexT(pa);
01061
01062 glColor4f(0.5,1,1,1);
01063 helper::gl::glVertexT(pd);
01064 helper::gl::glVertexT(pa);
01065 helper::gl::glVertexT(pb);
01066 }
01067 glEnd();
01068
01069 if (getContext()->getShowWireFrame())
01070 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01071 }
01072
01073
01074 template<class DataTypes>
01075 void TetrahedralCorotationalFEMForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix *mat, SReal , unsigned int &offset)
01076 {
01077
01078 unsigned int i,j,n1, n2, row, column, ROW, COLUMN;
01079
01080 Transformation Rot;
01081 StiffnessMatrix JKJt,tmp;
01082
01083 Index noeud1, noeud2;
01084
01085 Rot[0][0]=Rot[1][1]=Rot[2][2]=1;
01086 Rot[0][1]=Rot[0][2]=0;
01087 Rot[1][0]=Rot[1][2]=0;
01088 Rot[2][0]=Rot[2][1]=0;
01089
01090 for(int IT=0 ; IT != _topology->getNbTetras() ; ++IT)
01091 {
01092 computeStiffnessMatrix(JKJt,tmp,tetrahedronInfo[IT].materialMatrix,tetrahedronInfo[IT].strainDisplacementMatrix,Rot);
01093 const Tetrahedron &t=_topology->getTetra(IT);
01094
01095
01096 for (n1=0; n1<4; n1++)
01097 {
01098 noeud1 = t[n1];
01099
01100 for(i=0; i<3; i++)
01101 {
01102 ROW = offset+3*noeud1+i;
01103 row = 3*n1+i;
01104
01105 for (n2=0; n2<4; n2++)
01106 {
01107 noeud2 = t[n2];
01108
01109 for (j=0; j<3; j++)
01110 {
01111 COLUMN = offset+3*noeud2+j;
01112 column = 3*n2+j;
01113 mat->add(ROW, COLUMN, tmp[row][column]);
01114 }
01115 }
01116 }
01117 }
01118 }
01119 }
01120
01121 }
01122
01123 }
01124
01125 }
01126
01127 #endif