PMLFemForceField.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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
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
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
00097
00098 if(tmodel) delete tmodel;
00099 }
00100
00101
00102
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
00135
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
00162
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
00184
00185
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
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
00243
00244 void PMLFemForceField::createMass(StructuralComponent* body)
00245 {
00246
00247 if (massList.size() == 0) {
00248
00249 if (density.size() != 0) {
00250
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
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
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
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 }
00284 else {
00285
00286 if (massList.size() == 1){
00287 mass = new UniformMass<Vec3Types,SReal>;
00288 ((UniformMass<Vec3Types,SReal>*)mass)->setMass( massList[0] );
00289 }
00290 else {
00291
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
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
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
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
00362 void PMLFemForceField::createForceField()
00363 {
00364 forcefield = new TetrahedronFEMForceField<Vec3Types>;
00365
00366
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
00388
00389
00390 parentNode->addObject( tmodel);
00391
00392
00393
00394 tmodel->init();
00395
00396
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
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
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
00427 BaseMeshTopology * femTopo = (BaseMeshTopology * ) (femBody->getTopology());
00428
00429
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
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
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
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
00490 if (!collisionsON && femBody->collisionsON) {
00491 tmodel = femBody->getTriangleModel();
00492
00493
00494 }
00495
00496 return true;
00497 }
00498
00499 }
00500 }
00501 }