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

removeCells.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 "removeCells.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include "polyTopoChange.H"
00029 #include <dynamicMesh/polyRemoveCell.H>
00030 #include <dynamicMesh/polyRemoveFace.H>
00031 #include <dynamicMesh/polyModifyFace.H>
00032 #include <dynamicMesh/polyRemovePoint.H>
00033 #include <OpenFOAM/syncTools.H>
00034 
00035 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00036 
00037 namespace Foam
00038 {
00039 
00040 defineTypeNameAndDebug(removeCells, 0);
00041 
00042 }
00043 
00044 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00045 
00046 // Remove count of elements of f.
00047 void Foam::removeCells::uncount
00048 (
00049     const labelList& f,
00050     labelList& nUsage
00051 )
00052 {
00053     forAll(f, fp)
00054     {
00055         nUsage[f[fp]]--;
00056     }
00057 }
00058 
00059 
00060 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00061 
00062 // Construct from mesh
00063 Foam::removeCells::removeCells
00064 (
00065     const polyMesh& mesh,
00066     const bool syncPar
00067 )
00068 :
00069     mesh_(mesh),
00070     syncPar_(syncPar)
00071 {}
00072 
00073 
00074 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00075 
00076 //- Get labels of exposed faces. These are
00077 //  - internal faces that become boundary faces
00078 //  - coupled faces that become uncoupled (since on of the sides
00079 //    gets deleted)
00080 Foam::labelList Foam::removeCells::getExposedFaces
00081 (
00082     const labelList& cellLabels
00083 ) const
00084 {
00085     // Create list of cells to be removed
00086     boolList removedCell(mesh_.nCells(), false);
00087 
00088     // Go from labelList of cells-to-remove to a boolList.
00089     forAll(cellLabels, i)
00090     {
00091         removedCell[cellLabels[i]] = true;
00092     }
00093 
00094 
00095     const labelList& faceOwner = mesh_.faceOwner();
00096     const labelList& faceNeighbour = mesh_.faceNeighbour();
00097 
00098     // Count cells using face.
00099     labelList nCellsUsingFace(mesh_.nFaces(), 0);
00100 
00101     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00102     {
00103         label own = faceOwner[faceI];
00104         label nei = faceNeighbour[faceI];
00105 
00106         if (!removedCell[own])
00107         {
00108             nCellsUsingFace[faceI]++;
00109         }
00110         if (!removedCell[nei])
00111         {
00112             nCellsUsingFace[faceI]++;
00113         }
00114     }
00115 
00116     for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
00117     {
00118         label own = faceOwner[faceI];
00119 
00120         if (!removedCell[own])
00121         {
00122             nCellsUsingFace[faceI]++;
00123         }
00124     }
00125 
00126     // Coupled faces: add number of cells using face across couple.
00127     if (syncPar_)
00128     {
00129         syncTools::syncFaceList
00130         (
00131             mesh_,
00132             nCellsUsingFace,
00133             plusEqOp<label>(),
00134             false
00135         );
00136     }
00137 
00138     // Now nCellsUsingFace:
00139     // 0 : internal face whose both cells get deleted
00140     //     boundary face whose all cells get deleted
00141     // 1 : internal face that gets exposed
00142     //     unaffected (uncoupled) boundary face
00143     //     coupled boundary face that gets exposed ('uncoupled')
00144     // 2 : unaffected internal face
00145     //     unaffected coupled boundary face
00146 
00147     DynamicList<label> exposedFaces(mesh_.nFaces()/10);
00148 
00149     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00150     {
00151         if (nCellsUsingFace[faceI] == 1)
00152         {
00153             exposedFaces.append(faceI);
00154         }
00155     }
00156 
00157     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00158 
00159     forAll(patches, patchI)
00160     {
00161         const polyPatch& pp = patches[patchI];
00162 
00163         if (pp.coupled())
00164         {
00165             label faceI = pp.start();
00166 
00167             forAll(pp, i)
00168             {
00169                 label own = faceOwner[faceI];
00170 
00171                 if (nCellsUsingFace[faceI] == 1 && !removedCell[own])
00172                 {
00173                     // My owner not removed but other side is so has to become
00174                     // normal, uncoupled, boundary face
00175                     exposedFaces.append(faceI);
00176                 }
00177 
00178                 faceI++;
00179             }
00180         }
00181     }
00182 
00183     return exposedFaces.shrink();
00184 }
00185 
00186 
00187 void Foam::removeCells::setRefinement
00188 (
00189     const labelList& cellLabels,
00190     const labelList& exposedFaceLabels,
00191     const labelList& exposedPatchIDs,
00192     polyTopoChange& meshMod
00193 ) const
00194 {
00195     const polyBoundaryMesh& patches = mesh_.boundaryMesh();
00196 
00197     if (exposedFaceLabels.size() != exposedPatchIDs.size())
00198     {
00199         FatalErrorIn
00200         (
00201             "removeCells::setRefinement(const labelList&"
00202             ", const labelList&, const labelList&, polyTopoChange&)"
00203         )   << "Size of exposedFaceLabels " << exposedFaceLabels.size()
00204             << " differs from size of exposedPatchIDs "
00205             << exposedPatchIDs.size()
00206             << abort(FatalError);
00207     }
00208 
00209     // List of new patchIDs
00210     labelList newPatchID(mesh_.nFaces(), -1);
00211 
00212     forAll(exposedFaceLabels, i)
00213     {
00214         label patchI = exposedPatchIDs[i];
00215 
00216         if (patchI < 0 || patchI >= patches.size())
00217         {
00218             FatalErrorIn
00219             (
00220                 "removeCells::setRefinement(const labelList&"
00221                 ", const labelList&, const labelList&, polyTopoChange&)"
00222             )   << "Invalid patch " << patchI
00223                 << " for exposed face " << exposedFaceLabels[i] << endl
00224                 << "Valid patches 0.." << patches.size()-1
00225                 << abort(FatalError);
00226         }
00227 
00228         if (patches[patchI].coupled())
00229         {
00230             FatalErrorIn
00231             (
00232                 "removeCells::setRefinement(const labelList&"
00233                 ", const labelList&, const labelList&, polyTopoChange&)"
00234             )   << "Trying to put exposed face " << exposedFaceLabels[i]
00235                 << " into a coupled patch : " << patches[patchI].name()
00236                 << endl
00237                 << "This is illegal."
00238                 << abort(FatalError);
00239         }
00240 
00241         newPatchID[exposedFaceLabels[i]] = patchI;
00242     }
00243 
00244 
00245     // Create list of cells to be removed
00246     boolList removedCell(mesh_.nCells(), false);
00247 
00248     // Go from labelList of cells-to-remove to a boolList and remove all
00249     // cells mentioned.
00250     forAll(cellLabels, i)
00251     {
00252         label cellI = cellLabels[i];
00253 
00254         removedCell[cellI] = true;
00255 
00256         //Pout<< "Removing cell " << cellI
00257         //    << " cc:" << mesh_.cellCentres()[cellI] << endl;
00258 
00259         meshMod.setAction(polyRemoveCell(cellI));
00260     }
00261 
00262 
00263     // Remove faces that are no longer used. Modify faces that
00264     // are used by one cell only.
00265 
00266     const faceList& faces = mesh_.faces();
00267     const labelList& faceOwner = mesh_.faceOwner();
00268     const labelList& faceNeighbour = mesh_.faceNeighbour();
00269     const faceZoneMesh& faceZones = mesh_.faceZones();
00270 
00271     // Count starting number of faces using each point. Keep up to date whenever
00272     // removing a face.
00273     labelList nFacesUsingPoint(mesh_.nPoints(), 0);
00274 
00275     forAll(faces, faceI)
00276     {
00277         const face& f = faces[faceI];
00278 
00279         forAll(f, fp)
00280         {
00281             nFacesUsingPoint[f[fp]]++;
00282         }
00283     }
00284 
00285 
00286     for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
00287     {
00288         const face& f = faces[faceI];
00289         label own = faceOwner[faceI];
00290         label nei = faceNeighbour[faceI];
00291 
00292         if (removedCell[own])
00293         {
00294             if (removedCell[nei])
00295             {
00296                 // Face no longer used
00297                 //Pout<< "Removing internal face " << faceI
00298                 //    << " fc:" << mesh_.faceCentres()[faceI] << endl;
00299 
00300                 meshMod.setAction(polyRemoveFace(faceI));
00301                 uncount(f, nFacesUsingPoint);
00302             }
00303             else
00304             {
00305                 if (newPatchID[faceI] == -1)
00306                 {
00307                     FatalErrorIn
00308                     (
00309                         "removeCells::setRefinement(const labelList&"
00310                         ", const labelList&, const labelList&"
00311                         ", polyTopoChange&)"
00312                     )   << "No patchID provided for exposed face " << faceI
00313                         << " on cell " << nei << nl
00314                         << "Did you provide patch IDs for all exposed faces?"
00315                         << abort(FatalError);
00316                 }
00317 
00318                 // nei is remaining cell. FaceI becomes external cell
00319 
00320                 label zoneID = faceZones.whichZone(faceI);
00321                 bool zoneFlip = false;
00322 
00323                 if (zoneID >= 0)
00324                 {
00325                     const faceZone& fZone = faceZones[zoneID];
00326                     // Note: we reverse the owner/neighbour of the face
00327                     // so should also select the other side of the zone
00328                     zoneFlip = !fZone.flipMap()[fZone.whichFace(faceI)];
00329                 }
00330 
00331                 //Pout<< "Putting exposed internal face " << faceI
00332                 //    << " fc:" << mesh_.faceCentres()[faceI]
00333                 //    << " into patch " << newPatchID[faceI] << endl;
00334 
00335                 meshMod.setAction
00336                 (
00337                     polyModifyFace
00338                     (
00339                         f.reverseFace(),        // modified face
00340                         faceI,                  // label of face being modified
00341                         nei,                    // owner
00342                         -1,                     // neighbour
00343                         true,                   // face flip
00344                         newPatchID[faceI],      // patch for face
00345                         false,                  // remove from zone
00346                         zoneID,                 // zone for face
00347                         zoneFlip                // face flip in zone
00348                     )
00349                 );
00350             }
00351         }
00352         else if (removedCell[nei])
00353         {
00354             if (newPatchID[faceI] == -1)
00355             {
00356                 FatalErrorIn
00357                 (
00358                     "removeCells::setRefinement(const labelList&"
00359                     ", const labelList&, const labelList&"
00360                     ", polyTopoChange&)"
00361                 )   << "No patchID provided for exposed face " << faceI
00362                     << " on cell " << own << nl
00363                     << "Did you provide patch IDs for all exposed faces?"
00364                     << abort(FatalError);
00365             }
00366 
00367             //Pout<< "Putting exposed internal face " << faceI
00368             //    << " fc:" << mesh_.faceCentres()[faceI]
00369             //    << " into patch " << newPatchID[faceI] << endl;
00370 
00371             // own is remaining cell. FaceI becomes external cell.
00372             label zoneID = faceZones.whichZone(faceI);
00373             bool zoneFlip = false;
00374 
00375             if (zoneID >= 0)
00376             {
00377                 const faceZone& fZone = faceZones[zoneID];
00378                 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00379             }
00380 
00381             meshMod.setAction
00382             (
00383                 polyModifyFace
00384                 (
00385                     f,                      // modified face
00386                     faceI,                  // label of face being modified
00387                     own,                    // owner
00388                     -1,                     // neighbour
00389                     false,                  // face flip
00390                     newPatchID[faceI],      // patch for face
00391                     false,                  // remove from zone
00392                     zoneID,                 // zone for face
00393                     zoneFlip                // face flip in zone
00394                 )
00395             );
00396         }
00397     }
00398 
00399     forAll(patches, patchI)
00400     {
00401         const polyPatch& pp = patches[patchI];
00402 
00403         if (pp.coupled())
00404         {
00405             label faceI = pp.start();
00406 
00407             forAll(pp, i)
00408             {
00409                 if (newPatchID[faceI] != -1)
00410                 {
00411                     //Pout<< "Putting uncoupled coupled face " << faceI
00412                     //    << " fc:" << mesh_.faceCentres()[faceI]
00413                     //    << " into patch " << newPatchID[faceI] << endl;
00414 
00415                     label zoneID = faceZones.whichZone(faceI);
00416                     bool zoneFlip = false;
00417 
00418                     if (zoneID >= 0)
00419                     {
00420                         const faceZone& fZone = faceZones[zoneID];
00421                         zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00422                     }
00423 
00424                     meshMod.setAction
00425                     (
00426                         polyModifyFace
00427                         (
00428                             faces[faceI],           // modified face
00429                             faceI,                  // label of face
00430                             faceOwner[faceI],       // owner
00431                             -1,                     // neighbour
00432                             false,                  // face flip
00433                             newPatchID[faceI],      // patch for face
00434                             false,                  // remove from zone
00435                             zoneID,                 // zone for face
00436                             zoneFlip                // face flip in zone
00437                         )
00438                     );
00439                 }
00440                 else if (removedCell[faceOwner[faceI]])
00441                 {
00442                     // Face no longer used
00443                     //Pout<< "Removing boundary face " << faceI
00444                     //    << " fc:" << mesh_.faceCentres()[faceI]
00445                     //    << endl;
00446 
00447                     meshMod.setAction(polyRemoveFace(faceI));
00448                     uncount(faces[faceI], nFacesUsingPoint);
00449                 }
00450 
00451                 faceI++;
00452             }
00453         }
00454         else
00455         {
00456             label faceI = pp.start();
00457 
00458             forAll(pp, i)
00459             {
00460                 if (newPatchID[faceI] != -1)
00461                 {
00462                     FatalErrorIn
00463                     (
00464                         "removeCells::setRefinement(const labelList&"
00465                         ", const labelList&, const labelList&"
00466                         ", polyTopoChange&)"
00467                     )   << "new patchID provided for boundary face " << faceI
00468                         << " even though it is not on a coupled face."
00469                         << abort(FatalError);
00470                 }
00471 
00472                 if (removedCell[faceOwner[faceI]])
00473                 {
00474                     // Face no longer used
00475                     //Pout<< "Removing boundary face " << faceI
00476                     //    << " fc:" << mesh_.faceCentres()[faceI]
00477                     //    << endl;
00478 
00479                     meshMod.setAction(polyRemoveFace(faceI));
00480                     uncount(faces[faceI], nFacesUsingPoint);
00481                 }
00482 
00483                 faceI++;
00484             }
00485         }
00486     }    
00487 
00488 
00489     // Remove points that are no longer used.
00490     // Loop rewritten to not use pointFaces.
00491 
00492     forAll(nFacesUsingPoint, pointI)
00493     {
00494         if (nFacesUsingPoint[pointI] == 0)
00495         {
00496             //Pout<< "Removing unused point " << pointI
00497             //    << " at:" << mesh_.points()[pointI] << endl;
00498 
00499             meshMod.setAction(polyRemovePoint(pointI));
00500         }
00501         else if (nFacesUsingPoint[pointI] == 1)
00502         {
00503             WarningIn
00504             (
00505                 "removeCells::setRefinement(const labelList&"
00506                 ", const labelList&, const labelList&"
00507                 ", polyTopoChange&)"
00508             )   << "point " << pointI << " at coordinate "
00509                 << mesh_.points()[pointI]
00510                 << " is only used by 1 face after removing cells."
00511                 << " This probably results in an illegal mesh."
00512                 << endl;
00513         }
00514     }
00515 }
00516 
00517 
00518 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines