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_HEXAHEDRONFEMFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_HEXAHEDRONFEMFORCEFIELD_INL
00027
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include <sofa/component/forcefield/HexahedronFEMForceField.h>
00030 #include <sofa/helper/PolarDecompose.h>
00031 #include <sofa/helper/gl/template.h>
00032 #include <assert.h>
00033 #include <iostream>
00034 #include <set>
00035
00036 using std::cerr;
00037 using std::endl;
00038 using std::set;
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 namespace sofa
00059 {
00060
00061 namespace component
00062 {
00063
00064 namespace forcefield
00065 {
00066
00067 using namespace sofa::defaulttype;
00068
00069 #ifndef SOFA_NEW_HEXA
00070 template<class DataTypes> const int HexahedronFEMForceField<DataTypes>::_indices[8] = {0,1,3,2,4,5,7,6};
00071
00072 #endif
00073
00074 template<class DataTypes>
00075 void HexahedronFEMForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00076 {
00077 this->core::componentmodel::behavior::ForceField<DataTypes>::parse(arg);
00078
00079 }
00080
00081 template <class DataTypes>
00082 void HexahedronFEMForceField<DataTypes>::init()
00083 {
00084 if(_alreadyInit)return;
00085 else _alreadyInit=true;
00086
00087 this->core::componentmodel::behavior::ForceField<DataTypes>::init();
00088 if( this->getContext()->getMeshTopology()==NULL )
00089 {
00090 std::cerr << "ERROR(HexahedronFEMForceField): object must have a Topology.\n";
00091 return;
00092 }
00093
00094 _mesh = dynamic_cast<sofa::core::componentmodel::topology::BaseMeshTopology*>(this->getContext()->getMeshTopology());
00095 if ( _mesh==NULL)
00096 {
00097 std::cerr << "ERROR(HexahedronFEMForceField): object must have a MeshTopology.\n";
00098 return;
00099 }
00100 #ifdef SOFA_NEW_HEXA
00101 else if( _mesh->getNbHexas()<=0 )
00102 #else
00103 else if( _mesh->getNbCubes()<=0 )
00104 #endif
00105 {
00106 std::cerr << "ERROR(HexahedronFEMForceField): object must have a hexahedric MeshTopology.\n";
00107 std::cerr << _mesh->getName()<<std::endl;
00108 std::cerr << _mesh->getTypeName()<<std::endl;
00109 cerr<<_mesh->getNbPoints()<<endl;
00110 return;
00111 }
00112
00113
00114
00115 #ifdef SOFA_NEW_HEXA
00116 _indexedElements = & (_mesh->getHexas());
00117 #else
00118 _indexedElements = & (_mesh->getCubes());
00119 #endif
00120
00121 _sparseGrid = dynamic_cast<topology::SparseGridTopology*>(_mesh);
00122
00123
00124
00125 if (_initialPoints.getValue().size() == 0)
00126 {
00127 VecCoord& p = *this->mstate->getX();
00128 _initialPoints.setValue(p);
00129 }
00130
00131 _materialsStiffnesses.resize(_indexedElements->size() );
00132 _rotations.resize( _indexedElements->size() );
00133 _rotatedInitialElements.resize(_indexedElements->size());
00134
00135
00136
00137
00138
00139
00140
00141
00142 reinit();
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 }
00161
00162
00163 template <class DataTypes>
00164 void HexahedronFEMForceField<DataTypes>::reinit()
00165 {
00166 if (f_method.getValue() == "large")
00167 this->setMethod(LARGE);
00168 else if (f_method.getValue() == "polar")
00169 this->setMethod(POLAR);
00170
00171 switch(method)
00172 {
00173 case LARGE :
00174 {
00175 unsigned int i=0;
00176 typename VecElement::const_iterator it;
00177 for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00178 {
00179 computeMaterialStiffness(i);
00180 initLarge(i,*it);
00181 }
00182 break;
00183 }
00184 case POLAR :
00185 {
00186 unsigned int i=0;
00187 typename VecElement::const_iterator it;
00188 for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00189 {
00190 computeMaterialStiffness(i);
00191 initPolar(i,*it);
00192 }
00193 break;
00194 }
00195 }
00196 }
00197
00198
00199
00203
00204
00205
00206
00207 template<class DataTypes>
00208 void HexahedronFEMForceField<DataTypes>::addForce (VecDeriv& f, const VecCoord& p, const VecDeriv& )
00209 {
00210 f.resize(p.size());
00211
00212 unsigned int i=0;
00213 typename VecElement::const_iterator it;
00214
00215
00216
00217 switch(method)
00218 {
00219 case LARGE :
00220 {
00221 for(it=_indexedElements->begin();it!=_indexedElements->end();++it,++i)
00222 {
00223 accumulateForceLarge( f, p, i, *it );
00224 }
00225 break;
00226 }
00227 case POLAR :
00228 {
00229 for(it=_indexedElements->begin();it!=_indexedElements->end();++it,++i)
00230 {
00231 accumulateForcePolar( f, p, i, *it );
00232 }
00233 break;
00234 }
00235 }
00236
00237
00238 }
00239
00240 template<class DataTypes>
00241 void HexahedronFEMForceField<DataTypes>::addDForce (VecDeriv& v, const VecDeriv& x)
00242 {
00243 if( v.size()!=x.size() ) v.resize(x.size());
00244
00245
00246 unsigned int i=0;
00247 typename VecElement::const_iterator it;
00248
00249 for(it = _indexedElements->begin() ; it != _indexedElements->end() ; ++it, ++i)
00250 {
00251
00252 Transformation R_0_2;
00253 R_0_2.transpose(_rotations[i]);
00254
00255 Displacement X;
00256
00257 for(int w=0;w<8;++w)
00258 {
00259 Coord x_2;
00260 #ifndef SOFA_NEW_HEXA
00261 x_2 = R_0_2 * x[(*it)[_indices[w]]];
00262 #else
00263 x_2 = R_0_2 * x[(*it)[w]];
00264 #endif
00265 X[w*3] = x_2[0];
00266 X[w*3+1] = x_2[1];
00267 X[w*3+2] = x_2[2];
00268 }
00269
00270 Displacement F;
00271 computeForce( F, X, _elementStiffnesses.getValue()[i] );
00272
00273 for(int w=0;w<8;++w)
00274 #ifndef SOFA_NEW_HEXA
00275 v[(*it)[_indices[w]]] -= _rotations[i] * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00276 #else
00277 v[(*it)[w]] -= _rotations[i] * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00278 #endif
00279 }
00280
00281 }
00282
00283 template <class DataTypes>
00284 double HexahedronFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00285 {
00286 std::cerr<<"HexahedronFEMForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00287 return 0;
00288 }
00289
00290
00291
00292
00293
00297
00298
00299
00300
00301
00302 #define GENERIC_STIFFNESS_MATRIX
00303
00304 #define MAT_STIFFNESS_USE_W
00305
00306
00307 #define DN_USE_J
00308
00309
00310 template<class DataTypes>
00311 void HexahedronFEMForceField<DataTypes>::computeElementStiffness( ElementStiffness &K, const MaterialStiffness &M, const helper::fixed_array<Coord,8> &nodes, const int elementIndice, double stiffnessFactor)
00312 {
00313
00314
00315 const bool verbose = this->f_printLog.getValue() && (elementIndice==0);
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 K.fill( 0.0 );
00332 Mat33 J;
00333 Mat33 J_1;
00334 Mat33 J_1t;
00335 Real detJ = (Real)1.0;
00336
00337 Coord lx = nodes[1]-nodes[0];
00338 Coord ly = nodes[3]-nodes[0];
00339 Coord lz = nodes[4]-nodes[0];
00340 bool isParallel = false;
00341 if ((nodes[3]+lx-nodes[2]).norm() < lx.norm()*0.001 && (nodes[0]+lz-nodes[4]).norm() < lz.norm()*0.001 && (nodes[1]+lz-nodes[5]).norm() < lz.norm()*0.001 && (nodes[2]+lz-nodes[6]).norm() < lz.norm()*0.001 && (nodes[3]+lz-nodes[7]).norm() < lz.norm()*0.001)
00342 {
00343 isParallel = true;
00344 for (int c=0;c<3;++c)
00345 {
00346 J[c][0] = lx[c]/2;
00347 J[c][1] = ly[c]/2;
00348 J[c][2] = lz[c]/2;
00349 }
00350 detJ = defaulttype::determinant(J);
00351 J_1.invert(J);
00352 J_1t.transpose(J_1);
00353 if (verbose)
00354 {
00355 std::cout << "J = "<<J<<std::endl;
00356 std::cout << "invJ = "<<J_1<<std::endl;
00357 std::cout << "detJ = "<<detJ<<std::endl;
00358 }
00359 }
00360
00361
00362
00363 const Real U = M[0][0];
00364 const Real V = M[0][1];
00365 #ifdef MAT_STIFFNESS_USE_W
00366 const Real W = M[3][3];
00367 #else
00368 const Real W = M[2][2];
00369 #endif
00370 const double inv_sqrt3 = 1.0/sqrt(3.0);
00371 for (int gx1=-1;gx1<=1;gx1+=2)
00372 for (int gx2=-1;gx2<=1;gx2+=2)
00373 for (int gx3=-1;gx3<=1;gx3+=2)
00374 {
00375 double x1 = gx1*inv_sqrt3;
00376 double x2 = gx2*inv_sqrt3;
00377 double x3 = gx3*inv_sqrt3;
00378
00379
00380
00381 if (!isParallel)
00382 {
00383 for (int c=0;c<3;++c)
00384 {
00385 J[c][0] = (Real)( (nodes[1][c]-nodes[0][c])*(1-x2)*(1-x3)/8+(nodes[2][c]-nodes[3][c])*(1+x2)*(1-x3)/8+(nodes[5][c]-nodes[4][c])*(1-x2)*(1+x3)/8+(nodes[6][c]-nodes[7][c])*(1+x2)*(1+x3)/8);
00386 J[c][1] =(Real)( (nodes[3][c]-nodes[0][c])*(1-x1)*(1-x3)/8+(nodes[2][c]-nodes[1][c])*(1+x1)*(1-x3)/8+(nodes[7][c]-nodes[4][c])*(1-x1)*(1+x3)/8+(nodes[6][c]-nodes[5][c])*(1+x1)*(1+x3)/8);
00387 J[c][2] =(Real)( (nodes[4][c]-nodes[0][c])*(1-x1)*(1-x2)/8+(nodes[5][c]-nodes[1][c])*(1+x1)*(1-x2)/8+(nodes[6][c]-nodes[2][c])*(1+x1)*(1+x2)/8+(nodes[7][c]-nodes[3][c])*(1-x1)*(1+x2)/8);
00388 }
00389 detJ = defaulttype::determinant(J);
00390 J_1.invert(J);
00391 J_1t.transpose(J_1);
00392 if (verbose)
00393 {
00394 std::cout << "J = "<<J<<std::endl;
00395 std::cout << "invJ = "<<J_1<<std::endl;
00396 std::cout << "detJ = "<<detJ<<std::endl;
00397 }
00398 }
00399 Real qx[8];
00400 Real qy[8];
00401 Real qz[8];
00402 for(int i=0;i<8;++i)
00403 {
00404
00405
00406 Real dNi_dx1 =(Real)( (_coef[i][0])*(1+_coef[i][1]*x2)*(1+_coef[i][2]*x3)/8.0);
00407 Real dNi_dx2 =(Real)((1+_coef[i][0]*x1)*(_coef[i][1])*(1+_coef[i][2]*x3)/8.0);
00408 Real dNi_dx3 =(Real)((1+_coef[i][0]*x1)*(1+_coef[i][1]*x2)*(_coef[i][2])/8.0);
00409 if (verbose) std::cout << "dN"<<i<<"/dxi = "<<dNi_dx1<<" "<<dNi_dx2<<" "<<dNi_dx3<<"\n";
00410 #ifdef DN_USE_J
00411 qx[i] = dNi_dx1*J_1[0][0] + dNi_dx2*J_1[1][0] + dNi_dx3*J_1[2][0];
00412 qy[i] = dNi_dx1*J_1[0][1] + dNi_dx2*J_1[1][1] + dNi_dx3*J_1[2][1];
00413 qz[i] = dNi_dx1*J_1[0][2] + dNi_dx2*J_1[1][2] + dNi_dx3*J_1[2][2];
00414 if (verbose) std::cout << "q"<<i<<" = "<<qx[i]<<" "<<qy[i]<<" "<<qz[i]<<"\n";
00415 #else
00416 qx[i] = dNi_dx1;
00417 qy[i] = dNi_dx2;
00418 qz[i] = dNi_dx3;
00419 #endif
00420 }
00421 for(int i=0;i<8;++i)
00422 {
00423 Mat<6,3,Real> MBi;
00424
00425
00426
00427
00428
00429
00430 MBi[0][0] = U * qx[i]; MBi[0][1] = V * qy[i]; MBi[0][2] = V * qz[i];
00431 MBi[1][0] = V * qx[i]; MBi[1][1] = U * qy[i]; MBi[1][2] = V * qz[i];
00432 MBi[2][0] = V * qx[i]; MBi[2][1] = V * qy[i]; MBi[2][2] = U * qz[i];
00433 MBi[3][0] = W * qy[i]; MBi[3][1] = W * qx[i]; MBi[3][2] = (Real)0;
00434 MBi[4][0] = (Real)0; MBi[4][1] = W * qz[i]; MBi[4][2] = W * qy[i];
00435 MBi[5][0] = W * qz[i]; MBi[5][1] = (Real)0; MBi[5][2] = W * qx[i];
00436 if (verbose) std::cout << "MB"<<i<<" = "<<MBi<<"\n";
00437 for(int j=i;j<8;++j)
00438 {
00439 Mat33 k;
00440 k[0][0] = qx[j]*MBi[0][0] + qy[j]*MBi[3][0] + qz[j]*MBi[5][0];
00441 k[0][1] = qx[j]*MBi[0][1] + qy[j]*MBi[3][1] ;
00442 k[0][2] = qx[j]*MBi[0][2] + qz[j]*MBi[5][2];
00443
00444 k[1][0] = qy[j]*MBi[1][0] + qx[j]*MBi[3][0] ;
00445 k[1][1] = qy[j]*MBi[1][1] + qx[j]*MBi[3][1] + qz[j]*MBi[4][1];
00446 k[1][2] = qy[j]*MBi[1][2] + qz[j]*MBi[4][2];
00447
00448 k[2][0] = qz[j]*MBi[2][0] + qx[j]*MBi[5][0];
00449 k[2][1] = qz[j]*MBi[2][1] + qy[j]*MBi[4][1] ;
00450 k[2][2] = qz[j]*MBi[2][2] + qy[j]*MBi[4][2] + qx[j]*MBi[5][2];
00451 #ifndef DN_USE_J
00452 k = J_1t*k*J_1;
00453 #endif
00454 if (verbose) std::cout << "K"<<i<<j<<" += "<<k<<" * "<<detJ<<"\n";
00455 k *= detJ;
00456 for(int m=0;m<3;++m)
00457 for(int l=0;l<3;++l)
00458 {
00459 K[i*3+m][j*3+l] += k[l][m];
00460 }
00461 }
00462 }
00463 }
00464 for(int i=0;i<24;++i)
00465 for(int j=i+1;j<24;++j)
00466 {
00467 K[j][i] = K[i][j];
00468 }
00469 ElementStiffness K1 = K;
00470 K.fill( 0.0 );
00471
00472
00473
00474
00475
00476
00477 J_1.fill( 0.0 );
00478 Coord l = nodes[6] - nodes[0];
00479 J_1[0][0]=2.0f / l[0];
00480 J_1[1][1]=2.0f / l[1];
00481 J_1[2][2]=2.0f / l[2];
00482
00483
00484 Real vol = ((nodes[1]-nodes[0]).norm()*(nodes[3]-nodes[0]).norm()*(nodes[4]-nodes[0]).norm());
00485
00486 vol /= 8.0;
00487
00488 K.clear();
00489
00490
00491 for(int i=0;i<8;++i)
00492 {
00493 Mat33 k = vol*integrateStiffness( _coef[i][0], _coef[i][1],_coef[i][2], _coef[i][0], _coef[i][1],_coef[i][2], M[0][0], M[0][1],M[3][3], J_1 );
00494
00495
00496 for(int m=0;m<3;++m)
00497 for(int l=0;l<3;++l)
00498 {
00499 K[i*3+m][i*3+l] += k[m][l];
00500 }
00501
00502
00503
00504 for(int j=i+1;j<8;++j)
00505 {
00506 Mat33 k = vol*integrateStiffness( _coef[i][0], _coef[i][1],_coef[i][2], _coef[j][0], _coef[j][1],_coef[j][2], M[0][0], M[0][1],M[3][3], J_1 );
00507
00508
00509 for(int m=0;m<3;++m)
00510 for(int l=0;l<3;++l)
00511 {
00512 K[i*3+m][j*3+l] += k[m][l];
00513
00514 }
00515 }
00516 }
00517
00518 for(int i=0;i<24;++i)
00519 for(int j=i+1;j<24;++j)
00520 {
00521 K[j][i] = K[i][j];
00522 }
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 #ifdef GENERIC_STIFFNESS_MATRIX
00535 K=K1;
00536 #endif
00537
00538 K *= (Real)stiffnessFactor;
00539
00540 }
00541
00542
00543
00544
00545 template<class DataTypes>
00546 typename HexahedronFEMForceField<DataTypes>::Mat33 HexahedronFEMForceField<DataTypes>::integrateStiffness( int signx0, int signy0, int signz0, int signx1, int signy1, int signz1, const Real u, const Real v, const Real w, const Mat33& J_1 )
00547 {
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 Mat33 K;
00625
00626 Real t1 = J_1[0][0]*J_1[0][0];
00627 Real t2 = t1*signx0;
00628 Real t3 = (Real)(signy0*signz0);
00629 Real t4 = t2*t3;
00630 Real t5 = w*signx1;
00631 Real t6 = (Real)(signy1*signz1);
00632 Real t7 = t5*t6;
00633 Real t10 = t1*signy0;
00634 Real t12 = w*signy1;
00635 Real t13 = t12*signz1;
00636 Real t16 = t2*signz0;
00637 Real t17 = u*signx1;
00638 Real t18 = t17*signz1;
00639 Real t21 = t17*t6;
00640 Real t24 = t2*signy0;
00641 Real t25 = t17*signy1;
00642 Real t28 = t5*signy1;
00643 Real t32 = w*signz1;
00644 Real t37 = t5*signz1;
00645 Real t43 = J_1[0][0]*signx0;
00646 Real t45 = v*J_1[1][1];
00647 Real t49 = J_1[0][0]*signy0;
00648 Real t50 = t49*signz0;
00649 Real t51 = w*J_1[1][1];
00650 Real t52 = (Real)(signx1*signz1);
00651 Real t53 = t51*t52;
00652 Real t56 = t45*signy1;
00653 Real t64 = v*J_1[2][2];
00654 Real t68 = w*J_1[2][2];
00655 Real t69 = (Real)(signx1*signy1);
00656 Real t70 = t68*t69;
00657 Real t73 = t64*signz1;
00658 Real t81 = J_1[1][1]*signy0;
00659 Real t83 = v*J_1[0][0];
00660 Real t87 = J_1[1][1]*signx0;
00661 Real t88 = t87*signz0;
00662 Real t89 = w*J_1[0][0];
00663 Real t90 = t89*t6;
00664 Real t93 = t83*signx1;
00665 Real t100 = J_1[1][1]*J_1[1][1];
00666 Real t101 = t100*signx0;
00667 Real t102 = t101*t3;
00668 Real t110 = t100*signy0;
00669 Real t111 = t110*signz0;
00670 Real t112 = u*signy1;
00671 Real t113 = t112*signz1;
00672 Real t116 = t101*signy0;
00673 Real t144 = J_1[2][2]*signy0;
00674 Real t149 = J_1[2][2]*signx0;
00675 Real t150 = t149*signy0;
00676 Real t153 = J_1[2][2]*signz0;
00677 Real t172 = J_1[2][2]*J_1[2][2];
00678 Real t173 = t172*signx0;
00679 Real t174 = t173*t3;
00680 Real t177 = t173*signz0;
00681 Real t180 = t172*signy0;
00682 Real t181 = t180*signz0;
00683
00684 K[0][0] = (float)(t4*t7/36.0+t10*signz0*t13/12.0+t16*t18/24.0+t4*t21/72.0+
00685 t24*t25/24.0+t24*t28/24.0+t1*signz0*t32/8.0+t10*t12/8.0+t16*t37/24.0+t2*t17/8.0);
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 K[0][1] = (float)(t43*signz0*t45*t6/24.0+t50*t53/24.0+t43*t56/8.0+t49*t51*
00697 signx1/8.0);
00698
00699
00700
00701
00702 K[0][2] = (float)(t43*signy0*t64*t6/24.0+t50*t70/24.0+t43*t73/8.0+J_1[0][0]*signz0
00703 *t68*signx1/8.0);
00704
00705
00706
00707
00708 K[1][0] = (float)(t81*signz0*t83*t52/24.0+t88*t90/24.0+t81*t93/8.0+t87*t89*
00709 signy1/8.0);
00710
00711
00712
00713
00714 K[1][1] = (float)(t102*t7/36.0+t102*t21/72.0+t101*signz0*t37/12.0+t111*t113
00715 /24.0+t116*t28/24.0+t100*signz0*t32/8.0+t111*t13/24.0+t116*t25/24.0+t110*t112/
00716 8.0+t101*t5/8.0);
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 K[1][2] = (float)(t87*signy0*t64*t52/24.0+t88*t70/24.0+t81*t73/8.0+J_1[1][1]*
00728 signz0*t68*signy1/8.0);
00729
00730
00731
00732
00733 K[2][0] = (float)(t144*signz0*t83*t69/24.0+t150*t90/24.0+t153*t93/8.0+t149*
00734 t89*signz1/8.0);
00735
00736
00737
00738
00739 K[2][1] = (float)(t149*signz0*t45*t69/24.0+t150*t53/24.0+t153*t56/8.0+t144*
00740 t51*signz1/8.0);
00741
00742
00743
00744
00745 K[2][2] = (float)(t174*t7/36.0+t177*t37/24.0+t181*t13/24.0+t174*t21/72.0+
00746 t173*signy0*t28/12.0+t180*t12/8.0+t181*t113/24.0+t177*t18/24.0+t172*signz0*u*
00747 signz1/8.0+t173*t5/8.0);
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 return K ;
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 }
00774
00775
00776
00777 template<class DataTypes>
00778 void HexahedronFEMForceField<DataTypes>::computeMaterialStiffness(int i)
00779 {
00780 _materialsStiffnesses[i][0][0] = _materialsStiffnesses[i][1][1] = _materialsStiffnesses[i][2][2] = 1;
00781 _materialsStiffnesses[i][0][1] = _materialsStiffnesses[i][0][2] = _materialsStiffnesses[i][1][0]
00782 = _materialsStiffnesses[i][1][2] = _materialsStiffnesses[i][2][0] =
00783 _materialsStiffnesses[i][2][1] = f_poissonRatio.getValue()/(1-f_poissonRatio.getValue());
00784 _materialsStiffnesses[i][0][3] = _materialsStiffnesses[i][0][4] = _materialsStiffnesses[i][0][5] = 0;
00785 _materialsStiffnesses[i][1][3] = _materialsStiffnesses[i][1][4] = _materialsStiffnesses[i][1][5] = 0;
00786 _materialsStiffnesses[i][2][3] = _materialsStiffnesses[i][2][4] = _materialsStiffnesses[i][2][5] = 0;
00787 _materialsStiffnesses[i][3][0] = _materialsStiffnesses[i][3][1] = _materialsStiffnesses[i][3][2] = _materialsStiffnesses[i][3][4] = _materialsStiffnesses[i][3][5] = 0;
00788 _materialsStiffnesses[i][4][0] = _materialsStiffnesses[i][4][1] = _materialsStiffnesses[i][4][2] = _materialsStiffnesses[i][4][3] = _materialsStiffnesses[i][4][5] = 0;
00789 _materialsStiffnesses[i][5][0] = _materialsStiffnesses[i][5][1] = _materialsStiffnesses[i][5][2] = _materialsStiffnesses[i][5][3] = _materialsStiffnesses[i][5][4] = 0;
00790 _materialsStiffnesses[i][3][3] = _materialsStiffnesses[i][4][4] = _materialsStiffnesses[i][5][5] = (1-2*f_poissonRatio.getValue())/(2*(1-f_poissonRatio.getValue()));
00791 _materialsStiffnesses[i] *= (f_youngModulus.getValue()*(1-f_poissonRatio.getValue()))/((1+f_poissonRatio.getValue())*(1-2*f_poissonRatio.getValue()));
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 }
00802
00803 template<class DataTypes>
00804 void HexahedronFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const ElementStiffness &K )
00805 {
00806
00807 F = K*Depl;
00808 }
00809
00810
00811
00812
00813
00818
00819
00820 template<class DataTypes>
00821 void HexahedronFEMForceField<DataTypes>::initLarge(int i, const Element &elem)
00822 {
00823
00824
00825
00826 Vec<8,Coord> nodes;
00827 for(int w=0;w<8;++w)
00828 #ifndef SOFA_NEW_HEXA
00829 nodes[w] = _initialPoints.getValue()[elem[_indices[w]]];
00830 #else
00831 nodes[w] = _initialPoints.getValue()[elem[w]];
00832 #endif
00833
00834 Coord horizontal;
00835 horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00836 Coord vertical;
00837 vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00838 Transformation R_0_1;
00839 computeRotationLarge( R_0_1, horizontal,vertical);
00840
00841 for(int w=0;w<8;++w)
00842 #ifndef SOFA_NEW_HEXA
00843 _rotatedInitialElements[i][w] = R_0_1*_initialPoints.getValue()[elem[_indices[w]]];
00844 #else
00845 _rotatedInitialElements[i][w] = R_0_1*_initialPoints.getValue()[elem[w]];
00846 #endif
00847
00848 if( _elementStiffnesses.getValue().size() <= (unsigned)i )
00849 {
00850 _elementStiffnesses.beginEdit()->resize( _elementStiffnesses.getValue().size()+1 );
00851 computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], _rotatedInitialElements[i], i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00852 }
00853
00854
00855 }
00856
00857 template<class DataTypes>
00858 void HexahedronFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, Coord &edgex, Coord &edgey)
00859 {
00860
00861 edgex.normalize();
00862 edgey.normalize();
00863
00864 Coord edgez = cross( edgex, edgey );
00865 edgez.normalize();
00866
00867 edgey = cross( edgez, edgex );
00868 edgey.normalize();
00869
00870 r[0][0] = edgex[0];
00871 r[0][1] = edgex[1];
00872 r[0][2] = edgex[2];
00873 r[1][0] = edgey[0];
00874 r[1][1] = edgey[1];
00875 r[1][2] = edgey[2];
00876 r[2][0] = edgez[0];
00877 r[2][1] = edgez[1];
00878 r[2][2] = edgez[2];
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 }
00891
00892 template<class DataTypes>
00893 void HexahedronFEMForceField<DataTypes>::accumulateForceLarge( Vector& f, const Vector & p, int i, const Element&elem )
00894 {
00895 Vec<8,Coord> nodes;
00896 for(int w=0;w<8;++w)
00897 #ifndef SOFA_NEW_HEXA
00898 nodes[w] = p[elem[_indices[w]]];
00899 #else
00900 nodes[w] = p[elem[w]];
00901 #endif
00902
00903 Coord horizontal;
00904 horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00905 Coord vertical;
00906 vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00907
00908 Transformation R_0_2;
00909 computeRotationLarge( R_0_2, horizontal,vertical);
00910
00911 _rotations[i].transpose(R_0_2);
00912
00913
00914 Vec<8,Coord> deformed;
00915 for(int w=0;w<8;++w)
00916 deformed[w] = R_0_2 * nodes[w];
00917
00918
00919
00920 Displacement D;
00921 for(int k=0 ; k<8 ; ++k )
00922 {
00923 int indice = k*3;
00924 for(int j=0 ; j<3 ; ++j )
00925 D[indice+j] = _rotatedInitialElements[i][k][j] - deformed[k][j];
00926 }
00927
00928
00929 if(f_updateStiffnessMatrix.getValue())
00930
00931 computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], deformed, i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00932
00933
00934 Displacement F;
00935 computeForce( F, D, _elementStiffnesses.getValue()[i] );
00936
00937 for(int w=0;w<8;++w)
00938 #ifndef SOFA_NEW_HEXA
00939 f[elem[_indices[w]]] += _rotations[i] * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00940 #else
00941 f[elem[w]] += _rotations[i] * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00942 #endif
00943 }
00944
00945
00946
00947
00948
00949
00950
00955
00956
00957
00958 template<class DataTypes>
00959 void HexahedronFEMForceField<DataTypes>::initPolar(int i, const Element& elem)
00960 {
00961 Vec<8,Coord> nodes;
00962 for(int j=0;j<8;++j)
00963 #ifndef SOFA_NEW_HEXA
00964 nodes[j] = _initialPoints.getValue()[elem[_indices[j]]];
00965 #else
00966 nodes[j] = _initialPoints.getValue()[elem[j]];
00967 #endif
00968
00969 Transformation R_0_1;
00970 computeRotationPolar( R_0_1, nodes );
00971
00972
00973 for(int j=0;j<8;++j)
00974 {
00975 _rotatedInitialElements[i][j] = R_0_1 * nodes[j];
00976 }
00977
00978
00979 if( _elementStiffnesses.getValue().size() <= (unsigned)i )
00980 {
00981 _elementStiffnesses.beginEdit()->resize( _elementStiffnesses.getValue().size()+1 );
00982 computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], _rotatedInitialElements[i], i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
00983 }
00984 }
00985
00986
00987
00988 template<class DataTypes>
00989 void HexahedronFEMForceField<DataTypes>::computeRotationPolar( Transformation &r, Vec<8,Coord> &nodes)
00990 {
00991 Transformation A;
00992 Coord Edge =(nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00993
00994 A[0][0] = Edge[0];
00995 A[0][1] = Edge[1];
00996 A[0][2] = Edge[2];
00997 Edge = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00998
00999 A[1][0] = Edge[0];
01000 A[1][1] = Edge[1];
01001 A[1][2] = Edge[2];
01002 Edge = (nodes[4]-nodes[0] + nodes[5]-nodes[1] + nodes[7]-nodes[3] + nodes[6]-nodes[2])*.25;
01003
01004 A[2][0] = Edge[0];
01005 A[2][1] = Edge[1];
01006 A[2][2] = Edge[2];
01007
01008 Mat33 HT;
01009 for(int k=0;k<3;++k)
01010 for(int j=0;j<3;++j)
01011 HT[k][j]=A[k][j];
01012
01013
01014 Mat33 S;
01015
01016 polar_decomp(HT, r, S);
01017 }
01018
01019
01020 template<class DataTypes>
01021 void HexahedronFEMForceField<DataTypes>::accumulateForcePolar( Vector& f, const Vector & p, int i, const Element&elem )
01022 {
01023 Vec<8,Coord> nodes;
01024 for(int j=0;j<8;++j)
01025 #ifndef SOFA_NEW_HEXA
01026 nodes[j] = p[elem[_indices[j]]];
01027 #else
01028 nodes[j] = p[elem[j]];
01029 #endif
01030
01031 Transformation R_0_2;
01032 computeRotationPolar( R_0_2, nodes );
01033
01034 _rotations[i].transpose( R_0_2 );
01035
01036
01037
01038 Vec<8,Coord> deformed;
01039 for(int j=0;j<8;++j)
01040 deformed[j] = R_0_2 * nodes[j];
01041
01042
01043
01044
01045 Displacement D;
01046 for(int k=0 ; k<8 ; ++k )
01047 {
01048 int indice = k*3;
01049 for(int j=0 ; j<3 ; ++j )
01050 D[indice+j] = _rotatedInitialElements[i][k][j] - deformed[k][j];
01051 }
01052
01053
01054 Displacement F;
01055
01056 if(f_updateStiffnessMatrix.getValue())
01057
01058 computeElementStiffness( (*_elementStiffnesses.beginEdit())[i], _materialsStiffnesses[i], deformed, i, _sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5:1.0 );
01059
01060
01061 computeForce( F, D, _elementStiffnesses.getValue()[i] );
01062
01063
01064 for(int j=0;j<8;++j)
01065 #ifndef SOFA_NEW_HEXA
01066 f[elem[_indices[j]]] += _rotations[i] * Deriv( F[j*3], F[j*3+1], F[j*3+2] );
01067 #else
01068 f[elem[j]] += _rotations[i] * Deriv( F[j*3], F[j*3+1], F[j*3+2] );
01069 #endif
01070 }
01071
01072
01073
01074
01075
01079
01080
01081 template<class DataTypes>
01082 void HexahedronFEMForceField<DataTypes>::addKToMatrix(sofa::defaulttype::BaseMatrix *mat, SReal k, unsigned int &offset)
01083 {
01084
01085 int i,j,n1, n2, e;
01086
01087 typename VecElement::const_iterator it;
01088
01089 Index node1, node2;
01090
01091 for(it = _indexedElements->begin(), e=0 ; it != _indexedElements->end() ; ++it,++e)
01092 {
01093 const ElementStiffness &Ke = _elementStiffnesses.getValue()[e];
01094 const Transformation& Rt = _rotations[e];
01095 Transformation R; R.transpose(Rt);
01096
01097
01098 for (n1=0; n1<8; n1++)
01099 {
01100 #ifndef SOFA_NEW_HEXA
01101 node1 = (*it)[_indices[n1]];
01102 #else
01103 node1 = (*it)[n1];
01104 #endif
01105
01106 for (n2=0; n2<8; n2++)
01107 {
01108 #ifndef SOFA_NEW_HEXA
01109 node2 = (*it)[_indices[n2]];
01110 #else
01111 node2 = (*it)[n2];
01112 #endif
01113 Mat33 tmp = Rt * Mat33(Coord(Ke[3*n1+0][3*n2+0],Ke[3*n1+0][3*n2+1],Ke[3*n1+0][3*n2+2]),
01114 Coord(Ke[3*n1+1][3*n2+0],Ke[3*n1+1][3*n2+1],Ke[3*n1+1][3*n2+2]),
01115 Coord(Ke[3*n1+2][3*n2+0],Ke[3*n1+2][3*n2+1],Ke[3*n1+2][3*n2+2])) * R;
01116 for(i=0; i<3; i++)
01117 for (j=0; j<3; j++)
01118 mat->add(offset+3*node1+i, offset+3*node2+j, - tmp[i][j]*k);
01119 }
01120 }
01121 }
01122 }
01123
01124
01125
01126
01127 template<class DataTypes>
01128 void HexahedronFEMForceField<DataTypes>::draw()
01129 {
01130
01131 if (!getContext()->getShowForceFields()) return;
01132 if (!this->mstate) return;
01133
01134
01135 const VecCoord& x = *this->mstate->getX();
01136
01137 if (getContext()->getShowWireFrame())
01138 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
01139
01140 glDisable(GL_LIGHTING);
01141
01142 typename VecElement::const_iterator it;
01143 int i;
01144 for(it = _indexedElements->begin(), i = 0 ; it != _indexedElements->end() ; ++it, ++i)
01145 {
01146 Index a = (*it)[0];
01147 Index b = (*it)[1];
01148 #ifndef SOFA_NEW_HEXA
01149 Index d = (*it)[2];
01150 Index c = (*it)[3];
01151 #else
01152 Index d = (*it)[3];
01153 Index c = (*it)[2];
01154 #endif
01155 Index e = (*it)[4];
01156 Index f = (*it)[5];
01157 #ifndef SOFA_NEW_HEXA
01158 Index h = (*it)[6];
01159 Index g = (*it)[7];
01160 #else
01161 Index h = (*it)[7];
01162 Index g = (*it)[6];
01163 #endif
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 Coord center = (x[a]+x[b]+x[c]+x[d]+x[e]+x[g]+x[f]+x[h])*0.125;
01177 Real percentage = (Real) 0.15;
01178 Coord pa = x[a]-(x[a]-center)*percentage;
01179 Coord pb = x[b]-(x[b]-center)*percentage;
01180 Coord pc = x[c]-(x[c]-center)*percentage;
01181 Coord pd = x[d]-(x[d]-center)*percentage;
01182 Coord pe = x[e]-(x[e]-center)*percentage;
01183 Coord pf = x[f]-(x[f]-center)*percentage;
01184 Coord pg = x[g]-(x[g]-center)*percentage;
01185 Coord ph = x[h]-(x[h]-center)*percentage;
01186
01187
01188
01189
01190 if(_sparseGrid )
01191 {
01192 glEnable(GL_BLEND);
01193 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01194 }
01195
01196
01197
01198
01199
01200 glColor4f(0.7f, 0.7f, 0.1f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01201 glBegin(GL_POLYGON);
01202 helper::gl::glVertexT(pa);
01203 helper::gl::glVertexT(pb);
01204 helper::gl::glVertexT(pc);
01205 helper::gl::glVertexT(pd);
01206 glEnd();
01207 glColor4f(0.7f, 0, 0, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01208 glBegin(GL_POLYGON);
01209 helper::gl::glVertexT(pe);
01210 helper::gl::glVertexT(pf);
01211 helper::gl::glVertexT(pg);
01212 helper::gl::glVertexT(ph);
01213 glEnd();
01214 glColor4f(0, 0.7f, 0, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01215 glBegin(GL_POLYGON);
01216 helper::gl::glVertexT(pc);
01217 helper::gl::glVertexT(pd);
01218 helper::gl::glVertexT(ph);
01219 helper::gl::glVertexT(pg);
01220 glEnd();
01221 glColor4f(0, 0, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01222 glBegin(GL_POLYGON);
01223 helper::gl::glVertexT(pa);
01224 helper::gl::glVertexT(pb);
01225 helper::gl::glVertexT(pf);
01226 helper::gl::glVertexT(pe);
01227 glEnd();
01228 glColor4f(0.1f, 0.7f, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01229 glBegin(GL_POLYGON);
01230 helper::gl::glVertexT(pa);
01231 helper::gl::glVertexT(pd);
01232 helper::gl::glVertexT(ph);
01233 helper::gl::glVertexT(pe);
01234 glEnd();
01235 glColor4f(0.7f, 0.1f, 0.7f, (_sparseGrid && _sparseGrid->getType(i)==topology::SparseGridTopology::BOUNDARY?.5f:1.0f));
01236 glBegin(GL_POLYGON);
01237 helper::gl::glVertexT(pb);
01238 helper::gl::glVertexT(pc);
01239 helper::gl::glVertexT(pg);
01240 helper::gl::glVertexT(pf);
01241 glEnd();
01242 }
01243
01244 if (getContext()->getShowWireFrame())
01245 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
01246
01247 if(_sparseGrid )
01248 glDisable(GL_BLEND);
01249 }
01250
01251
01252 }
01253
01254 }
01255
01256 }
01257
01258 #endif