isoSurfaceCell.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) 2016-2019 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 "isoSurfaceCell.H"
30 #include "isoSurface.H"
31 #include "dictionary.H"
32 #include "polyMesh.H"
33 #include "mergePoints.H"
34 #include "tetMatcher.H"
35 #include "syncTools.H"
36 #include "triSurface.H"
37 #include "triSurfaceTools.H"
38 #include "Time.H"
39 #include "triPoints.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(isoSurfaceCell, 0);
46 }
47 
48 
49 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
50 
51 namespace Foam
52 {
53  // Does any edge of triangle cross iso value?
54  inline static bool isTriCut
55  (
56  const label a,
57  const label b,
58  const label c,
59  const scalarField& pointValues,
60  const scalar isoValue
61  )
62  {
63  const bool aLower = (pointValues[a] < isoValue);
64  const bool bLower = (pointValues[b] < isoValue);
65  const bool cLower = (pointValues[c] < isoValue);
66 
67  return !(aLower == bLower && aLower == cLower);
68  }
69 }
70 
71 
72 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
73 
74 Foam::scalar Foam::isoSurfaceCell::isoFraction
75 (
76  const scalar s0,
77  const scalar s1
78 ) const
79 {
80  const scalar d = s1-s0;
81 
82  if (mag(d) > VSMALL)
83  {
84  return (iso_-s0)/d;
85  }
86 
87  return -1.0;
88 }
89 
90 
91 Foam::isoSurfaceCell::cellCutType Foam::isoSurfaceCell::calcCutType
92 (
93  const bitSet& isTet,
94  const scalarField& cellValues,
95  const scalarField& pointValues,
96  const label celli
97 ) const
98 {
99  if (ignoreCells_.test(celli))
100  {
101  return NOTCUT;
102  }
103 
104  const cell& cFaces = mesh_.cells()[celli];
105 
106  if (isTet.test(celli))
107  {
108  for (const label facei : cFaces)
109  {
110  const face& f = mesh_.faces()[facei];
111 
112  for (label fp = 1; fp < f.size() - 1; ++fp)
113  {
114  if (isTriCut(f[0], f[fp], f[f.fcIndex(fp)], pointValues, iso_))
115  {
116  return CUT;
117  }
118  }
119  }
120  return NOTCUT;
121  }
122 
123 
124  const bool cellLower = (cellValues[celli] < iso_);
125 
126  // First check if there is any cut in cell
127  bool edgeCut = false;
128 
129  for (const label facei : cFaces)
130  {
131  const face& f = mesh_.faces()[facei];
132 
133  // Check pyramid edges (corner point to cell centre)
134  for (const label pointi : f)
135  {
136  if (cellLower != (pointValues[pointi] < iso_))
137  {
138  edgeCut = true;
139  break;
140  }
141  }
142 
143  if (edgeCut)
144  {
145  break;
146  }
147 
148  // Check (triangulated) face edges
149  // With fallback for problem decompositions
150  const label fp0 =
151  (mesh_.tetBasePtIs()[facei] < 0 ? 0 : mesh_.tetBasePtIs()[facei]);
152 
153  label fp = f.fcIndex(fp0);
154  for (label i = 2; i < f.size(); ++i)
155  {
156  const label nextFp = f.fcIndex(fp);
157 
158  if (isTriCut(f[fp0], f[fp], f[nextFp], pointValues, iso_))
159  {
160  edgeCut = true;
161  break;
162  }
163 
164  fp = nextFp;
165  }
166 
167  if (edgeCut)
168  {
169  break;
170  }
171  }
172 
173 
174  if (edgeCut)
175  {
176  // Count actual cuts (expensive since addressing needed)
177  // Note: not needed if you don't want to preserve maxima/minima
178  // centred around cellcentre. In that case just always return CUT
179 
180  const labelList& cPoints = mesh_.cellPoints(celli);
181 
182  label nPyrCuts = 0;
183 
184  for (const label pointi : cPoints)
185  {
186  if ((pointValues[pointi] < iso_) != cellLower)
187  {
188  ++nPyrCuts;
189  }
190  }
191 
192  if (nPyrCuts == cPoints.size())
193  {
194  return SPHERE;
195  }
196  else if (nPyrCuts)
197  {
198  // There is a pyramid edge cut. E.g. lopping off a tet from a corner
199  return CUT;
200  }
201  }
202 
203  return NOTCUT;
204 }
205 
206 
207 void Foam::isoSurfaceCell::calcCutTypes
208 (
209  const bitSet& isTet,
210  const scalarField& cVals,
211  const scalarField& pVals
212 )
213 {
214  cellCutType_.setSize(mesh_.nCells());
215  nCutCells_ = 0;
216 
217  // Some processor domains may require tetBasePtIs and others do not.
218  // Do now to ensure things stay synchronized.
219  (void)mesh_.tetBasePtIs();
220 
221  forAll(cellCutType_, celli)
222  {
223  cellCutType_[celli] = calcCutType(isTet, cVals, pVals, celli);
224 
225  if (cellCutType_[celli] == CUT)
226  {
227  ++nCutCells_;
228  }
229  }
230 
231  if (debug)
232  {
233  Pout<< "isoSurfaceCell : candidate cut cells "
234  << nCutCells_ << " / " << mesh_.nCells() << endl;
235  }
236 }
237 
238 
239 Foam::labelPair Foam::isoSurfaceCell::findCommonPoints
240 (
241  const labelledTri& tri0,
242  const labelledTri& tri1
243 )
244 {
245  labelPair common(-1, -1);
246 
247  label fp0 = 0;
248  label fp1 = tri1.find(tri0[fp0]);
249 
250  if (fp1 == -1)
251  {
252  fp0 = 1;
253  fp1 = tri1.find(tri0[fp0]);
254  }
255 
256  if (fp1 != -1)
257  {
258  // So tri0[fp0] is tri1[fp1]
259 
260  // Find next common point
261  label fp0p1 = tri0.fcIndex(fp0);
262  label fp1p1 = tri1.fcIndex(fp1);
263  label fp1m1 = tri1.rcIndex(fp1);
264 
265  if (tri0[fp0p1] == tri1[fp1p1] || tri0[fp0p1] == tri1[fp1m1])
266  {
267  common[0] = tri0[fp0];
268  common[1] = tri0[fp0p1];
269  }
270  }
271  return common;
272 }
273 
274 
275 Foam::point Foam::isoSurfaceCell::calcCentre(const triSurface& s)
276 {
277  vector sum = Zero;
278 
279  forAll(s, i)
280  {
281  sum += s[i].centre(s.points());
282  }
283  return sum/s.size();
284 }
285 
286 
287 Foam::pointIndexHit Foam::isoSurfaceCell::collapseSurface
288 (
289  const label celli,
290  pointField& localPoints,
291  DynamicList<labelledTri, 64>& localTris
292 ) const
293 {
294  pointIndexHit info(false, Zero, localTris.size());
295 
296  if (localTris.size() == 1)
297  {
298  const labelledTri& tri = localTris[0];
299  info.setPoint(tri.centre(localPoints));
300  info.setHit();
301  }
302  else if (localTris.size() == 2)
303  {
304  // Check if the two triangles share an edge.
305  const labelledTri& tri0 = localTris[0];
306  const labelledTri& tri1 = localTris[1];
307 
308  labelPair shared = findCommonPoints(tri0, tri1);
309 
310  if (shared[0] != -1)
311  {
312  const vector n0 = tri0.areaNormal(localPoints);
313  const vector n1 = tri1.areaNormal(localPoints);
314 
315  // Merge any zero-sized triangles,
316  // or if they point in the same direction.
317 
318  if
319  (
320  mag(n0) <= ROOTVSMALL
321  || mag(n1) <= ROOTVSMALL
322  || (n0 & n1) >= 0
323  )
324  {
325  info.setPoint
326  (
327  0.5
328  * (
329  tri0.centre(localPoints)
330  + tri1.centre(localPoints)
331  )
332  );
333  info.setHit();
334  }
335  }
336  }
337  else if (localTris.size())
338  {
339  // Check if single region. Rare situation.
340  triSurface surf
341  (
342  localTris,
344  localPoints,
345  true
346  );
347  localTris.clearStorage();
348 
349  labelList faceZone;
350  label nZones = surf.markZones
351  (
352  boolList(surf.nEdges(), false),
353  faceZone
354  );
355 
356  if (nZones == 1)
357  {
358  // Check that all normals make a decent angle
359  scalar minCos = GREAT;
360  const vector& n0 = surf.faceNormals()[0];
361  for (label i = 1; i < surf.size(); ++i)
362  {
363  scalar cosAngle = (n0 & surf.faceNormals()[i]);
364  if (cosAngle < minCos)
365  {
366  minCos = cosAngle;
367  }
368  }
369 
370  if (minCos > 0)
371  {
372  info.setPoint(calcCentre(surf));
373  info.setHit();
374  }
375  }
376  }
377 
378  return info;
379 }
380 
381 
382 void Foam::isoSurfaceCell::calcSnappedCc
383 (
384  const bitSet& isTet,
385  const scalarField& cVals,
386  const scalarField& pVals,
387 
388  DynamicList<point>& snappedPoints,
389  labelList& snappedCc
390 ) const
391 {
392  const pointField& cc = mesh_.cellCentres();
393  const pointField& pts = mesh_.points();
394 
395  snappedCc.setSize(mesh_.nCells());
396  snappedCc = -1;
397 
398  // Work arrays
399  DynamicList<point, 64> localPoints(64);
400  DynamicList<labelledTri, 64> localTris(64);
401  Map<label> pointToLocal(64);
402 
403  forAll(mesh_.cells(), celli)
404  {
405  if (cellCutType_[celli] == CUT && !isTet.test(celli))
406  {
407  const scalar cVal = cVals[celli];
408 
409  const cell& cFaces = mesh_.cells()[celli];
410 
411  localPoints.clear();
412  localTris.clear();
413  pointToLocal.clear();
414 
415  // Create points for all intersections close to cell centre
416  // (i.e. from pyramid edges)
417 
418  for (const label facei : cFaces)
419  {
420  const face& f = mesh_.faces()[facei];
421 
422  for (const label pointi : f)
423  {
424  scalar s = isoFraction(cVal, pVals[pointi]);
425 
426  if (s >= 0.0 && s <= 0.5)
427  {
428  if (pointToLocal.insert(pointi, localPoints.size()))
429  {
430  localPoints.append((1.0-s)*cc[celli]+s*pts[pointi]);
431  }
432  }
433  }
434  }
435 
436  if (localPoints.size() == 1)
437  {
438  // No need for any analysis.
439  snappedCc[celli] = snappedPoints.size();
440  snappedPoints.append(localPoints[0]);
441 
442  //Pout<< "cell:" << celli
443  // << " at " << mesh_.cellCentres()[celli]
444  // << " collapsing " << localPoints
445  // << " intersections down to "
446  // << snappedPoints[snappedCc[celli]] << endl;
447  }
448  else if (localPoints.size() == 2)
449  {
450  //? No need for any analysis.???
451  snappedCc[celli] = snappedPoints.size();
452  snappedPoints.append(0.5*(localPoints[0]+localPoints[1]));
453 
454  //Pout<< "cell:" << celli
455  // << " at " << mesh_.cellCentres()[celli]
456  // << " collapsing " << localPoints
457  // << " intersections down to "
458  // << snappedPoints[snappedCc[celli]] << endl;
459  }
460  else if (localPoints.size())
461  {
462  // Need to analyse
463  for (const label facei : cFaces)
464  {
465  const face& f = mesh_.faces()[facei];
466 
467  // Do a tetrahedralisation. Each face to cc becomes pyr.
468  // Each pyr gets split into tets by diagonalisation
469  // of face.
470 
471  const label fp0 = mesh_.tetBasePtIs()[facei];
472  label fp = f.fcIndex(fp0);
473  for (label i = 2; i < f.size(); ++i)
474  {
475  label nextFp = f.fcIndex(fp);
476  triFace tri(f[fp0], f[fp], f[nextFp]);
477 
478  // Get fractions for the three edges to cell centre
479  FixedList<scalar, 3> s(3);
480  s[0] = isoFraction(cVal, pVals[tri[0]]);
481  s[1] = isoFraction(cVal, pVals[tri[1]]);
482  s[2] = isoFraction(cVal, pVals[tri[2]]);
483 
484  if
485  (
486  (s[0] >= 0.0 && s[0] <= 0.5)
487  && (s[1] >= 0.0 && s[1] <= 0.5)
488  && (s[2] >= 0.0 && s[2] <= 0.5)
489  )
490  {
491  if
492  (
493  (mesh_.faceOwner()[facei] == celli)
494  == (cVal >= pVals[tri[0]])
495  )
496  {
497  localTris.append
498  (
499  labelledTri
500  (
501  pointToLocal[tri[1]],
502  pointToLocal[tri[0]],
503  pointToLocal[tri[2]],
504  0
505  )
506  );
507  }
508  else
509  {
510  localTris.append
511  (
512  labelledTri
513  (
514  pointToLocal[tri[0]],
515  pointToLocal[tri[1]],
516  pointToLocal[tri[2]],
517  0
518  )
519  );
520  }
521  }
522 
523  fp = nextFp;
524  }
525  }
526 
527  pointField surfPoints;
528  surfPoints.transfer(localPoints);
529  pointIndexHit info = collapseSurface
530  (
531  celli,
532  surfPoints,
533  localTris
534  );
535 
536  if (info.hit())
537  {
538  snappedCc[celli] = snappedPoints.size();
539  snappedPoints.append(info.hitPoint());
540 
541  //Pout<< "cell:" << celli
542  // << " at " << mesh_.cellCentres()[celli]
543  // << " collapsing " << surfPoints
544  // << " intersections down to "
545  // << snappedPoints[snappedCc[celli]] << endl;
546  }
547  }
548  }
549  }
550 }
551 
552 
553 void Foam::isoSurfaceCell::genPointTris
554 (
555  const scalarField& cellValues,
556  const scalarField& pointValues,
557  const label pointi,
558  const label facei,
559  const label celli,
560  DynamicList<point, 64>& localTriPoints
561 ) const
562 {
563  const pointField& cc = mesh_.cellCentres();
564  const pointField& pts = mesh_.points();
565  const face& f = mesh_.faces()[facei];
566 
567  const label fp0 = mesh_.tetBasePtIs()[facei];
568  label fp = f.fcIndex(fp0);
569  for (label i = 2; i < f.size(); ++i)
570  {
571  label nextFp = f.fcIndex(fp);
572  triFace tri(f[fp0], f[fp], f[nextFp]);
573 
574  label index = tri.find(pointi);
575 
576  if (index == -1)
577  {
578  continue;
579  }
580 
581  // Tet between index..index-1, index..index+1, index..cc
582  label b = tri[tri.fcIndex(index)];
583  label c = tri[tri.rcIndex(index)];
584 
585  // Get fractions for the three edges emanating from point
586  FixedList<scalar, 3> s(3);
587  s[0] = isoFraction(pointValues[pointi], pointValues[b]);
588  s[1] = isoFraction(pointValues[pointi], pointValues[c]);
589  s[2] = isoFraction(pointValues[pointi], cellValues[celli]);
590 
591  if
592  (
593  (s[0] >= 0.0 && s[0] <= 0.5)
594  && (s[1] >= 0.0 && s[1] <= 0.5)
595  && (s[2] >= 0.0 && s[2] <= 0.5)
596  )
597  {
598  point p0 = (1.0-s[0])*pts[pointi] + s[0]*pts[b];
599  point p1 = (1.0-s[1])*pts[pointi] + s[1]*pts[c];
600  point p2 = (1.0-s[2])*pts[pointi] + s[2]*cc[celli];
601 
602  if
603  (
604  (mesh_.faceOwner()[facei] == celli)
605  == (pointValues[pointi] > cellValues[celli])
606  )
607  {
608  localTriPoints.append(p0);
609  localTriPoints.append(p1);
610  localTriPoints.append(p2);
611  }
612  else
613  {
614  localTriPoints.append(p1);
615  localTriPoints.append(p0);
616  localTriPoints.append(p2);
617  }
618  }
619 
620  fp = nextFp;
621  }
622 }
623 
624 
625 void Foam::isoSurfaceCell::genPointTris
626 (
627  const scalarField& pointValues,
628  const label pointi,
629  const label facei,
630  const label celli,
631  DynamicList<point, 64>& localTriPoints
632 ) const
633 {
634  const pointField& pts = mesh_.points();
635  const cell& cFaces = mesh_.cells()[celli];
636 
637  // Make tet from this face to the 4th point (same as cellcentre in
638  // non-tet cells)
639  const face& f = mesh_.faces()[facei];
640 
641  // Find 4th point
642  label ccPointi = -1;
643  for (const label cfacei : cFaces)
644  {
645  const face& f1 = mesh_.faces()[cfacei];
646  for (const label p1 : f1)
647  {
648  if (!f.found(p1))
649  {
650  ccPointi = p1;
651  break;
652  }
653  }
654  if (ccPointi != -1)
655  {
656  break;
657  }
658  }
659 
660 
661  // Tet between index..index-1, index..index+1, index..cc
662  label index = f.find(pointi);
663  label b = f[f.fcIndex(index)];
664  label c = f[f.rcIndex(index)];
665 
666  //Pout<< " p0:" << pointi << " b:" << b << " c:" << c
667  //<< " d:" << ccPointi << endl;
668 
669  // Get fractions for the three edges emanating from point
670  FixedList<scalar, 3> s(3);
671  s[0] = isoFraction(pointValues[pointi], pointValues[b]);
672  s[1] = isoFraction(pointValues[pointi], pointValues[c]);
673  s[2] = isoFraction(pointValues[pointi], pointValues[ccPointi]);
674 
675  if
676  (
677  (s[0] >= 0.0 && s[0] <= 0.5)
678  && (s[1] >= 0.0 && s[1] <= 0.5)
679  && (s[2] >= 0.0 && s[2] <= 0.5)
680  )
681  {
682  point p0 = (1.0-s[0])*pts[pointi] + s[0]*pts[b];
683  point p1 = (1.0-s[1])*pts[pointi] + s[1]*pts[c];
684  point p2 = (1.0-s[2])*pts[pointi] + s[2]*pts[ccPointi];
685 
686  if (mesh_.faceOwner()[facei] != celli)
687  {
688  localTriPoints.append(p0);
689  localTriPoints.append(p1);
690  localTriPoints.append(p2);
691  }
692  else
693  {
694  localTriPoints.append(p1);
695  localTriPoints.append(p0);
696  localTriPoints.append(p2);
697  }
698  }
699 }
700 
701 
702 void Foam::isoSurfaceCell::calcSnappedPoint
703 (
704  const bitSet& isTet,
705  const scalarField& cVals,
706  const scalarField& pVals,
707 
708  DynamicList<point>& snappedPoints,
709  labelList& snappedPoint
710 ) const
711 {
712  // Determine if point is on boundary. Points on boundaries are never
713  // snapped. Coupled boundaries are handled explicitly so not marked here.
714  bitSet isBoundaryPoint(mesh_.nPoints());
715  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
716  for (const polyPatch& pp : patches)
717  {
718  if (!pp.coupled())
719  {
720  label facei = pp.start();
721  forAll(pp, i)
722  {
723  const face& f = mesh_.faces()[facei++];
724 
725  isBoundaryPoint.set(f);
726  }
727  }
728  }
729 
730 
731  const point greatPoint(GREAT, GREAT, GREAT);
732 
733  pointField collapsedPoint(mesh_.nPoints(), greatPoint);
734 
735 
736  // Work arrays
737  DynamicList<point, 64> localTriPoints(100);
738  labelHashSet localPointCells(100);
739 
740  forAll(mesh_.pointFaces(), pointi)
741  {
742  if (isBoundaryPoint.test(pointi))
743  {
744  continue;
745  }
746 
747  const labelList& pFaces = mesh_.pointFaces()[pointi];
748 
749  bool anyCut = false;
750 
751  for (const label facei : pFaces)
752  {
753  if
754  (
755  cellCutType_[mesh_.faceOwner()[facei]] == CUT
756  || (
757  mesh_.isInternalFace(facei)
758  && cellCutType_[mesh_.faceNeighbour()[facei]] == CUT
759  )
760  )
761  {
762  anyCut = true;
763  break;
764  }
765  }
766 
767  if (!anyCut)
768  {
769  continue;
770  }
771 
772 
773  // Do a pointCells walk (by using pointFaces)
774 
775  localPointCells.clear();
776  localTriPoints.clear();
777 
778  for (const label facei : pFaces)
779  {
780  const label own = mesh_.faceOwner()[facei];
781 
782  if (isTet.test(own))
783  {
784  // Since tets have no cell centre to include make sure
785  // we only generate a triangle once per point.
786  if (localPointCells.insert(own))
787  {
788  genPointTris(pVals, pointi, facei, own, localTriPoints);
789  }
790  }
791  else
792  {
793  genPointTris
794  (
795  cVals,
796  pVals,
797  pointi,
798  facei,
799  own,
800  localTriPoints
801  );
802  }
803 
804  if (mesh_.isInternalFace(facei))
805  {
806  const label nei = mesh_.faceNeighbour()[facei];
807 
808  if (isTet.test(nei))
809  {
810  if (localPointCells.insert(nei))
811  {
812  genPointTris(pVals, pointi, facei, nei, localTriPoints);
813  }
814  }
815  else
816  {
817  genPointTris
818  (
819  cVals,
820  pVals,
821  pointi,
822  facei,
823  nei,
824  localTriPoints
825  );
826  }
827  }
828  }
829 
830  if (localTriPoints.size() == 3)
831  {
832  // Single triangle. No need for any analysis. Average points.
834  points.transfer(localTriPoints);
835  collapsedPoint[pointi] = sum(points)/points.size();
836 
837  //Pout<< " point:" << pointi
838  // << " replacing coord:" << mesh_.points()[pointi]
839  // << " by average:" << collapsedPoint[pointi] << endl;
840  }
841  else if (localTriPoints.size())
842  {
843  // Convert points into triSurface.
844 
845  // Merge points and compact out non-valid triangles
846  labelList triMap; // merged to unmerged triangle
847  labelList triPointReverseMap; // unmerged to merged point
848  triSurface surf
849  (
850  stitchTriPoints
851  (
852  false, // do not check for duplicate tris
853  localTriPoints,
854  triPointReverseMap,
855  triMap
856  )
857  );
858 
859  labelList faceZone;
860  label nZones = surf.markZones
861  (
862  boolList(surf.nEdges(), false),
863  faceZone
864  );
865 
866  if (nZones == 1)
867  {
868  // Check that all normals make a decent angle
869  scalar minCos = GREAT;
870  const vector& n0 = surf.faceNormals()[0];
871  for (label i = 1; i < surf.size(); ++i)
872  {
873  const vector& n = surf.faceNormals()[i];
874  scalar cosAngle = (n0 & n);
875  if (cosAngle < minCos)
876  {
877  minCos = cosAngle;
878  }
879  }
880  if (minCos > 0)
881  {
882  collapsedPoint[pointi] = calcCentre(surf);
883  }
884  }
885  }
886  }
887 
889  (
890  mesh_,
891  collapsedPoint,
892  minMagSqrEqOp<point>(),
893  greatPoint
894  );
895 
896  snappedPoint.setSize(mesh_.nPoints());
897  snappedPoint = -1;
898 
899  forAll(collapsedPoint, pointi)
900  {
901  // Cannot do == comparison since might be transformed so have
902  // truncation errors.
903  if (magSqr(collapsedPoint[pointi]) < 0.5*magSqr(greatPoint))
904  {
905  snappedPoint[pointi] = snappedPoints.size();
906  snappedPoints.append(collapsedPoint[pointi]);
907  }
908  }
909 }
910 
911 
912 Foam::triSurface Foam::isoSurfaceCell::stitchTriPoints
913 (
914  const bool checkDuplicates,
915  const List<point>& triPoints,
916  labelList& triPointReverseMap, // unmerged to merged point
917  labelList& triMap // merged to unmerged triangle
918 ) const
919 {
920  label nTris = triPoints.size()/3;
921 
922  if ((triPoints.size() % 3) != 0)
923  {
925  << "Problem: number of points " << triPoints.size()
926  << " not a multiple of 3." << abort(FatalError);
927  }
928 
929  pointField newPoints;
931  (
932  triPoints,
933  mergeDistance_,
934  false,
935  triPointReverseMap,
936  newPoints
937  );
938 
939  // Check that enough merged.
940  if (debug)
941  {
942  Pout<< "isoSurfaceCell : merged from " << triPoints.size()
943  << " points down to " << newPoints.size() << endl;
944 
945  pointField newNewPoints;
946  labelList oldToNew;
947  bool hasMerged = mergePoints
948  (
949  newPoints,
950  mergeDistance_,
951  true,
952  oldToNew,
953  newNewPoints
954  );
955 
956  if (hasMerged)
957  {
959  << "Merged points contain duplicates"
960  << " when merging with distance " << mergeDistance_ << endl
961  << "merged:" << newPoints.size() << " re-merged:"
962  << newNewPoints.size()
963  << abort(FatalError);
964  }
965  }
966 
967 
968  List<labelledTri> tris;
969  {
970  DynamicList<labelledTri> dynTris(nTris);
971  label rawPointi = 0;
972  DynamicList<label> newToOldTri(nTris);
973 
974  for (label oldTriI = 0; oldTriI < nTris; ++oldTriI)
975  {
976  labelledTri tri
977  (
978  triPointReverseMap[rawPointi],
979  triPointReverseMap[rawPointi+1],
980  triPointReverseMap[rawPointi+2],
981  0
982  );
983  if ((tri[0] != tri[1]) && (tri[0] != tri[2]) && (tri[1] != tri[2]))
984  {
985  newToOldTri.append(oldTriI);
986  dynTris.append(tri);
987  }
988 
989  rawPointi += 3;
990  }
991 
992  triMap.transfer(newToOldTri);
993  tris.transfer(dynTris);
994  }
995 
996 
997  // Use face centres to determine 'flat hole' situation (see RMT paper).
998  // Two unconnected triangles get connected because (some of) the edges
999  // separating them get collapsed. Below only checks for duplicate triangles,
1000  // not non-manifold edge connectivity.
1001  if (checkDuplicates)
1002  {
1003  if (debug)
1004  {
1005  Pout<< "isoSurfaceCell : merged from " << nTris
1006  << " down to " << tris.size() << " triangles." << endl;
1007  }
1008 
1009  pointField centres(tris.size());
1010  forAll(tris, triI)
1011  {
1012  centres[triI] = tris[triI].centre(newPoints);
1013  }
1014 
1015  pointField mergedCentres;
1016  labelList oldToMerged;
1017  bool hasMerged = mergePoints
1018  (
1019  centres,
1020  mergeDistance_,
1021  false,
1022  oldToMerged,
1023  mergedCentres
1024  );
1025 
1026  if (debug)
1027  {
1028  Pout<< "isoSurfaceCell : detected "
1029  << centres.size()-mergedCentres.size()
1030  << " duplicate triangles." << endl;
1031  }
1032 
1033  if (hasMerged)
1034  {
1035  // Filter out duplicates.
1036  label newTriI = 0;
1037  DynamicList<label> newToOldTri(tris.size());
1038  labelList newToMaster(mergedCentres.size(), -1);
1039  forAll(tris, triI)
1040  {
1041  label mergedI = oldToMerged[triI];
1042 
1043  if (newToMaster[mergedI] == -1)
1044  {
1045  newToMaster[mergedI] = triI;
1046  newToOldTri.append(triMap[triI]);
1047  tris[newTriI++] = tris[triI];
1048  }
1049  }
1050 
1051  triMap.transfer(newToOldTri);
1052  tris.setSize(newTriI);
1053  }
1054  }
1055 
1056  return triSurface(tris, geometricSurfacePatchList(0), newPoints, true);
1057 }
1058 
1059 
1060 void Foam::isoSurfaceCell::calcAddressing
1061 (
1062  const triSurface& surf,
1063  List<FixedList<label, 3>>& faceEdges,
1064  labelList& edgeFace0,
1065  labelList& edgeFace1,
1066  Map<labelList>& edgeFacesRest
1067 ) const
1068 {
1069  const pointField& points = surf.points();
1070 
1071  pointField edgeCentres(3*surf.size());
1072  label edgeI = 0;
1073  forAll(surf, triI)
1074  {
1075  const labelledTri& tri = surf[triI];
1076  edgeCentres[edgeI++] = 0.5*(points[tri[0]]+points[tri[1]]);
1077  edgeCentres[edgeI++] = 0.5*(points[tri[1]]+points[tri[2]]);
1078  edgeCentres[edgeI++] = 0.5*(points[tri[2]]+points[tri[0]]);
1079  }
1080 
1081  pointField mergedCentres;
1082  labelList oldToMerged;
1083  bool hasMerged = mergePoints
1084  (
1085  edgeCentres,
1086  mergeDistance_,
1087  false,
1088  oldToMerged,
1089  mergedCentres
1090  );
1091 
1092  if (debug)
1093  {
1094  Pout<< "isoSurfaceCell : detected "
1095  << mergedCentres.size()
1096  << " edges on " << surf.size() << " triangles." << endl;
1097  }
1098 
1099  if (!hasMerged)
1100  {
1101  return;
1102  }
1103 
1104 
1105  // Determine faceEdges
1106  faceEdges.setSize(surf.size());
1107  edgeI = 0;
1108  forAll(surf, triI)
1109  {
1110  faceEdges[triI][0] = oldToMerged[edgeI++];
1111  faceEdges[triI][1] = oldToMerged[edgeI++];
1112  faceEdges[triI][2] = oldToMerged[edgeI++];
1113  }
1114 
1115 
1116  // Determine edgeFaces
1117  edgeFace0.setSize(mergedCentres.size());
1118  edgeFace0 = -1;
1119  edgeFace1.setSize(mergedCentres.size());
1120  edgeFace1 = -1;
1121  edgeFacesRest.clear();
1122 
1123  forAll(oldToMerged, oldEdgeI)
1124  {
1125  label triI = oldEdgeI / 3;
1126  label edgeI = oldToMerged[oldEdgeI];
1127 
1128  if (edgeFace0[edgeI] == -1)
1129  {
1130  edgeFace0[edgeI] = triI;
1131  }
1132  else if (edgeFace1[edgeI] == -1)
1133  {
1134  edgeFace1[edgeI] = triI;
1135  }
1136  else
1137  {
1138  //WarningInFunction
1139  // << "Edge " << edgeI << " with centre " << mergedCentres[edgeI]
1140  // << " used by more than two triangles: " << edgeFace0[edgeI]
1141  // << ", "
1142  // << edgeFace1[edgeI] << " and " << triI << endl;
1143  Map<labelList>::iterator iter = edgeFacesRest.find(edgeI);
1144 
1145  if (iter != edgeFacesRest.end())
1146  {
1147  labelList& eFaces = iter();
1148  label sz = eFaces.size();
1149  eFaces.setSize(sz+1);
1150  eFaces[sz] = triI;
1151  }
1152  else
1153  {
1154  edgeFacesRest.insert(edgeI, labelList(1, triI));
1155  }
1156  }
1157  }
1158 }
1159 
1160 
1161 bool Foam::isoSurfaceCell::danglingTriangle
1162 (
1163  const FixedList<label, 3>& fEdges,
1164  const labelList& edgeFace1
1165 )
1166 {
1167  label nOpen = 0;
1168  for (const label edgei : fEdges)
1169  {
1170  if (edgeFace1[edgei] == -1)
1171  {
1172  ++nOpen;
1173  }
1174  }
1175 
1176  return (nOpen == 1 || nOpen == 2 || nOpen == 3);
1177 }
1178 
1179 
1180 Foam::label Foam::isoSurfaceCell::markDanglingTriangles
1181 (
1182  const List<FixedList<label, 3>>& faceEdges,
1183  const labelList& edgeFace0,
1184  const labelList& edgeFace1,
1185  const Map<labelList>& edgeFacesRest,
1186  boolList& keepTriangles
1187 )
1188 {
1189  keepTriangles.setSize(faceEdges.size());
1190  keepTriangles = true;
1191 
1192  label nDangling = 0;
1193 
1194  // Remove any dangling triangles
1195  forAllConstIters(edgeFacesRest, iter)
1196  {
1197  // These are all the non-manifold edges. Filter out all triangles
1198  // with only one connected edge (= this edge)
1199 
1200  const label edgeI = iter.key();
1201  const labelList& otherEdgeFaces = iter.val();
1202 
1203  // Remove all dangling triangles
1204  if (danglingTriangle(faceEdges[edgeFace0[edgeI]], edgeFace1))
1205  {
1206  keepTriangles[edgeFace0[edgeI]] = false;
1207  ++nDangling;
1208  }
1209  if (danglingTriangle(faceEdges[edgeFace1[edgeI]], edgeFace1))
1210  {
1211  keepTriangles[edgeFace1[edgeI]] = false;
1212  ++nDangling;
1213  }
1214  for (const label triI : otherEdgeFaces)
1215  {
1216  if (danglingTriangle(faceEdges[triI], edgeFace1))
1217  {
1218  keepTriangles[triI] = false;
1219  ++nDangling;
1220  }
1221  }
1222  }
1223  return nDangling;
1224 }
1225 
1226 
1227 Foam::triSurface Foam::isoSurfaceCell::subsetMesh
1228 (
1229  const triSurface& s,
1230  const labelList& newToOldFaces,
1231  labelList& oldToNewPoints,
1232  labelList& newToOldPoints
1233 )
1234 {
1235  const boolList include
1236  (
1237  ListOps::createWithValue<bool>(s.size(), newToOldFaces, true, false)
1238  );
1239 
1240  newToOldPoints.setSize(s.points().size());
1241  oldToNewPoints.setSize(s.points().size());
1242  oldToNewPoints = -1;
1243  {
1244  label pointi = 0;
1245 
1246  forAll(include, oldFacei)
1247  {
1248  if (include[oldFacei])
1249  {
1250  // Renumber labels for face
1251  const triSurface::FaceType& f = s[oldFacei];
1252 
1253  for (const label oldPointi : f)
1254  {
1255  if (oldToNewPoints[oldPointi] == -1)
1256  {
1257  oldToNewPoints[oldPointi] = pointi;
1258  newToOldPoints[pointi++] = oldPointi;
1259  }
1260  }
1261  }
1262  }
1263  newToOldPoints.setSize(pointi);
1264  }
1265 
1266  // Extract points
1267  pointField newPoints(newToOldPoints.size());
1268  forAll(newToOldPoints, i)
1269  {
1270  newPoints[i] = s.points()[newToOldPoints[i]];
1271  }
1272  // Extract faces
1273  List<labelledTri> newTriangles(newToOldFaces.size());
1274 
1275  forAll(newToOldFaces, i)
1276  {
1277  // Get old vertex labels
1278  const labelledTri& tri = s[newToOldFaces[i]];
1279 
1280  newTriangles[i][0] = oldToNewPoints[tri[0]];
1281  newTriangles[i][1] = oldToNewPoints[tri[1]];
1282  newTriangles[i][2] = oldToNewPoints[tri[2]];
1283  newTriangles[i].region() = tri.region();
1284  }
1285 
1286  // Reuse storage.
1287  return triSurface(newTriangles, s.patches(), newPoints, true);
1288 }
1289 
1290 
1291 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1292 
1295  const polyMesh& mesh,
1296  const scalarField& cellValues,
1297  const scalarField& pointValues,
1298  const scalar iso,
1299  const isoSurfaceBase::filterType filter,
1300  const boundBox& bounds,
1301  const scalar mergeTol,
1302  const bitSet& ignoreCells
1303 )
1304 :
1306  (
1307  mesh,
1308  cellValues,
1309  pointValues,
1310  iso,
1311  (filter != filterType::NONE),
1312  bounds,
1313  mergeTol,
1314  ignoreCells
1315  )
1316 {}
1317 
1318 
1321  const polyMesh& mesh,
1322  const scalarField& cellValues,
1323  const scalarField& pointValues,
1324  const scalar iso,
1325  const bool regularise,
1326  const boundBox& bounds,
1327  const scalar mergeTol,
1328  const bitSet& ignoreCells
1329 )
1330 :
1331  isoSurfaceBase(iso, bounds),
1332  mesh_(mesh),
1333  cVals_(cellValues),
1334  pVals_(pointValues),
1335  ignoreCells_(ignoreCells),
1336  mergeDistance_(mergeTol*mesh.bounds().mag())
1337 {
1338  if (debug)
1339  {
1340  Pout<< "isoSurfaceCell::"
1341  << " cell min/max : "
1342  << min(cVals_) << " / "
1343  << max(cVals_) << nl
1344  << " point min/max : "
1345  << min(pVals_) << " / "
1346  << max(pVals_) << nl
1347  << " isoValue : " << iso << nl
1348  << " filter : " << Switch(regularise) << nl
1349  << " mergeTol : " << mergeTol << nl
1350  << " mesh span : " << mesh.bounds().mag() << nl
1351  << " mergeDistance : " << mergeDistance_ << nl
1352  << " ignoreCells : " << ignoreCells_.count()
1353  << " / " << cVals_.size() << nl
1354  << endl;
1355  }
1356 
1357  // Determine if cell is tet
1358  bitSet isTet(mesh_.nCells());
1359  {
1360  tetMatcher tet;
1361 
1362  forAll(isTet, celli)
1363  {
1364  if (tet.isA(mesh_, celli))
1365  {
1366  isTet.set(celli);
1367  }
1368  }
1369  }
1370 
1371 
1372  // Determine if any cut through cell
1373  calcCutTypes(isTet, cellValues, pointValues);
1374 
1375  if (debug && isA<fvMesh>(mesh))
1376  {
1377  const fvMesh& fvm = dynamicCast<const fvMesh&>(mesh);
1378 
1379  volScalarField debugField
1380  (
1381  IOobject
1382  (
1383  "isoSurfaceCell.cutType",
1384  fvm.time().timeName(),
1385  fvm.time(),
1388  false
1389  ),
1390  fvm,
1392  );
1393 
1394  auto& debugFld = debugField.primitiveFieldRef();
1395 
1396  forAll(cellCutType_, celli)
1397  {
1398  debugFld[celli] = cellCutType_[celli];
1399  }
1400 
1401  Pout<< "Writing cut types:"
1402  << debugField.objectPath() << endl;
1403 
1404  debugField.write();
1405  }
1406 
1407 
1408  DynamicList<point> snappedPoints(nCutCells_);
1409 
1410  // Per cc -1 or a point inside snappedPoints.
1411  labelList snappedCc;
1412  if (regularise)
1413  {
1414  calcSnappedCc
1415  (
1416  isTet,
1417  cellValues,
1418  pointValues,
1419  snappedPoints,
1420  snappedCc
1421  );
1422  }
1423  else
1424  {
1425  snappedCc.setSize(mesh_.nCells());
1426  snappedCc = -1;
1427  }
1428 
1429  if (debug)
1430  {
1431  Pout<< "isoSurfaceCell : shifted " << snappedPoints.size()
1432  << " cell centres to intersection." << endl;
1433  }
1434 
1435  snappedPoints.shrink();
1436  label nCellSnaps = snappedPoints.size();
1437 
1438  // Per point -1 or a point inside snappedPoints.
1439  labelList snappedPoint;
1440  if (regularise)
1441  {
1442  calcSnappedPoint
1443  (
1444  isTet,
1445  cellValues,
1446  pointValues,
1447  snappedPoints,
1448  snappedPoint
1449  );
1450  }
1451  else
1452  {
1453  snappedPoint.setSize(mesh_.nPoints());
1454  snappedPoint = -1;
1455  }
1456 
1457  if (debug)
1458  {
1459  Pout<< "isoSurfaceCell : shifted " << snappedPoints.size()-nCellSnaps
1460  << " vertices to intersection." << endl;
1461  }
1462 
1463 
1464  // Use a triSurface as a temporary for various operations
1465  triSurface tmpsurf;
1466 
1467  {
1468  DynamicList<point> triPoints(nCutCells_);
1469  DynamicList<label> triMeshCells(nCutCells_);
1470 
1471  generateTriPoints
1472  (
1473  cellValues,
1474  pointValues,
1475 
1476  mesh_.cellCentres(),
1477  mesh_.points(),
1478 
1479  snappedPoints,
1480  snappedCc,
1481  snappedPoint,
1482 
1483  triPoints,
1484  triMeshCells
1485  );
1486 
1487  if (debug)
1488  {
1489  Pout<< "isoSurfaceCell : generated " << triMeshCells.size()
1490  << " unmerged triangles." << endl;
1491  }
1492 
1493 
1494  label nOldPoints = triPoints.size();
1495 
1496  // Trimmed to original triangle
1497  DynamicList<label> trimTriMap;
1498  // Trimmed to original point
1499  labelList trimTriPointMap;
1500  if (bounds_.valid())
1501  {
1502  isoSurface::trimToBox
1503  (
1504  treeBoundBox(bounds_),
1505  triPoints, // new points
1506  trimTriMap, // map from (new) triangle to original
1507  trimTriPointMap, // map from (new) point to original
1508  interpolatedPoints_, // labels of newly introduced points
1509  interpolatedOldPoints_, // and their interpolation
1510  interpolationWeights_
1511  );
1512  triMeshCells = labelField(triMeshCells, trimTriMap);
1513  }
1514 
1515 
1516  // Merge points and compact out non-valid triangles
1517  labelList triMap; // merged to unmerged triangle
1518  tmpsurf = stitchTriPoints
1519  (
1520  regularise, // check for duplicate tris
1521  triPoints,
1522  triPointMergeMap_, // unmerged to merged point
1523  triMap // merged to unmerged triangle
1524  );
1525 
1526  if (debug)
1527  {
1528  Pout<< "isoSurfaceCell : generated " << triMap.size()
1529  << " merged triangles." << endl;
1530  }
1531 
1532  if (bounds_.valid())
1533  {
1534  // Adjust interpolatedPoints_
1535  inplaceRenumber(triPointMergeMap_, interpolatedPoints_);
1536 
1537  // Adjust triPointMergeMap_
1538  labelList newTriPointMergeMap(nOldPoints, -1);
1539  forAll(trimTriPointMap, trimPointI)
1540  {
1541  label oldPointI = trimTriPointMap[trimPointI];
1542  if (oldPointI >= 0)
1543  {
1544  label pointI = triPointMergeMap_[trimPointI];
1545  if (pointI >= 0)
1546  {
1547  newTriPointMergeMap[oldPointI] = pointI;
1548  }
1549  }
1550  }
1551  triPointMergeMap_.transfer(newTriPointMergeMap);
1552  }
1553 
1554  meshCells_.setSize(triMap.size());
1555  forAll(triMap, i)
1556  {
1557  meshCells_[i] = triMeshCells[triMap[i]];
1558  }
1559  }
1560 
1561 
1562  if (debug)
1563  {
1564  Pout<< "isoSurfaceCell : checking " << tmpsurf.size()
1565  << " triangles for validity." << endl;
1566 
1567  forAll(tmpsurf, triI)
1568  {
1569  triSurfaceTools::validTri(tmpsurf, triI);
1570  }
1571  }
1572 
1573 
1574  if (regularise)
1575  {
1576  List<FixedList<label, 3>> faceEdges;
1577  labelList edgeFace0, edgeFace1;
1578  Map<labelList> edgeFacesRest;
1579 
1580 
1581  while (true)
1582  {
1583  // Calculate addressing
1584  calcAddressing
1585  (
1586  tmpsurf,
1587  faceEdges,
1588  edgeFace0,
1589  edgeFace1,
1590  edgeFacesRest
1591  );
1592 
1593  // See if any dangling triangles
1594  boolList keepTriangles;
1595  label nDangling = markDanglingTriangles
1596  (
1597  faceEdges,
1598  edgeFace0,
1599  edgeFace1,
1600  edgeFacesRest,
1601  keepTriangles
1602  );
1603 
1604  if (debug)
1605  {
1606  Pout<< "isoSurfaceCell : detected " << nDangling
1607  << " dangling triangles." << endl;
1608  }
1609 
1610  if (nDangling == 0)
1611  {
1612  break;
1613  }
1614 
1615  // Create face map (new to old)
1616  labelList subsetTriMap(findIndices(keepTriangles, true));
1617 
1618  labelList subsetPointMap;
1619  labelList reversePointMap;
1620  tmpsurf = subsetMesh
1621  (
1622  tmpsurf,
1623  subsetTriMap,
1624  reversePointMap,
1625  subsetPointMap
1626  );
1627  meshCells_ = labelField(meshCells_, subsetTriMap);
1628  inplaceRenumber(reversePointMap, triPointMergeMap_);
1629  }
1630  }
1631 
1632 
1633  // Transfer to mesh storage. Note, an iso-surface has no zones
1634  {
1635  // Recover the pointField
1636  pointField pts;
1637  tmpsurf.swapPoints(pts);
1638 
1639  // Transcribe from triFace to face
1640  faceList faces;
1641  tmpsurf.triFaceFaces(faces);
1642 
1643  tmpsurf.clearOut();
1644 
1645  MeshStorage updated(std::move(pts), std::move(faces), surfZoneList());
1646 
1647  this->MeshStorage::transfer(updated);
1648  }
1649 }
1650 
1651 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
nZones
label nZones
Definition: interpolatedFaces.H:24
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::Switch
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:70
Foam::boundBox::mag
scalar mag() const
The magnitude of the bounding box span.
Definition: boundBoxI.H:133
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::triSurface::clearOut
void clearOut()
Definition: triSurface.C:542
Foam::isoSurfaceBase
Low-level components common to various iso-surface algorithms.
Definition: isoSurfaceBase.H:54
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::DynamicList< point >
isoSurfaceCell.H
Foam::triSurface::triFaceFaces
void triFaceFaces(List< face > &plainFaceList) const
Create a list of faces from the triFaces.
Definition: triSurface.C:660
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:87
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:764
Foam::tetMatcher
A cellMatcher for tet cells (cellModel::TET)
Definition: tetMatcher.H:53
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: HashTableFwd.H:46
Foam::FixedList::size
static constexpr label size() noexcept
Return the number of elements in the FixedList.
Definition: FixedList.H:368
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
triPoints.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::syncTools::syncPointPositions
static void syncPointPositions(const polyMesh &mesh, List< point > &positions, const CombineOp &cop, const point &nullValue)
Synchronize locations on all mesh points.
Definition: syncTools.H:199
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::Map::iterator
typename parent_type::iterator iterator
Definition: Map.H:69
triSurface.H
polyMesh.H
Foam::DynamicList::shrink
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:376
Foam::isTriCut
static bool isTriCut(const label a, const label b, const label c, const scalarField &pointValues, const scalar isoValue)
Definition: isoSurfaceCell.C:55
syncTools.H
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::isoSurfaceCell
A surface formed by the iso value. After "Polygonising A Scalar Field Using Tetrahedrons",...
Definition: isoSurfaceCell.H:69
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::geometricSurfacePatchList
List< geometricSurfacePatch > geometricSurfacePatchList
Definition: geometricSurfacePatchList.H:46
Foam::labelPair
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:54
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::triPoints
Triangle storage. Null constructable (unfortunately triangle<point, point> is not)
Definition: triPoints.H:52
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:55
Foam::label
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:62
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::Field< scalar >
Foam::labelField
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:52
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:70
Foam::triSurface::swapPoints
virtual void swapPoints(pointField &pts)
Swap points. Similar to movePoints, but returns the old points.
Definition: triSurface.C:601
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:436
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
Foam::isoSurfaceBase::iso_
const scalar iso_
Iso value.
Definition: isoSurfaceBase.H:66
Foam::PrimitivePatch< labelledTri, ::Foam::List, pointField, point >::FaceType
labelledTri FaceType
Definition: PrimitivePatch.H:100
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:84
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::GeometricField::primitiveFieldRef
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
Definition: GeometricField.C:735
Foam::polyMesh::bounds
const boundBox & bounds() const
Return mesh bounding box.
Definition: polyMesh.H:441
isoSurface.H
Time.H
Foam::isoSurfaceCell::isoSurfaceCell
isoSurfaceCell(const polyMesh &mesh, const scalarField &cellValues, const scalarField &pointValues, const scalar iso, const isoSurfaceBase::filterType filter, const boundBox &bounds=boundBox::invertedBox, const scalar mergeTol=1e-6, const bitSet &ignoreCells=bitSet())
Construct from cell and point values.
Definition: isoSurfaceCell.C:1294
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:45
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:54
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
f
labelList f(nPoints)
Foam::tetMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label celli)
Exact match. Uses faceSizeMatch.
Definition: tetMatcher.C:213
Foam::Vector
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition: Vector.H:62
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
dictionary.H
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
tetMatcher.H
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::surfZoneList
List< surfZone > surfZoneList
Definition: surfZoneList.H:47
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:320
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
mergePoints.H
Merge points. See below.
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:246
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::triSurfaceTools::validTri
static bool validTri(const triSurface &, const label facei, const bool verbose=true)
Check single triangle for (topological) validity.
Definition: triSurfaceTools.C:2699
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:415
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::MeshedSurface< face >
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
triFace
face triFace(3)
triSurfaceTools.H
Foam::isoSurfaceBase::filterType
filterType
The filtering (regularization) to apply.
Definition: isoSurfaceBase.H:87