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-2026 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_.boundary().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_.boundary().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_.boundary()[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 :
1792  <
1793  polyMesh,
1795  hexRef8
1796  >(mesh),
1797  mesh_(mesh),
1798  cellLevel_
1799  (
1800  IOobject
1801  (
1802  "cellLevel",
1803  mesh_.facesInstance(),
1804  polyMesh::meshSubDir,
1805  mesh_,
1806  IOobject::READ_IF_PRESENT,
1807  IOobject::NO_WRITE
1808  ),
1809  labelList(mesh_.nCells(), 0)
1810  ),
1811  pointLevel_
1812  (
1813  IOobject
1814  (
1815  "pointLevel",
1816  mesh_.facesInstance(),
1817  polyMesh::meshSubDir,
1818  mesh_,
1819  IOobject::READ_IF_PRESENT,
1820  IOobject::NO_WRITE
1821  ),
1822  labelList(mesh_.nPoints(), 0)
1823  ),
1824  level0Edge_
1825  (
1826  IOobject
1827  (
1828  "level0Edge",
1829  mesh_.facesInstance(),
1830  polyMesh::meshSubDir,
1831  mesh_,
1832  IOobject::READ_IF_PRESENT,
1833  IOobject::NO_WRITE
1834  ),
1835  dimensionedScalar(dimLength, getLevel0EdgeLength())
1836  ),
1837  history_
1838  (
1839  IOobject
1840  (
1841  "refinementHistory",
1842  mesh_.facesInstance(),
1843  polyMesh::meshSubDir,
1844  mesh_,
1845  IOobject::NO_READ,
1846  IOobject::NO_WRITE
1847  ),
1848  // All cells visible if not read or readHistory = false
1849  (readHistory ? mesh_.nCells() : 0)
1850  ),
1851  faceRemover_(mesh_, great) // merge boundary faces wherever possible
1852 {
1853  if (readHistory)
1854  {
1855  // Make sure we don't use the master-only reading. Bit of a hack for
1856  // now.
1857  regIOobject::fileCheckTypes oldType =
1860  history_.readOpt() = IOobject::READ_IF_PRESENT;
1861  if (history_.headerOk())
1862  {
1863  history_.read();
1864  }
1866  }
1867 
1868  if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
1869  {
1871  << "History enabled but number of visible cells "
1872  << history_.visibleCells().size() << " in "
1873  << history_.objectPath()
1874  << " is not equal to the number of cells in the mesh "
1875  << mesh_.nCells()
1876  << abort(FatalError);
1877  }
1878 
1879  if
1880  (
1881  cellLevel_.size() != mesh_.nCells()
1882  || pointLevel_.size() != mesh_.nPoints()
1883  )
1884  {
1886  << "Restarted from inconsistent cellLevel or pointLevel files."
1887  << endl
1888  << "cellLevel file " << cellLevel_.objectPath() << endl
1889  << "pointLevel file " << pointLevel_.objectPath() << endl
1890  << "Number of cells in mesh:" << mesh_.nCells()
1891  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
1892  << "Number of points in mesh:" << mesh_.nPoints()
1893  << " does not equal size of pointLevel:" << pointLevel_.size()
1894  << abort(FatalError);
1895  }
1896 
1897 
1898  // Check refinement levels for consistency
1900 
1901 
1902  // Check initial mesh for consistency
1903 
1904  // if (debug)
1905  {
1906  checkMesh();
1907  }
1908 
1910 }
1911 
1912 
1914 (
1915  const polyMesh& mesh,
1916  const labelList& cellLevel,
1917  const labelList& pointLevel,
1918  const refinementHistory& history,
1919  const scalar level0Edge
1920 )
1921 :
1923  <
1924  polyMesh,
1926  hexRef8
1927  >(mesh),
1928  mesh_(mesh),
1929  cellLevel_
1930  (
1931  IOobject
1932  (
1933  "cellLevel",
1934  mesh_.facesInstance(),
1935  polyMesh::meshSubDir,
1936  mesh_,
1937  IOobject::NO_READ,
1938  IOobject::NO_WRITE
1939  ),
1940  cellLevel
1941  ),
1942  pointLevel_
1943  (
1944  IOobject
1945  (
1946  "pointLevel",
1947  mesh_.facesInstance(),
1948  polyMesh::meshSubDir,
1949  mesh_,
1950  IOobject::NO_READ,
1951  IOobject::NO_WRITE
1952  ),
1953  pointLevel
1954  ),
1955  level0Edge_
1956  (
1957  IOobject
1958  (
1959  "level0Edge",
1960  mesh_.facesInstance(),
1961  polyMesh::meshSubDir,
1962  mesh_,
1963  IOobject::NO_READ,
1964  IOobject::NO_WRITE
1965  ),
1967  (
1968  dimLength,
1969  (level0Edge >= 0 ? level0Edge : getLevel0EdgeLength())
1970  )
1971  ),
1972  history_
1973  (
1974  IOobject
1975  (
1976  "refinementHistory",
1977  mesh_.facesInstance(),
1978  polyMesh::meshSubDir,
1979  mesh_,
1980  IOobject::NO_READ,
1981  IOobject::NO_WRITE
1982  ),
1983  history
1984  ),
1985  faceRemover_(mesh_, great) // merge boundary faces wherever possible
1986 {
1987  if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
1988  {
1990  << "History enabled but number of visible cells in it "
1991  << history_.visibleCells().size()
1992  << " is not equal to the number of cells in the mesh "
1993  << mesh_.nCells() << abort(FatalError);
1994  }
1995 
1996  if
1997  (
1998  cellLevel_.size() != mesh_.nCells()
1999  || pointLevel_.size() != mesh_.nPoints()
2000  )
2001  {
2003  << "Incorrect cellLevel or pointLevel size." << endl
2004  << "Number of cells in mesh:" << mesh_.nCells()
2005  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
2006  << "Number of points in mesh:" << mesh_.nPoints()
2007  << " does not equal size of pointLevel:" << pointLevel_.size()
2008  << abort(FatalError);
2009  }
2010 
2011  // Check refinement levels for consistency
2013 
2014 
2015  // Check initial mesh for consistency
2016 
2017  // if (debug)
2018  {
2019  checkMesh();
2020  }
2021 
2023 }
2024 
2025 
2027 (
2028  const polyMesh& mesh,
2029  const labelList& cellLevel,
2030  const labelList& pointLevel,
2031  const scalar level0Edge
2032 )
2033 :
2035  <
2036  polyMesh,
2038  hexRef8
2039  >(mesh),
2040  mesh_(mesh),
2041  cellLevel_
2042  (
2043  IOobject
2044  (
2045  "cellLevel",
2046  mesh_.facesInstance(),
2047  polyMesh::meshSubDir,
2048  mesh_,
2049  IOobject::NO_READ,
2050  IOobject::NO_WRITE
2051  ),
2052  cellLevel
2053  ),
2054  pointLevel_
2055  (
2056  IOobject
2057  (
2058  "pointLevel",
2059  mesh_.facesInstance(),
2060  polyMesh::meshSubDir,
2061  mesh_,
2062  IOobject::NO_READ,
2063  IOobject::NO_WRITE
2064  ),
2065  pointLevel
2066  ),
2067  level0Edge_
2068  (
2069  IOobject
2070  (
2071  "level0Edge",
2072  mesh_.facesInstance(),
2073  polyMesh::meshSubDir,
2074  mesh_,
2075  IOobject::NO_READ,
2076  IOobject::NO_WRITE
2077  ),
2079  (
2080  dimLength,
2081  (level0Edge >= 0 ? level0Edge : getLevel0EdgeLength())
2082  )
2083  ),
2084  history_
2085  (
2086  IOobject
2087  (
2088  "refinementHistory",
2089  mesh_.facesInstance(),
2090  polyMesh::meshSubDir,
2091  mesh_,
2092  IOobject::NO_READ,
2093  IOobject::NO_WRITE
2094  ),
2095  List<refinementHistory::splitCell8>(0),
2096  labelList(0),
2097  false
2098  ),
2099  faceRemover_(mesh_, great) // merge boundary faces wherever possible
2100 {
2101  if
2102  (
2103  cellLevel_.size() != mesh_.nCells()
2104  || pointLevel_.size() != mesh_.nPoints()
2105  )
2106  {
2108  << "Incorrect cellLevel or pointLevel size." << endl
2109  << "Number of cells in mesh:" << mesh_.nCells()
2110  << " does not equal size of cellLevel:" << cellLevel_.size() << endl
2111  << "Number of points in mesh:" << mesh_.nPoints()
2112  << " does not equal size of pointLevel:" << pointLevel_.size()
2113  << abort(FatalError);
2114  }
2115 
2116  // Check refinement levels for consistency
2118 
2119  // Check initial mesh for consistency
2120 
2121  // if (debug)
2122  {
2123  checkMesh();
2124  }
2125 }
2126 
2127 
2128 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2129 
2131 (
2132  const labelList& cellsToRefine,
2133  const bool maxSet
2134 ) const
2135 {
2136  // Loop, modifying cellsToRefine, until no more changes to due to 2:1
2137  // conflicts.
2138  // maxSet = false : deselect cells to refine
2139  // maxSet = true : select cells to refine
2140 
2141  // Go to straight boolList.
2142  PackedBoolList refineCell(mesh_.nCells());
2143  forAll(cellsToRefine, i)
2144  {
2145  refineCell.set(cellsToRefine[i]);
2146  }
2147 
2148  while (true)
2149  {
2150  label nChanged = faceConsistentRefinement(maxSet, refineCell);
2151 
2152  reduce(nChanged, sumOp<label>());
2153 
2154  if (debug)
2155  {
2156  Pout<< "hexRef8::consistentRefinement : Changed " << nChanged
2157  << " refinement levels due to 2:1 conflicts."
2158  << endl;
2159  }
2160 
2161  if (nChanged == 0)
2162  {
2163  break;
2164  }
2165  }
2166 
2167 
2168  // Convert back to labelList.
2169  label nRefined = 0;
2170 
2171  forAll(refineCell, celli)
2172  {
2173  if (refineCell.get(celli))
2174  {
2175  nRefined++;
2176  }
2177  }
2178 
2179  labelList newCellsToRefine(nRefined);
2180  nRefined = 0;
2181 
2182  forAll(refineCell, celli)
2183  {
2184  if (refineCell.get(celli))
2185  {
2186  newCellsToRefine[nRefined++] = celli;
2187  }
2188  }
2189 
2190  if (debug)
2191  {
2192  checkWantedRefinementLevels(newCellsToRefine);
2193  }
2194 
2195  return newCellsToRefine;
2196 }
2197 
2198 
2200 (
2201  const label maxFaceDiff,
2202  const labelList& cellsToRefine,
2203  const labelList& facesToCheck,
2204  const label maxPointDiff,
2205  const labelList& pointsToCheck
2206 ) const
2207 {
2208  const labelList& faceOwner = mesh_.faceOwner();
2209  const labelList& faceNeighbour = mesh_.faceNeighbour();
2210 
2211 
2212  if (maxFaceDiff <= 0)
2213  {
2215  << "Illegal maxFaceDiff " << maxFaceDiff << nl
2216  << "Value should be >= 1" << exit(FatalError);
2217  }
2218 
2219 
2220  // Bit tricky. Say we want a distance of three cells between two
2221  // consecutive refinement levels. This is done by using FaceCellWave to
2222  // transport out the new refinement level. It gets decremented by one
2223  // every cell it crosses so if we initialise it to maxFaceDiff
2224  // we will get a field everywhere that tells us whether an unselected cell
2225  // needs refining as well.
2226 
2227 
2228  // Initial information about (distance to) cellLevel on all cells
2229  List<refinementData> allCellInfo(mesh_.nCells());
2230 
2231  // Initial information about (distance to) cellLevel on all faces
2232  List<refinementData> allFaceInfo(mesh_.nFaces());
2233 
2234  forAll(allCellInfo, celli)
2235  {
2236  // maxFaceDiff since refinementData counts both
2237  // faces and cells.
2238  allCellInfo[celli] = refinementData
2239  (
2240  maxFaceDiff*(cellLevel_[celli]+1),// when cell is to be refined
2241  maxFaceDiff*cellLevel_[celli] // current level
2242  );
2243  }
2244 
2245  // Cells to be refined will have cellLevel+1
2246  forAll(cellsToRefine, i)
2247  {
2248  label celli = cellsToRefine[i];
2249 
2250  allCellInfo[celli].count() = allCellInfo[celli].refinementCount();
2251  }
2252 
2253 
2254  // Labels of seed faces
2255  DynamicList<label> seedFaces(mesh_.nFaces()/100);
2256  // refinementLevel data on seed faces
2257  DynamicList<refinementData> seedFacesInfo(mesh_.nFaces()/100);
2258 
2259  // Dummy additional info for FaceCellWave
2260  int dummyTrackData = 0;
2261 
2262 
2263  // Additional buffer layer thickness by changing initial count. Usually
2264  // this happens on boundary faces. Bit tricky. Use allFaceInfo to mark
2265  // off thus marked faces so they're skipped in the next loop.
2266  forAll(facesToCheck, i)
2267  {
2268  label facei = facesToCheck[i];
2269 
2270  if (allFaceInfo[facei].valid(dummyTrackData))
2271  {
2272  // Can only occur if face has already gone through loop below.
2274  << "Argument facesToCheck seems to have duplicate entries!"
2275  << endl
2276  << "face:" << facei << " occurs at positions "
2277  << findIndices(facesToCheck, facei)
2278  << abort(FatalError);
2279  }
2280 
2281 
2282  const refinementData& ownData = allCellInfo[faceOwner[facei]];
2283 
2284  if (mesh_.isInternalFace(facei))
2285  {
2286  // Seed face if neighbouring cell (after possible refinement)
2287  // will be refined one more than the current owner or neighbour.
2288 
2289  const refinementData& neiData = allCellInfo[faceNeighbour[facei]];
2290 
2291  label faceCount;
2292  label faceRefineCount;
2293  if (neiData.count() > ownData.count())
2294  {
2295  faceCount = neiData.count() + maxFaceDiff;
2296  faceRefineCount = faceCount + maxFaceDiff;
2297  }
2298  else
2299  {
2300  faceCount = ownData.count() + maxFaceDiff;
2301  faceRefineCount = faceCount + maxFaceDiff;
2302  }
2303 
2304  seedFaces.append(facei);
2305  seedFacesInfo.append
2306  (
2308  (
2309  faceRefineCount,
2310  faceCount
2311  )
2312  );
2313  allFaceInfo[facei] = seedFacesInfo.last();
2314  }
2315  else
2316  {
2317  label faceCount = ownData.count() + maxFaceDiff;
2318  label faceRefineCount = faceCount + maxFaceDiff;
2319 
2320  seedFaces.append(facei);
2321  seedFacesInfo.append
2322  (
2324  (
2325  faceRefineCount,
2326  faceCount
2327  )
2328  );
2329  allFaceInfo[facei] = seedFacesInfo.last();
2330  }
2331  }
2332 
2333 
2334  // Just seed with all faces in between different refinement levels for now
2335  // (alternatively only seed faces on cellsToRefine but that gives problems
2336  // if no cells to refine)
2337  forAll(faceNeighbour, facei)
2338  {
2339  // Check if face already handled in loop above
2340  if (!allFaceInfo[facei].valid(dummyTrackData))
2341  {
2342  label own = faceOwner[facei];
2343  label nei = faceNeighbour[facei];
2344 
2345  // Seed face with transported data from highest cell.
2346 
2347  if (allCellInfo[own].count() > allCellInfo[nei].count())
2348  {
2349  allFaceInfo[facei].updateFace
2350  (
2351  mesh_,
2352  facei,
2353  own,
2354  allCellInfo[own],
2356  dummyTrackData
2357  );
2358  seedFaces.append(facei);
2359  seedFacesInfo.append(allFaceInfo[facei]);
2360  }
2361  else if (allCellInfo[own].count() < allCellInfo[nei].count())
2362  {
2363  allFaceInfo[facei].updateFace
2364  (
2365  mesh_,
2366  facei,
2367  nei,
2368  allCellInfo[nei],
2370  dummyTrackData
2371  );
2372  seedFaces.append(facei);
2373  seedFacesInfo.append(allFaceInfo[facei]);
2374  }
2375  }
2376  }
2377 
2378  // Seed all boundary faces with owner value. This is to make sure that
2379  // they are visited (probably only important for coupled faces since
2380  // these need to be visited from both sides)
2381  for (label facei = mesh_.nInternalFaces(); facei < mesh_.nFaces(); facei++)
2382  {
2383  // Check if face already handled in loop above
2384  if (!allFaceInfo[facei].valid(dummyTrackData))
2385  {
2386  label own = faceOwner[facei];
2387 
2388  // Seed face with transported data from owner.
2389  refinementData faceData;
2390  faceData.updateFace
2391  (
2392  mesh_,
2393  facei,
2394  own,
2395  allCellInfo[own],
2397  dummyTrackData
2398  );
2399  seedFaces.append(facei);
2400  seedFacesInfo.append(faceData);
2401  }
2402  }
2403 
2404 
2405  // face-cell-face transport engine
2407  (
2408  mesh_,
2409  allFaceInfo,
2410  allCellInfo,
2411  dummyTrackData
2412  );
2413 
2414  while (true)
2415  {
2416  if (debug)
2417  {
2418  Pout<< "hexRef8::consistentSlowRefinement : Seeded "
2419  << seedFaces.size() << " faces between cells with different"
2420  << " refinement level." << endl;
2421  }
2422 
2423  // Set seed faces
2424  levelCalc.setFaceInfo(seedFaces.shrink(), seedFacesInfo.shrink());
2425  seedFaces.clear();
2426  seedFacesInfo.clear();
2427 
2428  // Iterate until no change. Now 2:1 face difference should be satisfied
2429  levelCalc.iterate(mesh_.globalData().nTotalFaces()+1);
2430 
2431 
2432  // Now check point-connected cells (face-connected cells already ok):
2433  // - get per point max of connected cells
2434  // - sync across coupled points
2435  // - check cells against above point max
2436 
2437  if (maxPointDiff == -1)
2438  {
2439  // No need to do any point checking.
2440  break;
2441  }
2442 
2443  // Determine per point the max cell level. (done as count, not
2444  // as cell level purely for ease)
2445  labelList maxPointCount(mesh_.nPoints(), 0);
2446 
2447  forAll(maxPointCount, pointi)
2448  {
2449  label& pLevel = maxPointCount[pointi];
2450 
2451  const labelList& pCells = mesh_.pointCells(pointi);
2452 
2453  forAll(pCells, i)
2454  {
2455  pLevel = max(pLevel, allCellInfo[pCells[i]].count());
2456  }
2457  }
2458 
2459  // Sync maxPointCount to neighbour
2461  (
2462  mesh_,
2463  maxPointCount,
2464  maxEqOp<label>(),
2465  labelMin // null value
2466  );
2467 
2468  // Update allFaceInfo from maxPointCount for all points to check
2469  // (usually on boundary faces)
2470 
2471  // Per face the new refinement data
2472  Map<refinementData> changedFacesInfo(pointsToCheck.size());
2473 
2474  forAll(pointsToCheck, i)
2475  {
2476  label pointi = pointsToCheck[i];
2477 
2478  // Loop over all cells using the point and check whether their
2479  // refinement level is much less than the maximum.
2480 
2481  const labelList& pCells = mesh_.pointCells(pointi);
2482 
2483  forAll(pCells, pCelli)
2484  {
2485  label celli = pCells[pCelli];
2486 
2487  refinementData& cellInfo = allCellInfo[celli];
2488 
2489  if
2490  (
2491  !cellInfo.isRefined()
2492  && (
2493  maxPointCount[pointi]
2494  > cellInfo.count() + maxFaceDiff*maxPointDiff
2495  )
2496  )
2497  {
2498  // Mark cell for refinement
2499  cellInfo.count() = cellInfo.refinementCount();
2500 
2501  // Insert faces of cell as seed faces.
2502  const cell& cFaces = mesh_.cells()[celli];
2503 
2504  forAll(cFaces, cFacei)
2505  {
2506  label facei = cFaces[cFacei];
2507 
2508  refinementData faceData;
2509  faceData.updateFace
2510  (
2511  mesh_,
2512  facei,
2513  celli,
2514  cellInfo,
2516  dummyTrackData
2517  );
2518 
2519  if (faceData.count() > allFaceInfo[facei].count())
2520  {
2521  changedFacesInfo.insert(facei, faceData);
2522  }
2523  }
2524  }
2525  }
2526  }
2527 
2528  label nChanged = changedFacesInfo.size();
2529  reduce(nChanged, sumOp<label>());
2530 
2531  if (nChanged == 0)
2532  {
2533  break;
2534  }
2535 
2536 
2537  // Transfer into seedFaces, seedFacesInfo
2538  seedFaces.setCapacity(changedFacesInfo.size());
2539  seedFacesInfo.setCapacity(changedFacesInfo.size());
2540 
2541  forAllConstIter(Map<refinementData>, changedFacesInfo, iter)
2542  {
2543  seedFaces.append(iter.key());
2544  seedFacesInfo.append(iter());
2545  }
2546  }
2547 
2548 
2549  if (debug)
2550  {
2551  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
2552  {
2553  label own = mesh_.faceOwner()[facei];
2554  label ownLevel =
2555  cellLevel_[own]
2556  + (allCellInfo[own].isRefined() ? 1 : 0);
2557 
2558  label nei = mesh_.faceNeighbour()[facei];
2559  label neiLevel =
2560  cellLevel_[nei]
2561  + (allCellInfo[nei].isRefined() ? 1 : 0);
2562 
2563  if (mag(ownLevel-neiLevel) > 1)
2564  {
2565  dumpCell(own);
2566  dumpCell(nei);
2568  << "cell:" << own
2569  << " current level:" << cellLevel_[own]
2570  << " current refData:" << allCellInfo[own]
2571  << " level after refinement:" << ownLevel
2572  << nl
2573  << "neighbour cell:" << nei
2574  << " current level:" << cellLevel_[nei]
2575  << " current refData:" << allCellInfo[nei]
2576  << " level after refinement:" << neiLevel
2577  << nl
2578  << "which does not satisfy 2:1 constraints anymore." << nl
2579  << "face:" << facei << " faceRefData:" << allFaceInfo[facei]
2580  << abort(FatalError);
2581  }
2582  }
2583 
2584 
2585  // Coupled faces. Swap owner level to get neighbouring cell level.
2586  // (only boundary faces of neiLevel used)
2587 
2588  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
2589  labelList neiCount(mesh_.nFaces()-mesh_.nInternalFaces());
2590  labelList neiRefCount(mesh_.nFaces()-mesh_.nInternalFaces());
2591 
2592  forAll(neiLevel, i)
2593  {
2594  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
2595  neiLevel[i] = cellLevel_[own];
2596  neiCount[i] = allCellInfo[own].count();
2597  neiRefCount[i] = allCellInfo[own].refinementCount();
2598  }
2599 
2600  // Swap to neighbour
2601  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
2602  syncTools::swapBoundaryFaceList(mesh_, neiCount);
2603  syncTools::swapBoundaryFaceList(mesh_, neiRefCount);
2604 
2605  // Now we have neighbour value see which cells need refinement
2606  forAll(neiLevel, i)
2607  {
2608  label facei = i+mesh_.nInternalFaces();
2609 
2610  label own = mesh_.faceOwner()[facei];
2611  label ownLevel =
2612  cellLevel_[own]
2613  + (allCellInfo[own].isRefined() ? 1 : 0);
2614 
2615  label nbrLevel =
2616  neiLevel[i]
2617  + ((neiCount[i] >= neiRefCount[i]) ? 1 : 0);
2618 
2619  if (mag(ownLevel - nbrLevel) > 1)
2620  {
2621  dumpCell(own);
2622  label patchi = mesh_.boundary().whichPatch(facei);
2623 
2625  << "Celllevel does not satisfy 2:1 constraint."
2626  << " On coupled face "
2627  << facei
2628  << " refData:" << allFaceInfo[facei]
2629  << " on patch " << patchi << " "
2630  << mesh_.boundary()[patchi].name() << nl
2631  << "owner cell " << own
2632  << " current level:" << cellLevel_[own]
2633  << " current count:" << allCellInfo[own].count()
2634  << " current refCount:"
2635  << allCellInfo[own].refinementCount()
2636  << " level after refinement:" << ownLevel
2637  << nl
2638  << "(coupled) neighbour cell"
2639  << " has current level:" << neiLevel[i]
2640  << " current count:" << neiCount[i]
2641  << " current refCount:" << neiRefCount[i]
2642  << " level after refinement:" << nbrLevel
2643  << abort(FatalError);
2644  }
2645  }
2646  }
2647 
2648  // Convert back to labelList of cells to refine.
2649 
2650  label nRefined = 0;
2651 
2652  forAll(allCellInfo, celli)
2653  {
2654  if (allCellInfo[celli].isRefined())
2655  {
2656  nRefined++;
2657  }
2658  }
2659 
2660  // Updated list of cells to refine
2661  labelList newCellsToRefine(nRefined);
2662  nRefined = 0;
2663 
2664  forAll(allCellInfo, celli)
2665  {
2666  if (allCellInfo[celli].isRefined())
2667  {
2668  newCellsToRefine[nRefined++] = celli;
2669  }
2670  }
2671 
2672  if (debug)
2673  {
2674  Pout<< "hexRef8::consistentSlowRefinement : From "
2675  << cellsToRefine.size() << " to " << newCellsToRefine.size()
2676  << " cells to refine." << endl;
2677  }
2678 
2679  return newCellsToRefine;
2680 }
2681 
2682 
2684 (
2685  const label maxFaceDiff,
2686  const labelList& cellsToRefine,
2687  const labelList& facesToCheck
2688 ) const
2689 {
2690  const labelList& faceOwner = mesh_.faceOwner();
2691  const labelList& faceNeighbour = mesh_.faceNeighbour();
2692 
2693  if (maxFaceDiff <= 0)
2694  {
2696  << "Illegal maxFaceDiff " << maxFaceDiff << nl
2697  << "Value should be >= 1" << exit(FatalError);
2698  }
2699 
2700  const scalar level0Size = 2*maxFaceDiff*level0EdgeLength();
2701 
2702 
2703  // Bit tricky. Say we want a distance of three cells between two
2704  // consecutive refinement levels. This is done by using FaceCellWave to
2705  // transport out the 'refinement shell'. Anything inside the refinement
2706  // shell (given by a distance) gets marked for refinement.
2707 
2708  // Initial information about (distance to) cellLevel on all cells
2709  List<refinementDistanceData> allCellInfo(mesh_.nCells());
2710 
2711  // Initial information about (distance to) cellLevel on all faces
2712  List<refinementDistanceData> allFaceInfo(mesh_.nFaces());
2713 
2714  // Dummy additional info for FaceCellWave
2715  int dummyTrackData = 0;
2716 
2717 
2718  // Mark cells with wanted refinement level
2719  forAll(cellsToRefine, i)
2720  {
2721  label celli = cellsToRefine[i];
2722 
2723  allCellInfo[celli] = refinementDistanceData
2724  (
2725  level0Size,
2726  mesh_.cellCentres()[celli],
2727  cellLevel_[celli]+1 // wanted refinement
2728  );
2729  }
2730  // Mark all others with existing refinement level
2731  forAll(allCellInfo, celli)
2732  {
2733  if (!allCellInfo[celli].valid(dummyTrackData))
2734  {
2735  allCellInfo[celli] = refinementDistanceData
2736  (
2737  level0Size,
2738  mesh_.cellCentres()[celli],
2739  cellLevel_[celli] // wanted refinement
2740  );
2741  }
2742  }
2743 
2744 
2745  // Labels of seed faces
2746  DynamicList<label> seedFaces(mesh_.nFaces()/100);
2747  // refinementLevel data on seed faces
2748  DynamicList<refinementDistanceData> seedFacesInfo(mesh_.nFaces()/100);
2749 
2750  const pointField& cc = mesh_.cellCentres();
2751 
2752  forAll(facesToCheck, i)
2753  {
2754  label facei = facesToCheck[i];
2755 
2756  if (allFaceInfo[facei].valid(dummyTrackData))
2757  {
2758  // Can only occur if face has already gone through loop below.
2760  << "Argument facesToCheck seems to have duplicate entries!"
2761  << endl
2762  << "face:" << facei << " occurs at positions "
2763  << findIndices(facesToCheck, facei)
2764  << abort(FatalError);
2765  }
2766 
2767  label own = faceOwner[facei];
2768 
2769  label ownLevel =
2770  (
2771  allCellInfo[own].valid(dummyTrackData)
2772  ? allCellInfo[own].originLevel()
2773  : cellLevel_[own]
2774  );
2775 
2776  if (!mesh_.isInternalFace(facei))
2777  {
2778  // Do as if boundary face would have neighbour with one higher
2779  // refinement level.
2780  const point& fc = mesh_.faceCentres()[facei];
2781 
2782  refinementDistanceData neiData
2783  (
2784  level0Size,
2785  2*fc - cc[own], // est'd cell centre
2786  ownLevel+1
2787  );
2788 
2789  allFaceInfo[facei].updateFace
2790  (
2791  mesh_,
2792  facei,
2793  own, // not used (should be nei)
2794  neiData,
2796  dummyTrackData
2797  );
2798  }
2799  else
2800  {
2801  label nei = faceNeighbour[facei];
2802 
2803  label neiLevel =
2804  (
2805  allCellInfo[nei].valid(dummyTrackData)
2806  ? allCellInfo[nei].originLevel()
2807  : cellLevel_[nei]
2808  );
2809 
2810  if (ownLevel == neiLevel)
2811  {
2812  // Fake as if nei>own or own>nei (whichever one 'wins')
2813  allFaceInfo[facei].updateFace
2814  (
2815  mesh_,
2816  facei,
2817  nei,
2818  refinementDistanceData(level0Size, cc[nei], neiLevel+1),
2820  dummyTrackData
2821  );
2822  allFaceInfo[facei].updateFace
2823  (
2824  mesh_,
2825  facei,
2826  own,
2827  refinementDistanceData(level0Size, cc[own], ownLevel+1),
2829  dummyTrackData
2830  );
2831  }
2832  else
2833  {
2834  // Difference in level anyway.
2835  allFaceInfo[facei].updateFace
2836  (
2837  mesh_,
2838  facei,
2839  nei,
2840  refinementDistanceData(level0Size, cc[nei], neiLevel),
2842  dummyTrackData
2843  );
2844  allFaceInfo[facei].updateFace
2845  (
2846  mesh_,
2847  facei,
2848  own,
2849  refinementDistanceData(level0Size, cc[own], ownLevel),
2851  dummyTrackData
2852  );
2853  }
2854  }
2855  seedFaces.append(facei);
2856  seedFacesInfo.append(allFaceInfo[facei]);
2857  }
2858 
2859 
2860  // Create some initial seeds to start walking from. This is only if there
2861  // are no facesToCheck.
2862  // Just seed with all faces in between different refinement levels for now
2863  forAll(faceNeighbour, facei)
2864  {
2865  // Check if face already handled in loop above
2866  if (!allFaceInfo[facei].valid(dummyTrackData))
2867  {
2868  label own = faceOwner[facei];
2869 
2870  label ownLevel =
2871  (
2872  allCellInfo[own].valid(dummyTrackData)
2873  ? allCellInfo[own].originLevel()
2874  : cellLevel_[own]
2875  );
2876 
2877  label nei = faceNeighbour[facei];
2878 
2879  label neiLevel =
2880  (
2881  allCellInfo[nei].valid(dummyTrackData)
2882  ? allCellInfo[nei].originLevel()
2883  : cellLevel_[nei]
2884  );
2885 
2886  if (ownLevel > neiLevel)
2887  {
2888  // Set face to owner data. (since face not yet would be copy)
2889  seedFaces.append(facei);
2890  allFaceInfo[facei].updateFace
2891  (
2892  mesh_,
2893  facei,
2894  own,
2895  refinementDistanceData(level0Size, cc[own], ownLevel),
2897  dummyTrackData
2898  );
2899  seedFacesInfo.append(allFaceInfo[facei]);
2900  }
2901  else if (neiLevel > ownLevel)
2902  {
2903  seedFaces.append(facei);
2904  allFaceInfo[facei].updateFace
2905  (
2906  mesh_,
2907  facei,
2908  nei,
2909  refinementDistanceData(level0Size, cc[nei], neiLevel),
2911  dummyTrackData
2912  );
2913  seedFacesInfo.append(allFaceInfo[facei]);
2914  }
2915  }
2916  }
2917 
2918  seedFaces.shrink();
2919  seedFacesInfo.shrink();
2920 
2921  // face-cell-face transport engine
2923  (
2924  mesh_,
2925  seedFaces,
2926  seedFacesInfo,
2927  allFaceInfo,
2928  allCellInfo,
2929  mesh_.globalData().nTotalCells()+1,
2930  dummyTrackData
2931  );
2932 
2933 
2934  // if (debug)
2935  //{
2936  // // Dump wanted level
2937  // volScalarField wantedLevel
2938  // (
2939  // IOobject
2940  // (
2941  // "wantedLevel",
2942  // fMesh.time().name(),
2943  // fMesh,
2944  // IOobject::NO_READ,
2945  // IOobject::NO_WRITE,
2946  // false
2947  // ),
2948  // fMesh,
2949  // dimensionedScalar(dimless, 0)
2950  // );
2951  //
2952  // forAll(wantedLevel, celli)
2953  // {
2954  // wantedLevel[celli] = allCellInfo[celli].wantedLevel(cc[celli]);
2955  // }
2956  //
2957  // Pout<< "Writing " << wantedLevel.objectPath() << endl;
2958  // wantedLevel.write();
2959  //}
2960 
2961 
2962  // Convert back to labelList of cells to refine.
2963  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2964 
2965  // 1. Force original refinement cells to be picked up by setting the
2966  // originLevel of input cells to be a very large level (but within range
2967  // of 1<< shift inside refinementDistanceData::wantedLevel)
2968  forAll(cellsToRefine, i)
2969  {
2970  label celli = cellsToRefine[i];
2971 
2972  allCellInfo[celli].originLevel() = sizeof(label)*8-2;
2973  allCellInfo[celli].origin() = cc[celli];
2974  }
2975 
2976  // 2. Extend to 2:1. I don't understand yet why this is not done
2977  // 2. Extend to 2:1. For non-cube cells the scalar distance does not work
2978  // so make sure it at least provides 2:1.
2979  PackedBoolList refineCell(mesh_.nCells());
2980  forAll(allCellInfo, celli)
2981  {
2982  label wanted = allCellInfo[celli].wantedLevel(cc[celli]);
2983 
2984  if (wanted > cellLevel_[celli]+1)
2985  {
2986  refineCell.set(celli);
2987  }
2988  }
2989  faceConsistentRefinement(true, refineCell);
2990 
2991  while (true)
2992  {
2993  label nChanged = faceConsistentRefinement(true, refineCell);
2994 
2995  reduce(nChanged, sumOp<label>());
2996 
2997  if (debug)
2998  {
2999  Pout<< "hexRef8::consistentSlowRefinement2 : Changed " << nChanged
3000  << " refinement levels due to 2:1 conflicts."
3001  << endl;
3002  }
3003 
3004  if (nChanged == 0)
3005  {
3006  break;
3007  }
3008  }
3009 
3010  // 3. Convert back to labelList.
3011  label nRefined = 0;
3012 
3013  forAll(refineCell, celli)
3014  {
3015  if (refineCell[celli])
3016  {
3017  nRefined++;
3018  }
3019  }
3020 
3021  labelList newCellsToRefine(nRefined);
3022  nRefined = 0;
3023 
3024  forAll(refineCell, celli)
3025  {
3026  if (refineCell[celli])
3027  {
3028  newCellsToRefine[nRefined++] = celli;
3029  }
3030  }
3031 
3032  if (debug)
3033  {
3034  Pout<< "hexRef8::consistentSlowRefinement2 : From "
3035  << cellsToRefine.size() << " to " << newCellsToRefine.size()
3036  << " cells to refine." << endl;
3037 
3038  // Check that newCellsToRefine obeys at least 2:1.
3039 
3040  {
3041  cellSet cellsIn(mesh_, "cellsToRefineIn", cellsToRefine);
3042  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3043  << cellsIn.size() << " to cellSet "
3044  << cellsIn.objectPath() << endl;
3045  cellsIn.write();
3046  }
3047  {
3048  cellSet cellsOut(mesh_, "cellsToRefineOut", newCellsToRefine);
3049  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3050  << cellsOut.size() << " to cellSet "
3051  << cellsOut.objectPath() << endl;
3052  cellsOut.write();
3053  }
3054 
3055  // Extend to 2:1
3056  PackedBoolList refineCell(mesh_.nCells());
3057  forAll(newCellsToRefine, i)
3058  {
3059  refineCell.set(newCellsToRefine[i]);
3060  }
3061  const PackedBoolList savedRefineCell(refineCell);
3062 
3063  label nChanged = faceConsistentRefinement(true, refineCell);
3064 
3065  {
3066  cellSet cellsOut2
3067  (
3068  mesh_, "cellsToRefineOut2", newCellsToRefine.size()
3069  );
3070  forAll(refineCell, celli)
3071  {
3072  if (refineCell.get(celli))
3073  {
3074  cellsOut2.insert(celli);
3075  }
3076  }
3077  Pout<< "hexRef8::consistentSlowRefinement2 : writing "
3078  << cellsOut2.size() << " to cellSet "
3079  << cellsOut2.objectPath() << endl;
3080  cellsOut2.write();
3081  }
3082 
3083  if (nChanged > 0)
3084  {
3085  forAll(refineCell, celli)
3086  {
3087  if (refineCell.get(celli) && !savedRefineCell.get(celli))
3088  {
3089  dumpCell(celli);
3091  << "Cell:" << celli << " cc:"
3092  << mesh_.cellCentres()[celli]
3093  << " was not marked for refinement but does not obey"
3094  << " 2:1 constraints."
3095  << abort(FatalError);
3096  }
3097  }
3098  }
3099  }
3100 
3101  return newCellsToRefine;
3102 }
3103 
3104 
3106 (
3107  const labelList& cellLabels,
3108  polyTopoChange& meshMod
3109 )
3110 {
3111  if (debug)
3112  {
3113  Pout<< "hexRef8::setRefinement :"
3114  << " Checking initial mesh just to make sure" << endl;
3115 
3116  checkMesh();
3117  // Cannot call checkRefinementlevels since hanging points might
3118  // get triggered by the mesher after subsetting.
3119  // checkRefinementLevels(-1, labelList(0));
3120  }
3121 
3122 
3123  // New point/cell level. Copy of pointLevel for existing points.
3124  DynamicList<label> newCellLevel(cellLevel_.size());
3125  forAll(cellLevel_, celli)
3126  {
3127  newCellLevel.append(cellLevel_[celli]);
3128  }
3129  DynamicList<label> newPointLevel(pointLevel_.size());
3130  forAll(pointLevel_, pointi)
3131  {
3132  newPointLevel.append(pointLevel_[pointi]);
3133  }
3134 
3135 
3136  if (debug)
3137  {
3138  Pout<< "hexRef8::setRefinement :"
3139  << " Allocating " << cellLabels.size() << " cell midpoints."
3140  << endl;
3141  }
3142 
3143 
3144  // Mid point per refined cell.
3145  // -1 : not refined
3146  // >=0: label of mid point.
3147  labelList cellMidPoint(mesh_.nCells(), -1);
3148 
3149  forAll(cellLabels, i)
3150  {
3151  label celli = cellLabels[i];
3152 
3153  label anchorPointi = mesh_.faces()[mesh_.cells()[celli][0]][0];
3154 
3155  cellMidPoint[celli] = meshMod.addPoint
3156  (
3157  mesh_.cellCentres()[celli], // point
3158  anchorPointi, // master point
3159  true // supports a cell
3160  );
3161 
3162  newPointLevel(cellMidPoint[celli]) = cellLevel_[celli]+1;
3163  }
3164 
3165 
3166  if (debug)
3167  {
3168  cellSet splitCells(mesh_, "splitCells", cellLabels.size());
3169 
3170  forAll(cellMidPoint, celli)
3171  {
3172  if (cellMidPoint[celli] >= 0)
3173  {
3174  splitCells.insert(celli);
3175  }
3176  }
3177 
3178  Pout<< "hexRef8::setRefinement : Dumping " << splitCells.size()
3179  << " cells to split to cellSet " << splitCells.objectPath()
3180  << endl;
3181 
3182  splitCells.write();
3183  }
3184 
3185 
3186 
3187  // Split edges
3188  // ~~~~~~~~~~~
3189 
3190  if (debug)
3191  {
3192  Pout<< "hexRef8::setRefinement :"
3193  << " Allocating edge midpoints."
3194  << endl;
3195  }
3196 
3197  // Unrefined edges are ones between cellLevel or lower points.
3198  // If any cell using this edge gets split then the edge needs to be split.
3199 
3200  // -1 : no need to split edge
3201  // >=0 : label of introduced mid point
3202  labelList edgeMidPoint(mesh_.nEdges(), -1);
3203 
3204  // Note: Loop over cells to be refined or edges?
3205  forAll(cellMidPoint, celli)
3206  {
3207  if (cellMidPoint[celli] >= 0)
3208  {
3209  const labelList& cEdges = mesh_.cellEdges(celli);
3210 
3211  forAll(cEdges, i)
3212  {
3213  label edgeI = cEdges[i];
3214 
3215  const edge& e = mesh_.edges()[edgeI];
3216 
3217  if
3218  (
3219  pointLevel_[e[0]] <= cellLevel_[celli]
3220  && pointLevel_[e[1]] <= cellLevel_[celli]
3221  )
3222  {
3223  edgeMidPoint[edgeI] = 12345; // mark need for splitting
3224  }
3225  }
3226  }
3227  }
3228 
3229  // Synchronise edgeMidPoint across coupled patches. Take max so that
3230  // any split takes precedence.
3232  (
3233  mesh_,
3234  edgeMidPoint,
3235  maxEqOp<label>(),
3236  labelMin
3237  );
3238 
3239 
3240  // Introduce edge points
3241  // ~~~~~~~~~~~~~~~~~~~~~
3242 
3243  {
3244  // Phase 1: calculate midpoints and sync.
3245  // This needs doing for if people do not write binary and we slowly
3246  // get differences.
3247 
3248  pointField edgeMids(mesh_.nEdges(), point(-great, -great, -great));
3249 
3250  forAll(edgeMidPoint, edgeI)
3251  {
3252  if (edgeMidPoint[edgeI] >= 0)
3253  {
3254  // Edge marked to be split.
3255  edgeMids[edgeI] = mesh_.edges()[edgeI].centre(mesh_.points());
3256  }
3257  }
3259  (
3260  mesh_,
3261  edgeMids,
3262  maxEqOp<vector>(),
3263  point(-great, -great, -great)
3264  );
3265 
3266 
3267  // Phase 2: introduce points at the synced locations.
3268  forAll(edgeMidPoint, edgeI)
3269  {
3270  if (edgeMidPoint[edgeI] >= 0)
3271  {
3272  // Edge marked to be split. Replace edgeMidPoint with actual
3273  // point label.
3274 
3275  const edge& e = mesh_.edges()[edgeI];
3276 
3277  edgeMidPoint[edgeI] = meshMod.addPoint
3278  (
3279  edgeMids[edgeI], // point
3280  e[0], // master point
3281  true // supports a cell
3282  );
3283 
3284  newPointLevel(edgeMidPoint[edgeI]) =
3285  max
3286  (
3287  pointLevel_[e[0]],
3288  pointLevel_[e[1]]
3289  )
3290  + 1;
3291  }
3292  }
3293  }
3294 
3295  if (debug)
3296  {
3297  OFstream str(mesh_.time().path()/"edgeMidPoint.obj");
3298 
3299  forAll(edgeMidPoint, edgeI)
3300  {
3301  if (edgeMidPoint[edgeI] >= 0)
3302  {
3303  const edge& e = mesh_.edges()[edgeI];
3304 
3305  meshTools::writeOBJ(str, e.centre(mesh_.points()));
3306  }
3307  }
3308 
3309  Pout<< "hexRef8::setRefinement :"
3310  << " Dumping edge centres to split to file " << str.name() << endl;
3311  }
3312 
3313 
3314  // Calculate face level
3315  // ~~~~~~~~~~~~~~~~~~~~
3316  // (after splitting)
3317 
3318  if (debug)
3319  {
3320  Pout<< "hexRef8::setRefinement :"
3321  << " Allocating face midpoints."
3322  << endl;
3323  }
3324 
3325  // Face anchor level. There are guaranteed 4 points with level
3326  // <= anchorLevel. These are the corner points.
3327  labelList faceAnchorLevel(mesh_.nFaces());
3328 
3329  for (label facei = 0; facei < mesh_.nFaces(); facei++)
3330  {
3331  faceAnchorLevel[facei] = faceLevel(facei);
3332  }
3333 
3334  // -1 : no need to split face
3335  // >=0 : label of introduced mid point
3336  labelList faceMidPoint(mesh_.nFaces(), -1);
3337 
3338 
3339  // Internal faces: look at cells on both sides. Uniquely determined since
3340  // face itself guaranteed to be same level as most refined neighbour.
3341  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
3342  {
3343  if (faceAnchorLevel[facei] >= 0)
3344  {
3345  label own = mesh_.faceOwner()[facei];
3346  label ownLevel = cellLevel_[own];
3347  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3348 
3349  label nei = mesh_.faceNeighbour()[facei];
3350  label neiLevel = cellLevel_[nei];
3351  label newNeiLevel = neiLevel + (cellMidPoint[nei] >= 0 ? 1 : 0);
3352 
3353  if
3354  (
3355  newOwnLevel > max(ownLevel, faceAnchorLevel[facei])
3356  || newNeiLevel > max(neiLevel, faceAnchorLevel[facei])
3357  )
3358  {
3359  faceMidPoint[facei] = 12345; // mark to be split
3360  }
3361  }
3362  }
3363 
3364  // Coupled patches handled like internal faces except now all information
3365  // from neighbour comes from across processor.
3366  // Boundary faces are more complicated since the boundary face can
3367  // be more refined than its owner (or neighbour for coupled patches)
3368  // (does not happen if refining/unrefining only, but does e.g. when
3369  // refinining and subsetting)
3370 
3371  {
3372  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
3373  labelList newNeiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
3374 
3375  forAll(newNeiLevel, i)
3376  {
3377  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
3378  label ownLevel = cellLevel_[own];
3379  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3380 
3381  neiLevel[i] = ownLevel;
3382  newNeiLevel[i] = newOwnLevel;
3383  }
3384 
3385  // Swap.
3386  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
3387  syncTools::swapBoundaryFaceList(mesh_, newNeiLevel);
3388 
3389  // So now we have information on the neighbour.
3390 
3391  forAll(newNeiLevel, i)
3392  {
3393  label facei = i+mesh_.nInternalFaces();
3394 
3395  if (faceAnchorLevel[facei] >= 0)
3396  {
3397  label own = mesh_.faceOwner()[facei];
3398  label ownLevel = cellLevel_[own];
3399  label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
3400 
3401  if
3402  (
3403  newOwnLevel > max(ownLevel, faceAnchorLevel[facei])
3404  || newNeiLevel[i] > max(neiLevel[i], faceAnchorLevel[facei])
3405  )
3406  {
3407  faceMidPoint[facei] = 12345; // mark to be split
3408  }
3409  }
3410  }
3411  }
3412 
3413 
3414  // Synchronise faceMidPoint across coupled patches. (logical or)
3416  (
3417  mesh_,
3418  faceMidPoint,
3419  maxEqOp<label>()
3420  );
3421 
3422 
3423 
3424  // Introduce face points
3425  // ~~~~~~~~~~~~~~~~~~~~~
3426 
3427  {
3428  // Phase 1: determine mid points and sync. See comment for edgeMids
3429  // above
3430  pointField bFaceMids
3431  (
3432  mesh_.nFaces()-mesh_.nInternalFaces(),
3433  point(-great, -great, -great)
3434  );
3435 
3436  forAll(bFaceMids, i)
3437  {
3438  label facei = i+mesh_.nInternalFaces();
3439 
3440  if (faceMidPoint[facei] >= 0)
3441  {
3442  bFaceMids[i] = mesh_.faceCentres()[facei];
3443  }
3444  }
3446  (
3447  mesh_,
3448  bFaceMids,
3449  maxEqOp<vector>()
3450  );
3451 
3452  forAll(faceMidPoint, facei)
3453  {
3454  if (faceMidPoint[facei] >= 0)
3455  {
3456  // Face marked to be split. Replace faceMidPoint with actual
3457  // point label.
3458 
3459  const face& f = mesh_.faces()[facei];
3460 
3461  faceMidPoint[facei] = meshMod.addPoint
3462  (
3463  (
3464  facei < mesh_.nInternalFaces()
3465  ? mesh_.faceCentres()[facei]
3466  : bFaceMids[facei-mesh_.nInternalFaces()]
3467  ), // point
3468  f[0], // master point
3469  true // supports a cell
3470  );
3471 
3472  // Determine the level of the corner points and midpoint will
3473  // be one higher.
3474  newPointLevel(faceMidPoint[facei]) = faceAnchorLevel[facei]+1;
3475  }
3476  }
3477  }
3478 
3479  if (debug)
3480  {
3481  faceSet splitFaces(mesh_, "splitFaces", cellLabels.size());
3482 
3483  forAll(faceMidPoint, facei)
3484  {
3485  if (faceMidPoint[facei] >= 0)
3486  {
3487  splitFaces.insert(facei);
3488  }
3489  }
3490 
3491  Pout<< "hexRef8::setRefinement : Dumping " << splitFaces.size()
3492  << " faces to split to faceSet " << splitFaces.objectPath() << endl;
3493 
3494  splitFaces.write();
3495  }
3496 
3497 
3498  // Information complete
3499  // ~~~~~~~~~~~~~~~~~~~~
3500  // At this point we have all the information we need. We should no
3501  // longer reference the cellLabels to refine. All the information is:
3502  // - cellMidPoint >= 0 : cell needs to be split
3503  // - faceMidPoint >= 0 : face needs to be split
3504  // - edgeMidPoint >= 0 : edge needs to be split
3505 
3506 
3507 
3508  // Get the corner/anchor points
3509  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3510 
3511  if (debug)
3512  {
3513  Pout<< "hexRef8::setRefinement :"
3514  << " Finding cell anchorPoints (8 per cell)"
3515  << endl;
3516  }
3517 
3518  // There will always be 8 points on the hex that have were introduced
3519  // with the hex and will have the same or lower refinement level.
3520 
3521  // Per cell the 8 corner points.
3522  labelListList cellAnchorPoints(mesh_.nCells());
3523 
3524  {
3525  labelList nAnchorPoints(mesh_.nCells(), 0);
3526 
3527  forAll(cellMidPoint, celli)
3528  {
3529  if (cellMidPoint[celli] >= 0)
3530  {
3531  cellAnchorPoints[celli].setSize(8);
3532  }
3533  }
3534 
3535  forAll(pointLevel_, pointi)
3536  {
3537  const labelList& pCells = mesh_.pointCells(pointi);
3538 
3539  forAll(pCells, pCelli)
3540  {
3541  label celli = pCells[pCelli];
3542 
3543  if
3544  (
3545  cellMidPoint[celli] >= 0
3546  && pointLevel_[pointi] <= cellLevel_[celli]
3547  )
3548  {
3549  if (nAnchorPoints[celli] == 8)
3550  {
3551  dumpCell(celli);
3553  << "cell " << celli
3554  << " of level " << cellLevel_[celli]
3555  << " uses more than 8 points of equal or"
3556  << " lower level" << nl
3557  << "Points so far:" << cellAnchorPoints[celli]
3558  << abort(FatalError);
3559  }
3560 
3561  cellAnchorPoints[celli][nAnchorPoints[celli]++] = pointi;
3562  }
3563  }
3564  }
3565 
3566  forAll(cellMidPoint, celli)
3567  {
3568  if (cellMidPoint[celli] >= 0)
3569  {
3570  if (nAnchorPoints[celli] != 8)
3571  {
3572  dumpCell(celli);
3573 
3574  const labelList& cPoints = mesh_.cellPoints(celli);
3575 
3577  << "cell " << celli
3578  << " of level " << cellLevel_[celli]
3579  << " does not seem to have 8 points of equal or"
3580  << " lower level" << endl
3581  << "cellPoints:" << cPoints << endl
3582  << "pointLevels:"
3583  << UIndirectList<label>(pointLevel_, cPoints)() << endl
3584  << abort(FatalError);
3585  }
3586  }
3587  }
3588  }
3589 
3590 
3591  // Add the cells
3592  // ~~~~~~~~~~~~~
3593 
3594  if (debug)
3595  {
3596  Pout<< "hexRef8::setRefinement :"
3597  << " Adding cells (1 per anchorPoint)"
3598  << endl;
3599  }
3600 
3601  // Per cell the 7 added cells (+ original cell)
3602  labelListList cellAddedCells(mesh_.nCells());
3603 
3604  forAll(cellAnchorPoints, celli)
3605  {
3606  const labelList& cAnchors = cellAnchorPoints[celli];
3607 
3608  if (cAnchors.size() == 8)
3609  {
3610  labelList& cAdded = cellAddedCells[celli];
3611  cAdded.setSize(8);
3612 
3613  // Original cell at 0
3614  cAdded[0] = celli;
3615 
3616  // Update cell level
3617  newCellLevel[celli] = cellLevel_[celli]+1;
3618 
3619  for (label i = 1; i < 8; i++)
3620  {
3621  cAdded[i] = meshMod.addCell(celli);
3622  newCellLevel(cAdded[i]) = cellLevel_[celli] + 1;
3623  }
3624  }
3625  }
3626 
3627 
3628  // Faces
3629  // ~~~~~
3630  // 1. existing faces that get split (into four always)
3631  // 2. existing faces that do not get split but only edges get split
3632  // 3. existing faces that do not get split but get new owner/neighbour
3633  // 4. new internal faces inside split cells.
3634 
3635  if (debug)
3636  {
3637  Pout<< "hexRef8::setRefinement :"
3638  << " Marking faces to be handled"
3639  << endl;
3640  }
3641 
3642  // Get all affected faces.
3643  PackedBoolList affectedFace(mesh_.nFaces());
3644 
3645  {
3646  forAll(cellMidPoint, celli)
3647  {
3648  if (cellMidPoint[celli] >= 0)
3649  {
3650  const cell& cFaces = mesh_.cells()[celli];
3651 
3652  forAll(cFaces, i)
3653  {
3654  affectedFace.set(cFaces[i]);
3655  }
3656  }
3657  }
3658 
3659  forAll(faceMidPoint, facei)
3660  {
3661  if (faceMidPoint[facei] >= 0)
3662  {
3663  affectedFace.set(facei);
3664  }
3665  }
3666 
3667  forAll(edgeMidPoint, edgeI)
3668  {
3669  if (edgeMidPoint[edgeI] >= 0)
3670  {
3671  const labelList& eFaces = mesh_.edgeFaces(edgeI);
3672 
3673  forAll(eFaces, i)
3674  {
3675  affectedFace.set(eFaces[i]);
3676  }
3677  }
3678  }
3679  }
3680 
3681 
3682  // 1. Faces that get split
3683  // ~~~~~~~~~~~~~~~~~~~~~~~
3684 
3685  if (debug)
3686  {
3687  Pout<< "hexRef8::setRefinement : Splitting faces" << endl;
3688  }
3689 
3690  forAll(faceMidPoint, facei)
3691  {
3692  if (faceMidPoint[facei] >= 0 && affectedFace.get(facei))
3693  {
3694  // Face needs to be split and hasn't yet been done in some way
3695  // (affectedFace - is impossible since this is first change but
3696  // just for completeness)
3697 
3698  const face& f = mesh_.faces()[facei];
3699 
3700  // Has original facei been used (three faces added, original gets
3701  // modified)
3702  bool modifiedFace = false;
3703 
3704  label anchorLevel = faceAnchorLevel[facei];
3705 
3706  face newFace(4);
3707 
3708  forAll(f, fp)
3709  {
3710  label pointi = f[fp];
3711 
3712  if (pointLevel_[pointi] <= anchorLevel)
3713  {
3714  // point is anchor. Start collecting face.
3715 
3716  DynamicList<label> faceVerts(4);
3717 
3718  faceVerts.append(pointi);
3719 
3720  // Walk forward to mid point.
3721  // - if next is +2 midpoint is +1
3722  // - if next is +1 it is midpoint
3723  // - if next is +0 there has to be edgeMidPoint
3724 
3725  walkFaceToMid
3726  (
3727  edgeMidPoint,
3728  anchorLevel,
3729  facei,
3730  fp,
3731  faceVerts
3732  );
3733 
3734  faceVerts.append(faceMidPoint[facei]);
3735 
3736  walkFaceFromMid
3737  (
3738  edgeMidPoint,
3739  anchorLevel,
3740  facei,
3741  fp,
3742  faceVerts
3743  );
3744 
3745  // Convert dynamiclist to face.
3746  newFace.transfer(faceVerts);
3747 
3748  // Pout<< "Split face:" << facei << " verts:" << f
3749  // << " into quad:" << newFace << endl;
3750 
3751  // Get new owner/neighbour
3752  label own, nei;
3753  getFaceNeighbours
3754  (
3755  cellAnchorPoints,
3756  cellAddedCells,
3757  facei,
3758  pointi, // Anchor point
3759 
3760  own,
3761  nei
3762  );
3763 
3764 
3765  if (debug)
3766  {
3767  if (mesh_.isInternalFace(facei))
3768  {
3769  label oldOwn = mesh_.faceOwner()[facei];
3770  label oldNei = mesh_.faceNeighbour()[facei];
3771 
3772  checkInternalOrientation
3773  (
3774  meshMod,
3775  oldOwn,
3776  facei,
3777  mesh_.cellCentres()[oldOwn],
3778  mesh_.cellCentres()[oldNei],
3779  newFace
3780  );
3781  }
3782  else
3783  {
3784  label oldOwn = mesh_.faceOwner()[facei];
3785 
3786  checkBoundaryOrientation
3787  (
3788  meshMod,
3789  oldOwn,
3790  facei,
3791  mesh_.cellCentres()[oldOwn],
3792  mesh_.faceCentres()[facei],
3793  newFace
3794  );
3795  }
3796  }
3797 
3798 
3799  if (!modifiedFace)
3800  {
3801  modifiedFace = true;
3802 
3803  modifyFace(meshMod, facei, newFace, own, nei);
3804  }
3805  else
3806  {
3807  addFace(meshMod, facei, newFace, own, nei);
3808  }
3809  }
3810  }
3811 
3812  // Mark face as having been handled
3813  affectedFace.unset(facei);
3814  }
3815  }
3816 
3817 
3818  // 2. faces that do not get split but use edges that get split
3819  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3820 
3821  if (debug)
3822  {
3823  Pout<< "hexRef8::setRefinement :"
3824  << " Adding edge splits to unsplit faces"
3825  << endl;
3826  }
3827 
3828  DynamicList<label> eFacesStorage;
3829  DynamicList<label> fEdgesStorage;
3830 
3831  forAll(edgeMidPoint, edgeI)
3832  {
3833  if (edgeMidPoint[edgeI] >= 0)
3834  {
3835  // Split edge. Check that face not already handled above.
3836 
3837  const labelList& eFaces = mesh_.edgeFaces(edgeI, eFacesStorage);
3838 
3839  forAll(eFaces, i)
3840  {
3841  label facei = eFaces[i];
3842 
3843  if (faceMidPoint[facei] < 0 && affectedFace.get(facei))
3844  {
3845  // Unsplit face. Add edge splits to face.
3846 
3847  const face& f = mesh_.faces()[facei];
3848  const labelList& fEdges = mesh_.faceEdges
3849  (
3850  facei,
3851  fEdgesStorage
3852  );
3853 
3854  DynamicList<label> newFaceVerts(f.size());
3855 
3856  forAll(f, fp)
3857  {
3858  newFaceVerts.append(f[fp]);
3859 
3860  label edgeI = fEdges[fp];
3861 
3862  if (edgeMidPoint[edgeI] >= 0)
3863  {
3864  newFaceVerts.append(edgeMidPoint[edgeI]);
3865  }
3866  }
3867 
3868  face newFace;
3869  newFace.transfer(newFaceVerts);
3870 
3871  // The point with the lowest level should be an anchor
3872  // point of the neighbouring cells.
3873  label anchorFp = findMinLevel(f);
3874 
3875  label own, nei;
3876  getFaceNeighbours
3877  (
3878  cellAnchorPoints,
3879  cellAddedCells,
3880  facei,
3881  f[anchorFp], // Anchor point
3882 
3883  own,
3884  nei
3885  );
3886 
3887 
3888  if (debug)
3889  {
3890  if (mesh_.isInternalFace(facei))
3891  {
3892  label oldOwn = mesh_.faceOwner()[facei];
3893  label oldNei = mesh_.faceNeighbour()[facei];
3894 
3895  checkInternalOrientation
3896  (
3897  meshMod,
3898  oldOwn,
3899  facei,
3900  mesh_.cellCentres()[oldOwn],
3901  mesh_.cellCentres()[oldNei],
3902  newFace
3903  );
3904  }
3905  else
3906  {
3907  label oldOwn = mesh_.faceOwner()[facei];
3908 
3909  checkBoundaryOrientation
3910  (
3911  meshMod,
3912  oldOwn,
3913  facei,
3914  mesh_.cellCentres()[oldOwn],
3915  mesh_.faceCentres()[facei],
3916  newFace
3917  );
3918  }
3919  }
3920 
3921  modifyFace(meshMod, facei, newFace, own, nei);
3922 
3923  // Mark face as having been handled
3924  affectedFace.unset(facei);
3925  }
3926  }
3927  }
3928  }
3929 
3930 
3931  // 3. faces that do not get split but whose owner/neighbour change
3932  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3933 
3934  if (debug)
3935  {
3936  Pout<< "hexRef8::setRefinement :"
3937  << " Changing owner/neighbour for otherwise unaffected faces"
3938  << endl;
3939  }
3940 
3941  forAll(affectedFace, facei)
3942  {
3943  if (affectedFace.get(facei))
3944  {
3945  const face& f = mesh_.faces()[facei];
3946 
3947  // The point with the lowest level should be an anchor
3948  // point of the neighbouring cells.
3949  label anchorFp = findMinLevel(f);
3950 
3951  label own, nei;
3952  getFaceNeighbours
3953  (
3954  cellAnchorPoints,
3955  cellAddedCells,
3956  facei,
3957  f[anchorFp], // Anchor point
3958 
3959  own,
3960  nei
3961  );
3962 
3963  modifyFace(meshMod, facei, f, own, nei);
3964 
3965  // Mark face as having been handled
3966  affectedFace.unset(facei);
3967  }
3968  }
3969 
3970 
3971  // 4. new internal faces inside split cells.
3972  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3973 
3974 
3975  // This is the hard one. We have to find the splitting points between
3976  // the anchor points. But the edges between the anchor points might have
3977  // been split (into two,three or four edges).
3978 
3979  if (debug)
3980  {
3981  Pout<< "hexRef8::setRefinement :"
3982  << " Create new internal faces for split cells"
3983  << endl;
3984  }
3985 
3986  forAll(cellMidPoint, celli)
3987  {
3988  if (cellMidPoint[celli] >= 0)
3989  {
3990  createInternalFaces
3991  (
3992  cellAnchorPoints,
3993  cellAddedCells,
3994  cellMidPoint,
3995  faceMidPoint,
3996  faceAnchorLevel,
3997  edgeMidPoint,
3998  celli,
3999  meshMod
4000  );
4001  }
4002  }
4003 
4004  // Extend pointLevels and cellLevels for the new cells. Could also be done
4005  // in topoChange but saves passing cellAddedCells out of this routine.
4006 
4007  // Check
4008  if (debug)
4009  {
4010  label minPointi = labelMax;
4011  label maxPointi = labelMin;
4012 
4013  forAll(cellMidPoint, celli)
4014  {
4015  if (cellMidPoint[celli] >= 0)
4016  {
4017  minPointi = min(minPointi, cellMidPoint[celli]);
4018  maxPointi = max(maxPointi, cellMidPoint[celli]);
4019  }
4020  }
4021  forAll(faceMidPoint, facei)
4022  {
4023  if (faceMidPoint[facei] >= 0)
4024  {
4025  minPointi = min(minPointi, faceMidPoint[facei]);
4026  maxPointi = max(maxPointi, faceMidPoint[facei]);
4027  }
4028  }
4029  forAll(edgeMidPoint, edgeI)
4030  {
4031  if (edgeMidPoint[edgeI] >= 0)
4032  {
4033  minPointi = min(minPointi, edgeMidPoint[edgeI]);
4034  maxPointi = max(maxPointi, edgeMidPoint[edgeI]);
4035  }
4036  }
4037 
4038  if (minPointi != labelMax && minPointi != mesh_.nPoints())
4039  {
4041  << "Added point labels not consecutive to existing mesh points."
4042  << nl
4043  << "mesh_.nPoints():" << mesh_.nPoints()
4044  << " minPointi:" << minPointi
4045  << " maxPointi:" << maxPointi
4046  << abort(FatalError);
4047  }
4048  }
4049 
4050  pointLevel_.transfer(newPointLevel);
4051  cellLevel_.transfer(newCellLevel);
4052 
4053  // Mark files as changed
4054  setInstance(mesh_.facesInstance());
4055 
4056 
4057  // Update the live split cells tree.
4058  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4059 
4060  // New unrefinement structure
4061  if (history_.active())
4062  {
4063  if (debug)
4064  {
4065  Pout<< "hexRef8::setRefinement :"
4066  << " Updating refinement history to " << cellLevel_.size()
4067  << " cells" << endl;
4068  }
4069 
4070  // Extend refinement history for new cells
4071  history_.resize(cellLevel_.size());
4072 
4073  forAll(cellAddedCells, celli)
4074  {
4075  const labelList& addedCells = cellAddedCells[celli];
4076 
4077  if (addedCells.size())
4078  {
4079  // Cell was split.
4080  history_.storeSplit(celli, addedCells);
4081  }
4082  }
4083  }
4084 
4085  // Compact cellAddedCells.
4086 
4087  labelListList refinedCells(cellLabels.size());
4088 
4089  forAll(cellLabels, i)
4090  {
4091  label celli = cellLabels[i];
4092 
4093  refinedCells[i].transfer(cellAddedCells[celli]);
4094  }
4095 
4096  return refinedCells;
4097 }
4098 
4099 
4101 {
4102  // Update celllevel
4103  if (debug)
4104  {
4105  Pout<< "hexRef8::topoChange :"
4106  << " Updating various lists"
4107  << endl;
4108  }
4109 
4110  {
4111  const labelList& reverseCellMap = map.reverseCellMap();
4112 
4113  if (debug)
4114  {
4115  Pout<< "hexRef8::topoChange :"
4116  << " reverseCellMap:" << map.reverseCellMap().size()
4117  << " cellMap:" << map.cellMap().size()
4118  << " nCells:" << mesh_.nCells()
4119  << " nOldCells:" << map.nOldCells()
4120  << " cellLevel_:" << cellLevel_.size()
4121  << " reversePointMap:" << map.reversePointMap().size()
4122  << " pointMap:" << map.pointMap().size()
4123  << " nPoints:" << mesh_.nPoints()
4124  << " nOldPoints:" << map.nOldPoints()
4125  << " pointLevel_:" << pointLevel_.size()
4126  << endl;
4127  }
4128 
4129  if (reverseCellMap.size() == cellLevel_.size())
4130  {
4131  // Assume it is after hexRef8 that this routine is called.
4132  // Just account for reordering. We cannot use cellMap since
4133  // then cells created from cells would get cellLevel_ of
4134  // cell they were created from.
4135  reorder(reverseCellMap, mesh_.nCells(), -1, cellLevel_);
4136  }
4137  else
4138  {
4139  // Map data
4140  const labelList& cellMap = map.cellMap();
4141 
4142  labelList newCellLevel(cellMap.size());
4143  forAll(cellMap, newCelli)
4144  {
4145  label oldCelli = cellMap[newCelli];
4146 
4147  if (oldCelli == -1)
4148  {
4149  newCellLevel[newCelli] = -1;
4150  }
4151  else
4152  {
4153  newCellLevel[newCelli] = cellLevel_[oldCelli];
4154  }
4155  }
4156  cellLevel_.transfer(newCellLevel);
4157  }
4158  }
4159 
4160 
4161  // Update pointlevel
4162  {
4163  const labelList& reversePointMap = map.reversePointMap();
4164 
4165  if (reversePointMap.size() == pointLevel_.size())
4166  {
4167  // Assume it is after hexRef8 that this routine is called.
4168  reorder(reversePointMap, mesh_.nPoints(), -1, pointLevel_);
4169  }
4170  else
4171  {
4172  // Map data
4173  const labelList& pointMap = map.pointMap();
4174 
4175  labelList newPointLevel(pointMap.size());
4176 
4177  forAll(pointMap, newPointi)
4178  {
4179  label oldPointi = pointMap[newPointi];
4180 
4181  if (oldPointi == -1)
4182  {
4183  newPointLevel[newPointi] = -1;
4184  }
4185  else
4186  {
4187  newPointLevel[newPointi] = pointLevel_[oldPointi];
4188  }
4189  }
4190  pointLevel_.transfer(newPointLevel);
4191  }
4192  }
4193 
4194  // Update refinement tree
4195  if (history_.active())
4196  {
4197  history_.topoChange(map);
4198  }
4199 
4200  // Mark files as changed
4201  setInstance(mesh_.facesInstance());
4202 
4203  // Update face removal engine
4204  faceRemover_.topoChange(map);
4205 
4206  // Clear cell shapes
4207  cellShapesPtr_.clear();
4208 }
4209 
4210 
4212 (
4213  const labelList& pointMap,
4214  const labelList& faceMap,
4215  const labelList& cellMap
4216 )
4217 {
4218  // Update celllevel
4219  if (debug)
4220  {
4221  Pout<< "hexRef8::subset :"
4222  << " Updating various lists"
4223  << endl;
4224  }
4225 
4226  if (history_.active())
4227  {
4229  << "Subsetting will not work in combination with unrefinement."
4230  << nl
4231  << "Proceed at your own risk." << endl;
4232  }
4233 
4234 
4235  // Update celllevel
4236  {
4237  labelList newCellLevel(cellMap.size());
4238 
4239  forAll(cellMap, newCelli)
4240  {
4241  newCellLevel[newCelli] = cellLevel_[cellMap[newCelli]];
4242  }
4243 
4244  cellLevel_.transfer(newCellLevel);
4245 
4246  if (findIndex(cellLevel_, -1) != -1)
4247  {
4249  << "Problem : "
4250  << "cellLevel_ contains illegal value -1 after mapping:"
4251  << cellLevel_
4252  << abort(FatalError);
4253  }
4254  }
4255 
4256  // Update pointlevel
4257  {
4258  labelList newPointLevel(pointMap.size());
4259 
4260  forAll(pointMap, newPointi)
4261  {
4262  newPointLevel[newPointi] = pointLevel_[pointMap[newPointi]];
4263  }
4264 
4265  pointLevel_.transfer(newPointLevel);
4266 
4267  if (findIndex(pointLevel_, -1) != -1)
4268  {
4270  << "Problem : "
4271  << "pointLevel_ contains illegal value -1 after mapping:"
4272  << pointLevel_
4273  << abort(FatalError);
4274  }
4275  }
4276 
4277  // Update refinement tree
4278  if (history_.active())
4279  {
4280  history_.subset(pointMap, faceMap, cellMap);
4281  }
4282 
4283  // Mark files as changed
4284  setInstance(mesh_.facesInstance());
4285 
4286  // Nothing needs doing to faceRemover.
4287  // faceRemover_.subset(pointMap, faceMap, cellMap);
4288 
4289  // Clear cell shapes
4290  cellShapesPtr_.clear();
4291 }
4292 
4293 
4295 {
4296  return true;
4297 }
4298 
4299 
4301 {
4302  // meshCutter_ will need to be re-constructed from the new mesh
4303  // and protectedCells_ updated.
4304  // The constructor should be refactored for the protectedCells_ update.
4306 }
4307 
4308 
4310 {
4311  if (debug)
4312  {
4313  Pout<< "hexRef8::distribute :"
4314  << " Updating various lists"
4315  << endl;
4316  }
4317 
4318  // Update celllevel
4319  map.distributeCellData(cellLevel_);
4320 
4321  // Update pointlevel
4322  map.distributePointData(pointLevel_);
4323 
4324  // Update refinement tree
4325  if (history_.active())
4326  {
4327  history_.distribute(map);
4328  }
4329 
4330  // Update face removal engine
4331  faceRemover_.distribute(map);
4332 
4333  // Clear cell shapes
4334  cellShapesPtr_.clear();
4335 }
4336 
4337 
4339 (
4340  const labelUList& newToOld,
4341  const bool validBoundary
4342 )
4343 {}
4344 
4345 
4347 {}
4348 
4349 
4351 {
4352  // hexRef8 update must be handled explicitly
4353 }
4354 
4355 
4357 {}
4358 
4359 
4361 {
4362  const scalar smallDim = 1e-6 * mesh_.bounds().mag();
4363 
4364  if (debug)
4365  {
4366  Pout<< "hexRef8::checkMesh : Using matching tolerance smallDim:"
4367  << smallDim << endl;
4368  }
4369 
4370  // Check owner on coupled faces.
4371  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4372 
4373  // There should be only one coupled face between two cells. Why? Since
4374  // otherwise mesh redistribution might cause multiple faces between two
4375  // cells
4376  {
4377  labelList nei(mesh_.nFaces()-mesh_.nInternalFaces());
4378  forAll(nei, i)
4379  {
4380  nei[i] = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
4381  }
4382 
4383  // Replace data on coupled patches with their neighbour ones.
4384  syncTools::swapBoundaryFaceList(mesh_, nei);
4385 
4386  const polyBoundaryMesh& patches = mesh_.boundary();
4387 
4389  {
4390  const polyPatch& pp = patches[patchi];
4391 
4392  if (pp.coupled())
4393  {
4394  // Check how many faces between owner and neighbour. Should
4395  // be only one.
4397  cellToFace(2*pp.size());
4398 
4399  label facei = pp.start();
4400 
4401  forAll(pp, i)
4402  {
4403  label own = mesh_.faceOwner()[facei];
4404  label bFacei = facei-mesh_.nInternalFaces();
4405 
4406  if (!cellToFace.insert(labelPair(own, nei[bFacei]), facei))
4407  {
4408  dumpCell(own);
4410  << "Faces do not seem to be correct across coupled"
4411  << " boundaries" << endl
4412  << "Coupled face " << facei
4413  << " between owner " << own
4414  << " on patch " << pp.name()
4415  << " and coupled neighbour " << nei[bFacei]
4416  << " has two faces connected to it:"
4417  << facei << " and "
4418  << cellToFace[labelPair(own, nei[bFacei])]
4419  << abort(FatalError);
4420  }
4421 
4422  facei++;
4423  }
4424  }
4425  }
4426  }
4427 
4428  // Check face areas.
4429  // ~~~~~~~~~~~~~~~~~
4430 
4431  {
4432  scalarField neiFaceAreas(mesh_.nFaces()-mesh_.nInternalFaces());
4433  forAll(neiFaceAreas, i)
4434  {
4435  neiFaceAreas[i] = mesh_.magFaceAreas()[i+mesh_.nInternalFaces()];
4436  }
4437 
4438  // Replace data on coupled patches with their neighbour ones.
4439  syncTools::swapBoundaryFaceList(mesh_, neiFaceAreas);
4440 
4441  forAll(neiFaceAreas, i)
4442  {
4443  label facei = i+mesh_.nInternalFaces();
4444 
4445  const scalar magArea = mesh_.magFaceAreas()[facei];
4446 
4447  if (mag(magArea - neiFaceAreas[i]) > smallDim)
4448  {
4449  const face& f = mesh_.faces()[facei];
4450  label patchi = mesh_.boundary().whichPatch(facei);
4451 
4452  dumpCell(mesh_.faceOwner()[facei]);
4453 
4455  << "Faces do not seem to be correct across coupled"
4456  << " boundaries" << endl
4457  << "Coupled face " << facei
4458  << " on patch " << patchi
4459  << " " << mesh_.boundary()[patchi].name()
4460  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4461  << " has face area:" << magArea
4462  << " (coupled) neighbour face area differs:"
4463  << neiFaceAreas[i]
4464  << " to within tolerance " << smallDim
4465  << abort(FatalError);
4466  }
4467  }
4468  }
4469 
4470 
4471  // Check number of points on faces.
4472  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4473  {
4474  labelList nVerts(mesh_.nFaces()-mesh_.nInternalFaces());
4475 
4476  forAll(nVerts, i)
4477  {
4478  nVerts[i] = mesh_.faces()[i+mesh_.nInternalFaces()].size();
4479  }
4480 
4481  // Replace data on coupled patches with their neighbour ones.
4482  syncTools::swapBoundaryFaceList(mesh_, nVerts);
4483 
4484  forAll(nVerts, i)
4485  {
4486  label facei = i+mesh_.nInternalFaces();
4487 
4488  const face& f = mesh_.faces()[facei];
4489 
4490  if (f.size() != nVerts[i])
4491  {
4492  dumpCell(mesh_.faceOwner()[facei]);
4493 
4494  label patchi = mesh_.boundary().whichPatch(facei);
4495 
4497  << "Faces do not seem to be correct across coupled"
4498  << " boundaries" << endl
4499  << "Coupled face " << facei
4500  << " on patch " << patchi
4501  << " " << mesh_.boundary()[patchi].name()
4502  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4503  << " has size:" << f.size()
4504  << " (coupled) neighbour face has size:"
4505  << nVerts[i]
4506  << abort(FatalError);
4507  }
4508  }
4509  }
4510 
4511 
4512  // Check points of face
4513  // ~~~~~~~~~~~~~~~~~~~~
4514  {
4515  // Anchor points.
4516  pointField anchorPoints(mesh_.nFaces()-mesh_.nInternalFaces());
4517 
4518  forAll(anchorPoints, i)
4519  {
4520  label facei = i+mesh_.nInternalFaces();
4521  const point& fc = mesh_.faceCentres()[facei];
4522  const face& f = mesh_.faces()[facei];
4523  const vector anchorVec(mesh_.points()[f[0]] - fc);
4524 
4525  anchorPoints[i] = anchorVec;
4526  }
4527 
4528  // Replace data on coupled patches with their neighbour ones. Apply
4529  // rotation transformation (but not separation since is relative vector
4530  // to point on same face.
4531  syncTools::swapBoundaryFaceList(mesh_, anchorPoints);
4532 
4533  forAll(anchorPoints, i)
4534  {
4535  label facei = i+mesh_.nInternalFaces();
4536  const point& fc = mesh_.faceCentres()[facei];
4537  const face& f = mesh_.faces()[facei];
4538  const vector anchorVec(mesh_.points()[f[0]] - fc);
4539 
4540  if (mag(anchorVec - anchorPoints[i]) > smallDim)
4541  {
4542  dumpCell(mesh_.faceOwner()[facei]);
4543 
4544  label patchi = mesh_.boundary().whichPatch(facei);
4545 
4547  << "Faces do not seem to be correct across coupled"
4548  << " boundaries" << endl
4549  << "Coupled face " << facei
4550  << " on patch " << patchi
4551  << " " << mesh_.boundary()[patchi].name()
4552  << " coords:" << UIndirectList<point>(mesh_.points(), f)()
4553  << " has anchor vector:" << anchorVec
4554  << " (coupled) neighbour face anchor vector differs:"
4555  << anchorPoints[i]
4556  << " to within tolerance " << smallDim
4557  << abort(FatalError);
4558  }
4559  }
4560  }
4561 
4562  if (debug)
4563  {
4564  Pout<< "hexRef8::checkMesh : Returning" << endl;
4565  }
4566 }
4567 
4568 
4570 (
4571  const label maxPointDiff,
4572  const labelList& pointsToCheck
4573 ) const
4574 {
4575  if (debug)
4576  {
4577  Pout<< "hexRef8::checkRefinementLevels :"
4578  << " Checking 2:1 refinement level" << endl;
4579  }
4580 
4581  if
4582  (
4583  cellLevel_.size() != mesh_.nCells()
4584  || pointLevel_.size() != mesh_.nPoints()
4585  )
4586  {
4588  << "cellLevel size should be number of cells"
4589  << " and pointLevel size should be number of points."<< nl
4590  << "cellLevel:" << cellLevel_.size()
4591  << " mesh.nCells():" << mesh_.nCells() << nl
4592  << "pointLevel:" << pointLevel_.size()
4593  << " mesh.nPoints():" << mesh_.nPoints()
4594  << abort(FatalError);
4595  }
4596 
4597 
4598  // Check 2:1 consistency.
4599  // ~~~~~~~~~~~~~~~~~~~~~~
4600 
4601  {
4602  // Internal faces.
4603  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
4604  {
4605  label own = mesh_.faceOwner()[facei];
4606  label nei = mesh_.faceNeighbour()[facei];
4607 
4608  if (mag(cellLevel_[own] - cellLevel_[nei]) > 1)
4609  {
4610  dumpCell(own);
4611  dumpCell(nei);
4612 
4614  << "Celllevel does not satisfy 2:1 constraint." << nl
4615  << "On face " << facei << " owner cell " << own
4616  << " has refinement " << cellLevel_[own]
4617  << " neighbour cell " << nei << " has refinement "
4618  << cellLevel_[nei]
4619  << abort(FatalError);
4620  }
4621  }
4622 
4623  // Coupled faces. Get neighbouring value
4624  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
4625 
4626  forAll(neiLevel, i)
4627  {
4628  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
4629 
4630  neiLevel[i] = cellLevel_[own];
4631  }
4632 
4633  // No separation
4634  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
4635 
4636  forAll(neiLevel, i)
4637  {
4638  label facei = i+mesh_.nInternalFaces();
4639 
4640  label own = mesh_.faceOwner()[facei];
4641 
4642  if (mag(cellLevel_[own] - neiLevel[i]) > 1)
4643  {
4644  dumpCell(own);
4645 
4646  label patchi = mesh_.boundary().whichPatch(facei);
4647 
4649  << "Celllevel does not satisfy 2:1 constraint."
4650  << " On coupled face " << facei
4651  << " on patch " << patchi << " "
4652  << mesh_.boundary()[patchi].name()
4653  << " owner cell " << own << " has refinement "
4654  << cellLevel_[own]
4655  << " (coupled) neighbour cell has refinement "
4656  << neiLevel[i]
4657  << abort(FatalError);
4658  }
4659  }
4660  }
4661 
4662 
4663  // Check pointLevel is synchronised
4664  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4665  {
4666  labelList syncPointLevel(pointLevel_);
4667 
4668  // Get min level
4670  (
4671  mesh_,
4672  syncPointLevel,
4673  minEqOp<label>(),
4674  labelMax
4675  );
4676 
4677 
4678  forAll(syncPointLevel, pointi)
4679  {
4680  if (pointLevel_[pointi] != syncPointLevel[pointi])
4681  {
4683  << "PointLevel is not consistent across coupled patches."
4684  << endl
4685  << "point:" << pointi << " coord:" << mesh_.points()[pointi]
4686  << " has level " << pointLevel_[pointi]
4687  << " whereas the coupled point has level "
4688  << syncPointLevel[pointi]
4689  << abort(FatalError);
4690  }
4691  }
4692  }
4693 
4694 
4695  // Check 2:1 across points (instead of faces)
4696  if (maxPointDiff != -1)
4697  {
4698  // Determine per point the max cell level.
4699  labelList maxPointLevel(mesh_.nPoints(), 0);
4700 
4701  forAll(maxPointLevel, pointi)
4702  {
4703  const labelList& pCells = mesh_.pointCells(pointi);
4704 
4705  label& pLevel = maxPointLevel[pointi];
4706 
4707  forAll(pCells, i)
4708  {
4709  pLevel = max(pLevel, cellLevel_[pCells[i]]);
4710  }
4711  }
4712 
4713  // Sync maxPointLevel to neighbour
4715  (
4716  mesh_,
4717  maxPointLevel,
4718  maxEqOp<label>(),
4719  labelMin // null value
4720  );
4721 
4722  // Check 2:1 across boundary points
4723  forAll(pointsToCheck, i)
4724  {
4725  label pointi = pointsToCheck[i];
4726 
4727  const labelList& pCells = mesh_.pointCells(pointi);
4728 
4729  forAll(pCells, i)
4730  {
4731  label celli = pCells[i];
4732 
4733  if
4734  (
4735  mag(cellLevel_[celli]-maxPointLevel[pointi])
4736  > maxPointDiff
4737  )
4738  {
4739  dumpCell(celli);
4740 
4742  << "Too big a difference between"
4743  << " point-connected cells." << nl
4744  << "cell:" << celli
4745  << " cellLevel:" << cellLevel_[celli]
4746  << " uses point:" << pointi
4747  << " coord:" << mesh_.points()[pointi]
4748  << " which is also used by a cell with level:"
4749  << maxPointLevel[pointi]
4750  << abort(FatalError);
4751  }
4752  }
4753  }
4754  }
4755 
4756 
4757  //- Gives problems after first splitting off inside mesher.
4759  //{
4760  // // Any patches with points having only two edges.
4761  //
4762  // boolList isHangingPoint(mesh_.nPoints(), false);
4763  //
4764  // const polyBoundaryMesh& patches = mesh_.boundary();
4765  //
4766  // forAll(patches, patchi)
4767  // {
4768  // const polyPatch& pp = patches[patchi];
4769  //
4770  // const labelList& meshPoints = pp.meshPoints();
4771  //
4772  // forAll(meshPoints, i)
4773  // {
4774  // label pointi = meshPoints[i];
4775  //
4776  // const labelList& pEdges = mesh_.pointEdges()[pointi];
4777  //
4778  // if (pEdges.size() == 2)
4779  // {
4780  // isHangingPoint[pointi] = true;
4781  // }
4782  // }
4783  // }
4784  //
4785  // syncTools::syncPointList
4786  // (
4787  // mesh_,
4788  // isHangingPoint,
4789  // andEqOp<bool>(), // only if all decide it is hanging point
4790  // true, // null
4791  // false // no separation
4792  // );
4793  //
4794  // // OFstream str(mesh_.time().path()/"hangingPoints.obj");
4795  //
4796  // label nHanging = 0;
4797  //
4798  // forAll(isHangingPoint, pointi)
4799  // {
4800  // if (isHangingPoint[pointi])
4801  // {
4802  // nHanging++;
4803  //
4804  // Pout<< "Hanging boundary point " << pointi
4805  // << " at " << mesh_.points()[pointi]
4806  // << endl;
4807  // // meshTools::writeOBJ(str, mesh_.points()[pointi]);
4808  // }
4809  // }
4810  //
4811  // if (returnReduce(nHanging, sumOp<label>()) > 0)
4812  // {
4813  // FatalErrorInFunction
4814  // << "Detected a point used by two edges only (hanging point)"
4815  // << nl << "This is not allowed"
4816  // << abort(FatalError);
4817  // }
4818  //}
4819 }
4820 
4821 
4823 {
4824  if (cellShapesPtr_.empty())
4825  {
4826  if (debug)
4827  {
4828  Pout<< "hexRef8::cellShapes() : calculating splitHex cellShapes."
4829  << " cellLevel:" << cellLevel_.size()
4830  << " pointLevel:" << pointLevel_.size()
4831  << endl;
4832  }
4833 
4834  const cellShapeList& meshShapes = mesh_.cellShapes();
4835  cellShapesPtr_.reset(new cellShapeList(meshShapes));
4836 
4837  label nSplitHex = 0;
4838  label nUnrecognised = 0;
4839 
4840  forAll(cellLevel_, celli)
4841  {
4842  if (meshShapes[celli].model().index() == 0)
4843  {
4844  label level = cellLevel_[celli];
4845 
4846  // Return true if we've found 6 quads
4847  DynamicList<face> quads;
4848  bool haveQuads = matchHexShape
4849  (
4850  celli,
4851  level,
4852  quads
4853  );
4854 
4855  if (haveQuads)
4856  {
4857  faceList faces(move(quads));
4858  cellShapesPtr_()[celli] = degenerateMatcher::match(faces);
4859  nSplitHex++;
4860  }
4861  else
4862  {
4863  nUnrecognised++;
4864  }
4865  }
4866  }
4867  if (debug)
4868  {
4869  Pout<< "hexRef8::cellShapes() :"
4870  << " nCells:" << mesh_.nCells() << " of which" << nl
4871  << " primitive:" << (mesh_.nCells()-nSplitHex-nUnrecognised)
4872  << nl
4873  << " split-hex:" << nSplitHex << nl
4874  << " poly :" << nUnrecognised << nl
4875  << endl;
4876  }
4877  }
4878  return cellShapesPtr_();
4879 }
4880 
4881 
4883 {
4884  if (debug)
4885  {
4886  checkRefinementLevels(-1, labelList(0));
4887  }
4888 
4889  if (debug)
4890  {
4891  Pout<< "hexRef8::getSplitPoints :"
4892  << " Calculating unrefineable points" << endl;
4893  }
4894 
4895 
4896  if (!history_.active())
4897  {
4899  << "Only call if constructed with history capability"
4900  << abort(FatalError);
4901  }
4902 
4903  // Master cell
4904  // -1 undetermined
4905  // -2 certainly not split point
4906  // >= label of master cell
4907  labelList splitMaster(mesh_.nPoints(), -1);
4908  labelList splitMasterLevel(mesh_.nPoints(), 0);
4909 
4910  // Unmark all with not 8 cells
4911  // const labelListList& pointCells = mesh_.pointCells();
4912 
4913  for (label pointi = 0; pointi < mesh_.nPoints(); pointi++)
4914  {
4915  const labelList& pCells = mesh_.pointCells(pointi);
4916 
4917  if (pCells.size() != 8)
4918  {
4919  splitMaster[pointi] = -2;
4920  }
4921  }
4922 
4923  // Unmark all with different master cells
4924  const labelList& visibleCells = history_.visibleCells();
4925 
4926  forAll(visibleCells, celli)
4927  {
4928  const labelList& cPoints = mesh_.cellPoints(celli);
4929 
4930  if (visibleCells[celli] != -1 && history_.parentIndex(celli) >= 0)
4931  {
4932  label parentIndex = history_.parentIndex(celli);
4933 
4934  // Check same master.
4935  forAll(cPoints, i)
4936  {
4937  label pointi = cPoints[i];
4938 
4939  label masterCelli = splitMaster[pointi];
4940 
4941  if (masterCelli == -1)
4942  {
4943  // First time visit of point. Store parent cell and
4944  // level of the parent cell (with respect to celli). This
4945  // is additional guarantee that we're referring to the
4946  // same master at the same refinement level.
4947 
4948  splitMaster[pointi] = parentIndex;
4949  splitMasterLevel[pointi] = cellLevel_[celli] - 1;
4950  }
4951  else if (masterCelli == -2)
4952  {
4953  // Already decided that point is not splitPoint
4954  }
4955  else if
4956  (
4957  (masterCelli != parentIndex)
4958  || (splitMasterLevel[pointi] != cellLevel_[celli] - 1)
4959  )
4960  {
4961  // Different masters so point is on two refinement
4962  // patterns
4963  splitMaster[pointi] = -2;
4964  }
4965  }
4966  }
4967  else
4968  {
4969  // Either not visible or is unrefined cell
4970  forAll(cPoints, i)
4971  {
4972  label pointi = cPoints[i];
4973 
4974  splitMaster[pointi] = -2;
4975  }
4976  }
4977  }
4978 
4979  // Unmark boundary faces
4980  for
4981  (
4982  label facei = mesh_.nInternalFaces();
4983  facei < mesh_.nFaces();
4984  facei++
4985  )
4986  {
4987  const face& f = mesh_.faces()[facei];
4988 
4989  forAll(f, fp)
4990  {
4991  splitMaster[f[fp]] = -2;
4992  }
4993  }
4994 
4995 
4996  // Collect into labelList
4997 
4998  label nSplitPoints = 0;
4999 
5000  forAll(splitMaster, pointi)
5001  {
5002  if (splitMaster[pointi] >= 0)
5003  {
5004  nSplitPoints++;
5005  }
5006  }
5007 
5008  labelList splitPoints(nSplitPoints);
5009  nSplitPoints = 0;
5010 
5011  forAll(splitMaster, pointi)
5012  {
5013  if (splitMaster[pointi] >= 0)
5014  {
5015  splitPoints[nSplitPoints++] = pointi;
5016  }
5017  }
5018 
5019  return splitPoints;
5020 }
5021 
5022 
5024 (
5025  const labelList& pointsToUnrefine,
5026  const bool maxSet
5027 ) const
5028 {
5029  if (debug)
5030  {
5031  Pout<< "hexRef8::consistentUnrefinement :"
5032  << " Determining 2:1 consistent unrefinement" << endl;
5033  }
5034 
5035  if (maxSet)
5036  {
5038  << "maxSet not implemented yet."
5039  << abort(FatalError);
5040  }
5041 
5042  // Loop, modifying pointsToUnrefine, until no more changes to due to 2:1
5043  // conflicts.
5044  // maxSet = false : deselect points to refine
5045  // maxSet = true: select points to refine
5046 
5047  // Maintain boolList for pointsToUnrefine and cellsToUnrefine
5048  PackedBoolList unrefinePoint(mesh_.nPoints());
5049 
5050  forAll(pointsToUnrefine, i)
5051  {
5052  label pointi = pointsToUnrefine[i];
5053 
5054  unrefinePoint.set(pointi);
5055  }
5056 
5057 
5058  while (true)
5059  {
5060  // Construct cells to unrefine
5061  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5062 
5063  PackedBoolList unrefineCell(mesh_.nCells());
5064 
5065  forAll(unrefinePoint, pointi)
5066  {
5067  if (unrefinePoint.get(pointi))
5068  {
5069  const labelList& pCells = mesh_.pointCells(pointi);
5070 
5071  forAll(pCells, j)
5072  {
5073  unrefineCell.set(pCells[j]);
5074  }
5075  }
5076  }
5077 
5078 
5079  label nChanged = 0;
5080 
5081 
5082  // Check 2:1 consistency taking refinement into account
5083  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5084 
5085  // Internal faces.
5086  for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
5087  {
5088  label own = mesh_.faceOwner()[facei];
5089  label ownLevel = cellLevel_[own] - unrefineCell.get(own);
5090 
5091  label nei = mesh_.faceNeighbour()[facei];
5092  label neiLevel = cellLevel_[nei] - unrefineCell.get(nei);
5093 
5094  if (ownLevel < (neiLevel-1))
5095  {
5096  // Since was 2:1 this can only occur if own is marked for
5097  // unrefinement.
5098 
5099  if (maxSet)
5100  {
5101  unrefineCell.set(nei);
5102  }
5103  else
5104  {
5105  // could also combine with unset:
5106  // if (!unrefineCell.unset(own))
5107  // {
5108  // FatalErrorInFunction
5109  // << "problem cell already unset"
5110  // << abort(FatalError);
5111  // }
5112  if (unrefineCell.get(own) == 0)
5113  {
5115  << "problem" << abort(FatalError);
5116  }
5117 
5118  unrefineCell.unset(own);
5119  }
5120  nChanged++;
5121  }
5122  else if (neiLevel < (ownLevel-1))
5123  {
5124  if (maxSet)
5125  {
5126  unrefineCell.set(own);
5127  }
5128  else
5129  {
5130  if (unrefineCell.get(nei) == 0)
5131  {
5133  << "problem" << abort(FatalError);
5134  }
5135 
5136  unrefineCell.unset(nei);
5137  }
5138  nChanged++;
5139  }
5140  }
5141 
5142 
5143  // Coupled faces. Swap owner level to get neighbouring cell level.
5144  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
5145 
5146  forAll(neiLevel, i)
5147  {
5148  label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
5149 
5150  neiLevel[i] = cellLevel_[own] - unrefineCell.get(own);
5151  }
5152 
5153  // Swap to neighbour
5154  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
5155 
5156  forAll(neiLevel, i)
5157  {
5158  label facei = i+mesh_.nInternalFaces();
5159  label own = mesh_.faceOwner()[facei];
5160  label ownLevel = cellLevel_[own] - unrefineCell.get(own);
5161 
5162  if (ownLevel < (neiLevel[i]-1))
5163  {
5164  if (!maxSet)
5165  {
5166  if (unrefineCell.get(own) == 0)
5167  {
5169  << "problem" << abort(FatalError);
5170  }
5171 
5172  unrefineCell.unset(own);
5173  nChanged++;
5174  }
5175  }
5176  else if (neiLevel[i] < (ownLevel-1))
5177  {
5178  if (maxSet)
5179  {
5180  if (unrefineCell.get(own) == 1)
5181  {
5183  << "problem" << abort(FatalError);
5184  }
5185 
5186  unrefineCell.set(own);
5187  nChanged++;
5188  }
5189  }
5190  }
5191 
5192  reduce(nChanged, sumOp<label>());
5193 
5194  if (debug)
5195  {
5196  Pout<< "hexRef8::consistentUnrefinement :"
5197  << " Changed " << nChanged
5198  << " refinement levels due to 2:1 conflicts."
5199  << endl;
5200  }
5201 
5202  if (nChanged == 0)
5203  {
5204  break;
5205  }
5206 
5207 
5208  // Convert cellsToUnrefine back into points to unrefine
5209  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5210 
5211  // Knock out any point whose cell neighbour cannot be unrefined.
5212  forAll(unrefinePoint, pointi)
5213  {
5214  if (unrefinePoint.get(pointi))
5215  {
5216  const labelList& pCells = mesh_.pointCells(pointi);
5217 
5218  forAll(pCells, j)
5219  {
5220  if (!unrefineCell.get(pCells[j]))
5221  {
5222  unrefinePoint.unset(pointi);
5223  break;
5224  }
5225  }
5226  }
5227  }
5228  }
5229 
5230 
5231  // Convert back to labelList.
5232  label nSet = 0;
5233 
5234  forAll(unrefinePoint, pointi)
5235  {
5236  if (unrefinePoint.get(pointi))
5237  {
5238  nSet++;
5239  }
5240  }
5241 
5242  labelList newPointsToUnrefine(nSet);
5243  nSet = 0;
5244 
5245  forAll(unrefinePoint, pointi)
5246  {
5247  if (unrefinePoint.get(pointi))
5248  {
5249  newPointsToUnrefine[nSet++] = pointi;
5250  }
5251  }
5252 
5253  return newPointsToUnrefine;
5254 }
5255 
5256 
5258 (
5259  const labelList& splitPointLabels,
5260  polyTopoChange& meshMod
5261 )
5262 {
5263  if (!history_.active())
5264  {
5266  << "Only call if constructed with history capability"
5267  << abort(FatalError);
5268  }
5269 
5270  if (debug)
5271  {
5272  Pout<< "hexRef8::setUnrefinement :"
5273  << " Checking initial mesh just to make sure" << endl;
5274 
5275  checkMesh();
5276 
5277  forAll(cellLevel_, celli)
5278  {
5279  if (cellLevel_[celli] < 0)
5280  {
5282  << "Illegal cell level " << cellLevel_[celli]
5283  << " for cell " << celli
5284  << abort(FatalError);
5285  }
5286  }
5287 
5288 
5289  // Write to sets.
5290  pointSet pSet(mesh_, "splitPoints", splitPointLabels);
5291  pSet.write();
5292 
5293  cellSet cSet(mesh_, "splitPointCells", splitPointLabels.size());
5294 
5295  forAll(splitPointLabels, i)
5296  {
5297  const labelList& pCells = mesh_.pointCells(splitPointLabels[i]);
5298 
5299  forAll(pCells, j)
5300  {
5301  cSet.insert(pCells[j]);
5302  }
5303  }
5304  cSet.write();
5305 
5306  Pout<< "hexRef8::setRefinement : Dumping " << pSet.size()
5307  << " points and "
5308  << cSet.size() << " cells for unrefinement to" << nl
5309  << " pointSet " << pSet.objectPath() << nl
5310  << " cellSet " << cSet.objectPath()
5311  << endl;
5312  }
5313 
5314 
5315  labelList cellRegion;
5316  labelList cellRegionMaster;
5317  labelList facesToRemove;
5318 
5319  {
5320  labelHashSet splitFaces(12*splitPointLabels.size());
5321 
5322  forAll(splitPointLabels, i)
5323  {
5324  const labelList& pFaces = mesh_.pointFaces()[splitPointLabels[i]];
5325 
5326  forAll(pFaces, j)
5327  {
5328  splitFaces.insert(pFaces[j]);
5329  }
5330  }
5331 
5332  // Check with faceRemover what faces will get removed. Note that this
5333  // can be more (but never less) than splitFaces provided.
5334  faceRemover_.compatibleRemoves
5335  (
5336  splitFaces.toc(), // pierced faces
5337  cellRegion, // per cell -1 or region it is merged into
5338  cellRegionMaster, // per region the master cell
5339  facesToRemove // new faces to be removed.
5340  );
5341 
5342  if (facesToRemove.size() != splitFaces.size())
5343  {
5345  << "Initial set of split points to unrefine does not"
5346  << " seem to be consistent or not mid points of refined cells"
5347  << abort(FatalError);
5348  }
5349  }
5350 
5351  // Redo the region master so it is consistent with our master.
5352  // This will guarantee that the new cell (for which faceRemover uses
5353  // the region master) is already compatible with our refinement structure.
5354 
5355  forAll(splitPointLabels, i)
5356  {
5357  label pointi = splitPointLabels[i];
5358 
5359  // Get original cell label
5360 
5361  const labelList& pCells = mesh_.pointCells(pointi);
5362 
5363  // Check
5364  if (pCells.size() != 8)
5365  {
5367  << "splitPoint " << pointi
5368  << " should have 8 cells using it. It has " << pCells
5369  << abort(FatalError);
5370  }
5371 
5372 
5373  // Check that the lowest numbered pCells is the master of the region
5374  // (should be guaranteed by directRemoveFaces)
5375  // if (debug)
5376  {
5377  label masterCelli = min(pCells);
5378 
5379  forAll(pCells, j)
5380  {
5381  label celli = pCells[j];
5382 
5383  label region = cellRegion[celli];
5384 
5385  if (region == -1)
5386  {
5388  << "Initial set of split points to unrefine does not"
5389  << " seem to be consistent or not mid points"
5390  << " of refined cells" << nl
5391  << "cell:" << celli << " on splitPoint " << pointi
5392  << " has no region to be merged into"
5393  << abort(FatalError);
5394  }
5395 
5396  if (masterCelli != cellRegionMaster[region])
5397  {
5399  << "cell:" << celli << " on splitPoint:" << pointi
5400  << " in region " << region
5401  << " has master:" << cellRegionMaster[region]
5402  << " which is not the lowest numbered cell"
5403  << " among the pointCells:" << pCells
5404  << abort(FatalError);
5405  }
5406  }
5407  }
5408  }
5409 
5410  // Insert all commands to combine cells. Never fails so don't have to
5411  // test for success.
5412  faceRemover_.setRefinement
5413  (
5414  facesToRemove,
5415  cellRegion,
5416  cellRegionMaster,
5417  meshMod
5418  );
5419 
5420  // Remove the 8 cells that originated from merging around the split point
5421  // and adapt cell levels (not that pointLevels stay the same since points
5422  // either get removed or stay at the same position.
5423  forAll(splitPointLabels, i)
5424  {
5425  label pointi = splitPointLabels[i];
5426 
5427  const labelList& pCells = mesh_.pointCells(pointi);
5428 
5429  label masterCelli = min(pCells);
5430 
5431  forAll(pCells, j)
5432  {
5433  cellLevel_[pCells[j]]--;
5434  }
5435 
5436  history_.combineCells(masterCelli, pCells);
5437  }
5438 
5439  // Mark files as changed
5440  setInstance(mesh_.facesInstance());
5441 
5442  // history_.topoChange will take care of truncating.
5443 }
5444 
5445 
5447 (
5451  const bool write
5452 ) const
5453 {
5454  if (cellLevel_.size() != mesh_.nCells())
5455  {
5457  << "Size of cellLevel:" << cellLevel_.size()
5458  << " does not equal number of cells in mesh:" << mesh_.nCells()
5459  << abort(FatalError);
5460  }
5461 
5462  if (pointLevel_.size() != mesh_.nPoints())
5463  {
5465  << "Size of pointLevel:" << pointLevel_.size()
5466  << " does not equal number of points in mesh:" << mesh_.nPoints()
5467  << abort(FatalError);
5468  }
5469 
5470  bool writeOk =
5471  cellLevel_.writeObject(fmt, ver, cmp, write)
5472  && pointLevel_.writeObject(fmt, ver, cmp, write)
5473  && level0Edge_.writeObject(fmt, ver, cmp, write);
5474 
5475  if (history_.active())
5476  {
5477  writeOk = writeOk && history_.writeObject(fmt, ver, cmp, write);
5478  }
5479 
5480  return writeOk;
5481 }
5482 
5483 
5484 // ************************************************************************* //
scalar y
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
Templated abstract base-class for demand-driven mesh objects used to automate their allocation to the...
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
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
writeOption & writeOpt() const
Definition: IOobject.H:367
readOption readOpt() const
Definition: IOobject.H:357
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:223
fileCheckTypes
Enumeration defining the file checking options.
Definition: IOobject.H:133
Version number type.
Definition: IOstream.H:97
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:87
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:194
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 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:87
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:121
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:938
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:61
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:73
void checkRefinementLevels(const label maxPointDiff, const labelList &pointsToCheck) const
Debug: Check 2:1 consistency across faces.
Definition: hexRef8.C:4570
virtual bool movePoints()
Correct weighting factors for moving mesh.
Definition: hexRef8.C:4294
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:2200
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:4360
virtual bool writeObject(IOstream::streamFormat, IOstream::versionNumber, IOstream::compressionType, const bool write=true) const
Write using given format, version and compression.
Definition: hexRef8.C:5447
labelListList setRefinement(const labelList &cells, polyTopoChange &)
Insert refinement. All selected cells will be split into 8.
Definition: hexRef8.C:3106
virtual void topoChange(const polyTopoChangeMap &)
Update local numbering for changed mesh.
Definition: hexRef8.C:4100
virtual void distribute(const polyDistributionMap &)
Update local numbering for mesh redistribution.
Definition: hexRef8.C:4309
const cellShapeList & cellShapes() const
Utility: get hexes as cell shapes.
Definition: hexRef8.C:4822
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
Definition: hexRef8.C:4300
void setUnrefinement(const labelList &splitPointLabels, polyTopoChange &)
Remove some refinement. Needs to be supplied output of.
Definition: hexRef8.C:5258
virtual void addPatch(const label patchi)
Inserted patch at patchi.
Definition: hexRef8.C:4346
labelList consistentUnrefinement(const labelList &pointsToUnrefine, const bool maxSet) const
Given proposed.
Definition: hexRef8.C:5024
labelList getSplitPoints() const
Return the points at the centre of top-level split cells.
Definition: hexRef8.C:4882
label faceLevel(const label facei) const
Gets level such that the face has four points <= level.
Definition: hexRef8.C:675
virtual void clear()
Clear.
Definition: hexRef8.C:4356
virtual void reset()
Reset.
Definition: hexRef8.C:4350
virtual void reorderPatches(const labelUList &newToOld, const bool validBoundary)
Reordered/removed trailing patches.
Definition: hexRef8.C:4339
labelList consistentRefinement(const labelList &cellsToRefine, const bool maxSet) const
Given valid mesh and current cell level and proposed.
Definition: hexRef8.C:2131
labelList consistentSlowRefinement2(const label maxFaceDiff, const labelList &cellsToRefine, const labelList &facesToCheck) const
Like consistentSlowRefinement but uses different meshWave.
Definition: hexRef8.C:2684
void subset(const labelList &pointMap, const labelList &faceMap, const labelList &cellMap)
Update local numbering for subsetted mesh.
Definition: hexRef8.C:4212
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.
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:71
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:296
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:277
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:155
virtual bool write(const bool write=true) const
Write using setting from DB.
bool headerOk()
Read and check header info.
Definition: regIOobject.C:429
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
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:381
#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(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:141
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 fvMesh & region(const dictionary &dict)
Cast the give dictionary to the corresponding region fvMesh.
Definition: fvMesh.C:1831
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
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
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)
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< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Type gMax(const UList< Type > &f, const label comm)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
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
void sqrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
tmp< DimensionedField< scalar, GeoMesh, Field > > magSqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
List< face > faceList
Definition: faceListFwd.H:41
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
static const char nl
Definition: Ostream.H:297
static const label labelMin
Definition: label.H:61
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
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