1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "directions.H"
28 #include "twoDPointCorrector.H"
29 #include "directionInfo.H"
32 #include "meshTools.H"
33 #include "hexMatcher.H"
35 #include "globalMeshData.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 const char* Foam::NamedEnum
44 Foam::directions::directionType,
54 const Foam::NamedEnum<Foam::directions::directionType, 3>
55 Foam::directions::directionTypeNames_;
58 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
61 void Foam::directions::writeOBJ(Ostream& os, const point& pt)
63 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
67 void Foam::directions::writeOBJ
78 os << "l " << vertI + 1 << ' ' << vertI + 2 << endl;
85 void Foam::directions::writeOBJ
87 const fileName& fName,
88 const primitiveMesh& mesh,
89 const vectorField& dirs
92 Pout<< "Writing cell info to " << fName << " as vectors at the cellCentres"
95 OFstream xDirStream(fName);
101 const point& ctr = mesh.cellCentres()[cellI];
103 // Calculate local length scale
104 scalar minDist = GREAT;
106 const labelList& nbrs = mesh.cellCells()[cellI];
110 minDist = min(minDist, mag(mesh.cellCentres()[nbrs[nbrI]] - ctr));
113 scalar scale = 0.5*minDist;
115 writeOBJ(xDirStream, ctr, ctr + scale*dirs[cellI], vertI);
120 void Foam::directions::check2D
122 const twoDPointCorrector* correct2DPtr,
128 if (mag(correct2DPtr->planeNormal() & vec) > 1E-6)
130 FatalErrorIn("check2D") << "Specified vector " << vec
131 << "is not normal to plane defined in dynamicMeshDict."
133 << "Either make case 3D or adjust vector."
140 // Get direction on all cells
141 Foam::vectorField Foam::directions::propagateDirection
143 const polyMesh& mesh,
146 const vectorField& ppField,
147 const vector& defaultDir
150 // Seed all faces on patch
151 labelList changedFaces(pp.size());
152 List<directionInfo> changedFacesInfo(pp.size());
156 forAll(pp, patchFaceI)
158 label meshFaceI = pp.start() + patchFaceI;
160 label cellI = mesh.faceOwner()[meshFaceI];
162 if (!hexMatcher().isA(mesh, cellI))
164 FatalErrorIn("propagateDirection")
165 << "useHexTopology specified but cell " << cellI
166 << " on face " << patchFaceI << " of patch " << pp.name()
167 << " is not a hex" << exit(FatalError);
170 const vector& cutDir = ppField[patchFaceI];
172 // Get edge(bundle) on cell most in direction of cutdir
173 label edgeI = meshTools::cutDirToEdge(mesh, cellI, cutDir);
175 // Convert edge into index on face
177 directionInfo::edgeToFaceIndex
185 // Set initial face and direction
186 changedFaces[patchFaceI] = meshFaceI;
187 changedFacesInfo[patchFaceI] =
197 forAll(pp, patchFaceI)
199 changedFaces[patchFaceI] = pp.start() + patchFaceI;
200 changedFacesInfo[patchFaceI] =
203 -2, // Geometric information only
209 MeshWave<directionInfo> directionCalc
214 mesh.globalData().nTotalCells()+1
217 const List<directionInfo>& cellInfo = directionCalc.allCellInfo();
219 vectorField dirField(cellInfo.size());
225 forAll(cellInfo, cellI)
227 label index = cellInfo[cellI].index();
232 WarningIn("propagateDirection")
233 << "Cell " << cellI << " never visited to determine "
234 << "local coordinate system" << endl
235 << "Using direction " << defaultDir << " instead" << endl;
237 dirField[cellI] = defaultDir;
241 else if (index == -2)
243 // Geometric direction
244 dirField[cellI] = cellInfo[cellI].n();
248 else if (index == -1)
250 FatalErrorIn("propagateDirection")
251 << "Illegal index " << index << endl
252 << "Value is only allowed on faces" << abort(FatalError);
256 // Topological edge cut. Convert into average cut direction.
257 dirField[cellI] = meshTools::edgeToCutDir(mesh, cellI, index);
263 Pout<< "Calculated local coords for " << defaultDir
265 << " Geometric cut cells : " << nGeom << endl
266 << " Topological cut cells : " << nTopo << endl
267 << " Unset cells : " << nUnset << endl
274 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
276 Foam::directions::directions
278 const polyMesh& mesh,
279 const dictionary& dict,
280 const twoDPointCorrector* correct2DPtr
283 List<vectorField>(wordList(dict.lookup("directions")).size())
285 const wordList wantedDirs(dict.lookup("directions"));
287 bool wantNormal = false;
288 bool wantTan1 = false;
289 bool wantTan2 = false;
291 forAll(wantedDirs, i)
293 directionType wantedDir = directionTypeNames_[wantedDirs[i]];
295 if (wantedDir == NORMAL)
299 else if (wantedDir == TAN1)
303 else if (wantedDir == TAN2)
312 const word coordSystem(dict.lookup("coordinateSystem"));
314 if (coordSystem == "global")
316 const dictionary& globalDict = dict.subDict("globalCoeffs");
318 vector tan1(globalDict.lookup("tan1"));
319 check2D(correct2DPtr, tan1);
321 vector tan2(globalDict.lookup("tan2"));
322 check2D(correct2DPtr, tan2);
324 vector normal = tan1 ^ tan2;
325 normal /= mag(normal);
327 Pout<< "Global Coordinate system:" << endl
328 << " normal : " << normal << endl
329 << " tan1 : " << tan1 << endl
330 << " tan2 : " << tan2
335 operator[](nDirs++) = vectorField(1, normal);
339 operator[](nDirs++) = vectorField(1, tan1);
343 operator[](nDirs++) = vectorField(1, tan2);
346 else if (coordSystem == "patchLocal")
348 const dictionary& patchDict = dict.subDict("patchLocalCoeffs");
350 const word patchName(patchDict.lookup("patch"));
352 const label patchI = mesh.boundaryMesh().findPatchID(patchName);
358 "directions::directions(const polyMesh&, const dictionary&,"
359 "const twoDPointCorrector*)"
360 ) << "Cannot find patch "
365 // Take zeroth face on patch
366 const polyPatch& pp = mesh.boundaryMesh()[patchI];
368 vector tan1(patchDict.lookup("tan1"));
370 const vector& n0 = pp.faceNormals()[0];
374 tan1 = correct2DPtr->planeNormal() ^ n0;
378 "directions::directions(const polyMesh&, const dictionary&,"
379 "const twoDPointCorrector*)"
380 ) << "Discarding user specified tan1 since 2D case." << endl
381 << "Recalculated tan1 from face normal and planeNormal as "
382 << tan1 << endl << endl;
385 Switch useTopo(dict.lookup("useHexTopology"));
387 vectorField normalDirs;
388 vectorField tan1Dirs;
390 if (wantNormal || wantTan2)
404 this->operator[](nDirs++) = normalDirs;
408 if (wantTan1 || wantTan2)
416 vectorField(pp.size(), tan1),
423 this->operator[](nDirs++) = tan1Dirs;
428 tmp<vectorField> tan2Dirs = normalDirs ^ tan1Dirs;
430 this->operator[](nDirs++) = tan2Dirs;
437 "directions::directions(const polyMesh&, const dictionary&,"
438 "const twoDPointCorrector*)"
439 ) << "Unknown coordinate system "
440 << coordSystem << endl
441 << "Known types are global and patchLocal"
447 // ************************************************************************* //