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

meshCutter.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 Description
00025 
00026 \*---------------------------------------------------------------------------*/
00027 
00028 #include "meshCutter.H"
00029 #include <OpenFOAM/polyMesh.H>
00030 #include <dynamicMesh/polyTopoChange.H>
00031 #include <dynamicMesh/cellCuts.H>
00032 #include <OpenFOAM/mapPolyMesh.H>
00033 #include <meshTools/meshTools.H>
00034 #include <dynamicMesh/polyModifyFace.H>
00035 #include <dynamicMesh/polyAddPoint.H>
00036 #include <dynamicMesh/polyAddFace.H>
00037 #include <dynamicMesh/polyAddCell.H>
00038 
00039 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00040 
00041 defineTypeNameAndDebug(Foam::meshCutter, 0);
00042 
00043 
00044 // * * * * * * * * * * * * * Private Static Functions  * * * * * * * * * * * //
00045 
00046 // Returns true if lst1 and lst2 share elements
00047 bool Foam::meshCutter::uses(const labelList& elems1, const labelList& elems2)
00048 {
00049     forAll(elems1, elemI)
00050     {
00051         if (findIndex(elems2, elems1[elemI]) != -1)
00052         {
00053             return true;
00054         }
00055     }
00056     return false;
00057 }
00058 
00059 
00060 // Check if twoCuts at two consecutive position in cuts.
00061 bool Foam::meshCutter::isIn
00062 (
00063     const edge& twoCuts,
00064     const labelList& cuts
00065 )
00066 {
00067     label index = findIndex(cuts, twoCuts[0]);
00068 
00069     if (index == -1)
00070     {
00071         return false;
00072     }
00073 
00074     return
00075     (
00076         cuts[cuts.fcIndex(index)] == twoCuts[1]
00077      || cuts[cuts.rcIndex(index)] == twoCuts[1]
00078     );
00079 }
00080 
00081 
00082 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00083 
00084 // Returns the cell in cellLabels that is cut. Or -1.
00085 Foam::label Foam::meshCutter::findCutCell
00086 (
00087     const cellCuts& cuts,
00088     const labelList& cellLabels
00089 ) const
00090 {
00091     forAll(cellLabels, labelI)
00092     {
00093         label cellI = cellLabels[labelI];
00094 
00095         if (cuts.cellLoops()[cellI].size())
00096         {
00097             return cellI;
00098         }
00099     }
00100     return -1;
00101 }
00102 
00103 
00104 //- Returns first pointI in pointLabels that uses an internal
00105 //  face. Used to find point to inflate cell/face from (has to be
00106 //  connected to internal face). Returns -1 (so inflate from nothing) if
00107 //  none found.
00108 Foam::label Foam::meshCutter::findInternalFacePoint
00109 (
00110     const labelList& pointLabels
00111 ) const
00112 {
00113     forAll(pointLabels, labelI)
00114     {
00115         label pointI = pointLabels[labelI];
00116 
00117         const labelList& pFaces = mesh().pointFaces()[pointI];
00118 
00119         forAll(pFaces, pFaceI)
00120         {
00121             label faceI = pFaces[pFaceI];
00122 
00123             if (mesh().isInternalFace(faceI))
00124             {
00125                 return pointI;
00126             }
00127         }
00128     }
00129 
00130     if (pointLabels.empty())
00131     {
00132         FatalErrorIn("meshCutter::findInternalFacePoint(const labelList&)")
00133             << "Empty pointLabels" << abort(FatalError);
00134     }
00135 
00136     return -1;
00137 }
00138 
00139 
00140 // Get new owner and neighbour of face. Checks anchor points to see if
00141 // need to get original or added cell.
00142 void Foam::meshCutter::faceCells
00143 (
00144     const cellCuts& cuts,
00145     const label faceI,
00146     label& own,
00147     label& nei
00148 ) const
00149 {
00150     const labelListList& anchorPts = cuts.cellAnchorPoints();
00151     const labelListList& cellLoops = cuts.cellLoops();
00152 
00153     const face& f = mesh().faces()[faceI];
00154 
00155     own = mesh().faceOwner()[faceI];
00156 
00157     if (cellLoops[own].size() && uses(f, anchorPts[own]))
00158     {
00159         own = addedCells_[own];
00160     }
00161 
00162     nei = -1;
00163 
00164     if (mesh().isInternalFace(faceI))
00165     {
00166         nei = mesh().faceNeighbour()[faceI];
00167 
00168         if (cellLoops[nei].size() && uses(f, anchorPts[nei]))
00169         {
00170             nei = addedCells_[nei];
00171         }
00172     }
00173 }
00174 
00175 
00176 void Foam::meshCutter::getFaceInfo
00177 (
00178     const label faceI,
00179     label& patchID,
00180     label& zoneID,
00181     label& zoneFlip
00182 ) const
00183 {
00184     patchID = -1;
00185 
00186     if (!mesh().isInternalFace(faceI))
00187     {
00188         patchID = mesh().boundaryMesh().whichPatch(faceI);
00189     }
00190 
00191     zoneID = mesh().faceZones().whichZone(faceI);
00192 
00193     zoneFlip = false;
00194 
00195     if (zoneID >= 0)
00196     {
00197         const faceZone& fZone = mesh().faceZones()[zoneID];
00198 
00199         zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00200     }
00201 }
00202 
00203 
00204 // Adds a face on top of existing faceI.
00205 void Foam::meshCutter::addFace
00206 (
00207     polyTopoChange& meshMod,
00208     const label faceI,
00209     const face& newFace,
00210     const label own,
00211     const label nei
00212 )
00213 {
00214     label patchID, zoneID, zoneFlip;
00215 
00216     getFaceInfo(faceI, patchID, zoneID, zoneFlip);
00217 
00218     if ((nei == -1) || (own < nei))
00219     {
00220         // Ordering ok.
00221         if (debug & 2)
00222         {
00223             Pout<< "Adding face " << newFace
00224                 << " with new owner:" << own
00225                 << " with new neighbour:" << nei
00226                 << " patchID:" << patchID
00227                 << " zoneID:" << zoneID
00228                 << " zoneFlip:" << zoneFlip
00229                 << endl;
00230         }
00231 
00232         meshMod.setAction
00233         (
00234             polyAddFace
00235             (
00236                 newFace,                    // face
00237                 own,                        // owner
00238                 nei,                        // neighbour
00239                 -1,                         // master point
00240                 -1,                         // master edge
00241                 faceI,                      // master face for addition
00242                 false,                      // flux flip
00243                 patchID,                    // patch for face
00244                 zoneID,                     // zone for face
00245                 zoneFlip                    // face zone flip
00246             )
00247         );
00248     }
00249     else
00250     {
00251         // Reverse owner/neighbour
00252         if (debug & 2)
00253         {
00254             Pout<< "Adding (reversed) face " << newFace.reverseFace()
00255                 << " with new owner:" << nei
00256                 << " with new neighbour:" << own
00257                 << " patchID:" << patchID
00258                 << " zoneID:" << zoneID
00259                 << " zoneFlip:" << zoneFlip
00260                 << endl;
00261         }
00262 
00263         meshMod.setAction
00264         (
00265             polyAddFace
00266             (
00267                 newFace.reverseFace(),      // face
00268                 nei,                        // owner
00269                 own,                        // neighbour
00270                 -1,                         // master point
00271                 -1,                         // master edge
00272                 faceI,                      // master face for addition
00273                 false,                      // flux flip
00274                 patchID,                    // patch for face
00275                 zoneID,                     // zone for face
00276                 zoneFlip                    // face zone flip
00277             )
00278         );
00279     }
00280 }
00281 
00282 
00283 // Modifies existing faceI for either new owner/neighbour or new face points.
00284 void Foam::meshCutter::modFace
00285 (
00286     polyTopoChange& meshMod,
00287     const label faceI,
00288     const face& newFace,
00289     const label own,
00290     const label nei
00291 )
00292 {
00293     label patchID, zoneID, zoneFlip;
00294 
00295     getFaceInfo(faceI, patchID, zoneID, zoneFlip);
00296 
00297     if
00298     (
00299         (own != mesh().faceOwner()[faceI])
00300      || (
00301             mesh().isInternalFace(faceI)
00302          && (nei != mesh().faceNeighbour()[faceI])
00303         )
00304      || (newFace != mesh().faces()[faceI])
00305     )
00306     {
00307         if (debug & 2)
00308         {
00309             Pout<< "Modifying face " << faceI
00310                 << " old vertices:" << mesh().faces()[faceI]
00311                 << " new vertices:" << newFace
00312                 << " new owner:" << own
00313                 << " new neighbour:" << nei
00314                 << " new zoneID:" << zoneID
00315                 << " new zoneFlip:" << zoneFlip
00316                 << endl;
00317         }
00318 
00319         if ((nei == -1) || (own < nei))
00320         {
00321             meshMod.setAction
00322             (
00323                 polyModifyFace
00324                 (
00325                     newFace,            // modified face
00326                     faceI,              // label of face being modified
00327                     own,                // owner
00328                     nei,                // neighbour
00329                     false,              // face flip
00330                     patchID,            // patch for face
00331                     false,              // remove from zone
00332                     zoneID,             // zone for face
00333                     zoneFlip            // face flip in zone
00334                 )
00335             );
00336         }
00337         else
00338         {
00339             meshMod.setAction
00340             (
00341                 polyModifyFace
00342                 (
00343                     newFace.reverseFace(),  // modified face
00344                     faceI,                  // label of face being modified
00345                     nei,                    // owner
00346                     own,                    // neighbour
00347                     false,                  // face flip
00348                     patchID,                // patch for face
00349                     false,                  // remove from zone
00350                     zoneID,                 // zone for face
00351                     zoneFlip                // face flip in zone
00352                 )
00353             );
00354         }
00355     }
00356 }
00357 
00358 
00359 // Copies face starting from startFp up to and including endFp.
00360 void Foam::meshCutter::copyFace
00361 (
00362     const face& f,
00363     const label startFp,
00364     const label endFp,
00365     face& newFace
00366 ) const
00367 {
00368     label fp = startFp;
00369 
00370     label newFp = 0;
00371 
00372     while (fp != endFp)
00373     {
00374         newFace[newFp++] = f[fp];
00375 
00376         fp = (fp + 1) % f.size();
00377     }
00378     newFace[newFp] = f[fp];
00379 }
00380 
00381 
00382 // Actually split face in two along splitEdge v0, v1 (the two vertices in new
00383 // vertex numbering). Generates faces in same ordering
00384 // as original face. Replaces cutEdges by the points introduced on them
00385 // (addedPoints_).
00386 void Foam::meshCutter::splitFace
00387 (
00388     const face& f,
00389     const label v0,
00390     const label v1,
00391 
00392     face& f0,
00393     face& f1
00394 ) const
00395 {
00396     // Check if we find any new vertex which is part of the splitEdge.
00397     label startFp = findIndex(f, v0);
00398 
00399     if (startFp == -1)
00400     {
00401         FatalErrorIn
00402         (
00403             "meshCutter::splitFace"
00404             ", const face&, const label, const label, face&, face&)"
00405         )   << "Cannot find vertex (new numbering) " << v0
00406             << " on face " << f
00407             << abort(FatalError);
00408     }
00409 
00410     label endFp = findIndex(f, v1);
00411 
00412     if (endFp == -1)
00413     {
00414         FatalErrorIn
00415         (
00416             "meshCutter::splitFace("
00417             ", const face&, const label, const label, face&, face&)"
00418         )   << "Cannot find vertex (new numbering) " << v1
00419             << " on face " << f
00420             << abort(FatalError);
00421     }
00422 
00423 
00424     f0.setSize((endFp + 1 + f.size() - startFp) % f.size());
00425     f1.setSize(f.size() - f0.size() + 2);
00426 
00427     copyFace(f, startFp, endFp, f0);
00428     copyFace(f, endFp, startFp, f1);
00429 }
00430 
00431 
00432 // Adds additional vertices (from edge cutting) to face. Used for faces which
00433 // are not split but still might use edge that has been cut.
00434 Foam::face Foam::meshCutter::addEdgeCutsToFace(const label faceI) const
00435 {
00436     const face& f = mesh().faces()[faceI];
00437 
00438     face newFace(2 * f.size());
00439 
00440     label newFp = 0;
00441 
00442     forAll(f, fp)
00443     {
00444         // Duplicate face vertex .
00445         newFace[newFp++] = f[fp];
00446 
00447         // Check if edge has been cut.
00448         label fp1 = f.fcIndex(fp);
00449 
00450         HashTable<label, edge, Hash<edge> >::const_iterator fnd =
00451             addedPoints_.find(edge(f[fp], f[fp1]));
00452 
00453         if (fnd != addedPoints_.end())
00454         {
00455             // edge has been cut. Introduce new vertex.
00456             newFace[newFp++] = fnd();
00457         }
00458     }
00459 
00460     newFace.setSize(newFp);
00461 
00462     return newFace;
00463 }
00464 
00465 
00466 // Walk loop (loop of cuts) across circumference of cellI. Returns face in
00467 // new vertices.
00468 // Note: tricky bit is that it can use existing edges which have been split.
00469 Foam::face Foam::meshCutter::loopToFace
00470 (
00471     const label cellI,
00472     const labelList& loop
00473 ) const
00474 {
00475     face newFace(2*loop.size());
00476 
00477     label newFaceI = 0;
00478 
00479     forAll(loop, fp)
00480     {
00481         label cut = loop[fp];
00482 
00483         if (isEdge(cut))
00484         {
00485             label edgeI = getEdge(cut);
00486 
00487             const edge& e = mesh().edges()[edgeI];
00488 
00489             label vertI = addedPoints_[e];
00490 
00491             newFace[newFaceI++] = vertI;
00492         }
00493         else
00494         {
00495             // cut is vertex.
00496             label vertI = getVertex(cut);
00497 
00498             newFace[newFaceI++] = vertI;
00499 
00500             label nextCut = loop[loop.fcIndex(fp)];
00501 
00502             if (!isEdge(nextCut))
00503             {
00504                 // From vertex to vertex -> cross cut only if no existing edge.
00505                 label nextVertI = getVertex(nextCut);
00506 
00507                 label edgeI = meshTools::findEdge(mesh(), vertI, nextVertI);
00508 
00509                 if (edgeI != -1)
00510                 {
00511                     // Existing edge. Insert split-edge point if any.
00512                     HashTable<label, edge, Hash<edge> >::const_iterator fnd =
00513                         addedPoints_.find(mesh().edges()[edgeI]);
00514 
00515                     if (fnd != addedPoints_.end())
00516                     {
00517                         newFace[newFaceI++] = fnd();
00518                     }
00519                 }
00520             }
00521         }
00522     }
00523     newFace.setSize(newFaceI);
00524 
00525     return newFace;
00526 }
00527 
00528 
00529 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00530 
00531 // Construct from components
00532 Foam::meshCutter::meshCutter(const polyMesh& mesh)
00533 :
00534     edgeVertex(mesh),
00535     addedCells_(),
00536     addedFaces_(),
00537     addedPoints_()
00538 
00539 {}
00540 
00541 
00542 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00543 
00544 Foam::meshCutter::~meshCutter()
00545 {}
00546 
00547 
00548 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00549 
00550 void Foam::meshCutter::setRefinement
00551 (
00552     const cellCuts& cuts,
00553     polyTopoChange& meshMod
00554 )
00555 {
00556     // Clear and size maps here since mesh size will change.
00557     addedCells_.clear();
00558     addedCells_.resize(cuts.nLoops());
00559 
00560     addedFaces_.clear();
00561     addedFaces_.resize(cuts.nLoops());
00562 
00563     addedPoints_.clear();
00564     addedPoints_.resize(cuts.nLoops());
00565 
00566     if (cuts.nLoops() == 0)
00567     {
00568         return;
00569     }
00570 
00571     const labelListList& anchorPts = cuts.cellAnchorPoints();
00572     const labelListList& cellLoops = cuts.cellLoops();
00573 
00574     //
00575     // Add new points along cut edges.
00576     //
00577 
00578     forAll(cuts.edgeIsCut(), edgeI)
00579     {
00580         if (cuts.edgeIsCut()[edgeI])
00581         {
00582             const edge& e = mesh().edges()[edgeI];
00583 
00584             // Check if there is any cell using this edge.
00585             if (debug && findCutCell(cuts, mesh().edgeCells()[edgeI]) == -1)
00586             {
00587                 FatalErrorIn
00588                 (
00589                     "meshCutter::setRefinement(const cellCuts&"
00590                     ", polyTopoChange&)"
00591                 )   << "Problem: cut edge but none of the cells using it is\n"
00592                     << "edge:" << edgeI << " verts:" << e
00593                     << abort(FatalError);
00594             }
00595 
00596             // One of the edge end points should be master point of nbCellI.
00597             label masterPointI = e.start();
00598 
00599             const point& v0 = mesh().points()[e.start()];
00600             const point& v1 = mesh().points()[e.end()];
00601 
00602             scalar weight = cuts.edgeWeight()[edgeI];
00603 
00604             point newPt = weight*v1 + (1.0-weight)*v0;
00605 
00606             label addedPointI =
00607                 meshMod.setAction
00608                 (
00609                     polyAddPoint
00610                     (
00611                         newPt,              // point
00612                         masterPointI,       // master point
00613                         -1,                 // zone for point
00614                         true                // supports a cell
00615                     )
00616                 );
00617 
00618             // Store on (hash of) edge.
00619             addedPoints_.insert(e, addedPointI);
00620 
00621             if (debug & 2)
00622             {
00623                 Pout<< "Added point " << addedPointI
00624                     << " to vertex "
00625                     << masterPointI << " of edge " << edgeI
00626                     << " vertices " << e << endl;
00627             }
00628         }
00629     }
00630 
00631     //
00632     // Add cells (on 'anchor' side of cell)
00633     //
00634 
00635     forAll(cellLoops, cellI)
00636     {
00637         if (cellLoops[cellI].size())
00638         {
00639             // Add a cell to the existing cell
00640             label addedCellI =
00641                 meshMod.setAction
00642                 (
00643                     polyAddCell
00644                     (
00645                         -1,                 // master point
00646                         -1,                 // master edge
00647                         -1,                 // master face
00648                         cellI,              // master cell
00649                         -1                  // zone for cell
00650                     )
00651                 );
00652 
00653             addedCells_.insert(cellI, addedCellI);
00654 
00655             if (debug & 2)
00656             {
00657                 Pout<< "Added cell " << addedCells_[cellI] << " to cell "
00658                     << cellI << endl;
00659             }
00660         }
00661     }
00662 
00663 
00664     //
00665     // For all cut cells add an internal face
00666     //
00667 
00668     forAll(cellLoops, cellI)
00669     {
00670         const labelList& loop = cellLoops[cellI];
00671 
00672         if (loop.size())
00673         {
00674             //
00675             // Convert loop (=list of cuts) into proper face.
00676             // Orientation should already be ok. (done by cellCuts)
00677             //
00678             face newFace(loopToFace(cellI, loop));
00679 
00680             // Pick any anchor point on cell
00681             label masterPointI = findInternalFacePoint(anchorPts[cellI]);
00682 
00683             label addedFaceI =
00684                 meshMod.setAction
00685                 (
00686                     polyAddFace
00687                     (
00688                         newFace,                // face
00689                         cellI,                  // owner
00690                         addedCells_[cellI],     // neighbour
00691                         masterPointI,           // master point
00692                         -1,                     // master edge
00693                         -1,                     // master face for addition
00694                         false,                  // flux flip
00695                         -1,                     // patch for face
00696                         -1,                     // zone for face
00697                         false                   // face zone flip
00698                     )
00699                 );
00700 
00701             addedFaces_.insert(cellI, addedFaceI);
00702 
00703             if (debug & 2)
00704             {
00705                 // Gets edgeweights of loop
00706                 scalarField weights(loop.size());
00707                 forAll(loop, i)
00708                 {
00709                     label cut = loop[i];
00710 
00711                     weights[i] =
00712                     (
00713                         isEdge(cut)
00714                       ? cuts.edgeWeight()[getEdge(cut)]
00715                       : -GREAT
00716                     );
00717                 }
00718 
00719                 Pout<< "Added splitting face " << newFace << " index:"
00720                     << addedFaceI
00721                     << " to owner " << cellI
00722                     << " neighbour " << addedCells_[cellI]
00723                     << " from Loop:";
00724                 writeCuts(Pout, loop, weights);
00725                 Pout<< endl;
00726             }
00727         }
00728     }
00729 
00730 
00731     //
00732     // Modify faces on the outside and create new ones
00733     // (in effect split old faces into two)
00734     //
00735 
00736     // Maintain whether face has been updated (for -split edges
00737     // -new owner/neighbour)
00738     boolList faceUptodate(mesh().nFaces(), false);
00739 
00740     const Map<edge>& faceSplitCuts = cuts.faceSplitCut();
00741 
00742     for
00743     (
00744         Map<edge>::const_iterator iter = faceSplitCuts.begin();
00745         iter != faceSplitCuts.end();
00746         ++iter
00747     )
00748     {
00749         label faceI = iter.key();
00750 
00751         // Renumber face to include split edges.
00752         face newFace(addEdgeCutsToFace(faceI));
00753 
00754         // Edge splitting the face. Convert cuts to new vertex numbering.
00755         const edge& splitEdge = iter();
00756 
00757         label cut0 = splitEdge[0];
00758 
00759         label v0;
00760         if (isEdge(cut0))
00761         {
00762             label edgeI = getEdge(cut0);
00763             v0 = addedPoints_[mesh().edges()[edgeI]];
00764         }
00765         else
00766         {
00767             v0 = getVertex(cut0);
00768         }
00769 
00770         label cut1 = splitEdge[1];
00771         label v1;
00772         if (isEdge(cut1))
00773         {
00774             label edgeI = getEdge(cut1);
00775             v1 = addedPoints_[mesh().edges()[edgeI]];
00776         }
00777         else
00778         {
00779             v1 = getVertex(cut1);
00780         }
00781 
00782         // Split face along the elements of the splitEdge.
00783         face f0, f1;
00784         splitFace(newFace, v0, v1, f0, f1);
00785 
00786         label own = mesh().faceOwner()[faceI];
00787 
00788         label nei = -1;
00789 
00790         if (mesh().isInternalFace(faceI))
00791         {
00792             nei = mesh().faceNeighbour()[faceI];
00793         }
00794 
00795         if (debug & 2)
00796         {
00797             Pout<< "Split face " << mesh().faces()[faceI]
00798                 << " own:" << own << " nei:" << nei
00799                 << " into f0:" << f0
00800                 << " and f1:" << f1 << endl;
00801         }
00802 
00803         // Check which face uses anchorPoints (connects to addedCell)
00804         // and which one doesn't (connects to original cell)
00805 
00806         // Bit tricky. We have to know whether this faceSplit splits owner/
00807         // neighbour or both. Even if cell is cut we have to make sure this is
00808         // the one that cuts it (this face cut might not be the one splitting
00809         // the cell)
00810 
00811         const face& f = mesh().faces()[faceI];
00812 
00813         label f0Owner = -1;
00814         label f1Owner = -1;
00815 
00816         if (cellLoops[own].empty())
00817         {
00818             f0Owner = own;
00819             f1Owner = own;
00820         }
00821         else if (isIn(splitEdge, cellLoops[own]))
00822         {
00823             // Owner is cut by this splitCut. See which of f0, f1 gets
00824             // owner, which gets addedCells_[owner]
00825             if (uses(f0, anchorPts[own]))
00826             {
00827                 f0Owner = addedCells_[own];
00828                 f1Owner = own;
00829             }
00830             else
00831             {
00832                 f0Owner = own;
00833                 f1Owner = addedCells_[own];
00834             }
00835         }
00836         else
00837         {
00838             // Owner not cut by this splitCut. Check on original face whether
00839             // use anchorPts.
00840             if (uses(f, anchorPts[own]))
00841             {
00842                 label newCellI = addedCells_[own];
00843                 f0Owner = newCellI;
00844                 f1Owner = newCellI;
00845             }
00846             else
00847             {
00848                 f0Owner = own;
00849                 f1Owner = own;
00850             }
00851         }
00852 
00853 
00854         label f0Neighbour = -1;
00855         label f1Neighbour = -1;
00856 
00857         if (nei != -1)
00858         {
00859             if (cellLoops[nei].empty())
00860             {
00861                 f0Neighbour = nei;
00862                 f1Neighbour = nei;
00863             }
00864             else if (isIn(splitEdge, cellLoops[nei]))
00865             {
00866                 // Neighbour is cut by this splitCut. See which of f0, f1
00867                 // gets which neighbour/addedCells_[neighbour]
00868                 if (uses(f0, anchorPts[nei]))
00869                 {
00870                     f0Neighbour = addedCells_[nei];
00871                     f1Neighbour = nei;
00872                 }
00873                 else
00874                 {
00875                     f0Neighbour = nei;
00876                     f1Neighbour = addedCells_[nei];
00877                 }
00878             }
00879             else
00880             {
00881                 // neighbour not cut by this splitCut. Check on original face
00882                 // whether use anchorPts.
00883                 if (uses(f, anchorPts[nei]))
00884                 {
00885                     label newCellI = addedCells_[nei];
00886                     f0Neighbour = newCellI;
00887                     f1Neighbour = newCellI;
00888                 }
00889                 else
00890                 {
00891                     f0Neighbour = nei;
00892                     f1Neighbour = nei;
00893                 }
00894             }
00895         }
00896 
00897         // f0 is the added face, f1 the modified one
00898         addFace(meshMod, faceI, f0, f0Owner, f0Neighbour);
00899 
00900         modFace(meshMod, faceI, f1, f1Owner, f1Neighbour);
00901 
00902         faceUptodate[faceI] = true;
00903     }
00904 
00905 
00906     //
00907     // Faces that have not been split but just appended to. Are guaranteed
00908     // to be reachable from an edgeCut.
00909     //
00910 
00911     const boolList& edgeIsCut = cuts.edgeIsCut();
00912 
00913     forAll(edgeIsCut, edgeI)
00914     {
00915         if (edgeIsCut[edgeI])
00916         {
00917             const labelList& eFaces = mesh().edgeFaces()[edgeI];
00918 
00919             forAll(eFaces, i)
00920             {
00921                 label faceI = eFaces[i];
00922 
00923                 if (!faceUptodate[faceI])
00924                 {
00925                     // Renumber face to include split edges.
00926                     face newFace(addEdgeCutsToFace(faceI));
00927 
00928                     if (debug & 2)
00929                     {
00930                         Pout<< "Added edge cuts to face " << faceI
00931                             << " f:" << mesh().faces()[faceI]
00932                             << " newFace:" << newFace << endl;
00933                     }
00934 
00935                     // Get (new or original) owner and neighbour of faceI
00936                     label own, nei;
00937                     faceCells(cuts, faceI, own, nei);
00938 
00939                     modFace(meshMod, faceI, newFace, own, nei);
00940 
00941                     faceUptodate[faceI] = true;
00942                 }
00943             }
00944         }
00945     }
00946 
00947 
00948     //
00949     // Correct any original faces on split cell for new neighbour/owner
00950     //
00951 
00952     forAll(cellLoops, cellI)
00953     {
00954         if (cellLoops[cellI].size())
00955         {
00956             const labelList& cllFaces = mesh().cells()[cellI];
00957 
00958             forAll(cllFaces, cllFaceI)
00959             {
00960                 label faceI = cllFaces[cllFaceI];
00961 
00962                 if (!faceUptodate[faceI])
00963                 {
00964                     // Update face with new owner/neighbour (if any)
00965                     const face& f = mesh().faces()[faceI];
00966 
00967                     if (debug && (f != addEdgeCutsToFace(faceI)))
00968                     {
00969                         FatalErrorIn
00970                         (
00971                             "meshCutter::setRefinement(const cellCuts&"
00972                             ", polyTopoChange&)"
00973                         )   << "Problem: edges added to face which does "
00974                             << " not use a marked cut" << endl
00975                             << "faceI:" << faceI << endl
00976                             << "face:" << f << endl
00977                             << "newFace:" << addEdgeCutsToFace(faceI)
00978                             << abort(FatalError);
00979                     }
00980 
00981                     // Get (new or original) owner and neighbour of faceI
00982                     label own, nei;
00983                     faceCells(cuts, faceI, own, nei);
00984 
00985                     modFace
00986                     (
00987                         meshMod,
00988                         faceI,
00989                         f,
00990                         own,
00991                         nei
00992                     );
00993 
00994                     faceUptodate[faceI] = true;
00995                 }
00996             }
00997         }
00998     }
00999 
01000     if (debug)
01001     {
01002         Pout<< "meshCutter:" << nl
01003             << "    cells split:" << addedCells_.size() << nl
01004             << "    faces added:" << addedFaces_.size() << nl
01005             << "    points added on edges:" << addedPoints_.size() << nl
01006             << endl;
01007     }
01008 }
01009 
01010 
01011 void Foam::meshCutter::updateMesh(const mapPolyMesh& morphMap)
01012 {
01013     // Update stored labels for mesh change.
01014 
01015     {
01016         // Create copy since new label might (temporarily) clash with existing
01017         // key.
01018         Map<label> newAddedCells(addedCells_.size());
01019 
01020         for
01021         (
01022             Map<label>::const_iterator iter = addedCells_.begin();
01023             iter != addedCells_.end();
01024             ++iter
01025         )
01026         {
01027             label cellI = iter.key();
01028 
01029             label newCellI = morphMap.reverseCellMap()[cellI];
01030 
01031             label addedCellI = iter();
01032 
01033             label newAddedCellI = morphMap.reverseCellMap()[addedCellI];
01034 
01035             if (newCellI >= 0 && newAddedCellI >= 0)
01036             {
01037                 if
01038                 (
01039                     (debug & 2)
01040                  && (newCellI != cellI || newAddedCellI != addedCellI)
01041                 )
01042                 {
01043                     Pout<< "meshCutter::updateMesh :"
01044                         << " updating addedCell for cell " << cellI
01045                         << " from " << addedCellI
01046                         << " to " << newAddedCellI << endl;
01047                 }
01048                 newAddedCells.insert(newCellI, newAddedCellI);
01049             }
01050         }
01051 
01052         // Copy
01053         addedCells_.transfer(newAddedCells);
01054     }
01055 
01056     {
01057         Map<label> newAddedFaces(addedFaces_.size());
01058 
01059         for
01060         (
01061             Map<label>::const_iterator iter = addedFaces_.begin();
01062             iter != addedFaces_.end();
01063             ++iter
01064         )
01065         {
01066             label cellI = iter.key();
01067 
01068             label newCellI = morphMap.reverseCellMap()[cellI];
01069 
01070             label addedFaceI = iter();
01071 
01072             label newAddedFaceI = morphMap.reverseFaceMap()[addedFaceI];
01073 
01074             if ((newCellI >= 0) && (newAddedFaceI >= 0))
01075             {
01076                 if
01077                 (
01078                     (debug & 2)
01079                  && (newCellI != cellI || newAddedFaceI != addedFaceI)
01080                 )
01081                 {
01082                     Pout<< "meshCutter::updateMesh :"
01083                         << " updating addedFace for cell " << cellI
01084                         << " from " << addedFaceI
01085                         << " to " << newAddedFaceI
01086                         << endl;
01087                 }
01088                 newAddedFaces.insert(newCellI, newAddedFaceI);
01089             }
01090         }
01091 
01092         // Copy
01093         addedFaces_.transfer(newAddedFaces);
01094     }
01095 
01096     {
01097         HashTable<label, edge, Hash<edge> > newAddedPoints(addedPoints_.size());
01098 
01099         for
01100         (
01101             HashTable<label, edge, Hash<edge> >::const_iterator iter =
01102                 addedPoints_.begin();
01103             iter != addedPoints_.end();
01104             ++iter
01105         )
01106         {
01107             const edge& e = iter.key();
01108 
01109             label newStart = morphMap.reversePointMap()[e.start()];
01110 
01111             label newEnd = morphMap.reversePointMap()[e.end()];
01112 
01113             label addedPointI = iter();
01114 
01115             label newAddedPointI = morphMap.reversePointMap()[addedPointI];
01116 
01117             if ((newStart >= 0) && (newEnd >= 0) && (newAddedPointI >= 0))
01118             {
01119                 edge newE = edge(newStart, newEnd);
01120 
01121                 if
01122                 (
01123                     (debug & 2)
01124                  && (e != newE || newAddedPointI != addedPointI)
01125                 )
01126                 {
01127                     Pout<< "meshCutter::updateMesh :"
01128                         << " updating addedPoints for edge " << e
01129                         << " from " << addedPointI
01130                         << " to " << newAddedPointI
01131                         << endl;
01132                 }
01133 
01134                 newAddedPoints.insert(newE, newAddedPointI);
01135             }
01136         }
01137 
01138         // Copy
01139         addedPoints_.transfer(newAddedPoints);
01140     }
01141 }
01142 
01143 
01144 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines