PMLFemForceField.cpp

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 
00026 /***************************************************************************
00027  *                                                                         *
00028  *   This program is free software; you can redistribute it and/or modify  *
00029  *   it under the terms of the GNU General Public License as published by  *
00030  *   the Free Software Foundation; either version 2 of the License, or     *
00031  *   (at your option) any later version.                                   *
00032  *                                                                         *
00033  ***************************************************************************/
00034 
00035 #include "PMLFemForceField.h"
00036 
00037 #include <sofa/component/MechanicalObject.h>
00038 #include <sofa/component/forcefield/TetrahedronFEMForceField.h>
00039 #include <sofa/component/forcefield/StiffSpringForceField.h>
00040 #include <sofa/component/mass/UniformMass.h>
00041 #include <sofa/component/mass/DiagonalMass.h>
00042 #include <sofa/component/mapping/IdentityMapping.h>
00043 #include <sofa/component/topology/MeshTopology.h>
00044 using namespace sofa::component::mass;
00045 using namespace sofa::component::mapping;
00046 using namespace sofa::component::forcefield;
00047 using namespace sofa::component::topology;
00048 using namespace sofa::component;
00049 
00050 #include <PhysicalModel.h>
00051 #include <MultiComponent.h>
00052 #include <CellProperties.h>
00053 #include <PMLTransform.h>
00054 
00055 namespace sofa
00056 {
00057 
00058 namespace filemanager
00059 {
00060 
00061 namespace pml
00062 {
00063 
00064 PMLFemForceField::PMLFemForceField(StructuralComponent* body, GNode * parent)
00065 {
00066     parentNode = parent;
00067     //get the parameters
00068     collisionsON = body->getProperties()->getBool("collision");
00069     name = body->getProperties()->getName();
00070 
00071     if(body->getProperties()->getString("mass") != "")
00072         initMass(body->getProperties()->getString("mass"));
00073 
00074     if(body->getProperties()->getString("density") != "")
00075         initDensity(body->getProperties()->getString("density"));
00076 
00077     young = body->getProperties()->getDouble("young");
00078     poisson = body->getProperties()->getDouble("poisson");
00079     deformationType = body->getProperties()->getString("deformation");
00080     solverName = body->getProperties()->getString("solver");
00081 
00082     //create the structure
00083     createMechanicalState(body);
00084     createTopology(body);
00085     createMass(body);
00086     createVisualModel(body);
00087     createForceField();
00088     createCollisionModel();
00089     createSolver();
00090 }
00091 
00092 
00093 PMLFemForceField::~PMLFemForceField()
00094 {
00095     if(mmodel) delete mmodel; 
00096     //if(pmodel) delete pmodel;
00097     //if(lmodel) delete lmodel;
00098     if(tmodel) delete tmodel;
00099 }
00100 
00101 
00102 //read the mass parameter
00103 void PMLFemForceField::initMass(string m)
00104 {
00105     int pos;
00106     while(!m.empty()) {
00107         pos = m.find(' ', 0);
00108         if(pos != 0) {
00109             string s=m.substr(0,pos);
00110             SReal d=atof(s.c_str());
00111             massList.push_back(d);
00112             m.erase(0,pos);
00113         }else
00114             m.erase(0,1);
00115     }
00116 }
00117 
00118 void PMLFemForceField::initDensity(string m)
00119 {
00120     int pos;
00121     while(!m.empty()) {
00122         pos = m.find(' ', 0);
00123         if(pos != 0) {
00124             string s=m.substr(0,pos);
00125             SReal d=atof(s.c_str());
00126             density.push_back(d);
00127             m.erase(0,pos);
00128         }else
00129             m.erase(0,1);
00130     }
00131 }
00132 
00133 
00134 //convenient method to tesselate a hexahedron to 5 tetrahedron
00135 // used by createTopology method
00136 BaseMeshTopology::Tetra * PMLFemForceField::Tesselate(Cell* pCell)
00137  {
00138    BaseMeshTopology::Tetra *tet = new BaseMeshTopology::Tetra[5];
00139    Atom *pAtom;
00140    int index[8];
00141 
00142    for (int i(0) ; i<8 ; i++) {
00143         pAtom = (Atom*)(pCell->getStructure(i));
00144         index[i] = AtomsToDOFsIndexes[pAtom->getIndex()];
00145    }
00146 
00147    tet[0][0]=index[0]; tet[0][1]=index[1]; tet[0][2]=index[4]; tet[0][3]=index[3];
00148    tet[1][0]=index[2]; tet[1][1]=index[3]; tet[1][2]=index[6]; tet[1][3]=index[1];
00149    tet[2][0]=index[5]; tet[2][1]=index[4]; tet[2][2]=index[1]; tet[2][3]=index[6];
00150    tet[3][0]=index[7]; tet[3][1]=index[6]; tet[3][2]=index[3]; tet[3][3]=index[4];
00151    tet[4][0]=index[1]; tet[4][1]=index[6]; tet[4][2]=index[4]; tet[4][3]=index[3];
00152 
00153    return tet;
00154 }
00155 
00156 Vector3 PMLFemForceField::getDOF(unsigned int index)
00157 {
00158     return (*((MechanicalState<Vec3Types>*)mmodel)->getX())[index];
00159 }
00160 
00161 //creation of the mechanical model
00162 //each pml atom constituing the body correspond to a DOF
00163 void PMLFemForceField::createMechanicalState(StructuralComponent* body)
00164 {
00165     mmodel = new MechanicalObject<Vec3Types>;
00166     StructuralComponent* atoms = body->getAtoms();
00167     mmodel->resize(atoms->getNumberOfStructures());
00168     Atom* pAtom;
00169 
00170     SReal pos[3];
00171     for (unsigned int i(0) ; i<atoms->getNumberOfStructures() ; i++) {
00172         pAtom = (Atom*) (atoms->getStructure(i));
00173         pAtom->getPosition(pos);
00174         AtomsToDOFsIndexes.insert(std::pair <unsigned int, unsigned int>(pAtom->getIndex(),i));
00175         (*((MechanicalState<Vec3Types>*)mmodel)->getX())[i] = Vector3(pos[0],pos[1],pos[2]);
00176     }
00177 
00178     parentNode->addObject(mmodel);
00179 
00180 }
00181 
00182 
00183 // creation of the topolgy
00184 // topology constituted exclusively by tetrahedrons 
00185 // --> if there is hexahedrons, they are tesselated in 5 tetrahedron
00186 void PMLFemForceField::createTopology(StructuralComponent* body)
00187 {
00188     topology = new MeshTopology();
00189     ((BaseMeshTopology*)topology)->clear();
00190 
00191     unsigned int nbCells = body->getNumberOfCells();
00192     BaseMeshTopology::Tetra * tet;
00193     BaseMeshTopology::Line * line;
00194     Cell * pCell;
00195     Atom * pAtom;
00196 
00197     //for each pml cell, build 1 or 5 tetrahedrons
00198     for (unsigned int cid(0) ; cid<nbCells ; cid++) {
00199         pCell = body->getCell(cid);
00200         switch(pCell->getProperties()->getType()) {
00201 
00202             case StructureProperties::HEXAHEDRON :
00203                 tet = Tesselate(pCell);
00204                 for (unsigned int p(0) ; p<5 ; p++) {
00205                     ((BaseMeshTopology::SeqTetras&)((BaseMeshTopology*)topology)->getTetras()).push_back(tet[p]);
00206                     for (unsigned int l1=0 ; l1<4 ; l1++) {
00207                         for (unsigned int l2=l1+1 ; l2<4 ; l2++) {
00208                             line = new BaseMeshTopology::Line;
00209                             (*line)[0] = tet[p][l1]; 
00210                             (*line)[1] = tet[p][l2];
00211                             ((BaseMeshTopology::SeqLines&)((BaseMeshTopology*)topology)->getLines()).push_back(*line);
00212                         }
00213                     }
00214                 }
00215                 break;
00216 
00217             case StructureProperties::TETRAHEDRON :
00218                 tet = new BaseMeshTopology::Tetra;
00219                 for (unsigned int i(0) ; i<4 ; i++) {
00220                     pAtom = (Atom*)(pCell->getStructure(i));
00221                     (*tet)[i] = AtomsToDOFsIndexes[pAtom->getIndex()];
00222                     for (unsigned int l1=0 ; l1<4 ; l1++) {
00223                         for (unsigned int l2=l1+1 ; l2<4 ; l2++) {
00224                             line = new BaseMeshTopology::Line;
00225                             (*line)[0] = (*tet)[l1]; 
00226                             (*line)[1] = (*tet)[l2];
00227                             ((BaseMeshTopology::SeqLines&)((BaseMeshTopology*)topology)->getLines()).push_back(*line);
00228                         }
00229                     }
00230                 }
00231                 ((BaseMeshTopology::SeqTetras&)((BaseMeshTopology*)topology)->getTetras()).push_back(*tet);
00232                 break;
00233                 
00234             default : break;
00235 
00236         }
00237     }
00238     parentNode->addObject(topology);
00239 }
00240 
00241 
00242 //creation of the mass 
00243 //normaly there 1 value OR nbDOFs values (OR 0 if not specified)
00244 void PMLFemForceField::createMass(StructuralComponent* body)
00245 {
00246     //if no mass specified...
00247     if (massList.size() == 0) {
00248         //...normally density is!
00249         if (density.size() != 0) {
00250             //BUILDING WITH DENSITY PROPERTY
00251             if (density.size() > 1 && density.size() != ((MechanicalState<Vec3Types>*)mmodel)->getX()->size()) {
00252                 cerr<<"WARNING building "<<name<<" object : density property not properly defined."<<endl;
00253                 return;
00254             }
00255             else {
00256                 //init the mass list
00257                 for (unsigned int i=0 ; i<((MechanicalState<Vec3Types>*)mmodel)->getX()->size() ; i++)
00258                     massList.push_back(0.0);
00259 
00260                 SReal m;
00261                 Cell * pCell;
00262                 Atom * pAtom;
00263 
00264                 //for each atom of each cell...
00265                 for (unsigned int cid(0) ; cid<body->getNumberOfCells(); cid++) {
00266                     pCell = body->getCell(cid);
00267                     SReal volumeCell = pCell->volume();
00268                     for (unsigned int j(0) ; j< pCell->getNumberOfStructures() ; j++) {
00269                         pAtom = (Atom*)(pCell->getStructure(j));
00270                         SReal dens = density.size()>1?density[AtomsToDOFsIndexes[pAtom->getIndex()]]:density[0];
00271                         //mass of atom += atom density * cell volume / nb atoms in cell
00272                         m = dens * volumeCell / pCell->getNumberOfStructures();
00273                         massList[AtomsToDOFsIndexes[pAtom->getIndex()]] += m;
00274                     }
00275                 }
00276                 
00277                 mass = new DiagonalMass<Vec3Types,SReal>;
00278                 for (unsigned int im=0 ; im<massList.size() ; im++) {
00279                     ((DiagonalMass<Vec3Types,SReal>*)mass)->addMass( massList[im] );
00280                 }
00281             }
00282         }
00283     } //BUILDING WITH MASS PROPERTY
00284     else {
00285         //if there is 1 value --> uniform mass for all the model
00286         if (massList.size() == 1){
00287             mass = new UniformMass<Vec3Types,SReal>;
00288             ((UniformMass<Vec3Types,SReal>*)mass)->setMass( massList[0] );
00289         }
00290         else {
00291             //if there nbDofs values --> diagonal mass (one value for each dof)
00292             if (massList.size() == ((MechanicalState<Vec3Types>*)mmodel)->getX()->size()) {
00293                 mass = new DiagonalMass<Vec3Types,SReal>;
00294                 for (unsigned int i=0 ; i<massList.size() ; i++) {
00295                     ((DiagonalMass<Vec3Types,SReal>*)mass)->addMass( massList[i] );
00296                 }
00297             }
00298             else    //else we don't build mass...
00299                 cerr<<"WARNING building "<<name<<" object : mass property not properly defined."<<endl;
00300         }
00301     }
00302     if (mass)
00303         parentNode->addObject(mass);
00304 }
00305 
00306 
00307 void PMLFemForceField::createVisualModel(StructuralComponent* body)
00308 {
00309     // ADD EXTERN FACETS TO TOPOLOGY
00310     MultiComponent * mc = PMLTransform::generateExternalSurface(body);
00311     StructuralComponent  * extFacets = (StructuralComponent*) mc->getSubComponent(0);
00312 
00313     if (!topology)
00314         topology = new MeshTopology();
00315 
00316     Cell * pCell;
00317     Atom * pAtom;
00318     BaseMeshTopology::Quad * quad;
00319     BaseMeshTopology::Triangle * triangle;
00320 
00321     for (unsigned int i=0 ; i< extFacets->getNumberOfStructures() ; i++)
00322     {
00323         pCell = extFacets->getCell(i);
00324         switch(pCell->getProperties()->getType())
00325         {
00326             case StructureProperties::QUAD :
00327                 quad = new BaseMeshTopology::Quad;
00328                 for (unsigned int j(0) ; j<4 ; j++) {
00329                     pAtom = (Atom*)(pCell->getStructure(j));
00330                     (*quad)[j] = AtomsToDOFsIndexes[pAtom->getIndex()];
00331                 }
00332                 ((BaseMeshTopology::SeqQuads&)((BaseMeshTopology*)topology)->getQuads()).push_back(*quad);
00333                 break;
00334 
00335             case StructureProperties::TRIANGLE :
00336                 triangle = new BaseMeshTopology::Triangle;
00337                 for (unsigned int j(0) ; j<3 ; j++) {
00338                     pAtom = (Atom*)(pCell->getStructure(j));
00339                     (*triangle)[j] = AtomsToDOFsIndexes[pAtom->getIndex()];
00340                 }
00341                 ((BaseMeshTopology::SeqTriangles&)((BaseMeshTopology*)topology)->getTriangles()).push_back(*triangle);
00342                 break;          
00343                 
00344                 default : break;
00345         }
00346     }
00347 
00348     //CREATE THE VISUAL MODEL
00349     OglModel * vmodel = new OglModel;
00350 
00351     double * color = body->getColor();
00352     vmodel->setColor((float)color[0], (float)color[1], (float)color[2], (float)color[3]);
00353     vmodel->load("","","");
00354     BaseMapping * mapping = new IdentityMapping< Mapping< State<Vec3Types>, MappedModel< ExtVectorTypes< Vec<3,GLfloat>, Vec<3,GLfloat> > > > >((MechanicalState<Vec3Types>*)mmodel, vmodel);
00355     parentNode->addObject(mapping);
00356     parentNode->addObject(vmodel);
00357 
00358 }
00359 
00360 
00361 //create a TetrahedronFEMForceField
00362 void PMLFemForceField::createForceField()
00363 {
00364     forcefield = new TetrahedronFEMForceField<Vec3Types>;
00365     //if(poisson==0.0)poisson=0.49;
00366     //if(young==0.0) young=5000.0;
00367 
00368     ((TetrahedronFEMForceField<Vec3Types>*)forcefield)->setPoissonRatio(poisson);
00369 
00370     ((TetrahedronFEMForceField<Vec3Types>*)forcefield)->setYoungModulus(young);
00371 
00372     if(deformationType== "SMALL")
00373         ((TetrahedronFEMForceField<Vec3Types>*)forcefield)->setMethod(0);
00374     if(deformationType== "LARGE") 
00375         ((TetrahedronFEMForceField<Vec3Types>*)forcefield)->setMethod(1);
00376     if(deformationType== "POLAR") 
00377         ((TetrahedronFEMForceField<Vec3Types>*)forcefield)->setMethod(2);
00378 
00379     parentNode->addObject(forcefield);
00380 }
00381 
00382 
00383 void PMLFemForceField::createCollisionModel()
00384 {
00385     if (collisionsON) {
00386         tmodel = new TriangleModel;
00387         //lmodel = new LineModel;
00388         //pmodel = new PointModel;
00389     
00390         parentNode->addObject( tmodel);
00391         //parentNode->addObject( lmodel );
00392         //parentNode->addObject( pmodel );
00393 
00394         tmodel->init();
00395         //lmodel->init();
00396         //pmodel->init();
00397     }
00398 }
00399 
00400 
00401 bool PMLFemForceField::FusionBody(PMLBody* body)
00402 {
00403     PMLFemForceField * femBody = (PMLFemForceField * )body;
00404     std::map<unsigned int, unsigned int> oldToNewIndex;
00405 
00406     //-----  Fusion Mechanical Model
00407     map<unsigned int, unsigned int>::iterator it = femBody->AtomsToDOFsIndexes.begin();
00408     map<unsigned int, unsigned int>::iterator itt;
00409     unsigned int X1size = ((MechanicalState<Vec3Types>*)mmodel)->getX()->size();
00410     while (it !=  femBody->AtomsToDOFsIndexes.end()) 
00411     {
00412         //if femBody's index doesn't exist in current list, we insert it
00413         if ( (itt = this->AtomsToDOFsIndexes.find( (*it).first)) == this->AtomsToDOFsIndexes.end() ){
00414             int cpt = ((MechanicalState<Vec3Types>*)mmodel)->getX()->size();
00415             mmodel->resize( cpt+1);
00416             this->AtomsToDOFsIndexes.insert(std::pair<unsigned int, unsigned int>((*it).first, cpt ));
00417             oldToNewIndex.insert(std::pair<unsigned int, unsigned int>((*it).second, cpt ));
00418             (*((MechanicalState<Vec3Types>*)mmodel)->getX())[cpt] = (*((MechanicalState<Vec3Types>*)(femBody->getMechanicalState()))->getX())[(*it).second];
00419         }
00420         else
00421             oldToNewIndex.insert(std::pair<unsigned int, unsigned int>((*it).second, (*itt).second) );
00422 
00423         it++;
00424     }
00425 
00426     //------   Fusion Topology
00427     BaseMeshTopology * femTopo = (BaseMeshTopology * ) (femBody->getTopology());
00428 
00429     //fusion tetras
00430     for (int i=0 ; i < femTopo->getNbTetras() ; i++)  {
00431         BaseMeshTopology::Tetra tet = femTopo->getTetra(i);
00432         for (unsigned int j(0) ; j<4 ; j++) {
00433             tet[j] = oldToNewIndex[tet[j] ];
00434         }
00435         ((BaseMeshTopology::SeqTetras&)((BaseMeshTopology*)topology)->getTetras()).push_back(tet);
00436     }
00437     //fusion triangles
00438     for (int i=0 ; i < femTopo->getNbTriangles() ; i++)  {
00439         BaseMeshTopology::Triangle tri = femTopo->getTriangle(i);
00440         for (unsigned int j(0) ; j<3 ; j++) {
00441             tri[j] = oldToNewIndex[tri[j] ];
00442         }
00443         ((BaseMeshTopology::SeqTriangles&)((BaseMeshTopology*)topology)->getTriangles()).push_back(tri);
00444     }
00445     //fusion quads
00446     for (int i=0 ; i < femTopo->getNbQuads() ; i++)  {
00447         BaseMeshTopology::Quad qua = femTopo->getQuad(i);
00448         for (unsigned int j(0) ; j<4 ; j++) {
00449             qua[j] = oldToNewIndex[qua[j] ];
00450         }
00451         ((BaseMeshTopology::SeqQuads&)((BaseMeshTopology*)topology)->getQuads()).push_back(qua);
00452     }
00453 
00454 
00455     //-------  Fusion Mass
00456     parentNode->removeObject(mass);
00457     if (mass) delete mass;
00458     mass = new DiagonalMass<Vec3Types,SReal>;
00459     parentNode->addObject(mass);
00460     SReal m1,m2;
00461 
00462     for (unsigned int i=0 ; i< ((MechanicalState<Vec3Types>*)mmodel)->getX()->size(); i++) {
00463       m1 = m2 = 0.0;
00464       if (massList.size() >0)
00465         {
00466           if (massList.size() == 1 && i < X1size)
00467         m1 = massList[0];
00468           else if (i < massList.size())
00469         m1 = massList[i];
00470         }
00471       if (femBody->massList.size() >0)
00472         {
00473           if (femBody->massList.size() == 1 ) {
00474         for (unsigned int j=0 ; j<oldToNewIndex.size() ; j++)
00475           if (oldToNewIndex[j] == i)
00476             m2 = femBody->massList[0];
00477           } else {
00478         for (unsigned int j=0 ; j<oldToNewIndex.size() ; j++)
00479           if (oldToNewIndex[j] == i)
00480             m2 = femBody->massList[j];
00481           }
00482         }
00483 
00484       ((DiagonalMass<Vec3Types,SReal>*)mass)->addMass( m1+m2 );
00485       cout<<"masse noeud "<<i<<" : "<<m1+m2<<endl;
00486     }
00487 
00488 
00489     //------  Fusion Collision Model
00490     if (!collisionsON && femBody->collisionsON) {
00491         tmodel = femBody->getTriangleModel();
00492         //lmodel = femBody->getLineModel();
00493         //pmodel = femBody->getPointModel();
00494     }
00495 
00496     return true;
00497 }
00498 
00499 }
00500 }
00501 }

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