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 -------------------------------------------------------------------------------
11 License
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
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,
255  cellClassification::OUTSIDE,
256  cellClassification::INSIDE
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 // ************************************************************************* //
cellClassification.H
Foam::surfaceSets::getHangingCells
static labelHashSet getHangingCells(const primitiveMesh &mesh, const labelHashSet &internalCells)
Get cells using points on 'outside' only.
Definition: surfaceSets.C:281
Foam::surfaceSets::getSurfaceSets
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
Foam::meshSearch
Various (local, not parallel) searches on polyMesh; uses (demand driven) octree to search.
Definition: meshSearch.H:60
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
cellToCell.H
triSurface.H
polyMesh.H
Foam::HashSet< label, Hash< label > >
Foam::triSurfaceSearch
Helper class to search on triSurface.
Definition: triSurfaceSearch.H:58
surfaceToCell.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::Field< vector >
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:76
surfaceSets.H
cut
Patchify triangles based on orientation w.r.t other (triangulated or triangulatable) surfaces.
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::cellClassification
'Cuts' a mesh with a surface.
Definition: cellClassification.H:117
pointToCell.H
meshSearch.H
f
labelList f(nPoints)
Foam::vtk::cellType
cellType
Equivalent to enumeration in "vtkCellType.h".
Definition: foamVtkCore.H:89
Foam::List< cell >
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
cellToPoint.H
triSurfaceSearch.H
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
pointSet.H
Foam::primitiveMesh
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:78