4 * Created on: 22 janv. 2012
20 #include "MEDCouplingIMesh.hxx"
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
24 #include "MEDFileMesh.hxx"
25 #include "MEDLoader.hxx"
27 #include "CdmathException.hxx"
29 using namespace MEDCoupling;
32 //----------------------------------------------------------------------
34 //----------------------------------------------------------------------
37 _meshNotDeleted=false;
50 _boundaryFaceIds.resize(0);
51 _boundaryNodeIds.resize(0);
52 _faceGroupNames.resize(0);
53 _faceGroups.resize(0);
54 _faceGroupsIds.resize(0);
55 _nodeGroupNames.resize(0);
56 _nodeGroups.resize(0);
57 _nodeGroupsIds.resize(0);
58 _indexFacePeriodicSet=false;
63 //----------------------------------------------------------------------
65 //----------------------------------------------------------------------
67 //for(int i=0; i< _faceGroups.size(); i++)
68 // _faceGroups[i]->decrRef();
69 // _nodeGroups[i]->decrRef();
71 (_mesh.retn())->decrRef();
75 Mesh::getName( void ) const
80 Mesh::Mesh( MEDCoupling::MCAuto<const MEDCoupling::MEDCouplingMesh> mesh )
82 _spaceDim=mesh->getSpaceDimension();
83 _meshDim=mesh->getMeshDimension();
84 _name=mesh->getName();
86 _indexFacePeriodicSet=false;
89 _mesh= mesh->clone(false);//Clone because you will need to buildUnstructured. No deep copy : it is assumed node coordinates and cell connectivity will not change
91 MEDCoupling::MEDCouplingStructuredMesh* structuredMesh = dynamic_cast<MEDCoupling::MEDCouplingStructuredMesh*> (_mesh.retn());
95 _nxyz=structuredMesh->getCellGridStructure();
103 //----------------------------------------------------------------------
104 Mesh::Mesh( const std::string filename, const std::string & meshName, int meshLevel)
105 //----------------------------------------------------------------------
107 readMeshMed(filename, meshName, meshLevel);
110 //----------------------------------------------------------------------
111 Mesh::Mesh( const Mesh& mesh )
112 //----------------------------------------------------------------------
114 _spaceDim = mesh.getSpaceDimension() ;
115 _meshDim = mesh.getMeshDimension() ;
116 _name=mesh.getName();
117 _epsilon=mesh.getComparisonEpsilon();
118 _isStructured=mesh.isStructured();
120 _nxyz = mesh.getCellGridStructure() ;
121 _numberOfNodes = mesh.getNumberOfNodes();
122 _numberOfFaces = mesh.getNumberOfFaces();
123 _numberOfCells = mesh.getNumberOfCells();
124 _numberOfEdges = mesh.getNumberOfEdges();
126 _faceGroupNames = mesh.getNameOfFaceGroups() ;
127 _faceGroups = mesh.getMEDCouplingFaceGroups() ;
128 _faceGroupsIds = mesh.getFaceGroups() ;
129 _nodeGroupNames = mesh.getNameOfNodeGroups() ;
130 _nodeGroups = mesh.getMEDCouplingNodeGroups() ;
131 _nodeGroupsIds = mesh.getNodeGroups() ;
133 _nodes = mesh.getNodes() ;
134 _faces = mesh.getFaces() ;
135 _cells = mesh.getCells() ;
137 _indexFacePeriodicSet= mesh.isIndexFacePeriodicSet();
138 if(_indexFacePeriodicSet)
139 _indexFacePeriodicMap=mesh.getIndexFacePeriodic();
141 _boundaryFaceIds=mesh.getBoundaryFaceIds();
142 _boundaryNodeIds=mesh.getBoundaryNodeIds();
144 _eltsTypes=mesh.getElementTypes();
145 _eltsTypesNames=mesh.getElementTypesNames();
147 MCAuto<MEDCouplingMesh> m1=mesh.getMEDCouplingMesh()->clone(false);//Clone because you will need to buildUnstructured. No deep copy : it is assumed node coordinates and cell connectivity will not change
150 _meshNotDeleted=mesh.meshNotDeleted();
153 //----------------------------------------------------------------------
155 Mesh::readMeshMed( const std::string filename, const std::string & meshName, int meshLevel)
156 //----------------------------------------------------------------------
160 m=MEDFileMesh::New(filename.c_str());//reads the first mesh encountered in the file, otherwise call New (const char *fileName, const char *mName, int dt=-1, int it=-1)
162 m=MEDFileMesh::New(filename.c_str(), meshName.c_str());//seeks the mesh named meshName in the file
164 _mesh=m->getMeshAtLevel(meshLevel);
165 _mesh->checkConsistencyLight();
166 _mesh->setName(_mesh->getName());
167 _meshDim=_mesh->getMeshDimension();
168 _spaceDim=_mesh->getSpaceDimension();
169 _name=_mesh->getName();
171 _indexFacePeriodicSet=false;
172 _meshNotDeleted=true;
174 MEDCoupling::MEDCouplingStructuredMesh* structuredMesh = dynamic_cast<MEDCoupling::MEDCouplingStructuredMesh*> (_mesh.retn());
178 _nxyz=structuredMesh->getCellGridStructure();
183 MEDCouplingUMesh* mu = setMesh();
184 setNodeGroups(m, mu);//Works for both cartesan and unstructured meshes
185 MEDFileUMesh *umedfile=dynamic_cast< MEDFileUMesh * > (m);
187 setFaceGroups(umedfile, mu);//Works only for unstructured meshes
189 cout<<endl<< "Loaded file "<< filename<<endl;
190 cout<<"Mesh name = "<<m->getName()<<", mesh dim = "<< _meshDim<< ", space dim = "<< _spaceDim<< ", nb cells= "<<getNumberOfCells()<< ", nb nodes= "<<getNumberOfNodes()<<endl;
195 //----------------------------------------------------------------------
196 Mesh::Mesh( std::vector<double> points, std::string meshName )
197 //----------------------------------------------------------------------
199 int nx=points.size();
202 throw CdmathException("Mesh::Mesh( vector<double> points, string meshName) : nx < 2, vector should contain at least two values");
204 while( i<nx-1 && points[i+1]>points[i] )
208 //cout<< points << endl;
209 throw CdmathException("Mesh::Mesh( vector<double> points, string meshName) : vector values should be sorted");
216 _indexFacePeriodicSet=false;
218 MEDCouplingUMesh * mesh1d = MEDCouplingUMesh::New(meshName, 1);
219 mesh1d->allocateCells(nx - 1);
220 double * coords = new double[nx];
221 mcIdType nodal_con[2];
223 for(int i=0; i<nx- 1 ; i++)
227 mesh1d->insertNextCell(INTERP_KERNEL::NORM_SEG2, 2, nodal_con);
228 coords[i+1]=points[i + 1];
230 mesh1d->finishInsertingCells();
232 DataArrayDouble * coords_arr = DataArrayDouble::New();
233 coords_arr->alloc(nx,1);
234 std::copy(coords,coords+nx,coords_arr->getPointer());
235 mesh1d->setCoords(coords_arr);
238 coords_arr->decrRef();
240 _mesh=mesh1d;//To enable writeMED. Because we declared the mesh as unstructured, we decide to build the unstructured data (not mandatory)
241 _meshNotDeleted=true;
242 _isStructured = false;
247 //----------------------------------------------------------------------
248 Mesh::Mesh( double xmin, double xmax, int nx, std::string meshName )
249 //----------------------------------------------------------------------
252 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx) : nx <= 0");
254 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx) : xmin >= xmax");
256 double dx = (xmax - xmin)/nx ;
262 _indexFacePeriodicSet=false;
264 _nxyz.resize(_spaceDim);
267 double originPtr[_spaceDim];
268 double dxyzPtr[_spaceDim];
269 mcIdType nodeStrctPtr[_spaceDim];
272 nodeStrctPtr[0]=nx+1;
275 _mesh=MEDCouplingIMesh::New(meshName,
278 nodeStrctPtr+_spaceDim,
283 _meshNotDeleted=true;
284 _isStructured = true;
289 //----------------------------------------------------------------------
290 Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, int split_to_triangles_policy, std::string meshName)
291 //----------------------------------------------------------------------
294 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny) : nx <= 0 or ny <= 0");
296 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny) : xmin >= xmax");
298 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny) : ymin >= ymax");
300 double dx = (xmax - xmin)/nx ;
301 double dy = (ymax - ymin)/ny ;
307 _indexFacePeriodicSet=false;
308 _nxyz.resize(_spaceDim);
312 double originPtr[_spaceDim];
313 double dxyzPtr[_spaceDim];
314 mcIdType nodeStrctPtr[_spaceDim];
318 nodeStrctPtr[0]=nx+1;
319 nodeStrctPtr[1]=ny+1;
323 _mesh=MEDCouplingIMesh::New(meshName,
326 nodeStrctPtr+_spaceDim,
331 _meshNotDeleted=true;
332 _isStructured = true;
334 if(split_to_triangles_policy==0 || split_to_triangles_policy==1)
336 _mesh=_mesh->buildUnstructured();//simplexize is not available for structured meshes
337 _mesh->simplexize(split_to_triangles_policy);
338 _isStructured = false;
340 else if (split_to_triangles_policy != -1)
342 cout<< "split_to_triangles_policy = "<< split_to_triangles_policy << endl;
343 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny) : Unknown splitting policy");
349 //----------------------------------------------------------------------
350 Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz, int split_to_tetrahedra_policy, std::string meshName)
351 //----------------------------------------------------------------------
353 if(nx<=0 || ny<=0 || nz<=0)
354 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz) : nx <= 0 or ny <= 0 or nz <= 0");
356 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz) : xmin >= xmax");
358 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz) : ymin >= ymax");
360 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz) : zmin >= zmax");
367 double dx = (xmax - xmin)/nx ;
368 double dy = (ymax - ymin)/ny ;
369 double dz = (zmax - zmin)/nz ;
371 _nxyz.resize(_spaceDim);
376 double originPtr[_spaceDim];
377 double dxyzPtr[_spaceDim];
378 mcIdType nodeStrctPtr[_spaceDim];
383 nodeStrctPtr[0]=nx+1;
384 nodeStrctPtr[1]=ny+1;
385 nodeStrctPtr[2]=nz+1;
390 _mesh=MEDCouplingIMesh::New(meshName,
393 nodeStrctPtr+_spaceDim,
398 _meshNotDeleted=true;
399 _isStructured = true;
401 if( split_to_tetrahedra_policy == 0 )
403 _mesh=_mesh->buildUnstructured();//simplexize is not available for structured meshes
404 _mesh->simplexize(INTERP_KERNEL::PLANAR_FACE_5);
405 _isStructured = false;
407 else if( split_to_tetrahedra_policy == 1 )
409 _mesh=_mesh->buildUnstructured();//simplexize is not available for structured meshes
410 _mesh->simplexize(INTERP_KERNEL::PLANAR_FACE_6);
411 _isStructured = false;
413 else if ( split_to_tetrahedra_policy != -1 )
415 cout<< "split_to_tetrahedra_policy = "<< split_to_tetrahedra_policy << endl;
416 throw CdmathException("Mesh::Mesh( double xmin, double xmax, int nx, double ymin, double ymax, int ny, double zmin, double zmax, int nz) : splitting policy value should be 0 or 1");
422 //----------------------------------------------------------------------
424 Mesh::setMesh( void )
425 //----------------------------------------------------------------------
427 /* This is the main function translating medcouplingumesh info into Mesh class to be used when designing numerical methods
428 * We need the level 0 mesh to extract the cell-node connectvity
429 * We need the level -1 mesh to extract the cell-face and face-node connectivities (use o build descending connectivity)
430 * Be careful : the nodes in the medcoupling mesh are not necessarily all conected to a cell/face.
431 * Mesh class discard isolated nodes, hence the number of nodes in Mesh class can be lower than the number of nodes in medcouplingumesh.
434 DataArrayIdType *desc = DataArrayIdType::New();
435 DataArrayIdType *descI = DataArrayIdType::New();
436 DataArrayIdType *revDesc = DataArrayIdType::New();
437 DataArrayIdType *revDescI = DataArrayIdType::New();
438 MEDCouplingUMesh* mu = _mesh->buildUnstructured();
439 MEDCouplingUMesh* mu2;//mesh of dimension N-1 containing the cell interfaces->cell/face connectivity
442 mu->sortCellsInMEDFileFrmt( );
445 mu2=mu->buildDescendingConnectivity(desc,descI,revDesc,revDescI);
447 mu2=mu->buildDescendingConnectivity2(desc,descI,revDesc,revDescI);
449 const mcIdType *tmp = desc->getConstPointer();//Lists the faces surrounding each cell
450 const mcIdType *tmpI=descI->getConstPointer();
452 const mcIdType *tmpA =revDesc->getConstPointer();//Lists the cells surrounding each face
453 const mcIdType *tmpAI=revDescI->getConstPointer();
455 //Test du type d'éléments contenus dans le maillage afin d'éviter les éléments contenant des points de gauss
456 _eltsTypes=mu->getAllGeoTypesSorted();
457 for(int i=0; i<_eltsTypes.size();i++)
460 _eltsTypes[i]!= INTERP_KERNEL::NORM_POINT1 && _eltsTypes[i]!= INTERP_KERNEL::NORM_SEG2
461 && _eltsTypes[i]!= INTERP_KERNEL::NORM_TRI3 && _eltsTypes[i]!= INTERP_KERNEL::NORM_QUAD4
462 && _eltsTypes[i]!= INTERP_KERNEL::NORM_TETRA4 && _eltsTypes[i]!= INTERP_KERNEL::NORM_PYRA5
463 && _eltsTypes[i]!= INTERP_KERNEL::NORM_PENTA6 && _eltsTypes[i]!= INTERP_KERNEL::NORM_HEXA8
464 && _eltsTypes[i]!= INTERP_KERNEL::NORM_POLYGON&& _eltsTypes[i]!= INTERP_KERNEL::NORM_POLYHED
467 cout<< "Mesh " + mu->getName() + " contains an element of type " <<endl;
468 cout<< _eltsTypes[i]<<endl;
469 throw CdmathException("Mesh::setMesh : in order to avoid gauss points, mesh should contain elements of type NORM_POINT1, NORM_SEG2, NORM_TRI3, NORM_QUAD4, NORM_TETRA4, NORM_PYRA5, NORM_PENTA6, NORM_HEXA8, NORM_POLYGON, NORM_POLYHED");
473 DataArrayDouble *baryCell = mu->computeCellCenterOfMass() ;
474 const double *coorBary=baryCell->getConstPointer();//Used for cell center coordinates
476 MEDCouplingFieldDouble* fields=mu->getMeasureField(true);
477 DataArrayDouble *surface = fields->getArray();
478 const double *surf=surface->getConstPointer();//Used for cell lenght/surface/volume
480 DataArrayDouble *coo = mu->getCoords() ;
481 const double *cood=coo->getConstPointer();//Used for nodes coordinates
483 DataArrayIdType *revNode =DataArrayIdType::New();
484 DataArrayIdType *revNodeI=DataArrayIdType::New();
485 mu->getReverseNodalConnectivity(revNode,revNodeI) ;
486 const mcIdType *tmpN =revNode->getConstPointer();//Used to know which cells surround a given node
487 const mcIdType *tmpNI=revNodeI->getConstPointer();
489 DataArrayIdType *revCell =DataArrayIdType::New();
490 DataArrayIdType *revCellI=DataArrayIdType::New();
491 mu2->getReverseNodalConnectivity(revCell,revCellI);
492 const mcIdType *tmpC =revCell->getConstPointer();//Used to know which faces surround a given node
493 const mcIdType *tmpCI=revCellI->getConstPointer();
495 const DataArrayIdType *nodal = mu2->getNodalConnectivity() ;
496 const DataArrayIdType *nodalI = mu2->getNodalConnectivityIndex() ;
497 const mcIdType *tmpNE =nodal->getConstPointer();//Used to know which nodes surround a given face
498 const mcIdType *tmpNEI=nodalI->getConstPointer();
500 _numberOfCells = mu->getNumberOfCells() ;
501 _cells = std::shared_ptr<Cell>(new Cell[_numberOfCells], std::default_delete<Cell[]>()) ;
503 _numberOfNodes = mu->getNumberOfNodes() ;//This number may include isolated nodes that will not be loaded. The number will be updated during nodes constructions
504 _nodes = std::shared_ptr<Node>(new Node[_numberOfNodes], std::default_delete<Node[]>()) ;//This array may be resized if isolated nodes are found
506 _numberOfFaces = mu2->getNumberOfCells();
507 _faces = std::shared_ptr<Face>(new Face[_numberOfFaces], std::default_delete<Face[]>()) ;
509 _indexFacePeriodicSet=false;
511 //Definition used if _meshDim =3 to determine the edges
512 DataArrayIdType *desc2 =DataArrayIdType::New();
513 DataArrayIdType *descI2=DataArrayIdType::New();
514 DataArrayIdType *revDesc2 =DataArrayIdType::New();
515 DataArrayIdType *revDescI2=DataArrayIdType::New();
516 DataArrayIdType *revNode2 =DataArrayIdType::New();
517 DataArrayIdType *revNodeI2=DataArrayIdType::New();
518 const mcIdType *tmpN2 ;
519 const mcIdType *tmpNI2;
520 MEDCouplingUMesh* mu3;
523 _numberOfEdges = mu->getNumberOfCells();
524 else if (_meshDim == 2)
525 _numberOfEdges = mu2->getNumberOfCells();
528 mu3=mu2->buildDescendingConnectivity(desc2,descI2,revDesc2,revDescI2);//1D mesh of segments
529 _numberOfEdges = mu3->getNumberOfCells();
530 mu3->getReverseNodalConnectivity(revNode2,revNodeI2) ;
531 tmpN2 =revNode2->getConstPointer();
532 tmpNI2=revNodeI2->getConstPointer();
535 // _cells, _nodes and _faces initialization:
538 double xn, yn=0., zn=0.;//Components of the normal vector at a cell interface
540 for( int id=0;id<_numberOfCells;id++ )
542 Point p(0.0,0.0,0.0) ;
543 for(int idim=0; idim<_spaceDim; idim++)
544 p[idim]=coorBary[id*_spaceDim+idim];
546 mcIdType nbVertices=mu->getNumberOfNodesInCell(id) ;//should be equal to 2
547 assert( nbVertices==2);
548 std::vector<mcIdType> nodeIdsOfCell ;
549 mu->getNodeIdsOfCell(id,nodeIdsOfCell) ;
551 mcIdType nbFaces=tmpI[id+1]-tmpI[id];//should be equal to 2
553 const mcIdType *work=tmp+tmpI[id];
555 /* compute the normal to the face */
556 xn = cood[nodeIdsOfCell[0]*_spaceDim ] - cood[nodeIdsOfCell[nbFaces-1]*_spaceDim ];
558 yn = cood[nodeIdsOfCell[0]*_spaceDim+1] - cood[nodeIdsOfCell[nbFaces-1]*_spaceDim+1];
560 zn = cood[nodeIdsOfCell[0]*_spaceDim+2] - cood[nodeIdsOfCell[nbFaces-1]*_spaceDim+2];
561 norm = sqrt(xn*xn+yn*yn+zn*zn);
563 throw CdmathException("!!! Mesh::setMesh Normal vector has norm 0 !!!");
571 Cell ci( nbVertices, nbFaces, surf[id], p ) ;//nbCells=nbFaces=2
572 for( int el=0;el<nbFaces;el++ )
574 ci.addNodeId(el,nodeIdsOfCell[el]) ;//global node number
575 ci.addNormalVector(el,xn,yn,zn) ;
576 ci.addFaceId(el,work[el]) ;
577 xn = - xn; yn=-yn; zn=-zn;
579 _cells.get()[id] = ci ;
582 for( int id(0); id<_numberOfFaces; id++ )
584 const mcIdType *workv=tmpNE+tmpNEI[id]+1;
585 mcIdType nbNodes= tmpNEI[id+1]-tmpNEI[id]-1;//Normally equal to 1.
588 std::vector<double> coo(0) ;
589 mu2->getCoordinatesOfNode(workv[0],coo);
591 for(int idim=0; idim<_spaceDim; idim++)
594 const mcIdType *workc=tmpA+tmpAI[id];
595 mcIdType nbCells=tmpAI[id+1]-tmpAI[id];
596 assert( nbCells>0);//To make sure our face is not located on an isolated node
598 Face fi( nbNodes, nbCells, 1.0, p, 1., 0., 0. ) ;
599 for(int node_id=0; node_id<nbNodes;node_id++)//This loop could be deleted since nbNodes=1. Trying to merge with setMesh
600 fi.addNodeId(node_id,workv[node_id]) ;//global node number
602 fi.addCellId(0,workc[0]) ;
603 for(int cell_id=1; cell_id<nbCells;cell_id++)
606 if (workc[cell_id]!=workc[cell_id-1])//For some meshes (bad ones) the same cell can appear several times
608 fi.addCellId(cell_idx+1,workc[cell_id]) ;
613 _boundaryFaceIds.push_back(id);
614 _faces.get()[id] = fi ;
617 int correctNbNodes=0;
618 for( int id=0;id<_numberOfNodes;id++ )
620 const mcIdType *workc=tmpN+tmpNI[id];
621 mcIdType nbCells=tmpNI[id+1]-tmpNI[id];
623 if( nbCells>0)//To make sure this is not an isolated node
626 std::vector<double> coo(0) ;
627 mu->getCoordinatesOfNode(id,coo);
629 for(int idim=0; idim<_spaceDim; idim++)
632 const mcIdType *workf=tmpC+tmpCI[id];
633 mcIdType nbFaces=tmpCI[id+1]-tmpCI[id];
636 const mcIdType *workn=tmpN+tmpNI[id];
637 mcIdType nbNeighbourNodes=tmpNI[id+1]-tmpNI[id];
639 Node vi( nbCells, nbFaces, nbNeighbourNodes, p ) ;
640 for( int el=0;el<nbCells;el++ )
641 vi.addCellId(el,workc[el]) ;
642 for( int el=0;el<nbNeighbourNodes;el++ )
643 vi.addNeighbourNodeId(el,workn[el]) ;//global node number
644 for( int el=0;el<nbFaces;el++ )
645 vi.addFaceId(el,workf[el],_faces.get()[workf[el]].isBorder()) ;
647 _boundaryNodeIds.push_back(id);
648 _nodes.get()[id] = vi ;
651 if( _numberOfNodes!=correctNbNodes)//To do : reduce the size of pointer _nodes
653 cout<<"Found isolated nodes : correctNbNodes= "<<correctNbNodes<<", _numberOfNodes= "<<_numberOfNodes<<endl;
654 _numberOfNodes = correctNbNodes;
655 //memcpy(_nodes,mesh.getNodes(),correctNbNodes*sizeof(*mesh.getNodes())) ;
658 else if(_meshDim==2 || _meshDim==3)
660 DataArrayDouble *barySeg = mu2->computeIsoBarycenterOfNodesPerCell();//computeCellCenterOfMass() ;//Used as face center
661 const double *coorBarySeg=barySeg->getConstPointer();
663 MEDCouplingFieldDouble* fieldl=mu2->getMeasureField(true);
664 DataArrayDouble *longueur = fieldl->getArray();
665 const double *lon=longueur->getConstPointer();//The lenght/area of each face
667 MEDCouplingFieldDouble* fieldn;//The normal to each face
668 DataArrayDouble *normal;
669 const double *tmpNormal;
671 if(_spaceDim==_meshDim)
672 fieldn = mu2->buildOrthogonalField();//Compute the normal to each cell interface
674 fieldn = mu->buildOrthogonalField();//compute the 3D normal vector to the 2D cell
676 normal = fieldn->getArray();
677 tmpNormal = normal->getConstPointer();
679 /*Building mesh cells */
680 for(int id(0), k(0); id<_numberOfCells; id++, k+=_spaceDim)
682 const mcIdType *work=tmp+tmpI[id];
683 mcIdType nbFaces=tmpI[id+1]-tmpI[id];
685 mcIdType nbVertices=mu->getNumberOfNodesInCell(id) ;
687 vector<double> coorBaryXyz(3,0);
688 for (int d=0; d<_spaceDim; d++)
689 coorBaryXyz[d] = coorBary[k+d];
691 Point p(coorBaryXyz[0],coorBaryXyz[1],coorBaryXyz[2]) ;
692 Cell ci( nbVertices, nbFaces, surf[id], p ) ;
694 /* Filling cell nodes */
695 std::vector<mcIdType> nodeIdsOfCell ;
696 mu->getNodeIdsOfCell(id,nodeIdsOfCell) ;
697 for( int el=0;el<nbVertices;el++ )
698 ci.addNodeId(el,nodeIdsOfCell[el]) ;
700 /* Filling cell faces */
701 if(_spaceDim==_meshDim)//use the normal field generated by buildOrthogonalField()
702 for( int el=0;el<nbFaces;el++ )
704 mcIdType faceIndex=(abs(work[el])-1);//=work[el] since Fortran type numbering was used, and negative sign means anticlockwise numbering
705 vector<double> xyzn(3,0);//Outer normal to the cell
707 for (int d=0; d<_spaceDim; d++)
708 xyzn[d] = -tmpNormal[_spaceDim*faceIndex+d];
710 for (int d=0; d<_spaceDim; d++)
711 xyzn[d] = +tmpNormal[_spaceDim*faceIndex+d];
712 ci.addNormalVector(el,xyzn[0],xyzn[1],xyzn[2]) ;
713 ci.addFaceId(el,faceIndex) ;
715 else//build normals associated to the couple (cell id, face el)
716 {//Case _meshDim=1 should be moved upper since we are in the 2D/3D branch
717 if(_meshDim==1)//we know in this case there are only two faces around the cell id, each face is composed of a single node
718 {//work[0]= first face global number, work[1]= second face global number
719 mcIdType indexFace0=abs(work[0])-1;//=work[0] since Fortran type numbering was used, and negative sign means anticlockwise numbering
720 mcIdType indexFace1=abs(work[1])-1;//=work[1] since Fortran type numbering was used, and negative sign means anticlockwise numbering
721 mcIdType idNodeA=(tmpNE+tmpNEI[indexFace0]+1)[0];//global number of the first face node work[0]=(abs(work[0])-1)
722 mcIdType idNodeB=(tmpNE+tmpNEI[indexFace1]+1)[0];//global number of the second face node work[1]=(abs(work[1])-1)
724 for(int i=0;i<_spaceDim;i++)
725 vecAB[i]=coo->getIJ(idNodeB,i) - coo->getIJ(idNodeA,i);
727 ci.addNormalVector(0,-vecAB[0],-vecAB[1],-vecAB[2]) ;
728 ci.addNormalVector(1,vecAB[0],vecAB[1],vecAB[2]) ;
729 ci.addFaceId(0,indexFace0) ;
730 ci.addFaceId(1,indexFace1) ;
732 else//_meshDim==2, number of faces around the cell id is variable, each face is composed of two nodes
735 for (int d=0; d<_spaceDim; d++)
736 xyzn[d] = tmpNormal[_spaceDim*id+d];
737 for( int el=0;el<nbFaces;el++ )
739 int faceIndex=(abs(work[el])-1);//=work[el] since Fortran type numbering was used, and negative sign means anticlockwise numbering
740 const mcIdType *workv=tmpNE+tmpNEI[faceIndex]+1;
741 mcIdType nbNodes= tmpNEI[faceIndex+1]-tmpNEI[faceIndex]-1;
742 if(nbNodes!=2)//We want to compute the normal to a straight line, not a curved interface composed of more thant 2 points
744 cout<<"Mesh name "<< mu->getName()<< " space dim= "<< _spaceDim <<" mesh dim= "<< _meshDim <<endl;
745 cout<<"For cell id "<<id<<" and local face number "<<el<<", the number of nodes is "<< nbNodes<< ", total number of faces is "<< nbFaces <<endl;
746 throw CdmathException("Mesh::setMesh number of nodes around a face should be 2");
749 mcIdType idNodeA=workv[0];
750 mcIdType idNodeB=workv[1];
751 vector<double> nodeA(_spaceDim), nodeB(_spaceDim), nodeP(_spaceDim);
752 for(int i=0;i<_spaceDim;i++)
754 nodeA[i]=coo->getIJ(idNodeA,i);
755 nodeB[i]=coo->getIJ(idNodeB,i);
756 nodeP[i]=coorBary[_spaceDim*id+i];
758 //Let P be the barycenter of the cell id
759 Vector vecAB(3), vecPA(3);
760 for(int i=0;i<_spaceDim;i++)
762 vecAB[i]=coo->getIJ(idNodeB,i) - coo->getIJ(idNodeA,i);
763 vecPA[i]=coo->getIJ(idNodeA,i) - coorBary[_spaceDim*id+i];
766 Vector normale = xyzn % vecAB;//Normal to the edge
767 normale/=normale.norm();
770 ci.addNormalVector(el,normale[0],normale[1],normale[2]) ;
772 ci.addNormalVector(el,-normale[0],-normale[1],-normale[2]) ;
773 ci.addFaceId(el,faceIndex) ;
777 _cells.get()[id] = ci ;
780 if(_spaceDim!=_meshDim)
782 /* Since spaceDim!=meshDim, don't build normal to faces */
788 /*Building mesh faces */
789 for(int id(0), k(0); id<_numberOfFaces; id++, k+=_spaceDim)
791 vector<double> coorBarySegXyz(3);
792 for (int d=0; d<_spaceDim; d++)
793 coorBarySegXyz[d] = coorBarySeg[k+d];
794 Point p(coorBarySegXyz[0],coorBarySegXyz[1],coorBarySegXyz[2]) ;
795 const mcIdType *workc=tmpA+tmpAI[id];
796 mcIdType nbCells=tmpAI[id+1]-tmpAI[id];
798 if (nbCells>2 && _spaceDim==_meshDim)
800 cout<<"Warning : nbCells>2, numberOfFaces="<<_numberOfFaces<<endl;
801 cout<<"nbCells= "<<nbCells<<", _spaceDim="<<_spaceDim<<", _meshDim="<<_meshDim<<endl;
802 for(int icell=0; icell<nbCells; icell++)
803 cout<<workc[icell]<<", ";
805 throw CdmathException("Wrong mesh : nbCells>2 and spaceDim==meshDim");
808 _boundaryFaceIds.push_back(id);
810 const mcIdType *workv=tmpNE+tmpNEI[id]+1;
811 mcIdType nbNodes= tmpNEI[id+1]-tmpNEI[id]-1;
814 if(_spaceDim==_meshDim)//Euclidean flat mesh geometry
816 fi=Face( nbNodes, nbCells, lon[id], p, tmpNormal[k], tmpNormal[k+1], 0.0) ;
818 fi=Face( nbNodes, nbCells, lon[id], p, tmpNormal[k], tmpNormal[k+1], tmpNormal[k+2]) ;
819 else//Curved mesh geometry
820 fi=Face( nbNodes, nbCells, lon[id], p, 0.0, 0.0, 0.0) ;//Since spaceDim!=meshDim, normal to face is not defined
822 for(int node_id=0; node_id<nbNodes;node_id++)
823 fi.addNodeId(node_id,workv[node_id]) ;
825 fi.addCellId(0,workc[0]) ;
826 for(int cell_id=1; cell_id<nbCells;cell_id++)
829 if (workc[cell_id]!=workc[cell_id-1])//For some meshes (bad ones) the same cell can appear several times
831 fi.addCellId(cell_idx+1,workc[cell_id]) ;
836 _faces.get()[id] = fi ;
839 /*Building mesh nodes, should be done after building mesh faces in order to detect boundary nodes*/
840 int correctNbNodes=0;
841 for(int id(0), k(0); id<_numberOfNodes; id++, k+=_spaceDim)
843 const mcIdType *workc=tmpN+tmpNI[id];
844 mcIdType nbCells=tmpNI[id+1]-tmpNI[id];
846 if( nbCells>0)//To make sure this is not an isolated node
849 vector<double> coorP(3);
850 for (int d=0; d<_spaceDim; d++)
851 coorP[d] = cood[k+d];
852 Point p(coorP[0],coorP[1],coorP[2]) ;
854 const mcIdType *workf=tmpC+tmpCI[id];
855 mcIdType nbFaces=tmpCI[id+1]-tmpCI[id];
856 const mcIdType *workn;
857 mcIdType nbNeighbourNodes;
860 workn=tmpA+tmpAI[id];
861 nbNeighbourNodes=tmpAI[id+1]-tmpAI[id];
863 else if (_meshDim == 2)
865 workn=tmpC+tmpCI[id];
866 nbNeighbourNodes=tmpCI[id+1]-tmpCI[id];
870 workn=tmpN2+tmpNI2[id];
871 nbNeighbourNodes=tmpNI2[id+1]-tmpNI2[id];
873 Node vi( nbCells, nbFaces, nbNeighbourNodes, p ) ;
875 for( int el=0;el<nbCells;el++ )
876 vi.addCellId(el,workc[el]) ;
877 for( int el=0;el<nbNeighbourNodes;el++ )
878 vi.addNeighbourNodeId(el,workn[el]) ;
879 //Detection of border nodes
880 for( int el=0;el<nbFaces;el++ )
881 vi.addFaceId(el,workf[el],_faces.get()[workf[el]].isBorder()) ;
883 _boundaryNodeIds.push_back(id);
884 _nodes.get()[id] = vi ;
887 if( _numberOfNodes!=correctNbNodes)//To do : reduce the size of pointer _nodes
889 cout<<"Found isolated nodes : correctNbNodes= "<<correctNbNodes<<", _numberOfNodes= "<<_numberOfNodes<<endl;
890 _numberOfNodes = correctNbNodes;
893 if(_spaceDim==_meshDim)
899 throw CdmathException("Mesh::setMesh space dimension should be 1, 2 or 3");
901 //Set boundary groups
902 _faceGroupNames.push_back("Boundary");
903 _nodeGroupNames.push_back("Boundary");
904 _faceGroupsIds.push_back(_boundaryFaceIds);
905 _nodeGroupsIds.push_back(_boundaryNodeIds);
907 { //Set face boundary group
908 _boundaryMesh = mu->computeSkin();
909 _faceGroups.push_back(_boundaryMesh);
912 _faceGroups.push_back(NULL);
913 _nodeGroups.push_back(NULL);
930 revNodeI2->decrRef();
934 revDescI2->decrRef();
942 Mesh::setGroupAtFaceByCoords(double x, double y, double z, double eps, std::string groupName, bool isBoundaryGroup)
944 std::vector< int > faceIds(0);
948 /* Construction of the face group */
950 for(int i=0; i<_boundaryFaceIds.size(); i++)
952 Fi=_faces.get()[_boundaryFaceIds[i]];
956 if (abs(FX-x)<eps && abs(FY-y)<eps && abs(FZ-z)<eps)
958 faceIds.insert(faceIds.end(),_boundaryFaceIds[i]);
959 _faces.get()[_boundaryFaceIds[i]].setGroupName(groupName);
963 for (int iface=0;iface<_numberOfFaces;iface++)
965 Fi=_faces.get()[iface];
969 if (abs(FX-x)<eps && abs(FY-y)<eps && abs(FZ-z)<eps)
971 faceIds.insert(faceIds.end(),iface);
972 _faces.get()[iface].setGroupName(groupName);
976 if (faceIds.size()>0)
978 std::vector< std::string >::iterator it = std::find(_faceGroupNames.begin(), _faceGroupNames.end(), groupName);
979 if(it == _faceGroupNames.end())//No group named groupName
981 _faceGroupNames.insert(_faceGroupNames.end(),groupName);
982 _faceGroupsIds.insert( _faceGroupsIds.end(),faceIds);
983 _faceGroups.insert( _faceGroups.end(), NULL);//No mesh created. Create one ?
987 std::vector< int > faceGroupIds = _faceGroupsIds[it-_faceGroupNames.begin()];
988 faceGroupIds.insert( faceGroupIds.end(), faceIds.begin(), faceIds.end());
989 /* Detect and erase duplicates face ids */
990 sort( faceGroupIds.begin(), faceGroupIds.end() );
991 faceGroupIds.erase( unique( faceGroupIds.begin(), faceGroupIds.end() ), faceGroupIds.end() );
992 _faceGroupsIds[it-_faceGroupNames.begin()] = faceGroupIds;
998 Mesh::setGroupAtNodeByCoords(double x, double y, double z, double eps, std::string groupName, bool isBoundaryGroup)
1000 std::vector< int > nodeIds(0);
1004 /* Construction of the node group */
1006 for(int i=0; i<_boundaryNodeIds.size(); i++)
1008 Ni=_nodes.get()[_boundaryNodeIds[i]];
1012 if (abs(NX-x)<eps && abs(NY-y)<eps && abs(NZ-z)<eps)
1014 nodeIds.insert(nodeIds.end(),_boundaryNodeIds[i]);
1015 _nodes.get()[_boundaryNodeIds[i]].setGroupName(groupName);
1019 for (int inode=0;inode<_numberOfNodes;inode++)
1021 NX=_nodes.get()[inode].x();
1022 NY=_nodes.get()[inode].y();
1023 NZ=_nodes.get()[inode].z();
1024 if (abs(NX-x)<eps && abs(NY-y)<eps && abs(NZ-z)<eps)
1026 nodeIds.insert(nodeIds.end(),inode);
1027 _nodes.get()[inode].setGroupName(groupName);
1031 if (nodeIds.size()>0)
1033 std::vector< std::string >::iterator it = std::find(_nodeGroupNames.begin(), _nodeGroupNames.end(), groupName);
1034 if(it == _nodeGroupNames.end())//No group named groupName
1036 _nodeGroupNames.insert(_nodeGroupNames.end(),groupName);
1037 _nodeGroupsIds.insert( _nodeGroupsIds.end(),nodeIds);
1038 _nodeGroups.insert( _nodeGroups.end(), NULL);//No mesh created. Create one ?
1042 std::vector< int > nodeGroupIds = _nodeGroupsIds[it-_nodeGroupNames.begin()];
1043 nodeGroupIds.insert( nodeGroupIds.end(), nodeIds.begin(), nodeIds.end());
1044 /* Detect and erase duplicates node ids */
1045 sort( nodeGroupIds.begin(), nodeGroupIds.end() );
1046 nodeGroupIds.erase( unique( nodeGroupIds.begin(), nodeGroupIds.end() ), nodeGroupIds.end() );
1047 _nodeGroupsIds[it-_nodeGroupNames.begin()] = nodeGroupIds;
1053 Mesh::setGroupAtPlan(double value, int direction, double eps, std::string groupName, bool isBoundaryGroup)
1055 std::vector< int > faceIds(0), nodeIds(0);
1058 /* Construction of the face group */
1060 for(int i=0; i<_boundaryFaceIds.size(); i++)
1062 cord=_faces.get()[_boundaryFaceIds[i]].getBarryCenter()[direction];
1063 if (abs(cord-value)<eps)
1065 faceIds.insert(faceIds.end(),_boundaryFaceIds[i]);
1066 _faces.get()[_boundaryFaceIds[i]].setGroupName(groupName);
1070 for (int iface=0;iface<_numberOfFaces;iface++)
1072 cord=_faces.get()[iface].getBarryCenter()[direction];
1073 if (abs(cord-value)<eps)
1075 faceIds.insert(faceIds.end(),iface);
1076 _faces.get()[iface].setGroupName(groupName);
1080 /* Construction of the node group */
1082 for(int i=0; i<_boundaryNodeIds.size(); i++)
1084 cord=_nodes.get()[_boundaryNodeIds[i]].getPoint()[direction];
1085 if (abs(cord-value)<eps)
1087 nodeIds.insert(nodeIds.end(),_boundaryNodeIds[i]);
1088 _nodes.get()[_boundaryNodeIds[i]].setGroupName(groupName);
1092 for (int inode=0;inode<_numberOfNodes;inode++)
1094 cord=_nodes.get()[inode].getPoint()[direction];
1095 if (abs(cord-value)<eps)
1097 nodeIds.insert(nodeIds.end(),inode);
1098 _nodes.get()[inode].setGroupName(groupName);
1102 if (faceIds.size()>0)
1104 std::vector< std::string >::iterator it = std::find(_faceGroupNames.begin(), _faceGroupNames.end(), groupName);
1105 if(it == _faceGroupNames.end())//No group named groupName
1107 _faceGroupNames.insert(_faceGroupNames.end(),groupName);
1108 _faceGroupsIds.insert( _faceGroupsIds.end(),faceIds);
1109 _faceGroups.insert( _faceGroups.end(), NULL);//No mesh created. Create one ?
1113 std::vector< int > faceGroupIds = _faceGroupsIds[it-_faceGroupNames.begin()];
1114 faceGroupIds.insert( faceGroupIds.end(), faceIds.begin(), faceIds.end());
1115 /* Detect and erase duplicates face ids */
1116 sort( faceGroupIds.begin(), faceGroupIds.end() );
1117 faceGroupIds.erase( unique( faceGroupIds.begin(), faceGroupIds.end() ), faceGroupIds.end() );
1118 _faceGroupsIds[it-_faceGroupNames.begin()] = faceGroupIds;
1121 if (nodeIds.size()>0)
1123 std::vector< std::string >::iterator it = std::find(_nodeGroupNames.begin(), _nodeGroupNames.end(), groupName);
1124 if(it == _nodeGroupNames.end())//No group named groupName
1126 _nodeGroupNames.insert(_nodeGroupNames.end(),groupName);
1127 _nodeGroupsIds.insert( _nodeGroupsIds.end(),nodeIds);
1128 _nodeGroups.insert( _nodeGroups.end(), NULL);//No mesh created. Create one ?
1132 std::vector< int > nodeGroupIds = _nodeGroupsIds[it-_nodeGroupNames.begin()];
1133 nodeGroupIds.insert( nodeGroupIds.end(), nodeIds.begin(), nodeIds.end());
1134 /* Detect and erase duplicates node ids */
1135 sort( nodeGroupIds.begin(), nodeGroupIds.end() );
1136 nodeGroupIds.erase( unique( nodeGroupIds.begin(), nodeGroupIds.end() ), nodeGroupIds.end() );
1137 _nodeGroupsIds[it-_nodeGroupNames.begin()] = nodeGroupIds;
1143 Mesh::setBoundaryNodesFromFaces()
1145 for (int iface=0;iface<_boundaryFaceIds.size();iface++)
1147 std::vector< int > nodesID= _faces.get()[_boundaryFaceIds[iface]].getNodesId();
1148 int nbNodes = _faces.get()[_boundaryFaceIds[iface]].getNumberOfNodes();
1149 for(int inode=0 ; inode<nbNodes ; inode++)
1151 std::vector<int>::const_iterator it = std::find(_boundaryNodeIds.begin(),_boundaryNodeIds.end(),nodesID[inode]);
1152 if( it != _boundaryNodeIds.end() )
1153 _boundaryNodeIds.push_back(nodesID[inode]);
1159 Mesh::getIndexFacePeriodic( void ) const
1161 return _indexFacePeriodicMap;
1165 Mesh::setPeriodicFaces(bool check_groups, bool use_central_inversion)
1167 if(_indexFacePeriodicSet)
1170 for (int indexFace=0;indexFace<_boundaryFaceIds.size() ; indexFace++)
1172 Face my_face=_faces.get()[_boundaryFaceIds[indexFace]];
1176 for (int iface=0;iface<_boundaryFaceIds.size() ; iface++)
1177 if(iface!=indexFace)
1179 iface_perio=_boundaryFaceIds[iface];
1183 else if(_meshDim==2)
1185 double x=my_face.x();
1186 double y=my_face.y();
1188 for (int iface=0;iface<_boundaryFaceIds.size() ; iface++)
1190 Face face_i=_faces.get()[_boundaryFaceIds[iface]];
1191 double xi=face_i.x();
1192 double yi=face_i.y();
1193 if ( (abs(y-yi)<_epsilon || abs(x-xi)<_epsilon )// Case of a square geometry
1194 && ( !check_groups || my_face.getGroupName()!=face_i.getGroupName()) //In case groups need to be checked
1195 && ( !use_central_inversion || abs(y+yi) + abs(x+xi)<_epsilon ) // Case of a central inversion
1196 && fabs(my_face.getMeasure() - face_i.getMeasure())<_epsilon
1197 && fabs(my_face.getXN() + face_i.getXN())<_epsilon
1198 && fabs(my_face.getYN() + face_i.getYN())<_epsilon
1199 && fabs(my_face.getZN() + face_i.getZN())<_epsilon )
1201 iface_perio=_boundaryFaceIds[iface];
1206 else if(_meshDim==3)
1208 double x=my_face.x();
1209 double y=my_face.y();
1210 double z=my_face.z();
1212 for (int iface=0;iface<_boundaryFaceIds.size() ; iface++)
1214 Face face_i=_faces.get()[_boundaryFaceIds[iface]];
1215 double xi=face_i.x();
1216 double yi=face_i.y();
1217 double zi=face_i.z();
1218 if ( ((abs(y-yi)<_epsilon && abs(x-xi)<_epsilon) || (abs(x-xi)<_epsilon && abs(z-zi)<_epsilon) || (abs(y-yi)<_epsilon && abs(z-zi)<_epsilon))// Case of a cube geometry
1219 && ( !check_groups || my_face.getGroupName()!=face_i.getGroupName()) //In case groups need to be checked
1220 && ( !use_central_inversion || abs(y+yi) + abs(x+xi) + abs(z+zi)<_epsilon )// Case of a central inversion
1221 && fabs(my_face.getMeasure() - face_i.getMeasure())<_epsilon
1222 && fabs(my_face.getXN() + face_i.getXN())<_epsilon
1223 && fabs(my_face.getYN() + face_i.getYN())<_epsilon
1224 && fabs(my_face.getZN() + face_i.getZN())<_epsilon )
1226 iface_perio=_boundaryFaceIds[iface];
1232 throw CdmathException("Mesh::setPeriodicFaces: Mesh dimension should be 1, 2 or 3");
1234 if (iface_perio==-1)
1235 throw CdmathException("Mesh::setPeriodicFaces: periodic face not found, iface_perio==-1 " );
1237 _indexFacePeriodicMap[_boundaryFaceIds[indexFace]]=iface_perio;
1239 _indexFacePeriodicSet=true;
1243 Mesh::getIndexFacePeriodic(int indexFace, bool check_groups, bool use_central_inversion)
1245 if (!_faces.get()[indexFace].isBorder())
1247 cout<<"Pb with indexFace= "<<indexFace<<endl;
1248 throw CdmathException("Mesh::getIndexFacePeriodic: not a border face" );
1251 if(!_indexFacePeriodicSet)
1252 setPeriodicFaces(check_groups, use_central_inversion);
1254 std::map<int,int>::const_iterator it = _indexFacePeriodicMap.find(indexFace);
1255 if( it != _indexFacePeriodicMap.end() )
1259 cout<<"Pb with indexFace= "<<indexFace<<endl;
1260 throw CdmathException("Mesh::getIndexFacePeriodic: not a periodic face" );
1265 Mesh::isBorderNode(int nodeid) const
1267 return _nodes.get()[nodeid].isBorder();
1271 Mesh::isBorderFace(int faceid) const
1273 return _faces.get()[faceid].isBorder();
1277 Mesh::getBoundaryFaceIds() const
1279 return _boundaryFaceIds;
1283 Mesh::getBoundaryNodeIds() const
1285 return _boundaryNodeIds;
1289 Mesh::isTriangular() const
1291 return _eltsTypes.size()==1 && _eltsTypes[0]==INTERP_KERNEL::NORM_TRI3;
1294 Mesh::isTetrahedral() const
1296 return _eltsTypes.size()==1 && _eltsTypes[0]==INTERP_KERNEL::NORM_TETRA4;
1299 Mesh::isQuadrangular() const
1301 return _eltsTypes.size()==1 && _eltsTypes[0]==INTERP_KERNEL::NORM_QUAD4;
1304 Mesh::isHexahedral() const
1306 return _eltsTypes.size()==1 && _eltsTypes[0]==INTERP_KERNEL::NORM_HEXA8;
1309 Mesh::isStructured() const
1311 return _isStructured;
1314 std::vector< INTERP_KERNEL::NormalizedCellType >
1315 Mesh::getElementTypes() const
1320 std::vector< string >
1321 Mesh::getElementTypesNames() const
1323 std::vector< string > result(0);
1324 for(int i=0; i< _eltsTypes.size(); i++)
1326 if( _eltsTypes[i]==INTERP_KERNEL::NORM_POINT1)
1327 result.push_back("Points");
1328 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_SEG2)
1329 result.push_back("Segments");
1330 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_TRI3)
1331 result.push_back("Triangles");
1332 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_QUAD4)
1333 result.push_back("Quadrangles");
1334 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_POLYGON)
1335 result.push_back("Polygons");
1336 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_TETRA4)
1337 result.push_back("Tetrahedra");
1338 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_PYRA5)
1339 result.push_back("Pyramids");
1340 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_PENTA6)
1341 result.push_back("Pentahedra");
1342 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_HEXA8)
1343 result.push_back("Hexahedra");
1344 else if( _eltsTypes[i]==INTERP_KERNEL::NORM_POLYHED)
1345 result.push_back("Polyhedrons");
1348 cout<< "Mesh " + _name + " contains an element of type " <<endl;
1349 cout<< _eltsTypes[i]<<endl;
1350 throw CdmathException("Mesh::getElementTypes : recognised cell med types are NORM_POINT1, NORM_SEG2, NORM_TRI3, NORM_QUAD4, NORM_TETRA4, NORM_PYRA5, NORM_PENTA6, NORM_HEXA8, NORM_POLYGON, NORM_POLYHED");
1357 Mesh::setFaceGroups( const MEDFileUMesh* medmesh, MEDCouplingUMesh* mu)
1362 /* Searching for face groups */
1363 vector<string> faceGroups=medmesh->getGroupsNames() ;
1365 for (unsigned int i=0;i<faceGroups.size();i++ )
1367 string groupName=faceGroups[i];
1368 vector<mcIdType> nonEmptyGrp(medmesh->getGrpNonEmptyLevels(groupName));
1369 //We check if the group has a relative dimension equal to -1
1370 //before call to the function getGroup(-1,groupName.c_str())
1371 vector<mcIdType>::iterator it = find(nonEmptyGrp.begin(), nonEmptyGrp.end(), -1);
1372 if (it != nonEmptyGrp.end())
1374 MEDCouplingUMesh *m=medmesh->getGroup(-1,groupName.c_str());
1376 nbCellsSubMesh=m->getNumberOfCells();
1378 _faceGroups.insert(_faceGroups.end(),m);//Vector of group meshes
1379 _faceGroupNames.insert(_faceGroupNames.end(),groupName);//Vector of group names
1380 _faceGroupsIds.insert(_faceGroupsIds.end(),std::vector<int>(nbCellsSubMesh));//Vector of group face Ids. The filling of the face ids takes place below.
1382 DataArrayDouble *baryCell = m->computeIsoBarycenterOfNodesPerCell();//computeCellCenterOfMass() ;
1383 const double *coorBary=baryCell->getConstPointer();
1384 // Face identification
1385 for (int ic(0), k(0); ic<nbCellsSubMesh; ic++, k+=_spaceDim)
1387 vector<double> coorBaryXyz(3,0);
1388 for (int d=0; d<_spaceDim; d++)
1389 coorBaryXyz[d] = coorBary[k+d];
1390 Point p1(coorBaryXyz[0],coorBaryXyz[1],coorBaryXyz[2]) ;
1393 for (int iface=0;iface<_numberOfFaces;iface++ )
1395 Point p2=_faces.get()[iface].getBarryCenter();
1396 if(p1.distance(p2)<_epsilon)
1398 _faces.get()[iface].setGroupName(groupName);
1399 _faceGroupsIds[_faceGroupsIds.size()-1][ic]=iface;
1405 throw CdmathException("No face found for group " + groupName );
1407 baryCell->decrRef();
1413 Mesh::setNodeGroups( const MEDFileMesh* medmesh, MEDCouplingUMesh* mu)
1418 /* Searching for node groups */
1419 vector<string> nodeGroups=medmesh->getGroupsOnSpecifiedLev(1) ;
1421 for (unsigned int i=0;i<nodeGroups.size();i++ )
1423 string groupName=nodeGroups[i];
1424 DataArrayIdType * nodeGroup=medmesh->getNodeGroupArr( groupName );
1425 const mcIdType *nodeids=nodeGroup->getConstPointer();
1429 _nodeGroups.insert(_nodeGroups.end(),nodeGroup);
1430 _nodeGroupNames.insert(_nodeGroupNames.end(),groupName);
1432 nbNodesSubMesh=nodeGroup->getNumberOfTuples();//nodeGroup->getNbOfElems();
1434 DataArrayDouble *coo = mu->getCoords() ;
1435 const double *cood=coo->getConstPointer();
1437 _nodeGroupsIds.insert(_nodeGroupsIds.end(),std::vector<int>(nbNodesSubMesh));//Vector of boundary faces
1438 /* Node identification */
1439 for (int ic(0); ic<nbNodesSubMesh; ic++)
1441 vector<double> coorP(3,0);
1442 for (int d=0; d<_spaceDim; d++)
1443 coorP[d] = cood[nodeids[ic]*_spaceDim+d];
1444 Point p1(coorP[0],coorP[1],coorP[2]) ;
1447 for (int inode=0;inode<_numberOfNodes;inode++ )
1449 Point p2=_nodes.get()[inode].getPoint();
1450 if(p1.distance(p2)<_epsilon)
1452 _nodes.get()[inode].setGroupName(groupName);
1453 _nodeGroupsIds[_nodeGroupsIds.size()-1][ic]=inode;
1459 throw CdmathException("No node found for group " + groupName );
1465 //----------------------------------------------------------------------
1467 Mesh::getSpaceDimension( void ) const
1468 //----------------------------------------------------------------------
1473 //----------------------------------------------------------------------
1475 Mesh::getMeshDimension( void ) const
1476 //----------------------------------------------------------------------
1481 std::vector<mcIdType>
1482 Mesh::getCellGridStructure() const
1485 throw CdmathException("std::vector<int> Mesh::getCellGridStructure() : nx, ny and nz are defined only for structured meshes !");
1490 //----------------------------------------------------------------------
1492 Mesh::getNx( void ) const
1493 //----------------------------------------------------------------------
1496 throw CdmathException("int Mesh::getNx( void ) : Nx is defined only for structured meshes !");
1501 //----------------------------------------------------------------------
1503 Mesh::getNy( void ) const
1504 //----------------------------------------------------------------------
1507 throw CdmathException("int Mesh::getNy( void ) : Ny is defined only for structured meshes !");
1509 throw CdmathException("int Mesh::getNy( void ) : Ny is not defined for mesh dimension < 2!");
1514 //----------------------------------------------------------------------
1516 Mesh::getNz( void ) const
1517 //----------------------------------------------------------------------
1520 throw CdmathException("int Mesh::getNz( void ) : Nz is defined only for structured meshes !");
1522 throw CdmathException("int Mesh::getNz( void ) : Nz is not defined for mesh dimension < 3!");
1527 //----------------------------------------------------------------------
1529 Mesh::getXMin( void ) const
1530 //----------------------------------------------------------------------
1532 double Box0[2*_meshDim];
1533 _mesh->getBoundingBox(Box0);
1538 //----------------------------------------------------------------------
1540 Mesh::getXMax( void ) const
1541 //----------------------------------------------------------------------
1543 double Box0[2*_meshDim];
1544 _mesh->getBoundingBox(Box0);
1549 //----------------------------------------------------------------------
1551 Mesh::getYMin( void ) const
1552 //----------------------------------------------------------------------
1555 throw CdmathException("Mesh::getYMin : dimension should be >=2");
1557 double Box0[2*_meshDim];
1558 _mesh->getBoundingBox(Box0);
1563 //----------------------------------------------------------------------
1565 Mesh::getYMax( void ) const
1566 //----------------------------------------------------------------------
1569 throw CdmathException("Mesh::getYMax : dimension should be >=2");
1571 double Box0[2*_meshDim];
1572 _mesh->getBoundingBox(Box0);
1577 //----------------------------------------------------------------------
1579 Mesh::getZMin( void ) const
1580 //----------------------------------------------------------------------
1583 throw CdmathException("Mesh::getZMin : dimension should be 3");
1585 double Box0[2*_meshDim];
1586 _mesh->getBoundingBox(Box0);
1591 //----------------------------------------------------------------------
1593 Mesh::getZMax( void ) const
1594 //----------------------------------------------------------------------
1597 throw CdmathException("Mesh::getZMax : dimension should be 3");
1599 double Box0[2*_meshDim];
1600 _mesh->getBoundingBox(Box0);
1605 //----------------------------------------------------------------------
1606 MCAuto<MEDCouplingMesh>
1607 Mesh::getMEDCouplingMesh( void ) const
1608 //----------------------------------------------------------------------
1613 //----------------------------------------------------------------------
1615 Mesh::getNumberOfNodes ( void ) const
1616 //----------------------------------------------------------------------
1618 return _numberOfNodes ;
1621 //----------------------------------------------------------------------
1623 Mesh::getNumberOfCells ( void ) const
1624 //----------------------------------------------------------------------
1626 return _numberOfCells ;
1629 //----------------------------------------------------------------------
1631 Mesh::getNumberOfFaces ( void ) const
1632 //----------------------------------------------------------------------
1634 return _numberOfFaces ;
1637 //----------------------------------------------------------------------
1639 Mesh::getNumberOfEdges ( void ) const
1640 //----------------------------------------------------------------------
1642 return _numberOfEdges ;
1645 //----------------------------------------------------------------------
1646 std::shared_ptr<Face>
1647 Mesh::getFaces ( void ) const
1648 //----------------------------------------------------------------------
1653 //----------------------------------------------------------------------
1654 std::shared_ptr<Cell>
1655 Mesh::getCells ( void ) const
1656 //----------------------------------------------------------------------
1661 //----------------------------------------------------------------------
1663 Mesh::getCell ( int i ) const
1664 //----------------------------------------------------------------------
1666 return _cells.get()[i] ;
1669 //----------------------------------------------------------------------
1671 Mesh::getFace ( int i ) const
1672 //----------------------------------------------------------------------
1674 return _faces.get()[i] ;
1677 //----------------------------------------------------------------------
1679 Mesh::getNode ( int i ) const
1680 //----------------------------------------------------------------------
1682 return _nodes.get()[i] ;
1685 //----------------------------------------------------------------------
1686 std::shared_ptr<Node>
1687 Mesh::getNodes ( void ) const
1688 //----------------------------------------------------------------------
1694 Mesh::getNameOfFaceGroups( void ) const
1696 return _faceGroupNames;
1699 vector< std::vector<int> >
1700 Mesh::getFaceGroups( void ) const
1702 return _faceGroupsIds;
1705 vector<MEDCoupling::MEDCouplingUMesh *>
1706 Mesh::getMEDCouplingFaceGroups( void ) const
1712 Mesh::getNameOfNodeGroups( void ) const
1714 return _nodeGroupNames;
1717 vector< std::vector<int> >
1718 Mesh::getNodeGroups( void ) const
1720 return _nodeGroupsIds;
1724 vector<MEDCoupling::DataArrayIdType *>
1725 Mesh::getMEDCouplingNodeGroups( void ) const
1730 //----------------------------------------------------------------------
1732 Mesh::operator= ( const Mesh& mesh )
1733 //----------------------------------------------------------------------
1735 _spaceDim = mesh.getSpaceDimension() ;
1736 _meshDim = mesh.getMeshDimension() ;
1737 _name = mesh.getName();
1738 _epsilon=mesh.getComparisonEpsilon();
1739 _numberOfNodes = mesh.getNumberOfNodes();
1740 _numberOfFaces = mesh.getNumberOfFaces();
1741 _numberOfCells = mesh.getNumberOfCells();
1742 _numberOfEdges = mesh.getNumberOfEdges();
1744 _isStructured = mesh.isStructured();
1745 _meshNotDeleted = mesh.meshNotDeleted();
1748 _nxyz = mesh.getCellGridStructure() ;
1750 _faceGroupNames = mesh.getNameOfFaceGroups() ;
1751 _faceGroupsIds = mesh.getFaceGroups() ;
1752 _faceGroups = mesh.getMEDCouplingFaceGroups() ;
1753 _nodeGroupNames = mesh.getNameOfNodeGroups() ;
1754 _nodeGroupsIds = mesh.getNodeGroups() ;
1755 _nodeGroups = mesh.getMEDCouplingNodeGroups() ;
1757 _nodes = mesh.getNodes() ;
1758 _faces = mesh.getFaces() ;
1759 _cells = mesh.getCells() ;
1761 _indexFacePeriodicSet= mesh.isIndexFacePeriodicSet();
1762 if(_indexFacePeriodicSet)
1763 _indexFacePeriodicMap=mesh.getIndexFacePeriodic();
1765 _boundaryFaceIds=mesh.getBoundaryFaceIds();
1766 _boundaryNodeIds=mesh.getBoundaryNodeIds();
1768 _eltsTypes=mesh.getElementTypes();
1769 _eltsTypesNames=mesh.getElementTypesNames();
1771 _mesh=mesh.getMEDCouplingMesh()->clone(false);//Clone because you will need to buildUnstructured. No deep copy : it is assumed node coordinates and cell connectivity will not change
1776 bool Mesh::isIndexFacePeriodicSet() const
1778 return _indexFacePeriodicSet;
1780 //----------------------------------------------------------------------
1782 Mesh::minRatioVolSurf() const
1784 double dx_min = 1e30;
1785 for(int i=0; i<_numberOfCells; i++)
1787 Cell Ci = getCell(i);
1791 for(int k=0; k< Ci.getNumberOfFaces(); k++)
1793 int indexFace=Ci.getFacesId()[k];
1794 Face Fk = getFace(indexFace);
1795 perimeter+=Fk.getMeasure();
1797 dx_min = min(dx_min,Ci.getMeasure()/perimeter);
1800 dx_min = min(dx_min,Ci.getMeasure());
1807 Mesh::getBoundaryMesh ( void ) const
1809 return Mesh(_boundaryMesh);
1813 Mesh::getBoundaryGroupMesh ( std::string groupName, int nth_occurence ) const
1815 //count occurences of groupName in known group name list
1816 int count_occurences = std::count (_faceGroupNames.begin(),_faceGroupNames.end(),groupName);
1818 if( count_occurences ==0 )//No group found
1820 cout<<"Mesh::getBoundaryGroupMesh Error : face group " << groupName << " does not exist"<<endl;
1821 cout<<"Known face group names are " ;
1822 for(int i=0; i<_faceGroupNames.size(); i++)
1823 cout<< _faceGroupNames[i]<<" ";
1825 throw CdmathException("Required face group does not exist");
1827 else if ( count_occurences <= nth_occurence)//Too many groups found
1829 cout<<"Mesh::getBoundaryGroupMesh Error : "<<count_occurences<<" groups have name " << groupName<<", but you asked fo occurencer number "<<nth_occurence<<"which is too large"<<endl;
1830 cout<<"Call function getBoundaryGroupMesh ( string groupName, int nth_group_match ) with nth_group_match between 0 and "<<count_occurences-1<<" to discriminate them "<<endl ;
1831 throw CdmathException("Several face groups have the same name but you asked for an occurence that does not exsit");
1833 else if( count_occurences >1 )//Wrning several groups found
1834 cout<<"Warning : "<<count_occurences<<" groups have name " << groupName<<". Searching occurence number "<<nth_occurence<<endl;
1836 //search occurence of group name in known group name list
1837 std::vector<std::string>::const_iterator it = _faceGroupNames.begin();
1838 for (int i = 0; i<nth_occurence+1; i++)
1839 it = std::find(it,_faceGroupNames.end(),groupName);
1841 return Mesh(_faceGroups[it - _faceGroupNames.begin()]);
1845 Mesh::getMaxNbNeighbours(EntityType type) const
1851 int nbNeib;//local number of neighbours
1852 for(int i=0; i<_numberOfCells; i++)
1854 Cell Ci = _cells.get()[i];
1855 //Careful with mesh with junctions : do not just take Ci.getNumberOfFaces()
1857 for(int j=0; j<Ci.getNumberOfFaces(); j++)
1858 nbNeib+=_faces.get()[Ci.getFacesId()[j]].getNumberOfCells()-1;//Without junction this would be +=1
1864 else if(type==NODES)
1866 for(int i=0; i<_numberOfNodes; i++)
1867 if(result < _nodes.get()[i].getNumberOfEdges())
1868 result=_nodes.get()[i].getNumberOfEdges();
1871 throw CdmathException("Mesh::getMaxNbNeighbours : entity type is not accepted. Should be CELLS or NODES");
1875 //----------------------------------------------------------------------
1877 Mesh::writeVTK ( const std::string fileName ) const
1878 //----------------------------------------------------------------------
1880 if( !_meshNotDeleted )
1881 throw CdmathException("Mesh::writeVTK : Cannot save mesh : no MEDCouplingMesh loaded (may be deleted)");
1883 string fname=fileName+".vtu";
1884 _mesh->writeVTK(fname.c_str()) ;
1887 //----------------------------------------------------------------------
1889 Mesh::writeMED ( const std::string fileName, bool fromScratch ) const
1890 //----------------------------------------------------------------------
1892 if( !_meshNotDeleted )
1893 throw CdmathException("Mesh::writeMED : Cannot save mesh : no MEDCouplingMesh loaded (may be deleted)");
1895 string fname=fileName+".med";
1896 if(_isStructured)//Check if we have a medcouplingimesh that can't be written directly
1898 const MEDCoupling::MEDCouplingIMesh* iMesh = dynamic_cast< const MEDCoupling::MEDCouplingIMesh* > ((const MEDCoupling::MEDCouplingMesh*) _mesh);
1899 if(iMesh)//medcouplingimesh : Use convertToCartesian in order to write mesh
1900 MEDCoupling::WriteMesh(fname.c_str(),iMesh->convertToCartesian(), fromScratch);
1901 else//medcouplingcmesh : save directly
1902 MEDCoupling::WriteMesh(fname.c_str(),_mesh, fromScratch);
1905 MEDCoupling::WriteMesh(fname.c_str(),_mesh, fromScratch);
1907 /* Try to save mesh groups */
1908 //MEDFileUMesh meshMEDFile;
1909 //meshMEDFile.setMeshAtLevel(0,mu);
1910 //for(int i=0; i< _faceGroups.size(); i++)
1911 //meshMEDFile.setMeshAtLevel(-1,_faceGroups[i]);
1913 //MEDCoupling::meshMEDFile.write(fname.c_str(),2) ;
1915 //MEDCoupling::meshMEDFile.write(fname.c_str(),1) ;
1919 Mesh::getFaceGroupIds(std::string groupName, bool isBoundaryGroup) const
1921 std::vector<std::string>::const_iterator it = std::find(_faceGroupNames.begin(),_faceGroupNames.end(),groupName);
1922 if( it == _faceGroupNames.end() )
1924 cout<<"Mesh::getGroupFaceIds Error : face group " << groupName << " does not exist"<<endl;
1925 throw CdmathException("Required face group does not exist");
1929 return _faceGroupsIds[it-_faceGroupNames.begin()];
1934 Mesh::getNodeGroupIds(std::string groupName, bool isBoundaryGroup) const
1936 std::vector<std::string>::const_iterator it = std::find(_nodeGroupNames.begin(),_nodeGroupNames.end(),groupName);
1937 if( it == _nodeGroupNames.end() )
1939 cout<<"Mesh::getGroupNodeIds Error : node group " << groupName << " does not exist"<<endl;
1940 throw CdmathException("Required node group does not exist");
1943 return _nodeGroupsIds[it-_nodeGroupNames.begin()];
1947 Mesh::setFaceGroupByIds(std::vector< int > faceIds, std::string groupName)
1949 for(int i=0; i< faceIds.size(); i++)
1950 getFace(faceIds[i]).setGroupName(groupName);
1952 _faceGroupsIds.insert( _faceGroupsIds.end(),faceIds);
1953 _faceGroupNames.insert(_faceGroupNames.end(), groupName);
1954 _faceGroups.insert( _faceGroups.end(), NULL);
1958 Mesh::setNodeGroupByIds(std::vector< int > nodeIds, std::string groupName)
1960 for(int i=0; i< nodeIds.size(); i++)
1961 getNode(nodeIds[i]).setGroupName(groupName);
1964 void Mesh::deleteMEDCouplingMesh()
1968 (_mesh.retn())->decrRef();
1969 _meshNotDeleted=false;
1972 throw CdmathException("Mesh::deleteMEDCouplingMesh() : mesh is not loaded");