TetrahedralCorotationalFEMForceField.inl

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #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(); // compute per-element stiffness matrices and other precomputed values
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& /*v*/)
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     // shape functions matrix
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     // 0
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     //m_deq( J, 1.2 ); //hack for stability ??
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     /*Real gamma = (youngModulus*poissonRatio) / ((1+poissonRatio)*(1-2*poissonRatio));
00380     Real        mu2 = youngModulus / (1+poissonRatio);
00381     _materialsStiffnesses[i][0][3] = _materialsStiffnesses[i][0][4] =   _materialsStiffnesses[i][0][5] = 0;
00382     _materialsStiffnesses[i][1][3] = _materialsStiffnesses[i][1][4] =   _materialsStiffnesses[i][1][5] = 0;
00383     _materialsStiffnesses[i][2][3] = _materialsStiffnesses[i][2][4] =   _materialsStiffnesses[i][2][5] = 0;
00384     _materialsStiffnesses[i][3][0] = _materialsStiffnesses[i][3][1] = _materialsStiffnesses[i][3][2] = _materialsStiffnesses[i][3][4] = _materialsStiffnesses[i][3][5] = 0;
00385     _materialsStiffnesses[i][4][0] = _materialsStiffnesses[i][4][1] = _materialsStiffnesses[i][4][2] = _materialsStiffnesses[i][4][3] = _materialsStiffnesses[i][4][5] = 0;
00386     _materialsStiffnesses[i][5][0] = _materialsStiffnesses[i][5][1] = _materialsStiffnesses[i][5][2] = _materialsStiffnesses[i][5][3] = _materialsStiffnesses[i][5][4] = 0;
00387     _materialsStiffnesses[i][0][0] = _materialsStiffnesses[i][1][1] = _materialsStiffnesses[i][2][2] = gamma+mu2;
00388     _materialsStiffnesses[i][0][1] = _materialsStiffnesses[i][0][2] = _materialsStiffnesses[i][1][0]
00389                 = _materialsStiffnesses[i][1][2] = _materialsStiffnesses[i][2][0] = _materialsStiffnesses[i][2][1] = gamma;
00390     _materialsStiffnesses[i][3][3] = _materialsStiffnesses[i][4][4] = _materialsStiffnesses[i][5][5] =  mu2;*/
00391 
00392     // divide by 36 times volumes of the element
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     /* We have these zeros
00415                                   K[0][3]   K[0][4]   K[0][5]   
00416                                   K[1][3]   K[1][4]   K[1][5]   
00417                                   K[2][3]   K[2][4]   K[2][5]   
00418     K[3][0]   K[3][1]   K[3][2]             K[3][4]   K[3][5]   
00419     K[4][0]   K[4][1]   K[4][2]   K[4][3]             K[4][5]   
00420     K[5][0]   K[5][1]   K[5][2]   K[5][3]   K[5][4]   
00421 
00422 
00423               J[0][1]   J[0][2]             J[0][4]  
00424     J[1][0]             J[1][2]                       J[1][5]  
00425     J[2][0]   J[2][1]             J[2][3]  
00426               J[3][1]   J[3][2]             J[3][4]   
00427     J[4][0]             J[4][2]                       J[4][5]   
00428     J[5][0]   J[5][1]             J[5][3]  
00429               J[6][1]   J[6][2]             J[6][4]   
00430     J[7][0]             J[7][2]                       J[7][5]   
00431     J[8][0]   J[8][1]             J[8][3]  
00432               J[9][1]   J[9][2]             J[9][4]   
00433     J[10][0]            J[10][2]                      J[10][5]  
00434     J[11][0]  J[11][1]            J[11][3] 
00435     */
00436 
00437     VecNoInit<6,Real> JtD;
00438     JtD[0] =   J[ 0][0]*Depl[ 0]+/*J[ 1][0]*Depl[ 1]+  J[ 2][0]*Depl[ 2]+*/
00439                J[ 3][0]*Depl[ 3]+/*J[ 4][0]*Depl[ 4]+  J[ 5][0]*Depl[ 5]+*/
00440                J[ 6][0]*Depl[ 6]+/*J[ 7][0]*Depl[ 7]+  J[ 8][0]*Depl[ 8]+*/
00441                J[ 9][0]*Depl[ 9] /*J[10][0]*Depl[10]+  J[11][0]*Depl[11]*/;
00442     JtD[1] = /*J[ 0][1]*Depl[ 0]+*/J[ 1][1]*Depl[ 1]+/*J[ 2][1]*Depl[ 2]+*/
00443              /*J[ 3][1]*Depl[ 3]+*/J[ 4][1]*Depl[ 4]+/*J[ 5][1]*Depl[ 5]+*/
00444              /*J[ 6][1]*Depl[ 6]+*/J[ 7][1]*Depl[ 7]+/*J[ 8][1]*Depl[ 8]+*/
00445              /*J[ 9][1]*Depl[ 9]+*/J[10][1]*Depl[10] /*J[11][1]*Depl[11]*/;
00446     JtD[2] = /*J[ 0][2]*Depl[ 0]+  J[ 1][2]*Depl[ 1]+*/J[ 2][2]*Depl[ 2]+
00447              /*J[ 3][2]*Depl[ 3]+  J[ 4][2]*Depl[ 4]+*/J[ 5][2]*Depl[ 5]+
00448              /*J[ 6][2]*Depl[ 6]+  J[ 7][2]*Depl[ 7]+*/J[ 8][2]*Depl[ 8]+
00449              /*J[ 9][2]*Depl[ 9]+  J[10][2]*Depl[10]+*/J[11][2]*Depl[11]  ;
00450     JtD[3] =   J[ 0][3]*Depl[ 0]+  J[ 1][3]*Depl[ 1]+/*J[ 2][3]*Depl[ 2]+*/
00451                J[ 3][3]*Depl[ 3]+  J[ 4][3]*Depl[ 4]+/*J[ 5][3]*Depl[ 5]+*/
00452                J[ 6][3]*Depl[ 6]+  J[ 7][3]*Depl[ 7]+/*J[ 8][3]*Depl[ 8]+*/
00453                J[ 9][3]*Depl[ 9]+  J[10][3]*Depl[10] /*J[11][3]*Depl[11]*/;
00454     JtD[4] = /*J[ 0][4]*Depl[ 0]+*/J[ 1][4]*Depl[ 1]+  J[ 2][4]*Depl[ 2]+
00455              /*J[ 3][4]*Depl[ 3]+*/J[ 4][4]*Depl[ 4]+  J[ 5][4]*Depl[ 5]+
00456              /*J[ 6][4]*Depl[ 6]+*/J[ 7][4]*Depl[ 7]+  J[ 8][4]*Depl[ 8]+
00457              /*J[ 9][4]*Depl[ 9]+*/J[10][4]*Depl[10]+  J[11][4]*Depl[11]  ;
00458     JtD[5] =   J[ 0][5]*Depl[ 0]+/*J[ 1][5]*Depl[ 1]*/ J[ 2][5]*Depl[ 2]+
00459                J[ 3][5]*Depl[ 3]+/*J[ 4][5]*Depl[ 4]*/ J[ 5][5]*Depl[ 5]+
00460                J[ 6][5]*Depl[ 6]+/*J[ 7][5]*Depl[ 7]*/ J[ 8][5]*Depl[ 8]+
00461                J[ 9][5]*Depl[ 9]+/*J[10][5]*Depl[10]*/ J[11][5]*Depl[11];
00462 //         cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::computeForce, D = "<<Depl<<endl;
00463 //         cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::computeForce, JtD = "<<JtD<<endl;
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               /*K[0][3]*JtD[3]+  K[0][4]*JtD[4]+  K[0][5]*JtD[5]*/;
00468     KJtD[1] =   K[1][0]*JtD[0]+  K[1][1]*JtD[1]+  K[1][2]*JtD[2]
00469               /*K[1][3]*JtD[3]+  K[1][4]*JtD[4]+  K[1][5]*JtD[5]*/;
00470     KJtD[2] =   K[2][0]*JtD[0]+  K[2][1]*JtD[1]+  K[2][2]*JtD[2]
00471               /*K[2][3]*JtD[3]+  K[2][4]*JtD[4]+  K[2][5]*JtD[5]*/;
00472     KJtD[3] = /*K[3][0]*JtD[0]+  K[3][1]*JtD[1]+  K[3][2]*JtD[2]+*/
00473                 K[3][3]*JtD[3] /*K[3][4]*JtD[4]+  K[3][5]*JtD[5]*/;
00474     KJtD[4] = /*K[4][0]*JtD[0]+  K[4][1]*JtD[1]+  K[4][2]*JtD[2]+*/
00475               /*K[4][3]*JtD[3]+*/K[4][4]*JtD[4] /*K[4][5]*JtD[5]*/;
00476     KJtD[5] = /*K[5][0]*JtD[0]+  K[5][1]*JtD[1]+  K[5][2]*JtD[2]+*/
00477               /*K[5][3]*JtD[3]+  K[5][4]*JtD[4]+*/K[5][5]*JtD[5]  ;
00478 
00479     F[ 0] =   J[ 0][0]*KJtD[0]+/*J[ 0][1]*KJtD[1]+  J[ 0][2]*KJtD[2]+*/
00480               J[ 0][3]*KJtD[3]+/*J[ 0][4]*KJtD[4]+*/J[ 0][5]*KJtD[5]  ;
00481     F[ 1] = /*J[ 1][0]*KJtD[0]+*/J[ 1][1]*KJtD[1]+/*J[ 1][2]*KJtD[2]+*/
00482               J[ 1][3]*KJtD[3]+  J[ 1][4]*KJtD[4] /*J[ 1][5]*KJtD[5]*/;
00483     F[ 2] = /*J[ 2][0]*KJtD[0]+  J[ 2][1]*KJtD[1]+*/J[ 2][2]*KJtD[2]+
00484             /*J[ 2][3]*KJtD[3]+*/J[ 2][4]*KJtD[4]+  J[ 2][5]*KJtD[5]  ;
00485     F[ 3] =   J[ 3][0]*KJtD[0]+/*J[ 3][1]*KJtD[1]+  J[ 3][2]*KJtD[2]+*/
00486               J[ 3][3]*KJtD[3]+/*J[ 3][4]*KJtD[4]+*/J[ 3][5]*KJtD[5]  ;
00487     F[ 4] = /*J[ 4][0]*KJtD[0]+*/J[ 4][1]*KJtD[1]+/*J[ 4][2]*KJtD[2]+*/
00488               J[ 4][3]*KJtD[3]+  J[ 4][4]*KJtD[4] /*J[ 4][5]*KJtD[5]*/;
00489     F[ 5] = /*J[ 5][0]*KJtD[0]+  J[ 5][1]*KJtD[1]+*/J[ 5][2]*KJtD[2]+
00490             /*J[ 5][3]*KJtD[3]+*/J[ 5][4]*KJtD[4]+  J[ 5][5]*KJtD[5]  ;
00491     F[ 6] =   J[ 6][0]*KJtD[0]+/*J[ 6][1]*KJtD[1]+  J[ 6][2]*KJtD[2]+*/
00492               J[ 6][3]*KJtD[3]+/*J[ 6][4]*KJtD[4]+*/J[ 6][5]*KJtD[5]  ;
00493     F[ 7] = /*J[ 7][0]*KJtD[0]+*/J[ 7][1]*KJtD[1]+/*J[ 7][2]*KJtD[2]+*/
00494               J[ 7][3]*KJtD[3]+  J[ 7][4]*KJtD[4] /*J[ 7][5]*KJtD[5]*/;
00495     F[ 8] = /*J[ 8][0]*KJtD[0]+  J[ 8][1]*KJtD[1]+*/J[ 8][2]*KJtD[2]+
00496             /*J[ 8][3]*KJtD[3]+*/J[ 8][4]*KJtD[4]+  J[ 8][5]*KJtD[5]  ;
00497     F[ 9] =   J[ 9][0]*KJtD[0]+/*J[ 9][1]*KJtD[1]+  J[ 9][2]*KJtD[2]+*/
00498               J[ 9][3]*KJtD[3]+/*J[ 9][4]*KJtD[4]+*/J[ 9][5]*KJtD[5]  ;
00499     F[10] = /*J[10][0]*KJtD[0]+*/J[10][1]*KJtD[1]+/*J[10][2]*KJtD[2]+*/
00500               J[10][3]*KJtD[3]+  J[10][4]*KJtD[4] /*J[10][5]*KJtD[5]*/;
00501     F[11] = /*J[11][0]*KJtD[0]+  J[11][1]*KJtD[1]+*/J[11][2]*KJtD[2]+
00502             /*J[11][3]*KJtD[3]+*/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     //std::cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall"<<std::endl;
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     // displacements
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 /*        std::cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall, displacement"<<D<<std::endl;
00547         std::cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall, straindisplacement"<<tetrahedronInfo[elementIndex].strainDisplacementMatrix<<std::endl;
00548         std::cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall, material"<<tetrahedronInfo[elementIndex].materialMatrix<<std::endl;*/
00549     
00550     // compute force on element
00551     Displacement F;
00552     
00553     if(!_assembling)
00554     {
00555         computeForce( F, D,tetrahedronInfo[elementIndex].materialMatrix,tetrahedronInfo[elementIndex].strainDisplacementMatrix );
00556                 //std::cerr<<"TetrahedralCorotationalFEMForceField<DataTypes>::accumulateForceSmall, force"<<F<<std::endl;
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         //erase the stiffness matrix at each time step
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                     //cerr<<row<<" "<<col<<endl;
00590                     
00591                     //typename CompressedValue::iterator result = _stiffnesses[row].find(col);
00592                     
00593                     
00594                     // search if the vertex is already take into account by another element
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         /*for(unsigned int i=0;i<_stiffnesses.size();++i)
00611             for(typename CompressedValue::iterator it=_stiffnesses[i].begin();it!=_stiffnesses[i].end();++it)
00612                 cerr<<i<<" "<<(*it).first<<"   "<<(*it).second<<"   "<<JKJt[i][(*it).first]<<endl;*/
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     // first vector on first edge
00661     // second vector in the plane of the two first edges
00662     // third vector orthogonal to first and second  
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     // Rotation matrix (initial Tetrahedre/world)
00691     // first vector on first edge
00692     // second vector in the plane of the two first edges
00693     // third vector orthogonal to first and second
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 //  cerr<<"a,b,c : "<<a<<" "<<b<<" "<<c<<endl;
00705 //  cerr<<"_initialPoints : "<<_initialPoints<<endl;
00706 //  cerr<<"R_0_1 large : "<<R_0_1<<endl;
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 //  cerr<<"_rotatedInitialElements : "<<_rotatedInitialElements<<endl;
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     // Rotation matrix (deformed and displaced Tetrahedron/world)
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     //cerr<<"R_0_2 large : "<<R_0_2<<endl;
00728 
00729     // positions of the deformed and displaced Tetrahedron in its frame
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     // displacement
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     //cerr<<"D : "<<D<<endl;
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         // compute force on element
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         //cerr<<"p large : "<<p<<endl;
00781         //cerr<<"F large : "<<f<<endl;
00782 //      for(int i=0;i<12;i+=3)
00783 //      {
00784 //          Vec tmp;
00785 //          v_eq_Ab( tmp, _rotations[elementIndex], Vec( F[i], F[i+1],  F[i+2] ) );
00786 //          cerr<<tmp<<"\t";
00787 //      }
00788 //      cerr<<endl;
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         //erase the stiffness matrix at each time step
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                     // search if the vertex is already take into account by another element
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     //cerr<<"X : "<<X<<endl;
00877 
00878     computeForce( F, X,tetrahedronInfo[i].materialMatrix, tetrahedronInfo[i].strainDisplacementMatrix);
00879 
00880     //cerr<<"F : "<<F<<endl;
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     // positions of the deformed and displaced Tetrahedre in its frame
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     // displacement
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     //cerr<<"D : "<<D<<endl;
00951 
00952     Displacement F;
00953     if(_updateStiffnessMatrix)
00954     {
00955         // shape functions matrix
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     //cerr<<"X : "<<X<<endl;
01003 
01004     computeForce( F, X, tetrahedronInfo[i].materialMatrix, tetrahedronInfo[i].strainDisplacementMatrix);
01005 
01006     //cerr<<"F : "<<F<<endl;
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 /*k*/, unsigned int &offset)
01076 {
01077     // Build Matrix Block for this ForceField
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         // find index of node 1
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                 // find index of node 2
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 } // namespace forcefield
01122 
01123 } // namespace component
01124 
01125 } // namespace sofa
01126 
01127 #endif

Generated on Sun Nov 23 03:13:05 2008 for Sofa by  doxygen 1.5.7.1