1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM 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 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "localPointRegion.H"
28 #include "syncTools.H"
30 #include "mapPolyMesh.H"
31 #include "globalIndex.H"
32 #include "indirectPrimitivePatch.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(localPointRegion, 0);
41 // Reduction class to get minimum value over face.
46 void operator()(face& x, const face& y) const
53 x[i] = min(x[i], y[j]);
62 // Dummy transform for faces. Used in synchronisation
65 const tensorField& rotTensor,
72 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
74 // Are two lists identical either in forward or in reverse order.
75 bool Foam::localPointRegion::isDuplicate
82 label fp1 = findIndex(f1, f0[0]);
91 if (f0[fp0] != f1[fp1])
98 fp1 = f1.fcIndex(fp1);
102 fp1 = f1.rcIndex(fp1);
109 // Count regions per point
110 void Foam::localPointRegion::countPointRegions
112 const polyMesh& mesh,
113 const boolList& candidatePoint,
114 const Map<label>& candidateFace,
118 // Almost all will have only one so only
119 // populate Map if more than one.
120 labelList minPointRegion(mesh.nPoints(), -1);
121 // From global point to local (multi-region) point numbering
122 meshPointMap_.resize(candidateFace.size()/100);
123 // From local (multi-region) point to regions
124 DynamicList<labelList> pointRegions(meshPointMap_.size());
126 // From faces with any duplicated point on it to local face
127 meshFaceMap_.resize(meshPointMap_.size());
129 forAllConstIter(Map<label>, candidateFace, iter)
131 label faceI = iter.key();
133 if (!mesh.isInternalFace(faceI))
135 const face& f = mesh.faces()[faceI];
137 if (minRegion[faceI].empty())
139 FatalErrorIn("localPointRegion::countPointRegions(..)")
140 << "Face from candidateFace without minRegion set." << endl
141 << "Face:" << faceI << " fc:" << mesh.faceCentres()[faceI]
142 << " verts:" << f << abort(FatalError);
147 label pointI = f[fp];
149 // Even points which were not candidates for splitting might
150 // be on multiple baffles that are being split so check.
152 if (candidatePoint[pointI])
154 label region = minRegion[faceI][fp];
156 if (minPointRegion[pointI] == -1)
158 minPointRegion[pointI] = region;
160 else if (minPointRegion[pointI] != region)
162 // Multiple regions for this point. Add.
163 Map<label>::iterator iter = meshPointMap_.find(pointI);
164 if (iter != meshPointMap_.end())
166 labelList& regions = pointRegions[iter()];
167 if (findIndex(regions, region) == -1)
169 label sz = regions.size();
170 regions.setSize(sz+1);
171 regions[sz] = region;
176 label localPointI = meshPointMap_.size();
177 meshPointMap_.insert(pointI, localPointI);
178 labelList regions(2);
179 regions[0] = minPointRegion[pointI];
181 pointRegions.append(regions);
184 label meshFaceMapI = meshFaceMap_.size();
185 meshFaceMap_.insert(faceI, meshFaceMapI);
191 minPointRegion.clear();
193 // Add internal faces that use any duplicated point. Can only have one
195 forAllConstIter(Map<label>, candidateFace, iter)
197 label faceI = iter.key();
199 if (mesh.isInternalFace(faceI))
201 const face& f = mesh.faces()[faceI];
205 // Note: candidatePoint test not really necessary but
206 // speeds up rejection.
207 if (candidatePoint[f[fp]] && meshPointMap_.found(f[fp]))
209 label meshFaceMapI = meshFaceMap_.size();
210 meshFaceMap_.insert(faceI, meshFaceMapI);
217 // Transfer to member data
218 pointRegions.shrink();
219 pointRegions_.setSize(pointRegions.size());
220 forAll(pointRegions, i)
222 pointRegions_[i].transfer(pointRegions[i]);
226 faceRegions_.setSize(meshFaceMap_.size());
227 forAllConstIter(Map<label>, meshFaceMap_, iter)
229 faceRegions_[iter()].labelList::transfer(minRegion[iter.key()]);
233 // label faceI = iter.key();
234 // const face& f = mesh.faces()[faceI];
235 // Pout<< "Face:" << faceI << " fc:" << mesh.faceCentres()[faceI]
236 // << " verts:" << f << endl;
239 // Pout<< " " << f[fp] << " min:" << faceRegions_[iter()][fp]
246 // Compact region numbering
251 void Foam::localPointRegion::calcPointRegions
253 const polyMesh& mesh,
254 boolList& candidatePoint
257 label nBnd = mesh.nFaces()-mesh.nInternalFaces();
258 const labelList& faceOwner = mesh.faceOwner();
259 const labelList& faceNeighbour = mesh.faceNeighbour();
262 syncTools::syncPointList
268 false // applySeparation
272 // Mark any face/boundaryFace/cell with a point on a candidate point.
273 // - candidateFace does not necessary have to be a baffle!
274 // - candidateFace is synchronised (since candidatePoint is)
275 Map<label> candidateFace(2*nBnd);
276 label candidateFaceI = 0;
278 Map<label> candidateCell(nBnd);
279 label candidateCellI = 0;
281 forAll(mesh.faces(), faceI)
283 const face& f = mesh.faces()[faceI];
287 if (candidatePoint[f[fp]])
290 if (candidateFace.insert(faceI, candidateFaceI))
296 if (candidateCell.insert(faceOwner[faceI], candidateCellI))
301 if (mesh.isInternalFace(faceI))
303 label nei = faceNeighbour[faceI];
304 if (candidateCell.insert(nei, candidateCellI))
317 // Get global indices for cells
318 globalIndex globalCells(mesh.nCells());
321 // Determine for every candidate face per point the minimum region
322 // (global cell) it is connected to. (candidateFaces are the
324 // candidate point so the only ones that can be affected)
325 faceList minRegion(mesh.nFaces());
326 forAllConstIter(Map<label>, candidateFace, iter)
328 label faceI = iter.key();
329 const face& f = mesh.faces()[faceI];
331 if (mesh.isInternalFace(faceI))
333 label globOwn = globalCells.toGlobal(faceOwner[faceI]);
334 label globNei = globalCells.toGlobal(faceNeighbour[faceI]);
335 minRegion[faceI].setSize(f.size(), min(globOwn, globNei));
339 label globOwn = globalCells.toGlobal(faceOwner[faceI]);
340 minRegion[faceI].setSize(f.size(), globOwn);
344 // Now minimize over all faces that are connected through internal
345 // faces or through cells. This loop iterates over the max number of
346 // cells connected to a point (=8 for hex mesh)
350 // Transport minimum from face across cell
351 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
353 Map<label> minPointValue(100);
355 forAllConstIter(Map<label>, candidateCell, iter)
357 minPointValue.clear();
359 label cellI = iter.key();
360 const cell& cFaces = mesh.cells()[cellI];
362 // Determine minimum per point
363 forAll(cFaces, cFaceI)
365 label faceI = cFaces[cFaceI];
367 if (minRegion[faceI].size())
369 const face& f = mesh.faces()[faceI];
373 label pointI = f[fp];
374 Map<label>::iterator iter = minPointValue.find(pointI);
376 if (iter == minPointValue.end())
378 minPointValue.insert(pointI, minRegion[faceI][fp]);
382 label currentMin = iter();
383 iter() = min(currentMin, minRegion[faceI][fp]);
389 // Set face minimum from point minimum
390 forAll(cFaces, cFaceI)
392 label faceI = cFaces[cFaceI];
394 if (minRegion[faceI].size())
396 const face& f = mesh.faces()[faceI];
400 label minVal = minPointValue[f[fp]];
402 if (minVal != minRegion[faceI][fp])
404 minRegion[faceI][fp] = minVal;
412 //Pout<< "nChanged:" << nChanged << endl;
414 if (returnReduce(nChanged, sumOp<label>()) == 0)
420 // Transport minimum across coupled faces
421 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423 syncTools::syncFaceList
428 false // applySeparation
433 // Count regions per point
434 countPointRegions(mesh, candidatePoint, candidateFace, minRegion);
438 //// Print points with multiple regions. These points need to be duplicated.
439 //forAllConstIter(Map<label>, meshPointMap_, iter)
441 // Pout<< "point:" << iter.key()
442 // << " coord:" << mesh.points()[iter.key()]
443 // << " regions:" << pointRegions_[iter()] << endl;
448 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
450 Foam::localPointRegion::localPointRegion(const polyMesh& mesh)
458 const polyBoundaryMesh& patches = mesh.boundaryMesh();
460 // Get any point on the outside which is on a non-coupled boundary
461 boolList candidatePoint(mesh.nPoints(), false);
463 forAll(patches, patchI)
465 if (!patches[patchI].coupled())
467 const polyPatch& pp = patches[patchI];
469 forAll(pp.meshPoints(), i)
471 candidatePoint[pp.meshPoints()[i]] = true;
476 calcPointRegions(mesh, candidatePoint);
480 Foam::localPointRegion::localPointRegion
482 const polyMesh& mesh,
483 const labelList& candidatePoints
492 boolList candidatePoint(mesh.nPoints(), false);
494 forAll(candidatePoints, i)
496 candidatePoint[candidatePoints[i]] = true;
499 calcPointRegions(mesh, candidatePoint);
503 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
505 // Return a list (in allPatch indices) with either -1 or the face label
506 // of the face that uses the same vertices.
507 Foam::labelList Foam::localPointRegion::findDuplicateFaces
509 const primitiveMesh& mesh,
510 const labelList& boundaryFaces
513 // Addressing engine for all boundary faces.
514 indirectPrimitivePatch allPatch
516 IndirectList<face>(mesh.faces(), boundaryFaces),
520 labelList duplicateFace(allPatch.size(), -1);
521 label nDuplicateFaces = 0;
523 // Find all duplicate faces.
524 forAll(allPatch, bFaceI)
526 const face& f = allPatch.localFaces()[bFaceI];
528 // Get faces connected to f[0].
529 // Check whether share all points with f.
530 const labelList& pFaces = allPatch.pointFaces()[f[0]];
534 label otherFaceI = pFaces[i];
536 if (otherFaceI > bFaceI)
538 const face& otherF = allPatch.localFaces()[otherFaceI];
540 if (isDuplicate(f, otherF, true))
544 "findDuplicateFaces(const primitiveMesh&"
545 ", const labelList&)"
546 ) << "Face:" << bFaceI + mesh.nInternalFaces()
547 << " has local points:" << f
548 << " which are in same order as face:"
549 << otherFaceI + mesh.nInternalFaces()
550 << " with local points:" << otherF
551 << abort(FatalError);
553 else if (isDuplicate(f, otherF, false))
555 label meshFace0 = bFaceI + mesh.nInternalFaces();
556 label meshFace1 = otherFaceI + mesh.nInternalFaces();
560 duplicateFace[bFaceI] != -1
561 || duplicateFace[otherFaceI] != -1
566 "findDuplicateFaces(const primitiveMesh&"
567 ", const labelList&)"
568 ) << "One of two duplicate faces already marked"
569 << " as duplicate." << nl
570 << "This means that three or more faces share"
571 << " the same points and this is illegal." << nl
572 << "Face:" << meshFace0
573 << " with local points:" << f
574 << " which are in same order as face:"
576 << " with local points:" << otherF
577 << abort(FatalError);
580 duplicateFace[bFaceI] = otherFaceI;
581 duplicateFace[otherFaceI] = bFaceI;
588 return duplicateFace;
592 void Foam::localPointRegion::updateMesh(const mapPolyMesh& map)
595 Map<label> newMap(meshFaceMap_.size());
597 forAllConstIter(Map<label>, meshFaceMap_, iter)
599 label newFaceI = map.reverseFaceMap()[iter.key()];
603 newMap.insert(newFaceI, iter());
606 meshFaceMap_.transfer(newMap);
609 Map<label> newMap(meshPointMap_.size());
611 forAllConstIter(Map<label>, meshPointMap_, iter)
613 label newPointI = map.reversePointMap()[iter.key()];
617 newMap.insert(newPointI, iter());
621 meshPointMap_.transfer(newMap);
626 // ************************************************************************* //