cellCuts.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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "cellCuts.H"
27 #include "polyMesh.H"
28 #include "Time.H"
29 #include "ListOps.H"
30 #include "cellLooper.H"
31 #include "refineCell.H"
32 #include "meshTools.H"
33 #include "geomCellLooper.H"
34 #include "OFstream.H"
35 #include "plane.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 defineTypeNameAndDebug(cellCuts, 0);
42 }
43 
44 
45 // * * * * * * * * * * * * * Private Static Functions * * * * * * * * * * * //
46 
47 // Find val in first nElems elements of list.
49 (
50  const labelList& elems,
51  const label nElems,
52  const label val
53 )
54 {
55  for (label i = 0; i < nElems; i++)
56  {
57  if (elems[i] == val)
58  {
59  return i;
60  }
61  }
62  return -1;
63 }
64 
65 
67 (
68  const label size,
69  const labelList& labels
70 )
71 {
72  boolList result(size, false);
73 
74  forAll(labels, labelI)
75  {
76  result[labels[labelI]] = true;
77  }
78  return result;
79 }
80 
81 
83 (
84  const label size,
85  const labelList& labels,
86  const scalarField& weights
87 )
88 {
89  scalarField result(size, -GREAT);
90 
91  forAll(labels, labelI)
92  {
93  result[labels[labelI]] = weights[labelI];
94  }
95  return result;
96 }
97 
98 
99 // Find first point in lst not in map.
101 (
102  const labelList& lst,
103  const Map<label>& map
104 )
105 {
106  forAll(lst, i)
107  {
108  if (!map.found(lst[i]))
109  {
110  return i;
111  }
112  }
113  return -1;
114 }
115 
116 
117 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
118 
119 // Write cell and raw cuts on any of the elements
121 (
122  const fileName& dir,
123  const label cellI
124 ) const
125 {
126  //- Cell edges
127  OFstream cutsStream(dir / "cell_" + name(cellI) + ".obj");
128 
129  Pout<< "Writing cell for time " << mesh().time().timeName()
130  << " to " << cutsStream.name() << nl;
131 
133  (
134  cutsStream,
135  mesh().cells(),
136  mesh().faces(),
137  mesh().points(),
138  labelList(1, cellI)
139  );
140 
141  //- Loop cutting cell in two
142  OFstream cutStream(dir / "cellCuts_" + name(cellI) + ".obj");
143 
144  Pout<< "Writing raw cuts on cell for time " << mesh().time().timeName()
145  << " to " << cutStream.name() << nl;
146 
147  const labelList& cPoints = mesh().cellPoints()[cellI];
148 
149  forAll(cPoints, i)
150  {
151  label pointI = cPoints[i];
152  if (pointIsCut_[pointI])
153  {
154  meshTools::writeOBJ(cutStream, mesh().points()[pointI]);
155  }
156  }
157 
158  const pointField& pts = mesh().points();
159 
160  const labelList& cEdges = mesh().cellEdges()[cellI];
161 
162  forAll(cEdges, i)
163  {
164  label edgeI = cEdges[i];
165 
166  if (edgeIsCut_[edgeI])
167  {
168  const edge& e = mesh().edges()[edgeI];
169 
170  const scalar w = edgeWeight_[edgeI];
171 
172  meshTools::writeOBJ(cutStream, w*pts[e[1]] + (1-w)*pts[e[0]]);
173  }
174  }
175 }
176 
177 
179 (
180  const fileName& dir,
181  const label cellI,
182  const pointField& loopPoints,
183  const labelList& anchors
184 ) const
185 {
186  //- Cell edges
187  OFstream cutsStream(dir / "cell_" + name(cellI) + ".obj");
188 
189  Pout<< "Writing cell for time " << mesh().time().timeName()
190  << " to " << cutsStream.name() << nl;
191 
193  (
194  cutsStream,
195  mesh().cells(),
196  mesh().faces(),
197  mesh().points(),
198  labelList(1, cellI)
199  );
200 
201 
202  //- Loop cutting cell in two
203  OFstream loopStream(dir / "cellLoop_" + name(cellI) + ".obj");
204 
205  Pout<< "Writing loop for time " << mesh().time().timeName()
206  << " to " << loopStream.name() << nl;
207 
208  label vertI = 0;
209 
210  writeOBJ(loopStream, loopPoints, vertI);
211 
212 
213  //- Anchors for cell
214  OFstream anchorStream(dir / "anchors_" + name(cellI) + ".obj");
215 
216  Pout<< "Writing anchors for time " << mesh().time().timeName()
217  << " to " << anchorStream.name() << endl;
218 
219  forAll(anchors, i)
220  {
221  meshTools::writeOBJ(anchorStream, mesh().points()[anchors[i]]);
222  }
223 }
224 
225 
226 // Find face on cell using the two edges.
228 (
229  const label cellI,
230  const label edgeA,
231  const label edgeB
232 ) const
233 {
234  const labelList& cFaces = mesh().cells()[cellI];
235 
236  forAll(cFaces, cFaceI)
237  {
238  label faceI = cFaces[cFaceI];
239 
240  const labelList& fEdges = mesh().faceEdges()[faceI];
241 
242  if
243  (
244  findIndex(fEdges, edgeA) != -1
245  && findIndex(fEdges, edgeB) != -1
246  )
247  {
248  return faceI;
249  }
250  }
251 
252  // Coming here means the loop is illegal since the two edges
253  // are not shared by a face. We just mark loop as invalid and continue.
254 
256  << "cellCuts : Cannot find face on cell "
257  << cellI << " that has both edges " << edgeA << ' ' << edgeB << endl
258  << "faces : " << cFaces << endl
259  << "edgeA : " << mesh().edges()[edgeA] << endl
260  << "edgeB : " << mesh().edges()[edgeB] << endl
261  << "Marking the loop across this cell as invalid" << endl;
262 
263  return -1;
264 }
265 
266 
267 // Find face on cell using an edge and a vertex.
269 (
270  const label cellI,
271  const label edgeI,
272  const label vertI
273 ) const
274 {
275  const labelList& cFaces = mesh().cells()[cellI];
276 
277  forAll(cFaces, cFaceI)
278  {
279  label faceI = cFaces[cFaceI];
280 
281  const face& f = mesh().faces()[faceI];
282 
283  const labelList& fEdges = mesh().faceEdges()[faceI];
284 
285  if
286  (
287  findIndex(fEdges, edgeI) != -1
288  && findIndex(f, vertI) != -1
289  )
290  {
291  return faceI;
292  }
293  }
294 
296  << "cellCuts : Cannot find face on cell "
297  << cellI << " that has both edge " << edgeI << " and vertex "
298  << vertI << endl
299  << "faces : " << cFaces << endl
300  << "edge : " << mesh().edges()[edgeI] << endl
301  << "Marking the loop across this cell as invalid" << endl;
302 
303  return -1;
304 }
305 
306 
307 // Find face using two vertices (guaranteed not to be along edge)
309 (
310  const label cellI,
311  const label vertA,
312  const label vertB
313 ) const
314 {
315  const labelList& cFaces = mesh().cells()[cellI];
316 
317  forAll(cFaces, cFaceI)
318  {
319  label faceI = cFaces[cFaceI];
320 
321  const face& f = mesh().faces()[faceI];
322 
323  if
324  (
325  findIndex(f, vertA) != -1
326  && findIndex(f, vertB) != -1
327  )
328  {
329  return faceI;
330  }
331  }
332 
334  << "cellCuts : Cannot find face on cell "
335  << cellI << " that has vertex " << vertA << " and vertex "
336  << vertB << endl
337  << "faces : " << cFaces << endl
338  << "Marking the loop across this cell as invalid" << endl;
339 
340  return -1;
341 }
342 
343 
345 {
346  if (faceCutsPtr_)
347  {
349  << "faceCuts already calculated" << abort(FatalError);
350  }
351 
352  const faceList& faces = mesh().faces();
353 
354 
355  faceCutsPtr_ = new labelListList(mesh().nFaces());
357 
358  for (label faceI = 0; faceI < mesh().nFaces(); faceI++)
359  {
360  const face& f = faces[faceI];
361 
362  // Big enough storage (possibly all points and all edges cut). Shrink
363  // later on.
364  labelList& cuts = faceCuts[faceI];
365 
366  cuts.setSize(2*f.size());
367 
368  label cutI = 0;
369 
370  // Do point-edge-point walk over face and collect all cuts.
371  // Problem is that we want to start from one of the endpoints of a
372  // string of connected cuts; we don't want to start somewhere in the
373  // middle.
374 
375  // Pass1: find first point cut not preceeded by a cut.
376  label startFp = -1;
377 
378  forAll(f, fp)
379  {
380  label v0 = f[fp];
381 
382  if (pointIsCut_[v0])
383  {
384  label vMin1 = f[f.rcIndex(fp)];
385 
386  if
387  (
388  !pointIsCut_[vMin1]
389  && !edgeIsCut_[findEdge(faceI, v0, vMin1)]
390  )
391  {
392  cuts[cutI++] = vertToEVert(v0);
393  startFp = f.fcIndex(fp);
394  break;
395  }
396  }
397  }
398 
399  // Pass2: first edge cut not preceeded by point cut
400  if (startFp == -1)
401  {
402  forAll(f, fp)
403  {
404  label fp1 = f.fcIndex(fp);
405 
406  label v0 = f[fp];
407  label v1 = f[fp1];
408 
409  label edgeI = findEdge(faceI, v0, v1);
410 
411  if (edgeIsCut_[edgeI] && !pointIsCut_[v0])
412  {
413  cuts[cutI++] = edgeToEVert(edgeI);
414  startFp = fp1;
415  break;
416  }
417  }
418  }
419 
420  // Pass3: nothing found so far. Either face is not cut at all or all
421  // vertices are cut. Start from 0.
422  if (startFp == -1)
423  {
424  startFp = 0;
425  }
426 
427  // Store all cuts starting from startFp;
428  label fp = startFp;
429 
430  bool allVerticesCut = true;
431 
432  forAll(f, i)
433  {
434  label fp1 = f.fcIndex(fp);
435 
436  // Get the three items: current vertex, next vertex and edge
437  // inbetween
438  label v0 = f[fp];
439  label v1 = f[fp1];
440  label edgeI = findEdge(faceI, v0, v1);
441 
442  if (pointIsCut_[v0])
443  {
444  cuts[cutI++] = vertToEVert(v0);
445  }
446  else
447  {
448  // For check if all vertices have been cut (= illegal)
449  allVerticesCut = false;
450  }
451 
452  if (edgeIsCut_[edgeI])
453  {
454  cuts[cutI++] = edgeToEVert(edgeI);
455  }
456 
457  fp = fp1;
458  }
459 
460 
461  if (allVerticesCut)
462  {
464  << "Face " << faceI << " vertices " << f
465  << " has all its vertices cut. Not cutting face." << endl;
466 
467  cutI = 0;
468  }
469 
470  // Remove duplicate starting point
471  if (cutI > 1 && cuts[cutI-1] == cuts[0])
472  {
473  cutI--;
474  }
475  cuts.setSize(cutI);
476  }
477 }
478 
479 
480 // Find edge on face using two vertices
482 (
483  const label faceI,
484  const label v0,
485  const label v1
486 ) const
487 {
488  const edgeList& edges = mesh().edges();
489 
490  const labelList& fEdges = mesh().faceEdges()[faceI];
491 
492  forAll(fEdges, i)
493  {
494  const edge& e = edges[fEdges[i]];
495 
496  if
497  (
498  (e[0] == v0 && e[1] == v1)
499  || (e[0] == v1 && e[1] == v0)
500  )
501  {
502  return fEdges[i];
503  }
504  }
505 
506  return -1;
507 }
508 
509 
510 // Check if there is a face on the cell on which all cuts are.
512 (
513  const label cellI,
514  const labelList& loop
515 ) const
516 {
517  const cell& cFaces = mesh().cells()[cellI];
518 
519  forAll(cFaces, cFaceI)
520  {
521  label faceI = cFaces[cFaceI];
522 
523  const labelList& fEdges = mesh().faceEdges()[faceI];
524  const face& f = mesh().faces()[faceI];
525 
526  bool allOnFace = true;
527 
528  forAll(loop, i)
529  {
530  label cut = loop[i];
531 
532  if (isEdge(cut))
533  {
534  if (findIndex(fEdges, getEdge(cut)) == -1)
535  {
536  // Edge not on face. Skip face.
537  allOnFace = false;
538  break;
539  }
540  }
541  else
542  {
543  if (findIndex(f, getVertex(cut)) == -1)
544  {
545  // Vertex not on face. Skip face.
546  allOnFace = false;
547  break;
548  }
549  }
550  }
551 
552  if (allOnFace)
553  {
554  // Found face where all elements of loop are on the face.
555  return faceI;
556  }
557  }
558  return -1;
559 }
560 
561 
562 // From point go into connected face
564 (
565  const label cellI,
566  const label startCut,
567 
568  const label exclude0,
569  const label exclude1,
570 
571  const label otherCut,
572 
573  label& nVisited,
574  labelList& visited
575 ) const
576 {
577  label vertI = getVertex(otherCut);
578 
579  const labelList& pFaces = mesh().pointFaces()[vertI];
580 
581  forAll(pFaces, pFaceI)
582  {
583  label otherFaceI = pFaces[pFaceI];
584 
585  if
586  (
587  otherFaceI != exclude0
588  && otherFaceI != exclude1
589  && meshTools::faceOnCell(mesh(), cellI, otherFaceI)
590  )
591  {
592  label oldNVisited = nVisited;
593 
594  bool foundLoop =
595  walkCell
596  (
597  cellI,
598  startCut,
599  otherFaceI,
600  otherCut,
601  nVisited,
602  visited
603  );
604 
605  if (foundLoop)
606  {
607  return true;
608  }
609 
610  // No success. Restore state and continue
611  nVisited = oldNVisited;
612  }
613  }
614  return false;
615 }
616 
617 
618 // Cross cut (which is edge on faceI) onto next face
620 (
621  const label cellI,
622  const label startCut,
623  const label faceI,
624  const label otherCut,
625 
626  label& nVisited,
627  labelList& visited
628 ) const
629 {
630  // Cross edge to other face
631  label edgeI = getEdge(otherCut);
632 
633  label otherFaceI = meshTools::otherFace(mesh(), cellI, faceI, edgeI);
634 
635  // Store old state
636  label oldNVisited = nVisited;
637 
638  // Recurse to otherCut
639  bool foundLoop =
640  walkCell
641  (
642  cellI,
643  startCut,
644  otherFaceI,
645  otherCut,
646  nVisited,
647  visited
648  );
649 
650  if (foundLoop)
651  {
652  return true;
653  }
654  else
655  {
656  // No success. Restore state (i.e. backtrack)
657  nVisited = oldNVisited;
658 
659  return false;
660  }
661 }
662 
663 
665 (
666  const label cellI,
667  const label cut,
668  label& nVisited,
669  labelList& visited
670 ) const
671 {
672  // Check for duplicate cuts.
673  if (findPartIndex(visited, nVisited, cut) != -1)
674  {
675  // Truncate (copy of) visited for ease of printing.
676  labelList truncVisited(visited);
677  truncVisited.setSize(nVisited);
678 
679  Pout<< "For cell " << cellI << " : trying to add duplicate cut " << cut;
680  labelList cuts(1, cut);
681  writeCuts(Pout, cuts, loopWeights(cuts));
682 
683  Pout<< " to path:";
684  writeCuts(Pout, truncVisited, loopWeights(truncVisited));
685  Pout<< endl;
686 
687  return false;
688  }
689  else
690  {
691  visited[nVisited++] = cut;
692 
693  return true;
694  }
695 }
696 
697 
698 // Walk across faceI, storing cuts as you go. Returns last two cuts visisted.
699 // Returns true if valid walk.
701 (
702  const label cellI,
703  const label startCut,
704  const label faceI,
705  const label cut,
706 
707  label& lastCut,
708  label& beforeLastCut,
709  label& nVisited,
710  labelList& visited
711 ) const
712 {
713  const labelList& fCuts = faceCuts()[faceI];
714 
715  if (fCuts.size() < 2)
716  {
717  return false;
718  }
719 
720  // Easy case : two cuts.
721  if (fCuts.size() == 2)
722  {
723  if (fCuts[0] == cut)
724  {
725  if (!addCut(cellI, cut, nVisited, visited))
726  {
727  return false;
728  }
729 
730  beforeLastCut = cut;
731  lastCut = fCuts[1];
732 
733  return true;
734  }
735  else
736  {
737  if (!addCut(cellI, cut, nVisited, visited))
738  {
739  return false;
740  }
741 
742  beforeLastCut = cut;
743  lastCut = fCuts[0];
744 
745  return true;
746  }
747  }
748 
749  // Harder case: more than 2 cuts on face.
750  // Should be start or end of string of cuts. Store all but last cut.
751  if (fCuts[0] == cut)
752  {
753  // Walk forward
754  for (label i = 0; i < fCuts.size()-1; i++)
755  {
756  if (!addCut(cellI, fCuts[i], nVisited, visited))
757  {
758  return false;
759  }
760  }
761  beforeLastCut = fCuts[fCuts.size()-2];
762  lastCut = fCuts[fCuts.size()-1];
763  }
764  else if (fCuts[fCuts.size()-1] == cut)
765  {
766  for (label i = fCuts.size()-1; i >= 1; --i)
767  {
768  if (!addCut(cellI, fCuts[i], nVisited, visited))
769  {
770  return false;
771  }
772  }
773  beforeLastCut = fCuts[1];
774  lastCut = fCuts[0];
775  }
776  else
777  {
779  << "In middle of cut. cell:" << cellI << " face:" << faceI
780  << " cuts:" << fCuts << " current cut:" << cut << endl;
781 
782  return false;
783  }
784 
785  return true;
786 }
787 
788 
789 
790 // Walk across cuts (cut edges or cut vertices) of cell. Stops when hit cut
791 // already visited. Returns true when loop of 3 or more vertices found.
793 (
794  const label cellI,
795  const label startCut,
796  const label faceI,
797  const label cut,
798 
799  label& nVisited,
800  labelList& visited
801 ) const
802 {
803  // Walk across face, storing cuts. Return last two cuts visited.
804  label lastCut = -1;
805  label beforeLastCut = -1;
806 
807 
808  if (debug & 2)
809  {
810  Pout<< "For cell:" << cellI << " walked across face " << faceI
811  << " from cut ";
812  labelList cuts(1, cut);
813  writeCuts(Pout, cuts, loopWeights(cuts));
814  Pout<< endl;
815  }
816 
817  bool validWalk = walkFace
818  (
819  cellI,
820  startCut,
821  faceI,
822  cut,
823 
824  lastCut,
825  beforeLastCut,
826  nVisited,
827  visited
828  );
829 
830  if (!validWalk)
831  {
832  return false;
833  }
834 
835  if (debug & 2)
836  {
837  Pout<< " to last cut ";
838  labelList cuts(1, lastCut);
839  writeCuts(Pout, cuts, loopWeights(cuts));
840  Pout<< endl;
841  }
842 
843  // Check if starting point reached.
844  if (lastCut == startCut)
845  {
846  if (nVisited >= 3)
847  {
848  if (debug & 2)
849  {
850  // Truncate (copy of) visited for ease of printing.
851  labelList truncVisited(visited);
852  truncVisited.setSize(nVisited);
853 
854  Pout<< "For cell " << cellI << " : found closed path:";
855  writeCuts(Pout, truncVisited, loopWeights(truncVisited));
856  Pout<< " closed by " << lastCut << endl;
857  }
858 
859  return true;
860  }
861  else
862  {
863  // Loop but too short. Probably folded back on itself.
864  return false;
865  }
866  }
867 
868 
869  // Check last cut and one before that to determine type.
870 
871  // From beforeLastCut to lastCut:
872  // - from edge to edge
873  // (- always not along existing edge)
874  // - from edge to vertex
875  // - not along existing edge
876  // - along existing edge: not allowed?
877  // - from vertex to edge
878  // - not along existing edge
879  // - along existing edge. Not allowed. See above.
880  // - from vertex to vertex
881  // - not along existing edge
882  // - along existing edge
883 
884  if (isEdge(beforeLastCut))
885  {
886  if (isEdge(lastCut))
887  {
888  // beforeLastCut=edge, lastCut=edge.
889 
890  // Cross lastCut (=edge) into face not faceI
891  return crossEdge
892  (
893  cellI,
894  startCut,
895  faceI,
896  lastCut,
897  nVisited,
898  visited
899  );
900  }
901  else
902  {
903  // beforeLastCut=edge, lastCut=vertex.
904 
905  // Go from lastCut to all connected faces (except faceI)
906  return walkPoint
907  (
908  cellI,
909  startCut,
910  faceI, // exclude0: don't cross back on current face
911  -1, // exclude1
912  lastCut,
913  nVisited,
914  visited
915  );
916  }
917  }
918  else
919  {
920  if (isEdge(lastCut))
921  {
922  // beforeLastCut=vertex, lastCut=edge.
923  return crossEdge
924  (
925  cellI,
926  startCut,
927  faceI,
928  lastCut,
929  nVisited,
930  visited
931  );
932  }
933  else
934  {
935  // beforeLastCut=vertex, lastCut=vertex. Check if along existing
936  // edge.
937  label edgeI =
938  findEdge
939  (
940  faceI,
941  getVertex(beforeLastCut),
942  getVertex(lastCut)
943  );
944 
945  if (edgeI != -1)
946  {
947  // Cut along existing edge. So is in fact on two faces.
948  // Get faces on both sides of the edge to make
949  // sure we dont fold back on to those.
950 
951  label f0, f1;
952  meshTools::getEdgeFaces(mesh(), cellI, edgeI, f0, f1);
953 
954  return walkPoint
955  (
956  cellI,
957  startCut,
958  f0,
959  f1,
960  lastCut,
961  nVisited,
962  visited
963  );
964 
965  }
966  else
967  {
968  // Cross cut across face.
969  return walkPoint
970  (
971  cellI,
972  startCut,
973  faceI, // face to exclude
974  -1, // face to exclude
975  lastCut,
976  nVisited,
977  visited
978  );
979  }
980  }
981  }
982 }
983 
984 
985 // Determine for every cut cell the loop (= face) it is cut by. Done by starting
986 // from a cut edge or cut vertex and walking across faces, from cut to cut,
987 // until starting cut hit.
988 // If multiple loops are possible across a cell circumference takes the first
989 // one found.
991 {
992  // Calculate cuts per face.
993  const labelListList& allFaceCuts = faceCuts();
994 
995  // Per cell the number of faces with valid cuts. Is used as quick
996  // rejection to see if cell can be cut.
997  labelList nCutFaces(mesh().nCells(), 0);
998 
999  forAll(allFaceCuts, faceI)
1000  {
1001  const labelList& fCuts = allFaceCuts[faceI];
1002 
1003  if (fCuts.size() == mesh().faces()[faceI].size())
1004  {
1005  // Too many cuts on face. WalkCell would get very upset so disable.
1006  nCutFaces[mesh().faceOwner()[faceI]] = labelMin;
1007 
1008  if (mesh().isInternalFace(faceI))
1009  {
1010  nCutFaces[mesh().faceNeighbour()[faceI]] = labelMin;
1011  }
1012  }
1013  else if (fCuts.size() >= 2)
1014  {
1015  // Could be valid cut. Update count for owner and neighbour.
1016  nCutFaces[mesh().faceOwner()[faceI]]++;
1017 
1018  if (mesh().isInternalFace(faceI))
1019  {
1020  nCutFaces[mesh().faceNeighbour()[faceI]]++;
1021  }
1022  }
1023  }
1024 
1025 
1026  // Stack of visited cuts (nVisited used as stack pointer)
1027  // Size big enough.
1028  labelList visited(mesh().nPoints());
1029 
1030  forAll(cutCells, i)
1031  {
1032  label cellI = cutCells[i];
1033 
1034  bool validLoop = false;
1035 
1036  // Quick rejection: has enough faces that are cut?
1037  if (nCutFaces[cellI] >= 3)
1038  {
1039  const labelList& cFaces = mesh().cells()[cellI];
1040 
1041  if (debug & 2)
1042  {
1043  Pout<< "cell:" << cellI << " cut faces:" << endl;
1044  forAll(cFaces, i)
1045  {
1046  label faceI = cFaces[i];
1047  const labelList& fCuts = allFaceCuts[faceI];
1048 
1049  Pout<< " face:" << faceI << " cuts:";
1050  writeCuts(Pout, fCuts, loopWeights(fCuts));
1051  Pout<< endl;
1052  }
1053  }
1054 
1055  label nVisited = 0;
1056 
1057  // Determine the first cut face to start walking from.
1058  forAll(cFaces, cFaceI)
1059  {
1060  label faceI = cFaces[cFaceI];
1061 
1062  const labelList& fCuts = allFaceCuts[faceI];
1063 
1064  // Take first or last cut of multiple on face.
1065  // Note that in calcFaceCuts
1066  // we have already made sure this is the start or end of a
1067  // string of cuts.
1068  if (fCuts.size() >= 2)
1069  {
1070  // Try walking from start of fCuts.
1071  nVisited = 0;
1072 
1073  if (debug & 2)
1074  {
1075  Pout<< "cell:" << cellI
1076  << " start walk at face:" << faceI
1077  << " cut:";
1078  labelList cuts(1, fCuts[0]);
1079  writeCuts(Pout, cuts, loopWeights(cuts));
1080  Pout<< endl;
1081  }
1082 
1083  validLoop =
1084  walkCell
1085  (
1086  cellI,
1087  fCuts[0],
1088  faceI,
1089  fCuts[0],
1090 
1091  nVisited,
1092  visited
1093  );
1094 
1095  if (validLoop)
1096  {
1097  break;
1098  }
1099 
1100  // No need to try and walk from end of cuts since
1101  // all paths already tried by walkCell.
1102  }
1103  }
1104 
1105  if (validLoop)
1106  {
1107  // Copy nVisited elements out of visited (since visited is
1108  // never truncated for efficiency reasons)
1109 
1110  labelList& loop = cellLoops_[cellI];
1111 
1112  loop.setSize(nVisited);
1113 
1114  for (label i = 0; i < nVisited; i++)
1115  {
1116  loop[i] = visited[i];
1117  }
1118  }
1119  else
1120  {
1121  // Invalid loop. Leave cellLoops_[cellI] zero size which
1122  // flags this.
1123  Pout<< "calcCellLoops(const labelList&) : did not find valid"
1124  << " loop for cell " << cellI << endl;
1125  // Dump cell and cuts on cell.
1126  writeUncutOBJ(".", cellI);
1127 
1128  cellLoops_[cellI].setSize(0);
1129  }
1130  }
1131  else
1132  {
1133  //Pout<< "calcCellLoops(const labelList&) : did not find valid"
1134  // << " loop for cell " << cellI << " since not enough cut faces"
1135  // << endl;
1136  cellLoops_[cellI].setSize(0);
1137  }
1138  }
1139 }
1140 
1141 
1142 // Walk unset edges of single cell from starting point and marks visited
1143 // edges and vertices with status.
1146  const label cellI,
1147  const label pointI,
1148  const label status,
1149 
1150  Map<label>& edgeStatus,
1151  Map<label>& pointStatus
1152 ) const
1153 {
1154  if (pointStatus.insert(pointI, status))
1155  {
1156  // First visit to pointI
1157 
1158  const labelList& pEdges = mesh().pointEdges()[pointI];
1159 
1160  forAll(pEdges, pEdgeI)
1161  {
1162  label edgeI = pEdges[pEdgeI];
1163 
1164  if
1165  (
1166  meshTools::edgeOnCell(mesh(), cellI, edgeI)
1167  && edgeStatus.insert(edgeI, status)
1168  )
1169  {
1170  // First visit to edgeI so recurse.
1171 
1172  label v2 = mesh().edges()[edgeI].otherVertex(pointI);
1173 
1174  walkEdges(cellI, v2, status, edgeStatus, pointStatus);
1175  }
1176  }
1177  }
1178 }
1179 
1180 
1181 // Invert anchor point selection.
1184  const labelList& cellPoints,
1185  const labelList& anchorPoints,
1186  const labelList& loop
1187 ) const
1188 {
1189  labelList newElems(cellPoints.size());
1190  label newElemI = 0;
1191 
1192  forAll(cellPoints, i)
1193  {
1194  label pointI = cellPoints[i];
1195 
1196  if
1197  (
1198  findIndex(anchorPoints, pointI) == -1
1199  && findIndex(loop, vertToEVert(pointI)) == -1
1200  )
1201  {
1202  newElems[newElemI++] = pointI;
1203  }
1204  }
1205 
1206  newElems.setSize(newElemI);
1207 
1208  return newElems;
1209 }
1210 
1211 
1212 //- Check anchor points on 'outside' of loop
1215  const label cellI,
1216  const pointField& loopPts,
1217  const labelList& anchorPoints
1218 ) const
1219 {
1220  // Create identity face for ease of calculation of normal etc.
1221  face f(identity(loopPts.size()));
1222 
1223  vector normal = f.normal(loopPts);
1224  point ctr = f.centre(loopPts);
1225 
1226 
1227  // Get average position of anchor points.
1228  vector avg(vector::zero);
1229 
1230  forAll(anchorPoints, ptI)
1231  {
1232  avg += mesh().points()[anchorPoints[ptI]];
1233  }
1234  avg /= anchorPoints.size();
1235 
1236 
1237  if (((avg - ctr) & normal) > 0)
1238  {
1239  return true;
1240  }
1241  else
1242  {
1243  return false;
1244  }
1245 }
1246 
1247 
1248 // Determines set of anchor points given a loop. The loop should split the
1249 // cell into (one or) two sets of vertices. The set of vertices that is
1250 // on the 'normal' side of the loop is the anchor set.
1251 // Returns true if valid set, false otherwise.
1254  const label cellI,
1255  const labelList& loop,
1256  const pointField& loopPts,
1257 
1258  labelList& anchorPoints
1259 ) const
1260 {
1261  const edgeList& edges = mesh().edges();
1262 
1263  const labelList& cPoints = mesh().cellPoints()[cellI];
1264  const labelList& cEdges = mesh().cellEdges()[cellI];
1265  const cell& cFaces = mesh().cells()[cellI];
1266 
1267  // Points on loop
1268 
1269  // Status of point:
1270  // 0 - on loop
1271  // 1 - point set 1
1272  // 2 - point set 2
1273  Map<label> pointStatus(2*cPoints.size());
1274  Map<label> edgeStatus(2*cEdges.size());
1275 
1276  // Mark loop vertices
1277  forAll(loop, i)
1278  {
1279  label cut = loop[i];
1280 
1281  if (isEdge(cut))
1282  {
1283  edgeStatus.insert(getEdge(cut), 0);
1284  }
1285  else
1286  {
1287  pointStatus.insert(getVertex(cut), 0);
1288  }
1289  }
1290  // Since edges between two cut vertices have not been marked, mark them
1291  // explicitly
1292  forAll(cEdges, i)
1293  {
1294  label edgeI = cEdges[i];
1295  const edge& e = edges[edgeI];
1296 
1297  if (pointStatus.found(e[0]) && pointStatus.found(e[1]))
1298  {
1299  edgeStatus.insert(edgeI, 0);
1300  }
1301  }
1302 
1303 
1304  // Find uncut starting vertex
1305  label uncutIndex = firstUnique(cPoints, pointStatus);
1306 
1307  if (uncutIndex == -1)
1308  {
1310  << "Invalid loop " << loop << " for cell " << cellI << endl
1311  << "Can not find point on cell which is not cut by loop."
1312  << endl;
1313 
1314  writeOBJ(".", cellI, loopPts, labelList(0));
1315 
1316  return false;
1317  }
1318 
1319  // Walk unset vertices and edges and mark with 1 in pointStatus, edgeStatus
1320  walkEdges(cellI, cPoints[uncutIndex], 1, edgeStatus, pointStatus);
1321 
1322  // Find new uncut starting vertex
1323  uncutIndex = firstUnique(cPoints, pointStatus);
1324 
1325  if (uncutIndex == -1)
1326  {
1327  // All vertices either in loop or in anchor. So split is along single
1328  // face.
1330  << "Invalid loop " << loop << " for cell " << cellI << endl
1331  << "All vertices of cell are either in loop or in anchor set"
1332  << endl;
1333 
1334  writeOBJ(".", cellI, loopPts, labelList(0));
1335 
1336  return false;
1337  }
1338 
1339  // Walk unset vertices and edges and mark with 2. These are the
1340  // pointset 2.
1341  walkEdges(cellI, cPoints[uncutIndex], 2, edgeStatus, pointStatus);
1342 
1343  // Collect both sets in lists.
1344  DynamicList<label> connectedPoints(cPoints.size());
1345  DynamicList<label> otherPoints(cPoints.size());
1346 
1347  forAllConstIter(Map<label>, pointStatus, iter)
1348  {
1349  if (iter() == 1)
1350  {
1351  connectedPoints.append(iter.key());
1352  }
1353  else if (iter() == 2)
1354  {
1355  otherPoints.append(iter.key());
1356  }
1357  }
1358  connectedPoints.shrink();
1359  otherPoints.shrink();
1360 
1361  // Check that all points have been used.
1362  uncutIndex = firstUnique(cPoints, pointStatus);
1363 
1364  if (uncutIndex != -1)
1365  {
1367  << "Invalid loop " << loop << " for cell " << cellI
1368  << " since it splits the cell into more than two cells" << endl;
1369 
1370  writeOBJ(".", cellI, loopPts, connectedPoints);
1371 
1372  return false;
1373  }
1374 
1375 
1376  // Check that both parts (connectedPoints, otherPoints) have enough faces.
1377  labelHashSet connectedFaces(2*cFaces.size());
1378  labelHashSet otherFaces(2*cFaces.size());
1379 
1380  forAllConstIter(Map<label>, pointStatus, iter)
1381  {
1382  label pointI = iter.key();
1383 
1384  const labelList& pFaces = mesh().pointFaces()[pointI];
1385 
1386  if (iter() == 1)
1387  {
1388  forAll(pFaces, pFaceI)
1389  {
1390  if (meshTools::faceOnCell(mesh(), cellI, pFaces[pFaceI]))
1391  {
1392  connectedFaces.insert(pFaces[pFaceI]);
1393  }
1394  }
1395  }
1396  else if (iter() == 2)
1397  {
1398  forAll(pFaces, pFaceI)
1399  {
1400  if (meshTools::faceOnCell(mesh(), cellI, pFaces[pFaceI]))
1401  {
1402  otherFaces.insert(pFaces[pFaceI]);
1403  }
1404  }
1405  }
1406  }
1407 
1408  if (connectedFaces.size() < 3)
1409  {
1411  << "Invalid loop " << loop << " for cell " << cellI
1412  << " since would have too few faces on one side." << nl
1413  << "All faces:" << cFaces << endl;
1414 
1415  writeOBJ(".", cellI, loopPts, connectedPoints);
1416 
1417  return false;
1418  }
1419 
1420  if (otherFaces.size() < 3)
1421  {
1423  << "Invalid loop " << loop << " for cell " << cellI
1424  << " since would have too few faces on one side." << nl
1425  << "All faces:" << cFaces << endl;
1426 
1427  writeOBJ(".", cellI, loopPts, otherPoints);
1428 
1429  return false;
1430  }
1431 
1432 
1433  // Check that faces are split into two regions and not more.
1434  // When walking across the face the only transition of pointStatus is
1435  // from set1 to loop to set2 or back. Not allowed is from set1 to loop to
1436  // set1.
1437  {
1438  forAll(cFaces, i)
1439  {
1440  label faceI = cFaces[i];
1441 
1442  const face& f = mesh().faces()[faceI];
1443 
1444  bool hasSet1 = false;
1445  bool hasSet2 = false;
1446 
1447  label prevStat = pointStatus[f[0]];
1448 
1449  forAll(f, fp)
1450  {
1451  label v0 = f[fp];
1452  label pStat = pointStatus[v0];
1453 
1454  if (pStat == prevStat)
1455  {
1456  }
1457  else if (pStat == 0)
1458  {
1459  // Loop.
1460  }
1461  else if (pStat == 1)
1462  {
1463  if (hasSet1)
1464  {
1465  // Second occurence of set1.
1467  << "Invalid loop " << loop << " for cell " << cellI
1468  << " since face " << f << " would be split into"
1469  << " more than two faces" << endl;
1470 
1471  writeOBJ(".", cellI, loopPts, otherPoints);
1472 
1473  return false;
1474  }
1475 
1476  hasSet1 = true;
1477  }
1478  else if (pStat == 2)
1479  {
1480  if (hasSet2)
1481  {
1482  // Second occurence of set1.
1484  << "Invalid loop " << loop << " for cell " << cellI
1485  << " since face " << f << " would be split into"
1486  << " more than two faces" << endl;
1487 
1488  writeOBJ(".", cellI, loopPts, otherPoints);
1489 
1490  return false;
1491  }
1492 
1493  hasSet2 = true;
1494  }
1495  else
1496  {
1498  << abort(FatalError);
1499  }
1500 
1501  prevStat = pStat;
1502 
1503 
1504  label v1 = f.nextLabel(fp);
1505  label edgeI = findEdge(faceI, v0, v1);
1506 
1507  label eStat = edgeStatus[edgeI];
1508 
1509  if (eStat == prevStat)
1510  {
1511  }
1512  else if (eStat == 0)
1513  {
1514  // Loop.
1515  }
1516  else if (eStat == 1)
1517  {
1518  if (hasSet1)
1519  {
1520  // Second occurence of set1.
1522  << "Invalid loop " << loop << " for cell " << cellI
1523  << " since face " << f << " would be split into"
1524  << " more than two faces" << endl;
1525 
1526  writeOBJ(".", cellI, loopPts, otherPoints);
1527 
1528  return false;
1529  }
1530 
1531  hasSet1 = true;
1532  }
1533  else if (eStat == 2)
1534  {
1535  if (hasSet2)
1536  {
1537  // Second occurence of set1.
1539  << "Invalid loop " << loop << " for cell " << cellI
1540  << " since face " << f << " would be split into"
1541  << " more than two faces" << endl;
1542 
1543  writeOBJ(".", cellI, loopPts, otherPoints);
1544 
1545  return false;
1546  }
1547 
1548  hasSet2 = true;
1549  }
1550  prevStat = eStat;
1551  }
1552  }
1553  }
1554 
1555 
1556 
1557 
1558  // Check which one of point sets to use.
1559  bool loopOk = loopAnchorConsistent(cellI, loopPts, connectedPoints);
1560 
1561  //if (debug)
1562  {
1563  // Additional check: are non-anchor points on other side?
1564  bool otherLoopOk = loopAnchorConsistent(cellI, loopPts, otherPoints);
1565 
1566  if (loopOk == otherLoopOk)
1567  {
1568  // Both sets of points are supposedly on the same side as the
1569  // loop normal. Oops.
1570 
1572  << " For cell:" << cellI
1573  << " achorpoints and nonanchorpoints are geometrically"
1574  << " on same side!" << endl
1575  << "cellPoints:" << cPoints << endl
1576  << "loop:" << loop << endl
1577  << "anchors:" << connectedPoints << endl
1578  << "otherPoints:" << otherPoints << endl;
1579 
1580  writeOBJ(".", cellI, loopPts, connectedPoints);
1581  }
1582  }
1583 
1584  if (loopOk)
1585  {
1586  // connectedPoints on 'outside' of loop so these are anchor points
1587  anchorPoints.transfer(connectedPoints);
1588  connectedPoints.clear();
1589  }
1590  else
1591  {
1592  anchorPoints.transfer(otherPoints);
1593  otherPoints.clear();
1594  }
1595  return true;
1596 }
1597 
1598 
1601  const labelList& loop,
1602  const scalarField& loopWeights
1603 ) const
1604 {
1605  pointField loopPts(loop.size());
1606 
1607  forAll(loop, fp)
1608  {
1609  loopPts[fp] = coord(loop[fp], loopWeights[fp]);
1610  }
1611  return loopPts;
1612 }
1613 
1614 
1615 // Returns weights of loop. Inverse of loopPoints.
1617 {
1618  scalarField weights(loop.size());
1619 
1620  forAll(loop, fp)
1621  {
1622  label cut = loop[fp];
1623 
1624  if (isEdge(cut))
1625  {
1626  label edgeI = getEdge(cut);
1627 
1628  weights[fp] = edgeWeight_[edgeI];
1629  }
1630  else
1631  {
1632  weights[fp] = -GREAT;
1633  }
1634  }
1635  return weights;
1636 }
1637 
1638 
1639 // Check if cut edges in loop are compatible with ones in edgeIsCut_
1642  const labelList& loop,
1643  const scalarField& loopWeights
1644 ) const
1645 {
1646  forAll(loop, fp)
1647  {
1648  label cut = loop[fp];
1649 
1650  if (isEdge(cut))
1651  {
1652  label edgeI = getEdge(cut);
1653 
1654  // Check: cut compatible only if can be snapped to existing one.
1655  if (edgeIsCut_[edgeI])
1656  {
1657  scalar edgeLen = mesh().edges()[edgeI].mag(mesh().points());
1658 
1659  if
1660  (
1661  mag(loopWeights[fp] - edgeWeight_[edgeI])
1662  > geomCellLooper::snapTol()*edgeLen
1663  )
1664  {
1665  // Positions differ too much->would create two cuts.
1666  return false;
1667  }
1668  }
1669  }
1670  }
1671  return true;
1672 }
1673 
1674 
1675 // Counts cuts on face. Includes cuts through vertices and through edges.
1676 // Assumes that if edge is cut both in edgeIsCut and in loop that the position
1677 // of the cut is the same.
1680  const label faceI,
1681  const labelList& loop
1682 ) const
1683 {
1684  label nCuts = 0;
1685 
1686  // Count cut vertices
1687  const face& f = mesh().faces()[faceI];
1688 
1689  forAll(f, fp)
1690  {
1691  label vertI = f[fp];
1692 
1693  // Vertex already cut or mentioned in current loop.
1694  if
1695  (
1696  pointIsCut_[vertI]
1697  || (findIndex(loop, vertToEVert(vertI)) != -1)
1698  )
1699  {
1700  nCuts++;
1701  }
1702  }
1703 
1704  // Count cut edges.
1705  const labelList& fEdges = mesh().faceEdges()[faceI];
1706 
1707  forAll(fEdges, fEdgeI)
1708  {
1709  label edgeI = fEdges[fEdgeI];
1710 
1711  // Edge already cut or mentioned in current loop.
1712  if
1713  (
1714  edgeIsCut_[edgeI]
1715  || (findIndex(loop, edgeToEVert(edgeI)) != -1)
1716  )
1717  {
1718  nCuts++;
1719  }
1720  }
1721 
1722  return nCuts;
1723 }
1724 
1725 
1726 // Determine compatibility of loop with existing cut pattern. Does not use
1727 // cut-addressing (faceCuts_, cutCuts_)
1730  const label cellI,
1731  const labelList& loop
1732 ) const
1733 {
1734 
1735  if (loop.size() < 2)
1736  {
1737  return false;
1738  }
1739 
1740  forAll(loop, cutI)
1741  {
1742  if (isEdge(loop[cutI]))
1743  {
1744  label edgeI = getEdge(loop[cutI]);
1745 
1746  if (edgeIsCut_[edgeI])
1747  {
1748  // edge compatibility already checked.
1749  }
1750  else
1751  {
1752  // Quick rejection: vertices of edge itself cannot be cut.
1753  const edge& e = mesh().edges()[edgeI];
1754 
1755  if (pointIsCut_[e.start()] || pointIsCut_[e.end()])
1756  {
1757  return false;
1758  }
1759 
1760 
1761  // Check faces using this edge
1762  const labelList& eFaces = mesh().edgeFaces()[edgeI];
1763 
1764  forAll(eFaces, eFaceI)
1765  {
1766  label nCuts = countFaceCuts(eFaces[eFaceI], loop);
1767 
1768  if (nCuts > 2)
1769  {
1770  return false;
1771  }
1772  }
1773  }
1774  }
1775  else
1776  {
1777  // Vertex cut
1778 
1779  label vertI = getVertex(loop[cutI]);
1780 
1781  if (!pointIsCut_[vertI])
1782  {
1783  // New cut through vertex.
1784 
1785  // Check edges using vertex.
1786  const labelList& pEdges = mesh().pointEdges()[vertI];
1787 
1788  forAll(pEdges, pEdgeI)
1789  {
1790  label edgeI = pEdges[pEdgeI];
1791 
1792  if (edgeIsCut_[edgeI])
1793  {
1794  return false;
1795  }
1796  }
1797 
1798  // Check faces using vertex.
1799  const labelList& pFaces = mesh().pointFaces()[vertI];
1800 
1801  forAll(pFaces, pFaceI)
1802  {
1803  label nCuts = countFaceCuts(pFaces[pFaceI], loop);
1804 
1805  if (nCuts > 2)
1806  {
1807  return false;
1808  }
1809  }
1810  }
1811  }
1812  }
1813 
1814  // All ok.
1815  return true;
1816 }
1817 
1818 
1819 // Determine compatibility of loop with existing cut pattern. Does not use
1820 // derived cut-addressing (faceCuts), only pointIsCut, edgeIsCut.
1821 // Adds any cross-cuts found to newFaceSplitCut and sets cell points on
1822 // one side of the loop in anchorPoints.
1825  const label cellI,
1826  const labelList& loop,
1827  const scalarField& loopWeights,
1828 
1829  Map<edge>& newFaceSplitCut,
1830  labelList& anchorPoints
1831 ) const
1832 {
1833  if (loop.size() < 2)
1834  {
1835  return false;
1836  }
1837 
1838  if (debug & 4)
1839  {
1840  // Allow as fallback the 'old' loop checking where only a single
1841  // cut per face is allowed.
1842  if (!conservativeValidLoop(cellI, loop))
1843  {
1844  return false;
1845  }
1846  }
1847 
1848  forAll(loop, fp)
1849  {
1850  label cut = loop[fp];
1851  label nextCut = loop[(fp+1) % loop.size()];
1852 
1853  // Label (if any) of face cut (so cut not along existing edge)
1854  label meshFaceI = -1;
1855 
1856  if (isEdge(cut))
1857  {
1858  label edgeI = getEdge(cut);
1859 
1860  // Look one cut ahead to find if it is along existing edge.
1861 
1862  if (isEdge(nextCut))
1863  {
1864  // From edge to edge -> cross cut
1865  label nextEdgeI = getEdge(nextCut);
1866 
1867  // Find face and mark as to be split.
1868  meshFaceI = edgeEdgeToFace(cellI, edgeI, nextEdgeI);
1869 
1870  if (meshFaceI == -1)
1871  {
1872  // Can't find face using both cut edges.
1873  return false;
1874  }
1875  }
1876  else
1877  {
1878  // From edge to vertex -> cross cut only if no existing edge.
1879 
1880  label nextVertI = getVertex(nextCut);
1881  const edge& e = mesh().edges()[edgeI];
1882 
1883  if (e.start() != nextVertI && e.end() != nextVertI)
1884  {
1885  // New edge. Find face and mark as to be split.
1886  meshFaceI = edgeVertexToFace(cellI, edgeI, nextVertI);
1887 
1888  if (meshFaceI == -1)
1889  {
1890  // Can't find face. Ilegal.
1891  return false;
1892  }
1893  }
1894  }
1895  }
1896  else
1897  {
1898  // Cut is vertex.
1899  label vertI = getVertex(cut);
1900 
1901  if (isEdge(nextCut))
1902  {
1903  // From vertex to edge -> cross cut only if no existing edge.
1904  label nextEdgeI = getEdge(nextCut);
1905 
1906  const edge& nextE = mesh().edges()[nextEdgeI];
1907 
1908  if (nextE.start() != vertI && nextE.end() != vertI)
1909  {
1910  // Should be cross cut. Find face.
1911  meshFaceI = edgeVertexToFace(cellI, nextEdgeI, vertI);
1912 
1913  if (meshFaceI == -1)
1914  {
1915  return false;
1916  }
1917  }
1918  }
1919  else
1920  {
1921  // From vertex to vertex -> cross cut only if no existing edge.
1922  label nextVertI = getVertex(nextCut);
1923 
1924  if (meshTools::findEdge(mesh(), vertI, nextVertI) == -1)
1925  {
1926  // New edge. Find face.
1927  meshFaceI = vertexVertexToFace(cellI, vertI, nextVertI);
1928 
1929  if (meshFaceI == -1)
1930  {
1931  return false;
1932  }
1933  }
1934  }
1935  }
1936 
1937  if (meshFaceI != -1)
1938  {
1939  // meshFaceI is cut across along cut-nextCut (so not along existing
1940  // edge). Check if this is compatible with existing pattern.
1941  edge cutEdge(cut, nextCut);
1942 
1943  Map<edge>::const_iterator iter = faceSplitCut_.find(meshFaceI);
1944 
1945  if (iter == faceSplitCut_.end())
1946  {
1947  // Face not yet cut so insert.
1948  newFaceSplitCut.insert(meshFaceI, cutEdge);
1949  }
1950  else
1951  {
1952  // Face already cut. Ok if same edge.
1953  if (iter() != cutEdge)
1954  {
1955  return false;
1956  }
1957  }
1958  }
1959  }
1960 
1961  // Is there a face on which all cuts are?
1962  label faceContainingLoop = loopFace(cellI, loop);
1963 
1964  if (faceContainingLoop != -1)
1965  {
1967  << "Found loop on cell " << cellI << " with all points"
1968  << " on face " << faceContainingLoop << endl;
1969 
1970  //writeOBJ(".", cellI, loopPoints(loop, loopWeights), labelList(0));
1971 
1972  return false;
1973  }
1974 
1975  // Calculate anchor points
1976  // Final success is determined by whether anchor points can be determined.
1977  return calcAnchors
1978  (
1979  cellI,
1980  loop,
1981  loopPoints(loop, loopWeights),
1982  anchorPoints
1983  );
1984 }
1985 
1986 
1987 // Update basic cut information (pointIsCut, edgeIsCut) from cellLoops.
1988 // Assumes cellLoops_ and edgeWeight_ already set and consistent.
1989 // Does not use any other information.
1991 {
1992  // 'Uncut' edges/vertices that are not used in loops.
1993  pointIsCut_ = false;
1994 
1995  edgeIsCut_ = false;
1996 
1997  faceSplitCut_.clear();
1998 
1999  forAll(cellLoops_, cellI)
2000  {
2001  const labelList& loop = cellLoops_[cellI];
2002 
2003  if (loop.size())
2004  {
2005  // Storage for cross-face cuts
2006  Map<edge> faceSplitCuts(loop.size());
2007  // Storage for points on one side of cell.
2008  labelList anchorPoints;
2009 
2010  if
2011  (
2012  !validLoop
2013  (
2014  cellI,
2015  loop,
2016  loopWeights(loop),
2017  faceSplitCuts,
2018  anchorPoints
2019  )
2020  )
2021  {
2022  //writeOBJ(".", cellI, loopPoints(cellI), anchorPoints);
2023 
2025  << "Illegal loop " << loop
2026  << " when recreating cut-addressing"
2027  << " from existing cellLoops for cell " << cellI
2028  << endl;
2029 
2030  cellLoops_[cellI].setSize(0);
2031  cellAnchorPoints_[cellI].setSize(0);
2032  }
2033  else
2034  {
2035  // Copy anchor points.
2036  cellAnchorPoints_[cellI].transfer(anchorPoints);
2037 
2038  // Copy faceSplitCuts into overall faceSplit info.
2039  forAllConstIter(Map<edge>, faceSplitCuts, iter)
2040  {
2041  faceSplitCut_.insert(iter.key(), iter());
2042  }
2043 
2044  // Update edgeIsCut, pointIsCut information
2045  forAll(loop, cutI)
2046  {
2047  label cut = loop[cutI];
2048 
2049  if (isEdge(cut))
2050  {
2051  edgeIsCut_[getEdge(cut)] = true;
2052  }
2053  else
2054  {
2055  pointIsCut_[getVertex(cut)] = true;
2056  }
2057  }
2058  }
2059  }
2060  }
2061 
2062  // Reset edge weights
2063  forAll(edgeIsCut_, edgeI)
2064  {
2065  if (!edgeIsCut_[edgeI])
2066  {
2067  // Weight not used. Set to illegal value to make any use fall over.
2068  edgeWeight_[edgeI] = -GREAT;
2069  }
2070  }
2071 }
2072 
2073 
2074 // Upate basic cut information from single cellLoop. Returns true if loop
2075 // was valid.
2078  const label cellI,
2079  const labelList& loop,
2080  const scalarField& loopWeights
2081 )
2082 {
2083  // Dump loop for debugging.
2084  if (debug)
2085  {
2086  OFstream str("last_cell.obj");
2087 
2088  str<< "# edges of cell " << cellI << nl;
2089 
2091  (
2092  str,
2093  mesh().cells(),
2094  mesh().faces(),
2095  mesh().points(),
2096  labelList(1, cellI)
2097  );
2098 
2099 
2100  OFstream loopStr("last_loop.obj");
2101 
2102  loopStr<< "# looppoints for cell " << cellI << nl;
2103 
2104  pointField pointsOfLoop = loopPoints(loop, loopWeights);
2105 
2106  forAll(pointsOfLoop, i)
2107  {
2108  meshTools::writeOBJ(loopStr, pointsOfLoop[i]);
2109  }
2110 
2111  str << 'l';
2112 
2113  forAll(pointsOfLoop, i)
2114  {
2115  str << ' ' << i + 1;
2116  }
2117  str << ' ' << 1 << nl;
2118  }
2119 
2120  bool okLoop = false;
2121 
2122  if (validEdgeLoop(loop, loopWeights))
2123  {
2124  // Storage for cuts across face
2125  Map<edge> faceSplitCuts(loop.size());
2126  // Storage for points on one side of cell
2127  labelList anchorPoints;
2128 
2129  okLoop =
2130  validLoop(cellI, loop, loopWeights, faceSplitCuts, anchorPoints);
2131 
2132  if (okLoop)
2133  {
2134  // Valid loop. Copy cellLoops and anchorPoints
2135  cellLoops_[cellI] = loop;
2136  cellAnchorPoints_[cellI].transfer(anchorPoints);
2137 
2138  // Copy split cuts
2139  forAllConstIter(Map<edge>, faceSplitCuts, iter)
2140  {
2141  faceSplitCut_.insert(iter.key(), iter());
2142  }
2143 
2144 
2145  // Update edgeIsCut, pointIsCut information
2146  forAll(loop, cutI)
2147  {
2148  label cut = loop[cutI];
2149 
2150  if (isEdge(cut))
2151  {
2152  label edgeI = getEdge(cut);
2153 
2154  edgeIsCut_[edgeI] = true;
2155 
2156  edgeWeight_[edgeI] = loopWeights[cutI];
2157  }
2158  else
2159  {
2160  label vertI = getVertex(cut);
2161 
2162  pointIsCut_[vertI] = true;
2163  }
2164  }
2165  }
2166  }
2167 
2168  return okLoop;
2169 }
2170 
2171 
2172 // Update basic cut information from cellLoops. Checks for consistency with
2173 // existing cut pattern.
2176  const labelList& cellLabels,
2177  const labelListList& cellLoops,
2178  const List<scalarField>& cellLoopWeights
2179 )
2180 {
2181  // 'Uncut' edges/vertices that are not used in loops.
2182  pointIsCut_ = false;
2183 
2184  edgeIsCut_ = false;
2185 
2186  forAll(cellLabels, cellLabelI)
2187  {
2188  label cellI = cellLabels[cellLabelI];
2189 
2190  const labelList& loop = cellLoops[cellLabelI];
2191 
2192  if (loop.size())
2193  {
2194  const scalarField& loopWeights = cellLoopWeights[cellLabelI];
2195 
2196  if (setFromCellLoop(cellI, loop, loopWeights))
2197  {
2198  // Valid loop. Call above will have upated all already.
2199  }
2200  else
2201  {
2202  // Clear cellLoops
2203  cellLoops_[cellI].setSize(0);
2204  }
2205  }
2206  }
2207 }
2208 
2209 
2210 // Cut cells and update basic cut information from cellLoops. Checks each loop
2211 // for consistency with existing cut pattern.
2214  const cellLooper& cellCutter,
2215  const List<refineCell>& refCells
2216 )
2217 {
2218  // 'Uncut' edges/vertices that are not used in loops.
2219  pointIsCut_ = false;
2220 
2221  edgeIsCut_ = false;
2222 
2223  // storage for loop of cuts (cut vertices and/or cut edges)
2224  labelList cellLoop;
2225  scalarField cellLoopWeights;
2226 
2227  // For debugging purposes
2228  DynamicList<label> invalidCutCells(2);
2229  DynamicList<labelList> invalidCutLoops(2);
2230  DynamicList<scalarField> invalidCutLoopWeights(2);
2231 
2232 
2233  forAll(refCells, refCellI)
2234  {
2235  const refineCell& refCell = refCells[refCellI];
2236 
2237  label cellI = refCell.cellNo();
2238 
2239  const vector& refDir = refCell.direction();
2240 
2241 
2242  // Cut cell. Determines cellLoop and cellLoopWeights
2243  bool goodCut =
2244  cellCutter.cut
2245  (
2246  refDir,
2247  cellI,
2248 
2249  pointIsCut_,
2250  edgeIsCut_,
2251  edgeWeight_,
2252 
2253  cellLoop,
2254  cellLoopWeights
2255  );
2256 
2257  // Check whether edge refinement is on a per face basis compatible with
2258  // current pattern.
2259  if (goodCut)
2260  {
2261  if (setFromCellLoop(cellI, cellLoop, cellLoopWeights))
2262  {
2263  // Valid loop. Will have updated all info already.
2264  }
2265  else
2266  {
2267  cellLoops_[cellI].setSize(0);
2268 
2269  // Discarded by validLoop
2270  if (debug)
2271  {
2272  invalidCutCells.append(cellI);
2273  invalidCutLoops.append(cellLoop);
2274  invalidCutLoopWeights.append(cellLoopWeights);
2275  }
2276  }
2277  }
2278  else
2279  {
2280  // Clear cellLoops
2281  cellLoops_[cellI].setSize(0);
2282  }
2283  }
2284 
2285  if (debug && invalidCutCells.size())
2286  {
2287  invalidCutCells.shrink();
2288  invalidCutLoops.shrink();
2289  invalidCutLoopWeights.shrink();
2290 
2291  fileName cutsFile("invalidLoopCells.obj");
2292 
2293  Pout<< "cellCuts : writing inValidLoops cells to " << cutsFile << endl;
2294 
2295  OFstream cutsStream(cutsFile);
2296 
2298  (
2299  cutsStream,
2300  mesh().cells(),
2301  mesh().faces(),
2302  mesh().points(),
2303  invalidCutCells
2304  );
2305 
2306  fileName loopsFile("invalidLoops.obj");
2307 
2308  Pout<< "cellCuts : writing inValidLoops loops to " << loopsFile << endl;
2309 
2310  OFstream loopsStream(loopsFile);
2311 
2312  label vertI = 0;
2313 
2314  forAll(invalidCutLoops, i)
2315  {
2316  writeOBJ
2317  (
2318  loopsStream,
2319  loopPoints(invalidCutLoops[i], invalidCutLoopWeights[i]),
2320  vertI
2321  );
2322  }
2323  }
2324 }
2325 
2326 
2327 // Same as one before but cut plane prescribed (instead of just normal)
2330  const cellLooper& cellCutter,
2331  const labelList& cellLabels,
2332  const List<plane>& cellCutPlanes
2333 )
2334 {
2335  // 'Uncut' edges/vertices that are not used in loops.
2336  pointIsCut_ = false;
2337 
2338  edgeIsCut_ = false;
2339 
2340  // storage for loop of cuts (cut vertices and/or cut edges)
2341  labelList cellLoop;
2342  scalarField cellLoopWeights;
2343 
2344  // For debugging purposes
2345  DynamicList<label> invalidCutCells(2);
2346  DynamicList<labelList> invalidCutLoops(2);
2347  DynamicList<scalarField> invalidCutLoopWeights(2);
2348 
2349 
2350  forAll(cellLabels, i)
2351  {
2352  label cellI = cellLabels[i];
2353 
2354  // Cut cell. Determines cellLoop and cellLoopWeights
2355  bool goodCut =
2356  cellCutter.cut
2357  (
2358  cellCutPlanes[i],
2359  cellI,
2360 
2361  pointIsCut_,
2362  edgeIsCut_,
2363  edgeWeight_,
2364 
2365  cellLoop,
2366  cellLoopWeights
2367  );
2368 
2369  // Check whether edge refinement is on a per face basis compatible with
2370  // current pattern.
2371  if (goodCut)
2372  {
2373  if (setFromCellLoop(cellI, cellLoop, cellLoopWeights))
2374  {
2375  // Valid loop. Will have updated all info already.
2376  }
2377  else
2378  {
2379  cellLoops_[cellI].setSize(0);
2380 
2381  // Discarded by validLoop
2382  if (debug)
2383  {
2384  invalidCutCells.append(cellI);
2385  invalidCutLoops.append(cellLoop);
2386  invalidCutLoopWeights.append(cellLoopWeights);
2387  }
2388  }
2389  }
2390  else
2391  {
2392  // Clear cellLoops
2393  cellLoops_[cellI].setSize(0);
2394  }
2395  }
2396 
2397  if (debug && invalidCutCells.size())
2398  {
2399  invalidCutCells.shrink();
2400  invalidCutLoops.shrink();
2401  invalidCutLoopWeights.shrink();
2402 
2403  fileName cutsFile("invalidLoopCells.obj");
2404 
2405  Pout<< "cellCuts : writing inValidLoops cells to " << cutsFile << endl;
2406 
2407  OFstream cutsStream(cutsFile);
2408 
2410  (
2411  cutsStream,
2412  mesh().cells(),
2413  mesh().faces(),
2414  mesh().points(),
2415  invalidCutCells
2416  );
2417 
2418  fileName loopsFile("invalidLoops.obj");
2419 
2420  Pout<< "cellCuts : writing inValidLoops loops to " << loopsFile << endl;
2421 
2422  OFstream loopsStream(loopsFile);
2423 
2424  label vertI = 0;
2425 
2426  forAll(invalidCutLoops, i)
2427  {
2428  writeOBJ
2429  (
2430  loopsStream,
2431  loopPoints(invalidCutLoops[i], invalidCutLoopWeights[i]),
2432  vertI
2433  );
2434  }
2435  }
2436 }
2437 
2438 
2439 // Set orientation of loops
2441 {
2442  // Determine anchorPoints if not yet done by validLoop.
2443  forAll(cellLoops_, cellI)
2444  {
2445  const labelList& loop = cellLoops_[cellI];
2446 
2447  if (loop.size() && cellAnchorPoints_[cellI].empty())
2448  {
2449  // Leave anchor points empty if illegal loop.
2450  calcAnchors
2451  (
2452  cellI,
2453  loop,
2454  loopPoints(cellI),
2455  cellAnchorPoints_[cellI]
2456  );
2457  }
2458  }
2459 
2460  if (debug & 2)
2461  {
2462  Pout<< "cellAnchorPoints:" << endl;
2463  }
2464  forAll(cellAnchorPoints_, cellI)
2465  {
2466  if (cellLoops_[cellI].size())
2467  {
2468  if (cellAnchorPoints_[cellI].empty())
2469  {
2471  << "No anchor points for cut cell " << cellI << endl
2472  << "cellLoop:" << cellLoops_[cellI] << abort(FatalError);
2473  }
2474 
2475  if (debug & 2)
2476  {
2477  Pout<< " cell:" << cellI << " anchored at "
2478  << cellAnchorPoints_[cellI] << endl;
2479  }
2480  }
2481  }
2482 
2483  // Calculate number of valid cellLoops
2484  nLoops_ = 0;
2485 
2486  forAll(cellLoops_, cellI)
2487  {
2488  if (cellLoops_[cellI].size())
2489  {
2490  nLoops_++;
2491  }
2492  }
2493 }
2494 
2495 
2496 // Do all: calculate addressing, calculate loops splitting cells
2498 {
2499  // Sanity check on weights
2500  forAll(edgeIsCut_, edgeI)
2501  {
2502  if (edgeIsCut_[edgeI])
2503  {
2504  scalar weight = edgeWeight_[edgeI];
2505 
2506  if (weight < 0 || weight > 1)
2507  {
2509  << "Weight out of range [0,1]. Edge " << edgeI
2510  << " verts:" << mesh().edges()[edgeI]
2511  << " weight:" << weight << abort(FatalError);
2512  }
2513  }
2514  else
2515  {
2516  // Weight not used. Set to illegal value to make any use fall over.
2517  edgeWeight_[edgeI] = -GREAT;
2518  }
2519  }
2520 
2521 
2522  // Calculate faces that split cells in two
2523  calcCellLoops(cutCells);
2524 
2525  if (debug & 2)
2526  {
2527  Pout<< "-- cellLoops --" << endl;
2528  forAll(cellLoops_, cellI)
2529  {
2530  const labelList& loop = cellLoops_[cellI];
2531 
2532  if (loop.size())
2533  {
2534  Pout<< "cell:" << cellI << " ";
2535  writeCuts(Pout, loop, loopWeights(loop));
2536  Pout<< endl;
2537  }
2538  }
2539  }
2540 
2541  // Redo basic cut information (pointIsCut, edgeIsCut, faceSplitCut)
2542  // using cellLoop only.
2543  setFromCellLoops();
2544 }
2545 
2546 
2548 {
2549  // Check weights for unsnapped values
2550  forAll(edgeIsCut_, edgeI)
2551  {
2552  if (edgeIsCut_[edgeI])
2553  {
2554  if
2555  (
2556  edgeWeight_[edgeI] < geomCellLooper::snapTol()
2557  || edgeWeight_[edgeI] > (1 - geomCellLooper::snapTol())
2558  )
2559  {
2560  // Should have been snapped.
2562  << "edge:" << edgeI << " vertices:"
2563  << mesh().edges()[edgeI]
2564  << " weight:" << edgeWeight_[edgeI] << " should have been"
2565  << " snapped to one of its endpoints"
2566  << endl;
2567  }
2568  }
2569  else
2570  {
2571  if (edgeWeight_[edgeI] > - 1)
2572  {
2574  << "edge:" << edgeI << " vertices:"
2575  << mesh().edges()[edgeI]
2576  << " weight:" << edgeWeight_[edgeI] << " is not cut but"
2577  << " its weight is not marked invalid"
2578  << abort(FatalError);
2579  }
2580  }
2581  }
2582 
2583  // Check that all elements of cellloop are registered
2584  forAll(cellLoops_, cellI)
2585  {
2586  const labelList& loop = cellLoops_[cellI];
2587 
2588  forAll(loop, i)
2589  {
2590  label cut = loop[i];
2591 
2592  if
2593  (
2594  (isEdge(cut) && !edgeIsCut_[getEdge(cut)])
2595  || (!isEdge(cut) && !pointIsCut_[getVertex(cut)])
2596  )
2597  {
2598  labelList cuts(1, cut);
2599  writeCuts(Pout, cuts, loopWeights(cuts));
2600 
2602  << "cell:" << cellI << " loop:"
2603  << loop
2604  << " cut:" << cut << " is not marked as cut"
2605  << abort(FatalError);
2606  }
2607  }
2608  }
2609 
2610  // Check that no elements of cell loop are anchor point.
2611  forAll(cellLoops_, cellI)
2612  {
2613  const labelList& anchors = cellAnchorPoints_[cellI];
2614 
2615  const labelList& loop = cellLoops_[cellI];
2616 
2617  if (loop.size() && anchors.empty())
2618  {
2620  << "cell:" << cellI << " loop:" << loop
2621  << " has no anchor points"
2622  << abort(FatalError);
2623  }
2624 
2625 
2626  forAll(loop, i)
2627  {
2628  label cut = loop[i];
2629 
2630  if
2631  (
2632  !isEdge(cut)
2633  && findIndex(anchors, getVertex(cut)) != -1
2634  )
2635  {
2637  << "cell:" << cellI << " loop:" << loop
2638  << " anchor points:" << anchors
2639  << " anchor:" << getVertex(cut) << " is part of loop"
2640  << abort(FatalError);
2641  }
2642  }
2643  }
2644 
2645 
2646  // Check that cut faces have a neighbour that is cut.
2647  forAllConstIter(Map<edge>, faceSplitCut_, iter)
2648  {
2649  label faceI = iter.key();
2650 
2651  if (mesh().isInternalFace(faceI))
2652  {
2653  label own = mesh().faceOwner()[faceI];
2654  label nei = mesh().faceNeighbour()[faceI];
2655 
2656  if (cellLoops_[own].empty() && cellLoops_[nei].empty())
2657  {
2659  << "Internal face:" << faceI << " cut by " << iter()
2660  << " has owner:" << own
2661  << " and neighbour:" << nei
2662  << " that are both uncut"
2663  << abort(FatalError);
2664  }
2665  }
2666  else
2667  {
2668  label own = mesh().faceOwner()[faceI];
2669 
2670  if (cellLoops_[own].empty())
2671  {
2673  << "Boundary face:" << faceI << " cut by " << iter()
2674  << " has owner:" << own
2675  << " that is uncut"
2676  << abort(FatalError);
2677  }
2678  }
2679  }
2680 }
2681 
2682 
2683 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
2684 
2685 // Construct from cells to cut and pattern of cuts
2688  const polyMesh& mesh,
2689  const labelList& cutCells,
2690  const labelList& meshVerts,
2691  const labelList& meshEdges,
2692  const scalarField& meshEdgeWeights
2693 )
2694 :
2695  edgeVertex(mesh),
2696  pointIsCut_(expand(mesh.nPoints(), meshVerts)),
2697  edgeIsCut_(expand(mesh.nEdges(), meshEdges)),
2698  edgeWeight_(expand(mesh.nEdges(), meshEdges, meshEdgeWeights)),
2699  faceCutsPtr_(NULL),
2700  faceSplitCut_(cutCells.size()),
2701  cellLoops_(mesh.nCells()),
2702  nLoops_(-1),
2703  cellAnchorPoints_(mesh.nCells())
2704 {
2705  if (debug)
2706  {
2707  Pout<< "cellCuts : constructor from cut verts and edges" << endl;
2708  }
2709 
2710  calcLoopsAndAddressing(cutCells);
2711 
2712  // Calculate planes and flip cellLoops if necessary
2713  orientPlanesAndLoops();
2714 
2715  if (debug)
2716  {
2717  check();
2718  }
2719 
2720  clearOut();
2721 
2722  if (debug)
2723  {
2724  Pout<< "cellCuts : leaving constructor from cut verts and edges"
2725  << endl;
2726  }
2727 }
2728 
2729 
2730 // Construct from pattern of cuts. Finds out itself which cells are cut.
2731 // (can go wrong if e.g. all neighbours of cell are refined)
2734  const polyMesh& mesh,
2735  const labelList& meshVerts,
2736  const labelList& meshEdges,
2737  const scalarField& meshEdgeWeights
2738 )
2739 :
2740  edgeVertex(mesh),
2741  pointIsCut_(expand(mesh.nPoints(), meshVerts)),
2742  edgeIsCut_(expand(mesh.nEdges(), meshEdges)),
2743  edgeWeight_(expand(mesh.nEdges(), meshEdges, meshEdgeWeights)),
2744  faceCutsPtr_(NULL),
2745  faceSplitCut_(mesh.nFaces()/10 + 1),
2746  cellLoops_(mesh.nCells()),
2747  nLoops_(-1),
2748  cellAnchorPoints_(mesh.nCells())
2749 {
2750  if (debug)
2751  {
2752  Pout<< "cellCuts : constructor from cellLoops" << endl;
2753  }
2754 
2755  calcLoopsAndAddressing(identity(mesh.nCells()));
2756 
2757  // Calculate planes and flip cellLoops if necessary
2758  orientPlanesAndLoops();
2759 
2760  if (debug)
2761  {
2762  check();
2763  }
2764 
2765  clearOut();
2766 
2767  if (debug)
2768  {
2769  Pout<< "cellCuts : leaving constructor from cellLoops" << endl;
2770  }
2771 }
2772 
2773 
2774 // Construct from complete cellLoops. Assumes correct cut pattern.
2775 // Only constructs cut-cut addressing and cellAnchorPoints
2778  const polyMesh& mesh,
2779  const labelList& cellLabels,
2780  const labelListList& cellLoops,
2781  const List<scalarField>& cellEdgeWeights
2782 )
2783 :
2784  edgeVertex(mesh),
2785  pointIsCut_(mesh.nPoints(), false),
2786  edgeIsCut_(mesh.nEdges(), false),
2787  edgeWeight_(mesh.nEdges(), -GREAT),
2788  faceCutsPtr_(NULL),
2789  faceSplitCut_(cellLabels.size()),
2790  cellLoops_(mesh.nCells()),
2791  nLoops_(-1),
2792  cellAnchorPoints_(mesh.nCells())
2793 {
2794  if (debug)
2795  {
2796  Pout<< "cellCuts : constructor from cellLoops" << endl;
2797  }
2798 
2799  // Update pointIsCut, edgeIsCut, faceSplitCut from cell loops.
2800  // Makes sure cuts are consistent
2801  setFromCellLoops(cellLabels, cellLoops, cellEdgeWeights);
2802 
2803  // Calculate planes and flip cellLoops if necessary
2804  orientPlanesAndLoops();
2805 
2806  if (debug)
2807  {
2808  check();
2809  }
2810 
2811  clearOut();
2812 
2813  if (debug)
2814  {
2815  Pout<< "cellCuts : leaving constructor from cellLoops" << endl;
2816  }
2817 }
2818 
2819 
2820 // Construct from list of cells to cut and cell cutter.
2823  const polyMesh& mesh,
2824  const cellLooper& cellCutter,
2825  const List<refineCell>& refCells
2826 )
2827 :
2828  edgeVertex(mesh),
2829  pointIsCut_(mesh.nPoints(), false),
2830  edgeIsCut_(mesh.nEdges(), false),
2831  edgeWeight_(mesh.nEdges(), -GREAT),
2832  faceCutsPtr_(NULL),
2833  faceSplitCut_(refCells.size()),
2834  cellLoops_(mesh.nCells()),
2835  nLoops_(-1),
2836  cellAnchorPoints_(mesh.nCells())
2837 {
2838  if (debug)
2839  {
2840  Pout<< "cellCuts : constructor from cellCutter" << endl;
2841  }
2842 
2843  // Update pointIsCut, edgeIsCut, faceSplitCut from cell loops.
2844  // Makes sure cuts are consistent
2845  setFromCellCutter(cellCutter, refCells);
2846 
2847  // Calculate planes and flip cellLoops if necessary
2848  orientPlanesAndLoops();
2849 
2850  if (debug)
2851  {
2852  check();
2853  }
2854 
2855  clearOut();
2856 
2857  if (debug)
2858  {
2859  Pout<< "cellCuts : leaving constructor from cellCutter" << endl;
2860  }
2861 }
2862 
2863 
2864 // Construct from list of cells to cut, plane to cut with and cell cutter.
2867  const polyMesh& mesh,
2868  const cellLooper& cellCutter,
2869  const labelList& cellLabels,
2870  const List<plane>& cutPlanes
2871 )
2872 :
2873  edgeVertex(mesh),
2874  pointIsCut_(mesh.nPoints(), false),
2875  edgeIsCut_(mesh.nEdges(), false),
2876  edgeWeight_(mesh.nEdges(), -GREAT),
2877  faceCutsPtr_(NULL),
2878  faceSplitCut_(cellLabels.size()),
2879  cellLoops_(mesh.nCells()),
2880  nLoops_(-1),
2881  cellAnchorPoints_(mesh.nCells())
2882 {
2883  if (debug)
2884  {
2885  Pout<< "cellCuts : constructor from cellCutter with prescribed plane"
2886  << endl;
2887  }
2888 
2889  // Update pointIsCut, edgeIsCut, faceSplitCut from cell loops.
2890  // Makes sure cuts are consistent
2891  setFromCellCutter(cellCutter, cellLabels, cutPlanes);
2892 
2893  // Calculate planes and flip cellLoops if necessary
2894  orientPlanesAndLoops();
2895 
2896  if (debug)
2897  {
2898  check();
2899  }
2900 
2901  clearOut();
2902 
2903  if (debug)
2904  {
2905  Pout<< "cellCuts : leaving constructor from cellCutter with prescribed"
2906  << " plane" << endl;
2907  }
2908 }
2909 
2910 
2911 // Construct from components
2914  const polyMesh& mesh,
2915  const boolList& pointIsCut,
2916  const boolList& edgeIsCut,
2917  const scalarField& edgeWeight,
2918  const Map<edge>& faceSplitCut,
2919  const labelListList& cellLoops,
2920  const label nLoops,
2921  const labelListList& cellAnchorPoints
2922 )
2923 :
2924  edgeVertex(mesh),
2925  pointIsCut_(pointIsCut),
2926  edgeIsCut_(edgeIsCut),
2927  edgeWeight_(edgeWeight),
2928  faceCutsPtr_(NULL),
2929  faceSplitCut_(faceSplitCut),
2930  cellLoops_(cellLoops),
2931  nLoops_(nLoops),
2932  cellAnchorPoints_(cellAnchorPoints)
2933 {
2934  if (debug)
2935  {
2936  Pout<< "cellCuts : constructor from components" << endl;
2937  Pout<< "cellCuts : leaving constructor from components" << endl;
2938  }
2939 }
2940 
2941 
2942 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
2943 
2945 {
2946  clearOut();
2947 }
2948 
2949 
2951 {
2952  deleteDemandDrivenData(faceCutsPtr_);
2953 }
2954 
2955 
2956 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2957 
2959 {
2960  const labelList& loop = cellLoops_[cellI];
2961 
2962  pointField loopPts(loop.size());
2963 
2964  forAll(loop, fp)
2965  {
2966  label cut = loop[fp];
2967 
2968  if (isEdge(cut))
2969  {
2970  label edgeI = getEdge(cut);
2971 
2972  loopPts[fp] = coord(cut, edgeWeight_[edgeI]);
2973  }
2974  else
2975  {
2976  loopPts[fp] = coord(cut, -GREAT);
2977  }
2978  }
2979  return loopPts;
2980 }
2981 
2982 
2983 // Flip loop for cell
2984 void Foam::cellCuts::flip(const label cellI)
2985 {
2986  labelList& loop = cellLoops_[cellI];
2987 
2988  reverse(loop);
2989 
2990  // Reverse anchor point set.
2991  cellAnchorPoints_[cellI] =
2992  nonAnchorPoints
2993  (
2994  mesh().cellPoints()[cellI],
2995  cellAnchorPoints_[cellI],
2996  loop
2997  );
2998 }
2999 
3000 
3001 // Flip loop only
3003 {
3004  labelList& loop = cellLoops_[cellI];
3005 
3006  reverse(loop);
3007 }
3008 
3009 
3012  Ostream& os,
3013  const pointField& loopPts,
3014  label& vertI
3015 ) const
3016 {
3017  label startVertI = vertI;
3018 
3019  forAll(loopPts, fp)
3020  {
3021  const point& pt = loopPts[fp];
3022 
3023  os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
3024 
3025  vertI++;
3026  }
3027 
3028  os << 'f';
3029  forAll(loopPts, fp)
3030  {
3031  os << ' ' << startVertI + fp + 1;
3032  }
3033  os << endl;
3034 }
3035 
3036 
3038 {
3039  label vertI = 0;
3040 
3041  forAll(cellLoops_, cellI)
3042  {
3043  writeOBJ(os, loopPoints(cellI), vertI);
3044  }
3045 }
3046 
3047 
3048 void Foam::cellCuts::writeCellOBJ(const fileName& dir, const label cellI) const
3049 {
3050  const labelList& anchors = cellAnchorPoints_[cellI];
3051 
3052  writeOBJ(dir, cellI, loopPoints(cellI), anchors);
3053 }
3054 
3055 
3056 // ************************************************************************* //
Foam::cellCuts::flip
void flip(const label cellI)
Flip loop for cellI. Updates anchor points as well.
Definition: cellCuts.C:2984
Foam::cellCuts::edgeEdgeToFace
label edgeEdgeToFace(const label cellI, const label edgeA, const label edgeB) const
Find face on cell using the two edges.
Definition: cellCuts.C:228
Foam::cellCuts::loopWeights
scalarField loopWeights(const labelList &loop) const
Returns weights of loop. Inverse of loopPoints.
Definition: cellCuts.C:1616
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
meshTools.H
Foam::cellCuts::faceCutsPtr_
labelListList * faceCutsPtr_
Cuts per existing face (includes those along edge of face)
Definition: cellCuts.H:130
w
volScalarField w(IOobject("w", runTime.timeName(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE), mesh, dimensionedScalar("w", dimensionSet(0, 0, 0, 0, 0, 0, 0), 0.0))
Foam::cellCuts::calcLoopsAndAddressing
void calcLoopsAndAddressing(const labelList &cutCells)
Top level driver: adressing calculation and loop detection.
Definition: cellCuts.C:2497
Foam::Vector< scalar >::zero
static const Vector zero
Definition: Vector.H:80
Foam::cellCuts::vertexVertexToFace
label vertexVertexToFace(const label cellI, const label vertA, const label vertB) const
Find face using two vertices (guaranteed not to be along edge)
Definition: cellCuts.C:309
Foam::cellCuts::edgeIsCut_
boolList edgeIsCut_
Is edge cut.
Definition: cellCuts.H:120
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::cellCuts::calcFaceCuts
void calcFaceCuts() const
Calculate faceCuts in face vertex order.
Definition: cellCuts.C:344
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
writeOBJ
void writeOBJ(Ostream &os, label &vertI, const tetPoints &tet)
Definition: Test-tetTetOverlap.C:38
Foam::primitiveMesh::cellPoints
const labelListList & cellPoints() const
Definition: primitiveMeshCellPoints.C:31
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::DynamicList< label >
Foam::cellCuts::writeOBJ
void writeOBJ(const fileName &dir, const label cellI, const pointField &loopPoints, const labelList &anchors) const
Debugging: write cell's edges, loop and anchors to directory.
Definition: cellCuts.C:179
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:31
Foam::cellCuts::walkCell
bool walkCell(const label cellI, const label startCut, const label faceI, const label prevCut, label &nVisited, labelList &visited) const
Walk across cuts (cut edges or cut vertices) of cell. Stops when.
Definition: cellCuts.C:793
cellLooper.H
Foam::meshTools::edgeOnCell
bool edgeOnCell(const primitiveMesh &, const label cellI, const label edgeI)
Is edge used by cell.
Definition: meshTools.C:285
Foam::HashTable::const_iterator
An STL-conforming const_iterator.
Definition: HashTable.H:470
Foam::primitiveMesh::pointFaces
const labelListList & pointFaces() const
Definition: primitiveMeshPointFaces.C:32
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:136
Foam::cellCuts::pointIsCut_
boolList pointIsCut_
Is mesh point cut.
Definition: cellCuts.H:117
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::cellCuts::cellCuts
cellCuts(const cellCuts &)
Disallow default bitwise copy construct.
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::edgeVertex
Combines edge or vertex in single label. Used to specify cuts across cell circumference.
Definition: edgeVertex.H:52
Foam::Map< label >
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:353
Foam::cellCuts::writeCellOBJ
void writeCellOBJ(const fileName &dir, const label cellI) const
debugging:Write edges of cell and loop
Definition: cellCuts.C:3048
geomCellLooper.H
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::primitiveMesh::pointEdges
const labelListList & pointEdges() const
Definition: primitiveMeshPointEdges.C:96
polyMesh.H
Foam::HashSet< label, Hash< label > >
Foam::cellLooper::cut
virtual bool cut(const vector &refDir, const label cellI, const boolList &vertIsCut, const boolList &edgeIsCut, const scalarField &edgeWeight, labelList &loop, scalarField &loopWeights) const =0
Create cut along circumference of cellI. Gets current mesh cuts.
Foam::primitiveMesh::nEdges
label nEdges() const
Definition: primitiveMeshI.H:41
Foam::cellCuts::~cellCuts
~cellCuts()
Destructor.
Definition: cellCuts.C:2944
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::meshTools::faceOnCell
bool faceOnCell(const primitiveMesh &, const label cellI, const label faceI)
Is face used by cell.
Definition: meshTools.C:307
Foam::cellCuts::firstUnique
static label firstUnique(const labelList &lst, const Map< label > &)
Returns -1 or index of first element of lst that cannot be found.
Definition: cellCuts.C:101
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
OFstream.H
Foam::edgeVertex::edgeToEVert
static label edgeToEVert(const primitiveMesh &mesh, const label edgeI)
Convert edgeI to eVert.
Definition: edgeVertex.H:174
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("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
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::edge::end
label end() const
Return end vertex label.
Definition: edgeI.H:92
Foam::primitiveMesh::nCells
label nCells() const
Definition: primitiveMeshI.H:64
Foam::geomCellLooper::snapTol
static scalar snapTol()
Definition: geomCellLooper.H:129
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:40
Foam::primitiveMesh::nPoints
label nPoints() const
Definition: primitiveMeshI.H:35
Foam::labelMin
static const label labelMin
Definition: label.H:61
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:59
Foam::meshTools::findEdge
label findEdge(const edgeList &edges, const labelList &candidates, const label v0, const label v1)
Return edge among candidates that uses the two vertices.
Definition: meshTools.C:336
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
plane.H
Foam::primitiveMesh::cellEdges
const labelListList & cellEdges() const
Definition: primitiveMeshCellEdges.C:118
Foam::cellCuts::faceCuts
const labelListList & faceCuts() const
Cuts per existing face (includes those along edge of face)
Definition: cellCuts.H:553
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:242
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1017
Foam::primitiveMesh::faceEdges
const labelListList & faceEdges() const
Definition: primitiveMeshEdges.C:366
f1
scalar f1
Definition: createFields.H:28
Foam::cellLooper
Abstract base class. Concrete implementations know how to cut a cell (i.e. determine a loop around th...
Definition: cellLooper.H:69
Foam::cellCuts::calcCellLoops
void calcCellLoops(const labelList &cutCells)
Determine for every cut cell the face it is cut by.
Definition: cellCuts.C:990
Foam::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
Foam::cellCuts::loopFace
label loopFace(const label cellI, const labelList &loop) const
Find face on which all cuts are (very rare) or -1.
Definition: cellCuts.C:512
Foam::meshTools::walkFace
label walkFace(const primitiveMesh &, const label faceI, const label startEdgeI, const label startVertI, const label nEdges)
Returns label of edge nEdges away from startEdge (in the direction.
Definition: meshTools.C:580
refineCell.H
cut
Patchify triangles based on orientation w.r.t other (triangulated or triangulatable) surfaces.
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
cellCuts.H
Foam::Vector::x
const Cmpt & x() const
Definition: VectorI.H:65
Foam::refineCell::direction
const vector & direction() const
Definition: refineCell.H:83
Foam::FatalError
error FatalError
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::cellCuts::conservativeValidLoop
bool conservativeValidLoop(const label cellI, const labelList &loop) const
Determines if loop through cellI consistent with existing.
Definition: cellCuts.C:1729
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::cellCuts::nonAnchorPoints
labelList nonAnchorPoints(const labelList &cellPoints, const labelList &anchorPoints, const labelList &loop) const
Invert anchor point selection.
Definition: cellCuts.C:1183
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::Vector::z
const Cmpt & z() const
Definition: VectorI.H:77
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::cellCuts::validEdgeLoop
bool validEdgeLoop(const labelList &loop, const scalarField &loopWeights) const
Check if cut edges in loop are compatible with ones in.
Definition: cellCuts.C:1641
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::meshTools::getEdgeFaces
void getEdgeFaces(const primitiveMesh &, const label cellI, const label edgeI, label &face0, label &face1)
Get faces on cell using edgeI. Throws error if no two found.
Definition: meshTools.C:456
Foam::cellCuts::validLoop
bool validLoop(const label cellI, const labelList &loop, const scalarField &loopWeights, Map< edge > &newFaceSplitCut, labelList &anchorPoints) const
Check if loop is compatible with existing cut pattern in.
Definition: cellCuts.C:1824
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::cellCuts::crossEdge
bool crossEdge(const label cellI, const label startCut, const label faceI, const label otherCut, label &nVisited, labelList &visited) const
Cross cut (which is edge on faceI) onto next face.
Definition: cellCuts.C:620
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Foam::cellCuts::expand
static boolList expand(const label size, const labelList &labels)
Create boolList with all labels specified set to true.
Definition: cellCuts.C:67
Foam::refineCell
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:52
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::cellCuts::setFromCellLoops
void setFromCellLoops()
Update basic cut information from cellLoops. Assumes cellLoops_.
Definition: cellCuts.C:1990
Foam::primitiveMesh::nFaces
label nFaces() const
Definition: primitiveMeshI.H:58
Foam::cellCuts::loopAnchorConsistent
bool loopAnchorConsistent(const label cellI, const pointField &loopPts, const labelList &anchorPoints) const
Check anchor points on 'outside' of loop.
Definition: cellCuts.C:1214
Foam::edge::start
label start() const
Return start vertex label.
Definition: edgeI.H:81
Foam::cellCuts::writeUncutOBJ
void writeUncutOBJ(const fileName &, const label cellI) const
Debugging: write cell's edges and any cut vertices and edges.
Definition: cellCuts.C:121
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
f
labelList f(nPoints)
Foam::cellCuts::flipLoopOnly
void flipLoopOnly(const label cellI)
Flip loop for cellI. Does not update anchors. Use with care.
Definition: cellCuts.C:3002
Foam::meshTools::otherFace
label otherFace(const primitiveMesh &, const label cellI, const label faceI, const label edgeI)
Return face on cell using edgeI but not faceI. Throws error.
Definition: meshTools.C:532
Foam::Vector< scalar >
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::cellCuts::walkFace
bool walkFace(const label cellI, const label startCut, const label faceI, const label cut, label &lastCut, label &beforeLastCut, label &nVisited, labelList &visited) const
Walk across faceI following cuts, starting at cut. Stores cuts.
Definition: cellCuts.C:701
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::cellCuts::check
void check() const
Check various consistencies.
Definition: cellCuts.C:2547
Foam::cellCuts::countFaceCuts
label countFaceCuts(const label faceI, const labelList &loop) const
Counts number of cuts on face.
Definition: cellCuts.C:1679
Foam::cellCuts::findPartIndex
static label findPartIndex(const labelList &, const label n, const label val)
Find value in first n elements of list.
Definition: cellCuts.C:49
Foam::refineCell::cellNo
label cellNo() const
Definition: refineCell.H:78
Foam::Vector::y
const Cmpt & y() const
Definition: VectorI.H:71
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::cellCuts::findEdge
label findEdge(const label faceI, const label v0, const label v1) const
Find edge (or -1) on faceI using vertices v0,v1.
Definition: cellCuts.C:482
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
ListOps.H
Various functions to operate on Lists.
Foam::OFstream::name
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
Foam::cellCuts::clearOut
void clearOut()
Clear out demand driven storage.
Definition: cellCuts.C:2950
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:53
Foam::cellCuts::walkPoint
bool walkPoint(const label cellI, const label startCut, const label exclude0, const label exclude1, const label otherCut, label &nVisited, labelList &visited) const
Cross otherCut into next faces (not exclude0, exclude1)
Definition: cellCuts.C:564
Foam::cellCuts::orientPlanesAndLoops
void orientPlanesAndLoops()
Set orientation of loops.
Definition: cellCuts.C:2440
Foam::cellCuts::loopPoints
pointField loopPoints(const labelList &loop, const scalarField &loopWeights) const
Returns coordinates of points on loop with explicitly provided.
Definition: cellCuts.C:1600
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:259
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::cellCuts::setFromCellCutter
void setFromCellCutter(const cellLooper &, const List< refineCell > &refCells)
Cut cells and update basic cut information from cellLoops.
Definition: cellCuts.C:2213
Foam::cellCuts::setFromCellLoop
bool setFromCellLoop(const label cellI, const labelList &loop, const scalarField &loopWeights)
Update basic cut information for single cell from cellLoop.
Definition: cellCuts.C:2077
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1023
Foam::cellCuts::calcAnchors
bool calcAnchors(const label cellI, const labelList &loop, const pointField &loopPts, labelList &anchorPoints) const
Determines set of anchor points given a loop. The loop should.
Definition: cellCuts.C:1253
Foam::stringOps::expand
string expand(const string &, const HashTable< string, word, string::hash > &mapping, const char sigil='$')
Expand occurences of variables according to the mapping.
Definition: stringOps.C:74
normal
A normal distribution model.
Foam::cellCuts::edgeVertexToFace
label edgeVertexToFace(const label cellI, const label edgeI, const label vertI) const
Find face on cell using an edge and a vertex.
Definition: cellCuts.C:269
Foam::cellCuts::addCut
bool addCut(const label cellI, const label cut, label &nVisited, labelList &visited) const
Definition: cellCuts.C:665
Foam::cellCuts::walkEdges
void walkEdges(const label cellI, const label pointI, const label status, Map< label > &edgeStatus, Map< label > &pointStatus) const
Walk unset edges of single cell from starting point and.
Definition: cellCuts.C:1145
Foam::edgeVertex::vertToEVert
static label vertToEVert(const primitiveMesh &mesh, const label vertI)
Convert pointI to eVert.
Definition: edgeVertex.H:158
Foam::labelI
static const labelSphericalTensor labelI(1)
Identity labelTensor.
Foam::edgeVertex::mesh
const polyMesh & mesh() const
Definition: edgeVertex.H:98
Foam::reverse
void reverse(UList< T > &, const label n)
Definition: UListI.H:322