00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00053
00054
00055 void Foam::directions::writeOBJ(Ostream& os, const point& pt)
00056 {
00057 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00058 }
00059
00060
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
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
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
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
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
00167 label edgeI = meshTools::cutDirToEdge(mesh, cellI, cutDir);
00168
00169
00170 label faceIndex =
00171 directionInfo::edgeToFaceIndex
00172 (
00173 mesh,
00174 cellI,
00175 meshFaceI,
00176 edgeI
00177 );
00178
00179
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,
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
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
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
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
00269
00270
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
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
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
00424 }
00425 }
00426 if (wantTan2)
00427 {
00428 vectorField tan2Dirs = normalDirs ^ tan1Dirs;
00429
00430 operator[](nDirs++) = tan2Dirs;
00431
00433
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
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464