1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "directions.H"
29 #include "twoDPointCorrector.H"
30 #include "directionInfo.H"
33 #include "meshTools.H"
34 #include "hexMatcher.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 const char* Foam::NamedEnum<Foam::directions::directionType, 3>::names[] =
47 const Foam::NamedEnum<Foam::directions::directionType, 3>
48 Foam::directions::directionTypeNames_;
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55 void Foam::directions::writeOBJ(Ostream& os, const point& pt)
57 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
61 void Foam::directions::writeOBJ
72 os << "l " << vertI + 1 << ' ' << vertI + 2 << endl;
79 void Foam::directions::writeOBJ
81 const fileName& fName,
82 const primitiveMesh& mesh,
83 const vectorField& dirs
86 Pout<< "Writing cell info to " << fName << " as vectors at the cellCentres"
89 OFstream xDirStream(fName);
95 const point& ctr = mesh.cellCentres()[cellI];
97 // Calculate local length scale
98 scalar minDist = GREAT;
100 const labelList& nbrs = mesh.cellCells()[cellI];
104 minDist = min(minDist, mag(mesh.cellCentres()[nbrs[nbrI]] - ctr));
107 scalar scale = 0.5*minDist;
109 writeOBJ(xDirStream, ctr, ctr + scale*dirs[cellI], vertI);
114 void Foam::directions::check2D
116 const twoDPointCorrector* correct2DPtr,
122 if (mag(correct2DPtr->planeNormal() & vec) > 1E-6)
124 FatalErrorIn("check2D") << "Specified vector " << vec
125 << "is not normal to plane defined in dynamicMeshDict."
127 << "Either make case 3D or adjust vector."
134 // Get direction on all cells
135 Foam::vectorField Foam::directions::propagateDirection
137 const polyMesh& mesh,
140 const vectorField& ppField,
141 const vector& defaultDir
144 // Seed all faces on patch
145 labelList changedFaces(pp.size());
146 List<directionInfo> changedFacesInfo(pp.size());
150 forAll(pp, patchFaceI)
152 label meshFaceI = pp.start() + patchFaceI;
154 label cellI = mesh.faceOwner()[meshFaceI];
156 if (!hexMatcher().isA(mesh, cellI))
158 FatalErrorIn("propagateDirection")
159 << "useHexTopology specified but cell " << cellI
160 << " on face " << patchFaceI << " of patch " << pp.name()
161 << " is not a hex" << exit(FatalError);
164 const vector& cutDir = ppField[patchFaceI];
166 // Get edge(bundle) on cell most in direction of cutdir
167 label edgeI = meshTools::cutDirToEdge(mesh, cellI, cutDir);
169 // Convert edge into index on face
171 directionInfo::edgeToFaceIndex
179 // Set initial face and direction
180 changedFaces[patchFaceI] = meshFaceI;
181 changedFacesInfo[patchFaceI] =
191 forAll(pp, patchFaceI)
193 changedFaces[patchFaceI] = pp.start() + patchFaceI;
194 changedFacesInfo[patchFaceI] =
197 -2, // Geometric information only
203 MeshWave<directionInfo> directionCalc
211 const List<directionInfo>& cellInfo = directionCalc.allCellInfo();
213 vectorField dirField(cellInfo.size());
219 forAll(cellInfo, cellI)
221 label index = cellInfo[cellI].index();
226 WarningIn("propagateDirection")
227 << "Cell " << cellI << " never visited to determine "
228 << "local coordinate system" << endl
229 << "Using direction " << defaultDir << " instead" << endl;
231 dirField[cellI] = defaultDir;
235 else if (index == -2)
237 // Geometric direction
238 dirField[cellI] = cellInfo[cellI].n();
242 else if (index == -1)
244 FatalErrorIn("propagateDirection")
245 << "Illegal index " << index << endl
246 << "Value is only allowed on faces" << abort(FatalError);
250 // Topological edge cut. Convert into average cut direction.
251 dirField[cellI] = meshTools::edgeToCutDir(mesh, cellI, index);
257 Pout<< "Calculated local coords for " << defaultDir
259 << " Geometric cut cells : " << nGeom << endl
260 << " Topological cut cells : " << nTopo << endl
261 << " Unset cells : " << nUnset << endl
268 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
270 // Construct from dictionary
271 Foam::directions::directions
273 const polyMesh& mesh,
274 const dictionary& dict,
275 const twoDPointCorrector* correct2DPtr
278 List<vectorField>(wordList(dict.lookup("directions")).size())
280 const wordList wantedDirs(dict.lookup("directions"));
282 bool wantNormal = false;
283 bool wantTan1 = false;
284 bool wantTan2 = false;
286 forAll(wantedDirs, i)
288 directionType wantedDir = directionTypeNames_[wantedDirs[i]];
290 if (wantedDir == NORMAL)
294 else if (wantedDir == TAN1)
298 else if (wantedDir == TAN2)
307 word coordSystem(dict.lookup("coordinateSystem"));
309 if (coordSystem == "global")
311 const dictionary& globalDict = dict.subDict("globalCoeffs");
313 vector tan1(globalDict.lookup("tan1"));
314 check2D(correct2DPtr, tan1);
316 vector tan2(globalDict.lookup("tan2"));
317 check2D(correct2DPtr, tan2);
319 vector normal = tan1 ^ tan2;
320 normal /= mag(normal);
322 Pout<< "Global Coordinate system:" << endl
323 << " normal : " << normal << endl
324 << " tan1 : " << tan1 << endl
325 << " tan2 : " << tan2
330 operator[](nDirs++) = vectorField(1, normal);
334 operator[](nDirs++) = vectorField(1, tan1);
338 operator[](nDirs++) = vectorField(1, tan2);
341 else if (coordSystem == "patchLocal")
343 const dictionary& patchDict = dict.subDict("patchLocalCoeffs");
345 word patchName(patchDict.lookup("patch"));
347 label patchI = mesh.boundaryMesh().findPatchID(patchName);
353 "directions::directions(const polyMesh&, const dictionary&,"
354 "const twoDPointCorrector*"
355 ) << "Cannot find patch "
356 << patchName << exit(FatalError);
359 // Take zeroth face on patch
360 const polyPatch& pp = mesh.boundaryMesh()[patchI];
362 vector tan1(patchDict.lookup("tan1"));
364 const vector& n0 = pp.faceNormals()[0];
368 tan1 = correct2DPtr->planeNormal() ^ n0;
372 "directions::directions(const polyMesh&, const dictionary&,"
373 "const twoDPointCorrector*"
374 ) << "Discarding user specified tan1 since 2D case." << endl
375 << "Recalculated tan1 from face normal and planeNormal as "
376 << tan1 << endl << endl;
379 Switch useTopo(dict.lookup("useHexTopology"));
381 vectorField normalDirs;
382 vectorField tan1Dirs;
384 if (wantNormal || wantTan2)
398 operator[](nDirs++) = normalDirs;
401 //writeOBJ("normal.obj", mesh, normalDirs);
405 if (wantTan1 || wantTan2)
413 vectorField(pp.size(), tan1),
420 operator[](nDirs++) = tan1Dirs;
423 //writeOBJ("tan1.obj", mesh, tan1Dirs);
428 vectorField tan2Dirs = normalDirs ^ tan1Dirs;
430 operator[](nDirs++) = tan2Dirs;
433 //writeOBJ("tan2.obj", mesh, tan2Dirs);
440 "directions::directions(const polyMesh&, const dictionary&,"
441 "const twoDPointCorrector*"
442 ) << "Unknown coordinate system "
443 << coordSystem << endl
444 << "Known types are global and patchLocal" << exit(FatalError);
449 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
452 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
455 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
458 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
461 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
464 // ************************************************************************* //