1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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
27 \*---------------------------------------------------------------------------*/
29 #include "surfaceSets.H"
31 #include "triSurface.H"
32 #include "triSurfaceSearch.H"
35 #include "surfaceToCell.H"
36 #include "cellToPoint.H"
37 #include "cellToCell.H"
38 #include "pointToCell.H"
39 #include "meshSearch.H"
40 #include "cellClassification.H"
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 //Foam::scalar Foam::surfaceSets::minEdgeLen
50 // const primitiveMesh& mesh,
54 // const edgeList& edges = mesh.edges();
56 // const pointField& points = mesh.points();
58 // const labelList& pEdges = mesh.pointEdges()[pointI];
60 // scalar minLen = GREAT;
64 // minLen = min(minLen, edges[pEdges[i]].mag(points));
70 //// Returns true if cell uses at least one selected point
71 //bool Foam::surfaceSets::usesPoint
73 // const primitiveMesh& mesh,
74 // const boolList& selectedPoint,
78 // const labelList& cFaces = mesh.cells()[cellI];
80 // forAll(cFaces, cFaceI)
82 // label faceI = cFaces[cFaceI];
84 // const face& f = mesh.faces()[faceI];
88 // if (selectedPoint[f[fp]])
99 //// Remove cells in allCells which are connected to other cells in allCells
100 //// by outside vertices only. Since these outside vertices will be moved onto
101 //// a surface they might result in flat cells.
102 //Foam::label Foam::surfaceSets::removeHangingCells
104 // const primitiveMesh& mesh,
105 // const triSurfaceSearch& querySurf,
106 // labelHashSet& internalCells
109 // const pointField& points = mesh.points();
110 // const cellList& cells = mesh.cells();
111 // const faceList& faces = mesh.faces();
113 // // Determine cells that have all points on the boundary.
114 // labelHashSet flatCandidates(getHangingCells(mesh, internalCells));
116 // // All boundary points will become visible after subsetting and will be
118 // // to surface. Calculate new volume for cells using only these points and
119 // // check if it does not become too small.
121 // // Get points used by flatCandidates.
122 // labelHashSet outsidePoints(flatCandidates.size());
124 // // Snap outside points to surface
125 // pointField newPoints(points);
129 // labelHashSet::const_iterator iter = flatCandidates.begin();
130 // iter != flatCandidates.end();
134 // const cell& cFaces = cells[iter.key()];
136 // forAll(cFaces, cFaceI)
138 // const face& f = faces[cFaces[cFaceI]];
142 // label pointI = f[fp];
144 // if (outsidePoints.insert(pointI))
146 // // Calculate new position for this outside point
147 // tmp<pointField> tnearest =
148 // querySurf.calcNearest(pointField(1, points[pointI]));
149 // newPoints[pointI] = tnearest()[0];
156 // // Calculate new volume for mixed cells
157 // label nRemoved = 0;
160 // labelHashSet::const_iterator iter = flatCandidates.begin();
161 // iter != flatCandidates.end();
165 // label cellI = iter.key();
167 // const cell& cll = cells[cellI];
169 // scalar newVol = cll.mag(newPoints, faces);
170 // scalar oldVol = mesh.cellVolumes()[cellI];
172 // if (newVol < 0.1 * oldVol)
174 // internalCells.erase(cellI);
183 //// Select all points out of pointSet where the distance to the surface is less
184 //// than a factor times a local length scale (minimum length of connected edges)
185 //void Foam::surfaceSets::getNearPoints
187 // const primitiveMesh& mesh,
188 // const triSurface&,
189 // const triSurfaceSearch& querySurf,
190 // const scalar edgeFactor,
191 // const pointSet& candidateSet,
192 // pointSet& nearPointSet
195 // if (edgeFactor <= 0)
200 // labelList candidates(candidateSet.toc());
202 // pointField candidatePoints(candidates.size());
203 // forAll(candidates, i)
205 // candidatePoints[i] = mesh.points()[candidates[i]];
208 // tmp<pointField> tnearest = querySurf.calcNearest(candidatePoints);
209 // const pointField& nearest = tnearest();
211 // const pointField& points = mesh.points();
213 // forAll(candidates, i)
215 // label pointI = candidates[i];
217 // scalar minLen = minEdgeLen(mesh, pointI);
219 // scalar dist = mag(nearest[i] - points[pointI]);
221 // if (dist < edgeFactor * minLen)
223 // nearPointSet.insert(pointI);
229 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
232 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
234 void Foam::surfaceSets::getSurfaceSets
236 const polyMesh& mesh,
239 const triSurfaceSearch& querySurf,
240 const pointField& outsidePts,
242 const label nCutLayers,
244 labelHashSet& inside,
245 labelHashSet& outside,
249 // Construct search engine on mesh
250 meshSearch queryMesh(mesh, true);
253 // Check all 'outside' points
254 forAll(outsidePts, outsideI)
256 const point& outsidePoint = outsidePts[outsideI];
258 // Find cell point is in. Linear search.
259 if (queryMesh.findCell(outsidePoint, -1, false) == -1)
263 "surfaceSets::getSurfaceSets"
264 "(const polyMesh&, const fileName&, const triSurface&"
265 ", const triSurfaceSearch&, const pointField&"
266 ", labelHashSet&, labelHashSet&, labelHashSet&)"
267 ) << "outsidePoint " << outsidePoint
268 << " is not inside any cell"
273 // Cut faces with surface and classify cells
274 cellClassification cellType
284 // Trim cutCells so they are max nCutLayers away (as seen in point-cell
285 // walk) from outside cells.
286 cellType.trimCutCells
289 cellClassification::OUTSIDE,
290 cellClassification::INSIDE
294 forAll(cellType, cellI)
296 label cType = cellType[cellI];
298 if (cType == cellClassification::CUT)
302 else if (cType == cellClassification::INSIDE)
304 inside.insert(cellI);
306 else if (cType == cellClassification::OUTSIDE)
308 outside.insert(cellI);
314 Foam::labelHashSet Foam::surfaceSets::getHangingCells
316 const primitiveMesh& mesh,
317 const labelHashSet& internalCells
320 const cellList& cells = mesh.cells();
321 const faceList& faces = mesh.faces();
324 // Divide points into
325 // -referenced by internal only
326 // -referenced by outside only
329 List<pointStatus> pointSide(mesh.nPoints(), NOTSET);
331 for (label cellI = 0; cellI < mesh.nCells(); cellI++)
333 if (internalCells.found(cellI))
335 // Inside cell. Mark all vertices seen from this cell.
336 const labelList& cFaces = cells[cellI];
338 forAll(cFaces, cFaceI)
340 const face& f = faces[cFaces[cFaceI]];
344 label pointI = f[fp];
346 if (pointSide[pointI] == NOTSET)
348 pointSide[pointI] = INSIDE;
350 else if (pointSide[pointI] == OUTSIDE)
352 pointSide[pointI] = MIXED;
356 // mixed or inside stay same
364 const labelList& cFaces = cells[cellI];
366 forAll(cFaces, cFaceI)
368 const face& f = faces[cFaces[cFaceI]];
372 label pointI = f[fp];
374 if (pointSide[pointI] == NOTSET)
376 pointSide[pointI] = OUTSIDE;
378 else if (pointSide[pointI] == INSIDE)
380 pointSide[pointI] = MIXED;
384 // mixed or outside stay same
392 //OFstream mixedStr("mixed.obj");
394 //forAll(pointSide, pointI)
396 // if (pointSide[pointI] == MIXED)
398 // const point& pt = points[pointI];
400 // mixedStr << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
406 // Determine cells using mixed points only
408 labelHashSet mixedOnlyCells(internalCells.size());
412 labelHashSet::const_iterator iter = internalCells.begin();
413 iter != internalCells.end();
417 label cellI = iter.key();
419 const cell& cFaces = cells[cellI];
421 label usesMixedOnly = true;
425 const face& f = faces[cFaces[i]];
429 if (pointSide[f[fp]] != MIXED)
431 usesMixedOnly = false;
443 mixedOnlyCells.insert(cellI);
447 return mixedOnlyCells;
451 //void Foam::surfaceSets::writeSurfaceSets
453 // const polyMesh& mesh,
454 // const fileName& surfName,
455 // const triSurface& surf,
456 // const triSurfaceSearch& querySurf,
457 // const pointField& outsidePts,
458 // const scalar edgeFactor
461 // // Cellsets for inside/outside determination
462 // cellSet rawInside(mesh, "rawInside", mesh.nCells()/10);
463 // cellSet rawOutside(mesh, "rawOutside", mesh.nCells()/10);
464 // cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
466 // // Get inside/outside/cut cells
481 // Pout<< "rawInside:" << rawInside.size() << endl;
486 // nRemoved = removeHangingCells(mesh, querySurf, rawInside);
489 // << "Removed " << nRemoved
490 // << " rawInside cells that have all their points on the outside"
493 // while (nRemoved != 0);
495 // Pout<< "Writing inside cells (" << rawInside.size() << ") to cellSet "
496 // << rawInside.instance()/rawInside.local()/rawInside.name()
498 // rawInside.write();
502 // // Select outside cells
503 // surfaceToCell outsideSource
510 // false, // includeCut
511 // false, // includeInside
512 // true, // includeOutside
513 // -GREAT, // nearDist
514 // -GREAT // curvature
517 // outsideSource.applyToSet(topoSetSource::NEW, rawOutside);
519 // Pout<< "rawOutside:" << rawOutside.size() << endl;
523 // nRemoved = removeHangingCells(mesh, querySurf, rawOutside);
526 // << "Removed " << nRemoved
527 // << " rawOutside cells that have all their points on the outside"
530 // while (nRemoved != 0);
532 // Pout<< "Writing outside cells (" << rawOutside.size() << ") to cellSet "
533 // << rawOutside.instance()/rawOutside.local()/rawOutside.name()
535 // rawOutside.write();
538 // // Select cut cells by negating inside and outside set.
539 // cutCells.invert(mesh.nCells());
541 // cellToCell deleteInsideSource(mesh, rawInside.name());
543 // deleteInsideSource.applyToSet(topoSetSource::DELETE, cutCells);
544 // Pout<< "Writing cut cells (" << cutCells.size() << ") to cellSet "
545 // << cutCells.instance()/cutCells.local()/cutCells.name()
551 // // Remove cells with points too close to surface.
555 // // Get all points in cutCells.
556 // pointSet cutPoints(mesh, "cutPoints", 4*cutCells.size());
557 // cellToPoint cutSource(mesh, "cutCells", cellToPoint::ALL);
558 // cutSource.applyToSet(topoSetSource::NEW, cutPoints);
560 // // Get all points that are too close to surface.
561 // pointSet nearPoints(mesh, "nearPoints", cutPoints.size());
574 // << "Selected " << nearPoints.size()
575 // << " points that are closer than " << edgeFactor
576 // << " times the local minimum lengthscale to the surface"
580 // // Remove cells that use any of the points in nearPoints
581 // // from the inside and outsideCells.
582 // nearPoints.write();
583 // pointToCell pToCell(mesh, nearPoints.name(), pointToCell::ANY);
587 // // Start off from copy of rawInside, rawOutside
588 // cellSet inside(mesh, "inside", rawInside);
589 // cellSet outside(mesh, "outside", rawOutside);
591 // pToCell.applyToSet(topoSetSource::DELETE, inside);
592 // pToCell.applyToSet(topoSetSource::DELETE, outside);
595 // << "Removed " << rawInside.size() - inside.size()
596 // << " inside cells that are too close to the surface" << endl;
599 // << "Removed " << rawOutside.size() - outside.size()
600 // << " inside cells that are too close to the surface" << nl << endl;
605 // // Remove cells with one or no faces on rest of cellSet. Note: Problem is
606 // // not these cells an sich but rather that all of their vertices will be
607 // // outside vertices and thus projected onto surface. Which might (if they
608 // // project onto same surface) result in flattened cells.
613 // nRemoved = removeHangingCells(mesh, querySurf, inside);
616 // << "Removed " << nRemoved
617 // << " inside cells that have all their points on the outside"
620 // while (nRemoved != 0);
623 // nRemoved = removeHangingCells(mesh, querySurf, outside);
626 // << "Removed " << nRemoved
627 // << " outside cells that have all their points on the inside"
630 // while (nRemoved != 0);
638 // Pout<< "Writing inside cells (" << inside.size() << ") to cellSet "
639 // << inside.instance()/inside.local()/inside.name()
644 // Pout<< "Writing outside cells (" << outside.size() << ") to cellSet "
645 // << outside.instance()/outside.local()/outside.name()
652 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
655 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
658 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
661 // ************************************************************************* //