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/TetrahedronFEMForceField.h>
00030 #include <sofa/component/topology/GridTopology.h>
00031 #include <sofa/helper/PolarDecompose.h>
00032 #include <sofa/helper/gl/template.h>
00033 #include <assert.h>
00034 #include <iostream>
00035 #include <set>
00036
00037 using std::cerr;
00038 using std::endl;
00039 using std::set;
00040
00041
00042 namespace sofa
00043 {
00044
00045 namespace component
00046 {
00047
00048 namespace forcefield
00049 {
00050
00051 using namespace sofa::defaulttype;
00052
00053
00054
00058
00059 template<class DataTypes>
00060 inline void TetrahedronFEMForceField<DataTypes>::computeStrainDisplacement( StrainDisplacement &J, Coord a, Coord b, Coord c, Coord d )
00061 {
00062
00063 Mat<2, 3, Real> M;
00064
00065 M[0][0] = b[1];
00066 M[0][1] = c[1];
00067 M[0][2] = d[1];
00068 M[1][0] = b[2];
00069 M[1][1] = c[2];
00070 M[1][2] = d[2];
00071 J[0][0] = J[1][3] = J[2][5] = - peudo_determinant_for_coef( M );
00072 M[0][0] = b[0];
00073 M[0][1] = c[0];
00074 M[0][2] = d[0];
00075 J[0][3] = J[1][1] = J[2][4] = peudo_determinant_for_coef( M );
00076 M[1][0] = b[1];
00077 M[1][1] = c[1];
00078 M[1][2] = d[1];
00079 J[0][5] = J[1][4] = J[2][2] = - peudo_determinant_for_coef( M );
00080
00081 M[0][0] = c[1];
00082 M[0][1] = d[1];
00083 M[0][2] = a[1];
00084 M[1][0] = c[2];
00085 M[1][1] = d[2];
00086 M[1][2] = a[2];
00087 J[3][0] = J[4][3] = J[5][5] = peudo_determinant_for_coef( M );
00088 M[0][0] = c[0];
00089 M[0][1] = d[0];
00090 M[0][2] = a[0];
00091 J[3][3] = J[4][1] = J[5][4] = - peudo_determinant_for_coef( M );
00092 M[1][0] = c[1];
00093 M[1][1] = d[1];
00094 M[1][2] = a[1];
00095 J[3][5] = J[4][4] = J[5][2] = peudo_determinant_for_coef( M );
00096
00097 M[0][0] = d[1];
00098 M[0][1] = a[1];
00099 M[0][2] = b[1];
00100 M[1][0] = d[2];
00101 M[1][1] = a[2];
00102 M[1][2] = b[2];
00103 J[6][0] = J[7][3] = J[8][5] = - peudo_determinant_for_coef( M );
00104 M[0][0] = d[0];
00105 M[0][1] = a[0];
00106 M[0][2] = b[0];
00107 J[6][3] = J[7][1] = J[8][4] = peudo_determinant_for_coef( M );
00108 M[1][0] = d[1];
00109 M[1][1] = a[1];
00110 M[1][2] = b[1];
00111 J[6][5] = J[7][4] = J[8][2] = - peudo_determinant_for_coef( M );
00112
00113 M[0][0] = a[1];
00114 M[0][1] = b[1];
00115 M[0][2] = c[1];
00116 M[1][0] = a[2];
00117 M[1][1] = b[2];
00118 M[1][2] = c[2];
00119 J[9][0] = J[10][3] = J[11][5] = peudo_determinant_for_coef( M );
00120 M[0][0] = a[0];
00121 M[0][1] = b[0];
00122 M[0][2] = c[0];
00123 J[9][3] = J[10][1] = J[11][4] = - peudo_determinant_for_coef( M );
00124 M[1][0] = a[1];
00125 M[1][1] = b[1];
00126 M[1][2] = c[1];
00127 J[9][5] = J[10][4] = J[11][2] = peudo_determinant_for_coef( M );
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 }
00139
00140 template<class DataTypes>
00141 typename TetrahedronFEMForceField<DataTypes>::Real TetrahedronFEMForceField<DataTypes>::peudo_determinant_for_coef ( const Mat<2, 3, Real>& M )
00142 {
00143 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];
00144 }
00145
00146 template<class DataTypes>
00147 void TetrahedronFEMForceField<DataTypes>::computeStiffnessMatrix( StiffnessMatrix& S,StiffnessMatrix& SR,const MaterialStiffness &K, const StrainDisplacement &J, const Transformation& Rot )
00148 {
00149 MatNoInit<6, 12, Real> Jt;
00150 Jt.transpose( J );
00151
00152 MatNoInit<12, 12, Real> JKJt;
00153 JKJt = J*K*Jt;
00154
00155 MatNoInit<12, 12, Real> RR,RRt;
00156 RR.clear();
00157 RRt.clear();
00158 for(int i=0;i<3;++i)
00159 for(int j=0;j<3;++j)
00160 {
00161 RR[i][j]=RR[i+3][j+3]=RR[i+6][j+6]=RR[i+9][j+9]=Rot[i][j];
00162 RRt[i][j]=RRt[i+3][j+3]=RRt[i+6][j+6]=RRt[i+9][j+9]=Rot[j][i];
00163 }
00164
00165 S = RR*JKJt;
00166 SR = S*RRt;
00167 }
00168
00169 template<class DataTypes>
00170 void TetrahedronFEMForceField<DataTypes>::computeMaterialStiffness(int i, Index&a, Index&b, Index&c, Index&d)
00171 {
00172 const VecReal& localStiffnessFactor = _localStiffnessFactor;
00173 const Real youngModulus = (localStiffnessFactor.empty() ? 1.0f : localStiffnessFactor[i*localStiffnessFactor.size()/_indexedElements->size()])*_youngModulus;
00174 const Real poissonRatio = _poissonRatio;
00175
00176 _materialsStiffnesses[i][0][0] = _materialsStiffnesses[i][1][1] = _materialsStiffnesses[i][2][2] = 1;
00177 _materialsStiffnesses[i][0][1] = _materialsStiffnesses[i][0][2] = _materialsStiffnesses[i][1][0]
00178 = _materialsStiffnesses[i][1][2] = _materialsStiffnesses[i][2][0] =
00179 _materialsStiffnesses[i][2][1] = poissonRatio/(1-poissonRatio);
00180 _materialsStiffnesses[i][0][3] = _materialsStiffnesses[i][0][4] = _materialsStiffnesses[i][0][5] = 0;
00181 _materialsStiffnesses[i][1][3] = _materialsStiffnesses[i][1][4] = _materialsStiffnesses[i][1][5] = 0;
00182 _materialsStiffnesses[i][2][3] = _materialsStiffnesses[i][2][4] = _materialsStiffnesses[i][2][5] = 0;
00183 _materialsStiffnesses[i][3][0] = _materialsStiffnesses[i][3][1] = _materialsStiffnesses[i][3][2] = _materialsStiffnesses[i][3][4] = _materialsStiffnesses[i][3][5] = 0;
00184 _materialsStiffnesses[i][4][0] = _materialsStiffnesses[i][4][1] = _materialsStiffnesses[i][4][2] = _materialsStiffnesses[i][4][3] = _materialsStiffnesses[i][4][5] = 0;
00185 _materialsStiffnesses[i][5][0] = _materialsStiffnesses[i][5][1] = _materialsStiffnesses[i][5][2] = _materialsStiffnesses[i][5][3] = _materialsStiffnesses[i][5][4] = 0;
00186 _materialsStiffnesses[i][3][3] = _materialsStiffnesses[i][4][4] = _materialsStiffnesses[i][5][5] = (1-2*poissonRatio)/(2*(1-poissonRatio));
00187 _materialsStiffnesses[i] *= (youngModulus*(1-poissonRatio))/((1+poissonRatio)*(1-2*poissonRatio));
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 Coord A = _initialPoints[b] - _initialPoints[a];
00205 Coord B = _initialPoints[c] - _initialPoints[a];
00206 Coord C = _initialPoints[d] - _initialPoints[a];
00207 Coord AB = cross(A, B);
00208 Real volumes6 = fabs( dot( AB, C ) );
00209 if (volumes6<0)
00210 {
00211 std::cerr << "ERROR: Negative volume for tetra "<<i<<" <"<<a<<','<<b<<','<<c<<','<<d<<"> = "<<volumes6/6<<std::endl;
00212 }
00213 _materialsStiffnesses[i] /= volumes6*6;
00214 }
00215
00216 template<class DataTypes>
00217 inline void TetrahedronFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const MaterialStiffness &K, const StrainDisplacement &J )
00218 {
00219
00220
00221
00222
00223
00224
00225
00226 #if 0
00227 F = J*(K*(J.multTranspose(Depl)));
00228 #else
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 VecNoInit<6,Real> JtD;
00253 JtD[0] = J[ 0][0]*Depl[ 0]+
00254 J[ 3][0]*Depl[ 3]+
00255 J[ 6][0]*Depl[ 6]+
00256 J[ 9][0]*Depl[ 9] ;
00257 JtD[1] = J[ 1][1]*Depl[ 1]+
00258 J[ 4][1]*Depl[ 4]+
00259 J[ 7][1]*Depl[ 7]+
00260 J[10][1]*Depl[10] ;
00261 JtD[2] = J[ 2][2]*Depl[ 2]+
00262 J[ 5][2]*Depl[ 5]+
00263 J[ 8][2]*Depl[ 8]+
00264 J[11][2]*Depl[11] ;
00265 JtD[3] = J[ 0][3]*Depl[ 0]+ J[ 1][3]*Depl[ 1]+
00266 J[ 3][3]*Depl[ 3]+ J[ 4][3]*Depl[ 4]+
00267 J[ 6][3]*Depl[ 6]+ J[ 7][3]*Depl[ 7]+
00268 J[ 9][3]*Depl[ 9]+ J[10][3]*Depl[10] ;
00269 JtD[4] = J[ 1][4]*Depl[ 1]+ J[ 2][4]*Depl[ 2]+
00270 J[ 4][4]*Depl[ 4]+ J[ 5][4]*Depl[ 5]+
00271 J[ 7][4]*Depl[ 7]+ J[ 8][4]*Depl[ 8]+
00272 J[10][4]*Depl[10]+ J[11][4]*Depl[11] ;
00273 JtD[5] = J[ 0][5]*Depl[ 0]+ J[ 2][5]*Depl[ 2]+
00274 J[ 3][5]*Depl[ 3]+ J[ 5][5]*Depl[ 5]+
00275 J[ 6][5]*Depl[ 6]+ J[ 8][5]*Depl[ 8]+
00276 J[ 9][5]*Depl[ 9]+ J[11][5]*Depl[11];
00277
00278
00279
00280 VecNoInit<6,Real> KJtD;
00281 KJtD[0] = K[0][0]*JtD[0]+ K[0][1]*JtD[1]+ K[0][2]*JtD[2]
00282 ;
00283 KJtD[1] = K[1][0]*JtD[0]+ K[1][1]*JtD[1]+ K[1][2]*JtD[2]
00284 ;
00285 KJtD[2] = K[2][0]*JtD[0]+ K[2][1]*JtD[1]+ K[2][2]*JtD[2]
00286 ;
00287 KJtD[3] =
00288 K[3][3]*JtD[3] ;
00289 KJtD[4] =
00290 K[4][4]*JtD[4] ;
00291 KJtD[5] =
00292 K[5][5]*JtD[5] ;
00293
00294 F[ 0] = J[ 0][0]*KJtD[0]+
00295 J[ 0][3]*KJtD[3]+J[ 0][5]*KJtD[5] ;
00296 F[ 1] = J[ 1][1]*KJtD[1]+
00297 J[ 1][3]*KJtD[3]+ J[ 1][4]*KJtD[4] ;
00298 F[ 2] = J[ 2][2]*KJtD[2]+
00299 J[ 2][4]*KJtD[4]+ J[ 2][5]*KJtD[5] ;
00300 F[ 3] = J[ 3][0]*KJtD[0]+
00301 J[ 3][3]*KJtD[3]+J[ 3][5]*KJtD[5] ;
00302 F[ 4] = J[ 4][1]*KJtD[1]+
00303 J[ 4][3]*KJtD[3]+ J[ 4][4]*KJtD[4] ;
00304 F[ 5] = J[ 5][2]*KJtD[2]+
00305 J[ 5][4]*KJtD[4]+ J[ 5][5]*KJtD[5] ;
00306 F[ 6] = J[ 6][0]*KJtD[0]+
00307 J[ 6][3]*KJtD[3]+J[ 6][5]*KJtD[5] ;
00308 F[ 7] = J[ 7][1]*KJtD[1]+
00309 J[ 7][3]*KJtD[3]+ J[ 7][4]*KJtD[4] ;
00310 F[ 8] = J[ 8][2]*KJtD[2]+
00311 J[ 8][4]*KJtD[4]+ J[ 8][5]*KJtD[5] ;
00312 F[ 9] = J[ 9][0]*KJtD[0]+
00313 J[ 9][3]*KJtD[3]+J[ 9][5]*KJtD[5] ;
00314 F[10] = J[10][1]*KJtD[1]+
00315 J[10][3]*KJtD[3]+ J[10][4]*KJtD[4] ;
00316 F[11] = J[11][2]*KJtD[2]+
00317 J[11][4]*KJtD[4]+ J[11][5]*KJtD[5] ;
00318 #endif
00319 }
00320
00321 template<class DataTypes>
00322 inline void TetrahedronFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const MaterialStiffness &K, const StrainDisplacement &J, double fact )
00323 {
00324
00325
00326
00327
00328
00329
00330
00331 #if 0
00332 F = J*(K*(J.multTranspose(Depl)));
00333 F *= fact;
00334 #else
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 VecNoInit<6,Real> JtD;
00359 JtD[0] = J[ 0][0]*Depl[ 0]+
00360 J[ 3][0]*Depl[ 3]+
00361 J[ 6][0]*Depl[ 6]+
00362 J[ 9][0]*Depl[ 9] ;
00363 JtD[1] = J[ 1][1]*Depl[ 1]+
00364 J[ 4][1]*Depl[ 4]+
00365 J[ 7][1]*Depl[ 7]+
00366 J[10][1]*Depl[10] ;
00367 JtD[2] = J[ 2][2]*Depl[ 2]+
00368 J[ 5][2]*Depl[ 5]+
00369 J[ 8][2]*Depl[ 8]+
00370 J[11][2]*Depl[11] ;
00371 JtD[3] = J[ 0][3]*Depl[ 0]+ J[ 1][3]*Depl[ 1]+
00372 J[ 3][3]*Depl[ 3]+ J[ 4][3]*Depl[ 4]+
00373 J[ 6][3]*Depl[ 6]+ J[ 7][3]*Depl[ 7]+
00374 J[ 9][3]*Depl[ 9]+ J[10][3]*Depl[10] ;
00375 JtD[4] = J[ 1][4]*Depl[ 1]+ J[ 2][4]*Depl[ 2]+
00376 J[ 4][4]*Depl[ 4]+ J[ 5][4]*Depl[ 5]+
00377 J[ 7][4]*Depl[ 7]+ J[ 8][4]*Depl[ 8]+
00378 J[10][4]*Depl[10]+ J[11][4]*Depl[11] ;
00379 JtD[5] = J[ 0][5]*Depl[ 0]+ J[ 2][5]*Depl[ 2]+
00380 J[ 3][5]*Depl[ 3]+ J[ 5][5]*Depl[ 5]+
00381 J[ 6][5]*Depl[ 6]+ J[ 8][5]*Depl[ 8]+
00382 J[ 9][5]*Depl[ 9]+ J[11][5]*Depl[11];
00383
00384
00385
00386 VecNoInit<6,Real> KJtD;
00387 KJtD[0] = K[0][0]*JtD[0]+ K[0][1]*JtD[1]+ K[0][2]*JtD[2]
00388 ;
00389 KJtD[1] = K[1][0]*JtD[0]+ K[1][1]*JtD[1]+ K[1][2]*JtD[2]
00390 ;
00391 KJtD[2] = K[2][0]*JtD[0]+ K[2][1]*JtD[1]+ K[2][2]*JtD[2]
00392 ;
00393 KJtD[3] =
00394 K[3][3]*JtD[3] ;
00395 KJtD[4] =
00396 K[4][4]*JtD[4] ;
00397 KJtD[5] =
00398 K[5][5]*JtD[5] ;
00399
00400 KJtD *= fact;
00401
00402 F[ 0] = J[ 0][0]*KJtD[0]+
00403 J[ 0][3]*KJtD[3]+J[ 0][5]*KJtD[5] ;
00404 F[ 1] = J[ 1][1]*KJtD[1]+
00405 J[ 1][3]*KJtD[3]+ J[ 1][4]*KJtD[4] ;
00406 F[ 2] = J[ 2][2]*KJtD[2]+
00407 J[ 2][4]*KJtD[4]+ J[ 2][5]*KJtD[5] ;
00408 F[ 3] = J[ 3][0]*KJtD[0]+
00409 J[ 3][3]*KJtD[3]+J[ 3][5]*KJtD[5] ;
00410 F[ 4] = J[ 4][1]*KJtD[1]+
00411 J[ 4][3]*KJtD[3]+ J[ 4][4]*KJtD[4] ;
00412 F[ 5] = J[ 5][2]*KJtD[2]+
00413 J[ 5][4]*KJtD[4]+ J[ 5][5]*KJtD[5] ;
00414 F[ 6] = J[ 6][0]*KJtD[0]+
00415 J[ 6][3]*KJtD[3]+J[ 6][5]*KJtD[5] ;
00416 F[ 7] = J[ 7][1]*KJtD[1]+
00417 J[ 7][3]*KJtD[3]+ J[ 7][4]*KJtD[4] ;
00418 F[ 8] = J[ 8][2]*KJtD[2]+
00419 J[ 8][4]*KJtD[4]+ J[ 8][5]*KJtD[5] ;
00420 F[ 9] = J[ 9][0]*KJtD[0]+
00421 J[ 9][3]*KJtD[3]+J[ 9][5]*KJtD[5] ;
00422 F[10] = J[10][1]*KJtD[1]+
00423 J[10][3]*KJtD[3]+ J[10][4]*KJtD[4] ;
00424 F[11] = J[11][2]*KJtD[2]+
00425 J[11][4]*KJtD[4]+ J[11][5]*KJtD[5] ;
00426 #endif
00427 }
00428
00432
00433 template<class DataTypes>
00434 void TetrahedronFEMForceField<DataTypes>::initSmall(int i, Index&a, Index&b, Index&c, Index&d)
00435 {
00436 computeStrainDisplacement( _strainDisplacements[i], _initialPoints[a], _initialPoints[b], _initialPoints[c], _initialPoints[d] );
00437 }
00438
00439 template<class DataTypes>
00440 inline void TetrahedronFEMForceField<DataTypes>::accumulateForceSmall( Vector& f, const Vector & p, typename VecElement::const_iterator elementIt, Index elementIndex )
00441 {
00442
00443 Element index = *elementIt;
00444 Index a = index[0];
00445 Index b = index[1];
00446 Index c = index[2];
00447 Index d = index[3];
00448
00449
00450 Displacement D;
00451 D[0] = 0;
00452 D[1] = 0;
00453 D[2] = 0;
00454 D[3] = _initialPoints[b][0] - _initialPoints[a][0] - p[b][0]+p[a][0];
00455 D[4] = _initialPoints[b][1] - _initialPoints[a][1] - p[b][1]+p[a][1];
00456 D[5] = _initialPoints[b][2] - _initialPoints[a][2] - p[b][2]+p[a][2];
00457 D[6] = _initialPoints[c][0] - _initialPoints[a][0] - p[c][0]+p[a][0];
00458 D[7] = _initialPoints[c][1] - _initialPoints[a][1] - p[c][1]+p[a][1];
00459 D[8] = _initialPoints[c][2] - _initialPoints[a][2] - p[c][2]+p[a][2];
00460 D[9] = _initialPoints[d][0] - _initialPoints[a][0] - p[d][0]+p[a][0];
00461 D[10] = _initialPoints[d][1] - _initialPoints[a][1] - p[d][1]+p[a][1];
00462 D[11] = _initialPoints[d][2] - _initialPoints[a][2] - p[d][2]+p[a][2];
00463
00464
00465
00466
00467
00468 Displacement F;
00469
00470 if(!_assembling)
00471 {
00472 computeForce( F, D, _materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex] );
00473
00474 }
00475 else
00476 {
00477 Transformation Rot;
00478 Rot[0][0]=Rot[1][1]=Rot[2][2]=1;
00479 Rot[0][1]=Rot[0][2]=0;
00480 Rot[1][0]=Rot[1][2]=0;
00481 Rot[2][0]=Rot[2][1]=0;
00482
00483
00484 StiffnessMatrix JKJt,tmp;
00485 computeStiffnessMatrix(JKJt,tmp,_materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex],Rot);
00486
00487
00488 if(elementIndex==0)
00489 {
00490 for(unsigned int i=0;i<_stiffnesses.size();++i)
00491 {
00492 _stiffnesses[i].resize(0);
00493 }
00494 }
00495
00496 for(int i=0;i<12;++i)
00497 {
00498 int row = index[i/3]*3+i%3;
00499
00500 for(int j=0;j<12;++j)
00501 {
00502 if(JKJt[i][j]!=0)
00503 {
00504
00505 int col = index[j/3]*3+j%3;
00506
00507
00508
00509
00510
00511
00512 typename CompressedValue::iterator result = _stiffnesses[row].end();
00513 for(typename CompressedValue::iterator it=_stiffnesses[row].begin();it!=_stiffnesses[row].end()&&result==_stiffnesses[row].end();++it)
00514 {
00515 if( (*it).first == col )
00516 result = it;
00517 }
00518
00519 if( result==_stiffnesses[row].end() )
00520 _stiffnesses[row].push_back( Col_Value(col,JKJt[i][j] ) );
00521 else
00522 (*result).second += JKJt[i][j];
00523 }
00524 }
00525 }
00526
00527
00528
00529
00530
00531 F = JKJt * D;
00532 }
00533
00534 f[a] += Deriv( F[0], F[1], F[2] );
00535 f[b] += Deriv( F[3], F[4], F[5] );
00536 f[c] += Deriv( F[6], F[7], F[8] );
00537 f[d] += Deriv( F[9], F[10], F[11] );
00538 }
00539
00540 template<class DataTypes>
00541 inline void TetrahedronFEMForceField<DataTypes>::applyStiffnessSmall( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d, double fact )
00542 {
00543 Displacement X;
00544
00545 X[0] = x[a][0];
00546 X[1] = x[a][1];
00547 X[2] = x[a][2];
00548
00549 X[3] = x[b][0];
00550 X[4] = x[b][1];
00551 X[5] = x[b][2];
00552
00553 X[6] = x[c][0];
00554 X[7] = x[c][1];
00555 X[8] = x[c][2];
00556
00557 X[9] = x[d][0];
00558 X[10] = x[d][1];
00559 X[11] = x[d][2];
00560
00561 Displacement F;
00562 computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i], fact );
00563
00564 f[a] += Deriv( -F[0], -F[1], -F[2] );
00565 f[b] += Deriv( -F[3], -F[4], -F[5] );
00566 f[c] += Deriv( -F[6], -F[7], -F[8] );
00567 f[d] += Deriv( -F[9], -F[10], -F[11] );
00568 }
00569
00573
00574 template<class DataTypes>
00575 inline void TetrahedronFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, const Vector &p, const Index &a, const Index &b, const Index &c)
00576 {
00577
00578
00579
00580
00581 Coord edgex = p[b]-p[a];
00582 edgex.normalize();
00583
00584 Coord edgey = p[c]-p[a];
00585 edgey.normalize();
00586
00587 Coord edgez = cross( edgex, edgey );
00588 edgez.normalize();
00589
00590 edgey = cross( edgez, edgex );
00591 edgey.normalize();
00592
00593 r[0][0] = edgex[0];
00594 r[0][1] = edgex[1];
00595 r[0][2] = edgex[2];
00596 r[1][0] = edgey[0];
00597 r[1][1] = edgey[1];
00598 r[1][2] = edgey[2];
00599 r[2][0] = edgez[0];
00600 r[2][1] = edgez[1];
00601 r[2][2] = edgez[2];
00602 }
00603
00604
00605 template<class DataTypes>
00606 inline void TetrahedronFEMForceField<DataTypes>::getRotation(Transformation& R, unsigned int nodeIdx)
00607 {
00608 if (!_rotationIdx.empty())
00609 {
00610 Transformation R0t;
00611 R0t.transpose(_initialRotations[_rotationIdx[nodeIdx]]);
00612 R = _rotations[_rotationIdx[nodeIdx]] * R0t;
00613
00614 }
00615 else
00616 {
00617 R[0][0] = 1.0 ; R[1][1] = 1.0 ;R[2][2] = 1.0 ;
00618 R[0][1] = 0.0 ; R[0][2] = 0.0 ;
00619 R[1][0] = 0.0 ; R[1][2] = 0.0 ;
00620 R[2][0] = 0.0 ; R[2][1] = 0.0 ;
00621 }
00622 }
00623
00624 template<class DataTypes>
00625 void TetrahedronFEMForceField<DataTypes>::initLarge(int i, Index&a, Index&b, Index&c, Index&d)
00626 {
00627
00628
00629
00630
00631 Transformation R_0_1;
00632 computeRotationLarge( R_0_1, _initialPoints, a, b, c);
00633 _initialRotations[i].transpose(R_0_1);
00634
00635
00636 _rotationIdx[a] = i;
00637 _rotationIdx[b] = i;
00638 _rotationIdx[c] = i;
00639 _rotationIdx[d] = i;
00640
00641 _rotatedInitialElements[i][0] = R_0_1*_initialPoints[a];
00642 _rotatedInitialElements[i][1] = R_0_1*_initialPoints[b];
00643 _rotatedInitialElements[i][2] = R_0_1*_initialPoints[c];
00644 _rotatedInitialElements[i][3] = R_0_1*_initialPoints[d];
00645
00646
00647
00648
00649
00650 _rotatedInitialElements[i][1] -= _rotatedInitialElements[i][0];
00651 _rotatedInitialElements[i][2] -= _rotatedInitialElements[i][0];
00652 _rotatedInitialElements[i][3] -= _rotatedInitialElements[i][0];
00653 _rotatedInitialElements[i][0] = Coord(0,0,0);
00654
00655
00656
00657 computeStrainDisplacement( _strainDisplacements[i],_rotatedInitialElements[i][0], _rotatedInitialElements[i][1],_rotatedInitialElements[i][2],_rotatedInitialElements[i][3] );
00658 }
00659
00660 template<class DataTypes>
00661 inline void TetrahedronFEMForceField<DataTypes>::accumulateForceLarge( Vector& f, const Vector & p, typename VecElement::const_iterator elementIt, Index elementIndex )
00662 {
00663 Element index = *elementIt;
00664
00665
00666 Transformation R_0_2;
00667 computeRotationLarge( R_0_2, p, index[0],index[1],index[2]);
00668
00669 _rotations[elementIndex].transpose(R_0_2);
00670
00671
00672
00673 helper::fixed_array<Coord,4> deforme;
00674 for(int i=0;i<4;++i)
00675 deforme[i] = R_0_2*p[index[i]];
00676
00677 deforme[1][0] -= deforme[0][0];
00678 deforme[2][0] -= deforme[0][0];
00679 deforme[2][1] -= deforme[0][1];
00680 deforme[3] -= deforme[0];
00681
00682
00683 Displacement D;
00684 D[0] = 0;
00685 D[1] = 0;
00686 D[2] = 0;
00687 D[3] = _rotatedInitialElements[elementIndex][1][0] - deforme[1][0];
00688 D[4] = 0;
00689 D[5] = 0;
00690 D[6] = _rotatedInitialElements[elementIndex][2][0] - deforme[2][0];
00691 D[7] = _rotatedInitialElements[elementIndex][2][1] - deforme[2][1];
00692 D[8] = 0;
00693 D[9] = _rotatedInitialElements[elementIndex][3][0] - deforme[3][0];
00694 D[10] = _rotatedInitialElements[elementIndex][3][1] - deforme[3][1];
00695 D[11] =_rotatedInitialElements[elementIndex][3][2] - deforme[3][2];
00696
00697
00698
00699 Displacement F;
00700 if(_updateStiffnessMatrix)
00701 {
00702
00703 _strainDisplacements[elementIndex][0][0] = ( - deforme[2][1]*deforme[3][2] );
00704 _strainDisplacements[elementIndex][1][1] = ( deforme[2][0]*deforme[3][2] - deforme[1][0]*deforme[3][2] );
00705 _strainDisplacements[elementIndex][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] );
00706
00707 _strainDisplacements[elementIndex][3][0] = ( deforme[2][1]*deforme[3][2] );
00708 _strainDisplacements[elementIndex][4][1] = ( - deforme[2][0]*deforme[3][2] );
00709 _strainDisplacements[elementIndex][5][2] = ( - deforme[2][1]*deforme[3][0] + deforme[2][0]*deforme[3][1] );
00710
00711 _strainDisplacements[elementIndex][7][1] = ( deforme[1][0]*deforme[3][2] );
00712 _strainDisplacements[elementIndex][8][2] = ( - deforme[1][0]*deforme[3][1] );
00713
00714 _strainDisplacements[elementIndex][11][2] = ( deforme[1][0]*deforme[2][1] );
00715 }
00716
00717 if(!_assembling)
00718 {
00719
00720 computeForce( F, D, _materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex]);
00721 for(int i=0;i<12;i+=3)
00722 f[index[i/3]] += _rotations[elementIndex] * Deriv( F[i], F[i+1], F[i+2] );
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 }
00734 else
00735 {
00736 _strainDisplacements[elementIndex][6][0] = 0;
00737 _strainDisplacements[elementIndex][9][0] = 0;
00738 _strainDisplacements[elementIndex][10][1] = 0;
00739
00740 StiffnessMatrix RJKJt, RJKJtRt;
00741 computeStiffnessMatrix(RJKJt,RJKJtRt,_materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex],_rotations[elementIndex]);
00742
00743
00744
00745 if(elementIndex==0)
00746 {
00747 for(unsigned int i=0;i<_stiffnesses.size();++i)
00748 {
00749 _stiffnesses[i].resize(0);
00750 }
00751 }
00752
00753 for(int i=0;i<12;++i)
00754 {
00755 int row = index[i/3]*3+i%3;
00756
00757 for(int j=0;j<12;++j)
00758 {
00759 int col = index[j/3]*3+j%3;
00760
00761
00762 typename CompressedValue::iterator result = _stiffnesses[row].end();
00763 for(typename CompressedValue::iterator it=_stiffnesses[row].begin();it!=_stiffnesses[row].end()&&result==_stiffnesses[row].end();++it)
00764 {
00765 if( (*it).first == col )
00766 {
00767 result = it;
00768 }
00769 }
00770
00771 if( result==_stiffnesses[row].end() )
00772 {
00773 _stiffnesses[row].push_back( Col_Value(col,RJKJtRt[i][j] ) );
00774 }
00775 else
00776 {
00777 (*result).second += RJKJtRt[i][j];
00778 }
00779 }
00780 }
00781
00782 F = RJKJt*D;
00783
00784 for(int i=0;i<12;i+=3)
00785 f[index[i/3]] += Deriv( F[i], F[i+1], F[i+2] );
00786 }
00787 }
00788
00789 template<class DataTypes>
00790 inline void TetrahedronFEMForceField<DataTypes>::applyStiffnessLarge( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d, double fact )
00791 {
00792 Transformation R_0_2;
00793 R_0_2.transpose(_rotations[i]);
00794
00795 Displacement X;
00796 Coord x_2;
00797
00798 x_2 = R_0_2*x[a];
00799 X[0] = x_2[0];
00800 X[1] = x_2[1];
00801 X[2] = x_2[2];
00802
00803 x_2 = R_0_2*x[b];
00804 X[3] = x_2[0];
00805 X[4] = x_2[1];
00806 X[5] = x_2[2];
00807
00808 x_2 = R_0_2*x[c];
00809 X[6] = x_2[0];
00810 X[7] = x_2[1];
00811 X[8] = x_2[2];
00812
00813 x_2 = R_0_2*x[d];
00814 X[9] = x_2[0];
00815 X[10] = x_2[1];
00816 X[11] = x_2[2];
00817
00818 Displacement F;
00819
00820
00821
00822 computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i], fact );
00823
00824
00825
00826 f[a] += _rotations[i] * Deriv( -F[0], -F[1], -F[2] );
00827 f[b] += _rotations[i] * Deriv( -F[3], -F[4], -F[5] );
00828 f[c] += _rotations[i] * Deriv( -F[6], -F[7], -F[8] );
00829 f[d] += _rotations[i] * Deriv( -F[9], -F[10], -F[11] );
00830 }
00831
00835
00836 template<class DataTypes>
00837 void TetrahedronFEMForceField<DataTypes>::initPolar(int i, Index& a, Index&b, Index&c, Index&d)
00838 {
00839 Transformation A;
00840 A[0] = _initialPoints[b]-_initialPoints[a];
00841 A[1] = _initialPoints[c]-_initialPoints[a];
00842 A[2] = _initialPoints[d]-_initialPoints[a];
00843 _initialTransformation[i] = A;
00844
00845 Transformation R_0_1;
00846 MatNoInit<3,3,Real> S;
00847 polar_decomp(A, R_0_1, S);
00848
00849 _initialRotations[i].transpose( R_0_1);
00850
00851
00852 _rotationIdx[a] = i;
00853 _rotationIdx[b] = i;
00854 _rotationIdx[c] = i;
00855 _rotationIdx[d] = i;
00856
00857 _rotatedInitialElements[i][0] = R_0_1*_initialPoints[a];
00858 _rotatedInitialElements[i][1] = R_0_1*_initialPoints[b];
00859 _rotatedInitialElements[i][2] = R_0_1*_initialPoints[c];
00860 _rotatedInitialElements[i][3] = R_0_1*_initialPoints[d];
00861
00862 computeStrainDisplacement( _strainDisplacements[i],_rotatedInitialElements[i][0], _rotatedInitialElements[i][1],_rotatedInitialElements[i][2],_rotatedInitialElements[i][3] );
00863 }
00864
00865 template<class DataTypes>
00866 inline void TetrahedronFEMForceField<DataTypes>::accumulateForcePolar( Vector& f, const Vector & p, typename VecElement::const_iterator elementIt, Index elementIndex )
00867 {
00868 Element index = *elementIt;
00869
00870 Transformation A;
00871 A[0] = p[index[1]]-p[index[0]];
00872 A[1] = p[index[2]]-p[index[0]];
00873 A[2] = p[index[3]]-p[index[0]];
00874
00875 Transformation R_0_2;
00876 MatNoInit<3,3,Real> S;
00877 polar_decomp(A, R_0_2, S);
00878
00879 _rotations[elementIndex].transpose( R_0_2 );
00880
00881
00882 helper::fixed_array<Coord, 4> deforme;
00883 for(int i=0;i<4;++i)
00884 deforme[i] = R_0_2 * p[index[i]];
00885
00886
00887 Displacement D;
00888 D[0] = _rotatedInitialElements[elementIndex][0][0] - deforme[0][0];
00889 D[1] = _rotatedInitialElements[elementIndex][0][1] - deforme[0][1];
00890 D[2] = _rotatedInitialElements[elementIndex][0][2] - deforme[0][2];
00891 D[3] = _rotatedInitialElements[elementIndex][1][0] - deforme[1][0];
00892 D[4] = _rotatedInitialElements[elementIndex][1][1] - deforme[1][1];
00893 D[5] = _rotatedInitialElements[elementIndex][1][2] - deforme[1][2];
00894 D[6] = _rotatedInitialElements[elementIndex][2][0] - deforme[2][0];
00895 D[7] = _rotatedInitialElements[elementIndex][2][1] - deforme[2][1];
00896 D[8] = _rotatedInitialElements[elementIndex][2][2] - deforme[2][2];
00897 D[9] = _rotatedInitialElements[elementIndex][3][0] - deforme[3][0];
00898 D[10] = _rotatedInitialElements[elementIndex][3][1] - deforme[3][1];
00899 D[11] = _rotatedInitialElements[elementIndex][3][2] - deforme[3][2];
00900
00901
00902 Displacement F;
00903 if(_updateStiffnessMatrix)
00904 {
00905
00906 computeStrainDisplacement( _strainDisplacements[elementIndex], deforme[0],deforme[1],deforme[2],deforme[3] );
00907 }
00908
00909 if(!_assembling)
00910 {
00911 computeForce( F, D, _materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex] );
00912 for(int i=0;i<12;i+=3)
00913 f[index[i/3]] += _rotations[elementIndex] * Deriv( F[i], F[i+1], F[i+2] );
00914 }
00915 else
00916 {
00917 std::cerr << "TODO(TetrahedronFEMForceField): support for assembling system matrix when using polar method.\n";
00918 }
00919 }
00920
00921 template<class DataTypes>
00922 inline void TetrahedronFEMForceField<DataTypes>::applyStiffnessPolar( Vector& f, const Vector& x, int i, Index a, Index b, Index c, Index d, double fact )
00923 {
00924 Transformation R_0_2;
00925 R_0_2.transpose( _rotations[i] );
00926
00927 Displacement X;
00928
00929
00930
00931 X[0] = R_0_2[0][0] * x[a][0] + R_0_2[0][1] * x[a][1] + R_0_2[0][2] * x[a][2];
00932 X[1] = R_0_2[1][0] * x[a][0] + R_0_2[1][1] * x[a][1] + R_0_2[1][2] * x[a][2];
00933 X[2] = R_0_2[2][0] * x[a][0] + R_0_2[2][1] * x[a][1] + R_0_2[2][2] * x[a][2];
00934
00935
00936 X[3] = R_0_2[0][0] * x[b][0] + R_0_2[0][1] * x[b][1] + R_0_2[0][2] * x[b][2];
00937 X[4] = R_0_2[1][0] * x[b][0] + R_0_2[1][1] * x[b][1] + R_0_2[1][2] * x[b][2];
00938 X[5] = R_0_2[2][0] * x[b][0] + R_0_2[2][1] * x[b][1] + R_0_2[2][2] * x[b][2];
00939
00940
00941 X[6] = R_0_2[0][0] * x[c][0] + R_0_2[0][1] * x[c][1] + R_0_2[0][2] * x[c][2];
00942 X[7] = R_0_2[1][0] * x[c][0] + R_0_2[1][1] * x[c][1] + R_0_2[1][2] * x[c][2];
00943 X[8] = R_0_2[2][0] * x[c][0] + R_0_2[2][1] * x[c][1] + R_0_2[2][2] * x[c][2];
00944
00945
00946 X[9] = R_0_2[0][0] * x[d][0] + R_0_2[0][1] * x[d][1] + R_0_2[0][2] * x[d][2];
00947 X[10] = R_0_2[1][0] * x[d][0] + R_0_2[1][1] * x[d][1] + R_0_2[1][2] * x[d][2];
00948 X[11] = R_0_2[2][0] * x[d][0] + R_0_2[2][1] * x[d][1] + R_0_2[2][2] * x[d][2];
00949
00950 Displacement F;
00951
00952
00953
00954 computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i], fact );
00955
00956
00957
00958 f[a][0] -= _rotations[i][0][0] * F[0] + _rotations[i][0][1] * F[1] + _rotations[i][0][2] * F[2];
00959 f[a][1] -= _rotations[i][1][0] * F[0] + _rotations[i][1][1] * F[1] + _rotations[i][1][2] * F[2];
00960 f[a][2] -= _rotations[i][2][0] * F[0] + _rotations[i][2][1] * F[1] + _rotations[i][2][2] * F[2];
00961
00962 f[b][0] -= _rotations[i][0][0] * F[3] + _rotations[i][0][1] * F[4] + _rotations[i][0][2] * F[5];
00963 f[b][1] -= _rotations[i][1][0] * F[3] + _rotations[i][1][1] * F[4] + _rotations[i][1][2] * F[5];
00964 f[b][2] -= _rotations[i][2][0] * F[3] + _rotations[i][2][1] * F[4] + _rotations[i][2][2] * F[5];
00965
00966 f[c][0] -= _rotations[i][0][0] * F[6] + _rotations[i][0][1] * F[7] + _rotations[i][0][2] * F[8];
00967 f[c][1] -= _rotations[i][1][0] * F[6] + _rotations[i][1][1] * F[7] + _rotations[i][1][2] * F[8];
00968 f[c][2] -= _rotations[i][2][0] * F[6] + _rotations[i][2][1] * F[7] + _rotations[i][2][2] * F[8];
00969
00970 f[d][0] -= _rotations[i][0][0] * F[9] + _rotations[i][0][1] * F[10] + _rotations[i][0][2] * F[11];
00971 f[d][1] -= _rotations[i][1][0] * F[9] + _rotations[i][1][1] * F[10] + _rotations[i][1][2] * F[11];
00972 f[d][2] -= _rotations[i][2][0] * F[9] + _rotations[i][2][1] * F[10] + _rotations[i][2][2] * F[11];
00973
00974 }
00975
00979
00980 template<class DataTypes>
00981 void TetrahedronFEMForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00982 {
00983 this->core::componentmodel::behavior::ForceField<DataTypes>::parse(arg);
00984 this->setComputeGlobalMatrix(std::string(arg->getAttribute("computeGlobalMatrix","false"))=="true");
00985 }
00986
00987 template <class DataTypes>
00988 void TetrahedronFEMForceField<DataTypes>::init()
00989 {
00990 f_initialPoints.beginEdit();
00991 f_poissonRatio.beginEdit();
00992 f_youngModulus.beginEdit();
00993 f_localStiffnessFactor.beginEdit();
00994 f_updateStiffnessMatrix.beginEdit();
00995 f_assembling.beginEdit();
00996
00997 this->core::componentmodel::behavior::ForceField<DataTypes>::init();
00998 _mesh = this->getContext()->getMeshTopology();
00999 #ifdef SOFA_NEW_HEXA
01000 if (_mesh==NULL || (_mesh->getTetras().empty() && _mesh->getNbHexas()<=0))
01001 #else
01002 if (_mesh==NULL || (_mesh->getTetras().empty() && _mesh->getNbCubes()<=0))
01003 #endif
01004 {
01005 std::cerr << "ERROR(TetrahedronFEMForceField): object must have a tetrahedric BaseMeshTopology.\n";
01006 return;
01007 }
01008 if (!_mesh->getTetras().empty())
01009 {
01010 _indexedElements = & (_mesh->getTetras());
01011 }
01012 else
01013 {
01014 core::componentmodel::topology::BaseMeshTopology::SeqTetras* tetras = new core::componentmodel::topology::BaseMeshTopology::SeqTetras;
01015 #ifdef SOFA_NEW_HEXA
01016 int nbcubes = _mesh->getNbHexas();
01017 #else
01018 int nbcubes = _mesh->getNbCubes();
01019 #endif
01020
01021 int nx = 2;
01022 int ny = 1;
01023 int nz = 1;
01024 {
01025 topology::GridTopology* grid = dynamic_cast<topology::GridTopology*>(_mesh);
01026 if (grid != NULL)
01027 {
01028 nx = grid->getNx()-1;
01029 ny = grid->getNy()-1;
01030 nz = grid->getNz()-1;
01031 }
01032 }
01033
01034
01035 tetras->reserve(nbcubes*6);
01036 for (int i=0;i<nbcubes;i++)
01037 {
01038
01039 #ifdef SOFA_NEW_HEXA
01040 core::componentmodel::topology::BaseMeshTopology::Hexa c = _mesh->getHexa(i);
01041 #define swap(a,b) { int t = a; a = b; b = t; }
01042 if (!((i%nx)&1))
01043 {
01044 swap(c[0],c[1]);
01045 swap(c[3],c[2]);
01046 swap(c[4],c[5]);
01047 swap(c[7],c[6]);
01048 }
01049 if (((i/nx)%ny)&1)
01050 {
01051 swap(c[0],c[3]);
01052 swap(c[1],c[2]);
01053 swap(c[4],c[7]);
01054 swap(c[5],c[6]);
01055 }
01056 if ((i/(nx*ny))&1)
01057 {
01058 swap(c[0],c[4]);
01059 swap(c[1],c[5]);
01060 swap(c[2],c[6]);
01061 swap(c[3],c[7]);
01062 }
01063 #undef swap
01064 typedef core::componentmodel::topology::BaseMeshTopology::Tetra Tetra;
01065 tetras->push_back(Tetra(c[0],c[5],c[1],c[6]));
01066 tetras->push_back(Tetra(c[0],c[1],c[3],c[6]));
01067 tetras->push_back(Tetra(c[1],c[3],c[6],c[2]));
01068 tetras->push_back(Tetra(c[6],c[3],c[0],c[7]));
01069 tetras->push_back(Tetra(c[6],c[7],c[0],c[5]));
01070 tetras->push_back(Tetra(c[7],c[5],c[4],c[0]));
01071 #else
01072 core::componentmodel::topology::BaseMeshTopology::Cube c = _mesh->getCube(i);
01073 int sym = 0;
01074 if (!((i%nx)&1)) sym+=1;
01075 if (((i/nx)%ny)&1) sym+=2;
01076 if ((i/(nx*ny))&1) sym+=4;
01077 typedef core::componentmodel::topology::BaseMeshTopology::Tetra Tetra;
01078 tetras->push_back(Tetra(c[0^sym],c[5^sym],c[1^sym],c[7^sym]));
01079 tetras->push_back(Tetra(c[0^sym],c[1^sym],c[2^sym],c[7^sym]));
01080 tetras->push_back(Tetra(c[1^sym],c[2^sym],c[7^sym],c[3^sym]));
01081 tetras->push_back(Tetra(c[7^sym],c[2^sym],c[0^sym],c[6^sym]));
01082 tetras->push_back(Tetra(c[7^sym],c[6^sym],c[0^sym],c[5^sym]));
01083 tetras->push_back(Tetra(c[6^sym],c[5^sym],c[4^sym],c[0^sym]));
01084 #endif
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 _indexedElements = tetras;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 reinit();
01125
01126
01127 }
01128
01129
01130 template <class DataTypes>
01131 void TetrahedronFEMForceField<DataTypes>::reinit()
01132 {
01133 if (!this->mstate) return;
01134 setMethod(f_method.getValue() );
01135 VecCoord& p = *this->mstate->getX0();
01136 (*f_initialPoints.beginEdit()) = p;
01137 _strainDisplacements.resize( _indexedElements->size() );
01138 _materialsStiffnesses.resize(_indexedElements->size() );
01139 if(_assembling)
01140 {
01141 _stiffnesses.resize( _initialPoints.size()*3 );
01142 }
01143
01144 unsigned int i;
01145 typename VecElement::const_iterator it;
01146 switch(method)
01147 {
01148 case SMALL :
01149 {
01150 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01151 {
01152 Index a = (*it)[0];
01153 Index b = (*it)[1];
01154 Index c = (*it)[2];
01155 Index d = (*it)[3];
01156 this->computeMaterialStiffness(i,a,b,c,d);
01157 this->initSmall(i,a,b,c,d);
01158 }
01159 break;
01160 }
01161 case LARGE :
01162 {
01163 _rotations.resize( _indexedElements->size() );
01164 _initialRotations.resize( _indexedElements->size() );
01165 _rotationIdx.resize(_indexedElements->size() *4);
01166 _rotatedInitialElements.resize(_indexedElements->size());
01167 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01168 {
01169 Index a = (*it)[0];
01170 Index b = (*it)[1];
01171 Index c = (*it)[2];
01172 Index d = (*it)[3];
01173 computeMaterialStiffness(i,a,b,c,d);
01174 initLarge(i,a,b,c,d);
01175 }
01176 break;
01177 }
01178 case POLAR :
01179 {
01180 _rotations.resize( _indexedElements->size() );
01181 _initialRotations.resize( _indexedElements->size() );
01182 _rotationIdx.resize(_indexedElements->size() *4);
01183 _rotatedInitialElements.resize(_indexedElements->size());
01184 _initialTransformation.resize(_indexedElements->size());
01185 unsigned int i=0;
01186 typename VecElement::const_iterator it;
01187 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01188 {
01189 Index a = (*it)[0];
01190 Index b = (*it)[1];
01191 Index c = (*it)[2];
01192 Index d = (*it)[3];
01193 computeMaterialStiffness(i,a,b,c,d);
01194 initPolar(i,a,b,c,d);
01195 }
01196 break;
01197 }
01198 }
01199 }
01200
01201
01202 template<class DataTypes>
01203 void TetrahedronFEMForceField<DataTypes>::addForce (VecDeriv& f, const VecCoord& p, const VecDeriv& )
01204 {
01205 f.resize(p.size());
01206
01207 if (needUpdateTopology)
01208 {
01209 reinit();
01210 needUpdateTopology = false;
01211 }
01212
01213 unsigned int i;
01214 typename VecElement::const_iterator it;
01215 switch(method)
01216 {
01217 case SMALL :
01218 {
01219 for(it=_indexedElements->begin(), i = 0 ; it!=_indexedElements->end();++it,++i)
01220 {
01221 accumulateForceSmall( f, p, it, i );
01222 }
01223 break;
01224 }
01225 case LARGE :
01226 {
01227 for(it=_indexedElements->begin(), i = 0 ; it!=_indexedElements->end();++it,++i)
01228 {
01229
01230 accumulateForceLarge( f, p, it, i );
01231 }
01232 break;
01233 }
01234 case POLAR :
01235 {
01236 for(it=_indexedElements->begin(), i = 0 ; it!=_indexedElements->end();++it,++i)
01237 {
01238 accumulateForcePolar( f, p, it, i );
01239 }
01240 break;
01241 }
01242 }
01243 }
01244
01245 template<class DataTypes>
01246 void TetrahedronFEMForceField<DataTypes>::addDForce (VecDeriv& v, const VecDeriv& x, double kFactor, double )
01247 {
01248 v.resize(x.size());
01249 unsigned int i;
01250 typename VecElement::const_iterator it;
01251
01252 switch(method)
01253 {
01254 case SMALL :
01255 {
01256 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01257 {
01258 Index a = (*it)[0];
01259 Index b = (*it)[1];
01260 Index c = (*it)[2];
01261 Index d = (*it)[3];
01262
01263 applyStiffnessSmall( v,x, i, a,b,c,d, kFactor );
01264 }
01265 break;
01266 }
01267 case LARGE :
01268 {
01269 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01270 {
01271 Index a = (*it)[0];
01272 Index b = (*it)[1];
01273 Index c = (*it)[2];
01274 Index d = (*it)[3];
01275
01276 applyStiffnessLarge( v,x, i, a,b,c,d, kFactor );
01277 }
01278
01279 break;
01280 }
01281 case POLAR :
01282 {
01283 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01284 {
01285 Index a = (*it)[0];
01286 Index b = (*it)[1];
01287 Index c = (*it)[2];
01288 Index d = (*it)[3];
01289
01290 applyStiffnessPolar( v,x, i, a,b,c,d, kFactor );
01291 }
01292 break;
01293 }
01294 }
01295 }
01296
01297 template <class DataTypes>
01298 double TetrahedronFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
01299 {
01300 cerr<<"TetrahedronFEMForceField::getPotentialEnergy-not-implemented !!!"<<endl;
01301 return 0;
01302 }
01303
01307
01308 template<class DataTypes>
01309 void TetrahedronFEMForceField<DataTypes>::draw()
01310 {
01311 if (!getContext()->getShowForceFields()) return;
01312 if (!this->mstate) return;
01313
01314 const VecCoord& x = *this->mstate->getX();
01315
01316 if (getContext()->getShowWireFrame())
01317 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01318
01319 glDisable(GL_LIGHTING);
01320
01321 glBegin(GL_TRIANGLES);
01322 typename VecElement::const_iterator it;
01323 int i;
01324 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01325 {
01326 Index a = (*it)[0];
01327 Index b = (*it)[1];
01328 Index c = (*it)[2];
01329 Index d = (*it)[3];
01330 Coord center = (x[a]+x[b]+x[c]+x[d])*0.125;
01331 Coord pa = (x[a]+center)*(Real)0.666667;
01332 Coord pb = (x[b]+center)*(Real)0.666667;
01333 Coord pc = (x[c]+center)*(Real)0.666667;
01334 Coord pd = (x[d]+center)*(Real)0.666667;
01335
01336 glColor4f(0,0,1,1);
01337 helper::gl::glVertexT(pa);
01338 helper::gl::glVertexT(pb);
01339 helper::gl::glVertexT(pc);
01340
01341 glColor4f(0,0.5,1,1);
01342 helper::gl::glVertexT(pb);
01343 helper::gl::glVertexT(pc);
01344 helper::gl::glVertexT(pd);
01345
01346 glColor4f(0,1,1,1);
01347 helper::gl::glVertexT(pc);
01348 helper::gl::glVertexT(pd);
01349 helper::gl::glVertexT(pa);
01350
01351 glColor4f(0.5,1,1,1);
01352 helper::gl::glVertexT(pd);
01353 helper::gl::glVertexT(pa);
01354 helper::gl::glVertexT(pb);
01355 }
01356 glEnd();
01357
01358 if (getContext()->getShowWireFrame())
01359 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01361 if (getContext()->getShowNormals())
01362 {
01363 glBegin(GL_LINES);
01364 glLineWidth(5);
01365
01366 for(unsigned ii = 0; ii< x.size() ; ii++)
01367 {
01368 Coord a = x[ii];
01369 Transformation R;
01370 getRotation(R, ii);
01371
01372 Deriv v;
01373
01374 glColor4f(1,0,0,1);
01375 v.x() =1.0; v.y()=0.0; v.z()=0.0;
01376 Coord b = a + R*v;
01377 helper::gl::glVertexT(a);
01378 helper::gl::glVertexT(b);
01379
01380 glColor4f(0,1,0,1);
01381 v.x() =0.0; v.y()=1.0; v.z()=0.0;
01382 b = a + R*v;
01383 helper::gl::glVertexT(a);
01384 helper::gl::glVertexT(b);
01385
01386 glColor4f(0,0,1,1);
01387 v.x() =0.0; v.y()=0.0; v.z()=1.0;
01388 b = a + R*v;
01389 helper::gl::glVertexT(a);
01390 helper::gl::glVertexT(b);
01391 }
01392 glEnd();
01393 }
01394 }
01395
01396
01397 template<class DataTypes>
01398 void TetrahedronFEMForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix *mat, SReal k, unsigned int &offset)
01399 {
01400
01401 int i,j,n1, n2, row, column, ROW, COLUMN , IT;
01402
01403 Transformation Rot;
01404 StiffnessMatrix JKJt,tmp;
01405
01406 typename VecElement::const_iterator it;
01407
01408 Index noeud1, noeud2;
01409
01410 Rot[0][0]=Rot[1][1]=Rot[2][2]=1;
01411 Rot[0][1]=Rot[0][2]=0;
01412 Rot[1][0]=Rot[1][2]=0;
01413 Rot[2][0]=Rot[2][1]=0;
01414
01415 for(it = _indexedElements->begin(), IT=0 ; it != _indexedElements->end() ; ++it,++IT)
01416 {
01417 if (method == SMALL)
01418 computeStiffnessMatrix(JKJt,tmp,_materialsStiffnesses[IT], _strainDisplacements[IT],Rot);
01419 else
01420 computeStiffnessMatrix(JKJt,tmp,_materialsStiffnesses[IT], _strainDisplacements[IT],_rotations[IT]);
01421
01422
01423 for (n1=0; n1<4; n1++)
01424 {
01425 noeud1 = (*it)[n1];
01426
01427 for(i=0; i<3; i++)
01428 {
01429 ROW = offset+3*noeud1+i;
01430 row = 3*n1+i;
01431
01432 for (n2=0; n2<4; n2++)
01433 {
01434 noeud2 = (*it)[n2];
01435
01436 for (j=0; j<3; j++)
01437 {
01438 COLUMN = offset+3*noeud2+j;
01439 column = 3*n2+j;
01440 mat->add(ROW, COLUMN, - tmp[row][column]*k);
01441 }
01442 }
01443 }
01444 }
01445 }
01446 }
01447
01448 }
01449
01450 }
01451
01452 }
01453
01454 #endif