polyMeshZipUpCells.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) 2022 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 "polyMeshZipUpCells.H"
30 #include "polyMesh.H"
31 #include "Time.H"
32 #include "CircularBuffer.H"
33 #include "DynamicList.H"
34 
35 // #define DEBUG_ZIPUP 1
36 // #define DEBUG_CHAIN 1
37 // #define DEBUG_ORDER 1
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 
42 {
43  if (polyMesh::debug)
44  {
45  Info<< "bool polyMeshZipUpCells(polyMesh& mesh) const: "
46  << "zipping up topologically open cells" << endl;
47  }
48 
49  // Algorithm:
50  // Take the original mesh and visit all cells. For every cell
51  // calculate the edges of all faces on the cells. A cell is
52  // correctly topologically closed when all the edges are referenced
53  // by exactly two faces. If the edges are referenced only by a
54  // single face, additional vertices need to be inserted into some
55  // of the faces (topological closedness). If an edge is
56  // referenced by more that two faces, there is an error in
57  // topological closedness.
58  // Point insertion into the faces is done by attempting to create
59  // closed loops and inserting the intermediate points into the
60  // defining edge
61  // Note:
62  // The algorithm is recursive and changes the mesh faces in each
63  // pass. It is therefore essential to discard the addressing
64  // after every pass. The algorithm is completed when the mesh
65  // stops changing.
66 
67  label nChangedFacesInMesh = 0;
68  label nCycles = 0;
69 
70  labelHashSet problemCells;
71 
72  DynamicList<bool> singleEdgeUsage(256);
73  CircularBuffer<label> pointChain(256);
74 
75  do
76  {
77  nChangedFacesInMesh = 0;
78 
79  const cellList& Cells = mesh.cells();
80  const pointField& Points = mesh.points();
81 
82  faceList newFaces = mesh.faces();
83 
84  const faceList& oldFaces = mesh.faces();
85  const labelListList& pFaces = mesh.pointFaces();
86 
87  forAll(Cells, celli)
88  {
89  const labelList& curFaces = Cells[celli];
90  const edgeList cellEdges = Cells[celli].edges(oldFaces);
91  const labelList cellPoints = Cells[celli].labels(oldFaces);
92 
93  // Find the edges used only once in the cell
94 
95  labelList edgeUsage(cellEdges.size(), Zero);
96 
97  forAll(curFaces, facei)
98  {
99  edgeList curFaceEdges = oldFaces[curFaces[facei]].edges();
100 
101  forAll(curFaceEdges, faceEdgeI)
102  {
103  const edge& curEdge = curFaceEdges[faceEdgeI];
104 
105  forAll(cellEdges, cellEdgeI)
106  {
107  if (cellEdges[cellEdgeI] == curEdge)
108  {
109  edgeUsage[cellEdgeI]++;
110  break;
111  }
112  }
113  }
114  }
115 
116  edgeList singleEdges(cellEdges.size());
117  label nSingleEdges = 0;
118 
119  forAll(edgeUsage, edgeI)
120  {
121  if (edgeUsage[edgeI] == 1)
122  {
123  singleEdges[nSingleEdges] = cellEdges[edgeI];
124  nSingleEdges++;
125  }
126  else if (edgeUsage[edgeI] != 2)
127  {
129  << "edge " << cellEdges[edgeI] << " in cell " << celli
130  << " used " << edgeUsage[edgeI] << " times. " << nl
131  << "Should be 1 or 2 - serious error "
132  << "in mesh structure. " << endl;
133 
134  #ifdef DEBUG_ZIPUP
135  forAll(curFaces, facei)
136  {
137  Info<< "face: " << oldFaces[curFaces[facei]]
138  << endl;
139  }
140 
141  Info<< "Cell edges: " << cellEdges << nl
142  << "Edge usage: " << edgeUsage << nl
143  << "Cell points: " << cellPoints << endl;
144 
145  forAll(cellPoints, cpI)
146  {
147  Info<< "vertex create \"" << cellPoints[cpI]
148  << "\" coordinates "
149  << Points[cellPoints[cpI]] << endl;
150  }
151  #endif
152 
153  // Gather the problem cell
154  problemCells.insert(celli);
155  }
156  }
157 
158  // Check if the cell is already zipped up
159  if (nSingleEdges == 0) continue;
160 
161  singleEdges.setSize(nSingleEdges);
162 
163  #ifdef DEBUG_ZIPUP
164  Info<< "Cell " << celli << endl;
165 
166  forAll(curFaces, facei)
167  {
168  Info<< "face: " << oldFaces[curFaces[facei]] << endl;
169  }
170 
171  Info<< "Cell edges: " << cellEdges << nl
172  << "Edge usage: " << edgeUsage << nl
173  << "Single edges: " << singleEdges << nl
174  << "Cell points: " << cellPoints << endl;
175 
176  forAll(cellPoints, cpI)
177  {
178  Info<< "vertex create \"" << cellPoints[cpI]
179  << "\" coordinates "
180  << points()[cellPoints[cpI]] << endl;
181  }
182  #endif
183 
184  // Loop through all single edges and mark the points they use
185  // points marked twice are internal to edge; those marked more than
186  // twice are corners
187 
188  labelList pointUsage(cellPoints.size(), Zero);
189 
190  forAll(singleEdges, edgeI)
191  {
192  const edge& curEdge = singleEdges[edgeI];
193 
194  forAll(cellPoints, pointi)
195  {
196  if
197  (
198  cellPoints[pointi] == curEdge.start()
199  || cellPoints[pointi] == curEdge.end()
200  )
201  {
202  pointUsage[pointi]++;
203  }
204  }
205  }
206 
207  singleEdgeUsage.resize_nocopy(singleEdges.size());
208  singleEdgeUsage = false;
209 
210  // loop through all edges and eliminate the ones that are
211  // blocked out
212  forAll(singleEdges, edgeI)
213  {
214  bool blockedHead = false;
215  bool blockedTail = false;
216 
217  label newEdgeStart = singleEdges[edgeI].start();
218  label newEdgeEnd = singleEdges[edgeI].end();
219 
220  // check that the edge has not got all ends blocked
221  forAll(cellPoints, pointi)
222  {
223  if (cellPoints[pointi] == newEdgeStart)
224  {
225  if (pointUsage[pointi] > 2)
226  {
227  blockedHead = true;
228  }
229  }
230  else if (cellPoints[pointi] == newEdgeEnd)
231  {
232  if (pointUsage[pointi] > 2)
233  {
234  blockedTail = true;
235  }
236  }
237  }
238 
239  if (blockedHead && blockedTail)
240  {
241  // Eliminating edge singleEdges[edgeI] as blocked
242  singleEdgeUsage[edgeI] = true;
243  }
244  }
245 
246  // Go through the points and start from the point used twice
247  // check all the edges to find the edges starting from this point
248  // add the
249 
250  labelListList edgesToInsert(singleEdges.size());
251  label nEdgesToInsert = 0;
252 
253  // Find a good edge
254  forAll(singleEdges, edgeI)
255  {
256  pointChain.clear();
257 
258  bool blockHead = false;
259  bool blockTail = false;
260 
261  if (!singleEdgeUsage[edgeI])
262  {
263  // found a new edge
264  singleEdgeUsage[edgeI] = true;
265 
266  label newEdgeStart = singleEdges[edgeI].start();
267  label newEdgeEnd = singleEdges[edgeI].end();
268 
269  pointChain.push_front(newEdgeStart);
270  pointChain.push_back(newEdgeEnd);
271 
272  #ifdef DEBUG_CHAIN
273  Info<< "found edge to start with: "
274  << singleEdges[edgeI] << endl;
275  #endif
276 
277  // Check if head or tail are blocked
278  forAll(cellPoints, pointi)
279  {
280  if (cellPoints[pointi] == newEdgeStart)
281  {
282  if (pointUsage[pointi] > 2)
283  {
284  #ifdef DEBUG_CHAIN
285  Info<< "start head blocked" << endl;
286  #endif
287 
288  blockHead = true;
289  }
290  }
291  else if (cellPoints[pointi] == newEdgeEnd)
292  {
293  if (pointUsage[pointi] > 2)
294  {
295  #ifdef DEBUG_CHAIN
296  Info<< "start tail blocked" << endl;
297  #endif
298 
299  blockTail = true;
300  }
301  }
302  }
303 
304  bool stopSearching = false;
305 
306  // Go through the unused edges and try to chain them up
307  do
308  {
309  stopSearching = false;
310 
311  forAll(singleEdges, addEdgeI)
312  {
313  if (!singleEdgeUsage[addEdgeI])
314  {
315  // Grab start and end of the candidate
316  label addStart =
317  singleEdges[addEdgeI].start();
318 
319  label addEnd =
320  singleEdges[addEdgeI].end();
321 
322  #ifdef DEBUG_CHAIN
323  Info<< "Trying candidate "
324  << singleEdges[addEdgeI] << endl;
325  #endif
326 
327  // Try to add the edge onto the head
328  if (!blockHead)
329  {
330  if (pointChain.front() == addStart)
331  {
332  // Added at start mark as used
333  pointChain.push_front(addEnd);
334 
335  singleEdgeUsage[addEdgeI] = true;
336  }
337  else if (pointChain.front() == addEnd)
338  {
339  pointChain.push_front(addStart);
340 
341  singleEdgeUsage[addEdgeI] = true;
342  }
343  }
344 
345  // Try the other end only if the first end
346  // did not add it
347  if (!blockTail && !singleEdgeUsage[addEdgeI])
348  {
349  if (pointChain.back() == addStart)
350  {
351  // Added at start mark as used
352  pointChain.push_back(addEnd);
353 
354  singleEdgeUsage[addEdgeI] = true;
355  }
356  else if (pointChain.back() == addEnd)
357  {
358  pointChain.push_back(addStart);
359 
360  singleEdgeUsage[addEdgeI] = true;
361  }
362  }
363 
364  // check if the new head or tail are blocked
365  label curEdgeStart = pointChain.front();
366  label curEdgeEnd = pointChain.back();
367 
368  #ifdef DEBUG_CHAIN
369  Info<< "curEdgeStart: " << curEdgeStart
370  << " curEdgeEnd: " << curEdgeEnd << endl;
371  #endif
372 
373  forAll(cellPoints, pointi)
374  {
375  if (cellPoints[pointi] == curEdgeStart)
376  {
377  if (pointUsage[pointi] > 2)
378  {
379  #ifdef DEBUG_CHAIN
380  Info<< "head blocked" << endl;
381  #endif
382 
383  blockHead = true;
384  }
385  }
386  else if (cellPoints[pointi] == curEdgeEnd)
387  {
388  if (pointUsage[pointi] > 2)
389  {
390  #ifdef DEBUG_CHAIN
391  Info<< "tail blocked" << endl;
392  #endif
393 
394  blockTail = true;
395  }
396  }
397  }
398 
399  // Check if the loop is closed
400  if (curEdgeStart == curEdgeEnd)
401  {
402  #ifdef DEBUG_CHAIN
403  Info<< "closed loop" << endl;
404  #endif
405 
406  pointChain.pop_front();
407 
408  blockHead = true;
409  blockTail = true;
410 
411  stopSearching = true;
412  }
413 
414  #ifdef DEBUG_CHAIN
415  Info<< "current pointChain: "
416  << pointChain << endl;
417  #endif
418 
419  if (stopSearching) break;
420  }
421  }
422  } while (stopSearching);
423  }
424 
425  #ifdef DEBUG_CHAIN
426  Info<< "completed patch chain: " << pointChain << endl;
427  #endif
428 
429  if (pointChain.size() > 2)
430  {
431  edgesToInsert[nEdgesToInsert] = pointChain.list();
432  nEdgesToInsert++;
433  }
434  }
435 
436  edgesToInsert.setSize(nEdgesToInsert);
437 
438  #ifdef DEBUG_ZIPUP
439  Info<< "edgesToInsert: " << edgesToInsert << endl;
440  #endif
441 
442  // Insert the edges into a list of faces
443  forAll(edgesToInsert, edgeToInsertI)
444  {
445  // Order the points of the edge
446  // Warning: the ordering must be parametric, because in
447  // the case of multiple point insertion onto the same edge
448  // it is possible to get non-cyclic loops
449  //
450 
451  const labelList& unorderedEdge = edgesToInsert[edgeToInsertI];
452 
453  scalarField dist(unorderedEdge.size());
454 
455  // Calculate distance
456  point startPoint = Points[unorderedEdge[0]];
457  dist[0] = 0;
458 
459  vector dir = Points[unorderedEdge.last()] - startPoint;
460 
461  for (label i = 1; i < dist.size(); i++)
462  {
463  dist[i] = (Points[unorderedEdge[i]] - startPoint) & dir;
464  }
465 
466  // Sort points
467  labelList orderedEdge(unorderedEdge.size(), -1);
468  boolList used(unorderedEdge.size(), false);
469 
470  forAll(orderedEdge, epI)
471  {
472  label nextPoint = -1;
473  scalar minDist = GREAT;
474 
475  forAll(dist, i)
476  {
477  if (!used[i] && dist[i] < minDist)
478  {
479  minDist = dist[i];
480  nextPoint = i;
481  }
482  }
483 
484  // Insert the next point
485  orderedEdge[epI] = unorderedEdge[nextPoint];
486  used[nextPoint] = true;
487  }
488 
489  #ifdef DEBUG_ORDER
490  Info<< "unorderedEdge: " << unorderedEdge << nl
491  << "orderedEdge: " << orderedEdge << endl;
492  #endif
493 
494  // check for duplicate points in the ordered edge
495  forAll(orderedEdge, checkI)
496  {
497  for
498  (
499  label checkJ = checkI + 1;
500  checkJ < orderedEdge.size();
501  checkJ++
502  )
503  {
504  if (orderedEdge[checkI] == orderedEdge[checkJ])
505  {
507  << "Duplicate point found in edge to insert. "
508  << nl << "Point: " << orderedEdge[checkI]
509  << " edge: " << orderedEdge << endl;
510 
511  problemCells.insert(celli);
512  }
513  }
514  }
515 
516  edge testEdge
517  (
518  orderedEdge[0],
519  orderedEdge.last()
520  );
521 
522  // In order to avoid edge-to-edge comparison, get faces using
523  // point-face addressing in two goes.
524  const labelList& startPF = pFaces[testEdge.start()];
525  const labelList& endPF = pFaces[testEdge.start()];
526 
527  labelList facesSharingEdge(startPF.size() + endPF.size());
528  label nfse = 0;
529 
530  forAll(startPF, pfI)
531  {
532  facesSharingEdge[nfse++] = startPF[pfI];
533  }
534  forAll(endPF, pfI)
535  {
536  facesSharingEdge[nfse++] = endPF[pfI];
537  }
538 
539  forAll(facesSharingEdge, facei)
540  {
541  bool faceChanges = false;
542 
543  // Label of the face being analysed
544  const label currentFaceIndex = facesSharingEdge[facei];
545 
546  const edgeList curFaceEdges =
547  oldFaces[currentFaceIndex].edges();
548 
549  forAll(curFaceEdges, cfeI)
550  {
551  if (curFaceEdges[cfeI] == testEdge)
552  {
553  faceChanges = true;
554  break;
555  }
556  }
557 
558  if (faceChanges)
559  {
560  nChangedFacesInMesh++;
561  // In order to avoid losing point from multiple
562  // insertions into the same face, the new face
563  // will be change incrementally.
564  // 1) Check if all the internal points of the edge
565  // to add already exist in the face. If so, the
566  // edge has already been included 2) Check if the
567  // point insertion occurs on an edge which is
568  // still untouched. If so, simply insert
569  // additional points into the face. 3) If not,
570  // the edge insertion occurs on an already
571  // modified edge. ???
572 
573  face& newFace = newFaces[currentFaceIndex];
574 
575  bool allPointsPresent = true;
576 
577  forAll(orderedEdge, oeI)
578  {
579  bool curPointFound = false;
580 
581  forAll(newFace, nfI)
582  {
583  if (newFace[nfI] == orderedEdge[oeI])
584  {
585  curPointFound = true;
586  break;
587  }
588  }
589 
590  allPointsPresent =
591  allPointsPresent && curPointFound;
592  }
593 
594  #ifdef DEBUG_ZIPUP
595  if (allPointsPresent)
596  {
597  Info<< "All points present" << endl;
598  }
599  #endif
600 
601  if (!allPointsPresent)
602  {
603  // Not all points are already present. The
604  // new edge will need to be inserted into the
605  // face.
606 
607  // Check to see if a new edge fits onto an
608  // untouched edge of the face. Make sure the
609  // edges are grabbed before the face is
610  // resized.
611  edgeList newFaceEdges = newFace.edges();
612 
613  #ifdef DEBUG_ZIPUP
614  Info<< "Not all points present." << endl;
615  #endif
616 
617  label nNewFacePoints = 0;
618 
619  bool edgeAdded = false;
620 
621  forAll(newFaceEdges, curFacEdgI)
622  {
623  // Does the current edge change?
624  if (newFaceEdges[curFacEdgI] == testEdge)
625  {
626  // Found an edge match
627  edgeAdded = true;
628 
629  // Resize the face to accept additional
630  // points
631  newFace.setSize
632  (
633  newFace.size()
634  + orderedEdge.size() - 2
635  );
636 
637  if
638  (
639  newFaceEdges[curFacEdgI].start()
640  == testEdge.start()
641  )
642  {
643  // insertion in ascending order
644  for
645  (
646  label i = 0;
647  i < orderedEdge.size() - 1;
648  i++
649  )
650  {
651  newFace[nNewFacePoints] =
652  orderedEdge[i];
653  nNewFacePoints++;
654  }
655  }
656  else
657  {
658  // insertion in reverse order
659  for
660  (
661  label i = orderedEdge.size() - 1;
662  i > 0;
663  i--
664  )
665  {
666  newFace[nNewFacePoints] =
667  orderedEdge[i];
668  nNewFacePoints++;
669  }
670  }
671  }
672  else
673  {
674  // Does not fit onto this edge.
675  // Copy the next point into the face
676  newFace[nNewFacePoints] =
677  newFaceEdges[curFacEdgI].start();
678  nNewFacePoints++;
679  }
680  }
681 
682  #ifdef DEBUG_ZIPUP
683  Info<< "oldFace: "
684  << oldFaces[currentFaceIndex] << nl
685  << "newFace: " << newFace << endl;
686  #endif
687 
688  // Check for duplicate points in the new face
689  forAll(newFace, checkI)
690  {
691  for
692  (
693  label checkJ = checkI + 1;
694  checkJ < newFace.size();
695  checkJ++
696  )
697  {
698  if (newFace[checkI] == newFace[checkJ])
699  {
701  << "Duplicate point found "
702  << "in the new face. " << nl
703  << "Point: "
704  << orderedEdge[checkI]
705  << " face: "
706  << newFace << endl;
707 
708  problemCells.insert(celli);
709  }
710  }
711  }
712 
713  // Check if the edge is added.
714  // If not, then it comes on top of an already
715  // modified edge and they need to be
716  // merged in together.
717  if (!edgeAdded)
718  {
719  Info<< "This edge modifies an already modified "
720  << "edge. Point insertions skipped."
721  << endl;
722  }
723  }
724  }
725  }
726  }
727  }
728 
729  if (problemCells.size())
730  {
731  // This cycle has failed. Print out the problem cells
733  << "Found " << problemCells.size() << " problem cells." << nl
734  << "Cells: " << problemCells.sortedToc()
735  << abort(FatalError);
736  }
737 
738  Info<< "Cycle " << ++nCycles
739  << " changed " << nChangedFacesInMesh << " faces." << endl;
740 
741 
742  const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
743 
744  // Reset the polyMesh. Number of points/faces/cells/patches stays the
745  // same, only the faces themselves have changed so clear all derived
746  // (edge, point) addressing.
747 
748  // Collect the patch sizes
749  labelList patchSizes(bMesh.size(), Zero);
750  labelList patchStarts(bMesh.size(), Zero);
751 
752  forAll(bMesh, patchi)
753  {
754  patchSizes[patchi] = bMesh[patchi].size();
755  patchStarts[patchi] = bMesh[patchi].start();
756  }
757 
758  // Reset the mesh. Number of active faces is one beyond the last patch
759  // (patches guaranteed to be in increasing order)
760  mesh.resetPrimitives
761  (
762  autoPtr<pointField>(), // <- null: leaves points untouched
763  autoPtr<faceList>::New(std::move(newFaces)),
764  autoPtr<labelList>(), // <- null: leaves owner untouched
765  autoPtr<labelList>(), // <- null: leaves neighbour untouched
766  patchSizes,
767  patchStarts,
768  true // boundary forms valid boundary mesh.
769  );
770 
771  // Reset any addressing on face zones.
772  mesh.faceZones().clearAddressing();
773 
774  // Clear the addressing
775  mesh.clearOut();
776 
777  } while (nChangedFacesInMesh > 0 || nCycles > 100);
778 
779  // Flags the mesh files as being changed
780  mesh.setInstance(mesh.time().timeName());
781 
782  if (nChangedFacesInMesh > 0)
783  {
785  << "with the original mesh"
786  << abort(FatalError);
787  }
788 
789  return nCycles != 1;
790 }
791 
792 
793 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void pop_front(label n=1)
Shrink by moving the front of the buffer 1 or more times.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
edgeList edges() const
Return list of edges in forward walk order.
Definition: face.C:764
labelHashSet used(const bitSet &select)
Convert a bitset to a labelHashSet of the indices used.
Definition: HashOps.C:26
vtkSmartPointer< vtkPoints > Points(const UList< point > &pts)
Return a list of points as vtkPoints.
Definition: foamVtkToolsI.H:52
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
bool polyMeshZipUpCells(polyMesh &mesh)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
void clear() noexcept
Clear the addressed buffer, does not change allocation.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void push_front(const T &val)
Copy prepend an element to the front of the buffer.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
label size() const noexcept
The current number of buffer items.
T & back()
Access the last element (back). Requires !empty().
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
label start() const noexcept
The start (first) vertex label.
Definition: edge.H:147
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
A list of faces which address into the list of points.
List< T > list() const
Return a copy of the buffer flattened into a single List. Use sparingly!
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
const pointField & points
An edge is a list of two vertex labels. This can correspond to a directed graph edge or an edge on a ...
Definition: edge.H:59
A simple list of objects of type <T> that is intended to be used as a circular buffer (eg...
errorManip< error > abort(error &err)
Definition: errorManip.H:139
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
T & front()
Access the first element (front). Requires !empty().
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].reset(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
#define WarningInFunction
Report a warning using Foam::Warning.
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:139
messageStream Info
Information stream (stdout output on master, null elsewhere)
Cell zip-up tool. This function modifies the list of faces such that all the cells are topologically ...
void push_back(const T &val)
Copy append an element to the end of the buffer.
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
Definition: DynamicListI.H:375
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
label end() const noexcept
The end (last/second) vertex label.
Definition: edge.H:152
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:435
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127