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

surfaceMeshTriangulate.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 Application
00025     surfaceMeshTriangulate
00026 
00027 Description
00028     Extracts triSurface from a polyMesh.
00029 
00030     Triangulates all boundary faces.  Region numbers on triangles are the patch
00031     numbers of the polyMesh.  Optionally only triangulates named patches.
00032 
00033     If run in parallel the processor patches get filtered out by default and
00034     the mesh gets merged. (based on vertex position, not topology, so might go
00035     wrong!).
00036 
00037 Usage
00038 
00039     - surfaceMeshTriangulate [OPTIONS] <output file>
00040 
00041     @param <output file> \n
00042     @todo Detailed description of argument.
00043 
00044     @param -patches <(patch0 .. patchN)>\n
00045     List of patches.
00046 
00047     @param -excludeProcPatches \n
00048     If not run parallel, exclude processor patches.
00049 
00050     @param -case <dir>\n
00051     Case directory.
00052 
00053     @param -parallel \n
00054     Run in parallel.
00055 
00056     @param -help \n
00057     Display help message.
00058 
00059     @param -doc \n
00060     Display Doxygen API documentation page for this application.
00061 
00062     @param -srcDoc \n
00063     Display Doxygen source documentation page for this application.
00064 
00065 \*---------------------------------------------------------------------------*/
00066 
00067 #include <OpenFOAM/argList.H>
00068 #include <OpenFOAM/Time.H>
00069 #include <OpenFOAM/polyMesh.H>
00070 #include <triSurface/triSurface.H>
00071 #include <meshTools/triSurfaceTools.H>
00072 #include <OpenFOAM/processorPolyPatch.H>
00073 #include <OpenFOAM/ListListOps.H>
00074 
00075 using namespace Foam;
00076 
00077 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00078 
00079 // Main program:
00080 
00081 int main(int argc, char *argv[])
00082 {
00083     argList::validArgs.append("output file");
00084 #   include <OpenFOAM/addRegionOption.H>
00085     argList::validOptions.insert("excludeProcPatches", "");
00086     argList::validOptions.insert("patches", "(patch0 .. patchN)");
00087 
00088 #   include <OpenFOAM/setRootCase.H>
00089 #   include <OpenFOAM/createTime.H>
00090 
00091     fileName outFileName(runTime.path()/args.additionalArgs()[0]);
00092 
00093     Info<< "Extracting triSurface from boundaryMesh ..."
00094         << endl << endl;
00095 
00096     Pout<< "Reading mesh from time " << runTime.value() << endl;
00097 
00098 #   include <OpenFOAM/createNamedPolyMesh.H>
00099 
00100     bool includeProcPatches =
00101        !(
00102             args.optionFound("excludeProcPatches")
00103          || Pstream::parRun()
00104         );
00105 
00106     // Create local surface from:
00107     // - explicitly named patches only (-patches option)
00108     // - all patches (default in sequential mode)
00109     // - all non-processor patches (default in parallel mode)
00110     // - all non-processor patches (sequential mode, -excludeProcPatches option)
00111 
00112     // Construct table of patches to include.
00113     const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
00114 
00115     labelHashSet includePatches(bMesh.size());
00116 
00117     if (args.optionFound("patches"))
00118     {
00119         wordList patchNames(args.optionLookup("patches")());
00120 
00121         forAll(patchNames, patchNameI)
00122         {
00123             const word& patchName = patchNames[patchNameI];
00124 
00125             label patchI = bMesh.findPatchID(patchName);
00126 
00127             if (patchI == -1)
00128             {
00129                 FatalErrorIn(args.executable()) << "No such patch "
00130                     << patchName << endl << "Patches are " << bMesh.names()
00131                     << exit(FatalError);
00132             }
00133             includePatches.insert(patchI);
00134         }
00135     }
00136     else
00137     {
00138         forAll(bMesh, patchI)
00139         {
00140             const polyPatch& patch = bMesh[patchI];
00141 
00142             if (includeProcPatches || !isA<processorPolyPatch>(patch))
00143             {
00144                 includePatches.insert(patchI);
00145             }
00146             else
00147             {
00148                 Pout<< patch.name() << " : skipped since processorPatch"
00149                     << endl;
00150             }
00151         }
00152     }
00153 
00154     triSurface localSurface
00155     (
00156         triSurfaceTools::triangulate
00157         (
00158             mesh.boundaryMesh(),
00159             includePatches
00160         )
00161     );
00162 
00163 
00164 
00165     if (!Pstream::parRun())
00166     {
00167         Info<< "Writing surface to " << outFileName << endl;
00168 
00169         localSurface.write(outFileName);
00170     }
00171     else
00172     {
00173         // Write local surface
00174         fileName localPath = runTime.path()/runTime.caseName() + ".ftr";
00175 
00176         Pout<< "Writing local surface to " << localPath << endl;
00177 
00178         localSurface.write(localPath);
00179 
00180         Info<< endl;
00181 
00182 
00183         // Gather all points on master
00184         List<pointField> gatheredPoints(Pstream::nProcs());
00185 
00186         gatheredPoints[Pstream::myProcNo()] = localSurface.points();
00187 
00188         Pstream::gatherList(gatheredPoints);
00189 
00190 
00191         // Gather all localSurface patches
00192         List<geometricSurfacePatchList> gatheredPatches(Pstream::nProcs());
00193 
00194         gatheredPatches[Pstream::myProcNo()] = localSurface.patches();
00195 
00196         Pstream::gatherList(gatheredPatches);
00197 
00198 
00199         // Gather all faces
00200         List<List<labelledTri> > gatheredFaces(Pstream::nProcs());
00201 
00202         gatheredFaces[Pstream::myProcNo()] = localSurface;
00203 
00204         Pstream::gatherList(gatheredFaces);
00205 
00206 
00207         if (Pstream::master())
00208         {
00209             // On master combine all points
00210             pointField allPoints =
00211                 ListListOps::combine<pointField>
00212                 (
00213                     gatheredPoints,
00214                     accessOp<pointField>()
00215                 );
00216 
00217             // Count number of patches.
00218             label nPatches = 0;
00219 
00220             forAll(gatheredPatches, procI)
00221             {
00222                 nPatches += gatheredPatches[procI].size();
00223             }
00224 
00225             // Count number of faces.
00226             label nFaces = 0;
00227 
00228             forAll(gatheredFaces, procI)
00229             {
00230                 nFaces += gatheredFaces[procI].size();
00231             }
00232 
00233 
00234 
00235             // Loop over all processors and
00236             // - construct mapping from local to global patches
00237             // - relabel faces (both points and regions)
00238 
00239             label newPatchI = 0;
00240 
00241             // Name to new patchI
00242             HashTable<label> nameToIndex(2*nPatches);
00243 
00244             // Storage (oversized) for all patches
00245             geometricSurfacePatchList allPatches(nPatches);
00246 
00247             label newFaceI = 0;
00248 
00249             // Storage for all faces
00250             List<labelledTri> allFaces(nFaces);
00251 
00252             // Offset into allPoints for current processor
00253             label pointOffset = 0;
00254 
00255             for (label procI = 0; procI < Pstream::nProcs(); procI++)
00256             {
00257                 Info<< "Processor " << procI << endl
00258                     << "-----------" << endl;
00259 
00260                 const geometricSurfacePatchList& patches =
00261                     gatheredPatches[procI];
00262 
00263                 // From local patch numbering to global
00264                 labelList localToGlobal(patches.size());
00265 
00266                 forAll(patches, patchI)
00267                 {
00268                     const geometricSurfacePatch& sp = patches[patchI];
00269 
00270                     if (!nameToIndex.found(sp.name()))
00271                     {
00272                         nameToIndex.insert(sp.name(), newPatchI);
00273 
00274                         localToGlobal[patchI] = newPatchI;
00275 
00276                         allPatches[newPatchI] = sp;
00277 
00278                         newPatchI++;
00279                     }
00280                     else
00281                     {
00282                         localToGlobal[patchI] = nameToIndex[sp.name()];
00283                     }
00284                 }
00285 
00286                 Info<< "Local patch to global patch mapping:"
00287                     << endl;
00288 
00289                 forAll(patches, patchI)
00290                 {
00291                     Info<< "    name   : " << patches[patchI].name() << endl
00292                         << "    local  : " << patchI << endl
00293                         << "    global : " << localToGlobal[patchI]
00294                         << endl;
00295                 }
00296 
00297                 Info<< "Local points added in global points starting at "
00298                     << pointOffset
00299                     << endl;
00300 
00301 
00302                 // Collect and relabel faces
00303                 const List<labelledTri>& localFaces = gatheredFaces[procI];
00304 
00305 
00306                 forAll(localFaces, faceI)
00307                 {
00308                     const labelledTri& f = localFaces[faceI];
00309 
00310                     allFaces[newFaceI++] =
00311                         labelledTri
00312                         (
00313                             f[0] + pointOffset,
00314                             f[1] + pointOffset,
00315                             f[2] + pointOffset,
00316                             localToGlobal[f.region()]
00317                         );
00318                 }
00319 
00320                 pointOffset += gatheredPoints[procI].size();
00321 
00322                 Info<< endl;
00323             }
00324             allPatches.setSize(newPatchI);
00325 
00326             // We now have allPoints, allFaces and allPatches.
00327             // Construct overall (yet unmerged) surface from these.
00328 
00329             triSurface allSurf(allFaces, allPatches, allPoints);
00330 
00331             // Cleanup (which does point merge as well
00332             allSurf.cleanup(false);
00333 
00334             // Write surface mesh
00335 
00336             label slashIndex = runTime.caseName().find_last_of('/');
00337 
00338             fileName globalCasePath(runTime.caseName().substr(0, slashIndex));
00339 
00340             Info<< "Writing merged surface to " << globalCasePath << endl;
00341 
00342             // create database for the sequential run
00343             fileName globalPath
00344             (
00345                 runTime.rootPath()
00346               / globalCasePath
00347               / args.additionalArgs()[0]
00348             );
00349 
00350             allSurf.write(globalPath);
00351         }
00352     }
00353 
00354     Info << "End\n" << endl;
00355 
00356     return 0;
00357 }
00358 
00359 
00360 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines