surfaceSets.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2018 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "surfaceSets.H"
30#include "polyMesh.H"
31#include "triSurface.H"
32#include "triSurfaceSearch.H"
33#include "pointSet.H"
34#include "cellSet.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"
41
42
43// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44
45
46// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47
48//Foam::scalar Foam::surfaceSets::minEdgeLen
49//(
50// const primitiveMesh& mesh,
51// const label pointi
52//)
53//{
54// const edgeList& edges = mesh.edges();
55//
56// const pointField& points = mesh.points();
57//
58// const labelList& pEdges = mesh.pointEdges()[pointi];
59//
60// scalar minLen = GREAT;
61//
62// forAll(pEdges, i)
63// {
64// minLen = min(minLen, edges[pEdges[i]].mag(points));
65// }
66// return minLen;
67//}
68//
69//
71//bool Foam::surfaceSets::usesPoint
72//(
73// const primitiveMesh& mesh,
74// const boolList& selectedPoint,
75// const label celli
76//)
77//{
78// const labelList& cFaces = mesh.cells()[celli];
79//
80// forAll(cFaces, cFacei)
81// {
82// label facei = cFaces[cFacei];
83//
84// const face& f = mesh.faces()[facei];
85//
86// forAll(f, fp)
87// {
88// if (selectedPoint[f[fp]])
89// {
90// return true;
91// }
92// }
93// }
94// return false;
95//}
96
97
98
102//Foam::label Foam::surfaceSets::removeHangingCells
103//(
104// const primitiveMesh& mesh,
105// const triSurfaceSearch& querySurf,
106// labelHashSet& internalCells
107//)
108//{
109// const pointField& points = mesh.points();
110// const cellList& cells = mesh.cells();
111// const faceList& faces = mesh.faces();
112//
113// // Determine cells that have all points on the boundary.
114// labelHashSet flatCandidates(getHangingCells(mesh, internalCells));
115//
116// // All boundary points will become visible after subsetting and will be
117// // snapped
118// // to surface. Calculate new volume for cells using only these points and
119// // check if it does not become too small.
120//
121// // Get points used by flatCandidates.
122// labelHashSet outsidePoints(flatCandidates.size());
123//
124// // Snap outside points to surface
125// pointField newPoints(points);
126//
127// for (const label celli : flatCandidates)
128// {
129// const cell& cFaces = cells[celli];
130//
131// for (const label facei : cFaces)
132// {
133// const face& f = faces[facei];
134//
135// for (const label pointi : f)
136// {
137// if (outsidePoints.insert(pointi))
138// {
139// // Calculate new position for this outside point
140// tmp<pointField> tnearest =
141// querySurf.calcNearest(pointField(1, points[pointi]));
142// newPoints[pointi] = tnearest()[0];
143// }
144// }
145// }
146// }
147//
148//
149// // Calculate new volume for mixed cells
150// label nRemoved = 0;
151// for (const label celli : flatCandidates)
152// {
153// const cell& cll = cells[celli];
154//
155// scalar newVol = cll.mag(newPoints, faces);
156// scalar oldVol = mesh.cellVolumes()[celli];
157//
158// if (newVol < 0.1 * oldVol)
159// {
160// internalCells.erase(celli);
161// nRemoved++;
162// }
163// }
164//
165// return nRemoved;
166//}
167
168
172//void Foam::surfaceSets::getNearPoints
173//(
174// const primitiveMesh& mesh,
175// const triSurface&,
176// const triSurfaceSearch& querySurf,
177// const scalar edgeFactor,
178// const pointSet& candidateSet,
179// pointSet& nearPointSet
180//)
181//{
182// if (edgeFactor <= 0)
183// {
184// return;
185// }
186//
187// labelList candidates(candidateSet.toc());
188//
189// pointField candidatePoints(candidates.size());
190// forAll(candidates, i)
191// {
192// candidatePoints[i] = mesh.points()[candidates[i]];
193// }
194//
195// tmp<pointField> tnearest = querySurf.calcNearest(candidatePoints);
196// const pointField& nearest = tnearest();
197//
198// const pointField& points = mesh.points();
199//
200// forAll(candidates, i)
201// {
202// label pointi = candidates[i];
203//
204// scalar minLen = minEdgeLen(mesh, pointi);
205//
206// scalar dist = mag(nearest[i] - points[pointi]);
207//
208// if (dist < edgeFactor * minLen)
209// {
210// nearPointSet.insert(pointi);
211// }
212// }
213//}
214
215
216// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
217
218
219// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
220
222(
223 const polyMesh& mesh,
224 const fileName&,
225 const triSurface&,
226 const triSurfaceSearch& querySurf,
227 const pointField& outsidePts,
228
229 const label nCutLayers,
230
231 labelHashSet& inside,
232 labelHashSet& outside,
234)
235{
236 // Construct search engine on mesh
237 meshSearch queryMesh(mesh);
238
239 // Cut faces with surface and classify cells
240 cellClassification cellType
241 (
242 mesh,
243 queryMesh,
244 querySurf,
245 outsidePts
246 );
247
248 if (nCutLayers > 0)
249 {
250 // Trim cutCells so they are max nCutLayers away (as seen in point-cell
251 // walk) from outside cells.
252 cellType.trimCutCells
253 (
254 nCutLayers,
257 );
258 }
259
260 forAll(cellType, celli)
261 {
262 label cType = cellType[celli];
263
264 if (cType == cellClassification::CUT)
265 {
266 cut.insert(celli);
267 }
268 else if (cType == cellClassification::INSIDE)
269 {
270 inside.insert(celli);
271 }
272 else if (cType == cellClassification::OUTSIDE)
273 {
274 outside.insert(celli);
275 }
276 }
277}
278
279
281(
282 const primitiveMesh& mesh,
283 const labelHashSet& internalCells
284)
285{
286 const cellList& cells = mesh.cells();
287 const faceList& faces = mesh.faces();
288
289
290 // Divide points into
291 // -referenced by internal only
292 // -referenced by outside only
293 // -mixed
294
295 List<pointStatus> pointSide(mesh.nPoints(), NOTSET);
296
297 for (label celli = 0; celli < mesh.nCells(); celli++)
298 {
299 if (internalCells.found(celli))
300 {
301 // Inside cell. Mark all vertices seen from this cell.
302 const labelList& cFaces = cells[celli];
303
304 forAll(cFaces, cFacei)
305 {
306 const face& f = faces[cFaces[cFacei]];
307
308 forAll(f, fp)
309 {
310 label pointi = f[fp];
311
312 if (pointSide[pointi] == NOTSET)
313 {
314 pointSide[pointi] = INSIDE;
315 }
316 else if (pointSide[pointi] == OUTSIDE)
317 {
318 pointSide[pointi] = MIXED;
319 }
320 else
321 {
322 // mixed or inside stay same
323 }
324 }
325 }
326 }
327 else
328 {
329 // Outside cell
330 const labelList& cFaces = cells[celli];
331
332 forAll(cFaces, cFacei)
333 {
334 const face& f = faces[cFaces[cFacei]];
335
336 forAll(f, fp)
337 {
338 label pointi = f[fp];
339
340 if (pointSide[pointi] == NOTSET)
341 {
342 pointSide[pointi] = OUTSIDE;
343 }
344 else if (pointSide[pointi] == INSIDE)
345 {
346 pointSide[pointi] = MIXED;
347 }
348 else
349 {
350 // mixed or outside stay same
351 }
352 }
353 }
354 }
355 }
356
357
358 //OFstream mixedStr("mixed.obj");
359 //
360 //forAll(pointSide, pointi)
361 //{
362 // if (pointSide[pointi] == MIXED)
363 // {
364 // const point& pt = points[pointi];
365 //
366 // mixedStr << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
367 // << endl;
368 // }
369 //}
370
371
372 // Determine cells using mixed points only
373
374 labelHashSet mixedOnlyCells(internalCells.size());
375
376 for (const label celli : internalCells)
377 {
378 const cell& cFaces = cells[celli];
379
380 label usesMixedOnly = true;
381
382 for (const label facei : cFaces)
383 {
384 const face& f = faces[facei];
385
386 for (const label pointi : f)
387 {
388 if (pointSide[pointi] != MIXED)
389 {
390 usesMixedOnly = false;
391 break;
392 }
393 }
394
395 if (!usesMixedOnly)
396 {
397 break;
398 }
399 }
400 if (usesMixedOnly)
401 {
402 mixedOnlyCells.insert(celli);
403 }
404 }
405
406 return mixedOnlyCells;
407}
408
409
410//void Foam::surfaceSets::writeSurfaceSets
411//(
412// const polyMesh& mesh,
413// const fileName& surfName,
414// const triSurface& surf,
415// const triSurfaceSearch& querySurf,
416// const pointField& outsidePts,
417// const scalar edgeFactor
418//)
419//{
420// // Cellsets for inside/outside determination
421// cellSet rawInside(mesh, "rawInside", mesh.nCells()/10);
422// cellSet rawOutside(mesh, "rawOutside", mesh.nCells()/10);
423// cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
424//
425// // Get inside/outside/cut cells
426// getSurfaceSets
427// (
428// mesh,
429// surfName,
430// surf,
431// querySurf,
432// outsidePts,
433//
434// rawInside,
435// rawOutside,
436// cutCells
437// );
438//
439//
440// Pout<< "rawInside:" << rawInside.size() << endl;
441//
442// label nRemoved;
443// do
444// {
445// nRemoved = removeHangingCells(mesh, querySurf, rawInside);
446//
447// Pout<< nl
448// << "Removed " << nRemoved
449// << " rawInside cells that have all their points on the outside"
450// << endl;
451// }
452// while (nRemoved != 0);
453//
454// Pout<< "Writing inside cells (" << rawInside.size() << ") to cellSet "
455// << rawInside.instance()/rawInside.local()/rawInside.name()
456// << endl << endl;
457// rawInside.write();
458//
459//
460//
461// // Select outside cells
462// surfaceToCell outsideSource
463// (
464// mesh,
465// surfName,
466// surf,
467// querySurf,
468// outsidePts,
469// false, // includeCut
470// false, // includeInside
471// true, // includeOutside
472// -GREAT, // nearDist
473// -GREAT // curvature
474// );
475//
476// outsideSource.applyToSet(topoSetSource::NEW, rawOutside);
477//
478// Pout<< "rawOutside:" << rawOutside.size() << endl;
479//
480// do
481// {
482// nRemoved = removeHangingCells(mesh, querySurf, rawOutside);
483//
484// Pout<< nl
485// << "Removed " << nRemoved
486// << " rawOutside cells that have all their points on the outside"
487// << endl;
488// }
489// while (nRemoved != 0);
490//
491// Pout<< "Writing outside cells (" << rawOutside.size() << ") to cellSet "
492// << rawOutside.instance()/rawOutside.local()/rawOutside.name()
493// << endl << endl;
494// rawOutside.write();
495//
496//
497// // Select cut cells by negating inside and outside set.
498// cutCells.invert(mesh.nCells());
499//
500// cellToCell deleteInsideSource(mesh, rawInside.name());
501//
502// deleteInsideSource.applyToSet(topoSetSource::SUBTRACT, cutCells);
503// Pout<< "Writing cut cells (" << cutCells.size() << ") to cellSet "
504// << cutCells.instance()/cutCells.local()/cutCells.name()
505// << endl << endl;
506// cutCells.write();
507//
508//
509// //
510// // Remove cells with points too close to surface.
511// //
512//
513//
514// // Get all points in cutCells.
515// pointSet cutPoints(mesh, "cutPoints", 4*cutCells.size());
516// cellToPoint cutSource(mesh, "cutCells", cellToPoint::ALL);
517// cutSource.applyToSet(topoSetSource::NEW, cutPoints);
518//
519// // Get all points that are too close to surface.
520// pointSet nearPoints(mesh, "nearPoints", cutPoints.size());
521//
522// getNearPoints
523// (
524// mesh,
525// surf,
526// querySurf,
527// edgeFactor,
528// cutPoints,
529// nearPoints
530// );
531//
532// Pout<< nl
533// << "Selected " << nearPoints.size()
534// << " points that are closer than " << edgeFactor
535// << " times the local minimum lengthscale to the surface"
536// << nl << endl;
537//
538//
539// // Remove cells that use any of the points in nearPoints
540// // from the inside and outsideCells.
541// nearPoints.write();
542// pointToCell pToCell(mesh, nearPoints.name(), pointToCell::ANY);
543//
544//
545//
546// // Start off from copy of rawInside, rawOutside
547// cellSet inside(mesh, "inside", rawInside);
548// cellSet outside(mesh, "outside", rawOutside);
549//
550// pToCell.applyToSet(topoSetSource::SUBTRACT, inside);
551// pToCell.applyToSet(topoSetSource::SUBTRACT, outside);
552//
553// Pout<< nl
554// << "Removed " << rawInside.size() - inside.size()
555// << " inside cells that are too close to the surface" << endl;
556//
557// Pout<< nl
558// << "Removed " << rawOutside.size() - outside.size()
559// << " inside cells that are too close to the surface" << nl << endl;
560//
561//
562//
563// //
564// // Remove cells with one or no faces on rest of cellSet. Note: Problem is
565// // not these cells an sich but rather that all of their vertices will be
566// // outside vertices and thus projected onto surface. Which might (if they
567// // project onto same surface) result in flattened cells.
568// //
569//
570// do
571// {
572// nRemoved = removeHangingCells(mesh, querySurf, inside);
573//
574// Pout<< nl
575// << "Removed " << nRemoved
576// << " inside cells that have all their points on the outside"
577// << endl;
578// }
579// while (nRemoved != 0);
580// do
581// {
582// nRemoved = removeHangingCells(mesh, querySurf, outside);
583//
584// Pout<< nl
585// << "Removed " << nRemoved
586// << " outside cells that have all their points on the inside"
587// << endl;
588// }
589// while (nRemoved != 0);
590//
591//
592// //
593// // Write
594// //
595//
596//
597// Pout<< "Writing inside cells (" << inside.size() << ") to cellSet "
598// << inside.instance()/inside.local()/inside.name()
599// << endl << endl;
600//
601// inside.write();
602//
603// Pout<< "Writing outside cells (" << outside.size() << ") to cellSet "
604// << outside.instance()/outside.local()/outside.name()
605// << endl << endl;
606//
607// outside.write();
608//}
609
610
611// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
612
613
614// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
615
616
617// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
618
619
620// ************************************************************************* //
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
bool found(const Key &key) const
Return true if hashed entry is found in table.
Definition: HashTableI.H:100
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
'Cuts' a mesh with a surface.
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:57
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A class for handling file names.
Definition: fileName.H:76
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition: meshSearch.H:61
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:79
label nPoints() const noexcept
Number of mesh points.
label nCells() const noexcept
Number of mesh cells.
const cellList & cells() const
Patchify triangles based on orientation w.r.t other (triangulated or triangulatable) surfaces.
static labelHashSet getHangingCells(const primitiveMesh &mesh, const labelHashSet &internalCells)
Get cells using points on 'outside' only.
Definition: surfaceSets.C:281
static void getSurfaceSets(const polyMesh &mesh, const fileName &surfName, const triSurface &surf, const triSurfaceSearch &querySurf, const pointField &outsidePts, const label nCutLayers, labelHashSet &inside, labelHashSet &outside, labelHashSet &cut)
Divide cells into cut,inside and outside.
Definition: surfaceSets.C:222
Helper class to search on triSurface.
Triangulated surface description with patch information.
Definition: triSurface.H:79
dynamicFvMesh & mesh
const cellShapeList & cells
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333