TetrahedronFEMForceField.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/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     // shape functions matrix
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     // 0
00131     /*
00132     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;
00133     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;
00134     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;
00135     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;
00136     */
00137     //m_deq( J, 1.2 ); //hack for stability ??
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     /*Real gamma = (youngModulus*poissonRatio) / ((1+poissonRatio)*(1-2*poissonRatio));
00190     Real        mu2 = youngModulus / (1+poissonRatio);
00191     _materialsStiffnesses[i][0][3] = _materialsStiffnesses[i][0][4] =   _materialsStiffnesses[i][0][5] = 0;
00192     _materialsStiffnesses[i][1][3] = _materialsStiffnesses[i][1][4] =   _materialsStiffnesses[i][1][5] = 0;
00193     _materialsStiffnesses[i][2][3] = _materialsStiffnesses[i][2][4] =   _materialsStiffnesses[i][2][5] = 0;
00194     _materialsStiffnesses[i][3][0] = _materialsStiffnesses[i][3][1] = _materialsStiffnesses[i][3][2] = _materialsStiffnesses[i][3][4] = _materialsStiffnesses[i][3][5] = 0;
00195     _materialsStiffnesses[i][4][0] = _materialsStiffnesses[i][4][1] = _materialsStiffnesses[i][4][2] = _materialsStiffnesses[i][4][3] = _materialsStiffnesses[i][4][5] = 0;
00196     _materialsStiffnesses[i][5][0] = _materialsStiffnesses[i][5][1] = _materialsStiffnesses[i][5][2] = _materialsStiffnesses[i][5][3] = _materialsStiffnesses[i][5][4] = 0;
00197     _materialsStiffnesses[i][0][0] = _materialsStiffnesses[i][1][1] = _materialsStiffnesses[i][2][2] = gamma+mu2;
00198     _materialsStiffnesses[i][0][1] = _materialsStiffnesses[i][0][2] = _materialsStiffnesses[i][1][0]
00199                 = _materialsStiffnesses[i][1][2] = _materialsStiffnesses[i][2][0] = _materialsStiffnesses[i][2][1] = gamma;
00200     _materialsStiffnesses[i][3][3] = _materialsStiffnesses[i][4][4] = _materialsStiffnesses[i][5][5] =  mu2;*/
00201 
00202     // divide by 36 times volumes of the element
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; // 36*Volume in the formula
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     // Unit of K = unit of youngModulus / unit of volume = Pa / m^3 = kg m^-4 s^-2
00221     // Unit of J = m^2
00222     // Unit of JKJt =  kg s^-2
00223     // Unit of displacement = m
00224     // Unit of force = kg m s^-2
00225     
00226 #if 0
00227     F = J*(K*(J.multTranspose(Depl)));
00228 #else
00229     /* We have these zeros
00230                                   K[0][3]   K[0][4]   K[0][5]   
00231                                   K[1][3]   K[1][4]   K[1][5]   
00232                                   K[2][3]   K[2][4]   K[2][5]   
00233     K[3][0]   K[3][1]   K[3][2]             K[3][4]   K[3][5]   
00234     K[4][0]   K[4][1]   K[4][2]   K[4][3]             K[4][5]   
00235     K[5][0]   K[5][1]   K[5][2]   K[5][3]   K[5][4]   
00236 
00237 
00238               J[0][1]   J[0][2]             J[0][4]  
00239     J[1][0]             J[1][2]                       J[1][5]  
00240     J[2][0]   J[2][1]             J[2][3]  
00241               J[3][1]   J[3][2]             J[3][4]   
00242     J[4][0]             J[4][2]                       J[4][5]   
00243     J[5][0]   J[5][1]             J[5][3]  
00244               J[6][1]   J[6][2]             J[6][4]   
00245     J[7][0]             J[7][2]                       J[7][5]   
00246     J[8][0]   J[8][1]             J[8][3]  
00247               J[9][1]   J[9][2]             J[9][4]   
00248     J[10][0]            J[10][2]                      J[10][5]  
00249     J[11][0]  J[11][1]            J[11][3] 
00250     */
00251 
00252     VecNoInit<6,Real> JtD;
00253     JtD[0] =   J[ 0][0]*Depl[ 0]+/*J[ 1][0]*Depl[ 1]+  J[ 2][0]*Depl[ 2]+*/
00254                J[ 3][0]*Depl[ 3]+/*J[ 4][0]*Depl[ 4]+  J[ 5][0]*Depl[ 5]+*/
00255                J[ 6][0]*Depl[ 6]+/*J[ 7][0]*Depl[ 7]+  J[ 8][0]*Depl[ 8]+*/
00256                J[ 9][0]*Depl[ 9] /*J[10][0]*Depl[10]+  J[11][0]*Depl[11]*/;
00257     JtD[1] = /*J[ 0][1]*Depl[ 0]+*/J[ 1][1]*Depl[ 1]+/*J[ 2][1]*Depl[ 2]+*/
00258              /*J[ 3][1]*Depl[ 3]+*/J[ 4][1]*Depl[ 4]+/*J[ 5][1]*Depl[ 5]+*/
00259              /*J[ 6][1]*Depl[ 6]+*/J[ 7][1]*Depl[ 7]+/*J[ 8][1]*Depl[ 8]+*/
00260              /*J[ 9][1]*Depl[ 9]+*/J[10][1]*Depl[10] /*J[11][1]*Depl[11]*/;
00261     JtD[2] = /*J[ 0][2]*Depl[ 0]+  J[ 1][2]*Depl[ 1]+*/J[ 2][2]*Depl[ 2]+
00262              /*J[ 3][2]*Depl[ 3]+  J[ 4][2]*Depl[ 4]+*/J[ 5][2]*Depl[ 5]+
00263              /*J[ 6][2]*Depl[ 6]+  J[ 7][2]*Depl[ 7]+*/J[ 8][2]*Depl[ 8]+
00264              /*J[ 9][2]*Depl[ 9]+  J[10][2]*Depl[10]+*/J[11][2]*Depl[11]  ;
00265     JtD[3] =   J[ 0][3]*Depl[ 0]+  J[ 1][3]*Depl[ 1]+/*J[ 2][3]*Depl[ 2]+*/
00266                J[ 3][3]*Depl[ 3]+  J[ 4][3]*Depl[ 4]+/*J[ 5][3]*Depl[ 5]+*/
00267                J[ 6][3]*Depl[ 6]+  J[ 7][3]*Depl[ 7]+/*J[ 8][3]*Depl[ 8]+*/
00268                J[ 9][3]*Depl[ 9]+  J[10][3]*Depl[10] /*J[11][3]*Depl[11]*/;
00269     JtD[4] = /*J[ 0][4]*Depl[ 0]+*/J[ 1][4]*Depl[ 1]+  J[ 2][4]*Depl[ 2]+
00270              /*J[ 3][4]*Depl[ 3]+*/J[ 4][4]*Depl[ 4]+  J[ 5][4]*Depl[ 5]+
00271              /*J[ 6][4]*Depl[ 6]+*/J[ 7][4]*Depl[ 7]+  J[ 8][4]*Depl[ 8]+
00272              /*J[ 9][4]*Depl[ 9]+*/J[10][4]*Depl[10]+  J[11][4]*Depl[11]  ;
00273     JtD[5] =   J[ 0][5]*Depl[ 0]+/*J[ 1][5]*Depl[ 1]*/ J[ 2][5]*Depl[ 2]+
00274                J[ 3][5]*Depl[ 3]+/*J[ 4][5]*Depl[ 4]*/ J[ 5][5]*Depl[ 5]+
00275                J[ 6][5]*Depl[ 6]+/*J[ 7][5]*Depl[ 7]*/ J[ 8][5]*Depl[ 8]+
00276                J[ 9][5]*Depl[ 9]+/*J[10][5]*Depl[10]*/ J[11][5]*Depl[11];
00277 //         cerr<<"TetrahedronFEMForceField<DataTypes>::computeForce, D = "<<Depl<<endl;
00278 //         cerr<<"TetrahedronFEMForceField<DataTypes>::computeForce, JtD = "<<JtD<<endl;
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               /*K[0][3]*JtD[3]+  K[0][4]*JtD[4]+  K[0][5]*JtD[5]*/;
00283     KJtD[1] =   K[1][0]*JtD[0]+  K[1][1]*JtD[1]+  K[1][2]*JtD[2]
00284               /*K[1][3]*JtD[3]+  K[1][4]*JtD[4]+  K[1][5]*JtD[5]*/;
00285     KJtD[2] =   K[2][0]*JtD[0]+  K[2][1]*JtD[1]+  K[2][2]*JtD[2]
00286               /*K[2][3]*JtD[3]+  K[2][4]*JtD[4]+  K[2][5]*JtD[5]*/;
00287     KJtD[3] = /*K[3][0]*JtD[0]+  K[3][1]*JtD[1]+  K[3][2]*JtD[2]+*/
00288                 K[3][3]*JtD[3] /*K[3][4]*JtD[4]+  K[3][5]*JtD[5]*/;
00289     KJtD[4] = /*K[4][0]*JtD[0]+  K[4][1]*JtD[1]+  K[4][2]*JtD[2]+*/
00290               /*K[4][3]*JtD[3]+*/K[4][4]*JtD[4] /*K[4][5]*JtD[5]*/;
00291     KJtD[5] = /*K[5][0]*JtD[0]+  K[5][1]*JtD[1]+  K[5][2]*JtD[2]+*/
00292               /*K[5][3]*JtD[3]+  K[5][4]*JtD[4]+*/K[5][5]*JtD[5]  ;
00293 
00294     F[ 0] =   J[ 0][0]*KJtD[0]+/*J[ 0][1]*KJtD[1]+  J[ 0][2]*KJtD[2]+*/
00295               J[ 0][3]*KJtD[3]+/*J[ 0][4]*KJtD[4]+*/J[ 0][5]*KJtD[5]  ;
00296     F[ 1] = /*J[ 1][0]*KJtD[0]+*/J[ 1][1]*KJtD[1]+/*J[ 1][2]*KJtD[2]+*/
00297               J[ 1][3]*KJtD[3]+  J[ 1][4]*KJtD[4] /*J[ 1][5]*KJtD[5]*/;
00298     F[ 2] = /*J[ 2][0]*KJtD[0]+  J[ 2][1]*KJtD[1]+*/J[ 2][2]*KJtD[2]+
00299             /*J[ 2][3]*KJtD[3]+*/J[ 2][4]*KJtD[4]+  J[ 2][5]*KJtD[5]  ;
00300     F[ 3] =   J[ 3][0]*KJtD[0]+/*J[ 3][1]*KJtD[1]+  J[ 3][2]*KJtD[2]+*/
00301               J[ 3][3]*KJtD[3]+/*J[ 3][4]*KJtD[4]+*/J[ 3][5]*KJtD[5]  ;
00302     F[ 4] = /*J[ 4][0]*KJtD[0]+*/J[ 4][1]*KJtD[1]+/*J[ 4][2]*KJtD[2]+*/
00303               J[ 4][3]*KJtD[3]+  J[ 4][4]*KJtD[4] /*J[ 4][5]*KJtD[5]*/;
00304     F[ 5] = /*J[ 5][0]*KJtD[0]+  J[ 5][1]*KJtD[1]+*/J[ 5][2]*KJtD[2]+
00305             /*J[ 5][3]*KJtD[3]+*/J[ 5][4]*KJtD[4]+  J[ 5][5]*KJtD[5]  ;
00306     F[ 6] =   J[ 6][0]*KJtD[0]+/*J[ 6][1]*KJtD[1]+  J[ 6][2]*KJtD[2]+*/
00307               J[ 6][3]*KJtD[3]+/*J[ 6][4]*KJtD[4]+*/J[ 6][5]*KJtD[5]  ;
00308     F[ 7] = /*J[ 7][0]*KJtD[0]+*/J[ 7][1]*KJtD[1]+/*J[ 7][2]*KJtD[2]+*/
00309               J[ 7][3]*KJtD[3]+  J[ 7][4]*KJtD[4] /*J[ 7][5]*KJtD[5]*/;
00310     F[ 8] = /*J[ 8][0]*KJtD[0]+  J[ 8][1]*KJtD[1]+*/J[ 8][2]*KJtD[2]+
00311             /*J[ 8][3]*KJtD[3]+*/J[ 8][4]*KJtD[4]+  J[ 8][5]*KJtD[5]  ;
00312     F[ 9] =   J[ 9][0]*KJtD[0]+/*J[ 9][1]*KJtD[1]+  J[ 9][2]*KJtD[2]+*/
00313               J[ 9][3]*KJtD[3]+/*J[ 9][4]*KJtD[4]+*/J[ 9][5]*KJtD[5]  ;
00314     F[10] = /*J[10][0]*KJtD[0]+*/J[10][1]*KJtD[1]+/*J[10][2]*KJtD[2]+*/
00315               J[10][3]*KJtD[3]+  J[10][4]*KJtD[4] /*J[10][5]*KJtD[5]*/;
00316     F[11] = /*J[11][0]*KJtD[0]+  J[11][1]*KJtD[1]+*/J[11][2]*KJtD[2]+
00317             /*J[11][3]*KJtD[3]+*/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     // Unit of K = unit of youngModulus / unit of volume = Pa / m^3 = kg m^-4 s^-2
00326     // Unit of J = m^2
00327     // Unit of JKJt =  kg s^-2
00328     // Unit of displacement = m
00329     // Unit of force = kg m s^-2
00330     
00331 #if 0
00332     F = J*(K*(J.multTranspose(Depl)));
00333     F *= fact;
00334 #else
00335     /* We have these zeros
00336                                   K[0][3]   K[0][4]   K[0][5]   
00337                                   K[1][3]   K[1][4]   K[1][5]   
00338                                   K[2][3]   K[2][4]   K[2][5]   
00339     K[3][0]   K[3][1]   K[3][2]             K[3][4]   K[3][5]   
00340     K[4][0]   K[4][1]   K[4][2]   K[4][3]             K[4][5]   
00341     K[5][0]   K[5][1]   K[5][2]   K[5][3]   K[5][4]   
00342 
00343 
00344               J[0][1]   J[0][2]             J[0][4]  
00345     J[1][0]             J[1][2]                       J[1][5]  
00346     J[2][0]   J[2][1]             J[2][3]  
00347               J[3][1]   J[3][2]             J[3][4]   
00348     J[4][0]             J[4][2]                       J[4][5]   
00349     J[5][0]   J[5][1]             J[5][3]  
00350               J[6][1]   J[6][2]             J[6][4]   
00351     J[7][0]             J[7][2]                       J[7][5]   
00352     J[8][0]   J[8][1]             J[8][3]  
00353               J[9][1]   J[9][2]             J[9][4]   
00354     J[10][0]            J[10][2]                      J[10][5]  
00355     J[11][0]  J[11][1]            J[11][3] 
00356     */
00357 
00358     VecNoInit<6,Real> JtD;
00359     JtD[0] =   J[ 0][0]*Depl[ 0]+/*J[ 1][0]*Depl[ 1]+  J[ 2][0]*Depl[ 2]+*/
00360                J[ 3][0]*Depl[ 3]+/*J[ 4][0]*Depl[ 4]+  J[ 5][0]*Depl[ 5]+*/
00361                J[ 6][0]*Depl[ 6]+/*J[ 7][0]*Depl[ 7]+  J[ 8][0]*Depl[ 8]+*/
00362                J[ 9][0]*Depl[ 9] /*J[10][0]*Depl[10]+  J[11][0]*Depl[11]*/;
00363     JtD[1] = /*J[ 0][1]*Depl[ 0]+*/J[ 1][1]*Depl[ 1]+/*J[ 2][1]*Depl[ 2]+*/
00364              /*J[ 3][1]*Depl[ 3]+*/J[ 4][1]*Depl[ 4]+/*J[ 5][1]*Depl[ 5]+*/
00365              /*J[ 6][1]*Depl[ 6]+*/J[ 7][1]*Depl[ 7]+/*J[ 8][1]*Depl[ 8]+*/
00366              /*J[ 9][1]*Depl[ 9]+*/J[10][1]*Depl[10] /*J[11][1]*Depl[11]*/;
00367     JtD[2] = /*J[ 0][2]*Depl[ 0]+  J[ 1][2]*Depl[ 1]+*/J[ 2][2]*Depl[ 2]+
00368              /*J[ 3][2]*Depl[ 3]+  J[ 4][2]*Depl[ 4]+*/J[ 5][2]*Depl[ 5]+
00369              /*J[ 6][2]*Depl[ 6]+  J[ 7][2]*Depl[ 7]+*/J[ 8][2]*Depl[ 8]+
00370              /*J[ 9][2]*Depl[ 9]+  J[10][2]*Depl[10]+*/J[11][2]*Depl[11]  ;
00371     JtD[3] =   J[ 0][3]*Depl[ 0]+  J[ 1][3]*Depl[ 1]+/*J[ 2][3]*Depl[ 2]+*/
00372                J[ 3][3]*Depl[ 3]+  J[ 4][3]*Depl[ 4]+/*J[ 5][3]*Depl[ 5]+*/
00373                J[ 6][3]*Depl[ 6]+  J[ 7][3]*Depl[ 7]+/*J[ 8][3]*Depl[ 8]+*/
00374                J[ 9][3]*Depl[ 9]+  J[10][3]*Depl[10] /*J[11][3]*Depl[11]*/;
00375     JtD[4] = /*J[ 0][4]*Depl[ 0]+*/J[ 1][4]*Depl[ 1]+  J[ 2][4]*Depl[ 2]+
00376              /*J[ 3][4]*Depl[ 3]+*/J[ 4][4]*Depl[ 4]+  J[ 5][4]*Depl[ 5]+
00377              /*J[ 6][4]*Depl[ 6]+*/J[ 7][4]*Depl[ 7]+  J[ 8][4]*Depl[ 8]+
00378              /*J[ 9][4]*Depl[ 9]+*/J[10][4]*Depl[10]+  J[11][4]*Depl[11]  ;
00379     JtD[5] =   J[ 0][5]*Depl[ 0]+/*J[ 1][5]*Depl[ 1]*/ J[ 2][5]*Depl[ 2]+
00380                J[ 3][5]*Depl[ 3]+/*J[ 4][5]*Depl[ 4]*/ J[ 5][5]*Depl[ 5]+
00381                J[ 6][5]*Depl[ 6]+/*J[ 7][5]*Depl[ 7]*/ J[ 8][5]*Depl[ 8]+
00382                J[ 9][5]*Depl[ 9]+/*J[10][5]*Depl[10]*/ J[11][5]*Depl[11];
00383 //         cerr<<"TetrahedronFEMForceField<DataTypes>::computeForce, D = "<<Depl<<endl;
00384 //         cerr<<"TetrahedronFEMForceField<DataTypes>::computeForce, JtD = "<<JtD<<endl;
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               /*K[0][3]*JtD[3]+  K[0][4]*JtD[4]+  K[0][5]*JtD[5]*/;
00389     KJtD[1] =   K[1][0]*JtD[0]+  K[1][1]*JtD[1]+  K[1][2]*JtD[2]
00390               /*K[1][3]*JtD[3]+  K[1][4]*JtD[4]+  K[1][5]*JtD[5]*/;
00391     KJtD[2] =   K[2][0]*JtD[0]+  K[2][1]*JtD[1]+  K[2][2]*JtD[2]
00392               /*K[2][3]*JtD[3]+  K[2][4]*JtD[4]+  K[2][5]*JtD[5]*/;
00393     KJtD[3] = /*K[3][0]*JtD[0]+  K[3][1]*JtD[1]+  K[3][2]*JtD[2]+*/
00394                 K[3][3]*JtD[3] /*K[3][4]*JtD[4]+  K[3][5]*JtD[5]*/;
00395     KJtD[4] = /*K[4][0]*JtD[0]+  K[4][1]*JtD[1]+  K[4][2]*JtD[2]+*/
00396               /*K[4][3]*JtD[3]+*/K[4][4]*JtD[4] /*K[4][5]*JtD[5]*/;
00397     KJtD[5] = /*K[5][0]*JtD[0]+  K[5][1]*JtD[1]+  K[5][2]*JtD[2]+*/
00398               /*K[5][3]*JtD[3]+  K[5][4]*JtD[4]+*/K[5][5]*JtD[5]  ;
00399 
00400     KJtD *= fact;
00401 
00402     F[ 0] =   J[ 0][0]*KJtD[0]+/*J[ 0][1]*KJtD[1]+  J[ 0][2]*KJtD[2]+*/
00403               J[ 0][3]*KJtD[3]+/*J[ 0][4]*KJtD[4]+*/J[ 0][5]*KJtD[5]  ;
00404     F[ 1] = /*J[ 1][0]*KJtD[0]+*/J[ 1][1]*KJtD[1]+/*J[ 1][2]*KJtD[2]+*/
00405               J[ 1][3]*KJtD[3]+  J[ 1][4]*KJtD[4] /*J[ 1][5]*KJtD[5]*/;
00406     F[ 2] = /*J[ 2][0]*KJtD[0]+  J[ 2][1]*KJtD[1]+*/J[ 2][2]*KJtD[2]+
00407             /*J[ 2][3]*KJtD[3]+*/J[ 2][4]*KJtD[4]+  J[ 2][5]*KJtD[5]  ;
00408     F[ 3] =   J[ 3][0]*KJtD[0]+/*J[ 3][1]*KJtD[1]+  J[ 3][2]*KJtD[2]+*/
00409               J[ 3][3]*KJtD[3]+/*J[ 3][4]*KJtD[4]+*/J[ 3][5]*KJtD[5]  ;
00410     F[ 4] = /*J[ 4][0]*KJtD[0]+*/J[ 4][1]*KJtD[1]+/*J[ 4][2]*KJtD[2]+*/
00411               J[ 4][3]*KJtD[3]+  J[ 4][4]*KJtD[4] /*J[ 4][5]*KJtD[5]*/;
00412     F[ 5] = /*J[ 5][0]*KJtD[0]+  J[ 5][1]*KJtD[1]+*/J[ 5][2]*KJtD[2]+
00413             /*J[ 5][3]*KJtD[3]+*/J[ 5][4]*KJtD[4]+  J[ 5][5]*KJtD[5]  ;
00414     F[ 6] =   J[ 6][0]*KJtD[0]+/*J[ 6][1]*KJtD[1]+  J[ 6][2]*KJtD[2]+*/
00415               J[ 6][3]*KJtD[3]+/*J[ 6][4]*KJtD[4]+*/J[ 6][5]*KJtD[5]  ;
00416     F[ 7] = /*J[ 7][0]*KJtD[0]+*/J[ 7][1]*KJtD[1]+/*J[ 7][2]*KJtD[2]+*/
00417               J[ 7][3]*KJtD[3]+  J[ 7][4]*KJtD[4] /*J[ 7][5]*KJtD[5]*/;
00418     F[ 8] = /*J[ 8][0]*KJtD[0]+  J[ 8][1]*KJtD[1]+*/J[ 8][2]*KJtD[2]+
00419             /*J[ 8][3]*KJtD[3]+*/J[ 8][4]*KJtD[4]+  J[ 8][5]*KJtD[5]  ;
00420     F[ 9] =   J[ 9][0]*KJtD[0]+/*J[ 9][1]*KJtD[1]+  J[ 9][2]*KJtD[2]+*/
00421               J[ 9][3]*KJtD[3]+/*J[ 9][4]*KJtD[4]+*/J[ 9][5]*KJtD[5]  ;
00422     F[10] = /*J[10][0]*KJtD[0]+*/J[10][1]*KJtD[1]+/*J[10][2]*KJtD[2]+*/
00423               J[10][3]*KJtD[3]+  J[10][4]*KJtD[4] /*J[10][5]*KJtD[5]*/;
00424     F[11] = /*J[11][0]*KJtD[0]+  J[11][1]*KJtD[1]+*/J[11][2]*KJtD[2]+
00425             /*J[11][3]*KJtD[3]+*/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     //std::cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceSmall"<<std::endl;
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     // displacements
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 /*        std::cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceSmall, displacement"<<D<<std::endl;
00464         std::cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceSmall, straindisplacement"<<_strainDisplacements[elementIndex]<<std::endl;
00465         std::cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceSmall, material"<<_materialsStiffnesses[elementIndex]<<std::endl;*/
00466     
00467     // compute force on element
00468     Displacement F;
00469     
00470     if(!_assembling)
00471     {
00472         computeForce( F, D, _materialsStiffnesses[elementIndex], _strainDisplacements[elementIndex] );
00473                 //std::cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceSmall, force"<<F<<std::endl;
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         //erase the stiffness matrix at each time step
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                     //cerr<<row<<" "<<col<<endl;
00507                     
00508                     //typename CompressedValue::iterator result = _stiffnesses[row].find(col);
00509                     
00510                     
00511                     // search if the vertex is already take into account by another element
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         /*for(unsigned int i=0;i<_stiffnesses.size();++i)
00528             for(typename CompressedValue::iterator it=_stiffnesses[i].begin();it!=_stiffnesses[i].end();++it)
00529                 cerr<<i<<" "<<(*it).first<<"   "<<(*it).second<<"   "<<JKJt[i][(*it).first]<<endl;*/
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     // first vector on first edge
00578     // second vector in the plane of the two first edges
00579     // third vector orthogonal to first and second  
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 //HACK get rotation for fast contact handling with simplified compliance
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     //R = _rotations[_rotationIdx[nodeIdx]];
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     // Rotation matrix (initial Tetrahedre/world)
00628     // first vector on first edge
00629     // second vector in the plane of the two first edges
00630     // third vector orthogonal to first and second
00631     Transformation R_0_1;
00632     computeRotationLarge( R_0_1, _initialPoints, a, b, c);
00633     _initialRotations[i].transpose(R_0_1);
00634 
00635     //save the element index as the node index 
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 //  cerr<<"a,b,c : "<<a<<" "<<b<<" "<<c<<endl;
00647 //  cerr<<"_initialPoints : "<<_initialPoints<<endl;
00648 //  cerr<<"R_0_1 large : "<<R_0_1<<endl;
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 //  cerr<<"_rotatedInitialElements : "<<_rotatedInitialElements<<endl;
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     // Rotation matrix (deformed and displaced Tetrahedron/world)
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     //cerr<<"R_0_2 large : "<<R_0_2<<endl;
00671 
00672     // positions of the deformed and displaced Tetrahedron in its frame
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     // displacement
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     //cerr<<"D : "<<D<<endl;
00698 
00699     Displacement F;
00700     if(_updateStiffnessMatrix)
00701     {
00702         //cerr<<"TetrahedronFEMForceField<DataTypes>::accumulateForceLarge, update stiffness matrix"<<endl;
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         // compute force on element
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         //cerr<<"p large : "<<p<<endl;
00725         //cerr<<"F large : "<<f<<endl;
00726 //      for(int i=0;i<12;i+=3)
00727 //      {
00728 //          Vec tmp;
00729 //          v_eq_Ab( tmp, _rotations[elementIndex], Vec( F[i], F[i+1],  F[i+2] ) );
00730 //          cerr<<tmp<<"\t";
00731 //      }
00732 //      cerr<<endl;
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         //erase the stiffness matrix at each time step
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                     // search if the vertex is already take into account by another element
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     //cerr<<"X : "<<X<<endl;
00821 
00822     computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i], fact );
00823 
00824     //cerr<<"F : "<<F<<endl;
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     //save the element index as the node index 
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     // positions of the deformed and displaced Tetrahedre in its frame
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     // displacement
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     //cerr<<"D : "<<D<<endl;
00901 
00902     Displacement F;
00903     if(_updateStiffnessMatrix)
00904     {
00905         // shape functions matrix
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     //Coord x_2;
00929 
00930     //x_2 = R_0_2*x[a];
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];//x_2[0];
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];//x_2[1];
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];//x_2[2];
00934 
00935     //x_2 = R_0_2*x[b];
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];//x_2[0];
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];//x_2[1];
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];//x_2[2];
00939 
00940     //x_2 = R_0_2*x[c];
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];//x_2[0];
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];//x_2[1];
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];//x_2[2];
00944 
00945     //x_2 = R_0_2*x[d];
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];//x_2[0];
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];//x_2[1];
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];//x_2[2];
00949 
00950     Displacement F;
00951 
00952     //cerr<<"X : "<<X<<endl;
00953 
00954     computeForce( F, X, _materialsStiffnesses[i], _strainDisplacements[i], fact );
00955 
00956     //cerr<<"F : "<<F<<endl;
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         // These values are only correct if the mesh is a grid topology
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         // Tesselation of each cube into 6 tetrahedra
01035         tetras->reserve(nbcubes*6);
01036         for (int i=0;i<nbcubes;i++)
01037         {
01038             // if (flags && !flags->isCubeActive(i)) continue;
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             { // swap all points on the X edges
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             { // swap all points on the Y edges
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             { // swap all points on the Z edges
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         // Tesselation of each cube into 5 tetrahedra
01089         tetras->reserve(nbcubes*5);
01090         for (int i=0;i<nbcubes;i++)
01091         {
01092             MeshTopology::Cube c = _mesh->getCube(i);
01093             int sym = 0;
01094             if ((i%nx)&1) sym+=1;
01095             if (((i/nx)%ny)&1) sym+=2;
01096             if ((i/(nx*ny))&1) sym+=4;
01097             tetras->push_back(make_array(c[1^sym],c[0^sym],c[3^sym],c[5^sym]));
01098             tetras->push_back(make_array(c[2^sym],c[3^sym],c[0^sym],c[6^sym]));
01099             tetras->push_back(make_array(c[4^sym],c[5^sym],c[6^sym],c[0^sym]));
01100             tetras->push_back(make_array(c[7^sym],c[6^sym],c[5^sym],c[3^sym]));
01101             tetras->push_back(make_array(c[0^sym],c[3^sym],c[5^sym],c[6^sym]));
01102         }
01103         */
01104         _indexedElements = tetras;
01105     }
01106     /*if (_mesh->hasPos())
01107     { // use positions from topology
01108     VecCoord& p = *f_initialPoints.beginEdit();
01109         p.resize(_mesh->getNbPoints());
01110         for (unsigned int i=0;i<p.size();i++)
01111         {
01112             p[i] = Coord((Real)_mesh->getPX(i),(Real)_mesh->getPY(i),(Real)_mesh->getPZ(i));
01113         }
01114     }
01115     else
01116     {
01117     if (f_initialPoints.getValue().size() == 0)
01118     {
01119           VecCoord& p = *this->mstate->getX0();
01120           (*f_initialPoints.beginEdit()) = p;
01121         }
01122     }*/
01123 
01124     reinit(); // compute per-element stiffness matrices and other precomputed values
01125     
01126 //     std::cout << "TetrahedronFEMForceField: init OK, "<<_indexedElements->size()<<" tetra."<<std::endl;
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& /*v*/)
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 /*bFactor*/)
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         //R.transpose();
01372         Deriv v;
01373         // x
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         // y
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         // z
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     // Build Matrix Block for this ForceField
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         // find index of node 1
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                 // find index of node 2
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 } // namespace forcefield
01449 
01450 } // namespace component
01451 
01452 } // namespace sofa
01453 
01454 #endif

Generated on Sun Nov 23 03:14:20 2008 for Sofa by  doxygen 1.5.7.1