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

addPatchCellLayer.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 "addPatchCellLayer.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include "polyTopoChange.H"
00029 #include <meshTools/meshTools.H>
00030 #include <OpenFOAM/mapPolyMesh.H>
00031 #include <OpenFOAM/syncTools.H>
00032 #include <dynamicMesh/polyAddPoint.H>
00033 #include <dynamicMesh/polyAddFace.H>
00034 #include <dynamicMesh/polyModifyFace.H>
00035 #include <dynamicMesh/polyAddCell.H>
00036 #include <meshTools/wallPoint.H>
00037 #include <OpenFOAM/globalIndex.H>
00038 
00039 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00040 
00041 defineTypeNameAndDebug(Foam::addPatchCellLayer, 0);
00042 
00043 
00044 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00045 
00046 // Calculate global faces per pp edge.
00047 Foam::labelListList Foam::addPatchCellLayer::calcGlobalEdgeFaces
00048 (
00049     const polyMesh& mesh,
00050     const globalIndex& globalFaces,
00051     const indirectPrimitivePatch& pp,
00052     const labelList& meshEdges
00053 )
00054 {
00057     //
00058     //PackedBoolList isCoupledEdge(mesh.nEdges());
00059     //
00060     //const polyBoundaryMesh& patches = mesh.boundaryMesh();
00061     //
00062     //forAll(patches, patchI)
00063     //{
00064     //    const polyPatch& pp = patches[patchI];
00065     //
00066     //    if (pp.coupled())
00067     //    {
00068     //        const labelList& meshEdges = pp.meshEdges();
00069     //
00070     //        forAll(meshEdges, i)
00071     //        {
00072     //            isCoupledEdge.set(meshEdges[i], 1);
00073     //        }
00074     //    }
00075     //}
00076 
00077     // From mesh edge to global face labels. Sized only for pp edges.
00078     labelListList globalEdgeFaces(mesh.nEdges());
00079 
00080     const labelListList& edgeFaces = pp.edgeFaces();
00081 
00082     forAll(edgeFaces, edgeI)
00083     {
00084         label meshEdgeI = meshEdges[edgeI];
00085 
00086         //if (isCoupledEdge.get(meshEdgeI) == 1)
00087         {
00088             const labelList& eFaces = edgeFaces[edgeI];
00089 
00090             // Store face and processor as unique tag.
00091             labelList& globalEFaces = globalEdgeFaces[meshEdgeI];
00092             globalEFaces.setSize(eFaces.size());
00093             forAll(eFaces, i)
00094             {
00095                 globalEFaces[i] =
00096                     globalFaces.toGlobal(pp.addressing()[eFaces[i]]);
00097             }
00098         }
00099     }
00100 
00101     // Synchronise across coupled edges.
00102     syncTools::syncEdgeList
00103     (
00104         mesh,
00105         globalEdgeFaces,
00106         uniqueEqOp(),
00107         labelList(),    // null value
00108         false           // no separation
00109     );
00110 
00111     // Extract pp part
00112     return UIndirectList<labelList>(globalEdgeFaces, meshEdges);
00113 }
00114 
00115 
00116 Foam::label Foam::addPatchCellLayer::nbrFace
00117 (
00118     const labelListList& edgeFaces,
00119     const label edgeI,
00120     const label faceI
00121 )
00122 {
00123     const labelList& eFaces = edgeFaces[edgeI];
00124 
00125     if (eFaces.size() == 2)
00126     {
00127         return (eFaces[0] != faceI ? eFaces[0] : eFaces[1]);
00128     }
00129     else
00130     {
00131         return -1;
00132     }
00133 }
00134 
00135 
00136 void Foam::addPatchCellLayer::addVertex
00137 (
00138     const label pointI,
00139     face& f,
00140     label& fp
00141 )
00142 {
00143     if (fp == 0)
00144     {
00145         f[fp++] = pointI;
00146     }
00147     else
00148     {
00149         if (f[fp-1] != pointI && f[0] != pointI)
00150         {
00151             f[fp++] = pointI;
00152         }
00153     }
00154 
00155     // Check for duplicates.
00156     if (debug)
00157     {
00158         label n = 0;
00159         for (label i = 0; i < fp; i++)
00160         {
00161             if (f[i] == pointI)
00162             {
00163                 n++;
00164 
00165                 if (n == 2)
00166                 {
00167                     f.setSize(fp);
00168                     FatalErrorIn
00169                     (
00170                         "addPatchCellLayer::addVertex(const label, face&"
00171                         ", label&)"
00172                     )   << "Point " << pointI << " already present in face "
00173                         << f << abort(FatalError);
00174                 }
00175             }
00176         }
00177     }
00178 }
00179 
00180 
00181 // Is edge to the same neighbour? (and needs extrusion and has not been
00182 // dealt with already)
00183 bool Foam::addPatchCellLayer::sameEdgeNeighbour
00184 (
00185     const indirectPrimitivePatch& pp,
00186     const labelListList& globalEdgeFaces,
00187     const boolList& doneEdge,
00188     const label thisGlobalFaceI,
00189     const label nbrGlobalFaceI,
00190     const label edgeI
00191 ) const
00192 {
00193     const edge& e = pp.edges()[edgeI];
00194 
00195     return
00196         !doneEdge[edgeI]                            // not yet handled
00197      && (
00198             addedPoints_[e[0]].size()               // is extruded
00199          || addedPoints_[e[1]].size()
00200         )
00201      && (
00202             nbrFace(globalEdgeFaces, edgeI, thisGlobalFaceI)
00203          == nbrGlobalFaceI  // is to same neighbour
00204         );
00205 }
00206 
00207 
00208 // Collect consecutive string of edges that connects the same two
00209 // (possibly coupled) faces. Returns -1 if no unvisited edge can be found.
00210 // Otherwise returns start and end index in face.
00211 Foam::labelPair Foam::addPatchCellLayer::getEdgeString
00212 (
00213     const indirectPrimitivePatch& pp,
00214     const labelListList& globalEdgeFaces,
00215     const boolList& doneEdge,
00216     const label patchFaceI,
00217     const label globalFaceI
00218 ) const
00219 {
00220     const labelList& fEdges = pp.faceEdges()[patchFaceI];
00221 
00222     label startFp = -1;
00223     label endFp = -1;
00224 
00225     // Get edge that hasn't been done yet but needs extrusion
00226     forAll(fEdges, fp)
00227     {
00228         label edgeI = fEdges[fp];
00229         const edge& e = pp.edges()[edgeI];
00230 
00231         if
00232         (
00233             !doneEdge[edgeI]
00234          && ( addedPoints_[e[0]].size() || addedPoints_[e[1]].size() )
00235         )
00236         {
00237             startFp = fp;
00238             break;
00239         }
00240     }
00241 
00242     if (startFp != -1)
00243     {
00244         // We found an edge that needs extruding but hasn't been done yet.
00245         // Now find the face on the other side
00246         label nbrGlobalFaceI = nbrFace
00247         (
00248             globalEdgeFaces,
00249             fEdges[startFp],
00250             globalFaceI
00251         );
00252 
00253         if (nbrGlobalFaceI == -1)
00254         {
00255             // Proper boundary edge. Only extrude single edge.
00256             endFp = startFp;
00257         }
00258         else
00259         {
00260             // Search back for edge
00261             // - which hasn't been handled yet
00262             // - with same neighbour
00263             // - that needs extrusion
00264             while(true)
00265             {
00266                 label prevFp = fEdges.rcIndex(startFp);
00267 
00268                 if
00269                 (
00270                     !sameEdgeNeighbour
00271                     (
00272                         pp,
00273                         globalEdgeFaces,
00274                         doneEdge,
00275                         globalFaceI,
00276                         nbrGlobalFaceI,
00277                         fEdges[prevFp]
00278                     )
00279                 )
00280                 {
00281                     break;
00282                 }
00283                 startFp = prevFp;
00284             }
00285 
00286             // Search forward for end of string
00287             endFp = startFp;
00288             while(true)
00289             {
00290                 label nextFp = fEdges.fcIndex(endFp);
00291 
00292                 if
00293                 (
00294                     !sameEdgeNeighbour
00295                     (
00296                         pp,
00297                         globalEdgeFaces,
00298                         doneEdge,
00299                         globalFaceI,
00300                         nbrGlobalFaceI,
00301                         fEdges[nextFp]
00302                     )
00303                 )
00304                 {
00305                     break;
00306                 }
00307                 endFp = nextFp;
00308             }
00309         }
00310     }
00311 
00312     return labelPair(startFp, endFp);
00313 }
00314 
00315 
00316 // Adds a side face i.e. extrudes a patch edge.
00317 Foam::label Foam::addPatchCellLayer::addSideFace
00318 (
00319     const indirectPrimitivePatch& pp,
00320     const labelList& patchID,           // prestored patch per pp face
00321     const labelListList& addedCells,    // per pp face the new extruded cell
00322     const face& newFace,
00323     const label ownFaceI,               // pp face that provides owner
00324     const label nbrFaceI,
00325     const label patchEdgeI,             // edge to add to
00326     const label meshEdgeI,              // corresponding mesh edge
00327     const label layerI,                 // layer
00328     const label numEdgeFaces,           // number of layers for edge
00329     const labelList& meshFaces,         // precalculated edgeFaces
00330     polyTopoChange& meshMod
00331 ) const
00332 {
00333     // Edge to 'inflate' from
00334     label inflateEdgeI = -1;
00335 
00336     // Check mesh faces using edge
00337     forAll(meshFaces, i)
00338     {
00339         if (mesh_.isInternalFace(meshFaces[i]))
00340         {
00341             // meshEdge uses internal faces so ok to inflate from it
00342             inflateEdgeI = meshEdgeI;
00343             break;
00344         }
00345     }
00346 
00347 
00348     // Get my mesh face and its zone.
00349     label meshFaceI = pp.addressing()[ownFaceI];
00350     // Zone info comes from any side patch face. Otherwise -1 since we
00351     // don't know what to put it in - inherit from the extruded faces?
00352     label zoneI = -1;   //mesh_.faceZones().whichZone(meshFaceI);
00353     bool flip = false;
00354 
00355     label addedFaceI = -1;
00356 
00357     // Is patch edge external edge of indirectPrimitivePatch?
00358     if (nbrFaceI == -1)
00359     {
00360         // External edge so external face. Patch id is obtained from
00361         // any other patch connected to edge.
00362 
00363         const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00364 
00365         // Loop over all faces connected to edge to inflate and
00366         // see if any boundary face (but not meshFaceI)
00367         label otherPatchID = patchID[ownFaceI];
00368 
00369         forAll(meshFaces, k)
00370         {
00371             label faceI = meshFaces[k];
00372 
00373             if
00374             (
00375                 faceI != meshFaceI
00376              && !mesh_.isInternalFace(faceI)
00377             )
00378             {
00379                 otherPatchID = patches.whichPatch(faceI);
00380                 zoneI = mesh_.faceZones().whichZone(faceI);
00381                 if (zoneI != -1)
00382                 {
00383                     label index = mesh_.faceZones()[zoneI].whichFace(faceI);
00384                     flip = mesh_.faceZones()[zoneI].flipMap()[index];
00385                 }
00386                 break;
00387             }
00388         }
00389 
00390         // Determine if different number of layer on owner and neighbour side
00391         // (relevant only for coupled faces). See section for internal edge
00392         // below.
00393 
00394         label layerOwn;
00395 
00396         if (addedCells[ownFaceI].size() < numEdgeFaces)
00397         {
00398             label offset = numEdgeFaces - addedCells[ownFaceI].size();
00399             if (layerI <= offset)
00400             {
00401                 layerOwn = 0;
00402             }
00403             else
00404             {
00405                 layerOwn = layerI - offset;
00406             }
00407         }
00408         else
00409         {
00410             layerOwn = layerI;
00411         }
00412 
00413 
00414         //Pout<< "Added boundary face:" << newFace
00415         //    << " own:" << addedCells[ownFaceI][layerOwn]
00416         //    << " patch:" << otherPatchID
00417         //    << endl;
00418 
00419         addedFaceI = meshMod.setAction
00420         (
00421             polyAddFace
00422             (
00423                 newFace,                    // face
00424                 addedCells[ownFaceI][layerOwn],   // owner
00425                 -1,                         // neighbour
00426                 -1,                         // master point
00427                 inflateEdgeI,               // master edge
00428                 -1,                         // master face
00429                 false,                      // flux flip
00430                 otherPatchID,               // patch for face
00431                 zoneI,                      // zone for face
00432                 flip                        // face zone flip
00433             )
00434         );
00435     }
00436     else
00437     {
00438         // When adding side faces we need to modify neighbour and owners
00439         // in region where layer mesh is stopped. Determine which side
00440         // has max number of faces and make sure layers match closest to
00441         // original pp if there are different number of layers.
00442 
00443         label layerNbr;
00444         label layerOwn;
00445 
00446         if (addedCells[ownFaceI].size() > addedCells[nbrFaceI].size())
00447         {
00448             label offset =
00449                 addedCells[ownFaceI].size() - addedCells[nbrFaceI].size();
00450 
00451             layerOwn = layerI;
00452 
00453             if (layerI <= offset)
00454             {
00455                 layerNbr = 0;
00456             }
00457             else
00458             {
00459                 layerNbr = layerI - offset;
00460             }
00461         }
00462         else if (addedCells[nbrFaceI].size() > addedCells[ownFaceI].size())
00463         {
00464             label offset =
00465                 addedCells[nbrFaceI].size() - addedCells[ownFaceI].size();
00466 
00467             layerNbr = layerI;
00468 
00469             if (layerI <= offset)
00470             {
00471                 layerOwn = 0;
00472             }
00473             else
00474             {
00475                 layerOwn = layerI - offset;
00476             }
00477         }
00478         else
00479         {
00480             // Same number of layers on both sides.
00481             layerNbr = layerI;
00482             layerOwn = layerI;
00483         }
00484 
00485         addedFaceI = meshMod.setAction
00486         (
00487             polyAddFace
00488             (
00489                 newFace,                    // face
00490                 addedCells[ownFaceI][layerOwn],   // owner
00491                 addedCells[nbrFaceI][layerNbr],   // neighbour
00492                 -1,                         // master point
00493                 inflateEdgeI,               // master edge
00494                 -1,                         // master face
00495                 false,                      // flux flip
00496                 -1,                         // patch for face
00497                 zoneI,                      // zone for face
00498                 flip                        // face zone flip
00499             )
00500         );
00501 
00502        //Pout<< "Added internal face:" << newFace
00503         //    << " own:" << addedCells[ownFaceI][layerOwn]
00504         //    << " nei:" << addedCells[nbrFaceI][layerNbr]
00505         //    << endl;
00506     }
00507 
00508     return addedFaceI;
00509 }
00510 
00511 
00512 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00513 
00514 // Construct from mesh
00515 Foam::addPatchCellLayer::addPatchCellLayer(const polyMesh& mesh)
00516 :
00517     mesh_(mesh),
00518     addedPoints_(0),
00519     layerFaces_(0)
00520 {}
00521 
00522 
00523 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00524 
00525 Foam::labelListList Foam::addPatchCellLayer::addedCells
00526 (
00527     const polyMesh& mesh,
00528     const labelListList& layerFaces
00529 )
00530 {
00531     labelListList layerCells(layerFaces.size());
00532 
00533     forAll(layerFaces, patchFaceI)
00534     {
00535         const labelList& faceLabels = layerFaces[patchFaceI];
00536 
00537         if (faceLabels.size())
00538         {
00539             labelList& added = layerCells[patchFaceI];
00540             added.setSize(faceLabels.size()-1);
00541 
00542             for (label i = 0; i < faceLabels.size()-1; i++)
00543             {
00544                 added[i] = mesh.faceNeighbour()[faceLabels[i]];
00545             }
00546         }
00547     }
00548     return layerCells;
00549 }
00550 
00551 
00552 Foam::labelListList Foam::addPatchCellLayer::addedCells() const
00553 {
00554     return addedCells(mesh_, layerFaces_);
00555 }
00556 
00557 
00558 void Foam::addPatchCellLayer::setRefinement
00559 (
00560     const scalarField& expansionRatio,
00561     const indirectPrimitivePatch& pp,
00562     const labelList& nFaceLayers,
00563     const labelList& nPointLayers,
00564     const vectorField& firstLayerDisp,
00565     polyTopoChange& meshMod
00566 )
00567 {
00568     if (debug)
00569     {
00570         Pout<< "addPatchCellLayer::setRefinement : Adding up to "
00571             << max(nPointLayers)
00572             << " layers of cells to indirectPrimitivePatch with "
00573             << pp.nPoints() << " points" << endl;
00574     }
00575 
00576     if
00577     (
00578         pp.nPoints() != firstLayerDisp.size()
00579      || pp.nPoints() != nPointLayers.size()
00580      || pp.size() != nFaceLayers.size()
00581     )
00582     {
00583         FatalErrorIn
00584         (
00585             "addPatchCellLayer::setRefinement"
00586             "(const scalar, const indirectPrimitivePatch&"
00587             ", const labelList&, const vectorField&, polyTopoChange&)"
00588         )   << "Size of new points is not same as number of points used by"
00589             << " the face subset" << endl
00590             << "  patch.nPoints:" << pp.nPoints()
00591             << "  displacement:" << firstLayerDisp.size()
00592             << "  nPointLayers:" << nPointLayers.size() << nl
00593             << " patch.nFaces:" << pp.size()
00594             << "  nFaceLayers:" << nFaceLayers.size()
00595             << abort(FatalError);
00596     }
00597 
00598     forAll(nPointLayers, i)
00599     {
00600         if (nPointLayers[i] < 0)
00601         {
00602             FatalErrorIn
00603             (
00604                 "addPatchCellLayer::setRefinement"
00605                 "(const scalar, const indirectPrimitivePatch&"
00606                 ", const labelList&, const vectorField&, polyTopoChange&)"
00607             )   << "Illegal number of layers " << nPointLayers[i]
00608                 << " at patch point " << i << abort(FatalError);
00609         }
00610     }
00611     forAll(nFaceLayers, i)
00612     {
00613         if (nFaceLayers[i] < 0)
00614         {
00615             FatalErrorIn
00616             (
00617                 "addPatchCellLayer::setRefinement"
00618                 "(const scalar, const indirectPrimitivePatch&"
00619                 ", const labelList&, const vectorField&, polyTopoChange&)"
00620             )   << "Illegal number of layers " << nFaceLayers[i]
00621                 << " at patch face " << i << abort(FatalError);
00622         }
00623     }
00624 
00625     const labelList& meshPoints = pp.meshPoints();
00626 
00627     // Some storage for edge-face-addressing.
00628     DynamicList<label> ef;
00629 
00630     // Precalculate mesh edges for pp.edges.
00631     labelList meshEdges(calcMeshEdges(mesh_, pp));
00632 
00633     if (debug)
00634     {
00635         // Check synchronisation
00636         // ~~~~~~~~~~~~~~~~~~~~~
00637 
00638         {
00639             labelList n(mesh_.nPoints(), 0);
00640             UIndirectList<label>(n, meshPoints) = nPointLayers;
00641             syncTools::syncPointList(mesh_, n, maxEqOp<label>(), 0, false);
00642 
00643             // Non-synced
00644             forAll(meshPoints, i)
00645             {
00646                 label meshPointI = meshPoints[i];
00647 
00648                 if (n[meshPointI] != nPointLayers[i])
00649                 {
00650                     FatalErrorIn
00651                     (
00652                         "addPatchCellLayer::setRefinement"
00653                         "(const scalar, const indirectPrimitivePatch&"
00654                         ", const labelList&, const vectorField&"
00655                         ", polyTopoChange&)"
00656                     )   << "At mesh point:" << meshPointI
00657                         << " coordinate:" << mesh_.points()[meshPointI]
00658                         << " specified nLayers:" << nPointLayers[i] << endl
00659                         << "On coupled point a different nLayers:"
00660                         << n[meshPointI] << " was specified."
00661                         << abort(FatalError);
00662                 }
00663             }
00664 
00665 
00666             // Check that nPointLayers equals the max layers of connected faces
00667             // (or 0). Anything else makes no sense.
00668             labelList nFromFace(mesh_.nPoints(), 0);
00669             forAll(nFaceLayers, i)
00670             {
00671                 const face& f = pp[i];
00672 
00673                 forAll(f, fp)
00674                 {
00675                     label pointI = f[fp];
00676 
00677                     nFromFace[pointI] = max(nFromFace[pointI], nFaceLayers[i]);
00678                 }
00679             }
00680             syncTools::syncPointList
00681             (
00682                 mesh_,
00683                 nFromFace,
00684                 maxEqOp<label>(),
00685                 0,
00686                 false
00687             );
00688 
00689             forAll(nPointLayers, i)
00690             {
00691                 label meshPointI = meshPoints[i];
00692 
00693                 if
00694                 (
00695                     nPointLayers[i] > 0
00696                  && nPointLayers[i] != nFromFace[meshPointI]
00697                 )
00698                 {
00699                     FatalErrorIn
00700                     (
00701                         "addPatchCellLayer::setRefinement"
00702                         "(const scalar, const indirectPrimitivePatch&"
00703                         ", const labelList&, const vectorField&"
00704                         ", polyTopoChange&)"
00705                     )   << "At mesh point:" << meshPointI
00706                         << " coordinate:" << mesh_.points()[meshPointI]
00707                         << " specified nLayers:" << nPointLayers[i] << endl
00708                         << "but the max nLayers of surrounding faces is:"
00709                         << nFromFace[meshPointI]
00710                         << abort(FatalError);
00711                 }
00712             }
00713         }
00714 
00715         {
00716             pointField d(mesh_.nPoints(), wallPoint::greatPoint);
00717             UIndirectList<point>(d, meshPoints) = firstLayerDisp;
00718             syncTools::syncPointList
00719             (
00720                 mesh_,
00721                 d,
00722                 minEqOp<vector>(),
00723                 wallPoint::greatPoint,
00724                 false
00725             );
00726 
00727             forAll(meshPoints, i)
00728             {
00729                 label meshPointI = meshPoints[i];
00730 
00731                 if (mag(d[meshPointI] - firstLayerDisp[i]) > SMALL)
00732                 {
00733                     FatalErrorIn
00734                     (
00735                         "addPatchCellLayer::setRefinement"
00736                         "(const scalar, const indirectPrimitivePatch&"
00737                         ", const labelList&, const vectorField&"
00738                         ", polyTopoChange&)"
00739                     )   << "At mesh point:" << meshPointI
00740                         << " coordinate:" << mesh_.points()[meshPointI]
00741                         << " specified displacement:" << firstLayerDisp[i]
00742                         << endl
00743                         << "On coupled point a different displacement:"
00744                         << d[meshPointI] << " was specified."
00745                         << abort(FatalError);
00746                 }
00747             }
00748         }
00749 
00750         // Check that edges of pp (so ones that become boundary faces)
00751         // connect to only one boundary face. Guarantees uniqueness of
00752         // patch that they go into so if this is a coupled patch both
00753         // sides decide the same.
00754         // ~~~~~~~~~~~~~~~~~~~~~~
00755 
00756         for (label edgeI = pp.nInternalEdges(); edgeI < pp.nEdges(); edgeI++)
00757         {
00758             const edge& e = pp.edges()[edgeI];
00759 
00760             if (nPointLayers[e[0]] > 0 || nPointLayers[e[1]] > 0)
00761             {
00762                 // Edge is to become a face
00763 
00764                 const labelList& eFaces = pp.edgeFaces()[edgeI];
00765 
00766                 // First check: pp should be single connected.
00767                 if (eFaces.size() != 1)
00768                 {
00769                     FatalErrorIn
00770                     (
00771                         "addPatchCellLayer::setRefinement"
00772                         "(const scalar, const indirectPrimitivePatch&"
00773                         ", const labelList&, const vectorField&"
00774                         ", polyTopoChange&)"
00775                     )   << "boundary-edge-to-be-extruded:"
00776                         << pp.points()[meshPoints[e[0]]]
00777                         << pp.points()[meshPoints[e[1]]]
00778                         << " has more than two faces using it:" << eFaces
00779                         << abort(FatalError);
00780                 }
00781 
00782                 label myFaceI = pp.addressing()[eFaces[0]];
00783 
00784                 label meshEdgeI = meshEdges[edgeI];
00785 
00786                 // Mesh faces using edge
00787 
00788                 // Mesh faces using edge
00789                 const labelList& meshFaces = mesh_.edgeFaces(meshEdgeI, ef);
00790 
00791                 // Check that there is only one patchface using edge.
00792                 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00793 
00794                 label bFaceI = -1;
00795 
00796                 forAll(meshFaces, i)
00797                 {
00798                     label faceI = meshFaces[i];
00799 
00800                     if (faceI != myFaceI)
00801                     {
00802                         if (!mesh_.isInternalFace(faceI))
00803                         {
00804                             if (bFaceI == -1)
00805                             {
00806                                 bFaceI = faceI;
00807                             }
00808                             else
00809                             {
00810                                 FatalErrorIn
00811                                 (
00812                                     "addPatchCellLayer::setRefinement"
00813                                     "(const scalar"
00814                                     ", const indirectPrimitivePatch&"
00815                                     ", const labelList&, const vectorField&"
00816                                     ", polyTopoChange&)"
00817                                 )   << "boundary-edge-to-be-extruded:"
00818                                     << pp.points()[meshPoints[e[0]]]
00819                                     << pp.points()[meshPoints[e[1]]]
00820                                     << " has more than two boundary faces"
00821                                     << " using it:"
00822                                     << bFaceI << " fc:"
00823                                     << mesh_.faceCentres()[bFaceI]
00824                                     << " patch:" << patches.whichPatch(bFaceI)
00825                                     << " and " << faceI << " fc:"
00826                                     << mesh_.faceCentres()[faceI]
00827                                     << " patch:" << patches.whichPatch(faceI)
00828                                     << abort(FatalError);
00829                             }
00830                         }
00831                     }
00832                 }
00833             }
00834         }
00835     }
00836 
00837 
00838     // From master point (in patch point label) to added points (in mesh point
00839     // label)
00840     addedPoints_.setSize(pp.nPoints());
00841 
00842     // Mark points that do not get extruded by setting size of addedPoints_ to 0
00843     label nTruncated = 0;
00844 
00845     forAll(nPointLayers, patchPointI)
00846     {
00847         if (nPointLayers[patchPointI] > 0)
00848         {
00849             addedPoints_[patchPointI].setSize(nPointLayers[patchPointI]);
00850         }
00851         else
00852         {
00853             nTruncated++;
00854         }
00855     }
00856 
00857     if (debug)
00858     {
00859         Pout<< "Not adding points at " << nTruncated << " out of "
00860             << pp.nPoints() << " points" << endl;
00861     }
00862 
00863 
00864     //
00865     // Create new points
00866     //
00867 
00868     forAll(firstLayerDisp, patchPointI)
00869     {
00870         if (addedPoints_[patchPointI].size())
00871         {
00872             label meshPointI = meshPoints[patchPointI];
00873 
00874             label zoneI = mesh_.pointZones().whichZone(meshPointI);
00875 
00876             point pt = mesh_.points()[meshPointI];
00877 
00878             vector disp = firstLayerDisp[patchPointI];
00879 
00880             for (label i = 0; i < addedPoints_[patchPointI].size(); i++)
00881             {
00882                 pt += disp;
00883 
00884                 label addedVertI = meshMod.setAction
00885                 (
00886                     polyAddPoint
00887                     (
00888                         pt,         // point
00889                         meshPointI, // master point
00890                         zoneI,      // zone for point
00891                         true        // supports a cell
00892                     )
00893                 );
00894 
00895                 addedPoints_[patchPointI][i] = addedVertI;
00896 
00897                 disp *= expansionRatio[patchPointI];
00898             }
00899         }
00900     }
00901 
00902 
00903     //
00904     // Add cells to all boundaryFaces
00905     //
00906 
00907     labelListList addedCells(pp.size());
00908 
00909     forAll(pp, patchFaceI)
00910     {
00911         if (nFaceLayers[patchFaceI] > 0)
00912         {
00913             addedCells[patchFaceI].setSize(nFaceLayers[patchFaceI]);
00914 
00915             label meshFaceI = pp.addressing()[patchFaceI];
00916 
00917             label ownZoneI = mesh_.cellZones().whichZone
00918             (
00919                 mesh_.faceOwner()[meshFaceI]
00920             );
00921 
00922             for (label i = 0; i < nFaceLayers[patchFaceI]; i++)
00923             {
00924                 // Note: add from cell (owner of patch face) or from face?
00925                 // for now add from cell so we can map easily.
00926                 addedCells[patchFaceI][i] = meshMod.setAction
00927                 (
00928                     polyAddCell
00929                     (
00930                         -1,             // master point
00931                         -1,             // master edge
00932                         -1,             // master face
00933                         mesh_.faceOwner()[meshFaceI],   // master cell id
00934                         ownZoneI        // zone for cell
00935                     )
00936                 );
00937 
00938                 //Pout<< "For patchFace:" << patchFaceI
00939                 //    << " meshFace:" << pp.addressing()[patchFaceI]
00940                 //    << " layer:" << i << " added cell:"
00941                 //    << addedCells[patchFaceI][i]
00942                 //    << endl;
00943             }
00944         }
00945     }
00946 
00947 
00948     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00949 
00950     // Precalculated patchID for each patch face
00951     labelList patchID(pp.size());
00952 
00953     forAll(pp, patchFaceI)
00954     {
00955         label meshFaceI = pp.addressing()[patchFaceI];
00956 
00957         patchID[patchFaceI] = patches.whichPatch(meshFaceI);
00958     }
00959 
00960 
00961 
00962     // Create faces on top of the original patch faces.
00963     // These faces are created from original patch faces outwards so in order
00964     // of increasing cell number. So orientation should be same as original
00965     // patch face for them to have owner<neighbour.
00966 
00967     layerFaces_.setSize(pp.size());
00968 
00969     forAll(pp.localFaces(), patchFaceI)
00970     {
00971         label meshFaceI = pp.addressing()[patchFaceI];
00972 
00973         if (addedCells[patchFaceI].size())
00974         {
00975             layerFaces_[patchFaceI].setSize(addedCells[patchFaceI].size() + 1);
00976             layerFaces_[patchFaceI][0] = meshFaceI;
00977 
00978             // Get duplicated vertices on the patch face.
00979             const face& f = pp.localFaces()[patchFaceI];
00980 
00981             face newFace(f.size());
00982 
00983             for (label i = 0; i < addedCells[patchFaceI].size(); i++)
00984             {
00985                 forAll(f, fp)
00986                 {
00987                     if (addedPoints_[f[fp]].empty())
00988                     {
00989                         // Keep original point
00990                         newFace[fp] = meshPoints[f[fp]];
00991                     }
00992                     else
00993                     {
00994                         // Get new outside point
00995                         label offset =
00996                             addedPoints_[f[fp]].size()
00997                           - addedCells[patchFaceI].size();
00998                         newFace[fp] = addedPoints_[f[fp]][i+offset];
00999                     }
01000                 }
01001 
01002 
01003                 // Get new neighbour
01004                 label nei;
01005                 label patchI;
01006                 label zoneI = -1;
01007                 bool flip = false;
01008 
01009 
01010                 if (i == addedCells[patchFaceI].size()-1)
01011                 {
01012                     // Top layer so is patch face.
01013                     nei = -1;
01014                     patchI = patchID[patchFaceI];
01015                     zoneI = mesh_.faceZones().whichZone(meshFaceI);
01016                     if (zoneI != -1)
01017                     {
01018                         const faceZone& fz = mesh_.faceZones()[zoneI];
01019                         flip = fz.flipMap()[fz.whichFace(meshFaceI)];
01020                     }
01021                 }
01022                 else
01023                 {
01024                     // Internal face between layer i and i+1
01025                     nei = addedCells[patchFaceI][i+1];
01026                     patchI = -1;
01027                 }
01028 
01029 
01030                 layerFaces_[patchFaceI][i+1] = meshMod.setAction
01031                 (
01032                     polyAddFace
01033                     (
01034                         newFace,                    // face
01035                         addedCells[patchFaceI][i],  // owner
01036                         nei,                        // neighbour
01037                         -1,                         // master point
01038                         -1,                         // master edge
01039                         meshFaceI,                  // master face for addition
01040                         false,                      // flux flip
01041                         patchI,                     // patch for face
01042                         zoneI,                      // zone for face
01043                         flip                        // face zone flip
01044                     )
01045                 );
01046                 //Pout<< "Added inbetween face " << newFace
01047                 //    << " own:" << addedCells[patchFaceI][i]
01048                 //    << " nei:" << nei
01049                 //    << " patch:" << patchI
01050                 //    << endl;
01051             }
01052         }
01053     }
01054 
01055     //
01056     // Modify old patch faces to be on the inside
01057     //
01058     forAll(pp, patchFaceI)
01059     {
01060         if (addedCells[patchFaceI].size())
01061         {
01062             label meshFaceI = pp.addressing()[patchFaceI];
01063 
01064             meshMod.setAction
01065             (
01066                 polyModifyFace
01067                 (
01068                     pp[patchFaceI],                 // modified face
01069                     meshFaceI,                      // label of face
01070                     mesh_.faceOwner()[meshFaceI],   // owner
01071                     addedCells[patchFaceI][0],      // neighbour
01072                     false,                          // face flip
01073                     -1,                             // patch for face
01074                     true, //false,                        // remove from zone
01075                     -1, //zoneI,                          // zone for face
01076                     false                           // face flip in zone
01077                 )
01078             );
01079             //Pout<< "Modified old patch face " << meshFaceI
01080             //    << " own:" << mesh_.faceOwner()[meshFaceI]
01081             //    << " nei:" << addedCells[patchFaceI][0]
01082             //    << endl;
01083         }
01084     }
01085 
01086 
01087     //
01088     // Create 'side' faces, one per edge that is being extended.
01089     //
01090 
01091     const labelListList& faceEdges = pp.faceEdges();
01092     const faceList& localFaces = pp.localFaces();
01093     const edgeList& edges = pp.edges();
01094 
01095     // Get number of layers per edge. This is 0 if edge is not extruded;
01096     // max of connected faces otherwise.
01097     labelList edgeLayers(pp.nEdges());
01098 
01099     {
01100         // Use list over mesh.nEdges() since syncTools does not yet support
01101         // partial list synchronisation.
01102         labelList meshEdgeLayers(mesh_.nEdges(), -1);
01103 
01104         forAll(meshEdges, edgeI)
01105         {
01106             const edge& e = edges[edgeI];
01107 
01108             label meshEdgeI = meshEdges[edgeI];
01109 
01110             if ((nPointLayers[e[0]] == 0) && (nPointLayers[e[1]] == 0))
01111             {
01112                 meshEdgeLayers[meshEdgeI] = 0;
01113             }
01114             else
01115             {
01116                 const labelList& eFaces = pp.edgeFaces()[edgeI];
01117 
01118                 forAll(eFaces, i)
01119                 {
01120                     meshEdgeLayers[meshEdgeI] = max
01121                     (
01122                         nFaceLayers[eFaces[i]],
01123                         meshEdgeLayers[meshEdgeI]
01124                     );
01125                 }
01126             }
01127         }
01128 
01129         syncTools::syncEdgeList
01130         (
01131             mesh_,
01132             meshEdgeLayers,
01133             maxEqOp<label>(),
01134             0,                  // initial value
01135             false               // no separation
01136         );
01137 
01138         forAll(meshEdges, edgeI)
01139         {
01140             edgeLayers[edgeI] = meshEdgeLayers[meshEdges[edgeI]];
01141         }
01142     }
01143 
01144 
01145     // Global indices engine
01146     const globalIndex globalFaces(mesh_.nFaces());
01147 
01148     // Get for all pp edgeFaces a unique faceID
01149     labelListList globalEdgeFaces
01150     (
01151          calcGlobalEdgeFaces
01152          (
01153             mesh_,
01154             globalFaces,
01155             pp,
01156             meshEdges
01157         )
01158     );
01159 
01160 
01161     // Mark off which edges have been extruded
01162     boolList doneEdge(pp.nEdges(), false);
01163 
01164 
01165     // Create faces. Per face walk connected edges and find string of edges
01166     // between the same two faces and extrude string into a single face.
01167     forAll(pp, patchFaceI)
01168     {
01169         const labelList& fEdges = faceEdges[patchFaceI];
01170 
01171         forAll(fEdges, fp)
01172         {
01173             // Get string of edges that needs to be extruded as a single face.
01174             // Returned as indices in fEdges.
01175             labelPair indexPair
01176             (
01177                 getEdgeString
01178                 (
01179                     pp,
01180                     globalEdgeFaces,
01181                     doneEdge,
01182                     patchFaceI,
01183                     globalFaces.toGlobal(pp.addressing()[patchFaceI])
01184                 )
01185             );
01186 
01187             //Pout<< "Found unextruded edges in edges:" << fEdges
01188             //    << " start:" << indexPair[0]
01189             //    << " end:" << indexPair[1]
01190             //    << endl;
01191 
01192             const label startFp = indexPair[0];
01193             const label endFp = indexPair[1];
01194 
01195             if (startFp != -1)
01196             {
01197                 // Extrude edges from indexPair[0] up to indexPair[1]
01198                 // (note indexPair = indices of edges. There is one more vertex
01199                 //  than edges)
01200                 const face& f = localFaces[patchFaceI];
01201 
01202                 labelList stringedVerts;
01203                 if (endFp >= startFp)
01204                 {
01205                     stringedVerts.setSize(endFp-startFp+2);
01206                 }
01207                 else
01208                 {
01209                     stringedVerts.setSize(endFp+f.size()-startFp+2);
01210                 }
01211 
01212                 label fp = startFp;
01213 
01214                 for (label i = 0; i < stringedVerts.size()-1; i++)
01215                 {
01216                     stringedVerts[i] = f[fp];
01217                     doneEdge[fEdges[fp]] = true;
01218                     fp = f.fcIndex(fp);
01219                 }
01220                 stringedVerts[stringedVerts.size()-1] = f[fp];
01221 
01222 
01223                 // Now stringedVerts contains the vertices in order of face f.
01224                 // This is consistent with the order if f becomes the owner cell
01225                 // and nbrFaceI the neighbour cell. Note that the cells get
01226                 // added in order of pp so we can just use face ordering and
01227                 // because we loop in incrementing order as well we will
01228                 // always have nbrFaceI > patchFaceI.
01229 
01230                 label startEdgeI = fEdges[startFp];
01231 
01232                 label meshEdgeI = meshEdges[startEdgeI];
01233 
01234                 label numEdgeSideFaces = edgeLayers[startEdgeI];
01235 
01236                 for (label i = 0; i < numEdgeSideFaces; i++)
01237                 {
01238                     label vEnd = stringedVerts[stringedVerts.size()-1];
01239                     label vStart = stringedVerts[0];
01240 
01241                     // calculate number of points making up a face
01242                     label newFp = 2*stringedVerts.size();
01243 
01244                     if (i == 0)
01245                     {
01246                         // layer 0 gets all the truncation of neighbouring
01247                         // faces with more layers.
01248                         if (addedPoints_[vEnd].size())
01249                         {
01250                             newFp += 
01251                                 addedPoints_[vEnd].size() - numEdgeSideFaces;
01252                         }
01253                         if (addedPoints_[vStart].size())
01254                         {
01255                             newFp +=
01256                                 addedPoints_[vStart].size() - numEdgeSideFaces;
01257                         }
01258                     }
01259 
01260                     face newFace(newFp);
01261 
01262                     newFp = 0;
01263 
01264                     // For layer 0 get pp points, for all other layers get
01265                     // points of layer-1.
01266                     if (i == 0)
01267                     {
01268                         forAll(stringedVerts, stringedI)
01269                         {
01270                             label v = stringedVerts[stringedI];
01271                             addVertex(meshPoints[v], newFace, newFp);
01272                         }
01273                     }
01274                     else
01275                     {
01276                         forAll(stringedVerts, stringedI)
01277                         {
01278                             label v = stringedVerts[stringedI];
01279                             if (addedPoints_[v].size())
01280                             {
01281                                 label offset =
01282                                     addedPoints_[v].size() - numEdgeSideFaces;
01283                                 addVertex
01284                                 (
01285                                     addedPoints_[v][i+offset-1],
01286                                     newFace,
01287                                     newFp
01288                                 );
01289                             }
01290                             else
01291                             {
01292                                 addVertex(meshPoints[v], newFace, newFp);
01293                             }
01294                         }
01295                     }
01296 
01297                     // add points between stringed vertices (end)
01298                     if (numEdgeSideFaces < addedPoints_[vEnd].size())
01299                     {
01300                         if (i == 0 && addedPoints_[vEnd].size())
01301                         {
01302                             label offset =
01303                                 addedPoints_[vEnd].size() - numEdgeSideFaces;
01304                             for (label ioff = 0; ioff < offset; ioff++)
01305                             {
01306                                 addVertex
01307                                 (
01308                                     addedPoints_[vEnd][ioff],
01309                                     newFace,
01310                                     newFp
01311                                 );
01312                             }
01313                         }
01314                     }
01315 
01316                     forAllReverse(stringedVerts, stringedI)
01317                     {
01318                         label v = stringedVerts[stringedI];
01319                         if (addedPoints_[v].size())
01320                         {
01321                             label offset =
01322                                 addedPoints_[v].size() - numEdgeSideFaces;
01323                             addVertex
01324                             (
01325                                 addedPoints_[v][i+offset],
01326                                 newFace,
01327                                 newFp
01328                             );
01329                         }
01330                         else
01331                         {
01332                             addVertex(meshPoints[v], newFace, newFp);
01333                         }
01334                     }
01335 
01336 
01337                     // add points between stringed vertices (start)
01338                     if (numEdgeSideFaces < addedPoints_[vStart].size())
01339                     {
01340                         if (i == 0 && addedPoints_[vStart].size())
01341                         {
01342                             label offset =
01343                                 addedPoints_[vStart].size() - numEdgeSideFaces;
01344                             for (label ioff = offset; ioff > 0; ioff--)
01345                             {
01346                                 addVertex
01347                                 (
01348                                     addedPoints_[vStart][ioff-1],
01349                                     newFace,
01350                                     newFp
01351                                 );
01352                             }
01353                         }
01354                     }
01355 
01356                     if (newFp >= 3)
01357                     {
01358                         // Add face inbetween faces patchFaceI and nbrFaceI
01359                         // (possibly -1 for external edges)
01360 
01361                         newFace.setSize(newFp);
01362 
01363                         label nbrFaceI = nbrFace
01364                         (
01365                             pp.edgeFaces(),
01366                             startEdgeI,
01367                             patchFaceI
01368                         );
01369 
01370                         const labelList& meshFaces = mesh_.edgeFaces
01371                         (
01372                             meshEdgeI,
01373                             ef
01374                         );
01375 
01376                         addSideFace
01377                         (
01378                             pp,
01379                             patchID,
01380                             addedCells,
01381                             newFace,
01382                             patchFaceI,
01383                             nbrFaceI,
01384                             startEdgeI,     // edge to inflate from
01385                             meshEdgeI,      // corresponding mesh edge
01386                             i,
01387                             numEdgeSideFaces,
01388                             meshFaces,
01389                             meshMod
01390                         );
01391                     }
01392                 }
01393             }
01394         }
01395     }
01396 }
01397 
01398 
01399 void Foam::addPatchCellLayer::updateMesh
01400 (
01401     const mapPolyMesh& morphMap,
01402     const labelList& faceMap,   // new to old patch faces
01403     const labelList& pointMap   // new to old patch points
01404 )
01405 {
01406     {
01407         labelListList newAddedPoints(pointMap.size());
01408 
01409         forAll(newAddedPoints, newPointI)
01410         {
01411             label oldPointI = pointMap[newPointI];
01412 
01413             const labelList& added = addedPoints_[oldPointI];
01414 
01415             labelList& newAdded = newAddedPoints[newPointI];
01416             newAdded.setSize(added.size());
01417             label newI = 0;
01418 
01419             forAll(added, i)
01420             {
01421                 label newPointI = morphMap.reversePointMap()[added[i]];
01422 
01423                 if (newPointI >= 0)
01424                 {
01425                     newAdded[newI++] = newPointI;
01426                 }
01427             }
01428             newAdded.setSize(newI);
01429         }
01430         addedPoints_.transfer(newAddedPoints);
01431     }
01432 
01433     {
01434         labelListList newLayerFaces(faceMap.size());
01435 
01436         forAll(newLayerFaces, newFaceI)
01437         {
01438             label oldFaceI = faceMap[newFaceI];
01439 
01440             const labelList& added = layerFaces_[oldFaceI];
01441 
01442             labelList& newAdded = newLayerFaces[newFaceI];
01443             newAdded.setSize(added.size());
01444             label newI = 0;
01445 
01446             forAll(added, i)
01447             {
01448                 label newFaceI = morphMap.reverseFaceMap()[added[i]];
01449 
01450                 if (newFaceI >= 0)
01451                 {
01452                     newAdded[newI++] = newFaceI;
01453                 }
01454             }
01455             newAdded.setSize(newI);
01456         }
01457         layerFaces_.transfer(newLayerFaces);
01458     }
01459 }
01460 
01461 
01462 Foam::labelList Foam::addPatchCellLayer::calcMeshEdges
01463 (
01464     const primitiveMesh& mesh,
01465     const indirectPrimitivePatch& pp
01466 )
01467 {
01468     labelList meshEdges(pp.nEdges());
01469 
01470     forAll(meshEdges, patchEdgeI)
01471     {
01472         const edge& e = pp.edges()[patchEdgeI];
01473 
01474         label v0 = pp.meshPoints()[e[0]];
01475         label v1 = pp.meshPoints()[e[1]];
01476         meshEdges[patchEdgeI] = meshTools::findEdge
01477         (
01478             mesh.edges(),
01479             mesh.pointEdges()[v0],
01480             v0,
01481             v1
01482         );
01483     }
01484     return meshEdges;
01485 }
01486 
01487 
01488 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines