FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

hexRef8.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "hexRef8.H"
00027 
00028 #include <OpenFOAM/polyMesh.H>
00029 #include "polyTopoChange.H"
00030 #include <meshTools/meshTools.H>
00031 #include <dynamicMesh/polyAddFace.H>
00032 #include <dynamicMesh/polyAddPoint.H>
00033 #include <dynamicMesh/polyAddCell.H>
00034 #include <dynamicMesh/polyModifyFace.H>
00035 #include <OpenFOAM/syncTools.H>
00036 #include <meshTools/faceSet.H>
00037 #include <meshTools/cellSet.H>
00038 #include <meshTools/pointSet.H>
00039 #include <OpenFOAM/OFstream.H>
00040 #include <OpenFOAM/Time.H>
00041 #include <OpenFOAM/FaceCellWave.H>
00042 #include <OpenFOAM/mapDistributePolyMesh.H>
00043 #include "refinementData.H"
00044 #include "refinementDistanceData.H"
00045 
00046 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00047 
00048 namespace Foam
00049 {
00050     defineTypeNameAndDebug(hexRef8, 0);
00051 
00052     //- Reduction class. If x and y are not equal assign value.
00053     template<int value>
00054     class ifEqEqOp
00055     {
00056         public:
00057         void operator()(label& x, const label& y) const
00058         {
00059             x = (x==y) ? x : value;
00060         }
00061     };
00062 }
00063 
00064 
00065 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00066 
00067 void Foam::hexRef8::reorder
00068 (
00069     const labelList& map,
00070     const label len,
00071     const label null,
00072     labelList& elems
00073 )
00074 {
00075     labelList newElems(len, null);
00076 
00077     forAll(elems, i)
00078     {
00079         label newI = map[i];
00080 
00081         if (newI >= len)
00082         {
00083             FatalErrorIn("hexRef8::reorder(..)") << abort(FatalError);
00084         }
00085 
00086         if (newI >= 0)
00087         {
00088             newElems[newI] = elems[i];
00089         }
00090     }
00091 
00092     elems.transfer(newElems);
00093 }
00094 
00095 
00096 void Foam::hexRef8::getFaceInfo
00097 (
00098     const label faceI,
00099     label& patchID,
00100     label& zoneID,
00101     label& zoneFlip
00102 ) const
00103 {
00104     patchID = -1;
00105 
00106     if (!mesh_.isInternalFace(faceI))
00107     {
00108         patchID = mesh_.boundaryMesh().whichPatch(faceI);
00109     }
00110 
00111     zoneID = mesh_.faceZones().whichZone(faceI);
00112 
00113     zoneFlip = false;
00114 
00115     if (zoneID >= 0)
00116     {
00117         const faceZone& fZone = mesh_.faceZones()[zoneID];
00118 
00119         zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00120     }
00121 }
00122 
00123 
00124 // Adds a face on top of existing faceI.
00125 Foam::label Foam::hexRef8::addFace
00126 (
00127     polyTopoChange& meshMod,
00128     const label faceI,
00129     const face& newFace,
00130     const label own,
00131     const label nei
00132 ) const
00133 {
00134     label patchID, zoneID, zoneFlip;
00135 
00136     getFaceInfo(faceI, patchID, zoneID, zoneFlip);
00137 
00138     label newFaceI = -1;
00139 
00140     if ((nei == -1) || (own < nei))
00141     {
00142         // Ordering ok.
00143         newFaceI = meshMod.setAction
00144         (
00145             polyAddFace
00146             (
00147                 newFace,                    // face
00148                 own,                        // owner
00149                 nei,                        // neighbour
00150                 -1,                         // master point
00151                 -1,                         // master edge
00152                 faceI,                      // master face for addition
00153                 false,                      // flux flip
00154                 patchID,                    // patch for face
00155                 zoneID,                     // zone for face
00156                 zoneFlip                    // face zone flip
00157             )
00158         );
00159     }
00160     else
00161     {
00162         // Reverse owner/neighbour
00163         newFaceI = meshMod.setAction
00164         (
00165             polyAddFace
00166             (
00167                 newFace.reverseFace(),      // face
00168                 nei,                        // owner
00169                 own,                        // neighbour
00170                 -1,                         // master point
00171                 -1,                         // master edge
00172                 faceI,                      // master face for addition
00173                 false,                      // flux flip
00174                 patchID,                    // patch for face
00175                 zoneID,                     // zone for face
00176                 zoneFlip                    // face zone flip
00177             )
00178         );
00179     }
00180     return newFaceI;
00181 }
00182 
00183 
00184 // Adds an internal face from an edge. Assumes orientation correct.
00185 // Problem is that the face is between four new vertices. So what do we provide
00186 // as master? The only existing mesh item we have is the edge we have split.
00187 // Have to be careful in only using it if it has internal faces since otherwise
00188 // polyMeshMorph will complain (because it cannot generate a sensible mapping
00189 // for the face)
00190 Foam::label Foam::hexRef8::addInternalFace
00191 (
00192     polyTopoChange& meshMod,
00193     const label meshFaceI,
00194     const label meshPointI,
00195     const face& newFace,
00196     const label own,
00197     const label nei
00198 ) const
00199 {
00200     if (mesh_.isInternalFace(meshFaceI))
00201     {
00202         return meshMod.setAction
00203         (
00204             polyAddFace
00205             (
00206                 newFace,                    // face
00207                 own,                        // owner
00208                 nei,                        // neighbour
00209                 -1,                         // master point
00210                 -1,                         // master edge
00211                 meshFaceI,                  // master face for addition
00212                 false,                      // flux flip
00213                 -1,                         // patch for face
00214                 -1,                         // zone for face
00215                 false                       // face zone flip
00216             )
00217         );
00218     }
00219     else
00220     {
00221         // Two choices:
00222         // - append (i.e. create out of nothing - will not be mapped)
00223         //   problem: field does not get mapped.
00224         // - inflate from point.
00225         //   problem: does interpolative mapping which constructs full
00226         //   volPointInterpolation!
00227 
00228         // For now create out of nothing
00229 
00230         return meshMod.setAction
00231         (
00232             polyAddFace
00233             (
00234                 newFace,                    // face
00235                 own,                        // owner
00236                 nei,                        // neighbour
00237                 -1,                         // master point
00238                 -1,                         // master edge
00239                 -1,                         // master face for addition
00240                 false,                      // flux flip
00241                 -1,                         // patch for face
00242                 -1,                         // zone for face
00243                 false                       // face zone flip
00244             )
00245         );
00246 
00247 
00250         //label masterPointI = -1;
00251         //
00252         //const labelList& pFaces = mesh_.pointFaces()[meshPointI];
00253         //
00254         //forAll(pFaces, i)
00255         //{
00256         //    if (mesh_.isInternalFace(pFaces[i]))
00257         //    {
00258         //        // meshPoint uses internal faces so ok to inflate from it
00259         //        masterPointI = meshPointI;
00260         //
00261         //        break;
00262         //    }
00263         //}
00264         //
00265         //return meshMod.setAction
00266         //(
00267         //    polyAddFace
00268         //    (
00269         //        newFace,                    // face
00270         //        own,                        // owner
00271         //        nei,                        // neighbour
00272         //        masterPointI,               // master point
00273         //        -1,                         // master edge
00274         //        -1,                         // master face for addition
00275         //        false,                      // flux flip
00276         //        -1,                         // patch for face
00277         //        -1,                         // zone for face
00278         //        false                       // face zone flip
00279         //    )
00280         //);
00281     }
00282 }
00283 
00284 
00285 // Modifies existing faceI for either new owner/neighbour or new face points.
00286 void Foam::hexRef8::modFace
00287 (
00288     polyTopoChange& meshMod,
00289     const label faceI,
00290     const face& newFace,
00291     const label own,
00292     const label nei
00293 ) const
00294 {
00295     label patchID, zoneID, zoneFlip;
00296 
00297     getFaceInfo(faceI, patchID, zoneID, zoneFlip);
00298 
00299     if
00300     (
00301         (own != mesh_.faceOwner()[faceI])
00302      || (
00303             mesh_.isInternalFace(faceI)
00304          && (nei != mesh_.faceNeighbour()[faceI])
00305         )
00306      || (newFace != mesh_.faces()[faceI])
00307     )
00308     {
00309         if ((nei == -1) || (own < nei))
00310         {
00311             meshMod.setAction
00312             (
00313                 polyModifyFace
00314                 (
00315                     newFace,            // modified face
00316                     faceI,              // label of face being modified
00317                     own,                // owner
00318                     nei,                // neighbour
00319                     false,              // face flip
00320                     patchID,            // patch for face
00321                     false,              // remove from zone
00322                     zoneID,             // zone for face
00323                     zoneFlip            // face flip in zone
00324                 )
00325             );
00326         }
00327         else
00328         {
00329             meshMod.setAction
00330             (
00331                 polyModifyFace
00332                 (
00333                     newFace.reverseFace(),  // modified face
00334                     faceI,                  // label of face being modified
00335                     nei,                    // owner
00336                     own,                    // neighbour
00337                     false,                  // face flip
00338                     patchID,                // patch for face
00339                     false,                  // remove from zone
00340                     zoneID,                 // zone for face
00341                     zoneFlip                // face flip in zone
00342                 )
00343             );
00344         }
00345     }
00346 }
00347 
00348 
00349 // Bit complex way to determine the unrefined edge length.
00350 Foam::scalar Foam::hexRef8::getLevel0EdgeLength() const
00351 {
00352     if (cellLevel_.size() != mesh_.nCells())
00353     {
00354         FatalErrorIn
00355         (
00356             "hexRef8::getLevel0EdgeLength() const"
00357         )   << "Number of cells in mesh:" << mesh_.nCells()
00358             << " does not equal size of cellLevel:" << cellLevel_.size()
00359             << endl
00360             << "This might be because of a restart with inconsistent cellLevel."
00361             << abort(FatalError);
00362     }
00363 
00364     // Determine minimum edge length per refinement level
00365     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00366 
00367     const scalar GREAT2 = sqr(GREAT);
00368 
00369     label nLevels = gMax(cellLevel_)+1;
00370 
00371     scalarField typEdgeLenSqr(nLevels, GREAT2);
00372 
00373 
00374     // 1. Look only at edges surrounded by cellLevel cells only.
00375     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00376 
00377     {
00378         // Per edge the cellLevel of connected cells. -1 if not set,
00379         // labelMax if different levels, otherwise levels of connected cells.
00380         labelList edgeLevel(mesh_.nEdges(), -1);
00381 
00382         forAll(cellLevel_, cellI)
00383         {
00384             const label cLevel = cellLevel_[cellI];
00385 
00386             const labelList& cEdges = mesh_.cellEdges(cellI);
00387 
00388             forAll(cEdges, i)
00389             {
00390                 label edgeI = cEdges[i];
00391 
00392                 if (edgeLevel[edgeI] == -1)
00393                 {
00394                     edgeLevel[edgeI] = cLevel;
00395                 }
00396                 else if (edgeLevel[edgeI] == labelMax)
00397                 {
00398                     // Already marked as on different cellLevels
00399                 }
00400                 else if (edgeLevel[edgeI] != cLevel)
00401                 {
00402                     edgeLevel[edgeI] = labelMax;
00403                 }
00404             }
00405         }
00406 
00407         // Make sure that edges with different levels on different processors
00408         // are also marked. Do the same test (edgeLevel != cLevel) on coupled
00409         // edges.
00410         syncTools::syncEdgeList
00411         (
00412             mesh_,
00413             edgeLevel,
00414             ifEqEqOp<labelMax>(),
00415             labelMin,
00416             false               // no separation
00417         );
00418 
00419         // Now use the edgeLevel with a valid value to determine the
00420         // length per level.
00421         forAll(edgeLevel, edgeI)
00422         {
00423             const label eLevel = edgeLevel[edgeI];
00424 
00425             if (eLevel >= 0 && eLevel < labelMax)
00426             {
00427                 const edge& e = mesh_.edges()[edgeI];
00428 
00429                 scalar edgeLenSqr = magSqr(e.vec(mesh_.points()));
00430 
00431                 typEdgeLenSqr[eLevel] = min(typEdgeLenSqr[eLevel], edgeLenSqr);
00432             }
00433         }
00434     }
00435 
00436     // Get the minimum per level over all processors. Note minimum so if
00437     // cells are not cubic we use the smallest edge side.
00438     Pstream::listCombineGather(typEdgeLenSqr, minEqOp<scalar>());
00439     Pstream::listCombineScatter(typEdgeLenSqr);
00440 
00441     if (debug)
00442     {
00443         Pout<< "hexRef8::getLevel0EdgeLength() :"
00444             << " After phase1: Edgelengths (squared) per refinementlevel:"
00445             << typEdgeLenSqr << endl;
00446     }
00447 
00448 
00449     // 2. For any levels where we haven't determined a valid length yet
00450     //    use any surrounding cell level. Here we use the max so we don't
00451     //    pick up levels between celllevel and higher celllevel (will have
00452     //    edges sized according to highest celllevel)
00453     //    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00454 
00455     scalarField maxEdgeLenSqr(nLevels, -GREAT2);
00456 
00457     forAll(cellLevel_, cellI)
00458     {
00459         const label cLevel = cellLevel_[cellI];
00460 
00461         const labelList& cEdges = mesh_.cellEdges(cellI);
00462 
00463         forAll(cEdges, i)
00464         {
00465             const edge& e = mesh_.edges()[cEdges[i]];
00466 
00467             scalar edgeLenSqr = magSqr(e.vec(mesh_.points()));
00468 
00469             maxEdgeLenSqr[cLevel] = max(maxEdgeLenSqr[cLevel], edgeLenSqr);
00470         }
00471     }
00472 
00473     Pstream::listCombineGather(maxEdgeLenSqr, maxEqOp<scalar>());
00474     Pstream::listCombineScatter(maxEdgeLenSqr);
00475 
00476     if (debug)
00477     {
00478         Pout<< "hexRef8::getLevel0EdgeLength() :"
00479             << " Crappy Edgelengths (squared) per refinementlevel:"
00480             << maxEdgeLenSqr << endl;
00481     }
00482 
00483 
00484     // 3. Combine the two sets of lengths
00485     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00486 
00487     forAll(typEdgeLenSqr, levelI)
00488     {
00489         if (typEdgeLenSqr[levelI] == GREAT2 && maxEdgeLenSqr[levelI] >= 0)
00490         {
00491             typEdgeLenSqr[levelI] = maxEdgeLenSqr[levelI];
00492         }
00493     }
00494 
00495     if (debug)
00496     {
00497         Pout<< "hexRef8::getLevel0EdgeLength() :"
00498             << " Final Edgelengths (squared) per refinementlevel:"
00499             << typEdgeLenSqr << endl;
00500     }
00501 
00502     // Find lowest level present
00503     scalar level0Size = -1;
00504 
00505     forAll(typEdgeLenSqr, levelI)
00506     {
00507         scalar lenSqr = typEdgeLenSqr[levelI];
00508 
00509         if (lenSqr < GREAT2)
00510         {
00511             level0Size = Foam::sqrt(lenSqr)*(1<<levelI);
00512 
00513             if (debug)
00514             {
00515                 Pout<< "hexRef8::getLevel0EdgeLength() :"
00516                     << " For level:" << levelI
00517                     << " have edgeLen:" << Foam::sqrt(lenSqr)
00518                     << " with equivalent level0 len:" << level0Size
00519                     << endl;
00520             }
00521             break;
00522         }
00523     }
00524 
00525     if (level0Size == -1)
00526     {
00527         FatalErrorIn("hexRef8::getLevel0EdgeLength()")
00528             << "Problem : typEdgeLenSqr:" << typEdgeLenSqr << abort(FatalError);
00529     }
00530 
00531     return level0Size;
00532 }
00533 
00534 
00535 // Check whether pointI is an anchor on cellI.
00536 // If it is not check whether any other point on the face is an anchor cell.
00537 Foam::label Foam::hexRef8::getAnchorCell
00538 (
00539     const labelListList& cellAnchorPoints,
00540     const labelListList& cellAddedCells,
00541     const label cellI,
00542     const label faceI,
00543     const label pointI
00544 ) const
00545 {
00546     if (cellAnchorPoints[cellI].size())
00547     {
00548         label index = findIndex(cellAnchorPoints[cellI], pointI);
00549 
00550         if (index != -1)
00551         {
00552             return cellAddedCells[cellI][index];
00553         }
00554 
00555 
00556         // pointI is not an anchor cell.
00557         // Maybe we are already a refined face so check all the face
00558         // vertices.
00559         const face& f = mesh_.faces()[faceI];
00560 
00561         forAll(f, fp)
00562         {
00563             label index = findIndex(cellAnchorPoints[cellI], f[fp]);
00564 
00565             if (index != -1)
00566             {
00567                 return cellAddedCells[cellI][index];
00568             }
00569         }
00570 
00571         // Problem.
00572         dumpCell(cellI);
00573         Perr<< "cell:" << cellI << " anchorPoints:" << cellAnchorPoints[cellI]
00574             << endl;
00575 
00576         FatalErrorIn("hexRef8::getAnchorCell(..)")
00577             << "Could not find point " << pointI
00578             << " in the anchorPoints for cell " << cellI << endl
00579             << "Does your original mesh obey the 2:1 constraint and"
00580             << " did you use consistentRefinement to make your cells to refine"
00581             << " obey this constraint as well?"
00582             << abort(FatalError);
00583 
00584         return -1;
00585     }
00586     else
00587     {
00588         return cellI;
00589     }
00590 }
00591 
00592 
00593 // Get new owner and neighbour
00594 void Foam::hexRef8::getFaceNeighbours
00595 (
00596     const labelListList& cellAnchorPoints,
00597     const labelListList& cellAddedCells,
00598     const label faceI,
00599     const label pointI,
00600 
00601     label& own,
00602     label& nei
00603 ) const
00604 {
00605     // Is owner split?
00606     own = getAnchorCell
00607     (
00608         cellAnchorPoints,
00609         cellAddedCells,
00610         mesh_.faceOwner()[faceI],
00611         faceI,
00612         pointI
00613     );
00614 
00615     if (mesh_.isInternalFace(faceI))
00616     {
00617         nei = getAnchorCell
00618         (
00619             cellAnchorPoints,
00620             cellAddedCells,
00621             mesh_.faceNeighbour()[faceI],
00622             faceI,
00623             pointI
00624         );
00625     }
00626     else
00627     {
00628         nei = -1;
00629     }
00630 }
00631 
00632 
00633 // Get point with the lowest pointLevel
00634 Foam::label Foam::hexRef8::findMinLevel(const labelList& f) const
00635 {
00636     label minLevel = labelMax;
00637     label minFp = -1;
00638 
00639     forAll(f, fp)
00640     {
00641         label level = pointLevel_[f[fp]];
00642 
00643         if (level < minLevel)
00644         {
00645             minLevel = level;
00646             minFp = fp;
00647         }
00648     }
00649 
00650     return minFp;
00651 }
00652 
00653 
00654 // Get point with the highest pointLevel
00655 Foam::label Foam::hexRef8::findMaxLevel(const labelList& f) const
00656 {
00657     label maxLevel = labelMin;
00658     label maxFp = -1;
00659 
00660     forAll(f, fp)
00661     {
00662         label level = pointLevel_[f[fp]];
00663 
00664         if (level > maxLevel)
00665         {
00666             maxLevel = level;
00667             maxFp = fp;
00668         }
00669     }
00670 
00671     return maxFp;
00672 }
00673 
00674 
00675 Foam::label Foam::hexRef8::countAnchors
00676 (
00677     const labelList& f,
00678     const label anchorLevel
00679 ) const
00680 {
00681     label nAnchors = 0;
00682 
00683     forAll(f, fp)
00684     {
00685         if (pointLevel_[f[fp]] <= anchorLevel)
00686         {
00687             nAnchors++;
00688         }
00689     }
00690     return nAnchors;
00691 }
00692 
00693 
00694 void Foam::hexRef8::dumpCell(const label cellI) const
00695 {
00696     OFstream str(mesh_.time().path()/"cell_" + Foam::name(cellI) + ".obj");
00697     Pout<< "hexRef8 : Dumping cell as obj to " << str.name() << endl;
00698 
00699     const cell& cFaces = mesh_.cells()[cellI];
00700 
00701     Map<label> pointToObjVert;
00702     label objVertI = 0;
00703 
00704     forAll(cFaces, i)
00705     {
00706         const face& f = mesh_.faces()[cFaces[i]];
00707 
00708         forAll(f, fp)
00709         {
00710             if (pointToObjVert.insert(f[fp], objVertI))
00711             {
00712                 meshTools::writeOBJ(str, mesh_.points()[f[fp]]);
00713                 objVertI++;
00714             }
00715         }
00716     }
00717 
00718     forAll(cFaces, i)
00719     {
00720         const face& f = mesh_.faces()[cFaces[i]];
00721 
00722         forAll(f, fp)
00723         {
00724             label pointI = f[fp];
00725             label nexPointI = f[f.fcIndex(fp)];
00726 
00727             str << "l " << pointToObjVert[pointI]+1
00728                 << ' ' << pointToObjVert[nexPointI]+1 << nl;
00729         }
00730     }
00731 }
00732 
00733 
00734 // Find point with certain pointLevel. Skip any higher levels.
00735 Foam::label Foam::hexRef8::findLevel
00736 (
00737     const label faceI,
00738     const face& f,
00739     const label startFp,
00740     const bool searchForward,
00741     const label wantedLevel
00742 ) const
00743 {
00744     label fp = startFp;
00745 
00746     forAll(f, i)
00747     {
00748         label pointI = f[fp];
00749 
00750         if (pointLevel_[pointI] < wantedLevel)
00751         {
00752             dumpCell(mesh_.faceOwner()[faceI]);
00753             if (mesh_.isInternalFace(faceI))
00754             {
00755                 dumpCell(mesh_.faceNeighbour()[faceI]);
00756             }
00757 
00758             FatalErrorIn("hexRef8::findLevel(..)")
00759                 << "face:" << f
00760                 << " level:" << UIndirectList<label>(pointLevel_, f)()
00761                 << " startFp:" << startFp
00762                 << " wantedLevel:" << wantedLevel
00763                 << abort(FatalError);
00764         }
00765         else if (pointLevel_[pointI] == wantedLevel)
00766         {
00767             return fp;
00768         }
00769 
00770         if (searchForward)
00771         {
00772             fp = f.fcIndex(fp);
00773         }
00774         else
00775         {
00776             fp = f.rcIndex(fp);
00777         }
00778     }
00779 
00780     dumpCell(mesh_.faceOwner()[faceI]);
00781     if (mesh_.isInternalFace(faceI))
00782     {
00783         dumpCell(mesh_.faceNeighbour()[faceI]);
00784     }
00785 
00786     FatalErrorIn("hexRef8::findLevel(..)")
00787         << "face:" << f
00788         << " level:" << UIndirectList<label>(pointLevel_, f)()
00789         << " startFp:" << startFp
00790         << " wantedLevel:" << wantedLevel
00791         << abort(FatalError);
00792 
00793     return -1;
00794 }
00795 
00796 
00797 // Gets cell level such that the face has four points <= level.
00798 Foam::label Foam::hexRef8::getAnchorLevel(const label faceI) const
00799 {
00800     const face& f = mesh_.faces()[faceI];
00801 
00802     if (f.size() <= 4)
00803     {
00804         return pointLevel_[f[findMaxLevel(f)]];
00805     }
00806     else
00807     {
00808         label ownLevel = cellLevel_[mesh_.faceOwner()[faceI]];
00809 
00810         if (countAnchors(f, ownLevel) == 4)
00811         {
00812             return ownLevel;
00813         }
00814         else if (countAnchors(f, ownLevel+1) == 4)
00815         {
00816             return ownLevel+1;
00817         }
00818         else
00819         {
00820             return -1;
00821         }
00822     }
00823 }
00824 
00825 
00826 void Foam::hexRef8::checkInternalOrientation
00827 (
00828     polyTopoChange& meshMod,
00829     const label cellI,
00830     const label faceI,
00831     const point& ownPt,
00832     const point& neiPt,
00833     const face& newFace
00834 )
00835 {
00836     face compactFace(identity(newFace.size()));
00837     pointField compactPoints(meshMod.points(), newFace);
00838 
00839     vector n(compactFace.normal(compactPoints));
00840 
00841     vector dir(neiPt - ownPt);
00842 
00843     if ((dir & n) < 0)
00844     {
00845         FatalErrorIn("checkInternalOrientation(..)")
00846             << "cell:" << cellI << " old face:" << faceI
00847             << " newFace:" << newFace << endl
00848             << " coords:" << compactPoints
00849             << " ownPt:" << ownPt
00850             << " neiPt:" << neiPt
00851             << abort(FatalError);
00852     }
00853 
00854     vector fcToOwn(compactFace.centre(compactPoints) - ownPt);
00855 
00856     scalar s = (fcToOwn&n) / (dir&n);
00857 
00858     if (s < 0.1 || s > 0.9)
00859     {
00860         FatalErrorIn("checkInternalOrientation(..)")
00861             << "cell:" << cellI << " old face:" << faceI
00862             << " newFace:" << newFace << endl
00863             << " coords:" << compactPoints
00864             << " ownPt:" << ownPt
00865             << " neiPt:" << neiPt
00866             << " s:" << s
00867             << abort(FatalError);
00868     }
00869 }
00870 
00871 
00872 void Foam::hexRef8::checkBoundaryOrientation
00873 (
00874     polyTopoChange& meshMod,
00875     const label cellI,
00876     const label faceI,
00877     const point& ownPt,
00878     const point& boundaryPt,
00879     const face& newFace
00880 )
00881 {
00882     face compactFace(identity(newFace.size()));
00883     pointField compactPoints(meshMod.points(), newFace);
00884 
00885     vector n(compactFace.normal(compactPoints));
00886 
00887     vector dir(boundaryPt - ownPt);
00888 
00889     if ((dir & n) < 0)
00890     {
00891         FatalErrorIn("checkBoundaryOrientation(..)")
00892             << "cell:" << cellI << " old face:" << faceI
00893             << " newFace:" << newFace
00894             << " coords:" << compactPoints
00895             << " ownPt:" << ownPt
00896             << " boundaryPt:" << boundaryPt
00897             << abort(FatalError);
00898     }
00899 
00900     vector fcToOwn(compactFace.centre(compactPoints) - ownPt);
00901 
00902     scalar s = (fcToOwn&dir) / magSqr(dir);
00903 
00904     if (s < 0.7 || s > 1.3)
00905     {
00906         WarningIn("checkBoundaryOrientation(..)")
00907             << "cell:" << cellI << " old face:" << faceI
00908             << " newFace:" << newFace
00909             << " coords:" << compactPoints
00910             << " ownPt:" << ownPt
00911             << " boundaryPt:" << boundaryPt
00912             << " s:" << s
00913             << endl;
00914             //<< abort(FatalError);
00915     }
00916 }
00917 
00918 
00919 // If p0 and p1 are existing vertices check if edge is split and insert
00920 // splitPoint.
00921 void Foam::hexRef8::insertEdgeSplit
00922 (
00923     const labelList& edgeMidPoint,
00924     const label p0,
00925     const label p1,
00926     DynamicList<label>& verts
00927 ) const
00928 {
00929     if (p0 < mesh_.nPoints() && p1 < mesh_.nPoints())
00930     {
00931         label edgeI = meshTools::findEdge(mesh_, p0, p1);
00932 
00933         if (edgeI != -1 && edgeMidPoint[edgeI] != -1)
00934         {
00935             verts.append(edgeMidPoint[edgeI]);
00936         }
00937     }
00938 }
00939 
00940 
00941 // Internal faces are one per edge between anchor points. So one per midPoint
00942 // between the anchor points. Here we store the information on the midPoint
00943 // and if we have enough information:
00944 // - two anchors
00945 // - two face mid points
00946 // we add the face. Note that this routine can get called anywhere from
00947 // two times (two unrefined faces) to four times (two refined faces) so
00948 // the first call that adds the information creates the face.
00949 Foam::label Foam::hexRef8::storeMidPointInfo
00950 (
00951     const labelListList& cellAnchorPoints,
00952     const labelListList& cellAddedCells,
00953     const labelList& cellMidPoint,
00954     const labelList& edgeMidPoint,
00955     const label cellI,
00956     const label faceI,
00957     const bool faceOrder,
00958     const label edgeMidPointI,
00959     const label anchorPointI,
00960     const label faceMidPointI,
00961 
00962     Map<edge>& midPointToAnchors,
00963     Map<edge>& midPointToFaceMids,
00964     polyTopoChange& meshMod
00965 ) const
00966 {
00967     // See if need to store anchors.
00968 
00969     bool changed = false;
00970     bool haveTwoAnchors = false;
00971 
00972     Map<edge>::iterator edgeMidFnd = midPointToAnchors.find(edgeMidPointI);
00973 
00974     if (edgeMidFnd == midPointToAnchors.end())
00975     {
00976         midPointToAnchors.insert(edgeMidPointI, edge(anchorPointI, -1));
00977     }
00978     else
00979     {
00980         edge& e = edgeMidFnd();
00981 
00982         if (anchorPointI != e[0])
00983         {
00984             if (e[1] == -1)
00985             {
00986                 e[1] = anchorPointI;
00987                 changed = true;
00988             }
00989         }
00990 
00991         if (e[0] != -1 && e[1] != -1)
00992         {
00993             haveTwoAnchors = true;
00994         }
00995     }
00996 
00997     bool haveTwoFaceMids = false;
00998 
00999     Map<edge>::iterator faceMidFnd = midPointToFaceMids.find(edgeMidPointI);
01000 
01001     if (faceMidFnd == midPointToFaceMids.end())
01002     {
01003         midPointToFaceMids.insert(edgeMidPointI, edge(faceMidPointI, -1));
01004     }
01005     else
01006     {
01007         edge& e = faceMidFnd();
01008 
01009         if (faceMidPointI != e[0])
01010         {
01011             if (e[1] == -1)
01012             {
01013                 e[1] = faceMidPointI;
01014                 changed = true;
01015             }
01016         }
01017 
01018         if (e[0] != -1 && e[1] != -1)
01019         {
01020             haveTwoFaceMids = true;
01021         }
01022     }
01023 
01024     // Check if this call of storeMidPointInfo is the one that completed all
01025     // the nessecary information.
01026 
01027     if (changed && haveTwoAnchors && haveTwoFaceMids)
01028     {
01029         const edge& anchors = midPointToAnchors[edgeMidPointI];
01030         const edge& faceMids = midPointToFaceMids[edgeMidPointI];
01031 
01032         label otherFaceMidPointI = faceMids.otherVertex(faceMidPointI);
01033 
01034         // Create face consistent with anchorI being the owner.
01035         // Note that the edges between the edge mid point and the face mids
01036         // might be marked for splitting. Note that these edge splits cannot
01037         // be between cellMid and face mids.
01038 
01039         DynamicList<label> newFaceVerts(4);
01040         if (faceOrder == (mesh_.faceOwner()[faceI] == cellI))
01041         {
01042             newFaceVerts.append(faceMidPointI);
01043 
01044             // Check & insert edge split if any
01045             insertEdgeSplit
01046             (
01047                 edgeMidPoint,
01048                 faceMidPointI,  // edge between faceMid and
01049                 edgeMidPointI,  // edgeMid
01050                 newFaceVerts
01051             );
01052 
01053             newFaceVerts.append(edgeMidPointI);
01054 
01055             insertEdgeSplit
01056             (
01057                 edgeMidPoint,
01058                 edgeMidPointI,
01059                 otherFaceMidPointI,
01060                 newFaceVerts
01061             );
01062 
01063             newFaceVerts.append(otherFaceMidPointI);
01064             newFaceVerts.append(cellMidPoint[cellI]);
01065         }
01066         else
01067         {
01068             newFaceVerts.append(otherFaceMidPointI);
01069 
01070             insertEdgeSplit
01071             (
01072                 edgeMidPoint,
01073                 otherFaceMidPointI,
01074                 edgeMidPointI,
01075                 newFaceVerts
01076             );
01077 
01078             newFaceVerts.append(edgeMidPointI);
01079 
01080             insertEdgeSplit
01081             (
01082                 edgeMidPoint,
01083                 edgeMidPointI,
01084                 faceMidPointI,
01085                 newFaceVerts
01086             );
01087 
01088             newFaceVerts.append(faceMidPointI);
01089             newFaceVerts.append(cellMidPoint[cellI]);
01090         }
01091 
01092         face newFace;
01093         newFace.transfer(newFaceVerts);
01094 
01095         label anchorCell0 = getAnchorCell
01096         (
01097             cellAnchorPoints,
01098             cellAddedCells,
01099             cellI,
01100             faceI,
01101             anchorPointI
01102         );
01103         label anchorCell1 = getAnchorCell
01104         (
01105             cellAnchorPoints,
01106             cellAddedCells,
01107             cellI,
01108             faceI,
01109             anchors.otherVertex(anchorPointI)
01110         );
01111 
01112 
01113         label own, nei;
01114         point ownPt, neiPt;
01115 
01116         if (anchorCell0 < anchorCell1)
01117         {
01118             own = anchorCell0;
01119             nei = anchorCell1;
01120 
01121             ownPt = mesh_.points()[anchorPointI];
01122             neiPt = mesh_.points()[anchors.otherVertex(anchorPointI)];
01123 
01124         }
01125         else
01126         {
01127             own = anchorCell1;
01128             nei = anchorCell0;
01129             newFace = newFace.reverseFace();
01130 
01131             ownPt = mesh_.points()[anchors.otherVertex(anchorPointI)];
01132             neiPt = mesh_.points()[anchorPointI];
01133         }
01134 
01135         if (debug)
01136         {
01137             point ownPt, neiPt;
01138 
01139             if (anchorCell0 < anchorCell1)
01140             {
01141                 ownPt = mesh_.points()[anchorPointI];
01142                 neiPt = mesh_.points()[anchors.otherVertex(anchorPointI)];
01143             }
01144             else
01145             {
01146                 ownPt = mesh_.points()[anchors.otherVertex(anchorPointI)];
01147                 neiPt = mesh_.points()[anchorPointI];
01148             }
01149 
01150             checkInternalOrientation
01151             (
01152                 meshMod,
01153                 cellI,
01154                 faceI,
01155                 ownPt,
01156                 neiPt,
01157                 newFace
01158             );
01159         }
01160 
01161         return addInternalFace
01162         (
01163             meshMod,
01164             faceI,
01165             anchorPointI,
01166             newFace,
01167             own,
01168             nei
01169         );
01170     }
01171     else
01172     {
01173         return -1;
01174     }
01175 }
01176 
01177 
01178 // Creates all the 12 internal faces for cellI.
01179 void Foam::hexRef8::createInternalFaces
01180 (
01181     const labelListList& cellAnchorPoints,
01182     const labelListList& cellAddedCells,
01183     const labelList& cellMidPoint,
01184     const labelList& faceMidPoint,
01185     const labelList& faceAnchorLevel,
01186     const labelList& edgeMidPoint,
01187     const label cellI,
01188 
01189     polyTopoChange& meshMod
01190 ) const
01191 {
01192     // Find in every face the cellLevel+1 points (from edge subdivision)
01193     // and the anchor points.
01194 
01195     const cell& cFaces = mesh_.cells()[cellI];
01196     const label cLevel = cellLevel_[cellI];
01197 
01198     // From edge mid to anchor points
01199     Map<edge> midPointToAnchors(24);
01200     // From edge mid to face mids
01201     Map<edge> midPointToFaceMids(24);
01202 
01203     // Storage for on-the-fly addressing
01204     DynamicList<label> storage;
01205 
01206 
01207     // Running count of number of internal faces added so far.
01208     label nFacesAdded = 0;
01209 
01210     forAll(cFaces, i)
01211     {
01212         label faceI = cFaces[i];
01213 
01214         const face& f = mesh_.faces()[faceI];
01215         const labelList& fEdges = mesh_.faceEdges(faceI, storage);
01216 
01217         // We are on the cellI side of face f. The face will have 1 or 4
01218         // cLevel points and lots of higher numbered ones.
01219 
01220         label faceMidPointI = -1;
01221 
01222         label nAnchors = countAnchors(f, cLevel);
01223 
01224         if (nAnchors == 1)
01225         {
01226             // Only one anchor point. So the other side of the face has already
01227             // been split using cLevel+1 and cLevel+2 points.
01228 
01229             // Find the one anchor.
01230             label anchorFp = -1;
01231 
01232             forAll(f, fp)
01233             {
01234                 if (pointLevel_[f[fp]] <= cLevel)
01235                 {
01236                     anchorFp = fp;
01237                     break;
01238                 }
01239             }
01240 
01241             // Now the face mid point is the second cLevel+1 point
01242             label edgeMid = findLevel
01243             (
01244                 faceI,
01245                 f,
01246                 f.fcIndex(anchorFp),
01247                 true,
01248                 cLevel+1
01249             );
01250             label faceMid = findLevel
01251             (
01252                 faceI,
01253                 f,
01254                 f.fcIndex(edgeMid),
01255                 true,
01256                 cLevel+1
01257             );
01258 
01259             faceMidPointI = f[faceMid];
01260         }
01261         else if (nAnchors == 4)
01262         {
01263             // There is no face middle yet but the face will be marked for
01264             // splitting.
01265 
01266             faceMidPointI = faceMidPoint[faceI];
01267         }
01268         else
01269         {
01270             dumpCell(mesh_.faceOwner()[faceI]);
01271             if (mesh_.isInternalFace(faceI))
01272             {
01273                 dumpCell(mesh_.faceNeighbour()[faceI]);
01274             }
01275 
01276             FatalErrorIn("createInternalFaces(..)")
01277                 << "nAnchors:" << nAnchors
01278                 << " faceI:" << faceI
01279                 << abort(FatalError);
01280         }
01281 
01282 
01283 
01284         // Now loop over all the anchors (might be just one) and store
01285         // the edge mids connected to it. storeMidPointInfo will collect
01286         // all the info and combine it all.
01287 
01288         forAll(f, fp0)
01289         {
01290             label point0 = f[fp0];
01291 
01292             if (pointLevel_[point0] <= cLevel)
01293             {
01294                 // Anchor.
01295 
01296                 // Walk forward
01297                 // ~~~~~~~~~~~~
01298                 // to cLevel+1 or edgeMidPoint of this level.
01299 
01300 
01301                 label edgeMidPointI = -1;
01302 
01303                 label fp1 = f.fcIndex(fp0);
01304 
01305                 if (pointLevel_[f[fp1]] <= cLevel)
01306                 {
01307                     // Anchor. Edge will be split.
01308                     label edgeI = fEdges[fp0];
01309 
01310                     edgeMidPointI = edgeMidPoint[edgeI];
01311 
01312                     if (edgeMidPointI == -1)
01313                     {
01314                         dumpCell(cellI);
01315 
01316                         const labelList& cPoints = mesh_.cellPoints(cellI);
01317 
01318                         FatalErrorIn("createInternalFaces(..)")
01319                             << "cell:" << cellI << " cLevel:" << cLevel
01320                             << " cell points:" << cPoints
01321                             << " pointLevel:"
01322                             << UIndirectList<label>(pointLevel_, cPoints)()
01323                             << " face:" << faceI
01324                             << " f:" << f
01325                             << " pointLevel:"
01326                             << UIndirectList<label>(pointLevel_, f)()
01327                             << " faceAnchorLevel:" << faceAnchorLevel[faceI]
01328                             << " faceMidPoint:" << faceMidPoint[faceI]
01329                             << " faceMidPointI:" << faceMidPointI
01330                             << " fp:" << fp0
01331                             << abort(FatalError);
01332                     }
01333                 }
01334                 else
01335                 {
01336                     // Search forward in face to clevel+1
01337                     label edgeMid = findLevel(faceI, f, fp1, true, cLevel+1);
01338 
01339                     edgeMidPointI = f[edgeMid];
01340                 }
01341 
01342                 label newFaceI = storeMidPointInfo
01343                 (
01344                     cellAnchorPoints,
01345                     cellAddedCells,
01346                     cellMidPoint,
01347                     edgeMidPoint,
01348 
01349                     cellI,
01350                     faceI,
01351                     true,                   // mid point after anchor
01352                     edgeMidPointI,          // edgemid
01353                     point0,                 // anchor
01354                     faceMidPointI,
01355 
01356                     midPointToAnchors,
01357                     midPointToFaceMids,
01358                     meshMod
01359                 );
01360 
01361                 if (newFaceI != -1)
01362                 {
01363                     nFacesAdded++;
01364 
01365                     if (nFacesAdded == 12)
01366                     {
01367                         break;
01368                     }
01369                 }
01370 
01371 
01372 
01373                 // Walk backward
01374                 // ~~~~~~~~~~~~~
01375 
01376                 label fpMin1 = f.rcIndex(fp0);
01377 
01378                 if (pointLevel_[f[fpMin1]] <= cLevel)
01379                 {
01380                     // Anchor. Edge will be split.
01381                     label edgeI = fEdges[fpMin1];
01382 
01383                     edgeMidPointI = edgeMidPoint[edgeI];
01384 
01385                     if (edgeMidPointI == -1)
01386                     {
01387                         dumpCell(cellI);
01388 
01389                         const labelList& cPoints = mesh_.cellPoints(cellI);
01390 
01391                         FatalErrorIn("createInternalFaces(..)")
01392                             << "cell:" << cellI << " cLevel:" << cLevel
01393                             << " cell points:" << cPoints
01394                             << " pointLevel:"
01395                             << UIndirectList<label>(pointLevel_, cPoints)()
01396                             << " face:" << faceI
01397                             << " f:" << f
01398                             << " pointLevel:"
01399                             << UIndirectList<label>(pointLevel_, f)()
01400                             << " faceAnchorLevel:" << faceAnchorLevel[faceI]
01401                             << " faceMidPoint:" << faceMidPoint[faceI]
01402                             << " faceMidPointI:" << faceMidPointI
01403                             << " fp:" << fp0
01404                             << abort(FatalError);
01405                     }
01406                 }
01407                 else
01408                 {
01409                     // Search back to clevel+1
01410                     label edgeMid = findLevel
01411                     (
01412                         faceI,
01413                         f,
01414                         fpMin1,
01415                         false,
01416                         cLevel+1
01417                     );
01418 
01419                     edgeMidPointI = f[edgeMid];
01420                 }
01421 
01422                 newFaceI = storeMidPointInfo
01423                 (
01424                     cellAnchorPoints,
01425                     cellAddedCells,
01426                     cellMidPoint,
01427                     edgeMidPoint,
01428 
01429                     cellI,
01430                     faceI,
01431                     false,                  // mid point before anchor
01432                     edgeMidPointI,          // edgemid
01433                     point0,                 // anchor
01434                     faceMidPointI,
01435 
01436                     midPointToAnchors,
01437                     midPointToFaceMids,
01438                     meshMod
01439                 );
01440 
01441                 if (newFaceI != -1)
01442                 {
01443                     nFacesAdded++;
01444 
01445                     if (nFacesAdded == 12)
01446                     {
01447                         break;
01448                     }
01449                 }
01450             }   // done anchor
01451         }   // done face
01452 
01453         if (nFacesAdded == 12)
01454         {
01455             break;
01456         }
01457     }
01458 }
01459 
01460 
01461 void Foam::hexRef8::walkFaceToMid
01462 (
01463     const labelList& edgeMidPoint,
01464     const label cLevel,
01465     const label faceI,
01466     const label startFp,
01467     DynamicList<label>& faceVerts
01468 ) const
01469 {
01470     const face& f = mesh_.faces()[faceI];
01471     const labelList& fEdges = mesh_.faceEdges(faceI);
01472 
01473     label fp = startFp;
01474 
01475     // Starting from fp store all (1 or 2) vertices until where the face
01476     // gets split
01477 
01478     while (true)
01479     {
01480         if (edgeMidPoint[fEdges[fp]] >= 0)
01481         {
01482             faceVerts.append(edgeMidPoint[fEdges[fp]]);
01483         }
01484 
01485         fp = f.fcIndex(fp);
01486 
01487         if (pointLevel_[f[fp]] <= cLevel)
01488         {
01489             // Next anchor. Have already append split point on edge in code
01490             // above.
01491             return;
01492         }
01493         else if (pointLevel_[f[fp]] == cLevel+1)
01494         {
01495             // Mid level
01496             faceVerts.append(f[fp]);
01497 
01498             return;
01499         }
01500         else if (pointLevel_[f[fp]] == cLevel+2)
01501         {
01502             // Store and continue to cLevel+1.
01503             faceVerts.append(f[fp]);
01504         }
01505     }
01506 }
01507 
01508 
01509 // Same as walkFaceToMid but now walk back.
01510 void Foam::hexRef8::walkFaceFromMid
01511 (
01512     const labelList& edgeMidPoint,
01513     const label cLevel,
01514     const label faceI,
01515     const label startFp,
01516     DynamicList<label>& faceVerts
01517 ) const
01518 {
01519     const face& f = mesh_.faces()[faceI];
01520     const labelList& fEdges = mesh_.faceEdges(faceI);
01521 
01522     label fp = f.rcIndex(startFp);
01523 
01524     while (true)
01525     {
01526         if (pointLevel_[f[fp]] <= cLevel)
01527         {
01528             // anchor.
01529             break;
01530         }
01531         else if (pointLevel_[f[fp]] == cLevel+1)
01532         {
01533             // Mid level
01534             faceVerts.append(f[fp]);
01535             break;
01536         }
01537         else if (pointLevel_[f[fp]] == cLevel+2)
01538         {
01539             // Continue to cLevel+1.
01540         }
01541         fp = f.rcIndex(fp);
01542     }
01543 
01544     // Store
01545     while (true)
01546     {
01547         if (edgeMidPoint[fEdges[fp]] >= 0)
01548         {
01549             faceVerts.append(edgeMidPoint[fEdges[fp]]);
01550         }
01551 
01552         fp = f.fcIndex(fp);
01553 
01554         if (fp == startFp)
01555         {
01556             break;
01557         }
01558         faceVerts.append(f[fp]);
01559     }
01560 }
01561 
01562 
01563 // Updates refineCell (cells marked for refinement) so across all faces
01564 // there will be 2:1 consistency after refinement.
01565 Foam::label Foam::hexRef8::faceConsistentRefinement
01566 (
01567     const bool maxSet,
01568     PackedBoolList& refineCell
01569 ) const
01570 {
01571     label nChanged = 0;
01572 
01573     // Internal faces.
01574     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
01575     {
01576         label own = mesh_.faceOwner()[faceI];
01577         label ownLevel = cellLevel_[own] + refineCell.get(own);
01578 
01579         label nei = mesh_.faceNeighbour()[faceI];
01580         label neiLevel = cellLevel_[nei] + refineCell.get(nei);
01581 
01582         if (ownLevel > (neiLevel+1))
01583         {
01584             if (maxSet)
01585             {
01586                 refineCell.set(nei, 1);
01587             }
01588             else
01589             {
01590                 refineCell.set(own, 0);
01591             }
01592             nChanged++;
01593         }
01594         else if (neiLevel > (ownLevel+1))
01595         {
01596             if (maxSet)
01597             {
01598                 refineCell.set(own, 1);
01599             }
01600             else
01601             {
01602                 refineCell.set(nei, 0);
01603             }
01604             nChanged++;
01605         }
01606     }
01607 
01608 
01609     // Coupled faces. Swap owner level to get neighbouring cell level.
01610     // (only boundary faces of neiLevel used)
01611     labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
01612 
01613     forAll(neiLevel, i)
01614     {
01615         label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
01616 
01617         neiLevel[i] = cellLevel_[own] + refineCell.get(own);
01618     }
01619 
01620     // Swap to neighbour
01621     syncTools::swapBoundaryFaceList(mesh_, neiLevel, false);
01622 
01623     // Now we have neighbour value see which cells need refinement
01624     forAll(neiLevel, i)
01625     {
01626         label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
01627         label ownLevel = cellLevel_[own] + refineCell.get(own);
01628 
01629         if (ownLevel > (neiLevel[i]+1))
01630         {
01631             if (!maxSet)
01632             {
01633                 refineCell.set(own, 0);
01634                 nChanged++;
01635             }
01636         }
01637         else if (neiLevel[i] > (ownLevel+1))
01638         {
01639             if (maxSet)
01640             {
01641                 refineCell.set(own, 1);
01642                 nChanged++;
01643             }
01644         }
01645     }
01646 
01647     return nChanged;
01648 }
01649 
01650 
01651 // Debug: check if wanted refinement is compatible with 2:1
01652 void Foam::hexRef8::checkWantedRefinementLevels
01653 (
01654     const labelList& cellsToRefine
01655 ) const
01656 {
01657     PackedBoolList refineCell(mesh_.nCells());
01658     forAll(cellsToRefine, i)
01659     {
01660         refineCell.set(cellsToRefine[i], 1);
01661     }
01662 
01663     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
01664     {
01665         label own = mesh_.faceOwner()[faceI];
01666         label ownLevel = cellLevel_[own] + refineCell.get(own);
01667 
01668         label nei = mesh_.faceNeighbour()[faceI];
01669         label neiLevel = cellLevel_[nei] + refineCell.get(nei);
01670 
01671         if (mag(ownLevel-neiLevel) > 1)
01672         {
01673             dumpCell(own);
01674             dumpCell(nei);
01675             FatalErrorIn
01676             (
01677                 "hexRef8::checkWantedRefinementLevels(const labelList&)"
01678             )   << "cell:" << own
01679                 << " current level:" << cellLevel_[own]
01680                 << " level after refinement:" << ownLevel
01681                 << nl
01682                 << "neighbour cell:" << nei
01683                 << " current level:" << cellLevel_[nei]
01684                 << " level after refinement:" << neiLevel
01685                 << nl
01686                 << "which does not satisfy 2:1 constraints anymore."
01687                 << abort(FatalError);
01688         }
01689     }
01690 
01691     // Coupled faces. Swap owner level to get neighbouring cell level.
01692     // (only boundary faces of neiLevel used)
01693     labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
01694 
01695     forAll(neiLevel, i)
01696     {
01697         label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
01698 
01699         neiLevel[i] = cellLevel_[own] + refineCell.get(own);
01700     }
01701 
01702     // Swap to neighbour
01703     syncTools::swapBoundaryFaceList(mesh_, neiLevel, false);
01704 
01705     // Now we have neighbour value see which cells need refinement
01706     forAll(neiLevel, i)
01707     {
01708         label faceI = i + mesh_.nInternalFaces();
01709 
01710         label own = mesh_.faceOwner()[faceI];
01711         label ownLevel = cellLevel_[own] + refineCell.get(own);
01712 
01713         if (mag(ownLevel - neiLevel[i]) > 1)
01714         {
01715             label patchI = mesh_.boundaryMesh().whichPatch(faceI);
01716 
01717             dumpCell(own);
01718             FatalErrorIn
01719             (
01720                 "hexRef8::checkWantedRefinementLevels(const labelList&)"
01721             )   << "Celllevel does not satisfy 2:1 constraint."
01722                 << " On coupled face "
01723                 << faceI
01724                 << " on patch " << patchI << " "
01725                 << mesh_.boundaryMesh()[patchI].name()
01726                 << " owner cell " << own
01727                 << " current level:" << cellLevel_[own]
01728                 << " level after refinement:" << ownLevel
01729                 << nl
01730                 << " (coupled) neighbour cell will get refinement "
01731                 << neiLevel[i]
01732                 << abort(FatalError);
01733         }
01734     }
01735 }
01736 
01737 
01738 // Set instance for mesh files
01739 void Foam::hexRef8::setInstance(const fileName& inst)
01740 {
01741     if (debug)
01742     {
01743         Pout<< "hexRef8::setInstance(const fileName& inst) : "
01744             << "Resetting file instance to " << inst << endl;
01745     }
01746 
01747     cellLevel_.instance() = inst;
01748     pointLevel_.instance() = inst;
01749     history_.instance() = inst;
01750 }
01751 
01752 
01753 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
01754 
01755 // Construct from mesh, read refinement data
01756 Foam::hexRef8::hexRef8(const polyMesh& mesh)
01757 :
01758     mesh_(mesh),
01759     cellLevel_
01760     (
01761         IOobject
01762         (
01763             "cellLevel",
01764             mesh_.facesInstance(),
01765             polyMesh::meshSubDir,
01766             mesh_,
01767             IOobject::READ_IF_PRESENT,
01768             IOobject::AUTO_WRITE
01769         ),
01770         labelList(mesh_.nCells(), 0)
01771     ),
01772     pointLevel_
01773     (
01774         IOobject
01775         (
01776             "pointLevel",
01777             mesh_.facesInstance(),
01778             polyMesh::meshSubDir,
01779             mesh_,
01780             IOobject::READ_IF_PRESENT,
01781             IOobject::AUTO_WRITE
01782         ),
01783         labelList(mesh_.nPoints(), 0)
01784     ),
01785     level0Edge_(getLevel0EdgeLength()),
01786     history_
01787     (
01788         IOobject
01789         (
01790             "refinementHistory",
01791             mesh_.facesInstance(),
01792             polyMesh::meshSubDir,
01793             mesh_,
01794             IOobject::READ_IF_PRESENT,
01795             IOobject::AUTO_WRITE
01796         ),
01797         mesh_.nCells()    // All cells visible if could not be read
01798     ),
01799     faceRemover_(mesh_, GREAT),     // merge boundary faces wherever possible
01800     savedPointLevel_(0),
01801     savedCellLevel_(0)
01802 {
01803     if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
01804     {
01805         FatalErrorIn
01806         (
01807             "hexRef8::hexRef8(const polyMesh&)"
01808         )   << "History enabled but number of visible cells in it "
01809             << history_.visibleCells().size()
01810             << " is not equal to the number of cells in the mesh "
01811             << mesh_.nCells()
01812             << abort(FatalError);
01813     }
01814 
01815     if
01816     (
01817         cellLevel_.size() != mesh_.nCells()
01818      || pointLevel_.size() != mesh_.nPoints()
01819     )
01820     {
01821         FatalErrorIn
01822         (
01823             "hexRef8::hexRef8(const polyMesh&)"
01824         )   << "Restarted from inconsistent cellLevel or pointLevel files."
01825             << endl
01826             << "Number of cells in mesh:" << mesh_.nCells()
01827             << " does not equal size of cellLevel:" << cellLevel_.size() << endl
01828             << "Number of points in mesh:" << mesh_.nPoints()
01829             << " does not equal size of pointLevel:" << pointLevel_.size()
01830             << abort(FatalError);
01831     }
01832 
01833 
01834     // Check refinement levels for consistency
01835     checkRefinementLevels(-1, labelList(0));
01836 
01837 
01838     // Check initial mesh for consistency
01839 
01840     //if (debug)
01841     {
01842         checkMesh();
01843     }
01844 }
01845 
01846 
01847 // Construct from components
01848 Foam::hexRef8::hexRef8
01849 (
01850     const polyMesh& mesh,
01851     const labelList& cellLevel,
01852     const labelList& pointLevel,
01853     const refinementHistory& history
01854 )
01855 :
01856     mesh_(mesh),
01857     cellLevel_
01858     (
01859         IOobject
01860         (
01861             "cellLevel",
01862             mesh_.facesInstance(),
01863             polyMesh::meshSubDir,
01864             mesh_,
01865             IOobject::NO_READ,
01866             IOobject::AUTO_WRITE
01867         ),
01868         cellLevel
01869     ),
01870     pointLevel_
01871     (
01872         IOobject
01873         (
01874             "pointLevel",
01875             mesh_.facesInstance(),
01876             polyMesh::meshSubDir,
01877             mesh_,
01878             IOobject::NO_READ,
01879             IOobject::AUTO_WRITE
01880         ),
01881         pointLevel
01882     ),
01883     level0Edge_(getLevel0EdgeLength()),
01884     history_
01885     (
01886         IOobject
01887         (
01888             "refinementHistory",
01889             mesh_.facesInstance(),
01890             polyMesh::meshSubDir,
01891             mesh_,
01892             IOobject::NO_READ,
01893             IOobject::AUTO_WRITE
01894         ),
01895         history
01896     ),
01897     faceRemover_(mesh_, GREAT),     // merge boundary faces wherever possible
01898     savedPointLevel_(0),
01899     savedCellLevel_(0)
01900 {
01901     if (history_.active() && history_.visibleCells().size() != mesh_.nCells())
01902     {
01903         FatalErrorIn
01904         (
01905             "hexRef8::hexRef8(const polyMesh&, const labelList&"
01906             ", const labelList&, const refinementHistory&)"
01907         )   << "History enabled but number of visible cells in it "
01908             << history_.visibleCells().size()
01909             << " is not equal to the number of cells in the mesh "
01910             << mesh_.nCells() << abort(FatalError);
01911     }
01912 
01913     if
01914     (
01915         cellLevel_.size() != mesh_.nCells()
01916      || pointLevel_.size() != mesh_.nPoints()
01917     )
01918     {
01919         FatalErrorIn
01920         (
01921             "hexRef8::hexRef8(const polyMesh&, const labelList&"
01922             ", const labelList&, const refinementHistory&)"
01923         )   << "Incorrect cellLevel or pointLevel size." << endl
01924             << "Number of cells in mesh:" << mesh_.nCells()
01925             << " does not equal size of cellLevel:" << cellLevel_.size() << endl
01926             << "Number of points in mesh:" << mesh_.nPoints()
01927             << " does not equal size of pointLevel:" << pointLevel_.size()
01928             << abort(FatalError);
01929     }
01930 
01931     // Check refinement levels for consistency
01932     checkRefinementLevels(-1, labelList(0));
01933 
01934 
01935     // Check initial mesh for consistency
01936 
01937     //if (debug)
01938     {
01939         checkMesh();
01940     }
01941 }
01942 
01943 
01944 // Construct from components
01945 Foam::hexRef8::hexRef8
01946 (
01947     const polyMesh& mesh,
01948     const labelList& cellLevel,
01949     const labelList& pointLevel
01950 )
01951 :
01952     mesh_(mesh),
01953     cellLevel_
01954     (
01955         IOobject
01956         (
01957             "cellLevel",
01958             mesh_.facesInstance(),
01959             polyMesh::meshSubDir,
01960             mesh_,
01961             IOobject::NO_READ,
01962             IOobject::AUTO_WRITE
01963         ),
01964         cellLevel
01965     ),
01966     pointLevel_
01967     (
01968         IOobject
01969         (
01970             "pointLevel",
01971             mesh_.facesInstance(),
01972             polyMesh::meshSubDir,
01973             mesh_,
01974             IOobject::NO_READ,
01975             IOobject::AUTO_WRITE
01976         ),
01977         pointLevel
01978     ),
01979     level0Edge_(getLevel0EdgeLength()),
01980     history_
01981     (
01982         IOobject
01983         (
01984             "refinementHistory",
01985             mesh_.facesInstance(),
01986             polyMesh::meshSubDir,
01987             mesh_,
01988             IOobject::NO_READ,
01989             IOobject::AUTO_WRITE
01990         ),
01991         List<refinementHistory::splitCell8>(0),
01992         labelList(0)
01993     ),
01994     faceRemover_(mesh_, GREAT),     // merge boundary faces wherever possible
01995     savedPointLevel_(0),
01996     savedCellLevel_(0)
01997 {
01998     if
01999     (
02000         cellLevel_.size() != mesh_.nCells()
02001      || pointLevel_.size() != mesh_.nPoints()
02002     )
02003     {
02004         FatalErrorIn
02005         (
02006             "hexRef8::hexRef8(const polyMesh&, const labelList&"
02007             ", const labelList&)"
02008         )   << "Incorrect cellLevel or pointLevel size." << endl
02009             << "Number of cells in mesh:" << mesh_.nCells()
02010             << " does not equal size of cellLevel:" << cellLevel_.size() << endl
02011             << "Number of points in mesh:" << mesh_.nPoints()
02012             << " does not equal size of pointLevel:" << pointLevel_.size()
02013             << abort(FatalError);
02014     }
02015 
02016     // Check refinement levels for consistency
02017     checkRefinementLevels(-1, labelList(0));
02018 
02019     // Check initial mesh for consistency
02020 
02021     //if (debug)
02022     {
02023         checkMesh();
02024     }
02025 }
02026 
02027 
02028 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
02029 
02030 Foam::labelList Foam::hexRef8::consistentRefinement
02031 (
02032     const labelList& cellsToRefine,
02033     const bool maxSet
02034 ) const
02035 {
02036     // Loop, modifying cellsToRefine, until no more changes to due to 2:1
02037     // conflicts.
02038     // maxSet = false : unselect cells to refine
02039     // maxSet = true  : select cells to refine
02040 
02041     // Go to straight boolList.
02042     PackedBoolList refineCell(mesh_.nCells());
02043     forAll(cellsToRefine, i)
02044     {
02045         refineCell.set(cellsToRefine[i], 1);
02046     }
02047 
02048     while (true)
02049     {
02050         label nChanged = faceConsistentRefinement(maxSet, refineCell);
02051 
02052         reduce(nChanged, sumOp<label>());
02053 
02054         if (debug)
02055         {
02056             Pout<< "hexRef8::consistentRefinement : Changed " << nChanged
02057                 << " refinement levels due to 2:1 conflicts."
02058                 << endl;
02059         }
02060 
02061         if (nChanged == 0)
02062         {
02063             break;
02064         }
02065     }
02066 
02067 
02068     // Convert back to labelList.
02069     label nRefined = 0;
02070 
02071     forAll(refineCell, cellI)
02072     {
02073         if (refineCell.get(cellI) == 1)
02074         {
02075             nRefined++;
02076         }
02077     }
02078 
02079     labelList newCellsToRefine(nRefined);
02080     nRefined = 0;
02081 
02082     forAll(refineCell, cellI)
02083     {
02084         if (refineCell.get(cellI) == 1)
02085         {
02086             newCellsToRefine[nRefined++] = cellI;
02087         }
02088     }
02089 
02090     if (debug)
02091     {
02092         checkWantedRefinementLevels(newCellsToRefine);
02093     }
02094 
02095     return newCellsToRefine;
02096 }
02097 
02098 
02099 // Given a list of cells to refine determine additional cells to refine
02100 // such that the overall refinement:
02101 // - satisfies maxFaceDiff (e.g. 2:1) across neighbouring faces
02102 // - satisfies maxPointDiff (e.g. 4:1) across selected point connected
02103 //   cells. This is used to ensure that e.g. cells on the surface are not
02104 //   point connected to cells which are 8 times smaller.
02105 Foam::labelList Foam::hexRef8::consistentSlowRefinement
02106 (
02107     const label maxFaceDiff,
02108     const labelList& cellsToRefine,
02109     const labelList& facesToCheck,
02110     const label maxPointDiff,
02111     const labelList& pointsToCheck
02112 ) const
02113 {
02114     const labelList& faceOwner = mesh_.faceOwner();
02115     const labelList& faceNeighbour = mesh_.faceNeighbour();
02116 
02117 
02118     if (maxFaceDiff <= 0)
02119     {
02120         FatalErrorIn
02121         (
02122             "hexRef8::consistentSlowRefinement"
02123             "(const label, const labelList&, const labelList&"
02124             ", const label, const labelList&)"
02125         )   << "Illegal maxFaceDiff " << maxFaceDiff << nl
02126             << "Value should be >= 1" << exit(FatalError);
02127     }
02128 
02129 
02130     // Bit tricky. Say we want a distance of three cells between two
02131     // consecutive refinement levels. This is done by using FaceCellWave to
02132     // transport out the new refinement level. It gets decremented by one
02133     // every cell it crosses so if we initialize it to maxFaceDiff
02134     // we will get a field everywhere that tells us whether an unselected cell
02135     // needs refining as well.
02136 
02137 
02138     // Initial information about (distance to) cellLevel on all cells
02139     List<refinementData> allCellInfo(mesh_.nCells());
02140 
02141     // Initial information about (distance to) cellLevel on all faces
02142     List<refinementData> allFaceInfo(mesh_.nFaces());
02143 
02144     forAll(allCellInfo, cellI)
02145     {
02146         // maxFaceDiff since refinementData counts both
02147         // faces and cells.
02148         allCellInfo[cellI] = refinementData
02149         (
02150             maxFaceDiff*(cellLevel_[cellI]+1),// when cell is to be refined
02151             maxFaceDiff*cellLevel_[cellI]     // current level
02152         );
02153     }
02154 
02155     // Cells to be refined will have cellLevel+1
02156     forAll(cellsToRefine, i)
02157     {
02158         label cellI = cellsToRefine[i];
02159 
02160         allCellInfo[cellI].count() = allCellInfo[cellI].refinementCount();
02161     }
02162 
02163 
02164     // Labels of seed faces
02165     DynamicList<label> seedFaces(mesh_.nFaces()/100);
02166     // refinementLevel data on seed faces
02167     DynamicList<refinementData> seedFacesInfo(mesh_.nFaces()/100);
02168 
02169 
02170     // Additional buffer layer thickness by changing initial count. Usually
02171     // this happens on boundary faces. Bit tricky. Use allFaceInfo to mark
02172     // off thus marked faces so they're skipped in the next loop.
02173     forAll(facesToCheck, i)
02174     {
02175         label faceI = facesToCheck[i];
02176 
02177         if (allFaceInfo[faceI].valid())
02178         {
02179             // Can only occur if face has already gone through loop below.
02180             FatalErrorIn
02181             (
02182                 "hexRef8::consistentSlowRefinement"
02183                 "(const label, const labelList&, const labelList&"
02184                 ", const label, const labelList&)"
02185             )   << "Argument facesToCheck seems to have duplicate entries!"
02186                 << endl
02187                 << "face:" << faceI << " occurs at positions "
02188                 << findIndices(facesToCheck, faceI)
02189                 << abort(FatalError);
02190         }
02191 
02192 
02193         const refinementData& ownData = allCellInfo[faceOwner[faceI]];
02194 
02195         if (mesh_.isInternalFace(faceI))
02196         {
02197             // Seed face if neighbouring cell (after possible refinement)
02198             // will be refined one more than the current owner or neighbour.
02199 
02200             const refinementData& neiData = allCellInfo[faceNeighbour[faceI]];
02201 
02202             label faceCount;
02203             label faceRefineCount;
02204             if (neiData.count() > ownData.count())
02205             {
02206                 faceCount = neiData.count() + maxFaceDiff;
02207                 faceRefineCount = faceCount + maxFaceDiff;
02208             }
02209             else
02210             {
02211                 faceCount = ownData.count() + maxFaceDiff;
02212                 faceRefineCount = faceCount + maxFaceDiff;
02213             }
02214 
02215             seedFaces.append(faceI);
02216             seedFacesInfo.append
02217             (
02218                 refinementData
02219                 (
02220                     faceRefineCount,
02221                     faceCount
02222                 )
02223             );
02224             allFaceInfo[faceI] = seedFacesInfo[seedFacesInfo.size()-1];
02225         }
02226         else
02227         {
02228             label faceCount = ownData.count() + maxFaceDiff;
02229             label faceRefineCount = faceCount + maxFaceDiff;
02230 
02231             seedFaces.append(faceI);
02232             seedFacesInfo.append
02233             (
02234                 refinementData
02235                 (
02236                     faceRefineCount,
02237                     faceCount
02238                 )
02239             );
02240             allFaceInfo[faceI] = seedFacesInfo[seedFacesInfo.size()-1];
02241         }
02242     }
02243 
02244 
02245     // Just seed with all faces inbetween different refinement levels for now
02246     // (alternatively only seed faces on cellsToRefine but that gives problems
02247     //  if no cells to refine)
02248     forAll(faceNeighbour, faceI)
02249     {
02250         // Check if face already handled in loop above
02251         if (!allFaceInfo[faceI].valid())
02252         {
02253             label own = faceOwner[faceI];
02254             label nei = faceNeighbour[faceI];
02255 
02256             // Seed face with transported data from highest cell.
02257 
02258             if (allCellInfo[own].count() > allCellInfo[nei].count())
02259             {
02260                 allFaceInfo[faceI].updateFace
02261                 (
02262                     mesh_,
02263                     faceI,
02264                     own,
02265                     allCellInfo[own],
02266                     FaceCellWave<refinementData>::propagationTol()
02267                 );
02268                 seedFaces.append(faceI);
02269                 seedFacesInfo.append(allFaceInfo[faceI]);
02270             }
02271             else if (allCellInfo[own].count() < allCellInfo[nei].count())
02272             {
02273                 allFaceInfo[faceI].updateFace
02274                 (
02275                     mesh_,
02276                     faceI,
02277                     nei,
02278                     allCellInfo[nei],
02279                     FaceCellWave<refinementData>::propagationTol()
02280                 );
02281                 seedFaces.append(faceI);
02282                 seedFacesInfo.append(allFaceInfo[faceI]);
02283             }
02284         }
02285     }
02286 
02287     // Seed all boundary faces with owner value. This is to make sure that
02288     // they are visited (probably only important for coupled faces since
02289     // these need to be visited from both sides)
02290     for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
02291     {
02292         // Check if face already handled in loop above
02293         if (!allFaceInfo[faceI].valid())
02294         {
02295             label own = faceOwner[faceI];
02296 
02297             // Seed face with transported data from owner.
02298             refinementData faceData;
02299             faceData.updateFace
02300             (
02301                 mesh_,
02302                 faceI,
02303                 own,
02304                 allCellInfo[own],
02305                 FaceCellWave<refinementData>::propagationTol()
02306             );
02307             seedFaces.append(faceI);
02308             seedFacesInfo.append(faceData);
02309         }
02310     }
02311 
02312 
02313     // face-cell-face transport engine
02314     FaceCellWave<refinementData> levelCalc
02315     (
02316         mesh_,
02317         allFaceInfo,
02318         allCellInfo
02319     );
02320 
02321     while(true)
02322     {
02323         if (debug)
02324         {
02325             Pout<< "hexRef8::consistentSlowRefinement : Seeded "
02326                 << seedFaces.size() << " faces between cells with different"
02327                 << " refinement level." << endl;
02328         }
02329 
02330         // Set seed faces
02331         levelCalc.setFaceInfo(seedFaces.shrink(), seedFacesInfo.shrink());
02332         seedFaces.clear();
02333         seedFacesInfo.clear();
02334 
02335         // Iterate until no change. Now 2:1 face difference should be satisfied
02336         levelCalc.iterate(mesh_.globalData().nTotalFaces());
02337 
02338 
02339         // Now check point-connected cells (face-connected cells already ok):
02340         // - get per point max of connected cells
02341         // - sync across coupled points
02342         // - check cells against above point max
02343 
02344         if (maxPointDiff == -1)
02345         {
02346             // No need to do any point checking.
02347             break;
02348         }
02349 
02350         // Determine per point the max cell level. (done as count, not
02351         // as cell level purely for ease)
02352         labelList maxPointCount(mesh_.nPoints(), 0);
02353 
02354         forAll(maxPointCount, pointI)
02355         {
02356             label& pLevel = maxPointCount[pointI];
02357 
02358             const labelList& pCells = mesh_.pointCells(pointI);
02359 
02360             forAll(pCells, i)
02361             {
02362                 pLevel = max(pLevel, allCellInfo[pCells[i]].count());
02363             }
02364         }
02365 
02366         // Sync maxPointCount to neighbour
02367         syncTools::syncPointList
02368         (
02369             mesh_,
02370             maxPointCount,
02371             maxEqOp<label>(),
02372             labelMin,           // null value
02373             false               // no separation
02374         );
02375 
02376         // Update allFaceInfo from maxPointCount for all points to check
02377         // (usually on boundary faces)
02378 
02379         // Per face the new refinement data
02380         Map<refinementData> changedFacesInfo(pointsToCheck.size());
02381 
02382         forAll(pointsToCheck, i)
02383         {
02384             label pointI = pointsToCheck[i];
02385 
02386             // Loop over all cells using the point and check whether their
02387             // refinement level is much less than the maximum.
02388 
02389             const labelList& pCells = mesh_.pointCells(pointI);
02390 
02391             forAll(pCells, pCellI)
02392             {
02393                 label cellI = pCells[pCellI];
02394 
02395                 refinementData& cellInfo = allCellInfo[cellI];
02396 
02397                 if
02398                 (
02399                    !cellInfo.isRefined()
02400                  && (
02401                         maxPointCount[pointI]
02402                       > cellInfo.count() + maxFaceDiff*maxPointDiff
02403                     )
02404                 )
02405                 {
02406                     // Mark cell for refinement
02407                     cellInfo.count() = cellInfo.refinementCount();
02408 
02409                     // Insert faces of cell as seed faces.
02410                     const cell& cFaces = mesh_.cells()[cellI];
02411 
02412                     forAll(cFaces, cFaceI)
02413                     {
02414                         label faceI = cFaces[cFaceI];
02415 
02416                         refinementData faceData;
02417                         faceData.updateFace
02418                         (
02419                             mesh_,
02420                             faceI,
02421                             cellI,
02422                             cellInfo,
02423                             FaceCellWave<refinementData>::propagationTol()
02424                         );
02425 
02426                         if (faceData.count() > allFaceInfo[faceI].count())
02427                         {
02428                             changedFacesInfo.insert(faceI, faceData);
02429                         }
02430                     }
02431                 }
02432             }
02433         }
02434 
02435         label nChanged = changedFacesInfo.size();
02436         reduce(nChanged, sumOp<label>());
02437 
02438         if (nChanged == 0)
02439         {
02440             break;
02441         }
02442 
02443 
02444         // Transfer into seedFaces, seedFacesInfo
02445         seedFaces.setCapacity(changedFacesInfo.size());
02446         seedFacesInfo.setCapacity(changedFacesInfo.size());
02447 
02448         forAllConstIter(Map<refinementData>, changedFacesInfo, iter)
02449         {
02450             seedFaces.append(iter.key());
02451             seedFacesInfo.append(iter());
02452         }
02453     }
02454 
02455 
02456     if (debug)
02457     {
02458         for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
02459         {
02460             label own = mesh_.faceOwner()[faceI];
02461             label ownLevel =
02462                 cellLevel_[own]
02463               + (allCellInfo[own].isRefined() ? 1 : 0);
02464 
02465             label nei = mesh_.faceNeighbour()[faceI];
02466             label neiLevel =
02467                 cellLevel_[nei]
02468               + (allCellInfo[nei].isRefined() ? 1 : 0);
02469 
02470             if (mag(ownLevel-neiLevel) > 1)
02471             {
02472                 dumpCell(own);
02473                 dumpCell(nei);
02474                 FatalErrorIn
02475                 (
02476                     "hexRef8::consistentSlowRefinement"
02477                     "(const label, const labelList&, const labelList&"
02478                     ", const label, const labelList&)"
02479                 )   << "cell:" << own
02480                     << " current level:" << cellLevel_[own]
02481                     << " current refData:" << allCellInfo[own]
02482                     << " level after refinement:" << ownLevel
02483                     << nl
02484                     << "neighbour cell:" << nei
02485                     << " current level:" << cellLevel_[nei]
02486                     << " current refData:" << allCellInfo[nei]
02487                     << " level after refinement:" << neiLevel
02488                     << nl
02489                     << "which does not satisfy 2:1 constraints anymore." << nl
02490                     << "face:" << faceI << " faceRefData:" << allFaceInfo[faceI]
02491                     << abort(FatalError);
02492             }
02493         }
02494 
02495 
02496         // Coupled faces. Swap owner level to get neighbouring cell level.
02497         // (only boundary faces of neiLevel used)
02498 
02499         labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
02500         labelList neiCount(mesh_.nFaces()-mesh_.nInternalFaces());
02501         labelList neiRefCount(mesh_.nFaces()-mesh_.nInternalFaces());
02502 
02503         forAll(neiLevel, i)
02504         {
02505             label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
02506             neiLevel[i] = cellLevel_[own];
02507             neiCount[i] = allCellInfo[own].count();
02508             neiRefCount[i] = allCellInfo[own].refinementCount();
02509         }
02510 
02511         // Swap to neighbour
02512         syncTools::swapBoundaryFaceList(mesh_, neiLevel, false);
02513         syncTools::swapBoundaryFaceList(mesh_, neiCount, false);
02514         syncTools::swapBoundaryFaceList(mesh_, neiRefCount, false);
02515 
02516         // Now we have neighbour value see which cells need refinement
02517         forAll(neiLevel, i)
02518         {
02519             label faceI = i+mesh_.nInternalFaces();
02520 
02521             label own = mesh_.faceOwner()[faceI];
02522             label ownLevel =
02523                 cellLevel_[own]
02524               + (allCellInfo[own].isRefined() ? 1 : 0);
02525 
02526             label nbrLevel =
02527                 neiLevel[i]
02528               + ((neiCount[i] >= neiRefCount[i]) ? 1 : 0);
02529 
02530             if (mag(ownLevel - nbrLevel) > 1)
02531             {
02532                 dumpCell(own);
02533                 label patchI = mesh_.boundaryMesh().whichPatch(faceI);
02534 
02535                 FatalErrorIn
02536                 (
02537                     "hexRef8::consistentSlowRefinement"
02538                     "(const label, const labelList&, const labelList&"
02539                     ", const label, const labelList&)"
02540                 )   << "Celllevel does not satisfy 2:1 constraint."
02541                     << " On coupled face "
02542                     << faceI
02543                     << " refData:" << allFaceInfo[faceI]
02544                     << " on patch " << patchI << " "
02545                     << mesh_.boundaryMesh()[patchI].name() << nl
02546                     << "owner cell " << own
02547                     << " current level:" << cellLevel_[own]
02548                     << " current count:" << allCellInfo[own].count()
02549                     << " current refCount:"
02550                     << allCellInfo[own].refinementCount()
02551                     << " level after refinement:" << ownLevel
02552                     << nl
02553                     << "(coupled) neighbour cell"
02554                     << " has current level:" << neiLevel[i]
02555                     << " current count:" << neiCount[i]
02556                     << " current refCount:" << neiRefCount[i]
02557                     << " level after refinement:" << nbrLevel
02558                     << abort(FatalError);
02559             }
02560         }
02561     }
02562 
02563     // Convert back to labelList of cells to refine.
02564 
02565     label nRefined = 0;
02566 
02567     forAll(allCellInfo, cellI)
02568     {
02569         if (allCellInfo[cellI].isRefined())
02570         {
02571             nRefined++;
02572         }
02573     }
02574 
02575     // Updated list of cells to refine
02576     labelList newCellsToRefine(nRefined);
02577     nRefined = 0;
02578 
02579     forAll(allCellInfo, cellI)
02580     {
02581         if (allCellInfo[cellI].isRefined())
02582         {
02583             newCellsToRefine[nRefined++] = cellI;
02584         }
02585     }
02586 
02587     if (debug)
02588     {
02589         Pout<< "hexRef8::consistentSlowRefinement : From "
02590             << cellsToRefine.size() << " to " << newCellsToRefine.size()
02591             << " cells to refine." << endl;
02592     }
02593 
02594     return newCellsToRefine;
02595 }
02596 
02597 
02598 Foam::labelList Foam::hexRef8::consistentSlowRefinement2
02599 (
02600     const label maxFaceDiff,
02601     const labelList& cellsToRefine,
02602     const labelList& facesToCheck
02603 ) const
02604 {
02605     const labelList& faceOwner = mesh_.faceOwner();
02606     const labelList& faceNeighbour = mesh_.faceNeighbour();
02607 
02608     if (maxFaceDiff <= 0)
02609     {
02610         FatalErrorIn
02611         (
02612             "hexRef8::consistentSlowRefinement2"
02613             "(const label, const labelList&, const labelList&)"
02614         )   << "Illegal maxFaceDiff " << maxFaceDiff << nl
02615             << "Value should be >= 1" << exit(FatalError);
02616     }
02617 
02618     const scalar level0Size = 2*maxFaceDiff*level0Edge_;
02619 
02620 
02621     // Bit tricky. Say we want a distance of three cells between two
02622     // consecutive refinement levels. This is done by using FaceCellWave to
02623     // transport out the 'refinement shell'. Anything inside the refinement
02624     // shell (given by a distance) gets marked for refinement.
02625 
02626     // Initial information about (distance to) cellLevel on all cells
02627     List<refinementDistanceData> allCellInfo(mesh_.nCells());
02628 
02629     // Initial information about (distance to) cellLevel on all faces
02630     List<refinementDistanceData> allFaceInfo(mesh_.nFaces());
02631 
02632 
02633     // Mark cells with wanted refinement level
02634     forAll(cellsToRefine, i)
02635     {
02636         label cellI = cellsToRefine[i];
02637 
02638         allCellInfo[cellI] = refinementDistanceData
02639         (
02640             level0Size,
02641             mesh_.cellCentres()[cellI],
02642             cellLevel_[cellI]+1             // wanted refinement
02643         );
02644     }
02645     // Mark all others with existing refinement level
02646     forAll(allCellInfo, cellI)
02647     {
02648         if (!allCellInfo[cellI].valid())
02649         {
02650             allCellInfo[cellI] = refinementDistanceData
02651             (
02652                 level0Size,
02653                 mesh_.cellCentres()[cellI],
02654                 cellLevel_[cellI]           // wanted refinement
02655             );
02656         }
02657     }
02658 
02659 
02660     // Labels of seed faces
02661     DynamicList<label> seedFaces(mesh_.nFaces()/100);
02662     // refinementLevel data on seed faces
02663     DynamicList<refinementDistanceData> seedFacesInfo(mesh_.nFaces()/100);
02664 
02665 
02666     const pointField& cc = mesh_.cellCentres();
02667 
02668     forAll(facesToCheck, i)
02669     {
02670         label faceI = facesToCheck[i];
02671 
02672         if (allFaceInfo[faceI].valid())
02673         {
02674             // Can only occur if face has already gone through loop below.
02675             FatalErrorIn
02676             (
02677                 "hexRef8::consistentSlowRefinement2"
02678                 "(const label, const labelList&, const labelList&)"
02679             )   << "Argument facesToCheck seems to have duplicate entries!"
02680                 << endl
02681                 << "face:" << faceI << " occurs at positions "
02682                 << findIndices(facesToCheck, faceI)
02683                 << abort(FatalError);
02684         }
02685 
02686         label own = faceOwner[faceI];
02687 
02688         label ownLevel =
02689         (
02690             allCellInfo[own].valid()
02691           ? allCellInfo[own].originLevel()
02692           : cellLevel_[own]
02693         );
02694 
02695         if (!mesh_.isInternalFace(faceI))
02696         {
02697             // Do as if boundary face would have neighbour with one higher
02698             // refinement level.
02699             const point& fc = mesh_.faceCentres()[faceI];
02700 
02701             refinementDistanceData neiData
02702             (
02703                 level0Size,
02704                 2*fc - cc[own],    // est'd cell centre
02705                 ownLevel+1
02706             );
02707 
02708             allFaceInfo[faceI].updateFace
02709             (
02710                 mesh_,
02711                 faceI,
02712                 own,        // not used (should be nei)
02713                 neiData,
02714                 FaceCellWave<refinementDistanceData>::propagationTol()
02715             );
02716         }
02717         else
02718         {
02719             label nei = faceNeighbour[faceI];
02720 
02721             label neiLevel =
02722             (
02723                 allCellInfo[nei].valid()
02724               ? allCellInfo[nei].originLevel()
02725               : cellLevel_[nei]
02726             );
02727 
02728             if (ownLevel == neiLevel)
02729             {
02730                 // Fake as if nei>own or own>nei (whichever one 'wins')
02731                 allFaceInfo[faceI].updateFace
02732                 (
02733                     mesh_,
02734                     faceI,
02735                     nei,
02736                     refinementDistanceData(level0Size, cc[nei], neiLevel+1),
02737                     FaceCellWave<refinementDistanceData>::propagationTol()
02738                 );
02739                 allFaceInfo[faceI].updateFace
02740                 (
02741                     mesh_,
02742                     faceI,
02743                     own,
02744                     refinementDistanceData(level0Size, cc[own], ownLevel+1),
02745                     FaceCellWave<refinementDistanceData>::propagationTol()
02746                 );
02747             }
02748             else
02749             {
02750                 // Difference in level anyway.
02751                 allFaceInfo[faceI].updateFace
02752                 (
02753                     mesh_,
02754                     faceI,
02755                     nei,
02756                     refinementDistanceData(level0Size, cc[nei], neiLevel),
02757                     FaceCellWave<refinementDistanceData>::propagationTol()
02758                 );
02759                 allFaceInfo[faceI].updateFace
02760                 (
02761                     mesh_,
02762                     faceI,
02763                     own,
02764                     refinementDistanceData(level0Size, cc[own], ownLevel),
02765                     FaceCellWave<refinementDistanceData>::propagationTol()
02766                 );
02767             }
02768         }
02769         seedFaces.append(faceI);
02770         seedFacesInfo.append(allFaceInfo[faceI]);
02771     }
02772 
02773 
02774     // Create some initial seeds to start walking from. This is only if there
02775     // are no facesToCheck.
02776     // Just seed with all faces inbetween different refinement levels for now
02777     forAll(faceNeighbour, faceI)
02778     {
02779         // Check if face already handled in loop above
02780         if (!allFaceInfo[faceI].valid())
02781         {
02782             label own = faceOwner[faceI];
02783 
02784             label ownLevel =
02785             (
02786                 allCellInfo[own].valid()
02787               ? allCellInfo[own].originLevel()
02788               : cellLevel_[own]
02789             );
02790 
02791             label nei = faceNeighbour[faceI];
02792 
02793             label neiLevel =
02794             (
02795                 allCellInfo[nei].valid()
02796               ? allCellInfo[nei].originLevel()
02797               : cellLevel_[nei]
02798             );
02799 
02800             if (ownLevel > neiLevel)
02801             {
02802                 // Set face to owner data. (since face not yet would be copy)
02803                 seedFaces.append(faceI);
02804                 allFaceInfo[faceI].updateFace
02805                 (
02806                     mesh_,
02807                     faceI,
02808                     own,
02809                     refinementDistanceData(level0Size, cc[own], ownLevel),
02810                     FaceCellWave<refinementDistanceData>::propagationTol()
02811                 );
02812                 seedFacesInfo.append(allFaceInfo[faceI]);
02813             }
02814             else if (neiLevel > ownLevel)
02815             {
02816                 seedFaces.append(faceI);
02817                 allFaceInfo[faceI].updateFace
02818                 (
02819                     mesh_,
02820                     faceI,
02821                     nei,
02822                     refinementDistanceData(level0Size, cc[nei], neiLevel),
02823                     FaceCellWave<refinementDistanceData>::propagationTol()
02824                 );
02825                 seedFacesInfo.append(allFaceInfo[faceI]);
02826             }
02827         }
02828     }
02829 
02830     seedFaces.shrink();
02831     seedFacesInfo.shrink();
02832 
02833     // face-cell-face transport engine
02834     FaceCellWave<refinementDistanceData> levelCalc
02835     (
02836         mesh_,
02837         seedFaces,
02838         seedFacesInfo,
02839         allFaceInfo,
02840         allCellInfo,
02841         mesh_.globalData().nTotalCells()
02842     );
02843 
02844 
02845     //if (debug)
02846     //{
02847     //    // Dump wanted level
02848     //    volScalarField wantedLevel
02849     //    (
02850     //        IOobject
02851     //        (
02852     //            "wantedLevel",
02853     //            fMesh.time().timeName(),
02854     //            fMesh,
02855     //            IOobject::NO_READ,
02856     //            IOobject::AUTO_WRITE,
02857     //            false
02858     //        ),
02859     //        fMesh,
02860     //        dimensionedScalar("zero", dimless, 0)
02861     //    );
02862     //
02863     //    forAll(wantedLevel, cellI)
02864     //    {
02865     //        wantedLevel[cellI] = allCellInfo[cellI].wantedLevel(cc[cellI]);
02866     //    }
02867     //
02868     //    Pout<< "Writing " << wantedLevel.objectPath() << endl;
02869     //    wantedLevel.write();
02870     //}
02871 
02872 
02873     // Convert back to labelList of cells to refine.
02874     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02875 
02876     // 1. Force original refinement cells to be picked up by setting the
02877     // originLevel of input cells to be a very large level (but within range
02878     // of 1<< shift inside refinementDistanceData::wantedLevel)
02879     forAll(cellsToRefine, i)
02880     {
02881         label cellI = cellsToRefine[i];
02882 
02883         allCellInfo[cellI].originLevel() = sizeof(label)*8-2;
02884         allCellInfo[cellI].origin() = cc[cellI];
02885     }
02886 
02887     // 2. Extend to 2:1. I don't understand yet why this is not done
02888     // 2. Extend to 2:1. For non-cube cells the scalar distance does not work
02889     // so make sure it at least provides 2:1.
02890     PackedBoolList refineCell(mesh_.nCells());
02891     forAll(allCellInfo, cellI)
02892     {
02893         label wanted = allCellInfo[cellI].wantedLevel(cc[cellI]);
02894 
02895         if (wanted > cellLevel_[cellI]+1)
02896         {
02897             refineCell.set(cellI, 1);
02898         }
02899     }
02900     faceConsistentRefinement(true, refineCell);
02901 
02902     while (true)
02903     {
02904         label nChanged = faceConsistentRefinement(true, refineCell);
02905 
02906         reduce(nChanged, sumOp<label>());
02907 
02908         if (debug)
02909         {
02910             Pout<< "hexRef8::consistentSlowRefinement2 : Changed " << nChanged
02911                 << " refinement levels due to 2:1 conflicts."
02912                 << endl;
02913         }
02914 
02915         if (nChanged == 0)
02916         {
02917             break;
02918         }
02919     }
02920 
02921     // 3. Convert back to labelList.
02922     label nRefined = 0;
02923 
02924     forAll(refineCell, cellI)
02925     {
02926         if (refineCell.get(cellI) == 1)
02927         {
02928             nRefined++;
02929         }
02930     }
02931 
02932     labelList newCellsToRefine(nRefined);
02933     nRefined = 0;
02934 
02935     forAll(refineCell, cellI)
02936     {
02937         if (refineCell.get(cellI) == 1)
02938         {
02939             newCellsToRefine[nRefined++] = cellI;
02940         }
02941     }
02942 
02943     if (debug)
02944     {
02945         Pout<< "hexRef8::consistentSlowRefinement2 : From "
02946             << cellsToRefine.size() << " to " << newCellsToRefine.size()
02947             << " cells to refine." << endl;
02948 
02949         // Check that newCellsToRefine obeys at least 2:1.
02950 
02951         {
02952             cellSet cellsIn(mesh_, "cellsToRefineIn", cellsToRefine);
02953             Pout<< "hexRef8::consistentSlowRefinement2 : writing "
02954                 << cellsIn.size() << " to cellSet "
02955                 << cellsIn.objectPath() << endl;
02956             cellsIn.write();
02957         }
02958         {
02959             cellSet cellsOut(mesh_, "cellsToRefineOut", newCellsToRefine);
02960             Pout<< "hexRef8::consistentSlowRefinement2 : writing "
02961                 << cellsOut.size() << " to cellSet "
02962                 << cellsOut.objectPath() << endl;
02963             cellsOut.write();
02964         }
02965 
02966         // Extend to 2:1
02967         PackedBoolList refineCell(mesh_.nCells());
02968         forAll(newCellsToRefine, i)
02969         {
02970             refineCell.set(newCellsToRefine[i], 1);
02971         }
02972         const PackedBoolList savedRefineCell(refineCell);
02973 
02974         label nChanged = faceConsistentRefinement(true, refineCell);
02975 
02976         {
02977             cellSet cellsOut2
02978             (
02979                 mesh_, "cellsToRefineOut2", newCellsToRefine.size()
02980             );
02981             forAll(refineCell, cellI)
02982             {
02983                 if (refineCell.get(cellI) == 1)
02984                 {
02985                     cellsOut2.insert(cellI);
02986                 }
02987             }
02988             Pout<< "hexRef8::consistentSlowRefinement2 : writing "
02989                 << cellsOut2.size() << " to cellSet "
02990                 << cellsOut2.objectPath() << endl;
02991             cellsOut2.write();
02992         }
02993 
02994         if (nChanged > 0)
02995         {
02996             forAll(refineCell, cellI)
02997             {
02998                 if
02999                 (
03000                     refineCell.get(cellI) == 1
03001                  && savedRefineCell.get(cellI) == 0
03002                 )
03003                 {
03004                     dumpCell(cellI);
03005                     FatalErrorIn
03006                     (
03007                         "hexRef8::consistentSlowRefinement2"
03008                         "(const label, const labelList&, const labelList&)"
03009                     )   << "Cell:" << cellI << " cc:"
03010                         << mesh_.cellCentres()[cellI]
03011                         << " was not marked for refinement but does not obey"
03012                         << " 2:1 constraints."
03013                         << abort(FatalError);
03014                 }
03015             }
03016         }
03017     }
03018 
03019     return newCellsToRefine;
03020 }
03021 
03022 
03023 // Top level driver to insert topo changes to do all refinement.
03024 Foam::labelListList Foam::hexRef8::setRefinement
03025 (
03026     const labelList& cellLabels,
03027     polyTopoChange& meshMod
03028 )
03029 {
03030     if (debug)
03031     {
03032         Pout<< "hexRef8::setRefinement :"
03033             << " Checking initial mesh just to make sure" << endl;
03034 
03035         checkMesh();
03036         // Cannot call checkRefinementlevels since hanging points might
03037         // get triggered by the mesher after subsetting.
03038         //checkRefinementLevels(-1, labelList(0));
03039     }
03040 
03041     // Clear any saved point/cell data.
03042     savedPointLevel_.clear();
03043     savedCellLevel_.clear();
03044 
03045 
03046     // New point/cell level. Copy of pointLevel for existing points.
03047     DynamicList<label> newCellLevel(cellLevel_.size());
03048     forAll(cellLevel_, cellI)
03049     {
03050         newCellLevel.append(cellLevel_[cellI]);
03051     }
03052     DynamicList<label> newPointLevel(pointLevel_.size());
03053     forAll(pointLevel_, pointI)
03054     {
03055         newPointLevel.append(pointLevel_[pointI]);
03056     }
03057 
03058 
03059     if (debug)
03060     {
03061         Pout<< "hexRef8::setRefinement :"
03062             << " Allocating " << cellLabels.size() << " cell midpoints."
03063             << endl;
03064     }
03065 
03066 
03067     // Mid point per refined cell.
03068     // -1 : not refined
03069     // >=0: label of mid point.
03070     labelList cellMidPoint(mesh_.nCells(), -1);
03071 
03072     forAll(cellLabels, i)
03073     {
03074         label cellI = cellLabels[i];
03075 
03076         label anchorPointI = mesh_.faces()[mesh_.cells()[cellI][0]][0];
03077 
03078         cellMidPoint[cellI] = meshMod.setAction
03079         (
03080             polyAddPoint
03081             (
03082                 mesh_.cellCentres()[cellI],     // point
03083                 anchorPointI,                   // master point
03084                 -1,                             // zone for point
03085                 true                            // supports a cell
03086             )
03087         );
03088 
03089         newPointLevel(cellMidPoint[cellI]) = cellLevel_[cellI]+1;
03090     }
03091 
03092 
03093     if (debug)
03094     {
03095         cellSet splitCells(mesh_, "splitCells", cellLabels.size());
03096 
03097         forAll(cellMidPoint, cellI)
03098         {
03099             if (cellMidPoint[cellI] >= 0)
03100             {
03101                 splitCells.insert(cellI);
03102             }
03103         }
03104 
03105         Pout<< "hexRef8::setRefinement : Dumping " << splitCells.size()
03106             << " cells to split to cellSet " << splitCells.objectPath()
03107             << endl;
03108 
03109         splitCells.write();
03110     }
03111 
03112 
03113 
03114     // Split edges
03115     // ~~~~~~~~~~~
03116 
03117     if (debug)
03118     {
03119         Pout<< "hexRef8::setRefinement :"
03120             << " Allocating edge midpoints."
03121             << endl;
03122     }
03123 
03124     // Unrefined edges are ones between cellLevel or lower points.
03125     // If any cell using this edge gets split then the edge needs to be split.
03126 
03127     // -1  : no need to split edge
03128     // >=0 : label of introduced mid point
03129     labelList edgeMidPoint(mesh_.nEdges(), -1);
03130 
03131     // Note: Loop over cells to be refined or edges?
03132     forAll(cellMidPoint, cellI)
03133     {
03134         if (cellMidPoint[cellI] >= 0)
03135         {
03136             const labelList& cEdges = mesh_.cellEdges(cellI);
03137 
03138             forAll(cEdges, i)
03139             {
03140                 label edgeI = cEdges[i];
03141 
03142                 const edge& e = mesh_.edges()[edgeI];
03143 
03144                 if
03145                 (
03146                     pointLevel_[e[0]] <= cellLevel_[cellI]
03147                  && pointLevel_[e[1]] <= cellLevel_[cellI]
03148                 )
03149                 {
03150                     edgeMidPoint[edgeI] = 12345;    // mark need for splitting
03151                 }
03152             }
03153         }
03154     }
03155 
03156     // Synchronize edgeMidPoint across coupled patches. Take max so that
03157     // any split takes precedence.
03158     syncTools::syncEdgeList
03159     (
03160         mesh_,
03161         edgeMidPoint,
03162         maxEqOp<label>(),
03163         labelMin,
03164         false               // no separation
03165     );
03166 
03167 
03168     // Introduce edge points
03169     // ~~~~~~~~~~~~~~~~~~~~~
03170 
03171     {
03172         // Phase 1: calculate midpoints and sync.
03173         // This needs doing for if people do not write binary and we slowly
03174         // get differences.
03175 
03176         pointField edgeMids(mesh_.nEdges(), point(-GREAT, -GREAT, -GREAT));
03177 
03178         forAll(edgeMidPoint, edgeI)
03179         {
03180             if (edgeMidPoint[edgeI] >= 0)
03181             {
03182                 // Edge marked to be split.
03183                 edgeMids[edgeI] = mesh_.edges()[edgeI].centre(mesh_.points());
03184             }
03185         }
03186         syncTools::syncEdgeList
03187         (
03188             mesh_,
03189             edgeMids,
03190             maxEqOp<vector>(),
03191             point(-GREAT, -GREAT, -GREAT),
03192             true               // apply separation
03193         );
03194 
03195 
03196         // Phase 2: introduce points at the synced locations.
03197         forAll(edgeMidPoint, edgeI)
03198         {
03199             if (edgeMidPoint[edgeI] >= 0)
03200             {
03201                 // Edge marked to be split. Replace edgeMidPoint with actual
03202                 // point label.
03203 
03204                 const edge& e = mesh_.edges()[edgeI];
03205 
03206                 edgeMidPoint[edgeI] = meshMod.setAction
03207                 (
03208                     polyAddPoint
03209                     (
03210                         edgeMids[edgeI],            // point
03211                         e[0],                       // master point
03212                         -1,                         // zone for point
03213                         true                        // supports a cell
03214                     )
03215                 );
03216 
03217                 newPointLevel(edgeMidPoint[edgeI]) =
03218                     max
03219                     (
03220                         pointLevel_[e[0]],
03221                         pointLevel_[e[1]]
03222                     )
03223                   + 1;
03224             }
03225         }
03226     }
03227 
03228     if (debug)
03229     {
03230         OFstream str(mesh_.time().path()/"edgeMidPoint.obj");
03231 
03232         forAll(edgeMidPoint, edgeI)
03233         {
03234             if (edgeMidPoint[edgeI] >= 0)
03235             {
03236                 const edge& e = mesh_.edges()[edgeI];
03237 
03238                 meshTools::writeOBJ(str, e.centre(mesh_.points()));
03239             }
03240         }
03241 
03242         Pout<< "hexRef8::setRefinement :"
03243             << " Dumping edge centres to split to file " << str.name() << endl;
03244     }
03245 
03246 
03247     // Calculate face level
03248     // ~~~~~~~~~~~~~~~~~~~~
03249     // (after splitting)
03250 
03251     if (debug)
03252     {
03253         Pout<< "hexRef8::setRefinement :"
03254             << " Allocating face midpoints."
03255             << endl;
03256     }
03257 
03258     // Face anchor level. There are guaranteed 4 points with level
03259     // <= anchorLevel. These are the corner points.
03260     labelList faceAnchorLevel(mesh_.nFaces());
03261 
03262     for (label faceI = 0; faceI < mesh_.nFaces(); faceI++)
03263     {
03264         faceAnchorLevel[faceI] = getAnchorLevel(faceI);
03265     }
03266 
03267     // -1  : no need to split face
03268     // >=0 : label of introduced mid point
03269     labelList faceMidPoint(mesh_.nFaces(), -1);
03270 
03271 
03272     // Internal faces: look at cells on both sides. Uniquely determined since
03273     // face itself guaranteed to be same level as most refined neighbour.
03274     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
03275     {
03276         if (faceAnchorLevel[faceI] >= 0)
03277         {
03278             label own = mesh_.faceOwner()[faceI];
03279             label ownLevel = cellLevel_[own];
03280             label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
03281 
03282             label nei = mesh_.faceNeighbour()[faceI];
03283             label neiLevel = cellLevel_[nei];
03284             label newNeiLevel = neiLevel + (cellMidPoint[nei] >= 0 ? 1 : 0);
03285 
03286             if
03287             (
03288                 newOwnLevel > faceAnchorLevel[faceI]
03289              || newNeiLevel > faceAnchorLevel[faceI]
03290             )
03291             {
03292                 faceMidPoint[faceI] = 12345;    // mark to be split
03293             }
03294         }
03295     }
03296 
03297     // Coupled patches handled like internal faces except now all information
03298     // from neighbour comes from across processor.
03299     // Boundary faces are more complicated since the boundary face can
03300     // be more refined than its owner (or neighbour for coupled patches)
03301     // (does not happen if refining/unrefining only, but does e.g. when
03302     //  refinining and subsetting)
03303 
03304     {
03305         labelList newNeiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
03306 
03307         forAll(newNeiLevel, i)
03308         {
03309             label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
03310             label ownLevel = cellLevel_[own];
03311             label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
03312 
03313             newNeiLevel[i] = newOwnLevel;
03314         }
03315 
03316         // Swap.
03317         syncTools::swapBoundaryFaceList(mesh_, newNeiLevel, false);
03318 
03319         // So now we have information on the neighbour.
03320 
03321         forAll(newNeiLevel, i)
03322         {
03323             label faceI = i+mesh_.nInternalFaces();
03324 
03325             if (faceAnchorLevel[faceI] >= 0)
03326             {
03327                 label own = mesh_.faceOwner()[faceI];
03328                 label ownLevel = cellLevel_[own];
03329                 label newOwnLevel = ownLevel + (cellMidPoint[own] >= 0 ? 1 : 0);
03330 
03331                 if
03332                 (
03333                     newOwnLevel > faceAnchorLevel[faceI]
03334                  || newNeiLevel[i] > faceAnchorLevel[faceI]
03335                 )
03336                 {
03337                     faceMidPoint[faceI] = 12345;    // mark to be split
03338                 }
03339             }
03340         }
03341     }
03342 
03343 
03344     // Synchronize faceMidPoint across coupled patches. (logical or)
03345     syncTools::syncFaceList
03346     (
03347         mesh_,
03348         faceMidPoint,
03349         maxEqOp<label>(),
03350         false
03351     );
03352 
03353 
03354 
03355     // Introduce face points
03356     // ~~~~~~~~~~~~~~~~~~~~~
03357 
03358     {
03359         // Phase 1: determine mid points and sync. See comment for edgeMids
03360         // above
03361         pointField bFaceMids
03362         (
03363             mesh_.nFaces()-mesh_.nInternalFaces(),
03364             point(-GREAT, -GREAT, -GREAT)
03365         );
03366 
03367         forAll(bFaceMids, i)
03368         {
03369             label faceI = i+mesh_.nInternalFaces();
03370 
03371             if (faceMidPoint[faceI] >= 0)
03372             {
03373                 bFaceMids[i] = mesh_.faceCentres()[faceI];
03374             }
03375         }
03376         syncTools::syncBoundaryFaceList
03377         (
03378             mesh_,
03379             bFaceMids,
03380             maxEqOp<vector>(),
03381             true               // apply separation
03382         );
03383 
03384         forAll(faceMidPoint, faceI)
03385         {
03386             if (faceMidPoint[faceI] >= 0)
03387             {
03388                 // Face marked to be split. Replace faceMidPoint with actual
03389                 // point label.
03390 
03391                 const face& f = mesh_.faces()[faceI];
03392 
03393                 faceMidPoint[faceI] = meshMod.setAction
03394                 (
03395                     polyAddPoint
03396                     (
03397                         (
03398                             faceI < mesh_.nInternalFaces()
03399                           ? mesh_.faceCentres()[faceI]
03400                           : bFaceMids[faceI-mesh_.nInternalFaces()]
03401                         ),                          // point
03402                         f[0],                       // master point
03403                         -1,                         // zone for point
03404                         true                        // supports a cell
03405                     )
03406                 );
03407 
03408                 // Determine the level of the corner points and midpoint will
03409                 // be one higher.
03410                 newPointLevel(faceMidPoint[faceI]) = faceAnchorLevel[faceI]+1;
03411             }
03412         }
03413     }
03414 
03415     if (debug)
03416     {
03417         faceSet splitFaces(mesh_, "splitFaces", cellLabels.size());
03418 
03419         forAll(faceMidPoint, faceI)
03420         {
03421             if (faceMidPoint[faceI] >= 0)
03422             {
03423                 splitFaces.insert(faceI);
03424             }
03425         }
03426 
03427         Pout<< "hexRef8::setRefinement : Dumping " << splitFaces.size()
03428             << " faces to split to faceSet " << splitFaces.objectPath() << endl;
03429 
03430         splitFaces.write();
03431     }
03432 
03433 
03434     // Information complete
03435     // ~~~~~~~~~~~~~~~~~~~~
03436     // At this point we have all the information we need. We should no
03437     // longer reference the cellLabels to refine. All the information is:
03438     // - cellMidPoint >= 0 : cell needs to be split
03439     // - faceMidPoint >= 0 : face needs to be split
03440     // - edgeMidPoint >= 0 : edge needs to be split
03441 
03442 
03443 
03444     // Get the corner/anchor points
03445     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03446 
03447     if (debug)
03448     {
03449         Pout<< "hexRef8::setRefinement :"
03450             << " Finding cell anchorPoints (8 per cell)"
03451             << endl;
03452     }
03453 
03454     // There will always be 8 points on the hex that have were introduced
03455     // with the hex and will have the same or lower refinement level.
03456 
03457     // Per cell the 8 corner points.
03458     labelListList cellAnchorPoints(mesh_.nCells());
03459 
03460     {
03461         labelList nAnchorPoints(mesh_.nCells(), 0);
03462 
03463         forAll(cellMidPoint, cellI)
03464         {
03465             if (cellMidPoint[cellI] >= 0)
03466             {
03467                 cellAnchorPoints[cellI].setSize(8);
03468             }
03469         }
03470 
03471         forAll(pointLevel_, pointI)
03472         {
03473             const labelList& pCells = mesh_.pointCells(pointI);
03474 
03475             forAll(pCells, pCellI)
03476             {
03477                 label cellI = pCells[pCellI];
03478 
03479                 if
03480                 (
03481                     cellMidPoint[cellI] >= 0
03482                  && pointLevel_[pointI] <= cellLevel_[cellI]
03483                 )
03484                 {
03485                     if (nAnchorPoints[cellI] == 8)
03486                     {
03487                         dumpCell(cellI);
03488                         FatalErrorIn
03489                         (
03490                             "hexRef8::setRefinement(const labelList&"
03491                             ", polyTopoChange&)"
03492                         )   << "cell " << cellI
03493                             << " of level " << cellLevel_[cellI]
03494                             << " uses more than 8 points of equal or"
03495                             << " lower level" << nl
03496                             << "Points so far:" << cellAnchorPoints[cellI]
03497                             << abort(FatalError);
03498                     }
03499 
03500                     cellAnchorPoints[cellI][nAnchorPoints[cellI]++] = pointI;
03501                 }
03502             }
03503         }
03504 
03505         forAll(cellMidPoint, cellI)
03506         {
03507             if (cellMidPoint[cellI] >= 0)
03508             {
03509                 if (nAnchorPoints[cellI] != 8)
03510                 {
03511                     dumpCell(cellI);
03512 
03513                     const labelList& cPoints = mesh_.cellPoints(cellI);
03514 
03515                     FatalErrorIn
03516                     (
03517                         "hexRef8::setRefinement(const labelList&"
03518                         ", polyTopoChange&)"
03519                     )   << "cell " << cellI
03520                         << " of level " << cellLevel_[cellI]
03521                         << " does not seem to have 8 points of equal or"
03522                         << " lower level" << endl
03523                         << "cellPoints:" << cPoints << endl
03524                         << "pointLevels:"
03525                         << UIndirectList<label>(pointLevel_, cPoints)() << endl
03526                         << abort(FatalError);
03527                 }
03528             }
03529         }
03530     }
03531 
03532 
03533     // Add the cells
03534     // ~~~~~~~~~~~~~
03535 
03536     if (debug)
03537     {
03538         Pout<< "hexRef8::setRefinement :"
03539             << " Adding cells (1 per anchorPoint)"
03540             << endl;
03541     }
03542 
03543     // Per cell the 7 added cells (+ original cell)
03544     labelListList cellAddedCells(mesh_.nCells());
03545 
03546     forAll(cellAnchorPoints, cellI)
03547     {
03548         const labelList& cAnchors = cellAnchorPoints[cellI];
03549 
03550         if (cAnchors.size() == 8)
03551         {
03552             labelList& cAdded = cellAddedCells[cellI];
03553             cAdded.setSize(8);
03554 
03555             // Original cell at 0
03556             cAdded[0] = cellI;
03557 
03558             // Update cell level
03559             newCellLevel[cellI] = cellLevel_[cellI]+1;
03560 
03561 
03562             for (label i = 1; i < 8; i++)
03563             {
03564                 cAdded[i] = meshMod.setAction
03565                 (
03566                     polyAddCell
03567                     (
03568                         -1,                                 // master point
03569                         -1,                                 // master edge
03570                         -1,                                 // master face
03571                         cellI,                              // master cell
03572                         mesh_.cellZones().whichZone(cellI)  // zone for cell
03573                     )
03574                 );
03575 
03576                 newCellLevel(cAdded[i]) = cellLevel_[cellI]+1;
03577             }
03578         }
03579     }
03580 
03581 
03582     // Faces
03583     // ~~~~~
03584     // 1. existing faces that get split (into four always)
03585     // 2. existing faces that do not get split but only edges get split
03586     // 3. existing faces that do not get split but get new owner/neighbour
03587     // 4. new internal faces inside split cells.
03588 
03589     if (debug)
03590     {
03591         Pout<< "hexRef8::setRefinement :"
03592             << " Marking faces to be handled"
03593             << endl;
03594     }
03595 
03596     // Get all affected faces.
03597     PackedBoolList affectedFace(mesh_.nFaces());
03598 
03599     {
03600         forAll(cellMidPoint, cellI)
03601         {
03602             if (cellMidPoint[cellI] >= 0)
03603             {
03604                 const cell& cFaces = mesh_.cells()[cellI];
03605 
03606                 forAll(cFaces, i)
03607                 {
03608                     affectedFace.set(cFaces[i], 1);
03609                 }
03610             }
03611         }
03612 
03613         forAll(faceMidPoint, faceI)
03614         {
03615             if (faceMidPoint[faceI] >= 0)
03616             {
03617                 affectedFace.set(faceI, 1);
03618             }
03619         }
03620 
03621         forAll(edgeMidPoint, edgeI)
03622         {
03623             if (edgeMidPoint[edgeI] >= 0)
03624             {
03625                 const labelList& eFaces = mesh_.edgeFaces(edgeI);
03626 
03627                 forAll(eFaces, i)
03628                 {
03629                     affectedFace.set(eFaces[i], 1);
03630                 }
03631             }
03632         }
03633     }
03634 
03635 
03636     // 1. Faces that get split
03637     // ~~~~~~~~~~~~~~~~~~~~~~~
03638 
03639     if (debug)
03640     {
03641         Pout<< "hexRef8::setRefinement : Splitting faces" << endl;
03642     }
03643 
03644     forAll(faceMidPoint, faceI)
03645     {
03646         if (faceMidPoint[faceI] >= 0 && affectedFace.get(faceI) == 1)
03647         {
03648             // Face needs to be split and hasn't yet been done in some way
03649             // (affectedFace - is impossible since this is first change but
03650             //  just for completeness)
03651 
03652             const face& f = mesh_.faces()[faceI];
03653 
03654             // Has original faceI been used (three faces added, original gets
03655             // modified)
03656             bool modifiedFace = false;
03657 
03658             label anchorLevel = faceAnchorLevel[faceI];
03659 
03660             face newFace(4);
03661 
03662             forAll(f, fp)
03663             {
03664                 label pointI = f[fp];
03665 
03666                 if (pointLevel_[pointI] <= anchorLevel)
03667                 {
03668                     // point is anchor. Start collecting face.
03669 
03670                     DynamicList<label> faceVerts(4);
03671 
03672                     faceVerts.append(pointI);
03673 
03674                     // Walk forward to mid point.
03675                     // - if next is +2 midpoint is +1
03676                     // - if next is +1 it is midpoint
03677                     // - if next is +0 there has to be edgeMidPoint
03678 
03679                     walkFaceToMid
03680                     (
03681                         edgeMidPoint,
03682                         anchorLevel,
03683                         faceI,
03684                         fp,
03685                         faceVerts
03686                     );
03687 
03688                     faceVerts.append(faceMidPoint[faceI]);
03689 
03690                     walkFaceFromMid
03691                     (
03692                         edgeMidPoint,
03693                         anchorLevel,
03694                         faceI,
03695                         fp,
03696                         faceVerts
03697                     );
03698 
03699                     // Convert dynamiclist to face.
03700                     newFace.transfer(faceVerts);
03701 
03702                     //Pout<< "Split face:" << faceI << " verts:" << f
03703                     //    << " into quad:" << newFace << endl;
03704 
03705                     // Get new owner/neighbour
03706                     label own, nei;
03707                     getFaceNeighbours
03708                     (
03709                         cellAnchorPoints,
03710                         cellAddedCells,
03711                         faceI,
03712                         pointI,          // Anchor point
03713 
03714                         own,
03715                         nei
03716                     );
03717 
03718 
03719                     if (debug)
03720                     {
03721                         if (mesh_.isInternalFace(faceI))
03722                         {
03723                             label oldOwn = mesh_.faceOwner()[faceI];
03724                             label oldNei = mesh_.faceNeighbour()[faceI];
03725 
03726                             checkInternalOrientation
03727                             (
03728                                 meshMod,
03729                                 oldOwn,
03730                                 faceI,
03731                                 mesh_.cellCentres()[oldOwn],
03732                                 mesh_.cellCentres()[oldNei],
03733                                 newFace
03734                             );
03735                         }
03736                         else
03737                         {
03738                             label oldOwn = mesh_.faceOwner()[faceI];
03739 
03740                             checkBoundaryOrientation
03741                             (
03742                                 meshMod,
03743                                 oldOwn,
03744                                 faceI,
03745                                 mesh_.cellCentres()[oldOwn],
03746                                 mesh_.faceCentres()[faceI],
03747                                 newFace
03748                             );
03749                         }
03750                     }
03751 
03752 
03753                     if (!modifiedFace)
03754                     {
03755                         modifiedFace = true;
03756 
03757                         modFace(meshMod, faceI, newFace, own, nei);
03758                     }
03759                     else
03760                     {
03761                         addFace(meshMod, faceI, newFace, own, nei);
03762                     }
03763                 }
03764             }
03765 
03766             // Mark face as having been handled
03767             affectedFace.set(faceI, 0);
03768         }
03769     }
03770 
03771 
03772     // 2. faces that do not get split but use edges that get split
03773     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03774 
03775     if (debug)
03776     {
03777         Pout<< "hexRef8::setRefinement :"
03778             << " Adding edge splits to unsplit faces"
03779             << endl;
03780     }
03781 
03782     DynamicList<label> eFacesStorage;
03783     DynamicList<label> fEdgesStorage;
03784 
03785     forAll(edgeMidPoint, edgeI)
03786     {
03787         if (edgeMidPoint[edgeI] >= 0)
03788         {
03789             // Split edge. Check that face not already handled above.
03790 
03791             const labelList& eFaces = mesh_.edgeFaces(edgeI, eFacesStorage);
03792 
03793             forAll(eFaces, i)
03794             {
03795                 label faceI = eFaces[i];
03796 
03797                 if (faceMidPoint[faceI] < 0 && affectedFace.get(faceI) == 1)
03798                 {
03799                     // Unsplit face. Add edge splits to face.
03800 
03801                     const face& f = mesh_.faces()[faceI];
03802                     const labelList& fEdges = mesh_.faceEdges
03803                     (
03804                         faceI,
03805                         fEdgesStorage
03806                     );
03807 
03808                     DynamicList<label> newFaceVerts(f.size());
03809 
03810                     forAll(f, fp)
03811                     {
03812                         newFaceVerts.append(f[fp]);
03813 
03814                         label edgeI = fEdges[fp];
03815 
03816                         if (edgeMidPoint[edgeI] >= 0)
03817                         {
03818                             newFaceVerts.append(edgeMidPoint[edgeI]);
03819                         }
03820                     }
03821 
03822                     face newFace;
03823                     newFace.transfer(newFaceVerts);
03824 
03825                     // The point with the lowest level should be an anchor
03826                     // point of the neighbouring cells.
03827                     label anchorFp = findMinLevel(f);
03828 
03829                     label own, nei;
03830                     getFaceNeighbours
03831                     (
03832                         cellAnchorPoints,
03833                         cellAddedCells,
03834                         faceI,
03835                         f[anchorFp],          // Anchor point
03836 
03837                         own,
03838                         nei
03839                     );
03840 
03841 
03842                     if (debug)
03843                     {
03844                         if (mesh_.isInternalFace(faceI))
03845                         {
03846                             label oldOwn = mesh_.faceOwner()[faceI];
03847                             label oldNei = mesh_.faceNeighbour()[faceI];
03848 
03849                             checkInternalOrientation
03850                             (
03851                                 meshMod,
03852                                 oldOwn,
03853                                 faceI,
03854                                 mesh_.cellCentres()[oldOwn],
03855                                 mesh_.cellCentres()[oldNei],
03856                                 newFace
03857                             );
03858                         }
03859                         else
03860                         {
03861                             label oldOwn = mesh_.faceOwner()[faceI];
03862 
03863                             checkBoundaryOrientation
03864                             (
03865                                 meshMod,
03866                                 oldOwn,
03867                                 faceI,
03868                                 mesh_.cellCentres()[oldOwn],
03869                                 mesh_.faceCentres()[faceI],
03870                                 newFace
03871                             );
03872                         }
03873                     }
03874 
03875                     modFace(meshMod, faceI, newFace, own, nei);
03876 
03877                     // Mark face as having been handled
03878                     affectedFace.set(faceI, 0);
03879                 }
03880             }
03881         }
03882     }
03883 
03884 
03885     // 3. faces that do not get split but whose owner/neighbour change
03886     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03887 
03888     if (debug)
03889     {
03890         Pout<< "hexRef8::setRefinement :"
03891             << " Changing owner/neighbour for otherwise unaffected faces"
03892             << endl;
03893     }
03894 
03895     forAll(affectedFace, faceI)
03896     {
03897         if (affectedFace.get(faceI) == 1)
03898         {
03899             const face& f = mesh_.faces()[faceI];
03900 
03901             // The point with the lowest level should be an anchor
03902             // point of the neighbouring cells.
03903             label anchorFp = findMinLevel(f);
03904 
03905             label own, nei;
03906             getFaceNeighbours
03907             (
03908                 cellAnchorPoints,
03909                 cellAddedCells,
03910                 faceI,
03911                 f[anchorFp],          // Anchor point
03912 
03913                 own,
03914                 nei
03915             );
03916 
03917             modFace(meshMod, faceI, f, own, nei);
03918 
03919             // Mark face as having been handled
03920             affectedFace.set(faceI, 0);
03921         }
03922     }
03923 
03924 
03925     // 4. new internal faces inside split cells.
03926     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03927 
03928 
03929     // This is the hard one. We have to find the splitting points between
03930     // the anchor points. But the edges between the anchor points might have
03931     // been split (into two,three or four edges).
03932 
03933     if (debug)
03934     {
03935         Pout<< "hexRef8::setRefinement :"
03936             << " Create new internal faces for split cells"
03937             << endl;
03938     }
03939 
03940     forAll(cellMidPoint, cellI)
03941     {
03942         if (cellMidPoint[cellI] >= 0)
03943         {
03944             createInternalFaces
03945             (
03946                 cellAnchorPoints,
03947                 cellAddedCells,
03948                 cellMidPoint,
03949                 faceMidPoint,
03950                 faceAnchorLevel,
03951                 edgeMidPoint,
03952                 cellI,
03953                 meshMod
03954             );
03955         }
03956     }
03957 
03958     // Extend pointLevels and cellLevels for the new cells. Could also be done
03959     // in updateMesh but saves passing cellAddedCells out of this routine.
03960 
03961     // Check
03962     if (debug)
03963     {
03964         label minPointI = labelMax;
03965         label maxPointI = labelMin;
03966 
03967         forAll(cellMidPoint, cellI)
03968         {
03969             if (cellMidPoint[cellI] >= 0)
03970             {
03971                 minPointI = min(minPointI, cellMidPoint[cellI]);
03972                 maxPointI = max(maxPointI, cellMidPoint[cellI]);
03973             }
03974         }
03975         forAll(faceMidPoint, faceI)
03976         {
03977             if (faceMidPoint[faceI] >= 0)
03978             {
03979                 minPointI = min(minPointI, faceMidPoint[faceI]);
03980                 maxPointI = max(maxPointI, faceMidPoint[faceI]);
03981             }
03982         }
03983         forAll(edgeMidPoint, edgeI)
03984         {
03985             if (edgeMidPoint[edgeI] >= 0)
03986             {
03987                 minPointI = min(minPointI, edgeMidPoint[edgeI]);
03988                 maxPointI = max(maxPointI, edgeMidPoint[edgeI]);
03989             }
03990         }
03991 
03992         if (minPointI != labelMax && minPointI != mesh_.nPoints())
03993         {
03994             FatalErrorIn("hexRef8::setRefinement(..)")
03995                 << "Added point labels not consecutive to existing mesh points."
03996                 << nl
03997                 << "mesh_.nPoints():" << mesh_.nPoints()
03998                 << " minPointI:" << minPointI
03999                 << " maxPointI:" << maxPointI
04000                 << abort(FatalError);
04001         }
04002     }
04003 
04004     pointLevel_.transfer(newPointLevel);
04005     cellLevel_.transfer(newCellLevel);
04006 
04007     // Mark files as changed
04008     setInstance(mesh_.facesInstance());
04009 
04010 
04011     // Update the live split cells tree.
04012     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
04013 
04014     // New unrefinement structure
04015     if (history_.active())
04016     {
04017         if (debug)
04018         {
04019             Pout<< "hexRef8::setRefinement :"
04020                 << " Updating refinement history to " << cellLevel_.size()
04021                 << " cells" << endl;
04022         }
04023 
04024         // Extend refinement history for new cells
04025         history_.resize(cellLevel_.size());
04026 
04027         forAll(cellAddedCells, cellI)
04028         {
04029             const labelList& addedCells = cellAddedCells[cellI];
04030 
04031             if (addedCells.size())
04032             {
04033                 // Cell was split.
04034                 history_.storeSplit(cellI, addedCells);
04035             }
04036         }
04037     }
04038 
04039     // Compact cellAddedCells.
04040 
04041     labelListList refinedCells(cellLabels.size());
04042 
04043     forAll(cellLabels, i)
04044     {
04045         label cellI = cellLabels[i];
04046 
04047         refinedCells[i].transfer(cellAddedCells[cellI]);
04048     }
04049 
04050     return refinedCells;
04051 }
04052 
04053 
04054 void Foam::hexRef8::storeData
04055 (
04056     const labelList& pointsToStore,
04057     const labelList& facesToStore,
04058     const labelList& cellsToStore
04059 )
04060 {
04061     savedPointLevel_.resize(2*pointsToStore.size());
04062     forAll(pointsToStore, i)
04063     {
04064         label pointI = pointsToStore[i];
04065         savedPointLevel_.insert(pointI, pointLevel_[pointI]);
04066     }
04067 
04068     savedCellLevel_.resize(2*cellsToStore.size());
04069     forAll(cellsToStore, i)
04070     {
04071         label cellI = cellsToStore[i];
04072         savedCellLevel_.insert(cellI, cellLevel_[cellI]);
04073     }
04074 }
04075 
04076 
04077 // Gets called after the mesh change. setRefinement will already have made
04078 // sure the pointLevel_ and cellLevel_ are the size of the new mesh so we
04079 // only need to account for reordering.
04080 void Foam::hexRef8::updateMesh(const mapPolyMesh& map)
04081 {
04082     Map<label> dummyMap(0);
04083 
04084     updateMesh(map, dummyMap, dummyMap, dummyMap);
04085 }
04086 
04087 
04088 // Gets called after the mesh change. setRefinement will already have made
04089 // sure the pointLevel_ and cellLevel_ are the size of the new mesh so we
04090 // only need to account for reordering.
04091 void Foam::hexRef8::updateMesh
04092 (
04093     const mapPolyMesh& map,
04094     const Map<label>& pointsToRestore,
04095     const Map<label>& facesToRestore,
04096     const Map<label>& cellsToRestore
04097 )
04098 {
04099     // Update celllevel
04100     if (debug)
04101     {
04102         Pout<< "hexRef8::updateMesh :"
04103             << " Updating various lists"
04104             << endl;
04105     }
04106 
04107     {
04108         const labelList& reverseCellMap = map.reverseCellMap();
04109 
04110         if (debug)
04111         {
04112             Pout<< "hexRef8::updateMesh :"
04113                 << " reverseCellMap:" << map.reverseCellMap().size()
04114                 << " cellMap:" << map.cellMap().size()
04115                 << " nCells:" << mesh_.nCells()
04116                 << " nOldCells:" << map.nOldCells()
04117                 << " cellLevel_:" << cellLevel_.size()
04118                 << " reversePointMap:" << map.reversePointMap().size()
04119                 << " pointMap:" << map.pointMap().size()
04120                 << " nPoints:" << mesh_.nPoints()
04121                 << " nOldPoints:" << map.nOldPoints()
04122                 << " pointLevel_:" << pointLevel_.size()
04123                 << endl;
04124         }
04125 
04126         if (reverseCellMap.size() == cellLevel_.size())
04127         {
04128             // Assume it is after hexRef8 that this routine is called.
04129             // Just account for reordering. We cannot use cellMap since
04130             // then cells created from cells would get cellLevel_ of
04131             // cell they were created from.
04132             reorder(reverseCellMap, mesh_.nCells(), -1, cellLevel_);
04133         }
04134         else
04135         {
04136             // Map data
04137             const labelList& cellMap = map.cellMap();
04138 
04139             labelList newCellLevel(cellMap.size());
04140             forAll(cellMap, newCellI)
04141             {
04142                 label oldCellI = cellMap[newCellI];
04143 
04144                 if (oldCellI == -1)
04145                 {
04146                     newCellLevel[newCellI] = -1;
04147                 }
04148                 else
04149                 {
04150                     newCellLevel[newCellI] = cellLevel_[oldCellI];
04151                 }
04152             }
04153             cellLevel_.transfer(newCellLevel);
04154         }
04155 
04156         // See if any cells to restore. This will be for some new cells
04157         // the corresponding old cell.
04158         forAllConstIter(Map<label>, cellsToRestore, iter)
04159         {
04160             label newCellI = iter.key();
04161             label storedCellI = iter();
04162 
04163             Map<label>::iterator fnd = savedCellLevel_.find(storedCellI);
04164 
04165             if (fnd == savedCellLevel_.end())
04166             {
04167                 FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
04168                     << "Problem : trying to restore old value for new cell "
04169                     << newCellI << " but cannot find old cell " << storedCellI
04170                     << " in map of stored values " << savedCellLevel_
04171                     << abort(FatalError);
04172             }
04173             cellLevel_[newCellI] = fnd();
04174         }
04175 
04176         //if (findIndex(cellLevel_, -1) != -1)
04177         //{
04178         //    WarningIn("hexRef8::updateMesh(const mapPolyMesh&)")
04179         //        << "Problem : "
04180         //        << "cellLevel_ contains illegal value -1 after mapping
04181         //        << " at cell " << findIndex(cellLevel_, -1) << endl
04182         //        << "This means that another program has inflated cells"
04183         //        << " (created cells out-of-nothing) and hence we don't know"
04184         //        << " their cell level. Continuing with illegal value."
04185         //        << abort(FatalError);
04186         //}
04187     }
04188 
04189 
04190     // Update pointlevel
04191     {
04192         const labelList& reversePointMap = map.reversePointMap();
04193 
04194         if (reversePointMap.size() == pointLevel_.size())
04195         {
04196             // Assume it is after hexRef8 that this routine is called.
04197             reorder(reversePointMap, mesh_.nPoints(), -1,  pointLevel_);
04198         }
04199         else
04200         {
04201             // Map data
04202             const labelList& pointMap = map.pointMap();
04203 
04204             labelList newPointLevel(pointMap.size());
04205 
04206             forAll(pointMap, newPointI)
04207             {
04208                 label oldPointI = pointMap[newPointI];
04209 
04210                 if (oldPointI == -1)
04211                 {
04212                     //FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
04213                     //    << "Problem : point " << newPointI
04214                     //    << " at " << mesh_.points()[newPointI]
04215                     //    << " does not originate from another point"
04216                     //    << " (i.e. is inflated)." << nl
04217                     //    << "Hence we cannot determine the new pointLevel"
04218                     //    << " for it." << abort(FatalError);
04219                     newPointLevel[newPointI] = -1;
04220                 }
04221                 else
04222                 {
04223                     newPointLevel[newPointI] = pointLevel_[oldPointI];
04224                 }
04225             }
04226             pointLevel_.transfer(newPointLevel);
04227         }
04228 
04229         // See if any points to restore. This will be for some new points
04230         // the corresponding old point (the one from the call to storeData)
04231         forAllConstIter(Map<label>, pointsToRestore, iter)
04232         {
04233             label newPointI = iter.key();
04234             label storedPointI = iter();
04235 
04236             Map<label>::iterator fnd = savedPointLevel_.find(storedPointI);
04237 
04238             if (fnd == savedPointLevel_.end())
04239             {
04240                 FatalErrorIn("hexRef8::updateMesh(const mapPolyMesh&)")
04241                     << "Problem : trying to restore old value for new point "
04242                     << newPointI << " but cannot find old point "
04243                     << storedPointI
04244                     << " in map of stored values " << savedPointLevel_
04245                     << abort(FatalError);
04246             }
04247             pointLevel_[newPointI] = fnd();
04248         }
04249 
04250         //if (findIndex(pointLevel_, -1) != -1)
04251         //{
04252         //    WarningIn("hexRef8::updateMesh(const mapPolyMesh&)")
04253         //        << "Problem : "
04254         //        << "pointLevel_ contains illegal value -1 after mapping"
04255         //        << " at point" << findIndex(pointLevel_, -1) << endl
04256         //        << "This means that another program has inflated points"
04257         //        << " (created points out-of-nothing) and hence we don't know"
04258         //        << " their point level. Continuing with illegal value."
04259         //        //<< abort(FatalError);
04260         //}
04261     }
04262 
04263     // Update refinement tree
04264     if (history_.active())
04265     {
04266         history_.updateMesh(map);
04267     }
04268 
04269     // Mark files as changed
04270     setInstance(mesh_.facesInstance());
04271 
04272     // Update face removal engine
04273     faceRemover_.updateMesh(map);
04274 }
04275 
04276 
04277 // Gets called after mesh subsetting. Maps are from new back to old.
04278 void Foam::hexRef8::subset
04279 (
04280     const labelList& pointMap,
04281     const labelList& faceMap,
04282     const labelList& cellMap
04283 )
04284 {
04285     // Update celllevel
04286     if (debug)
04287     {
04288         Pout<< "hexRef8::subset :"
04289             << " Updating various lists"
04290             << endl;
04291     }
04292 
04293     if (history_.active())
04294     {
04295         WarningIn
04296         (
04297             "hexRef8::subset(const labelList&, const labelList&"
04298             ", const labelList&)"
04299         )   << "Subsetting will not work in combination with unrefinement."
04300             << nl
04301             << "Proceed at your own risk." << endl;
04302     }
04303 
04304 
04305     // Update celllevel
04306     {
04307         labelList newCellLevel(cellMap.size());
04308 
04309         forAll(cellMap, newCellI)
04310         {
04311             newCellLevel[newCellI] = cellLevel_[cellMap[newCellI]];
04312         }
04313 
04314         cellLevel_.transfer(newCellLevel);
04315 
04316         if (findIndex(cellLevel_, -1) != -1)
04317         {
04318             FatalErrorIn("hexRef8::subset(..)")
04319                 << "Problem : "
04320                 << "cellLevel_ contains illegal value -1 after mapping:"
04321                 << cellLevel_
04322                 << abort(FatalError);
04323         }
04324     }
04325 
04326     // Update pointlevel
04327     {
04328         labelList newPointLevel(pointMap.size());
04329 
04330         forAll(pointMap, newPointI)
04331         {
04332             newPointLevel[newPointI] = pointLevel_[pointMap[newPointI]];
04333         }
04334 
04335         pointLevel_.transfer(newPointLevel);
04336 
04337         if (findIndex(pointLevel_, -1) != -1)
04338         {
04339             FatalErrorIn("hexRef8::subset(..)")
04340                 << "Problem : "
04341                 << "pointLevel_ contains illegal value -1 after mapping:"
04342                 << pointLevel_
04343                 << abort(FatalError);
04344         }
04345     }
04346 
04347     // Update refinement tree
04348     if (history_.active())
04349     {
04350         history_.subset(pointMap, faceMap, cellMap);
04351     }
04352 
04353     // Mark files as changed
04354     setInstance(mesh_.facesInstance());
04355 
04356     // Nothing needs doing to faceRemover.
04357     //faceRemover_.subset(pointMap, faceMap, cellMap);
04358 }
04359 
04360 
04361 // Gets called after the mesh distribution
04362 void Foam::hexRef8::distribute(const mapDistributePolyMesh& map)
04363 {
04364     if (debug)
04365     {
04366         Pout<< "hexRef8::distribute :"
04367             << " Updating various lists"
04368             << endl;
04369     }
04370 
04371     // Update celllevel
04372     map.distributeCellData(cellLevel_);
04373     // Update pointlevel
04374     map.distributePointData(pointLevel_);
04375 
04376     // Update refinement tree
04377     if (history_.active())
04378     {
04379         history_.distribute(map);
04380     }
04381 
04382     // Update face removal engine
04383     faceRemover_.distribute(map);
04384 }
04385 
04386 
04387 void Foam::hexRef8::checkMesh() const
04388 {
04389     const scalar smallDim = 1E-6 * mesh_.globalData().bb().mag();
04390 
04391     if (debug)
04392     {
04393         Pout<< "hexRef8::checkMesh : Using matching tolerance smallDim:"
04394             << smallDim << endl;
04395     }
04396 
04397     // Check owner on coupled faces.
04398     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
04399 
04400     // There should be only one coupled face between two cells. Why? Since
04401     // otherwise mesh redistribution might cause multiple faces between two
04402     // cells
04403     {
04404         labelList nei(mesh_.nFaces()-mesh_.nInternalFaces());
04405         forAll(nei, i)
04406         {
04407             nei[i] = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
04408         }
04409 
04410         // Replace data on coupled patches with their neighbour ones.
04411         syncTools::swapBoundaryFaceList(mesh_, nei, false);
04412 
04413         const polyBoundaryMesh& patches = mesh_.boundaryMesh();
04414 
04415         forAll(patches, patchI)
04416         {
04417             const polyPatch& pp = patches[patchI];
04418 
04419             if (pp.coupled())
04420             {
04421                 // Check how many faces between owner and neighbour. Should
04422                 // be only one.
04423                 HashTable<label, labelPair, labelPair::Hash<> >
04424                     cellToFace(2*pp.size());
04425 
04426                 label faceI = pp.start();
04427 
04428                 forAll(pp, i)
04429                 {
04430                     label own = mesh_.faceOwner()[faceI];
04431                     label bFaceI = faceI-mesh_.nInternalFaces();
04432 
04433                     if (!cellToFace.insert(labelPair(own, nei[bFaceI]), faceI))
04434                     {
04435                         dumpCell(own);
04436                         FatalErrorIn("hexRef8::checkMesh()")
04437                             << "Faces do not seem to be correct across coupled"
04438                             << " boundaries" << endl
04439                             << "Coupled face " << faceI
04440                             << " between owner " << own
04441                             << " on patch " << pp.name()
04442                             << " and coupled neighbour " << nei[bFaceI]
04443                             << " has two faces connected to it:"
04444                             << faceI << " and "
04445                             << cellToFace[labelPair(own, nei[bFaceI])]
04446                             << abort(FatalError);
04447                     }
04448 
04449                     faceI++;
04450                 }
04451             }
04452         }
04453     }
04454 
04455     // Check face areas.
04456     // ~~~~~~~~~~~~~~~~~
04457 
04458     {
04459         scalarField neiFaceAreas(mesh_.nFaces()-mesh_.nInternalFaces());
04460         forAll(neiFaceAreas, i)
04461         {
04462             neiFaceAreas[i] = mag(mesh_.faceAreas()[i+mesh_.nInternalFaces()]);
04463         }
04464 
04465         // Replace data on coupled patches with their neighbour ones.
04466         syncTools::swapBoundaryFaceList(mesh_, neiFaceAreas, false);
04467 
04468         forAll(neiFaceAreas, i)
04469         {
04470             label faceI = i+mesh_.nInternalFaces();
04471 
04472             const scalar magArea = mag(mesh_.faceAreas()[faceI]);
04473 
04474             if (mag(magArea - neiFaceAreas[i]) > smallDim)
04475             {
04476                 const face& f = mesh_.faces()[faceI];
04477                 label patchI = mesh_.boundaryMesh().whichPatch(faceI);
04478 
04479                 dumpCell(mesh_.faceOwner()[faceI]);
04480 
04481                 FatalErrorIn("hexRef8::checkMesh()")
04482                     << "Faces do not seem to be correct across coupled"
04483                     << " boundaries" << endl
04484                     << "Coupled face " << faceI
04485                     << " on patch " << patchI
04486                     << " " << mesh_.boundaryMesh()[patchI].name()
04487                     << " coords:" << UIndirectList<point>(mesh_.points(), f)()
04488                     << " has face area:" << magArea
04489                     << " (coupled) neighbour face area differs:"
04490                     << neiFaceAreas[i]
04491                     << " to within tolerance " << smallDim
04492                     << abort(FatalError);
04493             }
04494         }
04495     }
04496 
04497 
04498     // Check number of points on faces.
04499     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
04500     {
04501         labelList nVerts(mesh_.nFaces()-mesh_.nInternalFaces());
04502 
04503         forAll(nVerts, i)
04504         {
04505             nVerts[i] = mesh_.faces()[i+mesh_.nInternalFaces()].size();
04506         }
04507 
04508         // Replace data on coupled patches with their neighbour ones.
04509         syncTools::swapBoundaryFaceList(mesh_, nVerts, false);
04510 
04511         forAll(nVerts, i)
04512         {
04513             label faceI = i+mesh_.nInternalFaces();
04514 
04515             const face& f = mesh_.faces()[faceI];
04516 
04517             if (f.size() != nVerts[i])
04518             {
04519                 dumpCell(mesh_.faceOwner()[faceI]);
04520 
04521                 label patchI = mesh_.boundaryMesh().whichPatch(faceI);
04522 
04523                 FatalErrorIn("hexRef8::checkMesh()")
04524                     << "Faces do not seem to be correct across coupled"
04525                     << " boundaries" << endl
04526                     << "Coupled face " << faceI
04527                     << " on patch " << patchI
04528                     << " " << mesh_.boundaryMesh()[patchI].name()
04529                     << " coords:" << UIndirectList<point>(mesh_.points(), f)()
04530                     << " has size:" << f.size()
04531                     << " (coupled) neighbour face has size:"
04532                     << nVerts[i]
04533                     << abort(FatalError);
04534             }
04535         }
04536     }
04537 
04538 
04539     // Check points of face
04540     // ~~~~~~~~~~~~~~~~~~~~
04541     {
04542         // Anchor points.
04543         pointField anchorPoints(mesh_.nFaces()-mesh_.nInternalFaces());
04544 
04545         forAll(anchorPoints, i)
04546         {
04547             label faceI = i+mesh_.nInternalFaces();
04548             const point& fc = mesh_.faceCentres()[faceI];
04549             const face& f = mesh_.faces()[faceI];
04550             const vector anchorVec(mesh_.points()[f[0]] - fc);
04551 
04552             anchorPoints[i] = anchorVec;
04553         }
04554 
04555         // Replace data on coupled patches with their neighbour ones. Apply
04556         // rotation transformation (but not separation since is relative vector
04557         // to point on same face.
04558         syncTools::swapBoundaryFaceList(mesh_, anchorPoints, false);
04559 
04560         forAll(anchorPoints, i)
04561         {
04562             label faceI = i+mesh_.nInternalFaces();
04563             const point& fc = mesh_.faceCentres()[faceI];
04564             const face& f = mesh_.faces()[faceI];
04565             const vector anchorVec(mesh_.points()[f[0]] - fc);
04566 
04567             if (mag(anchorVec - anchorPoints[i]) > smallDim)
04568             {
04569                 dumpCell(mesh_.faceOwner()[faceI]);
04570 
04571                 label patchI = mesh_.boundaryMesh().whichPatch(faceI);
04572 
04573                 FatalErrorIn("hexRef8::checkMesh()")
04574                     << "Faces do not seem to be correct across coupled"
04575                     << " boundaries" << endl
04576                     << "Coupled face " << faceI
04577                     << " on patch " << patchI
04578                     << " " << mesh_.boundaryMesh()[patchI].name()
04579                     << " coords:" << UIndirectList<point>(mesh_.points(), f)()
04580                     << " has anchor vector:" << anchorVec
04581                     << " (coupled) neighbour face anchor vector differs:"
04582                     << anchorPoints[i]
04583                     << " to within tolerance " << smallDim
04584                     << abort(FatalError);
04585             }
04586         }
04587     }
04588 
04589     if (debug)
04590     {
04591         Pout<< "hexRef8::checkMesh : Returning" << endl;
04592     }
04593 }
04594 
04595 
04596 void Foam::hexRef8::checkRefinementLevels
04597 (
04598     const label maxPointDiff,
04599     const labelList& pointsToCheck
04600 ) const
04601 {
04602     if (debug)
04603     {
04604         Pout<< "hexRef8::checkRefinementLevels :"
04605             << " Checking 2:1 refinement level" << endl;
04606     }
04607 
04608     if
04609     (
04610         cellLevel_.size() != mesh_.nCells()
04611      || pointLevel_.size() != mesh_.nPoints()
04612     )
04613     {
04614         FatalErrorIn("hexRef8::checkRefinementLevels(const label)")
04615             << "cellLevel size should be number of cells"
04616             << " and pointLevel size should be number of points."<< nl
04617             << "cellLevel:" << cellLevel_.size()
04618             << " mesh.nCells():" << mesh_.nCells() << nl
04619             << "pointLevel:" << pointLevel_.size()
04620             << " mesh.nPoints():" << mesh_.nPoints()
04621             << abort(FatalError);
04622     }
04623 
04624 
04625     // Check 2:1 consistency.
04626     // ~~~~~~~~~~~~~~~~~~~~~~
04627 
04628     {
04629         // Internal faces.
04630         for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
04631         {
04632             label own = mesh_.faceOwner()[faceI];
04633             label nei = mesh_.faceNeighbour()[faceI];
04634 
04635             if (mag(cellLevel_[own] - cellLevel_[nei]) > 1)
04636             {
04637                 dumpCell(own);
04638                 dumpCell(nei);
04639 
04640                 FatalErrorIn
04641                 (
04642                     "hexRef8::checkRefinementLevels(const label)"
04643                 )   << "Celllevel does not satisfy 2:1 constraint." << nl
04644                     << "On face " << faceI << " owner cell " << own
04645                     << " has refinement " << cellLevel_[own]
04646                     << " neighbour cell " << nei << " has refinement "
04647                     << cellLevel_[nei]
04648                     << abort(FatalError);
04649             }
04650         }
04651 
04652         // Coupled faces. Get neighbouring value
04653         labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
04654 
04655         forAll(neiLevel, i)
04656         {
04657             label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
04658 
04659             neiLevel[i] = cellLevel_[own];
04660         }
04661 
04662         // No separation
04663         syncTools::swapBoundaryFaceList(mesh_, neiLevel, false);
04664 
04665         forAll(neiLevel, i)
04666         {
04667             label faceI = i+mesh_.nInternalFaces();
04668 
04669             label own = mesh_.faceOwner()[faceI];
04670 
04671             if (mag(cellLevel_[own] - neiLevel[i]) > 1)
04672             {
04673                 dumpCell(own);
04674 
04675                 label patchI = mesh_.boundaryMesh().whichPatch(faceI);
04676 
04677                 FatalErrorIn
04678                 (
04679                     "hexRef8::checkRefinementLevels(const label)"
04680                 )   << "Celllevel does not satisfy 2:1 constraint."
04681                     << " On coupled face " << faceI
04682                     << " on patch " << patchI << " "
04683                     << mesh_.boundaryMesh()[patchI].name()
04684                     << " owner cell " << own << " has refinement "
04685                     << cellLevel_[own]
04686                     << " (coupled) neighbour cell has refinement "
04687                     << neiLevel[i]
04688                     << abort(FatalError);
04689             }
04690         }
04691     }
04692 
04693 
04694     // Check pointLevel is synchronized
04695     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
04696     {
04697         labelList syncPointLevel(pointLevel_);
04698 
04699         // Get min level
04700         syncTools::syncPointList
04701         (
04702             mesh_,
04703             syncPointLevel,
04704             minEqOp<label>(),
04705             labelMax,
04706             false               // no separation
04707         );
04708 
04709 
04710         forAll(syncPointLevel, pointI)
04711         {
04712             if (pointLevel_[pointI] != syncPointLevel[pointI])
04713             {
04714                 FatalErrorIn
04715                 (
04716                     "hexRef8::checkRefinementLevels(const label)"
04717                 )   << "PointLevel is not consistent across coupled patches."
04718                     << endl
04719                     << "point:" << pointI << " coord:" << mesh_.points()[pointI]
04720                     << " has level " << pointLevel_[pointI]
04721                     << " whereas the coupled point has level "
04722                     << syncPointLevel[pointI]
04723                     << abort(FatalError);
04724             }
04725         }
04726     }
04727 
04728 
04729     // Check 2:1 across points (instead of faces)
04730     if (maxPointDiff != -1)
04731     {
04732         // Determine per point the max cell level.
04733         labelList maxPointLevel(mesh_.nPoints(), 0);
04734 
04735         forAll(maxPointLevel, pointI)
04736         {
04737             const labelList& pCells = mesh_.pointCells(pointI);
04738 
04739             label& pLevel = maxPointLevel[pointI];
04740 
04741             forAll(pCells, i)
04742             {
04743                 pLevel = max(pLevel, cellLevel_[pCells[i]]);
04744             }
04745         }
04746 
04747         // Sync maxPointLevel to neighbour
04748         syncTools::syncPointList
04749         (
04750             mesh_,
04751             maxPointLevel,
04752             maxEqOp<label>(),
04753             labelMin,           // null value
04754             false               // no separation
04755         );
04756 
04757         // Check 2:1 across boundary points
04758         forAll(pointsToCheck, i)
04759         {
04760             label pointI = pointsToCheck[i];
04761 
04762             const labelList& pCells = mesh_.pointCells(pointI);
04763 
04764             forAll(pCells, i)
04765             {
04766                 label cellI = pCells[i];
04767 
04768                 if
04769                 (
04770                     mag(cellLevel_[cellI]-maxPointLevel[pointI])
04771                   > maxPointDiff
04772                 )
04773                 {
04774                     dumpCell(cellI);
04775 
04776                     FatalErrorIn
04777                     (
04778                         "hexRef8::checkRefinementLevels(const label)"
04779                     )   << "Too big a difference between"
04780                         << " point-connected cells." << nl
04781                         << "cell:" << cellI
04782                         << " cellLevel:" << cellLevel_[cellI]
04783                         << " uses point:" << pointI
04784                         << " coord:" << mesh_.points()[pointI]
04785                         << " which is also used by a cell with level:"
04786                         << maxPointLevel[pointI]
04787                         << abort(FatalError);
04788                 }
04789             }
04790         }
04791     }
04792 
04793 
04794     //- Gives problems after first splitting off inside mesher.
04796     //{
04797     //    // Any patches with points having only two edges.
04798     //
04799     //    boolList isHangingPoint(mesh_.nPoints(), false);
04800     //
04801     //    const polyBoundaryMesh& patches = mesh_.boundaryMesh();
04802     //
04803     //    forAll(patches, patchI)
04804     //    {
04805     //        const polyPatch& pp = patches[patchI];
04806     //
04807     //        const labelList& meshPoints = pp.meshPoints();
04808     //
04809     //        forAll(meshPoints, i)
04810     //        {
04811     //            label pointI = meshPoints[i];
04812     //
04813     //            const labelList& pEdges = mesh_.pointEdges()[pointI];
04814     //
04815     //            if (pEdges.size() == 2)
04816     //            {
04817     //                isHangingPoint[pointI] = true;
04818     //            }
04819     //        }
04820     //    }
04821     //
04822     //    syncTools::syncPointList
04823     //    (
04824     //        mesh_,
04825     //        isHangingPoint,
04826     //        andEqOp<bool>(),        // only if all decide it is hanging point
04827     //        true,                   // null
04828     //        false                   // no separation
04829     //    );
04830     //
04831     //    //OFstream str(mesh_.time().path()/"hangingPoints.obj");
04832     //
04833     //    label nHanging = 0;
04834     //
04835     //    forAll(isHangingPoint, pointI)
04836     //    {
04837     //        if (isHangingPoint[pointI])
04838     //        {
04839     //            nHanging++;
04840     //
04841     //            Pout<< "Hanging boundary point " << pointI
04842     //                << " at " << mesh_.points()[pointI]
04843     //                << endl;
04844     //            //meshTools::writeOBJ(str, mesh_.points()[pointI]);
04845     //        }
04846     //    }
04847     //
04848     //    if (returnReduce(nHanging, sumOp<label>()) > 0)
04849     //    {
04850     //        FatalErrorIn
04851     //        (
04852     //            "hexRef8::checkRefinementLevels(const label)"
04853     //        )   << "Detected a point used by two edges only (hanging point)"
04854     //            << nl << "This is not allowed"
04855     //            << abort(FatalError);
04856     //    }
04857     //}
04858 }
04859 
04860 
04861 
04862 //
04863 // Unrefinement
04864 // ~~~~~~~~~~~~
04865 //
04866 
04867 
04868 Foam::labelList Foam::hexRef8::getSplitPoints() const
04869 {
04870     if (debug)
04871     {
04872         checkRefinementLevels(-1, labelList(0));
04873     }
04874 
04875     if (debug)
04876     {
04877         Pout<< "hexRef8::getSplitPoints :"
04878             << " Calculating unrefineable points" << endl;
04879     }
04880 
04881 
04882     if (!history_.active())
04883     {
04884         FatalErrorIn("hexRef8::getSplitPoints()")
04885             << "Only call if constructed with history capability"
04886             << abort(FatalError);
04887     }
04888 
04889     // Master cell
04890     // -1 undetermined
04891     // -2 certainly not split point
04892     // >= label of master cell
04893     labelList splitMaster(mesh_.nPoints(), -1);
04894     labelList splitMasterLevel(mesh_.nPoints(), 0);
04895 
04896     // Unmark all with not 8 cells
04897     //const labelListList& pointCells = mesh_.pointCells();
04898 
04899     for (label pointI = 0; pointI < mesh_.nPoints(); pointI++)
04900     {
04901         const labelList& pCells = mesh_.pointCells(pointI);
04902 
04903         if (pCells.size() != 8)
04904         {
04905             splitMaster[pointI] = -2;
04906         }
04907     }
04908 
04909     // Unmark all with different master cells
04910     const labelList& visibleCells = history_.visibleCells();
04911 
04912     forAll(visibleCells, cellI)
04913     {
04914         const labelList& cPoints = mesh_.cellPoints(cellI);
04915 
04916         if (visibleCells[cellI] != -1 && history_.parentIndex(cellI) >= 0)
04917         {
04918             label parentIndex = history_.parentIndex(cellI);
04919 
04920             // Check same master.
04921             forAll(cPoints, i)
04922             {
04923                 label pointI = cPoints[i];
04924 
04925                 label masterCellI = splitMaster[pointI];
04926 
04927                 if (masterCellI == -1)
04928                 {
04929                     // First time visit of point. Store parent cell and
04930                     // level of the parent cell (with respect to cellI). This
04931                     // is additional guarantee that we're referring to the
04932                     // same master at the same refinement level.
04933 
04934                     splitMaster[pointI] = parentIndex;
04935                     splitMasterLevel[pointI] = cellLevel_[cellI] - 1;
04936                 }
04937                 else if (masterCellI == -2)
04938                 {
04939                     // Already decided that point is not splitPoint
04940                 }
04941                 else if
04942                 (
04943                     (masterCellI != parentIndex)
04944                  || (splitMasterLevel[pointI] != cellLevel_[cellI] - 1)
04945                 )
04946                 {
04947                     // Different masters so point is on two refinement
04948                     // patterns
04949                     splitMaster[pointI] = -2;
04950                 }
04951             }
04952         }
04953         else
04954         {
04955             // Either not visible or is unrefined cell
04956             forAll(cPoints, i)
04957             {
04958                 label pointI = cPoints[i];
04959 
04960                 splitMaster[pointI] = -2;
04961             }
04962         }
04963     }
04964 
04965     // Unmark boundary faces
04966     for
04967     (
04968         label faceI = mesh_.nInternalFaces();
04969         faceI < mesh_.nFaces();
04970         faceI++
04971     )
04972     {
04973         const face& f = mesh_.faces()[faceI];
04974 
04975         forAll(f, fp)
04976         {
04977             splitMaster[f[fp]] = -2;
04978         }
04979     }
04980 
04981 
04982     // Collect into labelList
04983 
04984     label nSplitPoints = 0;
04985 
04986     forAll(splitMaster, pointI)
04987     {
04988         if (splitMaster[pointI] >= 0)
04989         {
04990             nSplitPoints++;
04991         }
04992     }
04993 
04994     labelList splitPoints(nSplitPoints);
04995     nSplitPoints = 0;
04996 
04997     forAll(splitMaster, pointI)
04998     {
04999         if (splitMaster[pointI] >= 0)
05000         {
05001             splitPoints[nSplitPoints++] = pointI;
05002         }
05003     }
05004 
05005     return splitPoints;
05006 }
05007 
05008 
05009 //void Foam::hexRef8::markIndex
05010 //(
05011 //    const label maxLevel,
05012 //    const label level,
05013 //    const label index,
05014 //    const label markValue,
05015 //    labelList& indexValues
05016 //) const
05017 //{
05018 //    if (level < maxLevel && indexValues[index] == -1)
05019 //    {
05020 //        // Mark
05021 //        indexValues[index] = markValue;
05022 //
05023 //        // Mark parent
05024 //        const splitCell8& split = history_.splitCells()[index];
05025 //
05026 //        if (split.parent_ >= 0)
05027 //        {
05028 //            markIndex
05029 //            (
05030 //              maxLevel, level+1, split.parent_, markValue, indexValues);
05031 //            )
05032 //        }
05033 //    }
05034 //}
05035 //
05036 //
05041 //void Foam::hexRef8::markCellClusters
05042 //(
05043 //    const label maxLevel,
05044 //    labelList& cluster
05045 //) const
05046 //{
05047 //    cluster.setSize(mesh_.nCells());
05048 //    cluster = -1;
05049 //
05050 //    const DynamicList<splitCell8>& splitCells = history_.splitCells();
05051 //
05052 //    // Mark all splitCells down to level maxLevel with a cell originating from
05053 //    // it.
05054 //
05055 //    labelList indexLevel(splitCells.size(), -1);
05056 //
05057 //    forAll(visibleCells, cellI)
05058 //    {
05059 //        label index = visibleCells[cellI];
05060 //
05061 //        if (index >= 0)
05062 //        {
05063 //            markIndex(maxLevel, 0, index, cellI, indexLevel);
05064 //        }
05065 //    }
05066 //
05067 //    // Mark cells with splitCell
05068 //}
05069 
05070 
05071 Foam::labelList Foam::hexRef8::consistentUnrefinement
05072 (
05073     const labelList& pointsToUnrefine,
05074     const bool maxSet
05075 ) const
05076 {
05077     if (debug)
05078     {
05079         Pout<< "hexRef8::consistentUnrefinement :"
05080             << " Determining 2:1 consistent unrefinement" << endl;
05081     }
05082 
05083     if (maxSet)
05084     {
05085         FatalErrorIn
05086         (
05087             "hexRef8::consistentUnrefinement(const labelList&, const bool"
05088         )   << "maxSet not implemented yet."
05089             << abort(FatalError);
05090     }
05091 
05092     // Loop, modifying pointsToUnrefine, until no more changes to due to 2:1
05093     // conflicts.
05094     // maxSet = false : unselect points to refine
05095     // maxSet = true: select points to refine
05096 
05097     // Maintain boolList for pointsToUnrefine and cellsToUnrefine
05098     PackedBoolList unrefinePoint(mesh_.nPoints());
05099 
05100     forAll(pointsToUnrefine, i)
05101     {
05102         label pointI = pointsToUnrefine[i];
05103 
05104         unrefinePoint.set(pointI, 1);
05105     }
05106 
05107 
05108     while (true)
05109     {
05110         // Construct cells to unrefine
05111         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
05112 
05113         PackedBoolList unrefineCell(mesh_.nCells());
05114 
05115         forAll(unrefinePoint, pointI)
05116         {
05117             if (unrefinePoint.get(pointI) == 1)
05118             {
05119                 const labelList& pCells = mesh_.pointCells(pointI);
05120 
05121                 forAll(pCells, j)
05122                 {
05123                     unrefineCell.set(pCells[j], 1);
05124                 }
05125             }
05126         }
05127 
05128 
05129         label nChanged = 0;
05130 
05131 
05132         // Check 2:1 consistency taking refinement into account
05133         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
05134 
05135         // Internal faces.
05136         for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
05137         {
05138             label own = mesh_.faceOwner()[faceI];
05139             label ownLevel = cellLevel_[own] - unrefineCell.get(own);
05140 
05141             label nei = mesh_.faceNeighbour()[faceI];
05142             label neiLevel = cellLevel_[nei] - unrefineCell.get(nei);
05143 
05144             if (ownLevel < (neiLevel-1))
05145             {
05146                 // Since was 2:1 this can only occur if own is marked for
05147                 // unrefinement.
05148 
05149                 if (maxSet)
05150                 {
05151                     unrefineCell.set(nei, 1);
05152                 }
05153                 else
05154                 {
05155                     if (unrefineCell.get(own) == 0)
05156                     {
05157                         FatalErrorIn("hexRef8::consistentUnrefinement(..)")
05158                             << "problem" << abort(FatalError);
05159                     }
05160 
05161                     unrefineCell.set(own, 0);
05162                 }
05163                 nChanged++;
05164             }
05165             else if (neiLevel < (ownLevel-1))
05166             {
05167                 if (maxSet)
05168                 {
05169                     unrefineCell.set(own, 1);
05170                 }
05171                 else
05172                 {
05173                     if (unrefineCell.get(nei) == 0)
05174                     {
05175                         FatalErrorIn("hexRef8::consistentUnrefinement(..)")
05176                             << "problem" << abort(FatalError);
05177                     }
05178 
05179                     unrefineCell.set(nei, 0);
05180                 }
05181                 nChanged++;
05182             }
05183         }
05184 
05185 
05186         // Coupled faces. Swap owner level to get neighbouring cell level.
05187         labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
05188 
05189         forAll(neiLevel, i)
05190         {
05191             label own = mesh_.faceOwner()[i+mesh_.nInternalFaces()];
05192 
05193             neiLevel[i] = cellLevel_[own] - unrefineCell.get(own);
05194         }
05195 
05196         // Swap to neighbour
05197         syncTools::swapBoundaryFaceList(mesh_, neiLevel, false);
05198 
05199         forAll(neiLevel, i)
05200         {
05201             label faceI = i+mesh_.nInternalFaces();
05202             label own = mesh_.faceOwner()[faceI];
05203             label ownLevel = cellLevel_[own] - unrefineCell.get(own);
05204 
05205             if (ownLevel < (neiLevel[i]-1))
05206             {
05207                 if (!maxSet)
05208                 {
05209                     if (unrefineCell.get(own) == 0)
05210                     {
05211                         FatalErrorIn("hexRef8::consistentUnrefinement(..)")
05212                             << "problem" << abort(FatalError);
05213                     }
05214 
05215                     unrefineCell.set(own, 0);
05216                     nChanged++;
05217                 }
05218             }
05219             else if (neiLevel[i] < (ownLevel-1))
05220             {
05221                 if (maxSet)
05222                 {
05223                     if (unrefineCell.get(own) == 1)
05224                     {
05225                         FatalErrorIn("hexRef8::consistentUnrefinement(..)")
05226                             << "problem" << abort(FatalError);
05227                     }
05228 
05229                     unrefineCell.set(own, 1);
05230                     nChanged++;
05231                 }
05232             }
05233         }
05234 
05235         reduce(nChanged, sumOp<label>());
05236 
05237         if (debug)
05238         {
05239             Pout<< "hexRef8::consistentUnrefinement :"
05240                 << " Changed " << nChanged
05241                 << " refinement levels due to 2:1 conflicts."
05242                 << endl;
05243         }
05244 
05245         if (nChanged == 0)
05246         {
05247             break;
05248         }
05249 
05250 
05251         // Convert cellsToUnrefine back into points to unrefine
05252         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
05253 
05254         // Knock out any point whose cell neighbour cannot be unrefined.
05255         forAll(unrefinePoint, pointI)
05256         {
05257             if (unrefinePoint.get(pointI) == 1)
05258             {
05259                 const labelList& pCells = mesh_.pointCells(pointI);
05260 
05261                 forAll(pCells, j)
05262                 {
05263                     if (unrefineCell.get(pCells[j]) == 0)
05264                     {
05265                         unrefinePoint.set(pointI, 0);
05266                         break;
05267                     }
05268                 }
05269             }
05270         }
05271     }
05272 
05273 
05274     // Convert back to labelList.
05275     label nSet = 0;
05276 
05277     forAll(unrefinePoint, pointI)
05278     {
05279         if (unrefinePoint.get(pointI) == 1)
05280         {
05281             nSet++;
05282         }
05283     }
05284 
05285     labelList newPointsToUnrefine(nSet);
05286     nSet = 0;
05287 
05288     forAll(unrefinePoint, pointI)
05289     {
05290         if (unrefinePoint.get(pointI) == 1)
05291         {
05292             newPointsToUnrefine[nSet++] = pointI;
05293         }
05294     }
05295 
05296     return newPointsToUnrefine;
05297 }
05298 
05299 
05300 void Foam::hexRef8::setUnrefinement
05301 (
05302     const labelList& splitPointLabels,
05303     polyTopoChange& meshMod
05304 )
05305 {
05306     if (!history_.active())
05307     {
05308         FatalErrorIn
05309         (
05310             "hexRef8::setUnrefinement(const labelList&, polyTopoChange&)"
05311         )   << "Only call if constructed with history capability"
05312             << abort(FatalError);
05313     }
05314 
05315     if (debug)
05316     {
05317         Pout<< "hexRef8::setUnrefinement :"
05318             << " Checking initial mesh just to make sure" << endl;
05319 
05320         checkMesh();
05321 
05322         forAll(cellLevel_, cellI)
05323         {
05324             if (cellLevel_[cellI] < 0)
05325             {
05326                 FatalErrorIn
05327                 (
05328                     "hexRef8::setUnrefinement(const labelList&, polyTopoChange&)"
05329                 )   << "Illegal cell level " << cellLevel_[cellI]
05330                     << " for cell " << cellI
05331                     << abort(FatalError);
05332             }
05333         }
05334 
05335 
05336         // Write to sets.
05337         pointSet pSet(mesh_, "splitPoints", splitPointLabels);
05338         pSet.write();
05339 
05340         cellSet cSet(mesh_, "splitPointCells", splitPointLabels.size());
05341 
05342         forAll(splitPointLabels, i)
05343         {
05344             const labelList& pCells = mesh_.pointCells(splitPointLabels[i]);
05345 
05346             forAll(pCells, j)
05347             {
05348                 cSet.insert(pCells[j]);
05349             }
05350         }
05351         cSet.write();
05352 
05353         Pout<< "hexRef8::setRefinement : Dumping " << pSet.size()
05354             << " points and "
05355             << cSet.size() << " cells for unrefinement to" << nl
05356             << "    pointSet " << pSet.objectPath() << nl
05357             << "    cellSet " << cSet.objectPath()
05358             << endl;
05359     }
05360 
05361 
05362     labelList cellRegion;
05363     labelList cellRegionMaster;
05364     labelList facesToRemove;
05365 
05366     {
05367         labelHashSet splitFaces(12*splitPointLabels.size());
05368 
05369         forAll(splitPointLabels, i)
05370         {
05371             const labelList& pFaces = mesh_.pointFaces()[splitPointLabels[i]];
05372 
05373             forAll(pFaces, j)
05374             {
05375                 splitFaces.insert(pFaces[j]);
05376             }
05377         }
05378 
05379         // Check with faceRemover what faces will get removed. Note that this
05380         // can be more (but never less) than splitFaces provided.
05381         faceRemover_.compatibleRemoves
05382         (
05383             splitFaces.toc(),   // pierced faces
05384             cellRegion,         // per cell -1 or region it is merged into
05385             cellRegionMaster,   // per region the master cell
05386             facesToRemove       // new faces to be removed.
05387         );
05388 
05389         if (facesToRemove.size() != splitFaces.size())
05390         {
05391             FatalErrorIn
05392             (
05393                 "hexRef8::setUnrefinement(const labelList&, polyTopoChange&)"
05394             )   << "Ininitial set of split points to unrefine does not"
05395                 << " seem to be consistent or not mid points of refined cells"
05396                 << abort(FatalError);
05397         }
05398     }
05399 
05400     // Redo the region master so it is consistent with our master.
05401     // This will guarantee that the new cell (for which faceRemover uses
05402     // the region master) is already compatible with our refinement structure.
05403 
05404     forAll(splitPointLabels, i)
05405     {
05406         label pointI = splitPointLabels[i];
05407 
05408         // Get original cell label
05409 
05410         const labelList& pCells = mesh_.pointCells(pointI);
05411 
05412         // Check
05413         if (pCells.size() != 8)
05414         {
05415             FatalErrorIn
05416             (
05417                 "hexRef8::setUnrefinement(const labelList&, polyTopoChange&)"
05418             )   << "splitPoint " << pointI
05419                 << " should have 8 cells using it. It has " << pCells
05420                 << abort(FatalError);
05421         }
05422 
05423 
05424         // Check that the lowest numbered pCells is the master of the region
05425         // (should be guaranteed by directRemoveFaces)
05426         //if (debug)
05427         {
05428             label masterCellI = min(pCells);
05429 
05430             forAll(pCells, j)
05431             {
05432                 label cellI = pCells[j];
05433 
05434                 label region = cellRegion[cellI];
05435 
05436                 if (region == -1)
05437                 {
05438                     FatalErrorIn("hexRef8::setUnrefinement(..)")
05439                         << "Ininitial set of split points to unrefine does not"
05440                         << " seem to be consistent or not mid points"
05441                         << " of refined cells" << nl
05442                         << "cell:" << cellI << " on splitPoint " << pointI
05443                         << " has no region to be merged into"
05444                         << abort(FatalError);
05445                 }
05446 
05447                 if (masterCellI != cellRegionMaster[region])
05448                 {
05449                     FatalErrorIn("hexRef8::setUnrefinement(..)")
05450                         << "cell:" << cellI << " on splitPoint:" << pointI
05451                         << " in region " << region
05452                         << " has master:" << cellRegionMaster[region]
05453                         << " which is not the lowest numbered cell"
05454                         << " among the pointCells:" << pCells
05455                         << abort(FatalError);
05456                 }
05457             }
05458         }
05459     }
05460 
05461     // Insert all commands to combine cells. Never fails so don't have to
05462     // test for success.
05463     faceRemover_.setRefinement
05464     (
05465         facesToRemove,
05466         cellRegion,
05467         cellRegionMaster,
05468         meshMod
05469     );
05470 
05471     // Remove the 8 cells that originated from merging around the split point
05472     // and adapt cell levels (not that pointLevels stay the same since points
05473     // either get removed or stay at the same position.
05474     forAll(splitPointLabels, i)
05475     {
05476         label pointI = splitPointLabels[i];
05477 
05478         const labelList& pCells = mesh_.pointCells(pointI);
05479 
05480         label masterCellI = min(pCells);
05481 
05482         forAll(pCells, j)
05483         {
05484             cellLevel_[pCells[j]]--;
05485         }
05486 
05487         history_.combineCells(masterCellI, pCells);
05488     }
05489 
05490     // Mark files as changed
05491     setInstance(mesh_.facesInstance());
05492 
05493     // history_.updateMesh will take care of truncating.
05494 }
05495 
05496 
05497 // Write refinement to polyMesh directory.
05498 bool Foam::hexRef8::write() const
05499 {
05500     bool writeOk = cellLevel_.write() && pointLevel_.write();
05501 
05502     if (history_.active())
05503     {
05504         writeOk = writeOk && history_.write();
05505     }
05506 
05507     return writeOk;
05508 }
05509 
05510 
05511 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines