hexRef8.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2024 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 "hexRef8.H"
27 
28 #include "polyMesh.H"
29 #include "polyTopoChange.H"
30 #include "meshTools.H"
31 #include "syncTools.H"
32 #include "faceSet.H"
33 #include "cellSet.H"
34 #include "pointSet.H"
35 #include "OFstream.H"
36 #include "Time.H"
37 #include "FaceCellWave.H"
38 #include "polyDistributionMap.H"
39 #include "refinementData.H"
40 #include "refinementDistanceData.H"
41 #include "degenerateMatcher.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 namespace Foam
46 {
48 
49  //- Reduction class. If x and y are not equal assign value.
50  template<label value>
51  class ifEqEqOp
52  {
53  public:
54  void operator()(label& x, const label y) const
55  {
56  x = (x == y) ? x : value;
57  }
58  };
59 }
60 
61 
62 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
63 
64 void Foam::hexRef8::reorder
65 (
66  const labelList& map,
67  const label len,
68  const label null,
69  labelList& elems
70 )
71 {
72  labelList newElems(len, null);
73 
74  forAll(elems, i)
75  {
76  label newI = map[i];
77 
78  if (newI >= len)
79  {
81  }
82 
83  if (newI >= 0)
84  {
85  newElems[newI] = elems[i];
86  }
87  }
88 
89  elems.transfer(newElems);
90 }
91 
92 
93 Foam::label Foam::hexRef8::getPatchIndex(const label facei) const
94 {
95  label patchID = -1;
96 
97  if (!mesh_.isInternalFace(facei))
98  {
99  patchID = mesh_.boundaryMesh().whichPatch(facei);
100  }
101 
102  return patchID;
103 }
104 
105 
106 Foam::label Foam::hexRef8::addFace
107 (
108  polyTopoChange& meshMod,
109  const label facei,
110  const face& newFace,
111  const label own,
112  const label nei
113 ) const
114 {
115  const label patchID = getPatchIndex(facei);
116 
117  label newFacei = -1;
118 
119  if ((nei == -1) || (own < nei))
120  {
121  // Ordering ok.
122  newFacei = meshMod.addFace
123  (
124  newFace, // face
125  own, // owner
126  nei, // neighbour
127  facei, // master face for addition
128  false, // flux flip
129  patchID // patch for face
130  );
131  }
132  else
133  {
134  // Reverse owner/neighbour
135  newFacei = meshMod.addFace
136  (
137  newFace.reverseFace(), // face
138  nei, // owner
139  own, // neighbour
140  facei, // master face for addition
141  false, // flux flip
142  patchID // patch for face
143  );
144  }
145  return newFacei;
146 }
147 
148 
149 Foam::label Foam::hexRef8::addInternalFace
150 (
151  polyTopoChange& meshMod,
152  const label meshFacei,
153  const label meshPointi,
154  const face& newFace,
155  const label own,
156  const label nei
157 ) const
158 {
159  if (mesh_.isInternalFace(meshFacei))
160  {
161  return meshMod.addFace
162  (
163  newFace, // face
164  own, // owner
165  nei, // neighbour
166  meshFacei, // master face for addition
167  false, // flux flip
168  -1 // patch for face
169  );
170  }
171  else
172  {
173  // For now create out of nothing
174  // problem: field does not get mapped.
175  return meshMod.addFace
176  (
177  newFace, // face
178  own, // owner
179  nei, // neighbour
180  -1, // master face for addition
181  false, // flux flip
182  -1 // patch for face
183  );
184  }
185 }
186 
187 
188 void Foam::hexRef8::modifyFace
189 (
190  polyTopoChange& meshMod,
191  const label facei,
192  const face& newFace,
193  const label own,
194  const label nei
195 ) const
196 {
197  const label patchID = getPatchIndex(facei);
198 
199  if
200  (
201  (own != mesh_.faceOwner()[facei])
202  || (
203  mesh_.isInternalFace(facei)
204  && (nei != mesh_.faceNeighbour()[facei])
205  )
206  || (newFace != mesh_.faces()[facei])
207  )
208  {
209  if ((nei == -1) || (own < nei))
210  {
211  meshMod.modifyFace
212  (
213  newFace, // modified face
214  facei, // label of face being modified
215  own, // owner
216  nei, // neighbour
217  false, // face flip
218  patchID // patch for face
219  );
220  }
221  else
222  {
223  meshMod.modifyFace
224  (
225  newFace.reverseFace(), // modified face
226  facei, // label of face being modified
227  nei, // owner
228  own, // neighbour
229  false, // face flip
230  patchID // patch for face
231  );
232  }
233  }
234 }
235 
236 
237 Foam::scalar Foam::hexRef8::getLevel0EdgeLength() const
238 {
239  if (cellLevel_.size() != mesh_.nCells())
240  {
242  << "Number of cells in mesh:" << mesh_.nCells()
243  << " does not equal size of cellLevel:" << cellLevel_.size()
244  << endl
245  << "This might be because of a restart with inconsistent cellLevel."
246  << abort(FatalError);
247  }
248 
249  // Determine minimum edge length per refinement level
250  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251 
252  const scalar great2 = sqr(great);
253 
254  label nLevels = gMax(cellLevel_)+1;
255 
256  scalarField typEdgeLenSqr(nLevels, great2);
257 
258 
259  // 1. Look only at edges surrounded by cellLevel cells only.
260  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261 
262  {
263  // Per edge the cellLevel of connected cells. -1 if not set,
264  // labelMax if different levels, otherwise levels of connected cells.
265  labelList edgeLevel(mesh_.nEdges(), -1);
266 
267  forAll(cellLevel_, celli)
268  {
269  const label cLevel = cellLevel_[celli];
270 
271  const labelList& cEdges = mesh_.cellEdges(celli);
272 
273  forAll(cEdges, i)
274  {
275  label edgeI = cEdges[i];
276 
277  if (edgeLevel[edgeI] == -1)
278  {
279  edgeLevel[edgeI] = cLevel;
280  }
281  else if (edgeLevel[edgeI] == labelMax)
282  {
283  // Already marked as on different cellLevels
284  }
285  else if (edgeLevel[edgeI] != cLevel)
286  {
287  edgeLevel[edgeI] = labelMax;
288  }
289  }
290  }
291 
292  // Make sure that edges with different levels on different processors
293  // are also marked. Do the same test (edgeLevel != cLevel) on coupled
294  // edges.
296  (
297  mesh_,
298  edgeLevel,
299  ifEqEqOp<labelMax>(),
300  labelMin
301  );
302 
303  // Now use the edgeLevel with a valid value to determine the
304  // length per level.
305  forAll(edgeLevel, edgeI)
306  {
307  const label eLevel = edgeLevel[edgeI];
308 
309  if (eLevel >= 0 && eLevel < labelMax)
310  {
311  const edge& e = mesh_.edges()[edgeI];
312 
313  scalar edgeLenSqr = magSqr(e.vec(mesh_.points()));
314 
315  typEdgeLenSqr[eLevel] = min(typEdgeLenSqr[eLevel], edgeLenSqr);
316  }
317  }
318  }
319 
320  // Get the minimum per level over all processors. Note minimum so if
321  // cells are not cubic we use the smallest edge side.
322  Pstream::listCombineGather(typEdgeLenSqr, minEqOp<scalar>());
323  Pstream::listCombineScatter(typEdgeLenSqr);
324 
325  if (debug)
326  {
327  Pout<< "hexRef8::getLevel0EdgeLength() :"
328  << " After phase1: Edgelengths (squared) per refinementlevel:"
329  << typEdgeLenSqr << endl;
330  }
331 
332 
333  // 2. For any levels where we haven't determined a valid length yet
334  // use any surrounding cell level. Here we use the max so we don't
335  // pick up levels between celllevel and higher celllevel (will have
336  // edges sized according to highest celllevel)
337  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
338 
339  scalarField maxEdgeLenSqr(nLevels, -great2);
340 
341  forAll(cellLevel_, celli)
342  {
343  const label cLevel = cellLevel_[celli];
344 
345  const labelList& cEdges = mesh_.cellEdges(celli);
346 
347  forAll(cEdges, i)
348  {
349  const edge& e = mesh_.edges()[cEdges[i]];
350 
351  scalar edgeLenSqr = magSqr(e.vec(mesh_.points()));
352 
353  maxEdgeLenSqr[cLevel] = max(maxEdgeLenSqr[cLevel], edgeLenSqr);
354  }
355  }
356 
357  Pstream::listCombineGather(maxEdgeLenSqr, maxEqOp<scalar>());
358  Pstream::listCombineScatter(maxEdgeLenSqr);
359 
360  if (debug)
361  {
362  Pout<< "hexRef8::getLevel0EdgeLength() :"
363  << " Crappy Edgelengths (squared) per refinementlevel:"
364  << maxEdgeLenSqr << endl;
365  }
366 
367 
368  // 3. Combine the two sets of lengths
369  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
370 
371  forAll(typEdgeLenSqr, levelI)
372  {
373  if (typEdgeLenSqr[levelI] == great2 && maxEdgeLenSqr[levelI] >= 0)
374  {
375  typEdgeLenSqr[levelI] = maxEdgeLenSqr[levelI];
376  }
377  }
378 
379  if (debug)
380  {
381  Pout<< "hexRef8::getLevel0EdgeLength() :"
382  << " Final Edgelengths (squared) per refinementlevel:"
383  << typEdgeLenSqr << endl;
384  }
385 
386  // Find lowest level present
387  scalar level0Size = -1;
388 
389  forAll(typEdgeLenSqr, levelI)
390  {
391  scalar lenSqr = typEdgeLenSqr[levelI];
392 
393  if (lenSqr < great2)
394  {
395  level0Size = Foam::sqrt(lenSqr)*(1<<levelI);
396 
397  if (debug)
398  {
399  Pout<< "hexRef8::getLevel0EdgeLength() :"
400  << " For level:" << levelI
401  << " have edgeLen:" << Foam::sqrt(lenSqr)
402  << " with equivalent level0 len:" << level0Size
403  << endl;
404  }
405  break;
406  }
407  }
408 
409  if (level0Size == -1)
410  {
412  << "Problem : typEdgeLenSqr:" << typEdgeLenSqr << abort(FatalError);
413  }
414 
415  return level0Size;
416 }
417 
418 
419 Foam::label Foam::hexRef8::getAnchorCell
420 (
421  const labelListList& cellAnchorPoints,
422  const labelListList& cellAddedCells,
423  const label celli,
424  const label facei,
425  const label pointi
426 ) const
427 {
428  if (cellAnchorPoints[celli].size())
429  {
430  label index = findIndex(cellAnchorPoints[celli], pointi);
431 
432  if (index != -1)
433  {
434  return cellAddedCells[celli][index];
435  }
436 
437 
438  // pointi is not an anchor cell.
439  // Maybe we are already a refined face so check all the face
440  // vertices.
441  const face& f = mesh_.faces()[facei];
442 
443  forAll(f, fp)
444  {
445  label index = findIndex(cellAnchorPoints[celli], f[fp]);
446 
447  if (index != -1)
448  {
449  return cellAddedCells[celli][index];
450  }
451  }
452 
453  // Problem.
454  dumpCell(celli);
455  Perr<< "cell:" << celli << " anchorPoints:" << cellAnchorPoints[celli]
456  << endl;
457 
459  << "Could not find point " << pointi
460  << " in the anchorPoints for cell " << celli << endl
461  << "Does your original mesh obey the 2:1 constraint and"
462  << " did you use consistentRefinement to make your cells to refine"
463  << " obey this constraint as well?"
464  << abort(FatalError);
465 
466  return -1;
467  }
468  else
469  {
470  return celli;
471  }
472 }
473 
474 
475 void Foam::hexRef8::getFaceNeighbours
476 (
477  const labelListList& cellAnchorPoints,
478  const labelListList& cellAddedCells,
479  const label facei,
480  const label pointi,
481 
482  label& own,
483  label& nei
484 ) const
485 {
486  // Is owner split?
487  own = getAnchorCell
488  (
489  cellAnchorPoints,
490  cellAddedCells,
491  mesh_.faceOwner()[facei],
492  facei,
493  pointi
494  );
495 
496  if (mesh_.isInternalFace(facei))
497  {
498  nei = getAnchorCell
499  (
500  cellAnchorPoints,
501  cellAddedCells,
502  mesh_.faceNeighbour()[facei],
503  facei,
504  pointi
505  );
506  }
507  else
508  {
509  nei = -1;
510  }
511 }
512 
513 
514 Foam::label Foam::hexRef8::findMinLevel(const labelList& f) const
515 {
516  label minLevel = labelMax;
517  label minFp = -1;
518 
519  forAll(f, fp)
520  {
521  label level = pointLevel_[f[fp]];
522 
523  if (level < minLevel)
524  {
525  minLevel = level;
526  minFp = fp;
527  }
528  }
529 
530  return minFp;
531 }
532 
533 
534 Foam::label Foam::hexRef8::findMaxLevel(const labelList& f) const
535 {
536  label maxLevel = labelMin;
537  label maxFp = -1;
538 
539  forAll(f, fp)
540  {
541  label level = pointLevel_[f[fp]];
542 
543  if (level > maxLevel)
544  {
545  maxLevel = level;
546  maxFp = fp;
547  }
548  }
549 
550  return maxFp;
551 }
552 
553 
554 Foam::label Foam::hexRef8::countAnchors
555 (
556  const labelList& f,
557  const label anchorLevel
558 ) const
559 {
560  label nAnchors = 0;
561 
562  forAll(f, fp)
563  {
564  if (pointLevel_[f[fp]] <= anchorLevel)
565  {
566  nAnchors++;
567  }
568  }
569  return nAnchors;
570 }
571 
572 
573 void Foam::hexRef8::dumpCell(const label celli) const
574 {
575  OFstream str(mesh_.time().path()/"cell_" + Foam::name(celli) + ".obj");
576  Pout<< "hexRef8 : Dumping cell as obj to " << str.name() << endl;
577 
578  const cell& cFaces = mesh_.cells()[celli];
579 
580  Map<label> pointToObjVert;
581  label objVertI = 0;
582 
583  forAll(cFaces, i)
584  {
585  const face& f = mesh_.faces()[cFaces[i]];
586 
587  forAll(f, fp)
588  {
589  if (pointToObjVert.insert(f[fp], objVertI))
590  {
591  meshTools::writeOBJ(str, mesh_.points()[f[fp]]);
592  objVertI++;
593  }
594  }
595  }
596 
597  forAll(cFaces, i)
598  {
599  const face& f = mesh_.faces()[cFaces[i]];
600 
601  forAll(f, fp)
602  {
603  label pointi = f[fp];
604  label nexPointi = f[f.fcIndex(fp)];
605 
606  str << "l " << pointToObjVert[pointi]+1
607  << ' ' << pointToObjVert[nexPointi]+1 << nl;
608  }
609  }
610 }
611 
612 
613 Foam::label Foam::hexRef8::findLevel
614 (
615  const label facei,
616  const face& f,
617  const label startFp,
618  const bool searchForward,
619  const label wantedLevel
620 ) const
621 {
622  label fp = startFp;
623 
624  forAll(f, i)
625  {
626  label pointi = f[fp];
627 
628  if (pointLevel_[pointi] < wantedLevel)
629  {
630  dumpCell(mesh_.faceOwner()[facei]);
631  if (mesh_.isInternalFace(facei))
632  {
633  dumpCell(mesh_.faceNeighbour()[facei]);
634  }
635 
637  << "face:" << f
638  << " level:" << UIndirectList<label>(pointLevel_, f)()
639  << " startFp:" << startFp
640  << " wantedLevel:" << wantedLevel
641  << abort(FatalError);
642  }
643  else if (pointLevel_[pointi] == wantedLevel)
644  {
645  return fp;
646  }
647 
648  if (searchForward)
649  {
650  fp = f.fcIndex(fp);
651  }
652  else
653  {
654  fp = f.rcIndex(fp);
655  }
656  }
657 
658  dumpCell(mesh_.faceOwner()[facei]);
659  if (mesh_.isInternalFace(facei))
660  {
661  dumpCell(mesh_.faceNeighbour()[facei]);
662  }
663 
665  << "face:" << f
666  << " level:" << UIndirectList<label>(pointLevel_, f)()
667  << " startFp:" << startFp
668  << " wantedLevel:" << wantedLevel
669  << abort(FatalError);
670 
671  return -1;
672 }
673 
674 
676 {
677  const face& f = mesh_.faces()[facei];
678 
679  if (f.size() <= 4)
680  {
681  return pointLevel_[f[findMaxLevel(f)]];
682  }
683  else
684  {
685  label ownLevel = cellLevel_[mesh_.faceOwner()[facei]];
686 
687  if (countAnchors(f, ownLevel) == 4)
688  {
689  return ownLevel;
690  }
691  else if (countAnchors(f, ownLevel+1) == 4)
692  {
693  return ownLevel+1;
694  }
695  else
696  {
697  return -1;
698  }
699  }
700 }
701 
702 
703 void Foam::hexRef8::checkInternalOrientation
704 (
705  polyTopoChange& meshMod,
706  const label celli,
707  const label facei,
708  const point& ownPt,
709  const point& neiPt,
710  const face& newFace
711 )
712 {
713  const face compactFace(identityMap(newFace.size()));
714  const pointField compactPoints(meshMod.points(), newFace);
715 
716  const vector a(compactFace.area(compactPoints));
717 
718  const vector dir(neiPt - ownPt);
719 
720  if ((dir & a) < 0)
721  {
723  << "cell:" << celli << " old face:" << facei
724  << " newFace:" << newFace << endl
725  << " coords:" << compactPoints
726  << " ownPt:" << ownPt
727  << " neiPt:" << neiPt
728  << abort(FatalError);
729  }
730 
731  const vector fcToOwn(compactFace.centre(compactPoints) - ownPt);
732 
733  const scalar s = (fcToOwn & a) / (dir & a);
734 
735  if (s < 0.1 || s > 0.9)
736  {
738  << "cell:" << celli << " old face:" << facei
739  << " newFace:" << newFace << endl
740  << " coords:" << compactPoints
741  << " ownPt:" << ownPt
742  << " neiPt:" << neiPt
743  << " s:" << s
744  << abort(FatalError);
745  }
746 }
747 
748 
749 void Foam::hexRef8::checkBoundaryOrientation
750 (
751  polyTopoChange& meshMod,
752  const label celli,
753  const label facei,
754  const point& ownPt,
755  const point& boundaryPt,
756  const face& newFace
757 )
758 {
759  const face compactFace(identityMap(newFace.size()));
760  const pointField compactPoints(meshMod.points(), newFace);
761 
762  const vector a(compactFace.area(compactPoints));
763 
764  const vector dir(boundaryPt - ownPt);
765 
766  if ((dir & a) < 0)
767  {
769  << "cell:" << celli << " old face:" << facei
770  << " newFace:" << newFace
771  << " coords:" << compactPoints
772  << " ownPt:" << ownPt
773  << " boundaryPt:" << boundaryPt
774  << abort(FatalError);
775  }
776 
777  const vector fcToOwn(compactFace.centre(compactPoints) - ownPt);
778 
779  const scalar s = (fcToOwn&dir) / magSqr(dir);
780 
781  if (s < 0.7 || s > 1.3)
782  {
784  << "cell:" << celli << " old face:" << facei
785  << " newFace:" << newFace
786  << " coords:" << compactPoints
787  << " ownPt:" << ownPt
788  << " boundaryPt:" << boundaryPt
789  << " s:" << s
790  << endl;
791  }
792 }
793 
794 
795 void Foam::hexRef8::insertEdgeSplit
796 (
797  const labelList& edgeMidPoint,
798  const label p0,
799  const label p1,
800  DynamicList<label>& verts
801 ) const
802 {
803  if (p0 < mesh_.nPoints() && p1 < mesh_.nPoints())
804  {
805  label edgeI = meshTools::findEdge(mesh_, p0, p1);
806 
807  if (edgeI != -1 && edgeMidPoint[edgeI] != -1)
808  {
809  verts.append(edgeMidPoint[edgeI]);
810  }
811  }
812 }
813 
814 
815 Foam::label Foam::hexRef8::storeMidPointInfo
816 (
817  const labelListList& cellAnchorPoints,
818  const labelListList& cellAddedCells,
819  const labelList& cellMidPoint,
820  const labelList& edgeMidPoint,
821  const label celli,
822  const label facei,
823  const bool faceOrder,
824  const label edgeMidPointi,
825  const label anchorPointi,
826  const label faceMidPointi,
827 
828  Map<edge>& midPointToAnchors,
829  Map<edge>& midPointToFaceMids,
830  polyTopoChange& meshMod
831 ) const
832 {
833  // See if need to store anchors.
834 
835  bool changed = false;
836  bool haveTwoAnchors = false;
837 
838  Map<edge>::iterator edgeMidFnd = midPointToAnchors.find(edgeMidPointi);
839 
840  if (edgeMidFnd == midPointToAnchors.end())
841  {
842  midPointToAnchors.insert(edgeMidPointi, edge(anchorPointi, -1));
843  }
844  else
845  {
846  edge& e = edgeMidFnd();
847 
848  if (anchorPointi != e[0])
849  {
850  if (e[1] == -1)
851  {
852  e[1] = anchorPointi;
853  changed = true;
854  }
855  }
856 
857  if (e[0] != -1 && e[1] != -1)
858  {
859  haveTwoAnchors = true;
860  }
861  }
862 
863  bool haveTwoFaceMids = false;
864 
865  Map<edge>::iterator faceMidFnd = midPointToFaceMids.find(edgeMidPointi);
866 
867  if (faceMidFnd == midPointToFaceMids.end())
868  {
869  midPointToFaceMids.insert(edgeMidPointi, edge(faceMidPointi, -1));
870  }
871  else
872  {
873  edge& e = faceMidFnd();
874 
875  if (faceMidPointi != e[0])
876  {
877  if (e[1] == -1)
878  {
879  e[1] = faceMidPointi;
880  changed = true;
881  }
882  }
883 
884  if (e[0] != -1 && e[1] != -1)
885  {
886  haveTwoFaceMids = true;
887  }
888  }
889 
890  // Check if this call of storeMidPointInfo is the one that completed all
891  // the necessary information.
892 
893  if (changed && haveTwoAnchors && haveTwoFaceMids)
894  {
895  const edge& anchors = midPointToAnchors[edgeMidPointi];
896  const edge& faceMids = midPointToFaceMids[edgeMidPointi];
897 
898  label otherFaceMidPointi = faceMids.otherVertex(faceMidPointi);
899 
900  // Create face consistent with anchorI being the owner.
901  // Note that the edges between the edge mid point and the face mids
902  // might be marked for splitting. Note that these edge splits cannot
903  // be between cellMid and face mids.
904 
905  DynamicList<label> newFaceVerts(4);
906  if (faceOrder == (mesh_.faceOwner()[facei] == celli))
907  {
908  newFaceVerts.append(faceMidPointi);
909 
910  // Check & insert edge split if any
911  insertEdgeSplit
912  (
913  edgeMidPoint,
914  faceMidPointi, // edge between faceMid and
915  edgeMidPointi, // edgeMid
916  newFaceVerts
917  );
918 
919  newFaceVerts.append(edgeMidPointi);
920 
921  insertEdgeSplit
922  (
923  edgeMidPoint,
924  edgeMidPointi,
925  otherFaceMidPointi,
926  newFaceVerts
927  );
928 
929  newFaceVerts.append(otherFaceMidPointi);
930  newFaceVerts.append(cellMidPoint[celli]);
931  }
932  else
933  {
934  newFaceVerts.append(otherFaceMidPointi);
935 
936  insertEdgeSplit
937  (
938  edgeMidPoint,
939  otherFaceMidPointi,
940  edgeMidPointi,
941  newFaceVerts
942  );
943 
944  newFaceVerts.append(edgeMidPointi);
945 
946  insertEdgeSplit
947  (
948  edgeMidPoint,
949  edgeMidPointi,
950  faceMidPointi,
951  newFaceVerts
952  );
953 
954  newFaceVerts.append(faceMidPointi);
955  newFaceVerts.append(cellMidPoint[celli]);
956  }
957 
958  face newFace;
959  newFace.transfer(newFaceVerts);
960 
961  label anchorCell0 = getAnchorCell
962  (
963  cellAnchorPoints,
964  cellAddedCells,
965  celli,
966  facei,
967  anchorPointi
968  );
969  label anchorCell1 = getAnchorCell
970  (
971  cellAnchorPoints,
972  cellAddedCells,
973  celli,
974  facei,
975  anchors.otherVertex(anchorPointi)
976  );
977 
978 
979  label own, nei;
980  point ownPt, neiPt;
981 
982  if (anchorCell0 < anchorCell1)
983  {
984  own = anchorCell0;
985  nei = anchorCell1;
986 
987  ownPt = mesh_.points()[anchorPointi];
988  neiPt = mesh_.points()[anchors.otherVertex(anchorPointi)];
989 
990  }
991  else
992  {
993  own = anchorCell1;
994  nei = anchorCell0;
995  newFace.flip();
996 
997  ownPt = mesh_.points()[anchors.otherVertex(anchorPointi)];
998  neiPt = mesh_.points()[anchorPointi];
999  }
1000 
1001  if (debug)
1002  {
1003  point ownPt, neiPt;
1004 
1005  if (anchorCell0 < anchorCell1)
1006  {
1007  ownPt = mesh_.points()[anchorPointi];
1008  neiPt = mesh_.points()[anchors.otherVertex(anchorPointi)];
1009  }
1010  else
1011  {
1012  ownPt = mesh_.points()[anchors.otherVertex(anchorPointi)];
1013  neiPt = mesh_.points()[anchorPointi];
1014  }
1015 
1016  checkInternalOrientation
1017  (
1018  meshMod,
1019  celli,
1020  facei,
1021  ownPt,
1022  neiPt,
1023  newFace
1024  );
1025  }
1026 
1027  return addInternalFace
1028  (
1029  meshMod,
1030  facei,
1031  anchorPointi,
1032  newFace,
1033  own,
1034  nei
1035  );
1036  }
1037  else
1038  {
1039  return -1;
1040  }
1041 }
1042 
1043 
1044 void Foam::hexRef8::createInternalFaces
1045 (
1046  const labelListList& cellAnchorPoints,
1047  const labelListList& cellAddedCells,
1048  const labelList& cellMidPoint,
1049  const labelList& faceMidPoint,
1050  const labelList& faceAnchorLevel,
1051  const labelList& edgeMidPoint,
1052  const label celli,
1053 
1054  polyTopoChange& meshMod
1055 ) const
1056 {
1057  // Find in every face the cellLevel+1 points (from edge subdivision)
1058  // and the anchor points.
1059 
1060  const cell& cFaces = mesh_.cells()[celli];
1061  const label cLevel = cellLevel_[celli];
1062 
1063  // From edge mid to anchor points
1064  Map<edge> midPointToAnchors(24);
1065  // From edge mid to face mids
1066  Map<edge> midPointToFaceMids(24);
1067 
1068  // Storage for on-the-fly addressing
1069  DynamicList<label> storage;
1070 
1071 
1072  // Running count of number of internal faces added so far.
1073  label nFacesAdded = 0;
1074 
1075  forAll(cFaces, i)
1076  {
1077  label facei = cFaces[i];
1078 
1079  const face& f = mesh_.faces()[facei];
1080  const labelList& fEdges = mesh_.faceEdges(facei, storage);
1081 
1082  // We are on the celli side of face f. The face will have 1 or 4
1083  // cLevel points and lots of higher numbered ones.
1084 
1085  label faceMidPointi = -1;
1086 
1087  label nAnchors = countAnchors(f, cLevel);
1088 
1089  if (nAnchors == 1)
1090  {
1091  // Only one anchor point. So the other side of the face has already
1092  // been split using cLevel+1 and cLevel+2 points.
1093 
1094  // Find the one anchor.
1095  label anchorFp = -1;
1096 
1097  forAll(f, fp)
1098  {
1099  if (pointLevel_[f[fp]] <= cLevel)
1100  {
1101  anchorFp = fp;
1102  break;
1103  }
1104  }
1105 
1106  // Now the face mid point is the second cLevel+1 point
1107  label edgeMid = findLevel
1108  (
1109  facei,
1110  f,
1111  f.fcIndex(anchorFp),
1112  true,
1113  cLevel+1
1114  );
1115  label faceMid = findLevel
1116  (
1117  facei,
1118  f,
1119  f.fcIndex(edgeMid),
1120  true,
1121  cLevel+1
1122  );
1123 
1124  faceMidPointi = f[faceMid];
1125  }
1126  else if (nAnchors == 4)
1127  {
1128  // There is no face middle yet but the face will be marked for
1129  // splitting.
1130 
1131  faceMidPointi = faceMidPoint[facei];
1132  }
1133  else
1134  {
1135  dumpCell(mesh_.faceOwner()[facei]);
1136  if (mesh_.isInternalFace(facei))
1137  {
1138  dumpCell(mesh_.faceNeighbour()[facei]);
1139  }
1140 
1142  << "nAnchors:" << nAnchors
1143  << " facei:" << facei
1144  << abort(FatalError);
1145  }
1146 
1147 
1148 
1149  // Now loop over all the anchors (might be just one) and store
1150  // the edge mids connected to it. storeMidPointInfo will collect
1151  // all the info and combine it all.
1152 
1153  forAll(f, fp0)
1154  {
1155  label point0 = f[fp0];
1156 
1157  if (pointLevel_[point0] <= cLevel)
1158  {
1159  // Anchor.
1160 
1161  // Walk forward
1162  // ~~~~~~~~~~~~
1163  // to cLevel+1 or edgeMidPoint of this level.
1164 
1165 
1166  label edgeMidPointi = -1;
1167 
1168  label fp1 = f.fcIndex(fp0);
1169 
1170  if (pointLevel_[f[fp1]] <= cLevel)
1171  {
1172  // Anchor. Edge will be split.
1173  label edgeI = fEdges[fp0];
1174 
1175  edgeMidPointi = edgeMidPoint[edgeI];
1176 
1177  if (edgeMidPointi == -1)
1178  {
1179  dumpCell(celli);
1180 
1181  const labelList& cPoints = mesh_.cellPoints(celli);
1182 
1184  << "cell:" << celli << " cLevel:" << cLevel
1185  << " cell points:" << cPoints
1186  << " pointLevel:"
1187  << UIndirectList<label>(pointLevel_, cPoints)()
1188  << " face:" << facei
1189  << " f:" << f
1190  << " pointLevel:"
1191  << UIndirectList<label>(pointLevel_, f)()
1192  << " faceAnchorLevel:" << faceAnchorLevel[facei]
1193  << " faceMidPoint:" << faceMidPoint[facei]
1194  << " faceMidPointi:" << faceMidPointi
1195  << " fp:" << fp0
1196  << abort(FatalError);
1197  }
1198  }
1199  else
1200  {
1201  // Search forward in face to clevel+1
1202  label edgeMid = findLevel(facei, f, fp1, true, cLevel+1);
1203 
1204  edgeMidPointi = f[edgeMid];
1205  }
1206 
1207  label newFacei = storeMidPointInfo
1208  (
1209  cellAnchorPoints,
1210  cellAddedCells,
1211  cellMidPoint,
1212  edgeMidPoint,
1213 
1214  celli,
1215  facei,
1216  true, // mid point after anchor
1217  edgeMidPointi, // edgemid
1218  point0, // anchor
1219  faceMidPointi,
1220 
1221  midPointToAnchors,
1222  midPointToFaceMids,
1223  meshMod
1224  );
1225 
1226  if (newFacei != -1)
1227  {
1228  nFacesAdded++;
1229 
1230  if (nFacesAdded == 12)
1231  {
1232  break;
1233  }
1234  }
1235 
1236 
1237 
1238  // Walk backward
1239  // ~~~~~~~~~~~~~
1240 
1241  label fpMin1 = f.rcIndex(fp0);
1242 
1243  if (pointLevel_[f[fpMin1]] <= cLevel)
1244  {
1245  // Anchor. Edge will be split.
1246  label edgeI = fEdges[fpMin1];
1247 
1248  edgeMidPointi = edgeMidPoint[edgeI];
1249 
1250  if (edgeMidPointi == -1)
1251  {
1252  dumpCell(celli);
1253 
1254  const labelList& cPoints = mesh_.cellPoints(celli);
1255 
1257  << "cell:" << celli << " cLevel:" << cLevel
1258  << " cell points:" << cPoints
1259  << " pointLevel:"
1260  << UIndirectList<label>(pointLevel_, cPoints)()
1261  << " face:" << facei
1262  << " f:" << f
1263  << " pointLevel:"
1264  << UIndirectList<label>(pointLevel_, f)()
1265  << " faceAnchorLevel:" << faceAnchorLevel[facei]
1266  << " faceMidPoint:" << faceMidPoint[facei]
1267  << " faceMidPointi:" << faceMidPointi
1268  << " fp:" << fp0
1269  << abort(FatalError);
1270  }
1271  }
1272  else
1273  {
1274  // Search back to clevel+1
1275  label edgeMid = findLevel
1276  (
1277  facei,
1278  f,
1279  fpMin1,
1280  false,
1281  cLevel+1
1282  );
1283 
1284  edgeMidPointi = f[edgeMid];
1285  }
1286 
1287  newFacei = storeMidPointInfo
1288  (
1289  cellAnchorPoints,
1290  cellAddedCells,
1291  cellMidPoint,
1292  edgeMidPoint,
1293 
1294  celli,
1295  facei,
1296  false, // mid point before anchor
1297  edgeMidPointi, // edgemid
1298  point0, // anchor
1299  faceMidPointi,
1300 
1301  midPointToAnchors,
1302  midPointToFaceMids,
1303  meshMod
1304  );
1305 
1306  if (newFacei != -1)
1307  {
1308  nFacesAdded++;
1309 
1310  if (nFacesAdded == 12)
1311  {
1312  break;
1313  }
1314  }
1315  } // done anchor
1316  } // done face
1317 
1318  if (nFacesAdded == 12)
1319  {
1320  break;
1321  }
1322  }
1323 }
1324 
1325 
1326 void Foam::hexRef8::walkFaceToMid
1327 (
1328  const labelList& edgeMidPoint,
1329  const label cLevel,
1330  const label facei,
1331  const label startFp,
1332  DynamicList<label>& faceVerts
1333 ) const
1334 {
1335  const face& f = mesh_.faces()[facei];
1336  const labelList& fEdges = mesh_.faceEdges(facei);
1337 
1338  label fp = startFp;
1339 
1340  // Starting from fp store all (1 or 2) vertices until where the face
1341  // gets split
1342 
1343  while (true)
1344  {
1345  if (edgeMidPoint[fEdges[fp]] >= 0)
1346  {
1347  faceVerts.append(edgeMidPoint[fEdges[fp]]);
1348  }
1349 
1350  fp = f.fcIndex(fp);
1351 
1352  if (pointLevel_[f[fp]] <= cLevel)
1353  {
1354  // Next anchor. Have already append split point on edge in code
1355  // above.
1356  return;
1357  }
1358  else if (pointLevel_[f[fp]] == cLevel+1)
1359  {
1360  // Mid level
1361  faceVerts.append(f[fp]);
1362 
1363  return;
1364  }
1365  else if (pointLevel_[f[fp]] == cLevel+2)
1366  {
1367  // Store and continue to cLevel+1.
1368  faceVerts.append(f[fp]);
1369  }
1370  }
1371 }
1372 
1373 
1374 void Foam::hexRef8::walkFaceFromMid
1375 (
1376  const labelList& edgeMidPoint,
1377  const label cLevel,
1378  const label facei,
1379  const label startFp,
1380  DynamicList<label>& faceVerts
1381 ) const
1382 {
1383  const face& f = mesh_.faces()[facei];
1384  const labelList& fEdges = mesh_.faceEdges(facei);
1385 
1386  label fp = f.rcIndex(startFp);
1387 
1388  while (true)
1389  {
1390  if (pointLevel_[f[fp]] <= cLevel)
1391  {
1392  // anchor.
1393  break;
1394  }
1395  else if (pointLevel_[f[fp]] == cLevel+1)
1396  {
1397  // Mid level
1398  faceVerts.append(f[fp]);
1399  break;
1400  }
1401  else if (pointLevel_[f[fp]] == cLevel+2)
1402  {
1403  // Continue to cLevel+1.
1404  }
1405  fp = f.rcIndex(fp);
1406  }
1407 
1408  // Store
1409  while (true)
1410  {
1411  if (edgeMidPoint[fEdges[fp]] >= 0)
1412  {
1413  faceVerts.append(edgeMidPoint[fEdges[fp]]);
1414  }
1415 
1416  fp = f.fcIndex(fp);
1417 
1418  if (fp == startFp)
1419  {
1420  break;
1421  }
1422  faceVerts.append(f[fp]);
1423  }
1424 }
1425 
1426 
1427 Foam::label Foam::hexRef8::faceConsistentRefinement
1428 (
1429  const bool maxSet,
1430  PackedBoolList& refineCell
1431 ) const
1432 {
1433  label nChanged = 0;
1434 
1435  // Internal faces.
1436  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
1437  {
1438  label own = mesh_.faceOwner()[facei];
1439  label ownLevel = cellLevel_[own] + refineCell.get(own);
1440 
1441  label nei = mesh_.faceNeighbour()[facei];
1442  label neiLevel = cellLevel_[nei] + refineCell.get(nei);
1443 
1444  if (ownLevel > (neiLevel+1))
1445  {
1446  if (maxSet)
1447  {
1448  refineCell.set(nei);
1449  }
1450  else
1451  {
1452  refineCell.unset(own);
1453  }
1454  nChanged++;
1455  }
1456  else if (neiLevel > (ownLevel+1))
1457  {
1458  if (maxSet)
1459  {
1460  refineCell.set(own);
1461  }
1462  else
1463  {
1464  refineCell.unset(nei);
1465  }
1466  nChanged++;
1467  }
1468  }
1469 
1470 
1471  // Coupled faces. Swap owner level to get neighbouring cell level.
1472  // (only boundary faces of neiLevel used)
1473  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1474 
1475  forAll(neiLevel, i)
1476  {
1477  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
1478 
1479  neiLevel[i] = cellLevel_[own] + refineCell.get(own);
1480  }
1481 
1482  // Swap to neighbour
1483  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
1484 
1485  // Now we have neighbour value see which cells need refinement
1486  forAll(neiLevel, i)
1487  {
1488  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
1489  label ownLevel = cellLevel_[own] + refineCell.get(own);
1490 
1491  if (ownLevel > (neiLevel[i]+1))
1492  {
1493  if (!maxSet)
1494  {
1495  refineCell.unset(own);
1496  nChanged++;
1497  }
1498  }
1499  else if (neiLevel[i] > (ownLevel+1))
1500  {
1501  if (maxSet)
1502  {
1503  refineCell.set(own);
1504  nChanged++;
1505  }
1506  }
1507  }
1508 
1509  return nChanged;
1510 }
1511 
1512 
1513 void Foam::hexRef8::checkWantedRefinementLevels
1514 (
1515  const labelList& cellsToRefine
1516 ) const
1517 {
1518  PackedBoolList refineCell(mesh_.nCells());
1519  forAll(cellsToRefine, i)
1520  {
1521  refineCell.set(cellsToRefine[i]);
1522  }
1523 
1524  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
1525  {
1526  label own = mesh_.faceOwner()[facei];
1527  label ownLevel = cellLevel_[own] + refineCell.get(own);
1528 
1529  label nei = mesh_.faceNeighbour()[facei];
1530  label neiLevel = cellLevel_[nei] + refineCell.get(nei);
1531 
1532  if (mag(ownLevel-neiLevel) > 1)
1533  {
1534  dumpCell(own);
1535  dumpCell(nei);
1537  << "cell:" << own
1538  << " current level:" << cellLevel_[own]
1539  << " level after refinement:" << ownLevel
1540  << nl
1541  << "neighbour cell:" << nei
1542  << " current level:" << cellLevel_[nei]
1543  << " level after refinement:" << neiLevel
1544  << nl
1545  << "which does not satisfy 2:1 constraints anymore."
1546  << abort(FatalError);
1547  }
1548  }
1549 
1550  // Coupled faces. Swap owner level to get neighbouring cell level.
1551  // (only boundary faces of neiLevel used)
1552  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1553 
1554  forAll(neiLevel, i)
1555  {
1556  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
1557 
1558  neiLevel[i] = cellLevel_[own] + refineCell.get(own);
1559  }
1560 
1561  // Swap to neighbour
1562  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
1563 
1564  // Now we have neighbour value see which cells need refinement
1565  forAll(neiLevel, i)
1566  {
1567  label facei = i + mesh_.nInternalFaces();
1568 
1569  label own = mesh_.faceOwner()[facei];
1570  label ownLevel = cellLevel_[own] + refineCell.get(own);
1571 
1572  if (mag(ownLevel - neiLevel[i]) > 1)
1573  {
1574  label patchi = mesh_.boundaryMesh().whichPatch(facei);
1575 
1576  dumpCell(own);
1578  << "Celllevel does not satisfy 2:1 constraint."
1579  << " On coupled face "
1580  << facei
1581  << " on patch " << patchi << " "
1582  << mesh_.boundaryMesh()[patchi].name()
1583  << " owner cell " << own
1584  << " current level:" << cellLevel_[own]
1585  << " level after refinement:" << ownLevel
1586  << nl
1587  << " (coupled) neighbour cell will get refinement "
1588  << neiLevel[i]
1589  << abort(FatalError);
1590  }
1591  }
1592 }
1593 
1594 
1596 {
1597  if (debug)
1598  {
1599  Pout<< "hexRef8::setInstance(const fileName& inst) : "
1600  << "Resetting file instance to " << inst << endl;
1601  }
1602 
1603  cellLevel_.instance() = inst;
1604  pointLevel_.instance() = inst;
1605  level0Edge_.instance() = inst;
1606  history_.instance() = inst;
1607 }
1608 
1609 
1610 void Foam::hexRef8::collectLevelPoints
1611 (
1612  const labelList& f,
1613  const label level,
1615 ) const
1616 {
1617  forAll(f, fp)
1618  {
1619  if (pointLevel_[f[fp]] <= level)
1620  {
1621  points.append(f[fp]);
1622  }
1623  }
1624 }
1625 
1626 
1627 void Foam::hexRef8::collectLevelPoints
1628 (
1629  const labelList& meshPoints,
1630  const labelList& f,
1631  const label level,
1632  DynamicList<label>& points
1633 ) const
1634 {
1635  forAll(f, fp)
1636  {
1637  label pointi = meshPoints[f[fp]];
1638  if (pointLevel_[pointi] <= level)
1639  {
1640  points.append(pointi);
1641  }
1642  }
1643 }
1644 
1645 
1646 bool Foam::hexRef8::matchHexShape
1647 (
1648  const label celli,
1649  const label cellLevel,
1650  DynamicList<face>& quads
1651 ) const
1652 {
1653  const cell& cFaces = mesh_.cells()[celli];
1654 
1655  // Work arrays
1656  DynamicList<label> verts(4);
1657  quads.clear();
1658 
1659 
1660  // 1. pick up any faces with four cellLevel points
1661 
1662  forAll(cFaces, i)
1663  {
1664  label facei = cFaces[i];
1665  const face& f = mesh_.faces()[facei];
1666 
1667  verts.clear();
1668  collectLevelPoints(f, cellLevel, verts);
1669  if (verts.size() == 4)
1670  {
1671  if (mesh_.faceOwner()[facei] != celli)
1672  {
1673  reverse(verts);
1674  }
1675  quads.append(face(0));
1676  labelList& quadVerts = quads.last();
1677  quadVerts.transfer(verts);
1678  }
1679  }
1680 
1681 
1682  if (quads.size() < 6)
1683  {
1684  Map<labelList> pointFaces(2*cFaces.size());
1685 
1686  forAll(cFaces, i)
1687  {
1688  label facei = cFaces[i];
1689  const face& f = mesh_.faces()[facei];
1690 
1691  // Pick up any faces with only one level point.
1692  // See if there are four of these where the common point
1693  // is a level+1 point. This common point is then the mid of
1694  // a split face.
1695 
1696  verts.clear();
1697  collectLevelPoints(f, cellLevel, verts);
1698  if (verts.size() == 1)
1699  {
1700  // Add to pointFaces for any level+1 point (this might be
1701  // a midpoint of a split face)
1702  forAll(f, fp)
1703  {
1704  label pointi = f[fp];
1705  if (pointLevel_[pointi] == cellLevel+1)
1706  {
1708  pointFaces.find(pointi);
1709  if (iter != pointFaces.end())
1710  {
1711  labelList& pFaces = iter();
1712  if (findIndex(pFaces, facei) == -1)
1713  {
1714  pFaces.append(facei);
1715  }
1716  }
1717  else
1718  {
1719  pointFaces.insert
1720  (
1721  pointi,
1722  labelList(1, facei)
1723  );
1724  }
1725  }
1726  }
1727  }
1728  }
1729 
1730  // 2. Check if we've collected any midPoints.
1731  forAllConstIter(Map<labelList>, pointFaces, iter)
1732  {
1733  const labelList& pFaces = iter();
1734 
1735  if (pFaces.size() == 4)
1736  {
1737  // Collect and orient.
1738  faceList fourFaces(pFaces.size());
1739  forAll(pFaces, pFacei)
1740  {
1741  label facei = pFaces[pFacei];
1742  const face& f = mesh_.faces()[facei];
1743  if (mesh_.faceOwner()[facei] == celli)
1744  {
1745  fourFaces[pFacei] = f;
1746  }
1747  else
1748  {
1749  fourFaces[pFacei] = f.reverseFace();
1750  }
1751  }
1752 
1753  primitivePatch bigFace
1754  (
1755  SubList<face>(fourFaces, fourFaces.size()),
1756  mesh_.points()
1757  );
1758  const labelListList& edgeLoops = bigFace.edgeLoops();
1759 
1760  if (edgeLoops.size() == 1)
1761  {
1762  // Collect the 4 cellLevel points
1763  verts.clear();
1764  collectLevelPoints
1765  (
1766  bigFace.meshPoints(),
1767  bigFace.edgeLoops()[0],
1768  cellLevel,
1769  verts
1770  );
1771 
1772  if (verts.size() == 4)
1773  {
1774  quads.append(face(0));
1775  labelList& quadVerts = quads.last();
1776  quadVerts.transfer(verts);
1777  }
1778  }
1779  }
1780  }
1781  }
1782 
1783  return (quads.size() == 6);
1784 }
1785 
1786 
1787 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1788 
1789 Foam::hexRef8::hexRef8(const polyMesh& mesh, const bool readHistory)
1790 :
1791  mesh_(mesh),
1792  cellLevel_
1793  (
1794  IOobject
1795  (
1796  "cellLevel",
1797  mesh_.facesInstance(),
1798  polyMesh::meshSubDir,
1799  mesh_,
1800  IOobject::READ_IF_PRESENT,
1801  IOobject::NO_WRITE
1802  ),
1803  labelList(mesh_.nCells(), 0)
1804  ),
1805  pointLevel_
1806  (
1807  IOobject
1808  (
1809  "pointLevel",
1810  mesh_.facesInstance(),
1811  polyMesh::meshSubDir,
1812  mesh_,
1813  IOobject::READ_IF_PRESENT,
1814  IOobject::NO_WRITE
1815  ),
1816  labelList(mesh_.nPoints(), 0)
1817  ),
1818  level0Edge_
1819  (
1820  IOobject
1821  (
1822  "level0Edge",
1823  mesh_.facesInstance(),
1824  polyMesh::meshSubDir,
1825  mesh_,
1826  IOobject::READ_IF_PRESENT,
1827  IOobject::NO_WRITE
1828  ),
1829  dimensionedScalar(dimLength, getLevel0EdgeLength())
1830  ),
1831  history_
1832  (
1833  IOobject
1834  (
1835  "refinementHistory",
1836  mesh_.facesInstance(),
1837  polyMesh::meshSubDir,
1838  mesh_,
1839  IOobject::NO_READ,
1840  IOobject::NO_WRITE
1841  ),
1842  // All cells visible if not read or readHistory = false
1843  (readHistory ? mesh_.nCells() : 0)
1844  ),
1845  faceRemover_(mesh_, great), // merge boundary faces wherever possible
1846  savedPointLevel_(0),
1847  savedCellLevel_(0)
1848 {
1849  if (readHistory)
1850  {
1851  // Make sure we don't use the master-only reading. Bit of a hack for
1852  // now.
1853  regIOobject::fileCheckTypes oldType =
1856  history_.readOpt() = IOobject::READ_IF_PRESENT;
1857  if (history_.headerOk())
1858  {
1859  history_.read();
1860  }
1862  }
1863 
1864  if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
1865  {
1867  << "History enabled but number of visible cells "
1868  << history_.visibleCells().size() << " in "
1869  << history_.objectPath()
1870  << " is not equal to the number of cells in the mesh "
1871  << mesh_.nCells()
1872  << abort(FatalError);
1873  }
1874 
1875  if
1876  (
1877  cellLevel_.size() != mesh_.nCells()
1878  || pointLevel_.size() != mesh_.nPoints()
1879  )
1880  {
1882  << "Restarted from inconsistent cellLevel or pointLevel files."
1883  << endl
1884  << "cellLevel file " << cellLevel_.objectPath() << endl
1885  << "pointLevel file " << pointLevel_.objectPath() << endl
1886  << "Number of cells in mesh:" << mesh_.nCells()
1887  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
1888  << "Number of points in mesh:" << mesh_.nPoints()
1889  << " does not equal size of pointLevel:" << pointLevel_.size()
1890  << abort(FatalError);
1891  }
1892 
1893 
1894  // Check refinement levels for consistency
1896 
1897 
1898  // Check initial mesh for consistency
1899 
1900  // if (debug)
1901  {
1902  checkMesh();
1903  }
1904 }
1905 
1906 
1908 (
1909  const polyMesh& mesh,
1910  const labelList& cellLevel,
1911  const labelList& pointLevel,
1912  const refinementHistory& history,
1913  const scalar level0Edge
1914 )
1915 :
1916  mesh_(mesh),
1917  cellLevel_
1918  (
1919  IOobject
1920  (
1921  "cellLevel",
1922  mesh_.facesInstance(),
1923  polyMesh::meshSubDir,
1924  mesh_,
1925  IOobject::NO_READ,
1926  IOobject::NO_WRITE
1927  ),
1928  cellLevel
1929  ),
1930  pointLevel_
1931  (
1932  IOobject
1933  (
1934  "pointLevel",
1935  mesh_.facesInstance(),
1936  polyMesh::meshSubDir,
1937  mesh_,
1938  IOobject::NO_READ,
1939  IOobject::NO_WRITE
1940  ),
1941  pointLevel
1942  ),
1943  level0Edge_
1944  (
1945  IOobject
1946  (
1947  "level0Edge",
1948  mesh_.facesInstance(),
1949  polyMesh::meshSubDir,
1950  mesh_,
1951  IOobject::NO_READ,
1952  IOobject::NO_WRITE
1953  ),
1955  (
1956  dimLength,
1957  (level0Edge >= 0 ? level0Edge : getLevel0EdgeLength())
1958  )
1959  ),
1960  history_
1961  (
1962  IOobject
1963  (
1964  "refinementHistory",
1965  mesh_.facesInstance(),
1966  polyMesh::meshSubDir,
1967  mesh_,
1968  IOobject::NO_READ,
1969  IOobject::NO_WRITE
1970  ),
1971  history
1972  ),
1973  faceRemover_(mesh_, great), // merge boundary faces wherever possible
1974  savedPointLevel_(0),
1975  savedCellLevel_(0)
1976 {
1977  if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
1978  {
1980  << "History enabled but number of visible cells in it "
1981  << history_.visibleCells().size()
1982  << " is not equal to the number of cells in the mesh "
1983  << mesh_.nCells() << abort(FatalError);
1984  }
1985 
1986  if
1987  (
1988  cellLevel_.size() != mesh_.nCells()
1989  || pointLevel_.size() != mesh_.nPoints()
1990  )
1991  {
1993  << "Incorrect cellLevel or pointLevel size." << endl
1994  << "Number of cells in mesh:" << mesh_.nCells()
1995  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
1996  << "Number of points in mesh:" << mesh_.nPoints()
1997  << " does not equal size of pointLevel:" << pointLevel_.size()
1998  << abort(FatalError);
1999  }
2000 
2001  // Check refinement levels for consistency
2003 
2004 
2005  // Check initial mesh for consistency
2006 
2007  // if (debug)
2008  {
2009  checkMesh();
2010  }
2011 }
2012 
2013 
2015 (
2016  const polyMesh& mesh,
2017  const labelList& cellLevel,
2018  const labelList& pointLevel,
2019  const scalar level0Edge
2020 )
2021 :
2022  mesh_(mesh),
2023  cellLevel_
2024  (
2025  IOobject
2026  (
2027  "cellLevel",
2028  mesh_.facesInstance(),
2029  polyMesh::meshSubDir,
2030  mesh_,
2031  IOobject::NO_READ,
2032  IOobject::NO_WRITE
2033  ),
2034  cellLevel
2035  ),
2036  pointLevel_
2037  (
2038  IOobject
2039  (
2040  "pointLevel",
2041  mesh_.facesInstance(),
2042  polyMesh::meshSubDir,
2043  mesh_,
2044  IOobject::NO_READ,
2045  IOobject::NO_WRITE
2046  ),
2047  pointLevel
2048  ),
2049  level0Edge_
2050  (
2051  IOobject
2052  (
2053  "level0Edge",
2054  mesh_.facesInstance(),
2055  polyMesh::meshSubDir,
2056  mesh_,
2057  IOobject::NO_READ,
2058  IOobject::NO_WRITE
2059  ),
2061  (
2062  dimLength,
2063  (level0Edge >= 0 ? level0Edge : getLevel0EdgeLength())
2064  )
2065  ),
2066  history_
2067  (
2068  IOobject
2069  (
2070  "refinementHistory",
2071  mesh_.facesInstance(),
2072  polyMesh::meshSubDir,
2073  mesh_,
2074  IOobject::NO_READ,
2075  IOobject::NO_WRITE
2076  ),
2077  List<refinementHistory::splitCell8>(0),
2078  labelList(0),
2079  false
2080  ),
2081  faceRemover_(mesh_, great), // merge boundary faces wherever possible
2082  savedPointLevel_(0),
2083  savedCellLevel_(0)
2084 {
2085  if
2086  (
2087  cellLevel_.size() != mesh_.nCells()
2088  || pointLevel_.size() != mesh_.nPoints()
2089  )
2090  {
2092  << "Incorrect cellLevel or pointLevel size." << endl
2093  << "Number of cells in mesh:" << mesh_.nCells()
2094  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
2095  << "Number of points in mesh:" << mesh_.nPoints()
2096  << " does not equal size of pointLevel:" << pointLevel_.size()
2097  << abort(FatalError);
2098  }
2099 
2100  // Check refinement levels for consistency
2102 
2103  // Check initial mesh for consistency
2104 
2105  // if (debug)
2106  {
2107  checkMesh();
2108  }
2109 }
2110 
2111 
2112 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2113 
2115 (
2116  const labelList& cellsToRefine,
2117  const bool maxSet
2118 ) const
2119 {
2120  // Loop, modifying cellsToRefine, until no more changes to due to 2:1
2121  // conflicts.
2122  // maxSet = false : deselect cells to refine
2123  // maxSet = true : select cells to refine
2124 
2125  // Go to straight boolList.
2126  PackedBoolList refineCell(mesh_.nCells());
2127  forAll(cellsToRefine, i)
2128  {
2129  refineCell.set(cellsToRefine[i]);
2130  }
2131 
2132  while (true)
2133  {
2134  label nChanged = faceConsistentRefinement(maxSet, refineCell);
2135 
2136  reduce(nChanged, sumOp<label>());
2137 
2138  if (debug)
2139  {
2140  Pout<< "hexRef8::consistentRefinement : Changed " << nChanged
2141  << " refinement levels due to 2:1 conflicts."
2142  << endl;
2143  }
2144 
2145  if (nChanged == 0)
2146  {
2147  break;
2148  }
2149  }
2150 
2151 
2152  // Convert back to labelList.
2153  label nRefined = 0;
2154 
2155  forAll(refineCell, celli)
2156  {
2157  if (refineCell.get(celli))
2158  {
2159  nRefined++;
2160  }
2161  }
2162 
2163  labelList newCellsToRefine(nRefined);
2164  nRefined = 0;
2165 
2166  forAll(refineCell, celli)
2167  {
2168  if (refineCell.get(celli))
2169  {
2170  newCellsToRefine[nRefined++] = celli;
2171  }
2172  }
2173 
2174  if (debug)
2175  {
2176  checkWantedRefinementLevels(newCellsToRefine);
2177  }
2178 
2179  return newCellsToRefine;
2180 }
2181 
2182 
2184 (
2185  const label maxFaceDiff,
2186  const labelList& cellsToRefine,
2187  const labelList& facesToCheck,
2188  const label maxPointDiff,
2189  const labelList& pointsToCheck
2190 ) const
2191 {
2192  const labelList& faceOwner = mesh_.faceOwner();
2193  const labelList& faceNeighbour = mesh_.faceNeighbour();
2194 
2195 
2196  if (maxFaceDiff <= 0)
2197  {
2199  << "Illegal maxFaceDiff " << maxFaceDiff << nl
2200  << "Value should be >= 1" << exit(FatalError);
2201  }
2202 
2203 
2204  // Bit tricky. Say we want a distance of three cells between two
2205  // consecutive refinement levels. This is done by using FaceCellWave to
2206  // transport out the new refinement level. It gets decremented by one
2207  // every cell it crosses so if we initialise it to maxFaceDiff
2208  // we will get a field everywhere that tells us whether an unselected cell
2209  // needs refining as well.
2210 
2211 
2212  // Initial information about (distance to) cellLevel on all cells
2213  List<refinementData> allCellInfo(mesh_.nCells());
2214 
2215  // Initial information about (distance to) cellLevel on all faces
2216  List<refinementData> allFaceInfo(mesh_.nFaces());
2217 
2218  forAll(allCellInfo, celli)
2219  {
2220  // maxFaceDiff since refinementData counts both
2221  // faces and cells.
2222  allCellInfo[celli] = refinementData
2223  (
2224  maxFaceDiff*(cellLevel_[celli]+1),// when cell is to be refined
2225  maxFaceDiff*cellLevel_[celli] // current level
2226  );
2227  }
2228 
2229  // Cells to be refined will have cellLevel+1
2230  forAll(cellsToRefine, i)
2231  {
2232  label celli = cellsToRefine[i];
2233 
2234  allCellInfo[celli].count() = allCellInfo[celli].refinementCount();
2235  }
2236 
2237 
2238  // Labels of seed faces
2239  DynamicList<label> seedFaces(mesh_.nFaces()/100);
2240  // refinementLevel data on seed faces
2241  DynamicList<refinementData> seedFacesInfo(mesh_.nFaces()/100);
2242 
2243  // Dummy additional info for FaceCellWave
2244  int dummyTrackData = 0;
2245 
2246 
2247  // Additional buffer layer thickness by changing initial count. Usually
2248  // this happens on boundary faces. Bit tricky. Use allFaceInfo to mark
2249  // off thus marked faces so they're skipped in the next loop.
2250  forAll(facesToCheck, i)
2251  {
2252  label facei = facesToCheck[i];
2253 
2254  if (allFaceInfo[facei].valid(dummyTrackData))
2255  {
2256  // Can only occur if face has already gone through loop below.
2258  << "Argument facesToCheck seems to have duplicate entries!"
2259  << endl
2260  << "face:" << facei << " occurs at positions "
2261  << findIndices(facesToCheck, facei)
2262  << abort(FatalError);
2263  }
2264 
2265 
2266  const refinementData& ownData = allCellInfo[faceOwner[facei]];
2267 
2268  if (mesh_.isInternalFace(facei))
2269  {
2270  // Seed face if neighbouring cell (after possible refinement)
2271  // will be refined one more than the current owner or neighbour.
2272 
2273  const refinementData& neiData = allCellInfo[faceNeighbour[facei]];
2274 
2275  label faceCount;
2276  label faceRefineCount;
2277  if (neiData.count() > ownData.count())
2278  {
2279  faceCount = neiData.count() + maxFaceDiff;
2280  faceRefineCount = faceCount + maxFaceDiff;
2281  }
2282  else
2283  {
2284  faceCount = ownData.count() + maxFaceDiff;
2285  faceRefineCount = faceCount + maxFaceDiff;
2286  }
2287 
2288  seedFaces.append(facei);
2289  seedFacesInfo.append
2290  (
2292  (
2293  faceRefineCount,
2294  faceCount
2295  )
2296  );
2297  allFaceInfo[facei] = seedFacesInfo.last();
2298  }
2299  else
2300  {
2301  label faceCount = ownData.count() + maxFaceDiff;
2302  label faceRefineCount = faceCount + maxFaceDiff;
2303 
2304  seedFaces.append(facei);
2305  seedFacesInfo.append
2306  (
2308  (
2309  faceRefineCount,
2310  faceCount
2311  )
2312  );
2313  allFaceInfo[facei] = seedFacesInfo.last();
2314  }
2315  }
2316 
2317 
2318  // Just seed with all faces in between different refinement levels for now
2319  // (alternatively only seed faces on cellsToRefine but that gives problems
2320  // if no cells to refine)
2321  forAll(faceNeighbour, facei)
2322  {
2323  // Check if face already handled in loop above
2324  if (!allFaceInfo[facei].valid(dummyTrackData))
2325  {
2326  label own = faceOwner[facei];
2327  label nei = faceNeighbour[facei];
2328 
2329  // Seed face with transported data from highest cell.
2330 
2331  if (allCellInfo[own].count() > allCellInfo[nei].count())
2332  {
2333  allFaceInfo[facei].updateFace
2334  (
2335  mesh_,
2336  facei,
2337  own,
2338  allCellInfo[own],
2340  dummyTrackData
2341  );
2342  seedFaces.append(facei);
2343  seedFacesInfo.append(allFaceInfo[facei]);
2344  }
2345  else if (allCellInfo[own].count() < allCellInfo[nei].count())
2346  {
2347  allFaceInfo[facei].updateFace
2348  (
2349  mesh_,
2350  facei,
2351  nei,
2352  allCellInfo[nei],
2354  dummyTrackData
2355  );
2356  seedFaces.append(facei);
2357  seedFacesInfo.append(allFaceInfo[facei]);
2358  }
2359  }
2360  }
2361 
2362  // Seed all boundary faces with owner value. This is to make sure that
2363  // they are visited (probably only important for coupled faces since
2364  // these need to be visited from both sides)
2365  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
2366  {
2367  // Check if face already handled in loop above
2368  if (!allFaceInfo[facei].valid(dummyTrackData))
2369  {
2370  label own = faceOwner[facei];
2371 
2372  // Seed face with transported data from owner.
2373  refinementData faceData;
2374  faceData.updateFace
2375  (
2376  mesh_,
2377  facei,
2378  own,
2379  allCellInfo[own],
2381  dummyTrackData
2382  );
2383  seedFaces.append(facei);
2384  seedFacesInfo.append(faceData);
2385  }
2386  }
2387 
2388 
2389  // face-cell-face transport engine
2391  (
2392  mesh_,
2393  allFaceInfo,
2394  allCellInfo,
2395  dummyTrackData
2396  );
2397 
2398  while (true)
2399  {
2400  if (debug)
2401  {
2402  Pout<< "hexRef8::consistentSlowRefinement : Seeded "
2403  << seedFaces.size() << " faces between cells with different"
2404  << " refinement level." << endl;
2405  }
2406 
2407  // Set seed faces
2408  levelCalc.setFaceInfo(seedFaces.shrink(), seedFacesInfo.shrink());
2409  seedFaces.clear();
2410  seedFacesInfo.clear();
2411 
2412  // Iterate until no change. Now 2:1 face difference should be satisfied
2413  levelCalc.iterate(mesh_.globalData().nTotalFaces()+1);
2414 
2415 
2416  // Now check point-connected cells (face-connected cells already ok):
2417  // - get per point max of connected cells
2418  // - sync across coupled points
2419  // - check cells against above point max
2420 
2421  if (maxPointDiff == -1)
2422  {
2423  // No need to do any point checking.
2424  break;
2425  }
2426 
2427  // Determine per point the max cell level. (done as count, not
2428  // as cell level purely for ease)
2429  labelList maxPointCount(mesh_.nPoints(), 0);
2430 
2431  forAll(maxPointCount, pointi)
2432  {
2433  label& pLevel = maxPointCount[pointi];
2434 
2435  const labelList& pCells = mesh_.pointCells(pointi);
2436 
2437  forAll(pCells, i)
2438  {
2439  pLevel = max(pLevel, allCellInfo[pCells[i]].count());
2440  }
2441  }
2442 
2443  // Sync maxPointCount to neighbour
2445  (
2446  mesh_,
2447  maxPointCount,
2448  maxEqOp<label>(),
2449  labelMin // null value
2450  );
2451 
2452  // Update allFaceInfo from maxPointCount for all points to check
2453  // (usually on boundary faces)
2454 
2455  // Per face the new refinement data
2456  Map<refinementData> changedFacesInfo(pointsToCheck.size());
2457 
2458  forAll(pointsToCheck, i)
2459  {
2460  label pointi = pointsToCheck[i];
2461 
2462  // Loop over all cells using the point and check whether their
2463  // refinement level is much less than the maximum.
2464 
2465  const labelList& pCells = mesh_.pointCells(pointi);
2466 
2467  forAll(pCells, pCelli)
2468  {
2469  label celli = pCells[pCelli];
2470 
2471  refinementData& cellInfo = allCellInfo[celli];
2472 
2473  if
2474  (
2475  !cellInfo.isRefined()
2476  && (
2477  maxPointCount[pointi]
2478  > cellInfo.count() + maxFaceDiff*maxPointDiff
2479  )
2480  )
2481  {
2482  // Mark cell for refinement
2483  cellInfo.count() = cellInfo.refinementCount();
2484 
2485  // Insert faces of cell as seed faces.
2486  const cell& cFaces = mesh_.cells()[celli];
2487 
2488  forAll(cFaces, cFacei)
2489  {
2490  label facei = cFaces[cFacei];
2491 
2492  refinementData faceData;
2493  faceData.updateFace
2494  (
2495  mesh_,
2496  facei,
2497  celli,
2498  cellInfo,
2500  dummyTrackData
2501  );
2502 
2503  if (faceData.count() > allFaceInfo[facei].count())
2504  {
2505  changedFacesInfo.insert(facei, faceData);
2506  }
2507  }
2508  }
2509  }
2510  }
2511 
2512  label nChanged = changedFacesInfo.size();
2513  reduce(nChanged, sumOp<label>());
2514 
2515  if (nChanged == 0)
2516  {
2517  break;
2518  }
2519 
2520 
2521  // Transfer into seedFaces, seedFacesInfo
2522  seedFaces.setCapacity(changedFacesInfo.size());
2523  seedFacesInfo.setCapacity(changedFacesInfo.size());
2524 
2525  forAllConstIter(Map<refinementData>, changedFacesInfo, iter)
2526  {
2527  seedFaces.append(iter.key());
2528  seedFacesInfo.append(iter());
2529  }
2530  }
2531 
2532 
2533  if (debug)
2534  {
2535  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
2536  {
2537  label own = mesh_.faceOwner()[facei];
2538  label ownLevel =
2539  cellLevel_[own]
2540  + (allCellInfo[own].isRefined() ? 1 : 0);
2541 
2542  label nei = mesh_.faceNeighbour()[facei];
2543  label neiLevel =
2544  cellLevel_[nei]
2545  + (allCellInfo[nei].isRefined() ? 1 : 0);
2546 
2547  if (mag(ownLevel-neiLevel) > 1)
2548  {
2549  dumpCell(own);
2550  dumpCell(nei);
2552  << "cell:" << own
2553  << " current level:" << cellLevel_[own]
2554  << " current refData:" << allCellInfo[own]
2555  << " level after refinement:" << ownLevel
2556  << nl
2557  << "neighbour cell:" << nei
2558  << " current level:" << cellLevel_[nei]
2559  << " current refData:" << allCellInfo[nei]
2560  << " level after refinement:" << neiLevel
2561  << nl
2562  << "which does not satisfy 2:1 constraints anymore." << nl
2563  << "face:" << facei << " faceRefData:" << allFaceInfo[facei]
2564  << abort(FatalError);
2565  }
2566  }
2567 
2568 
2569  // Coupled faces. Swap owner level to get neighbouring cell level.
2570  // (only boundary faces of neiLevel used)
2571 
2572  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
2573  labelList neiCount(mesh_.nFaces()-mesh_.nInternalFaces());
2574  labelList neiRefCount(mesh_.nFaces()-mesh_.nInternalFaces());
2575 
2576  forAll(neiLevel, i)
2577  {
2578  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
2579  neiLevel[i] = cellLevel_[own];
2580  neiCount[i] = allCellInfo[own].count();
2581  neiRefCount[i] = allCellInfo[own].refinementCount();
2582  }
2583 
2584  // Swap to neighbour
2585  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
2586  syncTools::swapBoundaryFaceList(mesh_, neiCount);
2587  syncTools::swapBoundaryFaceList(mesh_, neiRefCount);
2588 
2589  // Now we have neighbour value see which cells need refinement
2590  forAll(neiLevel, i)
2591  {
2592  label facei = i+mesh_.nInternalFaces();
2593 
2594  label own = mesh_.faceOwner()[facei];
2595  label ownLevel =
2596  cellLevel_[own]
2597  + (allCellInfo[own].isRefined() ? 1 : 0);
2598 
2599  label nbrLevel =
2600  neiLevel[i]
2601  + ((neiCount[i] >= neiRefCount[i]) ? 1 : 0);
2602 
2603  if (mag(ownLevel - nbrLevel) > 1)
2604  {
2605  dumpCell(own);
2606  label patchi = mesh_.boundaryMesh().whichPatch(facei);
2607 
2609  << "Celllevel does not satisfy 2:1 constraint."
2610  << " On coupled face "
2611  << facei
2612  << " refData:" << allFaceInfo[facei]
2613  << " on patch " << patchi << " "
2614  << mesh_.boundaryMesh()[patchi].name() << nl
2615  << "owner cell " << own
2616  << " current level:" << cellLevel_[own]
2617  << " current count:" << allCellInfo[own].count()
2618  << " current refCount:"
2619  << allCellInfo[own].refinementCount()
2620  << " level after refinement:" << ownLevel
2621  << nl
2622  << "(coupled) neighbour cell"
2623  << " has current level:" << neiLevel[i]
2624  << " current count:" << neiCount[i]
2625  << " current refCount:" << neiRefCount[i]
2626  << " level after refinement:" << nbrLevel
2627  << abort(FatalError);
2628  }
2629  }
2630  }
2631 
2632  // Convert back to labelList of cells to refine.
2633 
2634  label nRefined = 0;
2635 
2636  forAll(allCellInfo, celli)
2637  {
2638  if (allCellInfo[celli].isRefined())
2639  {
2640  nRefined++;
2641  }
2642  }
2643 
2644  // Updated list of cells to refine
2645  labelList newCellsToRefine(nRefined);
2646  nRefined = 0;
2647 
2648  forAll(allCellInfo, celli)
2649  {
2650  if (allCellInfo[celli].isRefined())
2651  {
2652  newCellsToRefine[nRefined++] = celli;
2653  }
2654  }
2655 
2656  if (debug)
2657  {
2658  Pout<< "hexRef8::consistentSlowRefinement : From "
2659  << cellsToRefine.size() << " to " << newCellsToRefine.size()
2660  << " cells to refine." << endl;
2661  }
2662 
2663  return newCellsToRefine;
2664 }
2665 
2666 
2668 (
2669  const label maxFaceDiff,
2670  const labelList& cellsToRefine,
2671  const labelList& facesToCheck
2672 ) const
2673 {
2674  const labelList& faceOwner = mesh_.faceOwner();
2675  const labelList& faceNeighbour = mesh_.faceNeighbour();
2676 
2677  if (maxFaceDiff <= 0)
2678  {
2680  << "Illegal maxFaceDiff " << maxFaceDiff << nl
2681  << "Value should be >= 1" << exit(FatalError);
2682  }
2683 
2684  const scalar level0Size = 2*maxFaceDiff*level0EdgeLength();
2685 
2686 
2687  // Bit tricky. Say we want a distance of three cells between two
2688  // consecutive refinement levels. This is done by using FaceCellWave to
2689  // transport out the 'refinement shell'. Anything inside the refinement
2690  // shell (given by a distance) gets marked for refinement.
2691 
2692  // Initial information about (distance to) cellLevel on all cells
2693  List<refinementDistanceData> allCellInfo(mesh_.nCells());
2694 
2695  // Initial information about (distance to) cellLevel on all faces
2696  List<refinementDistanceData> allFaceInfo(mesh_.nFaces());
2697 
2698  // Dummy additional info for FaceCellWave
2699  int dummyTrackData = 0;
2700 
2701 
2702  // Mark cells with wanted refinement level
2703  forAll(cellsToRefine, i)
2704  {
2705  label celli = cellsToRefine[i];
2706 
2707  allCellInfo[celli] = refinementDistanceData
2708  (
2709  level0Size,
2710  mesh_.cellCentres()[celli],
2711  cellLevel_[celli]+1 // wanted refinement
2712  );
2713  }
2714  // Mark all others with existing refinement level
2715  forAll(allCellInfo, celli)
2716  {
2717  if (!allCellInfo[celli].valid(dummyTrackData))
2718  {
2719  allCellInfo[celli] = refinementDistanceData
2720  (
2721  level0Size,
2722  mesh_.cellCentres()[celli],
2723  cellLevel_[celli] // wanted refinement
2724  );
2725  }
2726  }
2727 
2728 
2729  // Labels of seed faces
2730  DynamicList<label> seedFaces(mesh_.nFaces()/100);
2731  // refinementLevel data on seed faces
2732  DynamicList<refinementDistanceData> seedFacesInfo(mesh_.nFaces()/100);
2733 
2734  const pointField& cc = mesh_.cellCentres();
2735 
2736  forAll(facesToCheck, i)
2737  {
2738  label facei = facesToCheck[i];
2739 
2740  if (allFaceInfo[facei].valid(dummyTrackData))
2741  {
2742  // Can only occur if face has already gone through loop below.
2744  << "Argument facesToCheck seems to have duplicate entries!"
2745  << endl
2746  << "face:" << facei << " occurs at positions "
2747  << findIndices(facesToCheck, facei)
2748  << abort(FatalError);
2749  }
2750 
2751  label own = faceOwner[facei];
2752 
2753  label ownLevel =
2754  (
2755  allCellInfo[own].valid(dummyTrackData)
2756  ? allCellInfo[own].originLevel()
2757  : cellLevel_[own]
2758  );
2759 
2760  if (!mesh_.isInternalFace(facei))
2761  {
2762  // Do as if boundary face would have neighbour with one higher
2763  // refinement level.
2764  const point& fc = mesh_.faceCentres()[facei];
2765 
2766  refinementDistanceData neiData
2767  (
2768  level0Size,
2769  2*fc - cc[own], // est'd cell centre
2770  ownLevel+1
2771  );
2772 
2773  allFaceInfo[facei].updateFace
2774  (
2775  mesh_,
2776  facei,
2777  own, // not used (should be nei)
2778  neiData,
2780  dummyTrackData
2781  );
2782  }
2783  else
2784  {
2785  label nei = faceNeighbour[facei];
2786 
2787  label neiLevel =
2788  (
2789  allCellInfo[nei].valid(dummyTrackData)
2790  ? allCellInfo[nei].originLevel()
2791  : cellLevel_[nei]
2792  );
2793 
2794  if (ownLevel == neiLevel)
2795  {
2796  // Fake as if nei>own or own>nei (whichever one 'wins')
2797  allFaceInfo[facei].updateFace
2798  (
2799  mesh_,
2800  facei,
2801  nei,
2802  refinementDistanceData(level0Size, cc[nei], neiLevel+1),
2804  dummyTrackData
2805  );
2806  allFaceInfo[facei].updateFace
2807  (
2808  mesh_,
2809  facei,
2810  own,
2811  refinementDistanceData(level0Size, cc[own], ownLevel+1),
2813  dummyTrackData
2814  );
2815  }
2816  else
2817  {
2818  // Difference in level anyway.
2819  allFaceInfo[facei].updateFace
2820  (
2821  mesh_,
2822  facei,
2823  nei,
2824  refinementDistanceData(level0Size, cc[nei], neiLevel),
2826  dummyTrackData
2827  );
2828  allFaceInfo[facei].updateFace
2829  (
2830  mesh_,
2831  facei,
2832  own,
2833  refinementDistanceData(level0Size, cc[own], ownLevel),
2835  dummyTrackData
2836  );
2837  }
2838  }
2839  seedFaces.append(facei);
2840  seedFacesInfo.append(allFaceInfo[facei]);
2841  }
2842 
2843 
2844  // Create some initial seeds to start walking from. This is only if there
2845  // are no facesToCheck.
2846  // Just seed with all faces in between different refinement levels for now
2847  forAll(faceNeighbour, facei)
2848  {
2849  // Check if face already handled in loop above
2850  if (!allFaceInfo[facei].valid(dummyTrackData))
2851  {
2852  label own = faceOwner[facei];
2853 
2854  label ownLevel =
2855  (
2856  allCellInfo[own].valid(dummyTrackData)
2857  ? allCellInfo[own].originLevel()
2858  : cellLevel_[own]
2859  );
2860 
2861  label nei = faceNeighbour[facei];
2862 
2863  label neiLevel =
2864  (
2865  allCellInfo[nei].valid(dummyTrackData)
2866  ? allCellInfo[nei].originLevel()
2867  : cellLevel_[nei]
2868  );
2869 
2870  if (ownLevel > neiLevel)
2871  {
2872  // Set face to owner data. (since face not yet would be copy)
2873  seedFaces.append(facei);
2874  allFaceInfo[facei].updateFace
2875  (
2876  mesh_,
2877  facei,
2878  own,
2879  refinementDistanceData(level0Size, cc[own], ownLevel),
2881  dummyTrackData
2882  );
2883  seedFacesInfo.append(allFaceInfo[facei]);
2884  }
2885  else if (neiLevel > ownLevel)
2886  {
2887  seedFaces.append(facei);
2888  allFaceInfo[facei].updateFace
2889  (
2890  mesh_,
2891  facei,
2892  nei,
2893  refinementDistanceData(level0Size, cc[nei], neiLevel),
2895  dummyTrackData
2896  );
2897  seedFacesInfo.append(allFaceInfo[facei]);
2898  }
2899  }
2900  }
2901 
2902  seedFaces.shrink();
2903  seedFacesInfo.shrink();
2904 
2905  // face-cell-face transport engine
2907  (
2908  mesh_,
2909  seedFaces,
2910  seedFacesInfo,
2911  allFaceInfo,
2912  allCellInfo,
2913  mesh_.globalData().nTotalCells()+1,
2914  dummyTrackData
2915  );
2916 
2917 
2918  // if (debug)
2919  //{
2920  // // Dump wanted level
2921  // volScalarField wantedLevel
2922  // (
2923  // IOobject
2924  // (
2925  // "wantedLevel",
2926  // fMesh.time().name(),
2927  // fMesh,
2928  // IOobject::NO_READ,
2929  // IOobject::NO_WRITE,
2930  // false
2931  // ),
2932  // fMesh,
2933  // dimensionedScalar(dimless, 0)
2934  // );
2935  //
2936  // forAll(wantedLevel, celli)
2937  // {
2938  // wantedLevel[celli] = allCellInfo[celli].wantedLevel(cc[celli]);
2939  // }
2940  //
2941  // Pout<< "Writing " << wantedLevel.objectPath() << endl;
2942  // wantedLevel.write();
2943  //}
2944 
2945 
2946  // Convert back to labelList of cells to refine.
2947  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2948 
2949  // 1. Force original refinement cells to be picked up by setting the
2950  // originLevel of input cells to be a very large level (but within range
2951  // of 1<< shift inside refinementDistanceData::wantedLevel)
2952  forAll(cellsToRefine, i)
2953  {
2954  label celli = cellsToRefine[i];
2955 
2956  allCellInfo[celli].originLevel() = sizeof(label)*8-2;
2957  allCellInfo[celli].origin() = cc[celli];
2958  }
2959 
2960  // 2. Extend to 2:1. I don't understand yet why this is not done
2961  // 2. Extend to 2:1. For non-cube cells the scalar distance does not work
2962  // so make sure it at least provides 2:1.
2963  PackedBoolList refineCell(mesh_.nCells());
2964  forAll(allCellInfo, celli)
2965  {
2966  label wanted = allCellInfo[celli].wantedLevel(cc[celli]);
2967 
2968  if (wanted > cellLevel_[celli]+1)
2969  {
2970  refineCell.set(celli);
2971  }
2972  }
2973  faceConsistentRefinement(true, refineCell);
2974 
2975  while (true)
2976  {
2977  label nChanged = faceConsistentRefinement(true, refineCell);
2978 
2979  reduce(nChanged, sumOp<label>());
2980 
2981  if (debug)
2982  {
2983  Pout<< "hexRef8::consistentSlowRefinement2 : Changed " << nChanged
2984  << " refinement levels due to 2:1 conflicts."
2985  << endl;
2986  }
2987 
2988  if (nChanged == 0)
2989  {
2990  break;
2991  }
2992  }
2993 
2994  // 3. Convert back to labelList.
2995  label nRefined = 0;
2996 
2997  forAll(refineCell, celli)
2998  {
2999  if (refineCell[celli])
3000  {
3001  nRefined++;
3002  }
3003  }
3004 
3005  labelList newCellsToRefine(nRefined);
3006  nRefined = 0;
3007 
3008  forAll(refineCell, celli)
3009  {
3010  if (refineCell[celli])
3011  {
3012  newCellsToRefine[nRefined++] = celli;
3013  }
3014  }
3015 
3016  if (debug)
3017  {
3018  Pout<< "hexRef8::consistentSlowRefinement2 : From "
3019  << cellsToRefine.size() << " to " << newCellsToRefine.size()
3020  << " cells to refine." << endl;
3021 
3022  // Check that newCellsToRefine obeys at least 2:1.
3023 
3024  {
3025  cellSet cellsIn(mesh_, "cellsToRefineIn", cellsToRefine);
3026  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3027  << cellsIn.size() << " to cellSet "
3028  << cellsIn.objectPath() << endl;
3029  cellsIn.write();
3030  }
3031  {
3032  cellSet cellsOut(mesh_, "cellsToRefineOut", newCellsToRefine);
3033  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3034  << cellsOut.size() << " to cellSet "
3035  << cellsOut.objectPath() << endl;
3036  cellsOut.write();
3037  }
3038 
3039  // Extend to 2:1
3040  PackedBoolList refineCell(mesh_.nCells());
3041  forAll(newCellsToRefine, i)
3042  {
3043  refineCell.set(newCellsToRefine[i]);
3044  }
3045  const PackedBoolList savedRefineCell(refineCell);
3046 
3047  label nChanged = faceConsistentRefinement(true, refineCell);
3048 
3049  {
3050  cellSet cellsOut2
3051  (
3052  mesh_, "cellsToRefineOut2", newCellsToRefine.size()
3053  );
3054  forAll(refineCell, celli)
3055  {
3056  if (refineCell.get(celli))
3057  {
3058  cellsOut2.insert(celli);
3059  }
3060  }
3061  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3062  << cellsOut2.size() << " to cellSet "
3063  << cellsOut2.objectPath() << endl;
3064  cellsOut2.write();
3065  }
3066 
3067  if (nChanged > 0)
3068  {
3069  forAll(refineCell, celli)
3070  {
3071  if (refineCell.get(celli) && !savedRefineCell.get(celli))
3072  {
3073  dumpCell(celli);
3075  << "Cell:" << celli << " cc:"
3076  << mesh_.cellCentres()[celli]
3077  << " was not marked for refinement but does not obey"
3078  << " 2:1 constraints."
3079  << abort(FatalError);
3080  }
3081  }
3082  }
3083  }
3084 
3085  return newCellsToRefine;
3086 }
3087 
3088 
3090 (
3091  const labelList& cellLabels,
3092  polyTopoChange& meshMod
3093 )
3094 {
3095  if (debug)
3096  {
3097  Pout<< "hexRef8::setRefinement :"
3098  << " Checking initial mesh just to make sure" << endl;
3099 
3100  checkMesh();
3101  // Cannot call checkRefinementlevels since hanging points might
3102  // get triggered by the mesher after subsetting.
3103  // checkRefinementLevels(-1, labelList(0));
3104  }
3105 
3106  // Clear any saved point/cell data.
3107  savedPointLevel_.clear();
3108  savedCellLevel_.clear();
3109 
3110 
3111  // New point/cell level. Copy of pointLevel for existing points.
3112  DynamicList<label> newCellLevel(cellLevel_.size());
3113  forAll(cellLevel_, celli)
3114  {
3115  newCellLevel.append(cellLevel_[celli]);
3116  }
3117  DynamicList<label> newPointLevel(pointLevel_.size());
3118  forAll(pointLevel_, pointi)
3119  {
3120  newPointLevel.append(pointLevel_[pointi]);
3121  }
3122 
3123 
3124  if (debug)
3125  {
3126  Pout<< "hexRef8::setRefinement :"
3127  << " Allocating " << cellLabels.size() << " cell midpoints."
3128  << endl;
3129  }
3130 
3131 
3132  // Mid point per refined cell.
3133  // -1 : not refined
3134  // >=0: label of mid point.
3135  labelList cellMidPoint(mesh_.nCells(), -1);
3136 
3137  forAll(cellLabels, i)
3138  {
3139  label celli = cellLabels[i];
3140 
3141  label anchorPointi = mesh_.faces()[mesh_.cells()[celli][0]][0];
3142 
3143  cellMidPoint[celli] = meshMod.addPoint
3144  (
3145  mesh_.cellCentres()[celli], // point
3146  anchorPointi, // master point
3147  true // supports a cell
3148  );
3149 
3150  newPointLevel(cellMidPoint[celli]) = cellLevel_[celli]+1;
3151  }
3152 
3153 
3154  if (debug)
3155  {
3156  cellSet splitCells(mesh_, "splitCells", cellLabels.size());
3157 
3158  forAll(cellMidPoint, celli)
3159  {
3160  if (cellMidPoint[celli] >= 0)
3161  {
3162  splitCells.insert(celli);
3163  }
3164  }
3165 
3166  Pout<< "hexRef8::setRefinement : Dumping " << splitCells.size()
3167  << " cells to split to cellSet " << splitCells.objectPath()
3168  << endl;
3169 
3170  splitCells.write();
3171  }
3172 
3173 
3174 
3175  // Split edges
3176  // ~~~~~~~~~~~
3177 
3178  if (debug)
3179  {
3180  Pout<< "hexRef8::setRefinement :"
3181  << " Allocating edge midpoints."
3182  << endl;
3183  }
3184 
3185  // Unrefined edges are ones between cellLevel or lower points.
3186  // If any cell using this edge gets split then the edge needs to be split.
3187 
3188  // -1 : no need to split edge
3189  // >=0 : label of introduced mid point
3190  labelList edgeMidPoint(mesh_.nEdges(), -1);
3191 
3192  // Note: Loop over cells to be refined or edges?
3193  forAll(cellMidPoint, celli)
3194  {
3195  if (cellMidPoint[celli] >= 0)
3196  {
3197  const labelList& cEdges = mesh_.cellEdges(celli);
3198 
3199  forAll(cEdges, i)
3200  {
3201  label edgeI = cEdges[i];
3202 
3203  const edge& e = mesh_.edges()[edgeI];
3204 
3205  if
3206  (
3207  pointLevel_[e[0]] <= cellLevel_[celli]
3208  && pointLevel_[e[1]] <= cellLevel_[celli]
3209  )
3210  {
3211  edgeMidPoint[edgeI] = 12345; // mark need for splitting
3212  }
3213  }
3214  }
3215  }
3216 
3217  // Synchronise edgeMidPoint across coupled patches. Take max so that
3218  // any split takes precedence.
3220  (
3221  mesh_,
3222  edgeMidPoint,
3223  maxEqOp<label>(),
3224  labelMin
3225  );
3226 
3227 
3228  // Introduce edge points
3229  // ~~~~~~~~~~~~~~~~~~~~~
3230 
3231  {
3232  // Phase 1: calculate midpoints and sync.
3233  // This needs doing for if people do not write binary and we slowly
3234  // get differences.
3235 
3236  pointField edgeMids(mesh_.nEdges(), point(-great, -great, -great));
3237 
3238  forAll(edgeMidPoint, edgeI)
3239  {
3240  if (edgeMidPoint[edgeI] >= 0)
3241  {
3242  // Edge marked to be split.
3243  edgeMids[edgeI] = mesh_.edges()[edgeI].centre(mesh_.points());
3244  }
3245  }
3247  (
3248  mesh_,
3249  edgeMids,
3250  maxEqOp<vector>(),
3251  point(-great, -great, -great)
3252  );
3253 
3254 
3255  // Phase 2: introduce points at the synced locations.
3256  forAll(edgeMidPoint, edgeI)
3257  {
3258  if (edgeMidPoint[edgeI] >= 0)
3259  {
3260  // Edge marked to be split. Replace edgeMidPoint with actual
3261  // point label.
3262 
3263  const edge& e = mesh_.edges()[edgeI];
3264 
3265  edgeMidPoint[edgeI] = meshMod.addPoint
3266  (
3267  edgeMids[edgeI], // point
3268  e[0], // master point
3269  true // supports a cell
3270  );
3271 
3272  newPointLevel(edgeMidPoint[edgeI]) =
3273  max
3274  (
3275  pointLevel_[e[0]],
3276  pointLevel_[e[1]]
3277  )
3278  + 1;
3279  }
3280  }
3281  }
3282 
3283  if (debug)
3284  {
3285  OFstream str(mesh_.time().path()/"edgeMidPoint.obj");
3286 
3287  forAll(edgeMidPoint, edgeI)
3288  {
3289  if (edgeMidPoint[edgeI] >= 0)
3290  {
3291  const edge& e = mesh_.edges()[edgeI];
3292 
3293  meshTools::writeOBJ(str, e.centre(mesh_.points()));
3294  }
3295  }
3296 
3297  Pout<< "hexRef8::setRefinement :"
3298  << " Dumping edge centres to split to file " << str.name() << endl;
3299  }
3300 
3301 
3302  // Calculate face level
3303  // ~~~~~~~~~~~~~~~~~~~~
3304  // (after splitting)
3305 
3306  if (debug)
3307  {
3308  Pout<< "hexRef8::setRefinement :"
3309  << " Allocating face midpoints."
3310  << endl;
3311  }
3312 
3313  // Face anchor level. There are guaranteed 4 points with level
3314  // <= anchorLevel. These are the corner points.
3315  labelList faceAnchorLevel(mesh_.nFaces());
3316 
3317  for (label facei = 0; facei < mesh_.nFaces(); facei++)
3318  {
3319  faceAnchorLevel[facei] = faceLevel(facei);
3320  }
3321 
3322  // -1 : no need to split face
3323  // >=0 : label of introduced mid point
3324  labelList faceMidPoint(mesh_.nFaces(), -1);
3325 
3326 
3327  // Internal faces: look at cells on both sides. Uniquely determined since
3328  // face itself guaranteed to be same level as most refined neighbour.
3329  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
3330  {
3331  if (faceAnchorLevel[facei] >= 0)
3332  {
3333  label own = mesh_.faceOwner()[facei];
3334  label ownLevel = cellLevel_[own];
3335  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3336 
3337  label nei = mesh_.faceNeighbour()[facei];
3338  label neiLevel = cellLevel_[nei];
3339  label newNeiLevel = neiLevel + (cellMidPoint[nei] >= 0 ? 1 : 0);
3340 
3341  if
3342  (
3343  newOwnLevel > faceAnchorLevel[facei]
3344  || newNeiLevel > faceAnchorLevel[facei]
3345  )
3346  {
3347  faceMidPoint[facei] = 12345; // mark to be split
3348  }
3349  }
3350  }
3351 
3352  // Coupled patches handled like internal faces except now all information
3353  // from neighbour comes from across processor.
3354  // Boundary faces are more complicated since the boundary face can
3355  // be more refined than its owner (or neighbour for coupled patches)
3356  // (does not happen if refining/unrefining only, but does e.g. when
3357  // refinining and subsetting)
3358 
3359  {
3360  labelList newNeiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
3361 
3362  forAll(newNeiLevel, i)
3363  {
3364  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
3365  label ownLevel = cellLevel_[own];
3366  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3367 
3368  newNeiLevel[i] = newOwnLevel;
3369  }
3370 
3371  // Swap.
3372  syncTools::swapBoundaryFaceList(mesh_, newNeiLevel);
3373 
3374  // So now we have information on the neighbour.
3375 
3376  forAll(newNeiLevel, i)
3377  {
3378  label facei = i+mesh_.nInternalFaces();
3379 
3380  if (faceAnchorLevel[facei] >= 0)
3381  {
3382  label own = mesh_.faceOwner()[facei];
3383  label ownLevel = cellLevel_[own];
3384  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3385 
3386  if
3387  (
3388  newOwnLevel > faceAnchorLevel[facei]
3389  || newNeiLevel[i] > faceAnchorLevel[facei]
3390  )
3391  {
3392  faceMidPoint[facei] = 12345; // mark to be split
3393  }
3394  }
3395  }
3396  }
3397 
3398 
3399  // Synchronise faceMidPoint across coupled patches. (logical or)
3401  (
3402  mesh_,
3403  faceMidPoint,
3404  maxEqOp<label>()
3405  );
3406 
3407 
3408 
3409  // Introduce face points
3410  // ~~~~~~~~~~~~~~~~~~~~~
3411 
3412  {
3413  // Phase 1: determine mid points and sync. See comment for edgeMids
3414  // above
3415  pointField bFaceMids
3416  (
3417  mesh_.nFaces()-mesh_.nInternalFaces(),
3418  point(-great, -great, -great)
3419  );
3420 
3421  forAll(bFaceMids, i)
3422  {
3423  label facei = i+mesh_.nInternalFaces();
3424 
3425  if (faceMidPoint[facei] >= 0)
3426  {
3427  bFaceMids[i] = mesh_.faceCentres()[facei];
3428  }
3429  }
3431  (
3432  mesh_,
3433  bFaceMids,
3434  maxEqOp<vector>()
3435  );
3436 
3437  forAll(faceMidPoint, facei)
3438  {
3439  if (faceMidPoint[facei] >= 0)
3440  {
3441  // Face marked to be split. Replace faceMidPoint with actual
3442  // point label.
3443 
3444  const face& f = mesh_.faces()[facei];
3445 
3446  faceMidPoint[facei] = meshMod.addPoint
3447  (
3448  (
3449  facei < mesh_.nInternalFaces()
3450  ? mesh_.faceCentres()[facei]
3451  : bFaceMids[facei-mesh_.nInternalFaces()]
3452  ), // point
3453  f[0], // master point
3454  true // supports a cell
3455  );
3456 
3457  // Determine the level of the corner points and midpoint will
3458  // be one higher.
3459  newPointLevel(faceMidPoint[facei]) = faceAnchorLevel[facei]+1;
3460  }
3461  }
3462  }
3463 
3464  if (debug)
3465  {
3466  faceSet splitFaces(mesh_, "splitFaces", cellLabels.size());
3467 
3468  forAll(faceMidPoint, facei)
3469  {
3470  if (faceMidPoint[facei] >= 0)
3471  {
3472  splitFaces.insert(facei);
3473  }
3474  }
3475 
3476  Pout<< "hexRef8::setRefinement : Dumping " << splitFaces.size()
3477  << " faces to split to faceSet " << splitFaces.objectPath() << endl;
3478 
3479  splitFaces.write();
3480  }
3481 
3482 
3483  // Information complete
3484  // ~~~~~~~~~~~~~~~~~~~~
3485  // At this point we have all the information we need. We should no
3486  // longer reference the cellLabels to refine. All the information is:
3487  // - cellMidPoint >= 0 : cell needs to be split
3488  // - faceMidPoint >= 0 : face needs to be split
3489  // - edgeMidPoint >= 0 : edge needs to be split
3490 
3491 
3492 
3493  // Get the corner/anchor points
3494  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3495 
3496  if (debug)
3497  {
3498  Pout<< "hexRef8::setRefinement :"
3499  << " Finding cell anchorPoints (8 per cell)"
3500  << endl;
3501  }
3502 
3503  // There will always be 8 points on the hex that have were introduced
3504  // with the hex and will have the same or lower refinement level.
3505 
3506  // Per cell the 8 corner points.
3507  labelListList cellAnchorPoints(mesh_.nCells());
3508 
3509  {
3510  labelList nAnchorPoints(mesh_.nCells(), 0);
3511 
3512  forAll(cellMidPoint, celli)
3513  {
3514  if (cellMidPoint[celli] >= 0)
3515  {
3516  cellAnchorPoints[celli].setSize(8);
3517  }
3518  }
3519 
3520  forAll(pointLevel_, pointi)
3521  {
3522  const labelList& pCells = mesh_.pointCells(pointi);
3523 
3524  forAll(pCells, pCelli)
3525  {
3526  label celli = pCells[pCelli];
3527 
3528  if
3529  (
3530  cellMidPoint[celli] >= 0
3531  && pointLevel_[pointi] <= cellLevel_[celli]
3532  )
3533  {
3534  if (nAnchorPoints[celli] == 8)
3535  {
3536  dumpCell(celli);
3538  << "cell " << celli
3539  << " of level " << cellLevel_[celli]
3540  << " uses more than 8 points of equal or"
3541  << " lower level" << nl
3542  << "Points so far:" << cellAnchorPoints[celli]
3543  << abort(FatalError);
3544  }
3545 
3546  cellAnchorPoints[celli][nAnchorPoints[celli]++] = pointi;
3547  }
3548  }
3549  }
3550 
3551  forAll(cellMidPoint, celli)
3552  {
3553  if (cellMidPoint[celli] >= 0)
3554  {
3555  if (nAnchorPoints[celli] != 8)
3556  {
3557  dumpCell(celli);
3558 
3559  const labelList& cPoints = mesh_.cellPoints(celli);
3560 
3562  << "cell " << celli
3563  << " of level " << cellLevel_[celli]
3564  << " does not seem to have 8 points of equal or"
3565  << " lower level" << endl
3566  << "cellPoints:" << cPoints << endl
3567  << "pointLevels:"
3568  << UIndirectList<label>(pointLevel_, cPoints)() << endl
3569  << abort(FatalError);
3570  }
3571  }
3572  }
3573  }
3574 
3575 
3576  // Add the cells
3577  // ~~~~~~~~~~~~~
3578 
3579  if (debug)
3580  {
3581  Pout<< "hexRef8::setRefinement :"
3582  << " Adding cells (1 per anchorPoint)"
3583  << endl;
3584  }
3585 
3586  // Per cell the 7 added cells (+ original cell)
3587  labelListList cellAddedCells(mesh_.nCells());
3588 
3589  forAll(cellAnchorPoints, celli)
3590  {
3591  const labelList& cAnchors = cellAnchorPoints[celli];
3592 
3593  if (cAnchors.size() == 8)
3594  {
3595  labelList& cAdded = cellAddedCells[celli];
3596  cAdded.setSize(8);
3597 
3598  // Original cell at 0
3599  cAdded[0] = celli;
3600 
3601  // Update cell level
3602  newCellLevel[celli] = cellLevel_[celli]+1;
3603 
3604  for (label i = 1; i < 8; i++)
3605  {
3606  cAdded[i] = meshMod.addCell(celli);
3607  newCellLevel(cAdded[i]) = cellLevel_[celli] + 1;
3608  }
3609  }
3610  }
3611 
3612 
3613  // Faces
3614  // ~~~~~
3615  // 1. existing faces that get split (into four always)
3616  // 2. existing faces that do not get split but only edges get split
3617  // 3. existing faces that do not get split but get new owner/neighbour
3618  // 4. new internal faces inside split cells.
3619 
3620  if (debug)
3621  {
3622  Pout<< "hexRef8::setRefinement :"
3623  << " Marking faces to be handled"
3624  << endl;
3625  }
3626 
3627  // Get all affected faces.
3628  PackedBoolList affectedFace(mesh_.nFaces());
3629 
3630  {
3631  forAll(cellMidPoint, celli)
3632  {
3633  if (cellMidPoint[celli] >= 0)
3634  {
3635  const cell& cFaces = mesh_.cells()[celli];
3636 
3637  forAll(cFaces, i)
3638  {
3639  affectedFace.set(cFaces[i]);
3640  }
3641  }
3642  }
3643 
3644  forAll(faceMidPoint, facei)
3645  {
3646  if (faceMidPoint[facei] >= 0)
3647  {
3648  affectedFace.set(facei);
3649  }
3650  }
3651 
3652  forAll(edgeMidPoint, edgeI)
3653  {
3654  if (edgeMidPoint[edgeI] >= 0)
3655  {
3656  const labelList& eFaces = mesh_.edgeFaces(edgeI);
3657 
3658  forAll(eFaces, i)
3659  {
3660  affectedFace.set(eFaces[i]);
3661  }
3662  }
3663  }
3664  }
3665 
3666 
3667  // 1. Faces that get split
3668  // ~~~~~~~~~~~~~~~~~~~~~~~
3669 
3670  if (debug)
3671  {
3672  Pout<< "hexRef8::setRefinement : Splitting faces" << endl;
3673  }
3674 
3675  forAll(faceMidPoint, facei)
3676  {
3677  if (faceMidPoint[facei] >= 0 && affectedFace.get(facei))
3678  {
3679  // Face needs to be split and hasn't yet been done in some way
3680  // (affectedFace - is impossible since this is first change but
3681  // just for completeness)
3682 
3683  const face& f = mesh_.faces()[facei];
3684 
3685  // Has original facei been used (three faces added, original gets
3686  // modified)
3687  bool modifiedFace = false;
3688 
3689  label anchorLevel = faceAnchorLevel[facei];
3690 
3691  face newFace(4);
3692 
3693  forAll(f, fp)
3694  {
3695  label pointi = f[fp];
3696 
3697  if (pointLevel_[pointi] <= anchorLevel)
3698  {
3699  // point is anchor. Start collecting face.
3700 
3701  DynamicList<label> faceVerts(4);
3702 
3703  faceVerts.append(pointi);
3704 
3705  // Walk forward to mid point.
3706  // - if next is +2 midpoint is +1
3707  // - if next is +1 it is midpoint
3708  // - if next is +0 there has to be edgeMidPoint
3709 
3710  walkFaceToMid
3711  (
3712  edgeMidPoint,
3713  anchorLevel,
3714  facei,
3715  fp,
3716  faceVerts
3717  );
3718 
3719  faceVerts.append(faceMidPoint[facei]);
3720 
3721  walkFaceFromMid
3722  (
3723  edgeMidPoint,
3724  anchorLevel,
3725  facei,
3726  fp,
3727  faceVerts
3728  );
3729 
3730  // Convert dynamiclist to face.
3731  newFace.transfer(faceVerts);
3732 
3733  // Pout<< "Split face:" << facei << " verts:" << f
3734  // << " into quad:" << newFace << endl;
3735 
3736  // Get new owner/neighbour
3737  label own, nei;
3738  getFaceNeighbours
3739  (
3740  cellAnchorPoints,
3741  cellAddedCells,
3742  facei,
3743  pointi, // Anchor point
3744 
3745  own,
3746  nei
3747  );
3748 
3749 
3750  if (debug)
3751  {
3752  if (mesh_.isInternalFace(facei))
3753  {
3754  label oldOwn = mesh_.faceOwner()[facei];
3755  label oldNei = mesh_.faceNeighbour()[facei];
3756 
3757  checkInternalOrientation
3758  (
3759  meshMod,
3760  oldOwn,
3761  facei,
3762  mesh_.cellCentres()[oldOwn],
3763  mesh_.cellCentres()[oldNei],
3764  newFace
3765  );
3766  }
3767  else
3768  {
3769  label oldOwn = mesh_.faceOwner()[facei];
3770 
3771  checkBoundaryOrientation
3772  (
3773  meshMod,
3774  oldOwn,
3775  facei,
3776  mesh_.cellCentres()[oldOwn],
3777  mesh_.faceCentres()[facei],
3778  newFace
3779  );
3780  }
3781  }
3782 
3783 
3784  if (!modifiedFace)
3785  {
3786  modifiedFace = true;
3787 
3788  modifyFace(meshMod, facei, newFace, own, nei);
3789  }
3790  else
3791  {
3792  addFace(meshMod, facei, newFace, own, nei);
3793  }
3794  }
3795  }
3796 
3797  // Mark face as having been handled
3798  affectedFace.unset(facei);
3799  }
3800  }
3801 
3802 
3803  // 2. faces that do not get split but use edges that get split
3804  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3805 
3806  if (debug)
3807  {
3808  Pout<< "hexRef8::setRefinement :"
3809  << " Adding edge splits to unsplit faces"
3810  << endl;
3811  }
3812 
3813  DynamicList<label> eFacesStorage;
3814  DynamicList<label> fEdgesStorage;
3815 
3816  forAll(edgeMidPoint, edgeI)
3817  {
3818  if (edgeMidPoint[edgeI] >= 0)
3819  {
3820  // Split edge. Check that face not already handled above.
3821 
3822  const labelList& eFaces = mesh_.edgeFaces(edgeI, eFacesStorage);
3823 
3824  forAll(eFaces, i)
3825  {
3826  label facei = eFaces[i];
3827 
3828  if (faceMidPoint[facei] < 0 && affectedFace.get(facei))
3829  {
3830  // Unsplit face. Add edge splits to face.
3831 
3832  const face& f = mesh_.faces()[facei];
3833  const labelList& fEdges = mesh_.faceEdges
3834  (
3835  facei,
3836  fEdgesStorage
3837  );
3838 
3839  DynamicList<label> newFaceVerts(f.size());
3840 
3841  forAll(f, fp)
3842  {
3843  newFaceVerts.append(f[fp]);
3844 
3845  label edgeI = fEdges[fp];
3846 
3847  if (edgeMidPoint[edgeI] >= 0)
3848  {
3849  newFaceVerts.append(edgeMidPoint[edgeI]);
3850  }
3851  }
3852 
3853  face newFace;
3854  newFace.transfer(newFaceVerts);
3855 
3856  // The point with the lowest level should be an anchor
3857  // point of the neighbouring cells.
3858  label anchorFp = findMinLevel(f);
3859 
3860  label own, nei;
3861  getFaceNeighbours
3862  (
3863  cellAnchorPoints,
3864  cellAddedCells,
3865  facei,
3866  f[anchorFp], // Anchor point
3867 
3868  own,
3869  nei
3870  );
3871 
3872 
3873  if (debug)
3874  {
3875  if (mesh_.isInternalFace(facei))
3876  {
3877  label oldOwn = mesh_.faceOwner()[facei];
3878  label oldNei = mesh_.faceNeighbour()[facei];
3879 
3880  checkInternalOrientation
3881  (
3882  meshMod,
3883  oldOwn,
3884  facei,
3885  mesh_.cellCentres()[oldOwn],
3886  mesh_.cellCentres()[oldNei],
3887  newFace
3888  );
3889  }
3890  else
3891  {
3892  label oldOwn = mesh_.faceOwner()[facei];
3893 
3894  checkBoundaryOrientation
3895  (
3896  meshMod,
3897  oldOwn,
3898  facei,
3899  mesh_.cellCentres()[oldOwn],
3900  mesh_.faceCentres()[facei],
3901  newFace
3902  );
3903  }
3904  }
3905 
3906  modifyFace(meshMod, facei, newFace, own, nei);
3907 
3908  // Mark face as having been handled
3909  affectedFace.unset(facei);
3910  }
3911  }
3912  }
3913  }
3914 
3915 
3916  // 3. faces that do not get split but whose owner/neighbour change
3917  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3918 
3919  if (debug)
3920  {
3921  Pout<< "hexRef8::setRefinement :"
3922  << " Changing owner/neighbour for otherwise unaffected faces"
3923  << endl;
3924  }
3925 
3926  forAll(affectedFace, facei)
3927  {
3928  if (affectedFace.get(facei))
3929  {
3930  const face& f = mesh_.faces()[facei];
3931 
3932  // The point with the lowest level should be an anchor
3933  // point of the neighbouring cells.
3934  label anchorFp = findMinLevel(f);
3935 
3936  label own, nei;
3937  getFaceNeighbours
3938  (
3939  cellAnchorPoints,
3940  cellAddedCells,
3941  facei,
3942  f[anchorFp], // Anchor point
3943 
3944  own,
3945  nei
3946  );
3947 
3948  modifyFace(meshMod, facei, f, own, nei);
3949 
3950  // Mark face as having been handled
3951  affectedFace.unset(facei);
3952  }
3953  }
3954 
3955 
3956  // 4. new internal faces inside split cells.
3957  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3958 
3959 
3960  // This is the hard one. We have to find the splitting points between
3961  // the anchor points. But the edges between the anchor points might have
3962  // been split (into two,three or four edges).
3963 
3964  if (debug)
3965  {
3966  Pout<< "hexRef8::setRefinement :"
3967  << " Create new internal faces for split cells"
3968  << endl;
3969  }
3970 
3971  forAll(cellMidPoint, celli)
3972  {
3973  if (cellMidPoint[celli] >= 0)
3974  {
3975  createInternalFaces
3976  (
3977  cellAnchorPoints,
3978  cellAddedCells,
3979  cellMidPoint,
3980  faceMidPoint,
3981  faceAnchorLevel,
3982  edgeMidPoint,
3983  celli,
3984  meshMod
3985  );
3986  }
3987  }
3988 
3989  // Extend pointLevels and cellLevels for the new cells. Could also be done
3990  // in topoChange but saves passing cellAddedCells out of this routine.
3991 
3992  // Check
3993  if (debug)
3994  {
3995  label minPointi = labelMax;
3996  label maxPointi = labelMin;
3997 
3998  forAll(cellMidPoint, celli)
3999  {
4000  if (cellMidPoint[celli] >= 0)
4001  {
4002  minPointi = min(minPointi, cellMidPoint[celli]);
4003  maxPointi = max(maxPointi, cellMidPoint[celli]);
4004  }
4005  }
4006  forAll(faceMidPoint, facei)
4007  {
4008  if (faceMidPoint[facei] >= 0)
4009  {
4010  minPointi = min(minPointi, faceMidPoint[facei]);
4011  maxPointi = max(maxPointi, faceMidPoint[facei]);
4012  }
4013  }
4014  forAll(edgeMidPoint, edgeI)
4015  {
4016  if (edgeMidPoint[edgeI] >= 0)
4017  {
4018  minPointi = min(minPointi, edgeMidPoint[edgeI]);
4019  maxPointi = max(maxPointi, edgeMidPoint[edgeI]);
4020  }
4021  }
4022 
4023  if (minPointi != labelMax && minPointi != mesh_.nPoints())
4024  {
4026  << "Added point labels not consecutive to existing mesh points."
4027  << nl
4028  << "mesh_.nPoints():" << mesh_.nPoints()
4029  << " minPointi:" << minPointi
4030  << " maxPointi:" << maxPointi
4031  << abort(FatalError);
4032  }
4033  }
4034 
4035  pointLevel_.transfer(newPointLevel);
4036  cellLevel_.transfer(newCellLevel);
4037 
4038  // Mark files as changed
4039  setInstance(mesh_.facesInstance());
4040 
4041 
4042  // Update the live split cells tree.
4043  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4044 
4045  // New unrefinement structure
4046  if (history_.active())
4047  {
4048  if (debug)
4049  {
4050  Pout<< "hexRef8::setRefinement :"
4051  << " Updating refinement history to " << cellLevel_.size()
4052  << " cells" << endl;
4053  }
4054 
4055  // Extend refinement history for new cells
4056  history_.resize(cellLevel_.size());
4057 
4058  forAll(cellAddedCells, celli)
4059  {
4060  const labelList& addedCells = cellAddedCells[celli];
4061 
4062  if (addedCells.size())
4063  {
4064  // Cell was split.
4065  history_.storeSplit(celli, addedCells);
4066  }
4067  }
4068  }
4069 
4070  // Compact cellAddedCells.
4071 
4072  labelListList refinedCells(cellLabels.size());
4073 
4074  forAll(cellLabels, i)
4075  {
4076  label celli = cellLabels[i];
4077 
4078  refinedCells[i].transfer(cellAddedCells[celli]);
4079  }
4080 
4081  return refinedCells;
4082 }
4083 
4084 
4086 (
4087  const labelList& pointsToStore,
4088  const labelList& facesToStore,
4089  const labelList& cellsToStore
4090 )
4091 {
4092  savedPointLevel_.resize(2*pointsToStore.size());
4093  forAll(pointsToStore, i)
4094  {
4095  label pointi = pointsToStore[i];
4096  savedPointLevel_.insert(pointi, pointLevel_[pointi]);
4097  }
4098 
4099  savedCellLevel_.resize(2*cellsToStore.size());
4100  forAll(cellsToStore, i)
4101  {
4102  label celli = cellsToStore[i];
4103  savedCellLevel_.insert(celli, cellLevel_[celli]);
4104  }
4105 }
4106 
4107 
4109 {
4110  Map<label> dummyMap(0);
4111 
4112  topoChange(map, dummyMap, dummyMap, dummyMap);
4113 }
4114 
4115 
4117 (
4118  const polyTopoChangeMap& map,
4119  const Map<label>& pointsToRestore,
4120  const Map<label>& facesToRestore,
4121  const Map<label>& cellsToRestore
4122 )
4123 {
4124  // Update celllevel
4125  if (debug)
4126  {
4127  Pout<< "hexRef8::topoChange :"
4128  << " Updating various lists"
4129  << endl;
4130  }
4131 
4132  {
4133  const labelList& reverseCellMap = map.reverseCellMap();
4134 
4135  if (debug)
4136  {
4137  Pout<< "hexRef8::topoChange :"
4138  << " reverseCellMap:" << map.reverseCellMap().size()
4139  << " cellMap:" << map.cellMap().size()
4140  << " nCells:" << mesh_.nCells()
4141  << " nOldCells:" << map.nOldCells()
4142  << " cellLevel_:" << cellLevel_.size()
4143  << " reversePointMap:" << map.reversePointMap().size()
4144  << " pointMap:" << map.pointMap().size()
4145  << " nPoints:" << mesh_.nPoints()
4146  << " nOldPoints:" << map.nOldPoints()
4147  << " pointLevel_:" << pointLevel_.size()
4148  << endl;
4149  }
4150 
4151  if (reverseCellMap.size() == cellLevel_.size())
4152  {
4153  // Assume it is after hexRef8 that this routine is called.
4154  // Just account for reordering. We cannot use cellMap since
4155  // then cells created from cells would get cellLevel_ of
4156  // cell they were created from.
4157  reorder(reverseCellMap, mesh_.nCells(), -1, cellLevel_);
4158  }
4159  else
4160  {
4161  // Map data
4162  const labelList& cellMap = map.cellMap();
4163 
4164  labelList newCellLevel(cellMap.size());
4165  forAll(cellMap, newCelli)
4166  {
4167  label oldCelli = cellMap[newCelli];
4168 
4169  if (oldCelli == -1)
4170  {
4171  newCellLevel[newCelli] = -1;
4172  }
4173  else
4174  {
4175  newCellLevel[newCelli] = cellLevel_[oldCelli];
4176  }
4177  }
4178  cellLevel_.transfer(newCellLevel);
4179  }
4180 
4181  // See if any cells to restore. This will be for some new cells
4182  // the corresponding old cell.
4183  forAllConstIter(Map<label>, cellsToRestore, iter)
4184  {
4185  label newCelli = iter.key();
4186  label storedCelli = iter();
4187 
4188  Map<label>::iterator fnd = savedCellLevel_.find(storedCelli);
4189 
4190  if (fnd == savedCellLevel_.end())
4191  {
4193  << "Problem : trying to restore old value for new cell "
4194  << newCelli << " but cannot find old cell " << storedCelli
4195  << " in map of stored values " << savedCellLevel_
4196  << abort(FatalError);
4197  }
4198  cellLevel_[newCelli] = fnd();
4199  }
4200  }
4201 
4202 
4203  // Update pointlevel
4204  {
4205  const labelList& reversePointMap = map.reversePointMap();
4206 
4207  if (reversePointMap.size() == pointLevel_.size())
4208  {
4209  // Assume it is after hexRef8 that this routine is called.
4210  reorder(reversePointMap, mesh_.nPoints(), -1, pointLevel_);
4211  }
4212  else
4213  {
4214  // Map data
4215  const labelList& pointMap = map.pointMap();
4216 
4217  labelList newPointLevel(pointMap.size());
4218 
4219  forAll(pointMap, newPointi)
4220  {
4221  label oldPointi = pointMap[newPointi];
4222 
4223  if (oldPointi == -1)
4224  {
4225  newPointLevel[newPointi] = -1;
4226  }
4227  else
4228  {
4229  newPointLevel[newPointi] = pointLevel_[oldPointi];
4230  }
4231  }
4232  pointLevel_.transfer(newPointLevel);
4233  }
4234 
4235  // See if any points to restore. This will be for some new points
4236  // the corresponding old point (the one from the call to storeData)
4237  forAllConstIter(Map<label>, pointsToRestore, iter)
4238  {
4239  label newPointi = iter.key();
4240  label storedPointi = iter();
4241 
4242  Map<label>::iterator fnd = savedPointLevel_.find(storedPointi);
4243 
4244  if (fnd == savedPointLevel_.end())
4245  {
4247  << "Problem : trying to restore old value for new point "
4248  << newPointi << " but cannot find old point "
4249  << storedPointi
4250  << " in map of stored values " << savedPointLevel_
4251  << abort(FatalError);
4252  }
4253  pointLevel_[newPointi] = fnd();
4254  }
4255  }
4256 
4257  // Update refinement tree
4258  if (history_.active())
4259  {
4260  history_.topoChange(map);
4261  }
4262 
4263  // Mark files as changed
4264  setInstance(mesh_.facesInstance());
4265 
4266  // Update face removal engine
4267  faceRemover_.topoChange(map);
4268 
4269  // Clear cell shapes
4270  cellShapesPtr_.clear();
4271 }
4272 
4273 
4275 (
4276  const labelList& pointMap,
4277  const labelList& faceMap,
4278  const labelList& cellMap
4279 )
4280 {
4281  // Update celllevel
4282  if (debug)
4283  {
4284  Pout<< "hexRef8::subset :"
4285  << " Updating various lists"
4286  << endl;
4287  }
4288 
4289  if (history_.active())
4290  {
4292  << "Subsetting will not work in combination with unrefinement."
4293  << nl
4294  << "Proceed at your own risk." << endl;
4295  }
4296 
4297 
4298  // Update celllevel
4299  {
4300  labelList newCellLevel(cellMap.size());
4301 
4302  forAll(cellMap, newCelli)
4303  {
4304  newCellLevel[newCelli] = cellLevel_[cellMap[newCelli]];
4305  }
4306 
4307  cellLevel_.transfer(newCellLevel);
4308 
4309  if (findIndex(cellLevel_, -1) != -1)
4310  {
4312  << "Problem : "
4313  << "cellLevel_ contains illegal value -1 after mapping:"
4314  << cellLevel_
4315  << abort(FatalError);
4316  }
4317  }
4318 
4319  // Update pointlevel
4320  {
4321  labelList newPointLevel(pointMap.size());
4322 
4323  forAll(pointMap, newPointi)
4324  {
4325  newPointLevel[newPointi] = pointLevel_[pointMap[newPointi]];
4326  }
4327 
4328  pointLevel_.transfer(newPointLevel);
4329 
4330  if (findIndex(pointLevel_, -1) != -1)
4331  {
4333  << "Problem : "
4334  << "pointLevel_ contains illegal value -1 after mapping:"
4335  << pointLevel_
4336  << abort(FatalError);
4337  }
4338  }
4339 
4340  // Update refinement tree
4341  if (history_.active())
4342  {
4343  history_.subset(pointMap, faceMap, cellMap);
4344  }
4345 
4346  // Mark files as changed
4347  setInstance(mesh_.facesInstance());
4348 
4349  // Nothing needs doing to faceRemover.
4350  // faceRemover_.subset(pointMap, faceMap, cellMap);
4351 
4352  // Clear cell shapes
4353  cellShapesPtr_.clear();
4354 }
4355 
4356 
4358 {
4359  if (debug)
4360  {
4361  Pout<< "hexRef8::distribute :"
4362  << " Updating various lists"
4363  << endl;
4364  }
4365 
4366  // Update celllevel
4367  map.distributeCellData(cellLevel_);
4368 
4369  // Update pointlevel
4370  map.distributePointData(pointLevel_);
4371 
4372  // Update refinement tree
4373  if (history_.active())
4374  {
4375  history_.distribute(map);
4376  }
4377 
4378  // Update face removal engine
4379  faceRemover_.distribute(map);
4380 
4381  // Clear cell shapes
4382  cellShapesPtr_.clear();
4383 }
4384 
4385 
4387 {
4388  const scalar smallDim = 1e-6 * mesh_.bounds().mag();
4389 
4390  if (debug)
4391  {
4392  Pout<< "hexRef8::checkMesh : Using matching tolerance smallDim:"
4393  << smallDim << endl;
4394  }
4395 
4396  // Check owner on coupled faces.
4397  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4398 
4399  // There should be only one coupled face between two cells. Why? Since
4400  // otherwise mesh redistribution might cause multiple faces between two
4401  // cells
4402  {
4403  labelList nei(mesh_.nFaces()-mesh_.nInternalFaces());
4404  forAll(nei, i)
4405  {
4406  nei[i] = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
4407  }
4408 
4409  // Replace data on coupled patches with their neighbour ones.
4410  syncTools::swapBoundaryFaceList(mesh_, nei);
4411 
4412  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
4413 
4415  {
4416  const polyPatch& pp = patches[patchi];
4417 
4418  if (pp.coupled())
4419  {
4420  // Check how many faces between owner and neighbour. Should
4421  // be only one.
4423  cellToFace(2*pp.size());
4424 
4425  label facei = pp.start();
4426 
4427  forAll(pp, i)
4428  {
4429  label own = mesh_.faceOwner()[facei];
4430  label bFacei = facei-mesh_.nInternalFaces();
4431 
4432  if (!cellToFace.insert(labelPair(own, nei[bFacei]), facei))
4433  {
4434  dumpCell(own);
4436  << "Faces do not seem to be correct across coupled"
4437  << " boundaries" << endl
4438  << "Coupled face " << facei
4439  << " between owner " << own
4440  << " on patch " << pp.name()
4441  << " and coupled neighbour " << nei[bFacei]
4442  << " has two faces connected to it:"
4443  << facei << " and "
4444  << cellToFace[labelPair(own, nei[bFacei])]
4445  << abort(FatalError);
4446  }
4447 
4448  facei++;
4449  }
4450  }
4451  }
4452  }
4453 
4454  // Check face areas.
4455  // ~~~~~~~~~~~~~~~~~
4456 
4457  {
4458  scalarField neiFaceAreas(mesh_.nFaces()-mesh_.nInternalFaces());
4459  forAll(neiFaceAreas, i)
4460  {
4461  neiFaceAreas[i] = mesh_.magFaceAreas()[i+mesh_.nInternalFaces()];
4462  }
4463 
4464  // Replace data on coupled patches with their neighbour ones.
4465  syncTools::swapBoundaryFaceList(mesh_, neiFaceAreas);
4466 
4467  forAll(neiFaceAreas, i)
4468  {
4469  label facei = i+mesh_.nInternalFaces();
4470 
4471  const scalar magArea = mesh_.magFaceAreas()[facei];
4472 
4473  if (mag(magArea - neiFaceAreas[i]) > smallDim)
4474  {
4475  const face& f = mesh_.faces()[facei];
4476  label patchi = mesh_.boundaryMesh().whichPatch(facei);
4477 
4478  dumpCell(mesh_.faceOwner()[facei]);
4479 
4481  << "Faces do not seem to be correct across coupled"
4482  << " boundaries" << endl
4483  << "Coupled face " << facei
4484  << " on patch " << patchi
4485  << " " << mesh_.boundaryMesh()[patchi].name()
4486  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4487  << " has face area:" << magArea
4488  << " (coupled) neighbour face area differs:"
4489  << neiFaceAreas[i]
4490  << " to within tolerance " << smallDim
4491  << abort(FatalError);
4492  }
4493  }
4494  }
4495 
4496 
4497  // Check number of points on faces.
4498  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4499  {
4500  labelList nVerts(mesh_.nFaces()-mesh_.nInternalFaces());
4501 
4502  forAll(nVerts, i)
4503  {
4504  nVerts[i] = mesh_.faces()[i+mesh_.nInternalFaces()].size();
4505  }
4506 
4507  // Replace data on coupled patches with their neighbour ones.
4508  syncTools::swapBoundaryFaceList(mesh_, nVerts);
4509 
4510  forAll(nVerts, i)
4511  {
4512  label facei = i+mesh_.nInternalFaces();
4513 
4514  const face& f = mesh_.faces()[facei];
4515 
4516  if (f.size() != nVerts[i])
4517  {
4518  dumpCell(mesh_.faceOwner()[facei]);
4519 
4520  label patchi = mesh_.boundaryMesh().whichPatch(facei);
4521 
4523  << "Faces do not seem to be correct across coupled"
4524  << " boundaries" << endl
4525  << "Coupled face " << facei
4526  << " on patch " << patchi
4527  << " " << mesh_.boundaryMesh()[patchi].name()
4528  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4529  << " has size:" << f.size()
4530  << " (coupled) neighbour face has size:"
4531  << nVerts[i]
4532  << abort(FatalError);
4533  }
4534  }
4535  }
4536 
4537 
4538  // Check points of face
4539  // ~~~~~~~~~~~~~~~~~~~~
4540  {
4541  // Anchor points.
4542  pointField anchorPoints(mesh_.nFaces()-mesh_.nInternalFaces());
4543 
4544  forAll(anchorPoints, i)
4545  {
4546  label facei = i+mesh_.nInternalFaces();
4547  const point& fc = mesh_.faceCentres()[facei];
4548  const face& f = mesh_.faces()[facei];
4549  const vector anchorVec(mesh_.points()[f[0]] - fc);
4550 
4551  anchorPoints[i] = anchorVec;
4552  }
4553 
4554  // Replace data on coupled patches with their neighbour ones. Apply
4555  // rotation transformation (but not separation since is relative vector
4556  // to point on same face.
4557  syncTools::swapBoundaryFaceList(mesh_, anchorPoints);
4558 
4559  forAll(anchorPoints, i)
4560  {
4561  label facei = i+mesh_.nInternalFaces();
4562  const point& fc = mesh_.faceCentres()[facei];
4563  const face& f = mesh_.faces()[facei];
4564  const vector anchorVec(mesh_.points()[f[0]] - fc);
4565 
4566  if (mag(anchorVec - anchorPoints[i]) > smallDim)
4567  {
4568  dumpCell(mesh_.faceOwner()[facei]);
4569 
4570  label patchi = mesh_.boundaryMesh().whichPatch(facei);
4571 
4573  << "Faces do not seem to be correct across coupled"
4574  << " boundaries" << endl
4575  << "Coupled face " << facei
4576  << " on patch " << patchi
4577  << " " << mesh_.boundaryMesh()[patchi].name()
4578  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4579  << " has anchor vector:" << anchorVec
4580  << " (coupled) neighbour face anchor vector differs:"
4581  << anchorPoints[i]
4582  << " to within tolerance " << smallDim
4583  << abort(FatalError);
4584  }
4585  }
4586  }
4587 
4588  if (debug)
4589  {
4590  Pout<< "hexRef8::checkMesh : Returning" << endl;
4591  }
4592 }
4593 
4594 
4596 (
4597  const label maxPointDiff,
4598  const labelList& pointsToCheck
4599 ) const
4600 {
4601  if (debug)
4602  {
4603  Pout<< "hexRef8::checkRefinementLevels :"
4604  << " Checking 2:1 refinement level" << endl;
4605  }
4606 
4607  if
4608  (
4609  cellLevel_.size() != mesh_.nCells()
4610  || pointLevel_.size() != mesh_.nPoints()
4611  )
4612  {
4614  << "cellLevel size should be number of cells"
4615  << " and pointLevel size should be number of points."<< nl
4616  << "cellLevel:" << cellLevel_.size()
4617  << " mesh.nCells():" << mesh_.nCells() << nl
4618  << "pointLevel:" << pointLevel_.size()
4619  << " mesh.nPoints():" << mesh_.nPoints()
4620  << abort(FatalError);
4621  }
4622 
4623 
4624  // Check 2:1 consistency.
4625  // ~~~~~~~~~~~~~~~~~~~~~~
4626 
4627  {
4628  // Internal faces.
4629  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
4630  {
4631  label own = mesh_.faceOwner()[facei];
4632  label nei = mesh_.faceNeighbour()[facei];
4633 
4634  if (mag(cellLevel_[own] - cellLevel_[nei]) > 1)
4635  {
4636  dumpCell(own);
4637  dumpCell(nei);
4638 
4640  << "Celllevel does not satisfy 2:1 constraint." << nl
4641  << "On face " << facei << " owner cell " << own
4642  << " has refinement " << cellLevel_[own]
4643  << " neighbour cell " << nei << " has refinement "
4644  << cellLevel_[nei]
4645  << abort(FatalError);
4646  }
4647  }
4648 
4649  // Coupled faces. Get neighbouring value
4650  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
4651 
4652  forAll(neiLevel, i)
4653  {
4654  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
4655 
4656  neiLevel[i] = cellLevel_[own];
4657  }
4658 
4659  // No separation
4660  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
4661 
4662  forAll(neiLevel, i)
4663  {
4664  label facei = i+mesh_.nInternalFaces();
4665 
4666  label own = mesh_.faceOwner()[facei];
4667 
4668  if (mag(cellLevel_[own] - neiLevel[i]) > 1)
4669  {
4670  dumpCell(own);
4671 
4672  label patchi = mesh_.boundaryMesh().whichPatch(facei);
4673 
4675  << "Celllevel does not satisfy 2:1 constraint."
4676  << " On coupled face " << facei
4677  << " on patch " << patchi << " "
4678  << mesh_.boundaryMesh()[patchi].name()
4679  << " owner cell " << own << " has refinement "
4680  << cellLevel_[own]
4681  << " (coupled) neighbour cell has refinement "
4682  << neiLevel[i]
4683  << abort(FatalError);
4684  }
4685  }
4686  }
4687 
4688 
4689  // Check pointLevel is synchronised
4690  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4691  {
4692  labelList syncPointLevel(pointLevel_);
4693 
4694  // Get min level
4696  (
4697  mesh_,
4698  syncPointLevel,
4699  minEqOp<label>(),
4700  labelMax
4701  );
4702 
4703 
4704  forAll(syncPointLevel, pointi)
4705  {
4706  if (pointLevel_[pointi] != syncPointLevel[pointi])
4707  {
4709  << "PointLevel is not consistent across coupled patches."
4710  << endl
4711  << "point:" << pointi << " coord:" << mesh_.points()[pointi]
4712  << " has level " << pointLevel_[pointi]
4713  << " whereas the coupled point has level "
4714  << syncPointLevel[pointi]
4715  << abort(FatalError);
4716  }
4717  }
4718  }
4719 
4720 
4721  // Check 2:1 across points (instead of faces)
4722  if (maxPointDiff != -1)
4723  {
4724  // Determine per point the max cell level.
4725  labelList maxPointLevel(mesh_.nPoints(), 0);
4726 
4727  forAll(maxPointLevel, pointi)
4728  {
4729  const labelList& pCells = mesh_.pointCells(pointi);
4730 
4731  label& pLevel = maxPointLevel[pointi];
4732 
4733  forAll(pCells, i)
4734  {
4735  pLevel = max(pLevel, cellLevel_[pCells[i]]);
4736  }
4737  }
4738 
4739  // Sync maxPointLevel to neighbour
4741  (
4742  mesh_,
4743  maxPointLevel,
4744  maxEqOp<label>(),
4745  labelMin // null value
4746  );
4747 
4748  // Check 2:1 across boundary points
4749  forAll(pointsToCheck, i)
4750  {
4751  label pointi = pointsToCheck[i];
4752 
4753  const labelList& pCells = mesh_.pointCells(pointi);
4754 
4755  forAll(pCells, i)
4756  {
4757  label celli = pCells[i];
4758 
4759  if
4760  (
4761  mag(cellLevel_[celli]-maxPointLevel[pointi])
4762  > maxPointDiff
4763  )
4764  {
4765  dumpCell(celli);
4766 
4768  << "Too big a difference between"
4769  << " point-connected cells." << nl
4770  << "cell:" << celli
4771  << " cellLevel:" << cellLevel_[celli]
4772  << " uses point:" << pointi
4773  << " coord:" << mesh_.points()[pointi]
4774  << " which is also used by a cell with level:"
4775  << maxPointLevel[pointi]
4776  << abort(FatalError);
4777  }
4778  }
4779  }
4780  }
4781 
4782 
4783  //- Gives problems after first splitting off inside mesher.
4785  //{
4786  // // Any patches with points having only two edges.
4787  //
4788  // boolList isHangingPoint(mesh_.nPoints(), false);
4789  //
4790  // const polyBoundaryMesh& patches = mesh_.boundaryMesh();
4791  //
4792  // forAll(patches, patchi)
4793  // {
4794  // const polyPatch& pp = patches[patchi];
4795  //
4796  // const labelList& meshPoints = pp.meshPoints();
4797  //
4798  // forAll(meshPoints, i)
4799  // {
4800  // label pointi = meshPoints[i];
4801  //
4802  // const labelList& pEdges = mesh_.pointEdges()[pointi];
4803  //
4804  // if (pEdges.size() == 2)
4805  // {
4806  // isHangingPoint[pointi] = true;
4807  // }
4808  // }
4809  // }
4810  //
4811  // syncTools::syncPointList
4812  // (
4813  // mesh_,
4814  // isHangingPoint,
4815  // andEqOp<bool>(), // only if all decide it is hanging point
4816  // true, // null
4817  // false // no separation
4818  // );
4819  //
4820  // // OFstream str(mesh_.time().path()/"hangingPoints.obj");
4821  //
4822  // label nHanging = 0;
4823  //
4824  // forAll(isHangingPoint, pointi)
4825  // {
4826  // if (isHangingPoint[pointi])
4827  // {
4828  // nHanging++;
4829  //
4830  // Pout<< "Hanging boundary point " << pointi
4831  // << " at " << mesh_.points()[pointi]
4832  // << endl;
4833  // // meshTools::writeOBJ(str, mesh_.points()[pointi]);
4834  // }
4835  // }
4836  //
4837  // if (returnReduce(nHanging, sumOp<label>()) > 0)
4838  // {
4839  // FatalErrorInFunction
4840  // << "Detected a point used by two edges only (hanging point)"
4841  // << nl << "This is not allowed"
4842  // << abort(FatalError);
4843  // }
4844  //}
4845 }
4846 
4847 
4849 {
4850  if (cellShapesPtr_.empty())
4851  {
4852  if (debug)
4853  {
4854  Pout<< "hexRef8::cellShapes() : calculating splitHex cellShapes."
4855  << " cellLevel:" << cellLevel_.size()
4856  << " pointLevel:" << pointLevel_.size()
4857  << endl;
4858  }
4859 
4860  const cellShapeList& meshShapes = mesh_.cellShapes();
4861  cellShapesPtr_.reset(new cellShapeList(meshShapes));
4862 
4863  label nSplitHex = 0;
4864  label nUnrecognised = 0;
4865 
4866  forAll(cellLevel_, celli)
4867  {
4868  if (meshShapes[celli].model().index() == 0)
4869  {
4870  label level = cellLevel_[celli];
4871 
4872  // Return true if we've found 6 quads
4873  DynamicList<face> quads;
4874  bool haveQuads = matchHexShape
4875  (
4876  celli,
4877  level,
4878  quads
4879  );
4880 
4881  if (haveQuads)
4882  {
4883  faceList faces(move(quads));
4884  cellShapesPtr_()[celli] = degenerateMatcher::match(faces);
4885  nSplitHex++;
4886  }
4887  else
4888  {
4889  nUnrecognised++;
4890  }
4891  }
4892  }
4893  if (debug)
4894  {
4895  Pout<< "hexRef8::cellShapes() :"
4896  << " nCells:" << mesh_.nCells() << " of which" << nl
4897  << " primitive:" << (mesh_.nCells()-nSplitHex-nUnrecognised)
4898  << nl
4899  << " split-hex:" << nSplitHex << nl
4900  << " poly :" << nUnrecognised << nl
4901  << endl;
4902  }
4903  }
4904  return cellShapesPtr_();
4905 }
4906 
4907 
4909 {
4910  if (debug)
4911  {
4912  checkRefinementLevels(-1, labelList(0));
4913  }
4914 
4915  if (debug)
4916  {
4917  Pout<< "hexRef8::getSplitPoints :"
4918  << " Calculating unrefineable points" << endl;
4919  }
4920 
4921 
4922  if (!history_.active())
4923  {
4925  << "Only call if constructed with history capability"
4926  << abort(FatalError);
4927  }
4928 
4929  // Master cell
4930  // -1 undetermined
4931  // -2 certainly not split point
4932  // >= label of master cell
4933  labelList splitMaster(mesh_.nPoints(), -1);
4934  labelList splitMasterLevel(mesh_.nPoints(), 0);
4935 
4936  // Unmark all with not 8 cells
4937  // const labelListList& pointCells = mesh_.pointCells();
4938 
4939  for (label pointi = 0; pointi < mesh_.nPoints(); pointi++)
4940  {
4941  const labelList& pCells = mesh_.pointCells(pointi);
4942 
4943  if (pCells.size() != 8)
4944  {
4945  splitMaster[pointi] = -2;
4946  }
4947  }
4948 
4949  // Unmark all with different master cells
4950  const labelList& visibleCells = history_.visibleCells();
4951 
4952  forAll(visibleCells, celli)
4953  {
4954  const labelList& cPoints = mesh_.cellPoints(celli);
4955 
4956  if (visibleCells[celli] != -1 && history_.parentIndex(celli) >= 0)
4957  {
4958  label parentIndex = history_.parentIndex(celli);
4959 
4960  // Check same master.
4961  forAll(cPoints, i)
4962  {
4963  label pointi = cPoints[i];
4964 
4965  label masterCelli = splitMaster[pointi];
4966 
4967  if (masterCelli == -1)
4968  {
4969  // First time visit of point. Store parent cell and
4970  // level of the parent cell (with respect to celli). This
4971  // is additional guarantee that we're referring to the
4972  // same master at the same refinement level.
4973 
4974  splitMaster[pointi] = parentIndex;
4975  splitMasterLevel[pointi] = cellLevel_[celli] - 1;
4976  }
4977  else if (masterCelli == -2)
4978  {
4979  // Already decided that point is not splitPoint
4980  }
4981  else if
4982  (
4983  (masterCelli != parentIndex)
4984  || (splitMasterLevel[pointi] != cellLevel_[celli] - 1)
4985  )
4986  {
4987  // Different masters so point is on two refinement
4988  // patterns
4989  splitMaster[pointi] = -2;
4990  }
4991  }
4992  }
4993  else
4994  {
4995  // Either not visible or is unrefined cell
4996  forAll(cPoints, i)
4997  {
4998  label pointi = cPoints[i];
4999 
5000  splitMaster[pointi] = -2;
5001  }
5002  }
5003  }
5004 
5005  // Unmark boundary faces
5006  for
5007  (
5008  label facei = mesh_.nInternalFaces();
5009  facei < mesh_.nFaces();
5010  facei++
5011  )
5012  {
5013  const face& f = mesh_.faces()[facei];
5014 
5015  forAll(f, fp)
5016  {
5017  splitMaster[f[fp]] = -2;
5018  }
5019  }
5020 
5021 
5022  // Collect into labelList
5023 
5024  label nSplitPoints = 0;
5025 
5026  forAll(splitMaster, pointi)
5027  {
5028  if (splitMaster[pointi] >= 0)
5029  {
5030  nSplitPoints++;
5031  }
5032  }
5033 
5034  labelList splitPoints(nSplitPoints);
5035  nSplitPoints = 0;
5036 
5037  forAll(splitMaster, pointi)
5038  {
5039  if (splitMaster[pointi] >= 0)
5040  {
5041  splitPoints[nSplitPoints++] = pointi;
5042  }
5043  }
5044 
5045  return splitPoints;
5046 }
5047 
5048 
5050 (
5051  const labelList& pointsToUnrefine,
5052  const bool maxSet
5053 ) const
5054 {
5055  if (debug)
5056  {
5057  Pout<< "hexRef8::consistentUnrefinement :"
5058  << " Determining 2:1 consistent unrefinement" << endl;
5059  }
5060 
5061  if (maxSet)
5062  {
5064  << "maxSet not implemented yet."
5065  << abort(FatalError);
5066  }
5067 
5068  // Loop, modifying pointsToUnrefine, until no more changes to due to 2:1
5069  // conflicts.
5070  // maxSet = false : deselect points to refine
5071  // maxSet = true: select points to refine
5072 
5073  // Maintain boolList for pointsToUnrefine and cellsToUnrefine
5074  PackedBoolList unrefinePoint(mesh_.nPoints());
5075 
5076  forAll(pointsToUnrefine, i)
5077  {
5078  label pointi = pointsToUnrefine[i];
5079 
5080  unrefinePoint.set(pointi);
5081  }
5082 
5083 
5084  while (true)
5085  {
5086  // Construct cells to unrefine
5087  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5088 
5089  PackedBoolList unrefineCell(mesh_.nCells());
5090 
5091  forAll(unrefinePoint, pointi)
5092  {
5093  if (unrefinePoint.get(pointi))
5094  {
5095  const labelList& pCells = mesh_.pointCells(pointi);
5096 
5097  forAll(pCells, j)
5098  {
5099  unrefineCell.set(pCells[j]);
5100  }
5101  }
5102  }
5103 
5104 
5105  label nChanged = 0;
5106 
5107 
5108  // Check 2:1 consistency taking refinement into account
5109  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5110 
5111  // Internal faces.
5112  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
5113  {
5114  label own = mesh_.faceOwner()[facei];
5115  label ownLevel = cellLevel_[own] - unrefineCell.get(own);
5116 
5117  label nei = mesh_.faceNeighbour()[facei];
5118  label neiLevel = cellLevel_[nei] - unrefineCell.get(nei);
5119 
5120  if (ownLevel < (neiLevel-1))
5121  {
5122  // Since was 2:1 this can only occur if own is marked for
5123  // unrefinement.
5124 
5125  if (maxSet)
5126  {
5127  unrefineCell.set(nei);
5128  }
5129  else
5130  {
5131  // could also combine with unset:
5132  // if (!unrefineCell.unset(own))
5133  // {
5134  // FatalErrorInFunction
5135  // << "problem cell already unset"
5136  // << abort(FatalError);
5137  // }
5138  if (unrefineCell.get(own) == 0)
5139  {
5141  << "problem" << abort(FatalError);
5142  }
5143 
5144  unrefineCell.unset(own);
5145  }
5146  nChanged++;
5147  }
5148  else if (neiLevel < (ownLevel-1))
5149  {
5150  if (maxSet)
5151  {
5152  unrefineCell.set(own);
5153  }
5154  else
5155  {
5156  if (unrefineCell.get(nei) == 0)
5157  {
5159  << "problem" << abort(FatalError);
5160  }
5161 
5162  unrefineCell.unset(nei);
5163  }
5164  nChanged++;
5165  }
5166  }
5167 
5168 
5169  // Coupled faces. Swap owner level to get neighbouring cell level.
5170  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
5171 
5172  forAll(neiLevel, i)
5173  {
5174  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
5175 
5176  neiLevel[i] = cellLevel_[own] - unrefineCell.get(own);
5177  }
5178 
5179  // Swap to neighbour
5180  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
5181 
5182  forAll(neiLevel, i)
5183  {
5184  label facei = i+mesh_.nInternalFaces();
5185  label own = mesh_.faceOwner()[facei];
5186  label ownLevel = cellLevel_[own] - unrefineCell.get(own);
5187 
5188  if (ownLevel < (neiLevel[i]-1))
5189  {
5190  if (!maxSet)
5191  {
5192  if (unrefineCell.get(own) == 0)
5193  {
5195  << "problem" << abort(FatalError);
5196  }
5197 
5198  unrefineCell.unset(own);
5199  nChanged++;
5200  }
5201  }
5202  else if (neiLevel[i] < (ownLevel-1))
5203  {
5204  if (maxSet)
5205  {
5206  if (unrefineCell.get(own) == 1)
5207  {
5209  << "problem" << abort(FatalError);
5210  }
5211 
5212  unrefineCell.set(own);
5213  nChanged++;
5214  }
5215  }
5216  }
5217 
5218  reduce(nChanged, sumOp<label>());
5219 
5220  if (debug)
5221  {
5222  Pout<< "hexRef8::consistentUnrefinement :"
5223  << " Changed " << nChanged
5224  << " refinement levels due to 2:1 conflicts."
5225  << endl;
5226  }
5227 
5228  if (nChanged == 0)
5229  {
5230  break;
5231  }
5232 
5233 
5234  // Convert cellsToUnrefine back into points to unrefine
5235  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5236 
5237  // Knock out any point whose cell neighbour cannot be unrefined.
5238  forAll(unrefinePoint, pointi)
5239  {
5240  if (unrefinePoint.get(pointi))
5241  {
5242  const labelList& pCells = mesh_.pointCells(pointi);
5243 
5244  forAll(pCells, j)
5245  {
5246  if (!unrefineCell.get(pCells[j]))
5247  {
5248  unrefinePoint.unset(pointi);
5249  break;
5250  }
5251  }
5252  }
5253  }
5254  }
5255 
5256 
5257  // Convert back to labelList.
5258  label nSet = 0;
5259 
5260  forAll(unrefinePoint, pointi)
5261  {
5262  if (unrefinePoint.get(pointi))
5263  {
5264  nSet++;
5265  }
5266  }
5267 
5268  labelList newPointsToUnrefine(nSet);
5269  nSet = 0;
5270 
5271  forAll(unrefinePoint, pointi)
5272  {
5273  if (unrefinePoint.get(pointi))
5274  {
5275  newPointsToUnrefine[nSet++] = pointi;
5276  }
5277  }
5278 
5279  return newPointsToUnrefine;
5280 }
5281 
5282 
5284 (
5285  const labelList& splitPointLabels,
5286  polyTopoChange& meshMod
5287 )
5288 {
5289  if (!history_.active())
5290  {
5292  << "Only call if constructed with history capability"
5293  << abort(FatalError);
5294  }
5295 
5296  if (debug)
5297  {
5298  Pout<< "hexRef8::setUnrefinement :"
5299  << " Checking initial mesh just to make sure" << endl;
5300 
5301  checkMesh();
5302 
5303  forAll(cellLevel_, celli)
5304  {
5305  if (cellLevel_[celli] < 0)
5306  {
5308  << "Illegal cell level " << cellLevel_[celli]
5309  << " for cell " << celli
5310  << abort(FatalError);
5311  }
5312  }
5313 
5314 
5315  // Write to sets.
5316  pointSet pSet(mesh_, "splitPoints", splitPointLabels);
5317  pSet.write();
5318 
5319  cellSet cSet(mesh_, "splitPointCells", splitPointLabels.size());
5320 
5321  forAll(splitPointLabels, i)
5322  {
5323  const labelList& pCells = mesh_.pointCells(splitPointLabels[i]);
5324 
5325  forAll(pCells, j)
5326  {
5327  cSet.insert(pCells[j]);
5328  }
5329  }
5330  cSet.write();
5331 
5332  Pout<< "hexRef8::setRefinement : Dumping " << pSet.size()
5333  << " points and "
5334  << cSet.size() << " cells for unrefinement to" << nl
5335  << " pointSet " << pSet.objectPath() << nl
5336  << " cellSet " << cSet.objectPath()
5337  << endl;
5338  }
5339 
5340 
5341  labelList cellRegion;
5342  labelList cellRegionMaster;
5343  labelList facesToRemove;
5344 
5345  {
5346  labelHashSet splitFaces(12*splitPointLabels.size());
5347 
5348  forAll(splitPointLabels, i)
5349  {
5350  const labelList& pFaces = mesh_.pointFaces()[splitPointLabels[i]];
5351 
5352  forAll(pFaces, j)
5353  {
5354  splitFaces.insert(pFaces[j]);
5355  }
5356  }
5357 
5358  // Check with faceRemover what faces will get removed. Note that this
5359  // can be more (but never less) than splitFaces provided.
5360  faceRemover_.compatibleRemoves
5361  (
5362  splitFaces.toc(), // pierced faces
5363  cellRegion, // per cell -1 or region it is merged into
5364  cellRegionMaster, // per region the master cell
5365  facesToRemove // new faces to be removed.
5366  );
5367 
5368  if (facesToRemove.size() != splitFaces.size())
5369  {
5371  << "Initial set of split points to unrefine does not"
5372  << " seem to be consistent or not mid points of refined cells"
5373  << abort(FatalError);
5374  }
5375  }
5376 
5377  // Redo the region master so it is consistent with our master.
5378  // This will guarantee that the new cell (for which faceRemover uses
5379  // the region master) is already compatible with our refinement structure.
5380 
5381  forAll(splitPointLabels, i)
5382  {
5383  label pointi = splitPointLabels[i];
5384 
5385  // Get original cell label
5386 
5387  const labelList& pCells = mesh_.pointCells(pointi);
5388 
5389  // Check
5390  if (pCells.size() != 8)
5391  {
5393  << "splitPoint " << pointi
5394  << " should have 8 cells using it. It has " << pCells
5395  << abort(FatalError);
5396  }
5397 
5398 
5399  // Check that the lowest numbered pCells is the master of the region
5400  // (should be guaranteed by directRemoveFaces)
5401  // if (debug)
5402  {
5403  label masterCelli = min(pCells);
5404 
5405  forAll(pCells, j)
5406  {
5407  label celli = pCells[j];
5408 
5409  label region = cellRegion[celli];
5410 
5411  if (region == -1)
5412  {
5414  << "Initial set of split points to unrefine does not"
5415  << " seem to be consistent or not mid points"
5416  << " of refined cells" << nl
5417  << "cell:" << celli << " on splitPoint " << pointi
5418  << " has no region to be merged into"
5419  << abort(FatalError);
5420  }
5421 
5422  if (masterCelli != cellRegionMaster[region])
5423  {
5425  << "cell:" << celli << " on splitPoint:" << pointi
5426  << " in region " << region
5427  << " has master:" << cellRegionMaster[region]
5428  << " which is not the lowest numbered cell"
5429  << " among the pointCells:" << pCells
5430  << abort(FatalError);
5431  }
5432  }
5433  }
5434  }
5435 
5436  // Insert all commands to combine cells. Never fails so don't have to
5437  // test for success.
5438  faceRemover_.setRefinement
5439  (
5440  facesToRemove,
5441  cellRegion,
5442  cellRegionMaster,
5443  meshMod
5444  );
5445 
5446  // Remove the 8 cells that originated from merging around the split point
5447  // and adapt cell levels (not that pointLevels stay the same since points
5448  // either get removed or stay at the same position.
5449  forAll(splitPointLabels, i)
5450  {
5451  label pointi = splitPointLabels[i];
5452 
5453  const labelList& pCells = mesh_.pointCells(pointi);
5454 
5455  label masterCelli = min(pCells);
5456 
5457  forAll(pCells, j)
5458  {
5459  cellLevel_[pCells[j]]--;
5460  }
5461 
5462  history_.combineCells(masterCelli, pCells);
5463  }
5464 
5465  // Mark files as changed
5466  setInstance(mesh_.facesInstance());
5467 
5468  // history_.topoChange will take care of truncating.
5469 }
5470 
5471 
5472 bool Foam::hexRef8::write(const bool write) const
5473 {
5474  if (cellLevel_.size() != mesh_.nCells())
5475  {
5477  << "Size of cellLevel:" << cellLevel_.size()
5478  << " does not equal number of cells in mesh:" << mesh_.nCells()
5479  << abort(FatalError);
5480  }
5481 
5482  if (pointLevel_.size() != mesh_.nPoints())
5483  {
5485  << "Size of pointLevel:" << pointLevel_.size()
5486  << " does not equal number of points in mesh:" << mesh_.nPoints()
5487  << abort(FatalError);
5488  }
5489 
5490  bool writeOk =
5491  cellLevel_.write(write)
5492  && pointLevel_.write(write)
5493  && level0Edge_.write(write);
5494 
5495  if (history_.active())
5496  {
5497  writeOk = writeOk && history_.write(write);
5498  }
5499 
5500  return writeOk;
5501 }
5502 
5503 
5504 // ************************************************************************* //
scalar y
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:130
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Definition: DynamicListI.H:296
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:252
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:236
Wave propagation of information through grid. Every iteration information goes through one layer of c...
Definition: FaceCellWave.H:79
static scalar propagationTol()
Access to tolerance.
Definition: FaceCellWave.H:228
void setFaceInfo(const labelList &changedFaces, const List< Type > &changedFacesInfo)
Set initial changed faces.
Definition: FaceCellWave.C:260
virtual label iterate(const label maxIter)
Iterate until no changes or maxIter reached. Returns actual.
Definition: FaceCellWave.C:951
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:109
An STL-conforming hash table.
Definition: HashTable.H:127
List< Key > toc() const
Return the table of contents.
Definition: HashTable.C:227
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
friend class iterator
Declare friendship with the iterator.
Definition: HashTable.H:194
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:167
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
readOption readOpt() const
Definition: IOobject.H:360
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:226
fileCheckTypes
Enumeration defining the file checking options.
Definition: IOobject.H:133
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void resize(const label)
Alias for setSize(const label)
Definition: ListI.H:138
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:125
void setSize(const label)
Reset size of List.
Definition: List.C:281
A HashTable to objects of type <T> with a label key.
Definition: Map.H:52
Output to file stream.
Definition: OFstream.H:86
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:120
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:85
A bit-packed bool list.
void set(const PackedList< 1 > &)
Set specified bits.
void unset(const PackedList< 1 > &)
Unset specified bits.
unsigned int get(const label) const
Get value at index I.
Definition: PackedListI.H:954
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
A List with indirect addressing.
Definition: UIndirectList.H:60
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
T & last()
Return the last element of the list.
Definition: UListI.H:128
Holds information regarding type of cell. Used in inside/outside determination in cellClassification.
Definition: cellInfo.H:67
A collection of cell labels.
Definition: cellSet.H:51
A topoSetSource to select a faceSet from cells.
Definition: cellToFace.H:56
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:60
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:61
A list of face labels.
Definition: faceSet.H:51
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
A class for handling file names.
Definition: fileName.H:82
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef8.H:65
void checkRefinementLevels(const label maxPointDiff, const labelList &pointsToCheck) const
Debug: Check 2:1 consistency across faces.
Definition: hexRef8.C:4596
labelList consistentSlowRefinement(const label maxFaceDiff, const labelList &cellsToRefine, const labelList &facesToCheck, const label maxPointDiff, const labelList &pointsToCheck) const
Like consistentRefinement but slower:
Definition: hexRef8.C:2184
hexRef8(const polyMesh &mesh, const bool readHistory=true)
Construct from mesh, read_if_present refinement data.
Definition: hexRef8.C:1789
void checkMesh() const
Debug: Check coupled mesh for correctness.
Definition: hexRef8.C:4386
labelListList setRefinement(const labelList &cells, polyTopoChange &)
Insert refinement. All selected cells will be split into 8.
Definition: hexRef8.C:3090
void topoChange(const polyTopoChangeMap &)
Update local numbering for changed mesh.
Definition: hexRef8.C:4108
void distribute(const polyDistributionMap &)
Update local numbering for mesh redistribution.
Definition: hexRef8.C:4357
const cellShapeList & cellShapes() const
Utility: get hexes as cell shapes.
Definition: hexRef8.C:4848
bool write(const bool write=true) const
Force writing refinement+history to polyMesh directory.
Definition: hexRef8.C:5472
void setUnrefinement(const labelList &splitPointLabels, polyTopoChange &)
Remove some refinement. Needs to be supplied output of.
Definition: hexRef8.C:5284
labelList consistentUnrefinement(const labelList &pointsToUnrefine, const bool maxSet) const
Given proposed.
Definition: hexRef8.C:5050
labelList getSplitPoints() const
Return the points at the centre of top-level split cells.
Definition: hexRef8.C:4908
label faceLevel(const label facei) const
Gets level such that the face has four points <= level.
Definition: hexRef8.C:675
void storeData(const labelList &pointsToStore, const labelList &facesToStore, const labelList &cellsToStore)
Signal points/face/cells for which to store data.
Definition: hexRef8.C:4086
labelList consistentRefinement(const labelList &cellsToRefine, const bool maxSet) const
Given valid mesh and current cell level and proposed.
Definition: hexRef8.C:2115
labelList consistentSlowRefinement2(const label maxFaceDiff, const labelList &cellsToRefine, const labelList &facesToCheck) const
Like consistentSlowRefinement but uses different meshWave.
Definition: hexRef8.C:2668
void subset(const labelList &pointMap, const labelList &faceMap, const labelList &cellMap)
Update local numbering for subsetted mesh.
Definition: hexRef8.C:4275
void setInstance(const fileName &inst)
Definition: hexRef8.C:1595
Reduction class. If x and y are not equal assign value.
Definition: hexRef8.C:52
void operator()(label &x, const label y) const
Definition: hexRef8.C:54
const word & name() const
Return name.
A set of point labels.
Definition: pointSet.H:51
Foam::polyBoundaryMesh.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
void distributeCellData(List< T > &lst) const
Distribute list of cell data.
void distributePointData(List< T > &lst) const
Distribute list of point data.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:70
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:290
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:280
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
label nOldCells() const
Number of old cells.
const labelList & cellMap() const
Old cell map.
const labelList & reversePointMap() const
Reverse point map.
const labelList & pointMap() const
Old point map.
const labelList & reverseCellMap() const
Reverse cell map.
label nOldPoints() const
Number of old points.
Direct mesh changes based on v1.3 polyTopoChange syntax.
const DynamicList< point > & points() const
Points. Shrunk after constructing mesh (or calling of compact())
label addCell(const label masterCellID)
Add cell and return new cell index.
label addPoint(const point &, const label masterPointID, const bool inCell)
Add point and return new point index.
label nCells() const
label nPoints() const
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:57
Transfers refinement levels such that slow transition between levels is maintained....
label count() const
bool updateFace(const polyMesh &, const label thisFacei, const label neighbourCelli, const refinementData &neighbourInfo, const scalar tol, TrackingData &td)
Influence of neighbouring cell.
Transfers refinement levels such that slow transition between levels is maintained....
All refinement history. Used in unrefinement.
const labelList & visibleCells() const
Per cell in the current mesh (i.e. visible) either -1 (unrefined)
bool active() const
Is there unrefinement history?
virtual bool read()
Read object. If global number of visible cells > 0 becomes active.
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:158
virtual bool write(const bool write=true) const
Write using setting from DB.
bool headerOk()
Read and check header info.
Definition: regIOobject.C:453
static void syncPointList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronise values on all mesh points.
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:436
static void syncEdgeList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronise values on all mesh edges.
static void syncEdgePositions(const polyMesh &mesh, List< point > &l, const CombineOp &cop, const point &nullValue)
Synchronise locations on all mesh edges.
Definition: syncTools.H:283
static void syncBoundaryFacePositions(const polyMesh &mesh, UList< point > &l, const CombineOp &cop)
Synchronise locations on boundary faces only.
Definition: syncTools.H:369
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronise values on all mesh faces.
Definition: syncTools.H:387
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
const pointField & points
label nPoints
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
const fvPatchList & patches
#define WarningInFunction
Report a warning using Foam::Warning.
bool valid(const PtrList< ModelType > &l)
bool checkMesh(const bool report, const polyMesh &mesh, const dictionary &dict, const labelList &checkFaces, const List< labelPair > &baffles, labelHashSet &wrongFaces)
Check (subset of mesh including baffles) with mesh settings in dict.
Definition: checkMesh.C:33
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:337
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
prefixOSstream Perr(cerr, "Perr")
Definition: IOstreams.H:54
List< cellShape > cellShapeList
List of cellShapes and PtrList of List of cellShape.
Definition: cellShapeList.H:43
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
const doubleScalar e
Definition: doubleScalar.H:106
List< label > labelList
A List of labels.
Definition: labelList.H:56
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
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurrences of given element. Linear search.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const dimensionSet dimLength
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
vector point
Point is a vector.
Definition: point.H:41
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void reverse(UList< T > &, const label n)
Definition: UListI.H:334
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
Addressing for a faceList slice.
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensionedScalar sqrt(const dimensionedScalar &ds)
ListType reorder(const label size, const typename ListType::value_type &defaultValue, const labelUList &oldToNew, const ListType &lst)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
dimensioned< scalar > mag(const dimensioned< Type > &)
defineTypeNameAndDebug(combustionModel, 0)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
static const label labelMax
Definition: label.H:62
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
List< face > faceList
Definition: faceListFwd.H:41
static const char nl
Definition: Ostream.H:266
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Type gMax(const FieldField< Field, Type > &f)
static const label labelMin
Definition: label.H:61
label newPointi
Definition: readKivaGrid.H:495
labelList f(nPoints)
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, &mergedCyclicPolyPatch::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:229
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112