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