00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef CONNECTIVITY_BUILDER_HPP
00021 #define CONNECTIVITY_BUILDER_HPP
00022
00023 #include <set>
00024 #include <limits>
00025 #include <list>
00026 #include <map>
00027
00028 #include <TinyVector.hpp>
00029 #include <Connectivity.hpp>
00030 #include <ReferenceCounting.hpp>
00031
00032 #include <Mesh.hpp>
00033
00034 #include <Stringify.hpp>
00035 #include <ErrorHandler.hpp>
00036
00037 template <unsigned meshFamily>
00038 struct BorderLinker;
00039
00053 template <typename MeshType>
00054 class ConnectivityBuilder
00055 {
00056 private:
00057 MeshType& __mesh;
00058
00059 bool __buildCellToCells;
00060 bool __buildCellToFaces;
00061 bool __buildCellToEdges;
00062 bool __buildCellToVertices;
00063 bool __buildFaceToCells;
00064 bool __buildFaceToEdges;
00065 bool __buildFaceToVertices;
00066 bool __buildEdgeToCells;
00067 bool __buildEdgeToFaces;
00068 bool __buildEdgeToVertices;
00069 bool __buildVertexToCell;
00070 bool __buildVertexToFaces;
00071 bool __buildVertexToEdges;
00072 bool __buildVertexToVertices;
00073 bool __buildVertexToVerticesGeneralized;
00075 friend
00076 struct BorderLinker<MeshType::family>;
00077
00078 typedef typename MeshType::CellType CellType;
00079 typedef typename CellType::FaceType FaceType;
00080
00081 void __getOptions(const size_t& buildType)
00082 {
00083 if ((buildType>>15)!=0) {
00084 throw ErrorHandler(__FILE__,__LINE__,
00085 "unknown connectivity type",
00086 ErrorHandler::unexpected);
00087 }
00088 __buildCellToCells
00089 = (Connectivity<MeshType>::CellToCells & buildType);
00090 __buildCellToFaces
00091 = (Connectivity<MeshType>::CellToFaces & buildType);
00092 __buildCellToEdges
00093 = (Connectivity<MeshType>::CellToEdges & buildType);
00094 __buildCellToVertices
00095 = (Connectivity<MeshType>::CellToVertices & buildType);
00096 __buildFaceToCells
00097 = (Connectivity<MeshType>::FaceToCells & buildType);
00098 __buildFaceToEdges
00099 = (Connectivity<MeshType>::FaceToEdges & buildType);
00100 __buildFaceToVertices
00101 = (Connectivity<MeshType>::FaceToVertices & buildType);
00102 __buildEdgeToCells
00103 = (Connectivity<MeshType>::EdgeToCells & buildType);
00104 __buildEdgeToFaces
00105 = (Connectivity<MeshType>::EdgeToFaces & buildType);
00106 __buildEdgeToVertices
00107 = (Connectivity<MeshType>::EdgeToVertices & buildType);
00108 __buildVertexToCell
00109 = (Connectivity<MeshType>::VertexToCell & buildType);
00110 __buildVertexToFaces
00111 = (Connectivity<MeshType>::VertexToFaces & buildType);
00112 __buildVertexToEdges
00113 = (Connectivity<MeshType>::VertexToEdges & buildType);
00114 __buildVertexToVertices
00115 = (Connectivity<MeshType>::VertexToVertices & buildType);
00116 __buildVertexToVerticesGeneralized
00117 = (Connectivity<MeshType>::VertexToVerticesGeneralized & buildType);
00118 }
00119
00124 ConnectivityBuilder(const ConnectivityBuilder<MeshType>&);
00125
00126
00127 typedef TinyVector<FaceType::NumberOfVertices, size_t> FaceVerticesList;
00128 typedef std::pair<const CellType*, size_t> CellFace;
00129 typedef std::map<FaceVerticesList,
00130 std::list<CellFace> > FaceToCellMapping;
00131
00132 FaceToCellMapping __faceToCells;
00133
00138 void __faceToCellsConstruction()
00139 {
00140 ffout(4) << " - building face to cells mapping...\n";
00141 if (not(__faceToCells.empty())) {
00142 ffout(4) << "already done\n";
00143 return;
00144 }
00145
00146 if (not(__mesh.hasFaces())) {
00147 __mesh.buildFaces();
00148 }
00149
00150 for (typename MeshType::const_iterator i(__mesh); not(i.end()); ++i) {
00151 for (size_t l=0; l<CellType::NumberOfFaces; ++l) {
00152 std::set<size_t> verticesSet;
00153 for (size_t k=0; k<FaceType::NumberOfVertices; ++k) {
00154 const size_t vertexNumber
00155 = __mesh.vertexNumber((*i)(CellType::faces[l][k]));
00156 verticesSet.insert(__mesh.correspondance(vertexNumber));
00157 }
00158 FaceVerticesList vertices;
00159 size_t k=0;
00160 for (std::set<size_t>::iterator n=verticesSet.begin();
00161 n != verticesSet.end(); ++n) {
00162 vertices[k++]=*n;
00163 }
00164 __faceToCells[vertices].push_back(CellFace(i.pointer(),l));
00165 }
00166 }
00167 ffout(4) << "done\n";
00168 if (__buildFaceToCells) {
00169 ffout(3) << "- Storing face to cells connectivity\n";
00170 if (__mesh.connectivity().hasFaceToCells()) {
00171 ffout(4) << "already done\n";
00172 return;
00173 }
00174
00175 typedef
00176 typename Connectivity<MeshType>::FaceToCellsType
00177 FaceToCellsType;
00178
00179 ReferenceCounting<Vector<FaceToCellsType> > pFaceToCells
00180 = new Vector<FaceToCellsType>(__faceToCells.size());
00181 Vector<FaceToCellsType>& faceToCells = *pFaceToCells;
00182
00183 size_t faceNumber = 0;
00184 for (typename FaceToCellMapping::iterator i = __faceToCells.begin();
00185 i != __faceToCells.end(); ++i) {
00186 typename FaceToCellMapping::mapped_type& faceList
00187 = (*i).second;
00188
00189 switch (faceList.size()) {
00190 case 1: {
00191 typename FaceToCellMapping::mapped_type::iterator j
00192 = (*i).second.begin();
00193 faceToCells[faceNumber][0]=(*j);
00194 faceToCells[faceNumber][1]= std::make_pair(static_cast<CellType*>(0),
00195 std::numeric_limits<size_t>::max());
00196 break;
00197 }
00198 case 2: {
00199 typename FaceToCellMapping::mapped_type::iterator j1 = (*i).second.begin();
00200 typename FaceToCellMapping::mapped_type::iterator j2 = j1;
00201 j2++;
00202
00203 faceToCells[faceNumber][0] = (*j2);
00204 faceToCells[faceNumber][1] = (*j1);
00205 break;
00206 }
00207 default: {
00208 fferr(0) << "\noops: Something strange happened: incorrect mesh:\n";
00209 fferr(0) << " One of the faces of your mesh is related to "
00210 << faceList.size() << " cells (vertices: " << (*i).first << ")\n"; ;
00211 #ifndef NDEBUG
00212 throw ErrorHandler(__FILE__,__LINE__,
00213 "stopping execution since debug mode is activated",
00214 ErrorHandler::unexpected);
00215 #endif // NDEBUG
00216 }
00217 }
00218 faceNumber++;
00219 }
00220 __mesh.connectivity().setFaceToCells(pFaceToCells);
00221
00222 }
00223 }
00224
00229 void __cellToCellsConstruction()
00230 {
00231 this->__faceToCellsConstruction();
00232 ffout(3) << "- Storing cell to cells connectivity\n";
00233
00234 if (__mesh.connectivity().hasCellToCells()) {
00235 ffout(4) << "already done\n";
00236 return;
00237 }
00238
00239 if (not(__mesh.hasFaces())) {
00240 __mesh.buildFaces();
00241 }
00242
00243 typedef
00244 typename Connectivity<MeshType>::CellToCellsType
00245 CellToCellsType;
00246
00247 ReferenceCounting<Vector<CellToCellsType> > pCellToCells
00248 = new Vector<CellToCellsType>(__mesh.numberOfCells());
00249 Vector<CellToCellsType>& cellToCells = *pCellToCells;
00250
00251 for (typename FaceToCellMapping::iterator i
00252 = __faceToCells.begin();
00253 i != __faceToCells.end(); ++i) {
00254 typename FaceToCellMapping::mapped_type& faceList
00255 = (*i).second;
00256
00257 switch (faceList.size()) {
00258 case 1: {
00259 typename FaceToCellMapping::mapped_type::iterator j
00260 = (*i).second.begin();
00261
00262 cellToCells(__mesh.cellNumber(*(*j).first))[(*j).second] = 0;
00263 break;
00264 }
00265 case 2: {
00266 typename FaceToCellMapping::mapped_type::iterator j1 = (*i).second.begin();
00267 typename FaceToCellMapping::mapped_type::iterator j2 = j1;
00268 j2++;
00269
00270 cellToCells(__mesh.cellNumber(*(*j1).first))[(*j1).second] = (*j2).first;
00271 cellToCells(__mesh.cellNumber(*(*j2).first))[(*j2).second] = (*j1).first;
00272
00273 break;
00274 }
00275 default: {
00276 fferr(0) << "\noops: Something strange happened: incorrect mesh:\n";
00277 fferr(0) << " One of the faces of your mesh is related to "
00278 << faceList.size() << " cells (vertices: " << (*i).first << ")\n";
00279 for(typename FaceToCellMapping::mapped_type::iterator j = faceList.begin();
00280 j != faceList.end(); ++j) {
00281 const CellType& K = *(*j).first;
00282 fferr(0) << "Cell " << (*j).second << ':';
00283 for (size_t k=0; k<CellType::NumberOfVertices; ++k) {
00284 fferr(0) << ' ' << __mesh.vertexNumber(K(k));
00285 }
00286 fferr(0) << '\n';
00287 }
00288 }
00289 }
00290 }
00291 __mesh.connectivity().setCellToCells(pCellToCells);
00292 }
00293
00298 void __cellToFacesConstruction()
00299 {
00300 this->__faceToCellsConstruction();
00301 ffout(3) << "- Storing cell to faces connectivity\n";
00302 if (__mesh.connectivity().hasCellToFaces()) {
00303 ffout(3) << "already done\n";
00304 return;
00305 }
00306
00307 if (not(__mesh.hasFaces())) {
00308 __mesh.buildFaces();
00309 }
00310
00311 typedef
00312 typename Connectivity<MeshType>::CellToFacesType
00313 CellToFacesType;
00314
00315 ReferenceCounting<Vector<CellToFacesType> > pCellToFaces
00316 = new Vector<CellToFacesType>(__mesh.numberOfCells());
00317
00318 Vector<CellToFacesType>& cellToFaces = *pCellToFaces;
00319 size_t faceNumber = 0;
00320 for (typename FaceToCellMapping::iterator i = __faceToCells.begin();
00321 i != __faceToCells.end(); ++i) {
00322 const std::list<CellFace>& cellList = (*i).second;
00323 for (typename std::list<CellFace>::const_iterator j = cellList.begin();
00324 j != (*i).second.end(); ++j) {
00325 const size_t cellNumber = __mesh.cellNumber(*(*j).first);
00326 const size_t localFaceNumber = (*j).second;
00327 cellToFaces[cellNumber][localFaceNumber]
00328 = &__mesh.face(faceNumber);
00329 }
00330 faceNumber++;
00331 }
00332
00333 __mesh.connectivity().setCellToFaces(pCellToFaces);
00334 }
00335
00340 void __cellToEdgesConstruction()
00341 {
00342 ffout(3) << "- Storing cell to edges connectivity\n";
00343
00344 if (__mesh.connectivity().hasCellToEdges()) {
00345 ffout(4) << "already done\n";
00346 return;
00347 }
00348
00349 if (not(__mesh.hasEdges())) {
00350 __mesh.buildEdges();
00351 }
00352
00353 typedef TinyVector<2, size_t> EdgeVerticesList;
00354 typedef std::pair<const CellType*, size_t> CellEdge;
00355 typedef std::map<EdgeVerticesList,
00356 std::list<CellEdge> > EdgeToCellMapping;
00357
00358 if (__mesh.numberOfEdges() == 0) {
00359 throw ErrorHandler(__FILE__,__LINE__,
00360 "edge list not built",
00361 ErrorHandler::unexpected);
00362 }
00363
00364 EdgeToCellMapping edgeToCells;
00365
00366 for (typename MeshType::const_iterator icell(__mesh); not(icell.end()); ++icell) {
00367 for (size_t l=0; l<CellType::NumberOfEdges; ++l) {
00368 std::set<size_t> verticesSet;
00369 for (size_t k=0; k<2; ++k) {
00370 const size_t vertexNumber
00371 = __mesh.vertexNumber((*icell)(CellType::edges[l][k]));
00372 verticesSet.insert(__mesh.correspondance(vertexNumber));
00373 }
00374 EdgeVerticesList vertices;
00375 size_t k=0;
00376 for (std::set<size_t>::iterator n=verticesSet.begin();
00377 n != verticesSet.end(); ++n) {
00378 vertices[k++] = *n;
00379 }
00380 edgeToCells[vertices].push_back(CellFace(icell.pointer(),l));
00381 }
00382 }
00383
00384 typedef typename Connectivity<MeshType>::CellToEdgesType CellToEdgesType;
00385
00386 ReferenceCounting<Vector<CellToEdgesType> >
00387 pCellToEdges = new Vector<CellToEdgesType>(__mesh.numberOfCells());
00388 Vector<CellToEdgesType>& cellToEdges = *pCellToEdges;
00389
00390 for (size_t i=0; i<__mesh.numberOfEdges(); ++i) {
00391 const Edge& edge = __mesh.edge(i);
00392 std::set<size_t> edgeVerticesSet;
00393 for (size_t k=0; k<2; ++k) {
00394 const size_t vertexNumber = __mesh.vertexNumber(edge(k));
00395 edgeVerticesSet.insert(__mesh.correspondance(vertexNumber));
00396 }
00397
00398 size_t k=0;
00399 EdgeVerticesList vertices;
00400
00401 for (std::set<size_t>::iterator n=edgeVerticesSet.begin();
00402 n != edgeVerticesSet.end(); ++n) {
00403 vertices[k++]=*n;
00404 }
00405 typename EdgeToCellMapping::iterator ie
00406 = edgeToCells.find(vertices);
00407 if (ie == edgeToCells.end()) {
00408 fferr(0) << "\noops: Something strange happened: incorrect mesh:\n";
00409 fferr(0) << " One of the edges of your mesh is related to "
00410 << " no cells (vertices: " << (*ie).first << ")\n";
00411 #ifndef NDEBUG
00412 throw ErrorHandler(__FILE__,__LINE__,
00413 "stopping execution since debug mode is activated",
00414 ErrorHandler::unexpected);
00415 #endif // NDEBUG
00416 }
00417 for (typename EdgeToCellMapping::mapped_type::iterator
00418 j = ie->second.begin();
00419 j != ie->second.end(); ++j) {
00420 const CellType& cell = *j->first;
00421 const size_t edgeNumber = j->second;
00422 cellToEdges(__mesh.cellNumber(cell))[edgeNumber] = &edge;
00423 }
00424 }
00425 __mesh.connectivity().setCellToEdges(pCellToEdges);
00426 }
00427
00432 void __vertexToCellConstruction()
00433 {
00434 ffout(3) << "- Storing Vertex to Cells connectivity\n";
00435
00436 if (__mesh.connectivity().hasVertexToCells()) {
00437 ffout(4) << "already done\n";
00438 return;
00439 }
00440
00441 typedef
00442 typename Connectivity<MeshType>::VertexToCellsType
00443 VertexToCellsType;
00444
00445 ReferenceCounting<Vector<VertexToCellsType> > pVertexToCells
00446 = new Vector<VertexToCellsType>(__mesh.numberOfVertices());
00447 Vector<VertexToCellsType>& vertexToCells = *pVertexToCells;
00448
00449 for (typename MeshType::const_iterator i(__mesh); not(i.end()); ++i) {
00450 const CellType& cell = *i;
00451 for (size_t n=0; n<CellType::NumberOfVertices; ++n) {
00452 const size_t vertexNumber = __mesh.vertexNumber(cell(n));
00453 vertexToCells[__mesh.correspondance(vertexNumber)].insert(&cell);
00454 }
00455 }
00456
00457 __mesh.connectivity().setVertexToCells(pVertexToCells);
00458 }
00459
00465 void __vertexToVerticesGeneralizedConstruction()
00466 {
00467 ffout(3) << "- Storing Vertex to Vertices connectivity\n";
00468
00469 if (__mesh.connectivity().hasVertexToVericesGeneralized()) {
00470 ffout(4) << "already done\n";
00471 return;
00472 }
00473
00474 typedef
00475 typename Connectivity<MeshType>::VertexToVerticesType
00476 VertexToVerticesType;
00477
00478 ReferenceCounting<Vector<VertexToVerticesType> > pVertexToVertices
00479 = new Vector<VertexToVerticesType>(__mesh.numberOfVertices());
00480 Vector<VertexToVerticesType>& vertexToVertices = *pVertexToVertices;
00481
00482 for (typename MeshType::const_iterator i(__mesh); not(i.end()); ++i) {
00483 const CellType& cell = *i;
00484 for (size_t n=0; n<CellType::NumberOfVertices; ++n) {
00485 for (size_t m=0; m<CellType::NumberOfVertices; ++m) {
00486 if (m != n) {
00487 vertexToVertices[__mesh.vertexNumber(cell(n))].insert(&cell(m));
00488 }
00489 }
00490 }
00491 }
00492
00493 __mesh.connectivity().setVertexToVerticesGeneralized(pVertexToVertices);
00494 }
00495
00496 public:
00497
00503 void generates(const size_t& buildType)
00504 {
00505 this->__getOptions(buildType);
00506
00507 if (__buildCellToCells) {
00508 this->__cellToCellsConstruction();
00509 }
00510 if (__buildCellToFaces) {
00511 this->__cellToFacesConstruction();
00512 }
00513 if (__buildCellToEdges) {
00514 this->__cellToEdgesConstruction();
00515 }
00516 if (__buildCellToVertices) {
00517 throw ErrorHandler(__FILE__,__LINE__,
00518 "not implemented",
00519 ErrorHandler::unexpected);
00520 }
00521 if (__buildFaceToCells) {
00522 this->__faceToCellsConstruction();
00523 }
00524 if (__buildFaceToEdges) {
00525 throw ErrorHandler(__FILE__,__LINE__,
00526 "not implemented",
00527 ErrorHandler::unexpected);
00528 }
00529 if (__buildFaceToVertices) {
00530 throw ErrorHandler(__FILE__,__LINE__,
00531 "not implemented",
00532 ErrorHandler::unexpected);
00533 }
00534 if (__buildEdgeToCells) {
00535 throw ErrorHandler(__FILE__,__LINE__,
00536 "not implemented",
00537 ErrorHandler::unexpected);
00538 }
00539 if (__buildEdgeToFaces) {
00540 throw ErrorHandler(__FILE__,__LINE__,
00541 "not implemented",
00542 ErrorHandler::unexpected);
00543 }
00544 if (__buildEdgeToVertices) {
00545 throw ErrorHandler(__FILE__,__LINE__,
00546 "not implemented",
00547 ErrorHandler::unexpected);
00548 }
00549 if (__buildVertexToCell) {
00550 this->__vertexToCellConstruction();
00551 }
00552 if (__buildVertexToFaces) {
00553 throw ErrorHandler(__FILE__,__LINE__,
00554 "not implemented",
00555 ErrorHandler::unexpected);
00556 }
00557 if (__buildVertexToEdges) {
00558 throw ErrorHandler(__FILE__,__LINE__,
00559 "not implemented",
00560 ErrorHandler::unexpected);
00561 }
00562 if (__buildVertexToVertices) {
00563 throw ErrorHandler(__FILE__,__LINE__,
00564 "not implemented",
00565 ErrorHandler::unexpected);
00566 }
00567 if (__buildVertexToVerticesGeneralized) {
00568 this->__vertexToVerticesGeneralizedConstruction();
00569 }
00570 }
00571
00572 void borderMesh(ReferenceCounting<typename MeshType::BorderMeshType>& border)
00573 {
00574 BorderLinker<MeshType::family>(__mesh, *this, border);
00575 }
00576
00577 ConnectivityBuilder(const MeshType& m)
00578 : __mesh(const_cast<MeshType&>(m)),
00579 __buildCellToCells(false),
00580 __buildCellToFaces(false),
00581 __buildCellToEdges(false),
00582 __buildCellToVertices(false),
00583 __buildFaceToCells(false),
00584 __buildFaceToEdges(false),
00585 __buildFaceToVertices(false),
00586 __buildEdgeToCells(false),
00587 __buildEdgeToFaces(false),
00588 __buildEdgeToVertices(false),
00589 __buildVertexToCell(false),
00590 __buildVertexToFaces(false),
00591 __buildVertexToEdges(false)
00592 {
00593 ffout(3) << "Starting connectivity builder\n";
00594 }
00595
00596 ~ConnectivityBuilder()
00597 {
00598 ffout(3) << "Connectivity builder finished\n";
00599 }
00600 };
00601
00602 template<unsigned meshFamily>
00603 struct BorderLinker
00604 {
00605 template <typename MeshType>
00606 BorderLinker(const MeshType& m,
00607 const typename ConnectivityBuilder<MeshType>::FaceCorrespondance& faces,
00608 ReferenceCounting<typename MeshType::BorderMeshType>)
00609 {
00610 ;
00611 }
00612 };
00613
00614 template<>
00615 struct BorderLinker<Mesh::volume>
00616 {
00617 template <typename MeshType>
00618 BorderLinker(const MeshType& m,
00619 ConnectivityBuilder<MeshType>& connectivityBuilder,
00620 ReferenceCounting<typename MeshType::BorderMeshType> border)
00621 {
00622 if (border != 0) {
00623 connectivityBuilder.__faceToCellsConstruction();
00624
00625 ffout(3) << "- Connecting border mesh\n";
00626 const typename ConnectivityBuilder<MeshType>::FaceToCellMapping&
00627 faceToCells = connectivityBuilder.__faceToCells;
00628
00629 for (typename MeshType::BorderMeshType::iterator i(*border);
00630 not(i.end()); ++i) {
00631 std::set<size_t> verticesSet;
00632 for (size_t k=0; k<ConnectivityBuilder<MeshType>::FaceType::NumberOfVertices; ++k) {
00633 const size_t vertexNumber = m.vertexNumber((*i)(k));
00634 verticesSet.insert(m.correspondance(vertexNumber));
00635 }
00636 size_t k=0;
00637 typename ConnectivityBuilder<MeshType>::FaceVerticesList vertices;
00638 for (std::set<size_t>::iterator n=verticesSet.begin();
00639 n != verticesSet.end(); ++n) {
00640 vertices[k++]=*n;
00641 }
00642 typename ConnectivityBuilder<MeshType>::FaceToCellMapping
00643 ::const_iterator icell = faceToCells.find(vertices);
00644 if (icell != faceToCells.end()) {
00645 (*i).setMother(icell->second.begin()->first, icell->second.begin()->second);
00646 } else {
00647 const std::string errorMsg
00648 = "boundary element number "+stringify(border->cellNumber(*i))
00649 +" is not related to any cell of the mesh\n";
00650 throw ErrorHandler(__FILE__,__LINE__,
00651 errorMsg,
00652 ErrorHandler::normal);
00653
00654 }
00655 }
00656 }
00657 }
00658 };
00659
00660
00661 #endif // CONNECTIVITY_BUILDER_HPP