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

surfaceRedistributePar.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-2007 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     surfaceRedistributePar
00026 
00027 Description
00028     (Re)distribution of triSurface. Either takes an undecomposed surface
00029     or an already decomposed surface and redistribute it so each processor
00030     has all triangles that overlap its mesh.
00031 
00032 Usage
00033     - surfaceRedistributePar [OPTION]
00034 
00035     @param <triSurfaceMesh> \n
00036     Tri-Surface mesh to read.
00037 
00038     @param <distributionType> \n
00039     @todo Detailed description.
00040 
00041     @param -keepNonMapped \n
00042     Preserve surface outside of mesh bounds.
00043 
00044     @param -case <dir> \n
00045     Specify the case directory
00046 
00047     @param -parallel \n
00048     Run the case in parallel
00049 
00050     @param -help \n
00051     Display short usage message
00052 
00053     @param -doc \n
00054     Display Doxygen documentation page
00055 
00056     @param -srcDoc \n
00057     Display source code
00058 
00059 Note
00060     - best decomposition option is hierarchGeomDecomp since
00061     guarantees square decompositions.
00062     - triangles might be present on multiple processors.
00063     - merging uses geometric tolerance so take care with writing precision.
00064 
00065 \*---------------------------------------------------------------------------*/
00066 
00067 #include <meshTools/treeBoundBox.H>
00068 #include <OpenFOAM/FixedList.H>
00069 #include <OpenFOAM/argList.H>
00070 #include <OpenFOAM/Time.H>
00071 #include <OpenFOAM/polyMesh.H>
00072 #include <meshTools/distributedTriSurfaceMesh.H>
00073 #include <OpenFOAM/mapDistribute.H>
00074 #include <triSurface/triSurfaceFields.H>
00075 #include <OpenFOAM/Pair.H>
00076 
00077 using namespace Foam;
00078 
00079 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00080 
00081 // Print on master all the per-processor surface stats.
00082 void writeProcStats
00083 (
00084     const triSurface& s,
00085     const List<List<treeBoundBox> >& meshBb
00086 )
00087 {
00088     // Determine surface bounding boxes, faces, points
00089     List<treeBoundBox> surfBb(Pstream::nProcs());
00090     {
00091         surfBb[Pstream::myProcNo()] = treeBoundBox(s.points());
00092         Pstream::gatherList(surfBb);
00093         Pstream::scatterList(surfBb);
00094     }
00095 
00096     labelList nPoints(Pstream::nProcs());
00097     nPoints[Pstream::myProcNo()] = s.points().size();
00098     Pstream::gatherList(nPoints);
00099     Pstream::scatterList(nPoints);
00100 
00101     labelList nFaces(Pstream::nProcs());
00102     nFaces[Pstream::myProcNo()] = s.size();
00103     Pstream::gatherList(nFaces);
00104     Pstream::scatterList(nFaces);
00105 
00106     forAll(surfBb, procI)
00107     {
00108         const List<treeBoundBox>& bbs = meshBb[procI];
00109 
00110         Info<< "processor" << procI << endl
00111             << "\tMesh bounds          : " << bbs[0] << nl;
00112         for (label i = 1; i < bbs.size(); i++)
00113         {
00114             Info<< "\t                       " << bbs[i]<< nl;
00115         }
00116         Info<< "\tSurface bounding box : " << surfBb[procI] << nl
00117             << "\tTriangles            : " << nFaces[procI] << nl
00118             << "\tVertices             : " << nPoints[procI]
00119             << endl;
00120     }
00121     Info<< endl;
00122 }
00123 
00124 
00125 // Main program:
00126 
00127 int main(int argc, char *argv[])
00128 {
00129     argList::validArgs.append("triSurfaceMesh");
00130     argList::validArgs.append("distributionType");
00131 
00132     argList::validOptions.insert("keepNonMapped", "");
00133 #   include <OpenFOAM/setRootCase.H>
00134 #   include <OpenFOAM/createTime.H>
00135     runTime.functionObjects().off();
00136 
00137     fileName surfFileName(args.additionalArgs()[0]);
00138     Info<< "Reading surface from " << surfFileName << nl << endl;
00139 
00140     const word distType(args.additionalArgs()[1]);
00141 
00142     Info<< "Using distribution method "
00143         << distributedTriSurfaceMesh::distributionTypeNames_[distType]
00144         << " " << distType << nl << endl;
00145 
00146     bool keepNonMapped = args.options().found("keepNonMapped");
00147 
00148     if (keepNonMapped)
00149     {
00150         Info<< "Preserving surface outside of mesh bounds." << nl << endl;
00151     }
00152     else
00153     {
00154         Info<< "Removing surface outside of mesh bounds." << nl << endl;
00155     }
00156 
00157 
00158     if (!Pstream::parRun())
00159     {
00160         FatalErrorIn(args.executable())
00161             << "Please run this program on the decomposed case."
00162             << " It will read surface " << surfFileName
00163             << " and decompose it such that it overlaps the mesh bounding box."
00164             << exit(FatalError);
00165     }
00166 
00167 
00168 #   include <OpenFOAM/createPolyMesh.H>
00169 
00170     Random rndGen(653213);
00171 
00172     // Determine mesh bounding boxes:
00173     List<List<treeBoundBox> > meshBb(Pstream::nProcs());
00174     {
00175         meshBb[Pstream::myProcNo()] = List<treeBoundBox>
00176         (
00177             1,
00178             treeBoundBox
00179             (
00180                 boundBox(mesh.points(), false)
00181             ).extend(rndGen, 1E-3)
00182         );
00183         Pstream::gatherList(meshBb);
00184         Pstream::scatterList(meshBb);
00185     }
00186 
00187     IOobject io
00188     (
00189         surfFileName,         // name
00190         //runTime.findInstance("triSurface", surfFileName),   // instance
00191         runTime.constant(),   // instance
00192         "triSurface",         // local
00193         runTime,              // registry
00194         IOobject::MUST_READ,
00195         IOobject::NO_WRITE
00196     );
00197 
00198     const fileName actualPath(io.filePath());
00199     fileName localPath(actualPath);
00200     localPath.replace(runTime.rootPath() + '/', "");
00201 
00202     if (actualPath == io.objectPath())
00203     {
00204         Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
00205     }
00206     else
00207     {
00208         Info<< "Loading undecomposed surface " << localPath << nl << endl;
00209     }
00210 
00211 
00212     // Create dummy dictionary for bounding boxes if does not exist.
00213     if (!isFile(actualPath / "Dict"))
00214     {
00215         dictionary dict;
00216         dict.add("bounds", meshBb[Pstream::myProcNo()]);
00217         dict.add("distributionType", distType);
00218         dict.add("mergeDistance", SMALL);
00219 
00220         IOdictionary ioDict
00221         (
00222             IOobject
00223             (
00224                 io.name() + "Dict",
00225                 io.instance(),
00226                 io.local(),
00227                 io.db(),
00228                 IOobject::NO_READ,
00229                 IOobject::NO_WRITE,
00230                 false
00231             ),
00232             dict
00233         );
00234 
00235         Info<< "Writing dummy bounds dictionary to " << ioDict.name()
00236             << nl << endl;
00237 
00238         ioDict.regIOobject::writeObject
00239         (
00240             IOstream::ASCII,
00241             IOstream::currentVersion,
00242             ioDict.time().writeCompression()        
00243         );
00244     }
00245 
00246 
00247     // Load surface
00248     distributedTriSurfaceMesh surfMesh(io);
00249     Info<< "Loaded surface" << nl << endl;
00250 
00251 
00252     // Generate a test field
00253     {
00254         const triSurface& s = static_cast<const triSurface&>(surfMesh);
00255 
00256         autoPtr<triSurfaceVectorField> fcPtr
00257         (
00258             new triSurfaceVectorField
00259             (
00260                 IOobject
00261                 (
00262                     surfMesh.searchableSurface::name(),     // name
00263                     surfMesh.searchableSurface::instance(), // instance
00264                     surfMesh.searchableSurface::local(),    // local
00265                     surfMesh,
00266                     IOobject::NO_READ,
00267                     IOobject::AUTO_WRITE
00268                 ),
00269                 surfMesh,
00270                 dimLength
00271             )
00272         );
00273         triSurfaceVectorField& fc = fcPtr();
00274 
00275         forAll(fc, triI)
00276         {
00277             fc[triI] = s[triI].centre(s.points());
00278         }
00279 
00280         // Steal pointer and store object on surfMesh
00281         fcPtr.ptr()->store();
00282     }
00283 
00284 
00285     // Write per-processor stats
00286     Info<< "Before redistribution:" << endl;
00287     writeProcStats(surfMesh, meshBb);
00288 
00289 
00290     // Do redistribution
00291     Info<< "Redistributing surface" << nl << endl;
00292     autoPtr<mapDistribute> faceMap;
00293     autoPtr<mapDistribute> pointMap;
00294     surfMesh.distribute
00295     (
00296         meshBb[Pstream::myProcNo()],
00297         keepNonMapped,
00298         faceMap,
00299         pointMap
00300     );
00301     faceMap.clear();
00302     pointMap.clear();
00303 
00304     Info<< endl;
00305 
00306 
00307     // Write per-processor stats
00308     Info<< "After redistribution:" << endl;
00309     writeProcStats(surfMesh, meshBb);
00310 
00311 
00312     Info<< "Writing surface." << nl << endl;
00313     surfMesh.searchableSurface::write();
00314 
00315     Info<< "End\n" << endl;
00316 
00317     return 0;
00318 }
00319 
00320 
00321 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines