isoSurfaceTopo.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-2019 OpenFOAM Foundation
9  Copyright (C) 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 "isoSurfaceTopo.H"
30 #include "isoSurface.H"
31 #include "polyMesh.H"
32 #include "tetMatcher.H"
33 #include "tetPointRef.H"
34 #include "DynamicField.H"
35 #include "syncTools.H"
37 #include "cyclicACMIPolyPatch.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43  defineTypeNameAndDebug(isoSurfaceTopo, 0);
44 }
45 
46 
47 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
48 
49 namespace Foam
50 {
51  // Does any edge of triangle cross iso value?
52  inline static bool isTriCut
53  (
54  const label a,
55  const label b,
56  const label c,
57  const scalarField& pointValues,
58  const scalar isoValue
59  )
60  {
61  const bool aLower = (pointValues[a] < isoValue);
62  const bool bLower = (pointValues[b] < isoValue);
63  const bool cLower = (pointValues[c] < isoValue);
64 
65  return !(aLower == bLower && aLower == cLower);
66  }
67 }
68 
69 
70 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
71 
72 Foam::isoSurfaceTopo::cellCutType Foam::isoSurfaceTopo::calcCutType
73 (
74  const bool isTet,
75  const label celli
76 ) const
77 {
78  if (ignoreCells_.test(celli))
79  {
80  return NOTCUT;
81  }
82 
83  const cell& cFaces = mesh_.cells()[celli];
84 
85  if (isTet)
86  {
87  for (const label facei : cFaces)
88  {
89  if
90  (
91  !mesh_.isInternalFace(facei)
92  && ignoreBoundaryFaces_.test(facei-mesh_.nInternalFaces())
93  )
94  {
95  continue;
96  }
97 
98  const face& f = mesh_.faces()[facei];
99 
100  for (label fp = 1; fp < f.size() - 1; ++fp)
101  {
102  if (isTriCut(f[0], f[fp], f[f.fcIndex(fp)], pVals_, iso_))
103  {
104  return CUT;
105  }
106  }
107  }
108  return NOTCUT;
109  }
110 
111 
112  const bool cellLower = (cVals_[celli] < iso_);
113 
114  // First check if there is any cut in cell
115  bool edgeCut = false;
116 
117  for (const label facei : cFaces)
118  {
119  if
120  (
121  !mesh_.isInternalFace(facei)
122  && ignoreBoundaryFaces_.test(facei-mesh_.nInternalFaces())
123  )
124  {
125  continue;
126  }
127 
128  const face& f = mesh_.faces()[facei];
129 
130  // Check pyramids cut
131  for (const label pointi : f)
132  {
133  if ((pVals_[pointi] < iso_) != cellLower)
134  {
135  edgeCut = true;
136  break;
137  }
138  }
139 
140  if (edgeCut)
141  {
142  break;
143  }
144 
145  // Check (triangulated) face edges
146  // With fallback for problem decompositions
147  const label fp0 = (tetBasePtIs_[facei] < 0 ? 0 : tetBasePtIs_[facei]);
148 
149  label fp = f.fcIndex(fp0);
150  for (label i = 2; i < f.size(); ++i)
151  {
152  const label nextFp = f.fcIndex(fp);
153 
154  if (isTriCut(f[fp0], f[fp], f[nextFp], pVals_, iso_))
155  {
156  edgeCut = true;
157  break;
158  }
159 
160  fp = nextFp;
161  }
162 
163  if (edgeCut)
164  {
165  break;
166  }
167  }
168 
169  if (edgeCut)
170  {
171  // Count actual cuts (expensive since addressing needed)
172  // Note: not needed if you don't want to preserve maxima/minima
173  // centred around cellcentre. In that case just always return CUT
174 
175  const labelList& cPoints = mesh_.cellPoints(celli);
176 
177  label nPyrCuts = 0;
178 
179  for (const label pointi : cPoints)
180  {
181  if ((pVals_[pointi] < iso_) != cellLower)
182  {
183  ++nPyrCuts;
184  }
185  }
186 
187  if (nPyrCuts == cPoints.size())
188  {
189  return SPHERE;
190  }
191  else if (nPyrCuts)
192  {
193  return CUT;
194  }
195  }
196 
197  return NOTCUT;
198 }
199 
200 
201 Foam::label Foam::isoSurfaceTopo::calcCutTypes
202 (
203  tetMatcher& tet,
204  List<cellCutType>& cellCutTypes
205 )
206 {
207  cellCutTypes.setSize(mesh_.nCells());
208 
209  label nCutCells = 0;
210  forAll(cellCutTypes, celli)
211  {
212  cellCutTypes[celli] = calcCutType(tet.isA(mesh_, celli), celli);
213 
214  if (cellCutTypes[celli] == CUT)
215  {
216  ++nCutCells;
217  }
218  }
219 
220  if (debug)
221  {
222  Pout<< "isoSurfaceCell : candidate cut cells "
223  << nCutCells << " / " << mesh_.nCells() << endl;
224  }
225  return nCutCells;
226 }
227 
228 
229 Foam::scalar Foam::isoSurfaceTopo::minTetQ
230 (
231  const label facei,
232  const label faceBasePtI
233 ) const
234 {
236  (
237  mesh_,
238  mesh_.cellCentres()[mesh_.faceOwner()[facei]],
239  facei,
240  true,
241  faceBasePtI
242  );
243 
244  if (mesh_.isInternalFace(facei))
245  {
246  q = min
247  (
248  q,
250  (
251  mesh_,
252  mesh_.cellCentres()[mesh_.faceNeighbour()[facei]],
253  facei,
254  false,
255  faceBasePtI
256  )
257  );
258  }
259  return q;
260 }
261 
262 
263 void Foam::isoSurfaceTopo::fixTetBasePtIs()
264 {
265  // Determine points used by two faces on the same cell
266  const cellList& cells = mesh_.cells();
267  const faceList& faces = mesh_.faces();
268  const labelList& faceOwner = mesh_.faceOwner();
269  const labelList& faceNeighbour = mesh_.faceNeighbour();
270 
271 
272  // Get face triangulation base point
273  tetBasePtIs_ = mesh_.tetBasePtIs();
274 
275 
276  // Pre-filter: mark all cells with illegal base points
277  bitSet problemCells(cells.size());
278 
279  forAll(tetBasePtIs_, facei)
280  {
281  if (tetBasePtIs_[facei] == -1)
282  {
283  problemCells.set(faceOwner[facei]);
284 
285  if (mesh_.isInternalFace(facei))
286  {
287  problemCells.set(faceNeighbour[facei]);
288  }
289  }
290  }
291 
292 
293  // Mark all points that are shared by just two faces within an adjacent
294  // problem cell as problematic
295  bitSet problemPoints(mesh_.points().size());
296 
297  {
298  // Number of times a point occurs in a cell.
299  // Used to detect dangling vertices (count = 2)
300  Map<label> pointCount;
301 
302  // Analyse problem cells for points shared by two faces only
303  for (const label celli : problemCells)
304  {
305  pointCount.clear();
306 
307  for (const label facei : cells[celli])
308  {
309  for (const label pointi : faces[facei])
310  {
311  ++pointCount(pointi);
312  }
313  }
314 
315  forAllConstIters(pointCount, iter)
316  {
317  if (iter.val() == 1)
318  {
320  << "point:" << iter.key()
321  << " at:" << mesh_.points()[iter.key()]
322  << " only used by one face" << nl
323  << exit(FatalError);
324  }
325  else if (iter.val() == 2)
326  {
327  problemPoints.set(iter.key());
328  }
329  }
330  }
331  }
332 
333 
334  // For all faces which form a part of a problem-cell, check if the base
335  // point is adjacent to any problem points. If it is, re-calculate the base
336  // point so that it is not.
337  label nAdapted = 0;
338  forAll(tetBasePtIs_, facei)
339  {
340  if
341  (
342  problemCells[faceOwner[facei]]
343  || (mesh_.isInternalFace(facei) && problemCells[faceNeighbour[facei]])
344  )
345  {
346  const face& f = faces[facei];
347 
348  // Check if either of the points adjacent to the base point is a
349  // problem point. If not, the existing base point can be retained.
350  const label fp0 = tetBasePtIs_[facei] < 0 ? 0 : tetBasePtIs_[facei];
351 
352  if
353  (
354  !problemPoints[f[f.rcIndex(fp0)]]
355  && !problemPoints[f[f.fcIndex(fp0)]]
356  )
357  {
358  continue;
359  }
360 
361  // A new base point is required. Pick the point that results in the
362  // least-worst tet and which is not adjacent to any problem points.
363  scalar maxQ = -GREAT;
364  label maxFp = -1;
365  forAll(f, fp)
366  {
367  if
368  (
369  !problemPoints[f[f.rcIndex(fp)]]
370  && !problemPoints[f[f.fcIndex(fp)]]
371  )
372  {
373  const scalar q = minTetQ(facei, fp);
374  if (q > maxQ)
375  {
376  maxQ = q;
377  maxFp = fp;
378  }
379  }
380  }
381 
382  if (maxFp != -1)
383  {
384  // Success! Set the new base point
385  tetBasePtIs_[facei] = maxFp;
386  }
387  else
388  {
389  // No point was found on face that would not result in some
390  // duplicate triangle. Do what? Continue and hope? Spit an
391  // error? Silently or noisily reduce the filtering level?
392 
393  tetBasePtIs_[facei] = 0;
394  }
395 
396  ++nAdapted;
397  }
398  }
399 
400 
401  if (debug)
402  {
403  Pout<< "isoSurface : adapted starting point of triangulation on "
404  << nAdapted << " faces." << endl;
405  }
406 
407  syncTools::syncFaceList(mesh_, tetBasePtIs_, maxEqOp<label>());
408 }
409 
410 
411 Foam::label Foam::isoSurfaceTopo::generatePoint
412 (
413  const label facei,
414  const bool edgeIsDiag,
415  const edge& vertices,
416 
417  DynamicList<edge>& pointToVerts,
418  DynamicList<label>& pointToFace,
419  DynamicList<bool>& pointFromDiag,
420  EdgeMap<label>& vertsToPoint
421 ) const
422 {
423  const auto edgeFnd = vertsToPoint.cfind(vertices);
424  if (edgeFnd.found())
425  {
426  return edgeFnd.val();
427  }
428 
429  // Generate new point
430  label pointi = pointToVerts.size();
431 
432  pointToVerts.append(vertices);
433  pointToFace.append(facei);
434  pointFromDiag.append(edgeIsDiag);
435  vertsToPoint.insert(vertices, pointi);
436  return pointi;
437 }
438 
439 
440 void Foam::isoSurfaceTopo::generateTriPoints
441 (
442  const label facei,
443  const FixedList<scalar, 4>& s,
444  const FixedList<point, 4>& p,
445  const FixedList<label, 4>& pIndex,
446  const FixedList<bool, 6>& edgeIsDiag,// Per tet edge whether is face diag
447 
448  DynamicList<edge>& pointToVerts,
449  DynamicList<label>& pointToFace,
450  DynamicList<bool>& pointFromDiag,
451 
452  EdgeMap<label>& vertsToPoint,
453  DynamicList<label>& verts // Every three verts is new triangle
454 ) const
455 {
456  int triIndex = 0;
457  if (s[0] < iso_)
458  {
459  triIndex |= 1;
460  }
461  if (s[1] < iso_)
462  {
463  triIndex |= 2;
464  }
465  if (s[2] < iso_)
466  {
467  triIndex |= 4;
468  }
469  if (s[3] < iso_)
470  {
471  triIndex |= 8;
472  }
473 
474  // Form the vertices of the triangles for each case
475  switch (triIndex)
476  {
477  case 0x00:
478  case 0x0F:
479  break;
480 
481  case 0x01:
482  case 0x0E:
483  {
484  verts.append
485  (
486  generatePoint
487  (
488  facei,
489  edgeIsDiag[0],
490  edge(pIndex[0], pIndex[1]),
491  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
492  )
493  );
494  verts.append
495  (
496  generatePoint
497  (
498  facei,
499  edgeIsDiag[1],
500  edge(pIndex[0], pIndex[2]),
501  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
502  )
503  );
504  verts.append
505  (
506  generatePoint
507  (
508  facei,
509  edgeIsDiag[2],
510  edge(pIndex[0], pIndex[3]),
511  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
512  )
513  );
514 
515  if (triIndex == 0x0E)
516  {
517  // Flip normals
518  label sz = verts.size();
519  Swap(verts[sz-2], verts[sz-1]);
520  }
521  }
522  break;
523 
524  case 0x02:
525  case 0x0D:
526  {
527  verts.append
528  (
529  generatePoint
530  (
531  facei,
532  edgeIsDiag[0],
533  edge(pIndex[1], pIndex[0]),
534  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
535  )
536  );
537  verts.append
538  (
539  generatePoint
540  (
541  facei,
542  edgeIsDiag[3],
543  edge(pIndex[1], pIndex[3]),
544  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
545  )
546  );
547  verts.append
548  (
549  generatePoint
550  (
551  facei,
552  edgeIsDiag[4],
553  edge(pIndex[1], pIndex[2]),
554  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
555  )
556  );
557 
558  if (triIndex == 0x0D)
559  {
560  // Flip normals
561  label sz = verts.size();
562  Swap(verts[sz-2], verts[sz-1]);
563  }
564  }
565  break;
566 
567  case 0x03:
568  case 0x0C:
569  {
570  label p0p2
571  (
572  generatePoint
573  (
574  facei,
575  edgeIsDiag[1],
576  edge(pIndex[0], pIndex[2]),
577  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
578  )
579  );
580  label p1p3
581  (
582  generatePoint
583  (
584  facei,
585  edgeIsDiag[3],
586  edge(pIndex[1], pIndex[3]),
587  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
588  )
589  );
590 
591  verts.append
592  (
593  generatePoint
594  (
595  facei,
596  edgeIsDiag[2],
597  edge(pIndex[0], pIndex[3]),
598  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
599  )
600  );
601  verts.append(p1p3);
602  verts.append(p0p2);
603  verts.append(p1p3);
604  verts.append
605  (
606  generatePoint
607  (
608  facei,
609  edgeIsDiag[4],
610  edge(pIndex[1], pIndex[2]),
611  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
612  )
613  );
614  verts.append(p0p2);
615 
616  if (triIndex == 0x0C)
617  {
618  // Flip normals
619  label sz = verts.size();
620  Swap(verts[sz-5], verts[sz-4]);
621  Swap(verts[sz-2], verts[sz-1]);
622  }
623  }
624  break;
625 
626  case 0x04:
627  case 0x0B:
628  {
629  verts.append
630  (
631  generatePoint
632  (
633  facei,
634  edgeIsDiag[1],
635  edge(pIndex[2], pIndex[0]),
636  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
637  )
638  );
639  verts.append
640  (
641  generatePoint
642  (
643  facei,
644  edgeIsDiag[4],
645  edge(pIndex[2], pIndex[1]),
646  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
647  )
648  );
649  verts.append
650  (
651  generatePoint
652  (
653  facei,
654  edgeIsDiag[5],
655  edge(pIndex[2], pIndex[3]),
656  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
657  )
658  );
659 
660  if (triIndex == 0x0B)
661  {
662  // Flip normals
663  label sz = verts.size();
664  Swap(verts[sz-2], verts[sz-1]);
665  }
666  }
667  break;
668 
669  case 0x05:
670  case 0x0A:
671  {
672  label p0p1
673  (
674  generatePoint
675  (
676  facei,
677  edgeIsDiag[0],
678  edge(pIndex[0], pIndex[1]),
679  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
680  )
681  );
682  label p2p3
683  (
684  generatePoint
685  (
686  facei,
687  edgeIsDiag[5],
688  edge(pIndex[2], pIndex[3]),
689  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
690  )
691  );
692 
693  verts.append(p0p1);
694  verts.append(p2p3);
695  verts.append
696  (
697  generatePoint
698  (
699  facei,
700  edgeIsDiag[2],
701  edge(pIndex[0], pIndex[3]),
702  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
703  )
704  );
705  verts.append(p0p1);
706  verts.append
707  (
708  generatePoint
709  (
710  facei,
711  edgeIsDiag[4],
712  edge(pIndex[1], pIndex[2]),
713  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
714  )
715  );
716  verts.append(p2p3);
717 
718  if (triIndex == 0x0A)
719  {
720  // Flip normals
721  label sz = verts.size();
722  Swap(verts[sz-5], verts[sz-4]);
723  Swap(verts[sz-2], verts[sz-1]);
724  }
725  }
726  break;
727 
728  case 0x06:
729  case 0x09:
730  {
731  label p0p1
732  (
733  generatePoint
734  (
735  facei,
736  edgeIsDiag[0],
737  edge(pIndex[0], pIndex[1]),
738  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
739  )
740  );
741  label p2p3
742  (
743  generatePoint
744  (
745  facei,
746  edgeIsDiag[5],
747  edge(pIndex[2], pIndex[3]),
748  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
749  )
750  );
751 
752  verts.append(p0p1);
753  verts.append
754  (
755  generatePoint
756  (
757  facei,
758  edgeIsDiag[3],
759  edge(pIndex[1], pIndex[3]),
760  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
761  )
762  );
763  verts.append(p2p3);
764  verts.append(p0p1);
765  verts.append(p2p3);
766  verts.append
767  (
768  generatePoint
769  (
770  facei,
771  edgeIsDiag[1],
772  edge(pIndex[0], pIndex[2]),
773  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
774  )
775  );
776 
777  if (triIndex == 0x09)
778  {
779  // Flip normals
780  label sz = verts.size();
781  Swap(verts[sz-5], verts[sz-4]);
782  Swap(verts[sz-2], verts[sz-1]);
783  }
784  }
785  break;
786 
787  case 0x08:
788  case 0x07:
789  {
790  verts.append
791  (
792  generatePoint
793  (
794  facei,
795  edgeIsDiag[2],
796  edge(pIndex[3], pIndex[0]),
797  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
798  )
799  );
800  verts.append
801  (
802  generatePoint
803  (
804  facei,
805  edgeIsDiag[5],
806  edge(pIndex[3], pIndex[2]),
807  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
808  )
809  );
810  verts.append
811  (
812  generatePoint
813  (
814  facei,
815  edgeIsDiag[3],
816  edge(pIndex[3], pIndex[1]),
817  pointToVerts, pointToFace, pointFromDiag, vertsToPoint
818  )
819  );
820  if (triIndex == 0x07)
821  {
822  // Flip normals
823  label sz = verts.size();
824  Swap(verts[sz-2], verts[sz-1]);
825  }
826  }
827  break;
828  }
829 }
830 
831 
832 void Foam::isoSurfaceTopo::generateTriPoints
833 (
834  const label celli,
835  const bool isTet,
836 
837  DynamicList<edge>& pointToVerts,
838  DynamicList<label>& pointToFace,
839  DynamicList<bool>& pointFromDiag,
840 
841  EdgeMap<label>& vertsToPoint,
842  DynamicList<label>& verts,
843  DynamicList<label>& faceLabels
844 ) const
845 {
846  const faceList& faces = mesh_.faces();
847  const labelList& faceOwner = mesh_.faceOwner();
848  const pointField& points = mesh_.points();
849  const cell& cFaces = mesh_.cells()[celli];
850 
851  if (isTet)
852  {
853  // For tets don't do cell-centre decomposition, just use the
854  // tet points and values
855 
856  label facei = cFaces[0];
857  const face& f0 = faces[facei];
858 
859  // Get the other point from f1. Tbd: check if not duplicate face
860  // (ACMI / ignoreBoundaryFaces_).
861  const face& f1 = faces[cFaces[1]];
862  label oppositeI = -1;
863  forAll(f1, fp)
864  {
865  oppositeI = f1[fp];
866  if (!f0.found(oppositeI))
867  {
868  break;
869  }
870  }
871 
872 
873  label p0 = f0[0];
874  label p1 = f0[1];
875  label p2 = f0[2];
876  FixedList<bool, 6> edgeIsDiag(false);
877 
878  if (faceOwner[facei] == celli)
879  {
880  Swap(p1, p2);
881  }
882 
883  tetPointRef tet
884  (
885  points[p0],
886  points[p1],
887  points[p2],
888  points[oppositeI]
889  );
890 
891  label startTrii = verts.size();
892  generateTriPoints
893  (
894  facei,
895  FixedList<scalar, 4>
896  ({
897  pVals_[p0],
898  pVals_[p1],
899  pVals_[p2],
900  pVals_[oppositeI]
901  }),
902  FixedList<point, 4>
903  ({
904  points[p0],
905  points[p1],
906  points[p2],
907  points[oppositeI]
908  }),
909  FixedList<label, 4>
910  ({
911  p0,
912  p1,
913  p2,
914  oppositeI
915  }),
916  edgeIsDiag,
917 
918  pointToVerts,
919  pointToFace,
920  pointFromDiag,
921  vertsToPoint,
922  verts // Every three verts is new triangle
923  );
924 
925  label nTris = (verts.size()-startTrii)/3;
926  for (label i = 0; i < nTris; ++i)
927  {
928  faceLabels.append(facei);
929  }
930  }
931  else
932  {
933  const pointField& cellCentres = mesh_.cellCentres();
934 
935  for (const label facei : cFaces)
936  {
937  if
938  (
939  !mesh_.isInternalFace(facei)
940  && ignoreBoundaryFaces_.test(facei-mesh_.nInternalFaces())
941  )
942  {
943  continue;
944  }
945 
946  const face& f = faces[facei];
947 
948  label fp0 = tetBasePtIs_[facei];
949 
950  label startTrii = verts.size();
951 
952  // Fallback
953  if (fp0 < 0)
954  {
955  fp0 = 0;
956  }
957 
958  label fp = f.fcIndex(fp0);
959  for (label i = 2; i < f.size(); ++i)
960  {
961  label nextFp = f.fcIndex(fp);
962 
963  FixedList<bool, 6> edgeIsDiag(false);
964 
965  label p0 = f[fp0];
966  label p1 = f[fp];
967  label p2 = f[nextFp];
968  if (faceOwner[facei] == celli)
969  {
970  Swap(p1, p2);
971  if (i != 2) edgeIsDiag[1] = true;
972  if (i != f.size()-1) edgeIsDiag[0] = true;
973  }
974  else
975  {
976  if (i != 2) edgeIsDiag[0] = true;
977  if (i != f.size()-1) edgeIsDiag[1] = true;
978  }
979 
980  tetPointRef tet
981  (
982  points[p0],
983  points[p1],
984  points[p2],
985  cellCentres[celli]
986  );
987 
988  generateTriPoints
989  (
990  facei,
991  FixedList<scalar, 4>
992  ({
993  pVals_[p0],
994  pVals_[p1],
995  pVals_[p2],
996  cVals_[celli]
997  }),
998  FixedList<point, 4>
999  ({
1000  points[p0],
1001  points[p1],
1002  points[p2],
1003  cellCentres[celli]
1004  }),
1005  FixedList<label, 4>
1006  ({
1007  p0,
1008  p1,
1009  p2,
1010  mesh_.nPoints()+celli
1011  }),
1012  edgeIsDiag,
1013 
1014  pointToVerts,
1015  pointToFace,
1016  pointFromDiag,
1017  vertsToPoint,
1018  verts // Every three verts is new triangle
1019  );
1020 
1021  fp = nextFp;
1022  }
1023 
1024  label nTris = (verts.size()-startTrii)/3;
1025  for (label i = 0; i < nTris; ++i)
1026  {
1027  faceLabels.append(facei);
1028  }
1029  }
1030  }
1031 }
1032 
1033 
1034 void Foam::isoSurfaceTopo::triangulateOutside
1035 (
1036  const bool filterDiag,
1037  const primitivePatch& pp,
1038  const boolList& pointFromDiag,
1039  const labelList& pointToFace,
1040  const label cellID,
1041 
1042  DynamicList<face>& compactFaces,
1043  DynamicList<label>& compactCellIDs
1044 ) const
1045 {
1046  // We can form pockets:
1047  // - 1. triangle on face
1048  // - 2. multiple triangles on interior (from diag edges)
1049  // - the edge loop will be pocket since it is only the diag
1050  // edges that give it volume?
1051 
1052  // Retriangulate the exterior loops
1053  const labelListList& edgeLoops = pp.edgeLoops();
1054  const labelList& mp = pp.meshPoints();
1055 
1056  for (const labelList& loop : edgeLoops)
1057  {
1058  if (loop.size() > 2)
1059  {
1060  compactFaces.append(face(0));
1061  face& f = compactFaces.last();
1062 
1063  f.setSize(loop.size());
1064  label fpi = 0;
1065  forAll(f, i)
1066  {
1067  label pointi = mp[loop[i]];
1068  if (filterDiag && pointFromDiag[pointi])
1069  {
1070  label prevPointi = mp[loop[loop.fcIndex(i)]];
1071  if
1072  (
1073  pointFromDiag[prevPointi]
1074  && (pointToFace[pointi] != pointToFace[prevPointi])
1075  )
1076  {
1077  f[fpi++] = pointi;
1078  }
1079  else
1080  {
1081  // Filter out diagonal point
1082  }
1083  }
1084  else
1085  {
1086  f[fpi++] = pointi;
1087  }
1088  }
1089 
1090  if (fpi > 2)
1091  {
1092  f.setSize(fpi);
1093  }
1094  else
1095  {
1096  // Keep original face
1097  forAll(f, i)
1098  {
1099  label pointi = mp[loop[i]];
1100  f[i] = pointi;
1101  }
1102  }
1103  compactCellIDs.append(cellID);
1104  }
1105  }
1106 }
1107 
1108 
1109 Foam::MeshedSurface<Foam::face> Foam::isoSurfaceTopo::removeInsidePoints
1110 (
1111  const bool filterDiag,
1112  const MeshStorage& s,
1113  const boolList& pointFromDiag,
1114  const labelList& pointToFace,
1115  const labelList& start, // Per cell the starting triangle
1116  DynamicList<label>& pointCompactMap, // Per returned point the original
1117  DynamicList<label>& compactCellIDs // Per returned tri the cellID
1118 ) const
1119 {
1120  const pointField& points = s.points();
1121 
1122  pointCompactMap.clear();
1123  compactCellIDs.clear();
1124 
1125  DynamicList<face> compactFaces(s.size()/8);
1126 
1127  for (label celli = 0; celli < start.size()-1; ++celli)
1128  {
1129  // All triangles of the current cell
1130 
1131  label nTris = start[celli+1]-start[celli];
1132 
1133  if (nTris)
1134  {
1135  const SubList<face> cellFaces(s, nTris, start[celli]);
1136  const primitivePatch pp(cellFaces, points);
1137 
1138  triangulateOutside
1139  (
1140  filterDiag,
1141  pp,
1142  pointFromDiag,
1143  pointToFace,
1144  //protectedFace,
1145  celli,
1146 
1147  compactFaces,
1148  compactCellIDs
1149  );
1150  }
1151  }
1152 
1153 
1154  // Compact out unused points
1155  // Pick up the used vertices
1156  labelList oldToCompact(points.size(), -1);
1157  DynamicField<point> compactPoints(points.size());
1158  pointCompactMap.clear();
1159 
1160  for (face& f : compactFaces)
1161  {
1162  forAll(f, fp)
1163  {
1164  label pointi = f[fp];
1165  label compacti = oldToCompact[pointi];
1166  if (compacti == -1)
1167  {
1168  compacti = compactPoints.size();
1169  oldToCompact[pointi] = compacti;
1170  compactPoints.append(points[pointi]);
1171  pointCompactMap.append(pointi);
1172  }
1173  f[fp] = compacti;
1174  }
1175  }
1176 
1177 
1178  MeshStorage cpSurface
1179  (
1180  std::move(compactPoints),
1181  std::move(compactFaces),
1182  s.surfZones()
1183  );
1184 
1185  return cpSurface;
1186 }
1187 
1188 
1189 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1190 
1193  const polyMesh& mesh,
1194  const scalarField& cVals,
1195  const scalarField& pVals,
1196  const scalar iso,
1197  const filterType filter,
1198  const boundBox& bounds,
1199  const bitSet& ignoreCells
1200 )
1201 :
1202  isoSurfaceBase(iso, bounds),
1203  mesh_(mesh),
1204  cVals_(cVals),
1205  pVals_(pVals),
1206  ignoreCells_(ignoreCells)
1207 {
1208  if (debug)
1209  {
1210  Pout<< "isoSurfaceTopo::"
1211  << " cell min/max : "
1212  << min(cVals_) << " / "
1213  << max(cVals_) << nl
1214  << " point min/max : "
1215  << min(pVals_) << " / "
1216  << max(pVals_) << nl
1217  << " isoValue : " << iso << nl
1218  << " filter : " << isoSurfaceTopo::filterNames[filter]
1219  << nl
1220  << " mesh span : " << mesh.bounds().mag() << nl
1221  << " ignoreCells : " << ignoreCells_.count()
1222  << " / " << cVals_.size() << nl
1223  << endl;
1224  }
1225 
1226  // Determine boundary pyramids to ignore (since originating from ACMI faces)
1227  // Maybe needs to be optional argument or more general detect colocated
1228  // faces.
1229  {
1230  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
1231  forAll(pbm, patchi)
1232  {
1233  const polyPatch& pp = pbm[patchi];
1234  if (isA<cyclicACMIPolyPatch>(pp))
1235  {
1236  ignoreBoundaryFaces_.setSize(mesh_.nBoundaryFaces());
1237  forAll(pp, i)
1238  {
1239  label facei = pp.start()+i;
1240  ignoreBoundaryFaces_.set(facei-mesh_.nInternalFaces());
1241  }
1242  }
1243  }
1244  }
1245 
1246 
1247  fixTetBasePtIs();
1248 
1249  tetMatcher tet;
1250 
1251  // Determine if any cut through cell
1252  List<cellCutType> cellCutTypes;
1253  const label nCutCells = calcCutTypes(tet, cellCutTypes);
1254 
1255  // Per cell: 5 pyramids cut, each generating 2 triangles
1256  // - pointToVerts : from generated iso point to originating mesh verts
1257  DynamicList<edge> pointToVerts(10*nCutCells);
1258  // - pointToFace : from generated iso point to originating mesh face
1259  DynamicList<label> pointToFace(10*nCutCells);
1260  // - pointToFace : from generated iso point whether is on face diagonal
1261  DynamicList<bool> pointFromDiag(10*nCutCells);
1262 
1263  // Per cell: number of intersected edges:
1264  // - four faces cut so 4 mesh edges + 4 face-diagonal edges
1265  // - 4 of the pyramid edges
1266  EdgeMap<label> vertsToPoint(12*nCutCells);
1267  DynamicList<label> verts(12*nCutCells);
1268  // Per cell: 5 pyramids cut (since only one pyramid not cut)
1269  DynamicList<label> faceLabels(5*nCutCells);
1270  DynamicList<label> cellLabels(5*nCutCells);
1271 
1272 
1273  labelList startTri(mesh_.nCells()+1, Zero);
1274 
1275  for (label celli = 0; celli < mesh_.nCells(); ++celli)
1276  {
1277  startTri[celli] = faceLabels.size();
1278  if (cellCutTypes[celli] != NOTCUT)
1279  {
1280  generateTriPoints
1281  (
1282  celli,
1283  tet.isA(mesh_, celli),
1284 
1285  pointToVerts,
1286  pointToFace,
1287  pointFromDiag,
1288 
1289  vertsToPoint,
1290  verts,
1291  faceLabels
1292  );
1293 
1294  for (label i = startTri[celli]; i < faceLabels.size(); ++i)
1295  {
1296  cellLabels.append(celli);
1297  }
1298  }
1299  }
1300  startTri[mesh_.nCells()] = faceLabels.size();
1301 
1302 
1303  pointToVerts_.transfer(pointToVerts);
1304  meshCells_.transfer(cellLabels);
1305  pointToFace_.transfer(pointToFace);
1306 
1308  (
1309  interpolate
1310  (
1311  mesh_.cellCentres(),
1312  mesh_.points()
1313  )
1314  );
1315 
1316 
1317  // Assign to MeshedSurface
1318  faceList allTris(faceLabels.size());
1319  label verti = 0;
1320  for (face& allTri : allTris)
1321  {
1322  allTri.setSize(3);
1323  allTri[0] = verts[verti++];
1324  allTri[1] = verts[verti++];
1325  allTri[2] = verts[verti++];
1326  }
1327 
1328 
1329  surfZoneList allZones(one(), surfZone("allFaces", allTris.size()));
1330 
1332  MeshStorage updated
1333  (
1334  std::move(allPoints),
1335  std::move(allTris),
1336  std::move(allZones)
1337  );
1338  MeshStorage::transfer(updated);
1339 
1340  // Now:
1341  // - generated faces and points are assigned to *this
1342  // - per point we know:
1343  // - pointOnDiag: whether it is on a face-diagonal edge
1344  // - pointToFace_: from what pyramid (cell+face) it was produced
1345  // (note that the pyramid faces are shared between multiple mesh faces)
1346  // - pointToVerts_ : originating mesh vertex or cell centre
1347 
1348 
1349  if (debug)
1350  {
1351  Pout<< "isoSurfaceTopo : generated " << size() << " faces." << endl;
1352  }
1353 
1354 
1355  if (filter != filterType::NONE)
1356  {
1357  // Triangulate outside (filter edges to cell centres and optionally
1358  // face diagonals)
1359  DynamicList<label> pointCompactMap(size()); // Back to original point
1360  DynamicList<label> compactCellIDs(size()); // Per tri the cell
1361  MeshStorage::operator=
1362  (
1363  removeInsidePoints
1364  (
1365  (filter == filterType::DIAGCELL ? true : false),
1366  *this,
1367  pointFromDiag,
1368  pointToFace_,
1369  startTri,
1370  pointCompactMap,
1371  compactCellIDs
1372  )
1373  );
1374 
1375  pointToVerts_ = UIndirectList<edge>(pointToVerts_, pointCompactMap)();
1376  pointToFace_ = UIndirectList<label>(pointToFace_, pointCompactMap)();
1377  pointFromDiag = UIndirectList<bool>(pointFromDiag, pointCompactMap)();
1378  meshCells_.transfer(compactCellIDs);
1379 
1380  if (debug)
1381  {
1382  Pout<< "isoSurfaceTopo :"
1383  << " after removing cell centre and face-diag triangles : "
1384  << size() << endl;
1385  }
1386 
1387 
1388  if (filter == filterType::DIAGCELL)
1389  {
1390  // We remove verts on face diagonals. This is in fact just
1391  // straightening the edges of the face through the cell. This can
1392  // close off 'pockets' of triangles and create open or
1393  // multiply-connected triangles
1394 
1395  // Solved by eroding open-edges
1396  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1397 
1398  // Mark points on mesh outside. Note that we extend with nCells
1399  // so we can easily index with pointToVerts_.
1400  bitSet isBoundaryPoint(mesh.nPoints() + mesh.nCells());
1401  for
1402  (
1403  label facei = mesh.nInternalFaces();
1404  facei < mesh.nFaces();
1405  ++facei
1406  )
1407  {
1408  isBoundaryPoint.set(mesh.faces()[facei]);
1409  }
1410 
1411 
1412  // Include faces that would be exposed from mesh subset
1413  if (!ignoreCells_.empty())
1414  {
1415  const labelList& faceOwner = mesh_.faceOwner();
1416  const labelList& faceNeighbour = mesh_.faceNeighbour();
1417 
1418  label nMore = 0;
1419  for
1420  (
1421  label facei = 0;
1422  facei < mesh.nInternalFaces();
1423  ++facei
1424  )
1425  {
1426  int n = 0;
1427  if (ignoreCells_.test(faceOwner[facei])) ++n;
1428  if (ignoreCells_.test(faceNeighbour[facei])) ++n;
1429 
1430  // Only one of the cells is being ignored.
1431  // That means it is an exposed subMesh face.
1432  if (n == 1)
1433  {
1434  isBoundaryPoint.set(mesh.faces()[facei]);
1435 
1436  ++nMore;
1437  }
1438  }
1439  }
1440 
1441 
1443 
1444  while (true)
1445  {
1446  faceSelection.clear();
1447  faceSelection.resize(this->size());
1448 
1449  const labelList& mp = meshPoints();
1450 
1451  const labelListList& edgeFaces = MeshStorage::edgeFaces();
1452 
1453  forAll(edgeFaces, edgei)
1454  {
1455  const labelList& eFaces = edgeFaces[edgei];
1456  if (eFaces.size() == 1)
1457  {
1458  // Open edge. Check that vertices do not originate
1459  // from a boundary face
1460  const edge& e = edges()[edgei];
1461  const edge& verts0 = pointToVerts_[mp[e[0]]];
1462  const edge& verts1 = pointToVerts_[mp[e[1]]];
1463  if
1464  (
1465  isBoundaryPoint[verts0[0]]
1466  && isBoundaryPoint[verts0[1]]
1467  && isBoundaryPoint[verts1[0]]
1468  && isBoundaryPoint[verts1[1]]
1469  )
1470  {
1471  // Open edge on boundary face. Keep
1472  }
1473  else
1474  {
1475  // Open edge. Mark for erosion
1476  faceSelection.set(eFaces[0]);
1477  }
1478  }
1479  }
1480 
1481  if (debug)
1482  {
1483  Pout<< "isoSurfaceTopo :"
1484  << " removing " << faceSelection.count()
1485  << " faces since on open edges" << endl;
1486  }
1487 
1488  if (returnReduce(faceSelection.none(), andOp<bool>()))
1489  {
1490  break;
1491  }
1492 
1493 
1494  // Flip from remove face -> keep face
1495  faceSelection.flip();
1496 
1497  labelList pointMap;
1499  MeshStorage filteredSurf
1500  (
1501  MeshStorage::subsetMesh
1502  (
1503  faceSelection,
1504  pointMap,
1505  faceMap
1506  )
1507  );
1508  MeshStorage::transfer(filteredSurf);
1509 
1510  pointToVerts_ = UIndirectList<edge>(pointToVerts_, pointMap)();
1511  pointToFace_ = UIndirectList<label>(pointToFace_, pointMap)();
1512  pointFromDiag = UIndirectList<bool>(pointFromDiag, pointMap)();
1513  meshCells_ = UIndirectList<label>(meshCells_, faceMap)();
1514  }
1515  }
1516  }
1517 }
1518 
1519 
1520 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
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::constant::atomic::mp
const dimensionedScalar mp
Proton mass.
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::boundBox::mag
scalar mag() const
The magnitude of the bounding box span.
Definition: boundBoxI.H:133
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeFast.C:94
cyclicACMIPolyPatch.H
Foam::isoSurfaceBase
Low-level components common to various iso-surface algorithms.
Definition: isoSurfaceBase.H:54
isoSurfaceTopo.H
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
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::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::primitiveMesh::cellPoints
const labelListList & cellPoints() const
Definition: primitiveMeshCellPoints.C:34
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:57
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::primitiveMesh::nFaces
label nFaces() const
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::tetMatcher
A cellMatcher for tet cells (cellModel::TET)
Definition: tetMatcher.H:53
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:563
Foam::one
A class representing the concept of 1 (one), which can be used to avoid manipulating objects that are...
Definition: one.H:60
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:72
tetPointRef.H
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:182
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::isoSurfaceBase::filterNames
static const Enum< filterType > filterNames
Names for the filtering types.
Definition: isoSurfaceBase.H:103
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:512
polyMesh.H
Foam::Swap
void Swap(DynamicList< T, SizeMin1 > &a, DynamicList< T, SizeMin2 > &b)
Definition: DynamicListI.H:909
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::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
polyMeshTetDecomposition.H
Foam::faceSelection
Face selection method for createBaffles.
Definition: faceSelection.H:58
Foam::tetPointRef
tetrahedron< point, const point & > tetPointRef
Definition: tetPointRef.H:46
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::isoSurfaceTopo::isoSurfaceTopo
isoSurfaceTopo(const polyMesh &mesh, const scalarField &cellValues, const scalarField &pointValues, const scalar iso, const filterType filter=filterType::DIAGCELL, const boundBox &bounds=boundBox::invertedBox, const bitSet &ignoreCells=bitSet())
Construct from dictionary.
Definition: isoSurfaceTopo.C:1192
Foam::syncTools::syncFaceList
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:390
Foam::primitiveMesh::nCells
label nCells() const
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::interpolate
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
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
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
Foam::PtrList::setSize
void setSize(const label newLen)
Same as resize()
Definition: PtrListI.H:108
Foam::andOp
Definition: ops.H:233
Foam::isoSurfaceBase::iso_
const scalar iso_
Iso value.
Definition: isoSurfaceBase.H:66
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
Foam::vertices
pointField vertices(const blockVertexList &bvl)
Definition: blockVertexList.H:49
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:311
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::polyMesh::bounds
const boundBox & bounds() const
Return mesh bounding box.
Definition: polyMesh.H:441
isoSurface.H
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::EdgeMap< label >
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1063
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:355
DynamicField.H
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:372
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::tetMatcher::isA
virtual bool isA(const primitiveMesh &mesh, const label celli)
Exact match. Uses faceSizeMatch.
Definition: tetMatcher.C:213
Foam::List< cellCutType >
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:65
Foam::primitiveMesh::isInternalFace
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
Definition: primitiveMeshI.H:102
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
Foam::pointToFace
A topoSetFaceSource to select faces based on use of points.
Definition: pointToFace.H:83
Foam::DynamicList::transfer
void transfer(List< T > &lst)
Transfer contents of the argument List into this.
Definition: DynamicListI.H:426
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::primitiveMesh::nPoints
label nPoints() const
Number of mesh points.
Definition: primitiveMeshI.H:37
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
tetMatcher.H
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:109
Foam::primitivePatch
PrimitivePatch< face, SubList, const pointField & > primitivePatch
Addressing for a faceList slice.
Definition: primitivePatch.H:47
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::MeshedSurface< Foam::face >
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::polyMeshTetDecomposition::minQuality
static scalar minQuality(const polyMesh &mesh, const point &cC, const label fI, const bool isOwner, const label faceBasePtI)
Given a face and cc and starting index for triangulation determine.
Definition: polyMeshTetDecomposition.C:42
Foam::isoSurfaceBase::filterType
filterType
The filtering (regularization) to apply.
Definition: isoSurfaceBase.H:87