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