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