1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 cfMesh is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "polyMeshGenCells.H"
29 #include "polyMeshGenAddressing.H"
30 #include "IOobjectList.H"
32 #include "demandDrivenData.H"
34 #include "labelPair.H"
43 // * * * * * * * * * * Private member functions * * * * * * * * * * * * * * * //
45 void polyMeshGenCells::calculateOwnersAndNeighbours() const
47 if( ownerPtr_ || neighbourPtr_ )
50 "void polyMeshGenCells::calculateOwnersAndNeighbours() const"
51 ) << "Owners and neighbours are already allocated" << abort(FatalError);
66 labelIOList& own = *ownerPtr_;
68 //- allocate neighbours
81 labelIOList& nei = *neighbourPtr_;
83 //- start calculating owners and neighbours
87 const label nThreads = 3 * omp_get_num_procs();
88 const label chunkSize = faces_.size() / nThreads + 1;
90 const label nThreads = 1;
91 const label chunkSize = faces_.size();
94 label nInternalFaces(0);
96 List<List<LongList<labelPair> > > dataForOtherThreads(nThreads);
99 # pragma omp parallel num_threads(nThreads) reduction(+ : nInternalFaces)
103 const label threadI = omp_get_thread_num();
105 const label threadI(0);
108 const label startingFace = threadI * chunkSize;
109 const label endFace =
110 Foam::min(startingFace + chunkSize, faces_.size());
112 List<LongList<labelPair> >& dot = dataForOtherThreads[threadI];
113 dot.setSize(nThreads);
115 for(label faceI=startingFace;faceI<endFace;++faceI)
122 # pragma omp for schedule(static)
124 forAll(cells_, cellI)
126 const cell& c = cells_[cellI];
130 const label faceI = c[fI];
132 const label threadNo = faceI / chunkSize;
134 if( threadNo == threadI )
136 if( own[faceI] == -1 )
140 else if( nei[faceI] == -1 )
147 Serr << "Face " << faces_[faceI] << endl;
148 Serr << "Owner " << own[faceI] << endl;
149 Serr << "Neighbour " << nei[faceI] << endl;
150 Serr << "Current cell " << cellI << endl;
153 "void polyMeshGenCells::"
154 "calculateOwnersAndNeighbours()"
155 ) << Pstream::myProcNo() << "Face " << faceI
156 << " appears in more than 2 cells!!"
157 << abort(FatalError);
162 dot[threadNo].append(labelPair(faceI, cellI));
170 # pragma omp critical
172 for(label i=0;i<nThreads;++i)
174 const LongList<labelPair>& data =
175 dataForOtherThreads[i][threadI];
179 const label faceI = data[j].first();
180 const label cellI = data[j].second();
182 if( own[faceI] == -1 )
186 else if( own[faceI] > cellI )
188 if( nei[faceI] == -1 )
190 nei[faceI] = own[faceI];
196 Serr << "Face " << faces_[faceI] << endl;
197 Serr << "Owner " << own[faceI] << endl;
198 Serr << "Neighbour " << nei[faceI] << endl;
199 Serr << "Current cell " << cellI << endl;
202 "void polyMeshGenCells::"
203 "calculateOwnersAndNeighbours()"
204 ) << Pstream::myProcNo() << "Face " << faceI
205 << " appears in more than 2 cells!!"
206 << abort(FatalError);
209 else if( nei[faceI] == -1 )
216 Serr << "Face " << faces_[faceI] << endl;
217 Serr << "Owner " << own[faceI] << endl;
218 Serr << "Neighbour " << nei[faceI] << endl;
219 Serr << "Current cell " << cellI << endl;
222 "void polyMeshGenCells::"
223 "calculateOwnersAndNeighbours()"
224 ) << Pstream::myProcNo() << "Face " << faceI
225 << " appears in more than 2 cells!!"
226 << abort(FatalError);
232 nIntFaces_ = nInternalFaces;
235 void polyMeshGenCells::calculateAddressingData() const
237 if( !ownerPtr_ || !neighbourPtr_ )
240 if( omp_in_parallel() )
243 "inline label polyMeshGenCells::calculateAddressingData() const"
244 ) << "Calculating addressing inside a parallel region."
245 << " This is not thread safe" << exit(FatalError);
248 calculateOwnersAndNeighbours();
251 addressingDataPtr_ = new polyMeshGenAddressing(*this);
254 void polyMeshGenCells::clearOut() const
256 polyMeshGenFaces::clearOut();
257 deleteDemandDrivenData(addressingDataPtr_);
260 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
263 polyMeshGenCells::polyMeshGenCells(const Time& runTime)
265 polyMeshGenFaces(runTime),
268 addressingDataPtr_(NULL)
272 //- Construct from components without the boundary
273 polyMeshGenCells::polyMeshGenCells
276 const pointField& points,
277 const faceList& faces,
278 const cellList& cells
281 polyMeshGenFaces(runTime, points, faces),
284 addressingDataPtr_(NULL)
289 //- Construct from components with the boundary
290 polyMeshGenCells::polyMeshGenCells
293 const pointField& points,
294 const faceList& faces,
295 const cellList& cells,
296 const wordList& patchNames,
297 const labelList& patchStart,
298 const labelList& nFacesInPatch
312 addressingDataPtr_(NULL)
317 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
319 polyMeshGenCells::~polyMeshGenCells()
324 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
326 //- return addressing which may be needed
327 const polyMeshGenAddressing& polyMeshGenCells::addressingData() const
329 if( !addressingDataPtr_ )
332 if( omp_in_parallel() )
335 "inline label polyMeshGenCells::addressingData() const"
336 ) << "Calculating addressing inside a parallel region."
337 << " This is not thread safe" << exit(FatalError);
340 calculateAddressingData();
343 return *addressingDataPtr_;
346 void polyMeshGenCells::clearAddressingData() const
348 deleteDemandDrivenData(addressingDataPtr_);
351 label polyMeshGenCells::addCellSubset(const word& selName)
353 label id = cellSubsetIndex(selName);
356 Warning << "Cell subset " << selName << " already exists!" << endl;
363 std::map<label, meshSubset>::const_iterator it=cellSubsets_.begin();
364 it!=cellSubsets_.end();
367 id = Foam::max(id, it->first+1);
374 meshSubset(selName, meshSubset::CELLSUBSET)
381 void polyMeshGenCells::removeCellSubset(const label setI)
383 if( cellSubsets_.find(setI) == cellSubsets_.end() )
386 cellSubsets_.erase(setI);
389 word polyMeshGenCells::cellSubsetName(const label setI) const
391 std::map<label, meshSubset>::const_iterator it =
392 cellSubsets_.find(setI);
393 if( it == cellSubsets_.end() )
395 Warning << "Subset " << setI << " is not a cell subset" << endl;
399 return it->second.name();
402 label polyMeshGenCells::cellSubsetIndex(const word& selName) const
404 std::map<label, meshSubset>::const_iterator it;
405 for(it=cellSubsets_.begin();it!=cellSubsets_.end();++it)
407 if( it->second.name() == selName )
414 void polyMeshGenCells::read()
416 polyMeshGenFaces::read();
418 Info << "Starting creating cells" << endl;
419 //- count the number of cells and create the cells
421 const labelList& own = this->owner();
422 const labelList& nei = this->neighbour();
426 if( own[faceI] >= nCells )
427 nCells = own[faceI] + 1;
429 if( nei[faceI] >= nCells )
430 nCells = nei[faceI] + 1;
433 List<direction> nFacesInCell(nCells, direction(0));
435 ++nFacesInCell[own[faceI]];
438 if( nei[faceI] != -1 )
439 ++nFacesInCell[nei[faceI]];
441 cells_.setSize(nCells);
442 forAll(cells_, cellI)
443 cells_[cellI].setSize(nFacesInCell[cellI]);
448 cells_[own[faceI]][nFacesInCell[own[faceI]]++] = faceI;
449 if( nei[faceI] != -1 )
450 cells_[nei[faceI]][nFacesInCell[nei[faceI]]++] = faceI;
461 wordList setNames = allSets.names("cellSet");
462 forAll(setNames, setI)
464 IOobject* obj = allSets.lookup(setNames[setI]);
468 const labelList content = cSet.toc();
469 const label id = addCellSubset(setNames[setI]);
471 cellSubsets_[id].updateSubset(content);
475 void polyMeshGenCells::write() const
477 polyMeshGenFaces::write();
479 //- write cell subsets
480 std::map<label, meshSubset>::const_iterator setIt;
481 for(setIt=cellSubsets_.begin();setIt!=cellSubsets_.end();++setIt)
487 setIt->second.name(),
496 labelLongList containedElements;
497 setIt->second.containedElements(containedElements);
499 forAll(containedElements, i)
500 set.insert(containedElements[i]);
505 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
507 } // End namespace Foam
509 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //