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

directions.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 "directions.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <meshTools/twoDPointCorrector.H>
00029 #include <dynamicMesh/directionInfo.H>
00030 #include <OpenFOAM/MeshWave.H>
00031 #include <OpenFOAM/OFstream.H>
00032 #include <meshTools/meshTools.H>
00033 #include <OpenFOAM/hexMatcher.H>
00034 #include <OpenFOAM/Switch.H>
00035 #include <OpenFOAM/globalMeshData.H>
00036 
00037 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00038 
00039 template<>
00040 const char* Foam::NamedEnum<Foam::directions::directionType, 3>::names[] =
00041 {
00042     "tan1",
00043     "tan2",
00044     "normal"
00045 };
00046 
00047 const Foam::NamedEnum<Foam::directions::directionType, 3>
00048     Foam::directions::directionTypeNames_;
00049 
00050 
00051 
00052 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00053 
00054 // For debugging
00055 void Foam::directions::writeOBJ(Ostream& os, const point& pt)
00056 {
00057     os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00058 }
00059 
00060 // For debugging
00061 void Foam::directions::writeOBJ
00062 (
00063     Ostream& os,
00064     const point& pt0,
00065     const point& pt1,
00066     label& vertI
00067 )
00068 {
00069     writeOBJ(os, pt0);
00070     writeOBJ(os, pt1);
00071 
00072     os << "l " << vertI + 1 << ' ' << vertI + 2 << endl;
00073 
00074     vertI += 2;
00075 }
00076 
00077 
00078 // Dump to file.
00079 void Foam::directions::writeOBJ
00080 (
00081     const fileName& fName,
00082     const primitiveMesh& mesh,
00083     const vectorField& dirs
00084 )
00085 {
00086     Pout<< "Writing cell info to " << fName << " as vectors at the cellCentres"
00087         << endl << endl;
00088 
00089     OFstream xDirStream(fName);
00090 
00091     label vertI = 0;
00092 
00093     forAll(dirs, cellI)
00094     {
00095         const point& ctr = mesh.cellCentres()[cellI];
00096 
00097         // Calculate local length scale
00098         scalar minDist = GREAT;
00099 
00100         const labelList& nbrs = mesh.cellCells()[cellI];
00101 
00102         forAll(nbrs, nbrI)
00103         {
00104             minDist = min(minDist, mag(mesh.cellCentres()[nbrs[nbrI]] - ctr));
00105         }
00106 
00107         scalar scale = 0.5*minDist;
00108 
00109         writeOBJ(xDirStream, ctr, ctr + scale*dirs[cellI], vertI);
00110     }
00111 }
00112 
00113 
00114 void Foam::directions::check2D
00115 (
00116     const twoDPointCorrector* correct2DPtr,
00117     const vector& vec
00118 )
00119 {
00120     if (correct2DPtr)
00121     {
00122         if (mag(correct2DPtr->planeNormal() & vec) > 1E-6)
00123         {
00124             FatalErrorIn("check2D") << "Specified vector " << vec
00125                 << "is not normal to plane defined in dynamicMeshDict."
00126                 << endl
00127                 << "Either make case 3D or adjust vector."
00128                 << exit(FatalError);
00129         }
00130     }
00131 }
00132 
00133 
00134 // Get direction on all cells
00135 Foam::vectorField Foam::directions::propagateDirection
00136 (
00137     const polyMesh& mesh,
00138     const bool useTopo,
00139     const polyPatch& pp,
00140     const vectorField& ppField,
00141     const vector& defaultDir
00142 )
00143 {
00144     // Seed all faces on patch
00145     labelList changedFaces(pp.size());
00146     List<directionInfo> changedFacesInfo(pp.size());
00147 
00148     if (useTopo)
00149     {
00150         forAll(pp, patchFaceI)
00151         {
00152             label meshFaceI = pp.start() + patchFaceI;
00153 
00154             label cellI = mesh.faceOwner()[meshFaceI];
00155 
00156             if (!hexMatcher().isA(mesh, cellI))
00157             {
00158                 FatalErrorIn("propagateDirection")
00159                     << "useHexTopology specified but cell " << cellI
00160                     << " on face " << patchFaceI << " of patch " << pp.name()
00161                     << " is not a hex" << exit(FatalError);
00162             }
00163 
00164             const vector& cutDir = ppField[patchFaceI];
00165 
00166             // Get edge(bundle) on cell most in direction of cutdir
00167             label edgeI = meshTools::cutDirToEdge(mesh, cellI, cutDir);
00168 
00169             // Convert edge into index on face
00170             label faceIndex =
00171                 directionInfo::edgeToFaceIndex
00172                 (
00173                     mesh,
00174                     cellI,
00175                     meshFaceI,
00176                     edgeI
00177                 );
00178 
00179             // Set initial face and direction
00180             changedFaces[patchFaceI] = meshFaceI;
00181             changedFacesInfo[patchFaceI] =
00182                 directionInfo
00183                 (
00184                     faceIndex, 
00185                     cutDir
00186                 );
00187         }
00188     }
00189     else
00190     {
00191         forAll(pp, patchFaceI)
00192         {
00193             changedFaces[patchFaceI] = pp.start() + patchFaceI;
00194             changedFacesInfo[patchFaceI] =
00195                 directionInfo
00196                 (
00197                     -2,         // Geometric information only
00198                     ppField[patchFaceI]
00199                 );
00200         }
00201     }
00202 
00203     MeshWave<directionInfo> directionCalc
00204     (
00205         mesh,
00206         changedFaces,
00207         changedFacesInfo,
00208         mesh.globalData().nTotalCells()+1
00209     );
00210 
00211     const List<directionInfo>& cellInfo = directionCalc.allCellInfo();
00212 
00213     vectorField dirField(cellInfo.size());
00214 
00215     label nUnset = 0;
00216     label nGeom = 0;
00217     label nTopo = 0;
00218 
00219     forAll(cellInfo, cellI)
00220     {
00221         label index = cellInfo[cellI].index();
00222 
00223         if (index == -3)
00224         {
00225             // Never visited
00226             WarningIn("propagateDirection")
00227                 << "Cell " << cellI << " never visited to determine "
00228                 << "local coordinate system" << endl
00229                 << "Using direction " << defaultDir << " instead" << endl;
00230 
00231             dirField[cellI] = defaultDir;
00232 
00233             nUnset++;
00234         }
00235         else if (index == -2)
00236         {
00237             // Geometric direction
00238             dirField[cellI] = cellInfo[cellI].n();
00239 
00240             nGeom++;
00241         }
00242         else if (index == -1)
00243         {
00244             FatalErrorIn("propagateDirection")
00245                 << "Illegal index " << index << endl
00246                 << "Value is only allowed on faces" << abort(FatalError);
00247         }
00248         else
00249         {
00250             // Topological edge cut. Convert into average cut direction.
00251             dirField[cellI] = meshTools::edgeToCutDir(mesh, cellI, index);
00252 
00253             nTopo++;
00254         }
00255     }
00256 
00257     Pout<< "Calculated local coords for " << defaultDir
00258         << endl
00259         << "    Geometric cut cells   : " << nGeom << endl
00260         << "    Topological cut cells : " << nTopo << endl
00261         << "    Unset cells           : " << nUnset << endl
00262         << endl;
00263 
00264     return dirField;
00265 }
00266 
00267 
00268 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00269 
00270 // Construct from dictionary
00271 Foam::directions::directions
00272 (
00273     const polyMesh& mesh,
00274     const dictionary& dict,
00275     const twoDPointCorrector* correct2DPtr
00276 )
00277 :
00278     List<vectorField>(wordList(dict.lookup("directions")).size())
00279 {
00280     const wordList wantedDirs(dict.lookup("directions"));
00281 
00282     bool wantNormal = false;
00283     bool wantTan1 = false;
00284     bool wantTan2 = false;
00285 
00286     forAll(wantedDirs, i)
00287     {
00288         directionType wantedDir = directionTypeNames_[wantedDirs[i]];
00289 
00290         if (wantedDir == NORMAL)
00291         {
00292             wantNormal = true;
00293         }
00294         else if (wantedDir == TAN1)
00295         {
00296             wantTan1 = true;
00297         }
00298         else if (wantedDir == TAN2)
00299         {
00300             wantTan2 = true;
00301         }
00302     }
00303 
00304 
00305     label nDirs = 0;
00306 
00307     word coordSystem(dict.lookup("coordinateSystem"));
00308 
00309     if (coordSystem == "global")
00310     {
00311         const dictionary& globalDict = dict.subDict("globalCoeffs");
00312 
00313         vector tan1(globalDict.lookup("tan1"));
00314         check2D(correct2DPtr, tan1);
00315 
00316         vector tan2(globalDict.lookup("tan2"));
00317         check2D(correct2DPtr, tan2);
00318 
00319         vector normal = tan1 ^ tan2;
00320         normal /= mag(normal);
00321 
00322         Pout<< "Global Coordinate system:" << endl
00323             << "     normal : " << normal << endl
00324             << "     tan1   : " << tan1 << endl
00325             << "     tan2   : " << tan2
00326             << endl << endl;
00327 
00328         if (wantNormal)
00329         {
00330             operator[](nDirs++) = vectorField(1, normal);
00331         }
00332         if (wantTan1)
00333         {
00334             operator[](nDirs++) = vectorField(1, tan1);
00335         }
00336         if (wantTan2)
00337         {
00338             operator[](nDirs++) = vectorField(1, tan2);
00339         }
00340     }
00341     else if (coordSystem == "patchLocal")
00342     {
00343         const dictionary& patchDict = dict.subDict("patchLocalCoeffs");
00344 
00345         word patchName(patchDict.lookup("patch"));
00346 
00347         label patchI = mesh.boundaryMesh().findPatchID(patchName);
00348 
00349         if (patchI == -1)
00350         {
00351             FatalErrorIn
00352             (
00353                 "directions::directions(const polyMesh&, const dictionary&,"
00354                 "const twoDPointCorrector*"
00355             )   << "Cannot find patch "
00356                 << patchName << exit(FatalError);
00357         }
00358 
00359         // Take zeroth face on patch
00360         const polyPatch& pp = mesh.boundaryMesh()[patchI];
00361 
00362         vector tan1(patchDict.lookup("tan1"));
00363 
00364         const vector& n0 = pp.faceNormals()[0];
00365 
00366         if (correct2DPtr)
00367         {
00368             tan1 = correct2DPtr->planeNormal() ^ n0;
00369 
00370             WarningIn
00371             (
00372                 "directions::directions(const polyMesh&, const dictionary&,"
00373                 "const twoDPointCorrector*"
00374             )   << "Discarding user specified tan1 since 2D case." << endl
00375                 << "Recalculated tan1 from face normal and planeNormal as "
00376                 << tan1 << endl << endl;
00377         }
00378 
00379         Switch useTopo(dict.lookup("useHexTopology"));
00380 
00381         vectorField normalDirs;
00382         vectorField tan1Dirs;
00383 
00384         if (wantNormal || wantTan2)
00385         {
00386             normalDirs =
00387                 propagateDirection
00388                 (
00389                     mesh,
00390                     useTopo,
00391                     pp,
00392                     pp.faceNormals(),
00393                     n0
00394                 );
00395 
00396             if (wantNormal)
00397             {
00398                 operator[](nDirs++) = normalDirs;
00399 
00401                 //writeOBJ("normal.obj", mesh, normalDirs);
00402             }
00403         }
00404 
00405         if (wantTan1 || wantTan2)
00406         {
00407             tan1Dirs = 
00408                 propagateDirection
00409                 (
00410                     mesh,
00411                     useTopo,
00412                     pp,
00413                     vectorField(pp.size(), tan1),
00414                     tan1
00415                 );
00416 
00417 
00418             if (wantTan1)
00419             {
00420                 operator[](nDirs++) = tan1Dirs;
00421 
00423                 //writeOBJ("tan1.obj", mesh, tan1Dirs);
00424             }
00425         }
00426         if (wantTan2)
00427         {
00428             vectorField tan2Dirs = normalDirs ^ tan1Dirs;
00429 
00430             operator[](nDirs++) = tan2Dirs;
00431 
00433             //writeOBJ("tan2.obj", mesh, tan2Dirs);
00434         }
00435     }
00436     else
00437     {
00438         FatalErrorIn
00439         (
00440             "directions::directions(const polyMesh&, const dictionary&,"
00441             "const twoDPointCorrector*"
00442         )   << "Unknown coordinate system "
00443             << coordSystem << endl
00444             << "Known types are global and patchLocal" << exit(FatalError);
00445     }
00446 }
00447 
00448 
00449 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00450 
00451 
00452 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00453 
00454 
00455 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
00456 
00457 
00458 // * * * * * * * * * * * * * * * Friend Functions  * * * * * * * * * * * * * //
00459 
00460 
00461 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
00462 
00463 
00464 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines