1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 Select cells in relation to surface.
27 Divides cells into three sets:
28 - cutCells : cells cut by surface or close to surface.
29 - outside : cells not in cutCells and reachable from set of
30 user-defined points (outsidePoints)
31 - inside : same but not reachable.
33 Finally the wanted sets are combined into a cellSet 'selected'. Apart
34 from straightforward adding the contents there are a few extra rules to
35 make sure that the surface of the 'outside' of the mesh is singly
38 \*---------------------------------------------------------------------------*/
41 #include "objectRegistry.H"
44 #include "IOdictionary.H"
45 #include "twoDPointCorrector.H"
47 #include "meshTools.H"
49 #include "triSurface.H"
50 #include "triSurfaceSearch.H"
51 #include "meshSearch.H"
52 #include "cellClassification.H"
56 #include "edgeStats.H"
57 #include "treeDataTriSurface.H"
58 #include "indexedOctree.H"
62 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
64 // cellType for cells included/not included in mesh.
65 static const label MESH = cellClassification::INSIDE;
66 static const label NONMESH = cellClassification::OUTSIDE;
69 void writeSet(const cellSet& cells, const string& msg)
71 Info<< "Writing " << msg << " (" << cells.size() << ") to cellSet "
72 << cells.instance()/cells.local()/cells.name()
78 void getType(const labelList& elems, const label type, labelHashSet& set)
93 const meshSearch& queryMesh,
94 const triSurfaceSearch& querySurf,
96 const pointField& outsidePts,
98 const bool selectInside,
99 const bool selectOutside,
100 const scalar nearDist,
102 cellClassification& cellType
105 // Cut with surface and classify as inside/outside/cut
115 // Get inside/outside/cutCells cellSets.
116 cellSet inside(mesh, "inside", mesh.nCells()/10);
117 getType(cellType, cellClassification::INSIDE, inside);
118 writeSet(inside, "inside cells");
120 cellSet outside(mesh, "outside", mesh.nCells()/10);
121 getType(cellType, cellClassification::OUTSIDE, outside);
122 writeSet(outside, "outside cells");
124 cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
125 getType(cellType, cellClassification::CUT, cutCells);
126 writeSet(cutCells, "cells cut by surface");
129 // Change cellType to reflect selected part of mesh. Use
130 // MESH to denote selected part, NONMESH for all
132 // Is a bit of a hack but allows us to reuse all the functionality
133 // in cellClassification.
135 forAll(cellType, cellI)
137 label cType = cellType[cellI];
139 if (cType == cellClassification::CUT)
143 cellType[cellI] = MESH;
147 cellType[cellI] = NONMESH;
150 else if (cType == cellClassification::INSIDE)
154 cellType[cellI] = MESH;
158 cellType[cellI] = NONMESH;
161 else if (cType == cellClassification::OUTSIDE)
165 cellType[cellI] = MESH;
169 cellType[cellI] = NONMESH;
174 FatalErrorIn("cutBySurface")
175 << "Multiple mesh regions in original mesh" << endl
176 << "Please use splitMeshRegions to separate these"
184 Info<< "Removing cells with points closer than " << nearDist
185 << " to the surface ..." << nl << endl;
187 const pointField& pts = mesh.points();
188 const indexedOctree<treeDataTriSurface>& tree = querySurf.tree();
194 const point& pt = pts[pointI];
196 pointIndexHit hitInfo = tree.findNearest(pt, sqr(nearDist));
200 const labelList& pCells = mesh.pointCells()[pointI];
204 if (cellType[pCells[i]] != NONMESH)
206 cellType[pCells[i]] = NONMESH;
213 // tmp<pointField> tnearest = querySurf.calcNearest(pts);
214 // const pointField& nearest = tnearest();
216 // label nRemoved = 0;
218 // forAll(nearest, pointI)
220 // if (mag(nearest[pointI] - pts[pointI]) < nearDist)
222 // const labelList& pCells = mesh.pointCells()[pointI];
226 // if (cellType[pCells[i]] != NONMESH)
228 // cellType[pCells[i]] = NONMESH;
235 Info<< "Removed " << nRemoved << " cells since too close to surface"
242 // We're meshing the outside. Subset the currently selected mesh cells with the
243 // ones reachable from the outsidepoints.
244 label selectOutsideCells
246 const polyMesh& mesh,
247 const meshSearch& queryMesh,
248 const pointField& outsidePts,
249 cellClassification& cellType
253 // Check all outsidePts and for all of them inside a mesh cell
254 // collect the faces to start walking from
258 labelHashSet outsideFacesMap(outsidePts.size() * 6 * 2);
259 DynamicList<label> outsideFaces(outsideFacesMap.size());
260 // CellInfo on outside faces
261 DynamicList<cellInfo> outsideFacesInfo(outsideFacesMap.size());
263 // cellInfo for mesh cell
264 const cellInfo meshInfo(MESH);
266 forAll(outsidePts, outsidePtI)
268 // Find cell containing point. Linear search.
269 label cellI = queryMesh.findCell(outsidePts[outsidePtI], -1, false);
271 if (cellType[cellI] == MESH)
273 Info<< "Marking cell " << cellI << " containing outside point "
274 << outsidePts[outsidePtI] << " with type " << cellType[cellI]
278 // Mark this cell and its faces to start walking from
281 // Mark faces of cellI
282 const labelList& cFaces = mesh.cells()[cellI];
285 label faceI = cFaces[i];
287 if (outsideFacesMap.insert(faceI))
289 outsideFaces.append(faceI);
290 outsideFacesInfo.append(meshInfo);
296 // Floodfill starting from outsideFaces (of type meshInfo)
297 MeshWave<cellInfo> regionCalc
300 outsideFaces.shrink(),
301 outsideFacesInfo.shrink(),
302 mesh.nCells() // max iterations
305 // Now regionCalc should hold info on cells that are reachable from
306 // changedFaces. Use these to subset cellType
307 const List<cellInfo>& allCellInfo = regionCalc.allCellInfo();
311 forAll(allCellInfo, cellI)
313 if (cellType[cellI] == MESH)
315 // Original cell was selected for meshing. Check if cell was
316 // reached from outsidePoints
317 if (allCellInfo[cellI].type() != MESH)
319 cellType[cellI] = NONMESH;
331 int main(int argc, char *argv[])
333 argList::noParallel();
335 # include "setRootCase.H"
336 # include "createTime.H"
337 # include "createPolyMesh.H"
339 // Mesh edge statistics calculator
340 edgeStats edgeCalc(mesh);
343 IOdictionary refineDict
355 fileName surfName(refineDict.lookup("surface"));
356 pointField outsidePts(refineDict.lookup("outsidePoints"));
357 bool useSurface(readBool(refineDict.lookup("useSurface")));
358 bool selectCut(readBool(refineDict.lookup("selectCut")));
359 bool selectInside(readBool(refineDict.lookup("selectInside")));
360 bool selectOutside(readBool(refineDict.lookup("selectOutside")));
361 scalar nearDist(readScalar(refineDict.lookup("nearDistance")));
366 Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
367 << " cells cut by surface : " << selectCut << nl
368 << " cells inside of surface : " << selectInside << nl
369 << " cells outside of surface : " << selectOutside << nl
370 << " cells with points further than : " << nearDist << nl
375 Info<< "Cells to be used for meshing (0=false, 1=true):" << nl
376 << " cells reachable from outsidePoints:" << selectOutside << nl
380 // Print edge stats on original mesh.
381 (void)edgeCalc.minLen(Info);
383 // Search engine on mesh. Face decomposition since faces might be warped.
384 meshSearch queryMesh(mesh, true);
386 // Check all 'outside' points
387 forAll(outsidePts, outsideI)
389 const point& outsidePoint = outsidePts[outsideI];
391 if (queryMesh.findCell(outsidePoint, -1, false) == -1)
393 FatalErrorIn(args.executable())
394 << "outsidePoint " << outsidePoint
395 << " is not inside any cell"
400 // Cell status (compared to surface if provided): inside/outside/cut.
401 // Start off from everything selected and cut later.
402 cellClassification cellType
408 cellClassification::MESH
414 autoPtr<triSurface> surf(NULL);
415 // Search engine on surface.
416 autoPtr<triSurfaceSearch> querySurf(NULL);
420 surf.reset(new triSurface(surfName));
423 surf().writeStats(Info);
425 // Search engine on surface.
426 querySurf.reset(new triSurfaceSearch(surf));
428 // Set cellType[cellI] according to relation to surface
446 // Now 'trim' all the corners from the mesh so meshing/surface extraction
449 label nHanging, nRegionEdges, nRegionPoints, nOutside;
453 Info<< "Removing cells which after subsetting would have all points"
454 << " on outside ..." << nl << endl;
456 nHanging = cellType.fillHangingCells
459 NONMESH, // fill type
464 Info<< "Removing edges connecting cells unconnected by faces ..."
467 nRegionEdges = cellType.fillRegionEdges
470 NONMESH, // fill type
475 Info<< "Removing points connecting cells unconnected by faces ..."
478 nRegionPoints = cellType.fillRegionPoints
481 NONMESH, // fill type
488 // Since we're selecting the cells reachable from outsidePoints
489 // and the set might have changed, redo the outsideCells
491 nOutside = selectOutsideCells
503 || nRegionPoints != 0
507 cellSet selectedCells(mesh, "selected", mesh.nCells()/10);
508 getType(cellType, MESH, selectedCells);
510 writeSet(selectedCells, "cells selected for meshing");
513 Info << "End\n" << endl;
519 // ************************************************************************* //