surfaceSets.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
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
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "surfaceSets.H"
27 #include "polyMesh.H"
28 #include "triSurface.H"
29 #include "triSurfaceSearch.H"
30 #include "pointSet.H"
31 #include "cellSet.H"
32 #include "surfaceToCell.H"
33 #include "cellToPoint.H"
34 #include "cellToCell.H"
35 #include "pointToCell.H"
36 #include "cellClassification.H"
37 
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 //Foam::scalar Foam::surfaceSets::minEdgeLen
45 //(
46 // const primitiveMesh& mesh,
47 // const label pointi
48 //)
49 //{
50 // const edgeList& edges = mesh.edges();
51 //
52 // const pointField& points = mesh.points();
53 //
54 // const labelList& pEdges = mesh.pointEdges()[pointi];
55 //
56 // scalar minLen = great;
57 //
58 // forAll(pEdges, i)
59 // {
60 // minLen = min(minLen, edges[pEdges[i]].mag(points));
61 // }
62 // return minLen;
63 //}
64 //
65 //
67 //bool Foam::surfaceSets::usesPoint
68 //(
69 // const primitiveMesh& mesh,
70 // const boolList& selectedPoint,
71 // const label celli
72 //)
73 //{
74 // const labelList& cFaces = mesh.cells()[celli];
75 //
76 // forAll(cFaces, cFacei)
77 // {
78 // label facei = cFaces[cFacei];
79 //
80 // const face& f = mesh.faces()[facei];
81 //
82 // forAll(f, fp)
83 // {
84 // if (selectedPoint[f[fp]])
85 // {
86 // return true;
87 // }
88 // }
89 // }
90 // return false;
91 //}
92 
93 
94 
98 //Foam::label Foam::surfaceSets::removeHangingCells
99 //(
100 // const primitiveMesh& mesh,
101 // const triSurfaceSearch& querySurf,
102 // labelHashSet& internalCells
103 //)
104 //{
105 // const pointField& points = mesh.points();
106 // const cellList& cells = mesh.cells();
107 // const faceList& faces = mesh.faces();
108 //
109 // // Determine cells that have all points on the boundary.
110 // labelHashSet flatCandidates(getHangingCells(mesh, internalCells));
111 //
112 // // All boundary points will become visible after subsetting and will be
113 // // snapped
114 // // to surface. Calculate new volume for cells using only these points and
115 // // check if it does not become too small.
116 //
117 // // Get points used by flatCandidates.
118 // labelHashSet outsidePoints(flatCandidates.size());
119 //
120 // // Snap outside points to surface
121 // pointField newPoints(points);
122 //
123 // forAllConstIter(labelHashSet, flatCandidates, iter)
124 // {
125 // const cell& cFaces = cells[iter.key()];
126 //
127 // forAll(cFaces, cFacei)
128 // {
129 // const face& f = faces[cFaces[cFacei]];
130 //
131 // forAll(f, fp)
132 // {
133 // label pointi = f[fp];
134 //
135 // if (outsidePoints.insert(pointi))
136 // {
137 // // Calculate new position for this outside point
138 // tmp<pointField> tnearest =
139 // querySurf.calcNearest(pointField(1, points[pointi]));
140 // newPoints[pointi] = tnearest()[0];
141 // }
142 // }
143 // }
144 // }
145 //
146 //
147 // // Calculate new volume for mixed cells
148 // label nRemoved = 0;
149 // forAllConstIter(labelHashSet, flatCandidates, iter)
150 // {
151 // label celli = iter.key();
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,
233  labelHashSet& cut
234 )
235 {
236  // Cut faces with surface and classify cells
237  cellClassification cellType(mesh, querySurf, outsidePts);
238 
239  if (nCutLayers > 0)
240  {
241  // Trim cutCells so they are max nCutLayers away (as seen in point-cell
242  // walk) from outside cells.
243  cellType.trimCutCells
244  (
245  nCutLayers,
248  );
249  }
250 
251  forAll(cellType, celli)
252  {
253  label cType = cellType[celli];
254 
255  if (cType == cellClassification::CUT)
256  {
257  cut.insert(celli);
258  }
259  else if (cType == cellClassification::INSIDE)
260  {
261  inside.insert(celli);
262  }
263  else if (cType == cellClassification::OUTSIDE)
264  {
265  outside.insert(celli);
266  }
267  }
268 }
269 
270 
272 (
273  const primitiveMesh& mesh,
274  const labelHashSet& internalCells
275 )
276 {
277  const cellList& cells = mesh.cells();
278  const faceList& faces = mesh.faces();
279 
280 
281  // Divide points into
282  // -referenced by internal only
283  // -referenced by outside only
284  // -mixed
285 
286  List<pointStatus> pointSide(mesh.nPoints(), NOTSET);
287 
288  for (label celli = 0; celli < mesh.nCells(); celli++)
289  {
290  if (internalCells.found(celli))
291  {
292  // Inside cell. Mark all vertices seen from this cell.
293  const labelList& cFaces = cells[celli];
294 
295  forAll(cFaces, cFacei)
296  {
297  const face& f = faces[cFaces[cFacei]];
298 
299  forAll(f, fp)
300  {
301  label pointi = f[fp];
302 
303  if (pointSide[pointi] == NOTSET)
304  {
305  pointSide[pointi] = INSIDE;
306  }
307  else if (pointSide[pointi] == OUTSIDE)
308  {
309  pointSide[pointi] = MIXED;
310  }
311  else
312  {
313  // mixed or inside stay same
314  }
315  }
316  }
317  }
318  else
319  {
320  // Outside cell
321  const labelList& cFaces = cells[celli];
322 
323  forAll(cFaces, cFacei)
324  {
325  const face& f = faces[cFaces[cFacei]];
326 
327  forAll(f, fp)
328  {
329  label pointi = f[fp];
330 
331  if (pointSide[pointi] == NOTSET)
332  {
333  pointSide[pointi] = OUTSIDE;
334  }
335  else if (pointSide[pointi] == INSIDE)
336  {
337  pointSide[pointi] = MIXED;
338  }
339  else
340  {
341  // mixed or outside stay same
342  }
343  }
344  }
345  }
346  }
347 
348 
349  // OFstream mixedStr("mixed.obj");
350  //
351  // forAll(pointSide, pointi)
352  //{
353  // if (pointSide[pointi] == MIXED)
354  // {
355  // const point& pt = points[pointi];
356  //
357  // mixedStr << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z()
358  // << endl;
359  // }
360  //}
361 
362 
363  // Determine cells using mixed points only
364 
365  labelHashSet mixedOnlyCells(internalCells.size());
366 
367  forAllConstIter(labelHashSet, internalCells, iter)
368  {
369  const label celli = iter.key();
370  const cell& cFaces = cells[celli];
371 
372  label usesMixedOnly = true;
373 
374  forAll(cFaces, i)
375  {
376  const face& f = faces[cFaces[i]];
377 
378  forAll(f, fp)
379  {
380  if (pointSide[f[fp]] != MIXED)
381  {
382  usesMixedOnly = false;
383  break;
384  }
385  }
386 
387  if (!usesMixedOnly)
388  {
389  break;
390  }
391  }
392  if (usesMixedOnly)
393  {
394  mixedOnlyCells.insert(celli);
395  }
396  }
397 
398  return mixedOnlyCells;
399 }
400 
401 
402 //void Foam::surfaceSets::writeSurfaceSets
403 //(
404 // const polyMesh& mesh,
405 // const fileName& surfName,
406 // const triSurface& surf,
407 // const triSurfaceSearch& querySurf,
408 // const pointField& outsidePts,
409 // const scalar edgeFactor
410 //)
411 //{
412 // // Cellsets for inside/outside determination
413 // cellSet rawInside(mesh, "rawInside", mesh.nCells()/10);
414 // cellSet rawOutside(mesh, "rawOutside", mesh.nCells()/10);
415 // cellSet cutCells(mesh, "cutCells", mesh.nCells()/10);
416 //
417 // // Get inside/outside/cut cells
418 // getSurfaceSets
419 // (
420 // mesh,
421 // surfName,
422 // surf,
423 // querySurf,
424 // outsidePts,
425 //
426 // rawInside,
427 // rawOutside,
428 // cutCells
429 // );
430 //
431 //
432 // Pout<< "rawInside:" << rawInside.size() << endl;
433 //
434 // label nRemoved;
435 // do
436 // {
437 // nRemoved = removeHangingCells(mesh, querySurf, rawInside);
438 //
439 // Pout<< nl
440 // << "Removed " << nRemoved
441 // << " rawInside cells that have all their points on the outside"
442 // << endl;
443 // }
444 // while (nRemoved != 0);
445 //
446 // Pout<< "Writing inside cells (" << rawInside.size() << ") to cellSet "
447 // << rawInside.instance()/rawInside.local()/rawInside.name()
448 // << endl << endl;
449 // rawInside.write();
450 //
451 //
452 //
453 // // Select outside cells
454 // surfaceToCell outsideSource
455 // (
456 // mesh,
457 // surfName,
458 // surf,
459 // querySurf,
460 // outsidePts,
461 // false, // includeCut
462 // false, // includeInside
463 // true, // includeOutside
464 // -great, // nearDist
465 // -great // curvature
466 // );
467 //
468 // outsideSource.applyToSet(topoSetSource::NEW, rawOutside);
469 //
470 // Pout<< "rawOutside:" << rawOutside.size() << endl;
471 //
472 // do
473 // {
474 // nRemoved = removeHangingCells(mesh, querySurf, rawOutside);
475 //
476 // Pout<< nl
477 // << "Removed " << nRemoved
478 // << " rawOutside cells that have all their points on the outside"
479 // << endl;
480 // }
481 // while (nRemoved != 0);
482 //
483 // Pout<< "Writing outside cells (" << rawOutside.size() << ") to cellSet "
484 // << rawOutside.instance()/rawOutside.local()/rawOutside.name()
485 // << endl << endl;
486 // rawOutside.write();
487 //
488 //
489 // // Select cut cells by negating inside and outside set.
490 // cutCells.invert(mesh.nCells());
491 //
492 // cellToCell deleteInsideSource(mesh, rawInside.name());
493 //
494 // deleteInsideSource.applyToSet(topoSetSource::DELETE, cutCells);
495 // Pout<< "Writing cut cells (" << cutCells.size() << ") to cellSet "
496 // << cutCells.instance()/cutCells.local()/cutCells.name()
497 // << endl << endl;
498 // cutCells.write();
499 //
500 //
501 // //
502 // // Remove cells with points too close to surface.
503 // //
504 //
505 //
506 // // Get all points in cutCells.
507 // pointSet cutPoints(mesh, "cutPoints", 4*cutCells.size());
508 // cellToPoint cutSource(mesh, "cutCells", cellToPoint::ALL);
509 // cutSource.applyToSet(topoSetSource::NEW, cutPoints);
510 //
511 // // Get all points that are too close to surface.
512 // pointSet nearPoints(mesh, "nearPoints", cutPoints.size());
513 //
514 // getNearPoints
515 // (
516 // mesh,
517 // surf,
518 // querySurf,
519 // edgeFactor,
520 // cutPoints,
521 // nearPoints
522 // );
523 //
524 // Pout<< nl
525 // << "Selected " << nearPoints.size()
526 // << " points that are closer than " << edgeFactor
527 // << " times the local minimum lengthscale to the surface"
528 // << nl << endl;
529 //
530 //
531 // // Remove cells that use any of the points in nearPoints
532 // // from the inside and outsideCells.
533 // nearPoints.write();
534 // pointToCell pToCell(mesh, nearPoints.name(), pointToCell::ANY);
535 //
536 //
537 //
538 // // Start off from copy of rawInside, rawOutside
539 // cellSet inside(mesh, "inside", rawInside);
540 // cellSet outside(mesh, "outside", rawOutside);
541 //
542 // pToCell.applyToSet(topoSetSource::DELETE, inside);
543 // pToCell.applyToSet(topoSetSource::DELETE, outside);
544 //
545 // Pout<< nl
546 // << "Removed " << rawInside.size() - inside.size()
547 // << " inside cells that are too close to the surface" << endl;
548 //
549 // Pout<< nl
550 // << "Removed " << rawOutside.size() - outside.size()
551 // << " inside cells that are too close to the surface" << nl << endl;
552 //
553 //
554 //
555 // //
556 // // Remove cells with one or no faces on rest of cellSet. Note: Problem is
557 // // not these cells an sich but rather that all of their vertices will be
558 // // outside vertices and thus projected onto surface. Which might (if they
559 // // project onto same surface) result in flattened cells.
560 // //
561 //
562 // do
563 // {
564 // nRemoved = removeHangingCells(mesh, querySurf, inside);
565 //
566 // Pout<< nl
567 // << "Removed " << nRemoved
568 // << " inside cells that have all their points on the outside"
569 // << endl;
570 // }
571 // while (nRemoved != 0);
572 // do
573 // {
574 // nRemoved = removeHangingCells(mesh, querySurf, outside);
575 //
576 // Pout<< nl
577 // << "Removed " << nRemoved
578 // << " outside cells that have all their points on the inside"
579 // << endl;
580 // }
581 // while (nRemoved != 0);
582 //
583 //
584 // //
585 // // Write
586 // //
587 //
588 //
589 // Pout<< "Writing inside cells (" << inside.size() << ") to cellSet "
590 // << inside.instance()/inside.local()/inside.name()
591 // << endl << endl;
592 //
593 // inside.write();
594 //
595 // Pout<< "Writing outside cells (" << outside.size() << ") to cellSet "
596 // << outside.instance()/outside.local()/outside.name()
597 // << endl << endl;
598 //
599 // outside.write();
600 //}
601 
602 
603 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
604 
605 
606 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
607 
608 
609 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
610 
611 
612 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
Motion of the mesh specified as a list of pointMeshMovers.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1308
label nCells() const
label nPoints() const
const cellList & cells() const
static labelHashSet getHangingCells(const primitiveMesh &mesh, const labelHashSet &internalCells)
Get cells using points on 'outside' only.
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.
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
const cellShapeList & cells
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
List< cell > cellList
list of cells
Definition: cellList.H:42
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:213
List< face > faceList
Definition: faceListFwd.H:41
labelList f(nPoints)