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

sampledSurfaces.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 "sampledSurfaces.H"
00027 #include <finiteVolume/volFields.H>
00028 #include <OpenFOAM/dictionary.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <OpenFOAM/IOmanip.H>
00031 #include <OpenFOAM/ListListOps.H>
00032 #include <OpenFOAM/mergePoints.H>
00033 #include <finiteVolume/volPointInterpolation.H>
00034 
00035 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00036 
00037 namespace Foam
00038 {
00039     //- Used to offset faces in Pstream::combineOffset
00040     template <>
00041     class offsetOp<face>
00042     {
00043 
00044     public:
00045 
00046         face operator()
00047         (
00048             const face& x,
00049             const label offset
00050         ) const
00051         {
00052             face result(x.size());
00053 
00054             forAll(x, xI)
00055             {
00056                 result[xI] = x[xI] + offset;
00057             }
00058             return result;
00059         }
00060     };
00061 
00062 
00063     defineTypeNameAndDebug(sampledSurfaces, 0);
00064 }
00065 
00066 
00067 bool Foam::sampledSurfaces::verbose_(false);
00068 Foam::scalar Foam::sampledSurfaces::mergeTol_(1e-10);
00069 
00070 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00071 
00072 Foam::label Foam::sampledSurfaces::classifyFieldTypes()
00073 {
00074     label nFields = 0;
00075 
00076     scalarFields_.clear();
00077     vectorFields_.clear();
00078     sphericalTensorFields_.clear();
00079     symmTensorFields_.clear();
00080     tensorFields_.clear();
00081 
00082     forAll(fieldNames_, fieldI)
00083     {
00084         const word& fieldName = fieldNames_[fieldI];
00085         word fieldType = "";
00086 
00087         // check files for a particular time
00088         if (loadFromFiles_)
00089         {
00090             IOobject io
00091             (
00092                 fieldName,
00093                 mesh_.time().timeName(),
00094                 mesh_,
00095                 IOobject::MUST_READ,
00096                 IOobject::NO_WRITE,
00097                 false
00098             );
00099 
00100             if (io.headerOk())
00101             {
00102                 fieldType = io.headerClassName();
00103             }
00104             else
00105             {
00106                 continue;
00107             }
00108         }
00109         else
00110         {
00111             // check objectRegistry
00112             objectRegistry::const_iterator iter = mesh_.find(fieldName);
00113 
00114             if (iter != mesh_.objectRegistry::end())
00115             {
00116                 fieldType = iter()->type();
00117             }
00118             else
00119             {
00120                 continue;
00121             }
00122         }
00123 
00124 
00125         if (fieldType == volScalarField::typeName)
00126         {
00127             scalarFields_.append(fieldName);
00128             nFields++;
00129         }
00130         else if (fieldType == volVectorField::typeName)
00131         {
00132             vectorFields_.append(fieldName);
00133             nFields++;
00134         }
00135         else if (fieldType == volSphericalTensorField::typeName)
00136         {
00137             sphericalTensorFields_.append(fieldName);
00138             nFields++;
00139         }
00140         else if (fieldType == volSymmTensorField::typeName)
00141         {
00142             symmTensorFields_.append(fieldName);
00143             nFields++;
00144         }
00145         else if (fieldType == volTensorField::typeName)
00146         {
00147             tensorFields_.append(fieldName);
00148             nFields++;
00149         }
00150 
00151     }
00152 
00153     return nFields;
00154 }
00155 
00156 
00157 void Foam::sampledSurfaces::writeGeometry() const
00158 {
00159     // Write to time directory under outputPath_
00160     // skip surface without faces (eg, a failed cut-plane)
00161 
00162     const fileName outputDir = outputPath_/mesh_.time().timeName();
00163 
00164     forAll(*this, surfI)
00165     {
00166         const sampledSurface& s = operator[](surfI);
00167 
00168         if (Pstream::parRun())
00169         {
00170             if (Pstream::master() && mergeList_[surfI].faces.size())
00171             {
00172                 genericFormatter_->write
00173                 (
00174                     outputDir,
00175                     s.name(),
00176                     mergeList_[surfI].points,
00177                     mergeList_[surfI].faces
00178                 );
00179             }
00180         }
00181         else if (s.faces().size())
00182         {
00183             genericFormatter_->write
00184             (
00185                 outputDir,
00186                 s.name(),
00187                 s.points(),
00188                 s.faces()
00189             );
00190         }
00191     }
00192 }
00193 
00194 
00195 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00196 
00197 Foam::sampledSurfaces::sampledSurfaces
00198 (
00199     const word& name,
00200     const objectRegistry& obr,
00201     const dictionary& dict,
00202     const bool loadFromFiles
00203 )
00204 :
00205     PtrList<sampledSurface>(),
00206     name_(name),
00207     mesh_(refCast<const fvMesh>(obr)),
00208     loadFromFiles_(loadFromFiles),
00209     outputPath_(fileName::null),
00210     fieldNames_(),
00211     interpolationScheme_(word::null),
00212     writeFormat_(word::null),
00213     mergeList_(),
00214     genericFormatter_(NULL),
00215     scalarFields_(),
00216     vectorFields_(),
00217     sphericalTensorFields_(),
00218     symmTensorFields_(),
00219     tensorFields_()
00220 {
00221     if (Pstream::parRun())
00222     {
00223         outputPath_ = mesh_.time().path()/".."/name_;
00224     }
00225     else
00226     {
00227         outputPath_ = mesh_.time().path()/name_;
00228     }
00229 
00230     read(dict);
00231 }
00232 
00233 
00234 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00235 
00236 Foam::sampledSurfaces::~sampledSurfaces()
00237 {}
00238 
00239 
00240 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00241 
00242 void Foam::sampledSurfaces::verbose(const bool verbosity)
00243 {
00244     verbose_ = verbosity;
00245 }
00246 
00247 
00248 void Foam::sampledSurfaces::execute()
00249 {
00250     // Do nothing - only valid on write
00251 }
00252 
00253 
00254 void Foam::sampledSurfaces::end()
00255 {
00256     // Do nothing - only valid on write
00257 }
00258 
00259 
00260 void Foam::sampledSurfaces::write()
00261 {
00262     if (size())
00263     {
00264         // finalize surfaces, merge points etc.
00265         update();
00266 
00267         const label nFields = classifyFieldTypes();
00268 
00269         if (Pstream::master())
00270         {
00271             if (debug)
00272             {
00273                 Pout<< "timeName = " << mesh_.time().timeName() << nl
00274                     << "scalarFields    " << scalarFields_ << nl
00275                     << "vectorFields    " << vectorFields_ << nl
00276                     << "sphTensorFields " << sphericalTensorFields_ << nl
00277                     << "symTensorFields " << symmTensorFields_ <<nl
00278                     << "tensorFields    " << tensorFields_ <<nl;
00279 
00280                 Pout<< "Creating directory "
00281                     << outputPath_/mesh_.time().timeName() << nl << endl;
00282 
00283             }
00284 
00285             mkDir(outputPath_/mesh_.time().timeName());
00286         }
00287 
00288         // write geometry first if required, or when no fields would otherwise
00289         // be written
00290         if (nFields == 0 || genericFormatter_->separateFiles())
00291         {
00292             writeGeometry();
00293         }
00294 
00295         sampleAndWrite(scalarFields_);
00296         sampleAndWrite(vectorFields_);
00297         sampleAndWrite(sphericalTensorFields_);
00298         sampleAndWrite(symmTensorFields_);
00299         sampleAndWrite(tensorFields_);
00300     }
00301 }
00302 
00303 
00304 void Foam::sampledSurfaces::read(const dictionary& dict)
00305 {
00306     fieldNames_ = wordList(dict.lookup("fields"));
00307 
00308     const label nFields = fieldNames_.size();
00309 
00310     scalarFields_.reset(nFields);
00311     vectorFields_.reset(nFields);
00312     sphericalTensorFields_.reset(nFields);
00313     symmTensorFields_.reset(nFields);
00314     tensorFields_.reset(nFields);
00315 
00316     interpolationScheme_ = dict.lookupOrDefault<word>
00317     (
00318         "interpolationScheme",
00319         "cell"
00320     );
00321     writeFormat_ = dict.lookupOrDefault<word>
00322     (
00323         "surfaceFormat",
00324         "null"
00325     );
00326 
00327 
00328     // define the generic (geometry) writer
00329     genericFormatter_ = surfaceWriter<bool>::New(writeFormat_);
00330 
00331 
00332     PtrList<sampledSurface> newList
00333     (
00334         dict.lookup("surfaces"),
00335         sampledSurface::iNew(mesh_)
00336     );
00337 
00338     transfer(newList);
00339 
00340     if (Pstream::parRun())
00341     {
00342         mergeList_.setSize(size());
00343     }
00344 
00345     // ensure all surfaces and merge information are expired
00346     expire();
00347 
00348     if (Pstream::master() && debug)
00349     {
00350         Pout<< "sample fields:" << fieldNames_ << nl
00351             << "sample surfaces:" << nl << "(" << nl;
00352 
00353         forAll(*this, surfI)
00354         {
00355             Pout<< "  " << operator[](surfI) << endl;
00356         }
00357         Pout<< ")" << endl;
00358     }
00359 }
00360 
00361 
00362 void Foam::sampledSurfaces::updateMesh(const mapPolyMesh&)
00363 {
00364     expire();
00365 
00366     // pointMesh and interpolation will have been reset in mesh.update
00367 }
00368 
00369 
00370 void Foam::sampledSurfaces::movePoints(const pointField&)
00371 {
00372     expire();
00373 }
00374 
00375 
00376 void Foam::sampledSurfaces::readUpdate(const polyMesh::readUpdateState state)
00377 {
00378     if (state != polyMesh::UNCHANGED)
00379     {
00380         expire();
00381     }
00382 }
00383 
00384 
00385 bool Foam::sampledSurfaces::needsUpdate() const
00386 {
00387     forAll(*this, surfI)
00388     {
00389         if (operator[](surfI).needsUpdate())
00390         {
00391             return true;
00392         }
00393     }
00394 
00395     return false;
00396 }
00397 
00398 
00399 bool Foam::sampledSurfaces::expire()
00400 {
00401     bool justExpired = false;
00402 
00403     forAll(*this, surfI)
00404     {
00405         if (operator[](surfI).expire())
00406         {
00407             justExpired = true;
00408         }
00409 
00410         // clear merge information
00411         if (Pstream::parRun())
00412         {
00413             mergeList_[surfI].clear();
00414         }
00415     }
00416 
00417     // true if any surfaces just expired
00418     return justExpired;
00419 }
00420 
00421 
00422 bool Foam::sampledSurfaces::update()
00423 {
00424     bool updated = false;
00425 
00426     if (!needsUpdate())
00427     {
00428         return updated;
00429     }
00430 
00431     // serial: quick and easy, no merging required
00432     if (!Pstream::parRun())
00433     {
00434         forAll(*this, surfI)
00435         {
00436             if (operator[](surfI).update())
00437             {
00438                 updated = true;
00439             }
00440         }
00441 
00442         return updated;
00443     }
00444 
00445     // dimension as fraction of mesh bounding box
00446     scalar mergeDim = mergeTol_ * mesh_.globalData().bb().mag();
00447 
00448     if (Pstream::master() && debug)
00449     {
00450         Pout<< nl << "Merging all points within "
00451             << mergeDim << " meter" << endl;
00452     }
00453 
00454     forAll(*this, surfI)
00455     {
00456         sampledSurface& s = operator[](surfI);
00457 
00458         if (s.update())
00459         {
00460             updated = true;
00461         }
00462         else
00463         {
00464             continue;
00465         }
00466 
00467 
00468         // Collect points from all processors
00469         List<pointField> gatheredPoints(Pstream::nProcs());
00470         gatheredPoints[Pstream::myProcNo()] = s.points();
00471         Pstream::gatherList(gatheredPoints);
00472 
00473         if (Pstream::master())
00474         {
00475             mergeList_[surfI].points = ListListOps::combine<pointField>
00476             (
00477                 gatheredPoints,
00478                 accessOp<pointField>()
00479             );
00480         }
00481 
00482         // Collect faces from all processors and renumber using sizes of
00483         // gathered points
00484         List<faceList> gatheredFaces(Pstream::nProcs());
00485         gatheredFaces[Pstream::myProcNo()] = s.faces();
00486         Pstream::gatherList(gatheredFaces);
00487 
00488         if (Pstream::master())
00489         {
00490             mergeList_[surfI].faces = static_cast<const faceList&>
00491             (
00492                 ListListOps::combineOffset<faceList>
00493                 (
00494                     gatheredFaces,
00495                     ListListOps::subSizes
00496                     (
00497                         gatheredPoints,
00498                         accessOp<pointField>()
00499                     ),
00500                     accessOp<faceList>(),
00501                     offsetOp<face>()
00502                 )
00503             );
00504         }
00505 
00506         pointField newPoints;
00507         labelList oldToNew;
00508 
00509         bool hasMerged = mergePoints
00510         (
00511             mergeList_[surfI].points,
00512             mergeDim,
00513             false,                  // verbosity
00514             oldToNew,
00515             newPoints
00516         );
00517 
00518         if (hasMerged)
00519         {
00520             // Store point mapping
00521             mergeList_[surfI].pointsMap.transfer(oldToNew);
00522 
00523             // Copy points
00524             mergeList_[surfI].points.transfer(newPoints);
00525 
00526             // Relabel faces
00527             faceList& faces = mergeList_[surfI].faces;
00528 
00529             forAll(faces, faceI)
00530             {
00531                 inplaceRenumber(mergeList_[surfI].pointsMap, faces[faceI]);
00532             }
00533 
00534             if (Pstream::master() && debug)
00535             {
00536                 Pout<< "For surface " << surfI << " merged from "
00537                     << mergeList_[surfI].pointsMap.size() << " points down to "
00538                     << mergeList_[surfI].points.size()    << " points" << endl;
00539             }
00540         }
00541     }
00542 
00543     return updated;
00544 }
00545 
00546 
00547 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines