meshCutAndRemove.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 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 "meshCutAndRemove.H"
30 #include "polyMesh.H"
31 #include "polyTopoChange.H"
32 #include "polyAddFace.H"
33 #include "polyAddPoint.H"
34 #include "polyRemovePoint.H"
35 #include "polyRemoveFace.H"
36 #include "polyModifyFace.H"
37 #include "cellCuts.H"
38 #include "mapPolyMesh.H"
39 #include "meshTools.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(meshCutAndRemove, 0);
46 }
47 
48 
49 // * * * * * * * * * * * * * Private Static Functions * * * * * * * * * * * //
50 
51 // Returns -1 or index in elems1 of first shared element.
52 Foam::label Foam::meshCutAndRemove::firstCommon
53 (
54  const labelList& elems1,
55  const labelList& elems2
56 )
57 {
58  forAll(elems1, elemI)
59  {
60  label index1 = elems2.find(elems1[elemI]);
61 
62  if (index1 != -1)
63  {
64  return index1;
65  }
66  }
67  return -1;
68 }
69 
70 
71 // Check if twoCuts at two consecutive position in cuts.
72 bool Foam::meshCutAndRemove::isIn
73 (
74  const edge& twoCuts,
75  const labelList& cuts
76 )
77 {
78  label index = cuts.find(twoCuts[0]);
79 
80  if (index == -1)
81  {
82  return false;
83  }
84 
85  return
86  (
87  cuts[cuts.fcIndex(index)] == twoCuts[1]
88  || cuts[cuts.rcIndex(index)] == twoCuts[1]
89  );
90 }
91 
92 
93 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
94 
95 Foam::label Foam::meshCutAndRemove::findCutCell
96 (
97  const cellCuts& cuts,
98  const labelList& cellLabels
99 ) const
100 {
101  forAll(cellLabels, labelI)
102  {
103  label celli = cellLabels[labelI];
104 
105  if (cuts.cellLoops()[celli].size())
106  {
107  return celli;
108  }
109  }
110  return -1;
111 }
112 
113 
114 Foam::label Foam::meshCutAndRemove::findInternalFacePoint
115 (
116  const labelList& pointLabels
117 ) const
118 {
120  {
121  label pointi = pointLabels[labelI];
122 
123  const labelList& pFaces = mesh().pointFaces()[pointi];
124 
125  forAll(pFaces, pFacei)
126  {
127  label facei = pFaces[pFacei];
128 
129  if (mesh().isInternalFace(facei))
130  {
131  return pointi;
132  }
133  }
134  }
135 
136  if (pointLabels.empty())
137  {
139  << "Empty pointLabels" << abort(FatalError);
140  }
141 
142  return -1;
143 }
144 
145 
146 Foam::label Foam::meshCutAndRemove::findPatchFacePoint
147 (
148  const face& f,
149  const label exposedPatchi
150 ) const
151 {
152  const labelListList& pointFaces = mesh().pointFaces();
153  const polyBoundaryMesh& patches = mesh().boundaryMesh();
154 
155  forAll(f, fp)
156  {
157  label pointi = f[fp];
158 
159  if (pointi < mesh().nPoints())
160  {
161  const labelList& pFaces = pointFaces[pointi];
162 
163  forAll(pFaces, i)
164  {
165  if (patches.whichPatch(pFaces[i]) == exposedPatchi)
166  {
167  return pointi;
168  }
169  }
170  }
171  }
172  return -1;
173 }
174 
175 
176 void Foam::meshCutAndRemove::faceCells
177 (
178  const cellCuts& cuts,
179  const label exposedPatchi,
180  const label facei,
181  label& own,
182  label& nei,
183  label& patchID
184 ) const
185 {
186  const labelListList& anchorPts = cuts.cellAnchorPoints();
187  const labelListList& cellLoops = cuts.cellLoops();
188 
189  const face& f = mesh().faces()[facei];
190 
191  own = mesh().faceOwner()[facei];
192 
193  if (cellLoops[own].size() && firstCommon(f, anchorPts[own]) == -1)
194  {
195  // owner has been split and this is the removed part.
196  own = -1;
197  }
198 
199  nei = -1;
200 
201  if (mesh().isInternalFace(facei))
202  {
203  nei = mesh().faceNeighbour()[facei];
204 
205  if (cellLoops[nei].size() && firstCommon(f, anchorPts[nei]) == -1)
206  {
207  nei = -1;
208  }
209  }
210 
211  patchID = mesh().boundaryMesh().whichPatch(facei);
212 
213  if (patchID == -1 && (own == -1 || nei == -1))
214  {
215  // Face was internal but becomes external
216  patchID = exposedPatchi;
217  }
218 }
219 
220 
221 void Foam::meshCutAndRemove::getZoneInfo
222 (
223  const label facei,
224  label& zoneID,
225  bool& zoneFlip
226 ) const
227 {
228  zoneID = mesh().faceZones().whichZone(facei);
229 
230  zoneFlip = false;
231 
232  if (zoneID >= 0)
233  {
234  const faceZone& fZone = mesh().faceZones()[zoneID];
235 
236  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
237  }
238 }
239 
240 
241 void Foam::meshCutAndRemove::addFace
242 (
243  polyTopoChange& meshMod,
244  const label facei,
245  const label masterPointi,
246  const face& newFace,
247  const label own,
248  const label nei,
249  const label patchID
250 )
251 {
252  label zoneID;
253  bool zoneFlip;
254 
255  getZoneInfo(facei, zoneID, zoneFlip);
256 
257  if ((nei == -1) || (own != -1 && own < nei))
258  {
259  // Ordering ok.
260  if (debug & 2)
261  {
262  Pout<< "Adding face " << newFace
263  << " with new owner:" << own
264  << " with new neighbour:" << nei
265  << " patchID:" << patchID
266  << " anchor:" << masterPointi
267  << " zoneID:" << zoneID
268  << " zoneFlip:" << zoneFlip
269  << endl;
270  }
271 
272  meshMod.setAction
273  (
274  polyAddFace
275  (
276  newFace, // face
277  own, // owner
278  nei, // neighbour
279  masterPointi, // master point
280  -1, // master edge
281  -1, // master face for addition
282  false, // flux flip
283  patchID, // patch for face
284  zoneID, // zone for face
285  zoneFlip // face zone flip
286  )
287  );
288  }
289  else
290  {
291  // Reverse owner/neighbour
292  if (debug & 2)
293  {
294  Pout<< "Adding (reversed) face " << newFace.reverseFace()
295  << " with new owner:" << nei
296  << " with new neighbour:" << own
297  << " patchID:" << patchID
298  << " anchor:" << masterPointi
299  << " zoneID:" << zoneID
300  << " zoneFlip:" << zoneFlip
301  << endl;
302  }
303 
304  meshMod.setAction
305  (
306  polyAddFace
307  (
308  newFace.reverseFace(), // face
309  nei, // owner
310  own, // neighbour
311  masterPointi, // master point
312  -1, // master edge
313  -1, // master face for addition
314  false, // flux flip
315  patchID, // patch for face
316  zoneID, // zone for face
317  zoneFlip // face zone flip
318  )
319  );
320  }
321 }
322 
323 
324 // Modifies existing facei for either new owner/neighbour or new face points.
325 void Foam::meshCutAndRemove::modFace
326 (
327  polyTopoChange& meshMod,
328  const label facei,
329  const face& newFace,
330  const label own,
331  const label nei,
332  const label patchID
333 )
334 {
335  label zoneID;
336  bool zoneFlip;
337 
338  getZoneInfo(facei, zoneID, zoneFlip);
339 
340  if
341  (
342  (own != mesh().faceOwner()[facei])
343  || (
344  mesh().isInternalFace(facei)
345  && (nei != mesh().faceNeighbour()[facei])
346  )
347  || (newFace != mesh().faces()[facei])
348  )
349  {
350  if (debug & 2)
351  {
352  Pout<< "Modifying face " << facei
353  << " old vertices:" << mesh().faces()[facei]
354  << " new vertices:" << newFace
355  << " new owner:" << own
356  << " new neighbour:" << nei
357  << " new patch:" << patchID
358  << " new zoneID:" << zoneID
359  << " new zoneFlip:" << zoneFlip
360  << endl;
361  }
362 
363  if ((nei == -1) || (own != -1 && own < nei))
364  {
365  meshMod.setAction
366  (
367  polyModifyFace
368  (
369  newFace, // modified face
370  facei, // label of face being modified
371  own, // owner
372  nei, // neighbour
373  false, // face flip
374  patchID, // patch for face
375  false, // remove from zone
376  zoneID, // zone for face
377  zoneFlip // face flip in zone
378  )
379  );
380  }
381  else
382  {
383  meshMod.setAction
384  (
385  polyModifyFace
386  (
387  newFace.reverseFace(), // modified face
388  facei, // label of face being modified
389  nei, // owner
390  own, // neighbour
391  false, // face flip
392  patchID, // patch for face
393  false, // remove from zone
394  zoneID, // zone for face
395  zoneFlip // face flip in zone
396  )
397  );
398  }
399  }
400 }
401 
402 
403 void Foam::meshCutAndRemove::copyFace
404 (
405  const face& f,
406  const label startFp,
407  const label endFp,
408  face& newFace
409 ) const
410 {
411  label fp = startFp;
412 
413  label newFp = 0;
414 
415  while (fp != endFp)
416  {
417  newFace[newFp++] = f[fp];
418 
419  fp = (fp + 1) % f.size();
420  }
421  newFace[newFp] = f[fp];
422 }
423 
424 
425 // Actually split face in two along splitEdge v0, v1 (the two vertices in new
426 // vertex numbering). Generates faces in same ordering
427 // as original face. Replaces cutEdges by the points introduced on them
428 // (addedPoints_).
429 void Foam::meshCutAndRemove::splitFace
430 (
431  const face& f,
432  const label v0,
433  const label v1,
434 
435  face& f0,
436  face& f1
437 ) const
438 {
439  // Check if we find any new vertex which is part of the splitEdge.
440  label startFp = f.find(v0);
441 
442  if (startFp == -1)
443  {
445  << "Cannot find vertex (new numbering) " << v0
446  << " on face " << f
447  << abort(FatalError);
448  }
449 
450  label endFp = f.find(v1);
451 
452  if (endFp == -1)
453  {
455  << "Cannot find vertex (new numbering) " << v1
456  << " on face " << f
457  << abort(FatalError);
458  }
459 
460 
461  f0.setSize((endFp + 1 + f.size() - startFp) % f.size());
462  f1.setSize(f.size() - f0.size() + 2);
463 
464  copyFace(f, startFp, endFp, f0);
465  copyFace(f, endFp, startFp, f1);
466 }
467 
468 
469 Foam::face Foam::meshCutAndRemove::addEdgeCutsToFace(const label facei) const
470 {
471  const face& f = mesh().faces()[facei];
472 
473  face newFace(2 * f.size());
474 
475  label newFp = 0;
476 
477  forAll(f, fp)
478  {
479  // Duplicate face vertex.
480  newFace[newFp++] = f[fp];
481 
482  // Check if edge has been cut.
483  label fp1 = f.fcIndex(fp);
484 
485  EdgeMap<label>::const_iterator fnd =
486  addedPoints_.find(edge(f[fp], f[fp1]));
487 
488  if (fnd.found())
489  {
490  // edge has been cut. Introduce new vertex.
491  newFace[newFp++] = fnd.val();
492  }
493  }
494 
495  newFace.setSize(newFp);
496 
497  return newFace;
498 }
499 
500 
501 // Walk loop (loop of cuts) across circumference of celli. Returns face in
502 // new vertices.
503 // Note: tricky bit is that it can use existing edges which have been split.
504 Foam::face Foam::meshCutAndRemove::loopToFace
505 (
506  const label celli,
507  const labelList& loop
508 ) const
509 {
510  face newFace(2*loop.size());
511 
512  label newFacei = 0;
513 
514  forAll(loop, fp)
515  {
516  label cut = loop[fp];
517 
518  if (isEdge(cut))
519  {
520  label edgeI = getEdge(cut);
521 
522  const edge& e = mesh().edges()[edgeI];
523 
524  label vertI = addedPoints_[e];
525 
526  newFace[newFacei++] = vertI;
527  }
528  else
529  {
530  // cut is vertex.
531  label vertI = getVertex(cut);
532 
533  newFace[newFacei++] = vertI;
534 
535  label nextCut = loop[loop.fcIndex(fp)];
536 
537  if (!isEdge(nextCut))
538  {
539  // From vertex to vertex -> cross cut only if no existing edge.
540  label nextVertI = getVertex(nextCut);
541 
542  label edgeI = meshTools::findEdge(mesh(), vertI, nextVertI);
543 
544  if (edgeI != -1)
545  {
546  // Existing edge. Insert split-edge point if any.
547  EdgeMap<label>::const_iterator fnd =
548  addedPoints_.find(mesh().edges()[edgeI]);
549 
550  if (fnd.found())
551  {
552  newFace[newFacei++] = fnd.val();
553  }
554  }
555  }
556  }
557  }
558  newFace.setSize(newFacei);
559 
560  return newFace;
561 }
562 
563 
564 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
565 
566 // Construct from components
567 Foam::meshCutAndRemove::meshCutAndRemove(const polyMesh& mesh)
568 :
569  edgeVertex(mesh),
570  addedFaces_(),
571  addedPoints_()
572 {}
573 
574 
575 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
576 
578 (
579  const label exposedPatchi,
580  const cellCuts& cuts,
581  const labelList& cutPatch,
582  polyTopoChange& meshMod
583 )
584 {
585  // Clear and size maps here since mesh size will change.
586  addedFaces_.clear();
587  addedFaces_.resize(cuts.nLoops());
588 
589  addedPoints_.clear();
590  addedPoints_.resize(cuts.nLoops());
591 
592  if (cuts.nLoops() == 0)
593  {
594  return;
595  }
596 
597  const labelListList& anchorPts = cuts.cellAnchorPoints();
598  const labelListList& cellLoops = cuts.cellLoops();
600 
601  if (exposedPatchi < 0 || exposedPatchi >= patches.size())
602  {
604  << "Illegal exposed patch " << exposedPatchi
605  << abort(FatalError);
606  }
607 
608 
609  //
610  // Add new points along cut edges.
611  //
612 
613  forAll(cuts.edgeIsCut(), edgeI)
614  {
615  if (cuts.edgeIsCut()[edgeI])
616  {
617  const edge& e = mesh().edges()[edgeI];
618 
619  // Check if there is any cell using this edge.
620  if (debug && findCutCell(cuts, mesh().edgeCells()[edgeI]) == -1)
621  {
623  << "Problem: cut edge but none of the cells using it is\n"
624  << "edge:" << edgeI << " verts:" << e
625  << abort(FatalError);
626  }
627 
628  // One of the edge end points should be master point of nbCelli.
629  label masterPointi = e.start();
630 
631  const point& v0 = mesh().points()[e.start()];
632  const point& v1 = mesh().points()[e.end()];
633 
634  scalar weight = cuts.edgeWeight()[edgeI];
635 
636  point newPt = weight*v1 + (1.0-weight)*v0;
637 
638  label addedPointi =
639  meshMod.setAction
640  (
642  (
643  newPt, // point
644  masterPointi, // master point
645  -1, // zone for point
646  true // supports a cell
647  )
648  );
649 
650  // Store on (hash of) edge.
651  addedPoints_.insert(e, addedPointi);
652 
653  if (debug & 2)
654  {
655  Pout<< "Added point " << addedPointi
656  << " to vertex "
657  << masterPointi << " of edge " << edgeI
658  << " vertices " << e << endl;
659  }
660  }
661  }
662 
663 
664  //
665  // Remove all points that will not be used anymore
666  //
667  {
668  boolList usedPoint(mesh().nPoints(), false);
669 
670  forAll(cellLoops, celli)
671  {
672  const labelList& loop = cellLoops[celli];
673 
674  if (loop.size())
675  {
676  // Cell is cut. Uses only anchor points and loop itself.
677  forAll(loop, fp)
678  {
679  label cut = loop[fp];
680 
681  if (!isEdge(cut))
682  {
683  usedPoint[getVertex(cut)] = true;
684  }
685  }
686 
687  const labelList& anchors = anchorPts[celli];
688 
689  forAll(anchors, i)
690  {
691  usedPoint[anchors[i]] = true;
692  }
693  }
694  else
695  {
696  // Cell is not cut so use all its points
697  const labelList& cPoints = mesh().cellPoints()[celli];
698 
699  forAll(cPoints, i)
700  {
701  usedPoint[cPoints[i]] = true;
702  }
703  }
704  }
705 
706 
707  // Check
708  const Map<edge>& faceSplitCut = cuts.faceSplitCut();
709 
710  forAllConstIters(faceSplitCut, iter)
711  {
712  const edge& fCut = iter.val();
713 
714  forAll(fCut, i)
715  {
716  label cut = fCut[i];
717 
718  if (!isEdge(cut))
719  {
720  label pointi = getVertex(cut);
721 
722  if (!usedPoint[pointi])
723  {
725  << "Problem: faceSplitCut not used by any loop"
726  << " or cell anchor point"
727  << "face:" << iter.key() << " point:" << pointi
728  << " coord:" << mesh().points()[pointi]
729  << abort(FatalError);
730  }
731  }
732  }
733  }
734 
735  forAll(cuts.pointIsCut(), pointi)
736  {
737  if (cuts.pointIsCut()[pointi])
738  {
739  if (!usedPoint[pointi])
740  {
742  << "Problem: point is marked as cut but"
743  << " not used by any loop"
744  << " or cell anchor point"
745  << "point:" << pointi
746  << " coord:" << mesh().points()[pointi]
747  << abort(FatalError);
748  }
749  }
750  }
751 
752 
753  // Remove unused points.
754  forAll(usedPoint, pointi)
755  {
756  if (!usedPoint[pointi])
757  {
758  meshMod.setAction(polyRemovePoint(pointi));
759 
760  if (debug & 2)
761  {
762  Pout<< "Removing unused point " << pointi << endl;
763  }
764  }
765  }
766  }
767 
768 
769  //
770  // For all cut cells add an internal or external face
771  //
772 
773  forAll(cellLoops, celli)
774  {
775  const labelList& loop = cellLoops[celli];
776 
777  if (loop.size())
778  {
779  if (cutPatch[celli] < 0 || cutPatch[celli] >= patches.size())
780  {
782  << "Illegal patch " << cutPatch[celli]
783  << " provided for cut cell " << celli
784  << abort(FatalError);
785  }
786 
787  //
788  // Convert loop (=list of cuts) into proper face.
789  // cellCuts sets orientation is towards anchor side so reverse.
790  //
791  face newFace(loopToFace(celli, loop));
792 
793  reverse(newFace);
794 
795  // Pick any anchor point on cell
796  label masterPointi = findPatchFacePoint(newFace, exposedPatchi);
797 
798  label addedFacei =
799  meshMod.setAction
800  (
802  (
803  newFace, // face
804  celli, // owner
805  -1, // neighbour
806  masterPointi, // master point
807  -1, // master edge
808  -1, // master face for addition
809  false, // flux flip
810  cutPatch[celli], // patch for face
811  -1, // zone for face
812  false // face zone flip
813  )
814  );
815 
816  addedFaces_.insert(celli, addedFacei);
817 
818  if (debug & 2)
819  {
820  Pout<< "Added splitting face " << newFace << " index:"
821  << addedFacei << " from masterPoint:" << masterPointi
822  << " to owner " << celli << " with anchors:"
823  << anchorPts[celli]
824  << " from Loop:";
825 
826  // Gets edgeweights of loop
827  scalarField weights(loop.size());
828  forAll(loop, i)
829  {
830  label cut = loop[i];
831 
832  weights[i] =
833  (
834  isEdge(cut)
835  ? cuts.edgeWeight()[getEdge(cut)]
836  : -GREAT
837  );
838  }
839  writeCuts(Pout, loop, weights);
840  Pout<< endl;
841  }
842  }
843  }
844 
845 
846  //
847  // Modify faces to use only anchorpoints and loop points
848  // (so throw away part without anchorpoints)
849  //
850 
851 
852  // Maintain whether face has been updated (for -split edges
853  // -new owner/neighbour)
854  boolList faceUptodate(mesh().nFaces(), false);
855 
856  const Map<edge>& faceSplitCuts = cuts.faceSplitCut();
857 
858  forAllConstIters(faceSplitCuts, iter)
859  {
860  const label facei = iter.key();
861 
862  const edge& splitEdge = iter.val();
863 
864  // Renumber face to include split edges.
865  face newFace(addEdgeCutsToFace(facei));
866 
867  // Edge splitting the face. Convert edge to new vertex numbering.
868  label cut0 = splitEdge[0];
869 
870  label v0;
871  if (isEdge(cut0))
872  {
873  label edgeI = getEdge(cut0);
874  v0 = addedPoints_[mesh().edges()[edgeI]];
875  }
876  else
877  {
878  v0 = getVertex(cut0);
879  }
880 
881  label cut1 = splitEdge[1];
882  label v1;
883  if (isEdge(cut1))
884  {
885  label edgeI = getEdge(cut1);
886  v1 = addedPoints_[mesh().edges()[edgeI]];
887  }
888  else
889  {
890  v1 = getVertex(cut1);
891  }
892 
893  // Split face along the elements of the splitEdge.
894  face f0, f1;
895  splitFace(newFace, v0, v1, f0, f1);
896 
897  label own = mesh().faceOwner()[facei];
898 
899  label nei = -1;
900 
901  if (mesh().isInternalFace(facei))
902  {
903  nei = mesh().faceNeighbour()[facei];
904  }
905 
906  if (debug & 2)
907  {
908  Pout<< "Split face " << mesh().faces()[facei]
909  << " own:" << own << " nei:" << nei
910  << " into f0:" << f0
911  << " and f1:" << f1 << endl;
912  }
913 
914 
915  // Check which cell using face uses anchorPoints (so is kept)
916  // and which one doesn't (gets removed)
917 
918  // Bit tricky. We have to know whether this faceSplit splits owner/
919  // neighbour or both. Even if cell is cut we have to make sure this is
920  // the one that cuts it (this face cut might not be the one splitting
921  // the cell)
922  // The face f gets split into two parts, f0 and f1.
923  // Each of these can have a different owner and or neighbour.
924 
925  const face& f = mesh().faces()[facei];
926 
927  label f0Own = -1;
928  label f1Own = -1;
929 
930  if (cellLoops[own].empty())
931  {
932  // Owner side is not split so keep both halves.
933  f0Own = own;
934  f1Own = own;
935  }
936  else if (isIn(splitEdge, cellLoops[own]))
937  {
938  // Owner is cut by this splitCut. See which of f0, f1 gets
939  // preserved and becomes owner, and which gets removed.
940  if (firstCommon(f0, anchorPts[own]) != -1)
941  {
942  // f0 preserved so f1 gets deleted
943  f0Own = own;
944  f1Own = -1;
945  }
946  else
947  {
948  f0Own = -1;
949  f1Own = own;
950  }
951  }
952  else
953  {
954  // Owner not cut by this splitCut but by another.
955  // Check on original face whether
956  // use anchorPts.
957  if (firstCommon(f, anchorPts[own]) != -1)
958  {
959  // both f0 and f1 owner side preserved
960  f0Own = own;
961  f1Own = own;
962  }
963  else
964  {
965  // both f0 and f1 owner side removed
966  f0Own = -1;
967  f1Own = -1;
968  }
969  }
970 
971 
972  label f0Nei = -1;
973  label f1Nei = -1;
974 
975  if (nei != -1)
976  {
977  if (cellLoops[nei].empty())
978  {
979  f0Nei = nei;
980  f1Nei = nei;
981  }
982  else if (isIn(splitEdge, cellLoops[nei]))
983  {
984  // Neighbour is cut by this splitCut. So anchor part of it
985  // gets kept, non-anchor bit gets removed. See which of f0, f1
986  // connects to which part.
987 
988  if (firstCommon(f0, anchorPts[nei]) != -1)
989  {
990  f0Nei = nei;
991  f1Nei = -1;
992  }
993  else
994  {
995  f0Nei = -1;
996  f1Nei = nei;
997  }
998  }
999  else
1000  {
1001  // neighbour not cut by this splitCut. Check on original face
1002  // whether use anchorPts.
1003 
1004  if (firstCommon(f, anchorPts[nei]) != -1)
1005  {
1006  f0Nei = nei;
1007  f1Nei = nei;
1008  }
1009  else
1010  {
1011  // both f0 and f1 on neighbour side removed
1012  f0Nei = -1;
1013  f1Nei = -1;
1014  }
1015  }
1016  }
1017 
1018 
1019  if (debug & 2)
1020  {
1021  Pout<< "f0 own:" << f0Own << " nei:" << f0Nei
1022  << " f1 own:" << f1Own << " nei:" << f1Nei
1023  << endl;
1024  }
1025 
1026 
1027  // If faces were internal but now become external set a patch.
1028  // If they were external already keep the patch.
1029  label patchID = patches.whichPatch(facei);
1030 
1031  if (patchID == -1)
1032  {
1033  patchID = exposedPatchi;
1034  }
1035 
1036 
1037  // Do as much as possible by modifying facei. Delay any remove
1038  // face. Keep track of whether facei has been used.
1039 
1040  bool modifiedFacei = false;
1041 
1042  if (f0Own == -1)
1043  {
1044  if (f0Nei != -1)
1045  {
1046  // f0 becomes external face (note:modFace will reverse face)
1047  modFace(meshMod, facei, f0, f0Own, f0Nei, patchID);
1048  modifiedFacei = true;
1049  }
1050  }
1051  else
1052  {
1053  if (f0Nei == -1)
1054  {
1055  // f0 becomes external face
1056  modFace(meshMod, facei, f0, f0Own, f0Nei, patchID);
1057  modifiedFacei = true;
1058  }
1059  else
1060  {
1061  // f0 stays internal face.
1062  modFace(meshMod, facei, f0, f0Own, f0Nei, -1);
1063  modifiedFacei = true;
1064  }
1065  }
1066 
1067 
1068  // f1 is added face (if at all)
1069 
1070  if (f1Own == -1)
1071  {
1072  if (f1Nei == -1)
1073  {
1074  // f1 not needed.
1075  }
1076  else
1077  {
1078  // f1 becomes external face (note:modFace will reverse face)
1079  if (!modifiedFacei)
1080  {
1081  modFace(meshMod, facei, f1, f1Own, f1Nei, patchID);
1082  modifiedFacei = true;
1083  }
1084  else
1085  {
1086  label masterPointi = findPatchFacePoint(f1, patchID);
1087 
1088  addFace
1089  (
1090  meshMod,
1091  facei, // face for zone info
1092  masterPointi, // inflation point
1093  f1, // vertices of face
1094  f1Own,
1095  f1Nei,
1096  patchID // patch for new face
1097  );
1098  }
1099  }
1100  }
1101  else
1102  {
1103  if (f1Nei == -1)
1104  {
1105  // f1 becomes external face
1106  if (!modifiedFacei)
1107  {
1108  modFace(meshMod, facei, f1, f1Own, f1Nei, patchID);
1109  modifiedFacei = true;
1110  }
1111  else
1112  {
1113  label masterPointi = findPatchFacePoint(f1, patchID);
1114 
1115  addFace
1116  (
1117  meshMod,
1118  facei,
1119  masterPointi,
1120  f1,
1121  f1Own,
1122  f1Nei,
1123  patchID
1124  );
1125  }
1126  }
1127  else
1128  {
1129  // f1 is internal face.
1130  if (!modifiedFacei)
1131  {
1132  modFace(meshMod, facei, f1, f1Own, f1Nei, -1);
1133  modifiedFacei = true;
1134  }
1135  else
1136  {
1137  label masterPointi = findPatchFacePoint(f1, -1);
1138 
1139  addFace(meshMod, facei, masterPointi, f1, f1Own, f1Nei, -1);
1140  }
1141  }
1142  }
1143 
1144  if (f0Own == -1 && f0Nei == -1 && !modifiedFacei)
1145  {
1146  meshMod.setAction(polyRemoveFace(facei));
1147 
1148  if (debug & 2)
1149  {
1150  Pout<< "Removed face " << facei << endl;
1151  }
1152  }
1153 
1154  faceUptodate[facei] = true;
1155  }
1156 
1157 
1158  //
1159  // Faces that have not been split but just appended to. Are guaranteed
1160  // to be reachable from an edgeCut.
1161  //
1162 
1163  const boolList& edgeIsCut = cuts.edgeIsCut();
1164 
1165  forAll(edgeIsCut, edgeI)
1166  {
1167  if (edgeIsCut[edgeI])
1168  {
1169  const labelList& eFaces = mesh().edgeFaces()[edgeI];
1170 
1171  forAll(eFaces, i)
1172  {
1173  label facei = eFaces[i];
1174 
1175  if (!faceUptodate[facei])
1176  {
1177  // So the face has not been split itself (i.e. its owner
1178  // or neighbour have not been split) so it only
1179  // borders by edge a cell which has been split.
1180 
1181  // Get (new or original) owner and neighbour of facei
1182  label own, nei, patchID;
1183  faceCells(cuts, exposedPatchi, facei, own, nei, patchID);
1184 
1185 
1186  if (own == -1 && nei == -1)
1187  {
1188  meshMod.setAction(polyRemoveFace(facei));
1189 
1190  if (debug & 2)
1191  {
1192  Pout<< "Removed face " << facei << endl;
1193  }
1194  }
1195  else
1196  {
1197  // Renumber face to include split edges.
1198  face newFace(addEdgeCutsToFace(facei));
1199 
1200  if (debug & 2)
1201  {
1202  Pout<< "Added edge cuts to face " << facei
1203  << " f:" << mesh().faces()[facei]
1204  << " newFace:" << newFace << endl;
1205  }
1206 
1207  modFace
1208  (
1209  meshMod,
1210  facei,
1211  newFace,
1212  own,
1213  nei,
1214  patchID
1215  );
1216  }
1217 
1218  faceUptodate[facei] = true;
1219  }
1220  }
1221  }
1222  }
1223 
1224 
1225  //
1226  // Remove any faces on the non-anchor side of a split cell.
1227  // Note: could loop through all cut cells only and check their faces but
1228  // looping over all faces is cleaner and probably faster for dense
1229  // cut patterns.
1230 
1231  const faceList& faces = mesh().faces();
1232 
1233  forAll(faces, facei)
1234  {
1235  if (!faceUptodate[facei])
1236  {
1237  // Get (new or original) owner and neighbour of facei
1238  label own, nei, patchID;
1239  faceCells(cuts, exposedPatchi, facei, own, nei, patchID);
1240 
1241  if (own == -1 && nei == -1)
1242  {
1243  meshMod.setAction(polyRemoveFace(facei));
1244 
1245  if (debug & 2)
1246  {
1247  Pout<< "Removed face " << facei << endl;
1248  }
1249  }
1250  else
1251  {
1252  modFace(meshMod, facei, faces[facei], own, nei, patchID);
1253  }
1254 
1255  faceUptodate[facei] = true;
1256  }
1257  }
1258 
1259  if (debug)
1260  {
1261  Pout<< "meshCutAndRemove:" << nl
1262  << " cells split:" << cuts.nLoops() << nl
1263  << " faces added:" << addedFaces_.size() << nl
1264  << " points added on edges:" << addedPoints_.size() << nl
1265  << endl;
1266  }
1267 }
1268 
1269 
1271 {
1272  // Update stored labels for mesh change.
1273  {
1274  Map<label> newAddedFaces(addedFaces_.size());
1275 
1276  forAllConstIters(addedFaces_, iter)
1277  {
1278  const label celli = iter.key();
1279  const label addedFacei = iter.val();
1280 
1281  const label newCelli = map.reverseCellMap()[celli];
1282  const label newAddedFacei = map.reverseFaceMap()[addedFacei];
1283 
1284  if ((newCelli >= 0) && (newAddedFacei >= 0))
1285  {
1286  if
1287  (
1288  (debug & 2)
1289  && (newCelli != celli || newAddedFacei != addedFacei)
1290  )
1291  {
1292  Pout<< "meshCutAndRemove::updateMesh :"
1293  << " updating addedFace for cell " << celli
1294  << " from " << addedFacei
1295  << " to " << newAddedFacei
1296  << endl;
1297  }
1298  newAddedFaces.insert(newCelli, newAddedFacei);
1299  }
1300  }
1301 
1302  // Copy
1303  addedFaces_.transfer(newAddedFaces);
1304  }
1305 
1306  {
1307  EdgeMap<label> newAddedPoints(addedPoints_.size());
1308 
1309  forAllConstIters(addedPoints_, iter)
1310  {
1311  const edge& e = iter.key();
1312  const label addedPointi = iter.val();
1313 
1314  const label newStart = map.reversePointMap()[e.start()];
1315  const label newEnd = map.reversePointMap()[e.end()];
1316  const label newAddedPointi = map.reversePointMap()[addedPointi];
1317 
1318  if ((newStart >= 0) && (newEnd >= 0) && (newAddedPointi >= 0))
1319  {
1320  edge newE(newStart, newEnd);
1321 
1322  if
1323  (
1324  (debug & 2)
1325  && (e != newE || newAddedPointi != addedPointi)
1326  )
1327  {
1328  Pout<< "meshCutAndRemove::updateMesh :"
1329  << " updating addedPoints for edge " << e
1330  << " from " << addedPointi
1331  << " to " << newAddedPointi
1332  << endl;
1333  }
1334 
1335  newAddedPoints.insert(newE, newAddedPointi);
1336  }
1337  }
1338 
1339  // Copy
1340  addedPoints_.transfer(newAddedPoints);
1341  }
1342 }
1343 
1344 
1345 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::reverse
void reverse(UList< T > &list, const label n)
Definition: UListI.H:396
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1038
meshTools.H
Foam::cellCuts::nLoops
label nLoops() const
Number of valid cell loops.
Definition: cellCuts.H:595
Foam::cellCuts::pointIsCut
const boolList & pointIsCut() const
Is mesh point cut.
Definition: cellCuts.H:554
polyRemovePoint.H
Foam::cellCuts::faceSplitCut
const Map< edge > & faceSplitCut() const
Gives for split face the two cuts that split the face into two.
Definition: cellCuts.H:583
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:62
Foam::polyRemovePoint
Class containing data for point removal.
Definition: polyRemovePoint.H:48
Foam::primitiveMesh::cellPoints
const labelListList & cellPoints() const
Definition: primitiveMeshCellPoints.C:34
polyAddFace.H
Foam::primitiveMesh::edgeFaces
const labelListList & edgeFaces() const
Definition: primitiveMeshEdgeFaces.C:33
polyRemoveFace.H
mapPolyMesh.H
polyTopoChange.H
Foam::primitiveMesh::pointFaces
const labelListList & pointFaces() const
Definition: primitiveMeshPointFaces.C:34
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:100
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::edgeVertex
Combines edge or vertex in single label. Used to specify cuts across cell circumference.
Definition: edgeVertex.H:54
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: HashTableFwd.H:46
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:435
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Foam::cellCuts::cellAnchorPoints
const labelListList & cellAnchorPoints() const
For each cut cell the points on the 'anchor' side of the cell.
Definition: cellCuts.H:601
Foam::primitiveMesh::edges
const edgeList & edges() const
Return mesh edges. Uses calcEdges.
Definition: primitiveMeshEdges.C:505
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
polyMesh.H
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
meshCutAndRemove.H
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:477
Foam::meshCutAndRemove::setRefinement
void setRefinement(const label exposedPatchi, const cellCuts &cuts, const labelList &cutPatch, polyTopoChange &meshMod)
Do actual cutting with cut description. Inserts mesh changes.
Definition: meshCutAndRemove.C:578
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::cellCuts::edgeWeight
const scalarField & edgeWeight() const
If edge is cut gives weight (ratio between start() and end())
Definition: cellCuts.H:566
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::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:359
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::Field< scalar >
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1076
Foam::cellCuts::cellLoops
const labelListList & cellLoops() const
For each cut cell the cut along the circumference.
Definition: cellCuts.H:589
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Definition: polyBoundaryMesh.C:805
polyAddPoint.H
cut
Patchify triangles based on orientation w.r.t other (triangulated or triangulatable) surfaces.
Foam::ZoneMesh::whichZone
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:315
cellCuts.H
Foam::FatalError
error FatalError
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::meshCutAndRemove::updateMesh
void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: meshCutAndRemove.C:1270
polyModifyFace.H
Foam::mapPolyMesh::reverseFaceMap
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:500
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::EdgeMap< label >
Foam::mapPolyMesh::reverseCellMap
const labelList & reverseCellMap() const
Reverse cell map.
Definition: mapPolyMesh.H:531
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
Foam::polyTopoChange::setAction
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Definition: polyTopoChange.C:2458
Foam::nl
constexpr char nl
Definition: Ostream.H:372
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
f
labelList f(nPoints)
Foam::mapPolyMesh::reversePointMap
const labelList & reversePointMap() const
Reverse point map.
Definition: mapPolyMesh.H:468
Foam::Vector< scalar >
Foam::polyRemoveFace
Class containing data for face removal.
Definition: polyRemoveFace.H:48
Foam::List< label >
Foam::cellCuts::edgeIsCut
const boolList & edgeIsCut() const
Is edge cut.
Definition: cellCuts.H:560
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::polyAddPoint
Class containing data for point addition.
Definition: polyAddPoint.H:49
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:160
Foam::polyAddFace
A face addition data class. A face can be inflated either from a point or from another face and can e...
Definition: polyAddFace.H:53
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::faceCells
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:56
pointLabels
labelList pointLabels(nPoints, -1)
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1082
Foam::cellCuts
Description of cuts across cells.
Definition: cellCuts.H:110
Foam::labelI
static const labelSphericalTensor labelI(1)
Identity labelTensor.