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
29 Calculates and writes the stream function of velocity field U at each time
31 \*---------------------------------------------------------------------------*/
34 #include "pointFields.H"
35 #include "emptyPolyPatch.H"
36 #include "symmetryPolyPatch.H"
37 #include "wedgePolyPatch.H"
38 #include "OSspecific.H"
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 int main(int argc, char *argv[])
45 timeSelector::addOptions();
47 # include "setRootCase.H"
48 # include "createTime.H"
50 instantList timeDirs = timeSelector::select0(runTime, args);
52 # include "createMeshNoClear.H"
54 pointMesh pMesh(mesh);
56 forAll(timeDirs, timeI)
58 runTime.setTime(timeDirs[timeI], timeI);
60 Info<< nl << "Time: " << runTime.timeName() << endl;
70 if (phiHeader.headerOk())
74 Info<< nl << "Reading field phi" << endl;
76 surfaceScalarField phi
89 pointScalarField streamFunction
100 dimensionedScalar("zero", phi.dimensions(), 0.0)
103 labelList visitedPoint(mesh.nPoints());
104 forAll (visitedPoint, pointI)
106 visitedPoint[pointI] = 0;
109 label nVisitedOld = 0;
111 const unallocFaceList& faces = mesh.faces();
112 const pointField& points = mesh.points();
114 label nInternalFaces = mesh.nInternalFaces();
116 vectorField unitAreas = mesh.faceAreas();
117 unitAreas /= mag(unitAreas);
119 const polyPatchList& patches = mesh.boundaryMesh();
121 bool finished = true;
123 // Find the boundary face with zero flux. set the stream function
124 // to zero on that face
131 forAll (patches, patchI)
133 const primitivePatch& bouFaces = patches[patchI];
135 if (!isType<emptyPolyPatch>(patches[patchI]))
137 forAll (bouFaces, faceI)
141 magSqr(phi.boundaryField()[patchI][faceI])
145 const labelList& zeroPoints = bouFaces[faceI];
147 // Zero flux face found
150 forAll (zeroPoints, pointI)
152 if (visitedPoint[zeroPoints[pointI]] == 1)
161 Info<< "Zero face: patch: " << patchI
162 << " face: " << faceI << endl;
164 forAll (zeroPoints, pointI)
166 streamFunction[zeroPoints[pointI]] = 0;
167 visitedPoint[zeroPoints[pointI]] = 1;
182 Info<< "zero flux boundary face not found. "
183 << "Using cell as a reference."
186 const cellList& c = mesh.cells();
190 labelList zeroPoints = c[cI].labels(mesh.faces());
194 forAll (zeroPoints, pointI)
196 if (visitedPoint[zeroPoints[pointI]] == 1)
205 forAll (zeroPoints, pointI)
207 streamFunction[zeroPoints[pointI]] = 0.0;
208 visitedPoint[zeroPoints[pointI]] = 1;
216 FatalErrorIn(args.executable())
217 << "Cannot find initialisation face or a cell."
218 << abort(FatalError);
223 // Loop through all faces. If one of the points on
224 // the face has the streamfunction value different
225 // from -1, all points with -1 ont that face have the
226 // streamfunction value equal to the face flux in
227 // that point plus the value in the visited point
234 label faceI = nInternalFaces;
239 const labelList& curBPoints = faces[faceI];
240 bool bPointFound = false;
242 scalar currentBStream = 0.0;
243 vector currentBStreamPoint(0, 0, 0);
245 forAll (curBPoints, pointI)
247 // Check if the point has been visited
248 if (visitedPoint[curBPoints[pointI]] == 1)
250 // The point has been visited
252 streamFunction[curBPoints[pointI]];
253 currentBStreamPoint =
254 points[curBPoints[pointI]];
264 // Sort out other points on the face
265 forAll (curBPoints, pointI)
267 // Check if the point has been visited
268 if (visitedPoint[curBPoints[pointI]] == 0)
271 mesh.boundaryMesh().whichPatch(faceI);
275 !isType<emptyPolyPatch>
277 && !isType<symmetryPolyPatch>
279 && !isType<wedgePolyPatch>
284 mesh.boundaryMesh()[patchNo]
288 points[curBPoints[pointI]]
289 - currentBStreamPoint;
290 edgeHat.replace(vector::Z, 0);
291 edgeHat /= mag(edgeHat);
293 vector nHat = unitAreas[faceI];
295 if (edgeHat.y() > VSMALL)
297 visitedPoint[curBPoints[pointI]] =
301 streamFunction[curBPoints[pointI]]
304 + phi.boundaryField()
308 else if (edgeHat.y() < -VSMALL)
310 visitedPoint[curBPoints[pointI]] =
314 streamFunction[curBPoints[pointI]]
317 - phi.boundaryField()
323 if (edgeHat.x() > VSMALL)
326 [curBPoints[pointI]] = 1;
330 [curBPoints[pointI]] =
332 + phi.boundaryField()
336 else if (edgeHat.x() < -VSMALL)
339 [curBPoints[pointI]] = 1;
343 [curBPoints[pointI]] =
345 - phi.boundaryField()
360 for (label faceI=0; faceI<nInternalFaces; faceI++)
362 // Get the list of point labels for the face
363 const labelList& curPoints = faces[faceI];
365 bool pointFound = false;
367 scalar currentStream = 0.0;
368 point currentStreamPoint(0, 0, 0);
370 forAll (curPoints, pointI)
372 // Check if the point has been visited
373 if (visitedPoint[curPoints[pointI]] == 1)
375 // The point has been visited
377 streamFunction[curPoints[pointI]];
379 points[curPoints[pointI]];
388 // Sort out other points on the face
389 forAll (curPoints, pointI)
391 // Check if the point has been visited
392 if (visitedPoint[curPoints[pointI]] == 0)
395 points[curPoints[pointI]]
396 - currentStreamPoint;
398 edgeHat.replace(vector::Z, 0);
399 edgeHat /= mag(edgeHat);
401 vector nHat = unitAreas[faceI];
403 if (edgeHat.y() > VSMALL)
405 visitedPoint[curPoints[pointI]] = 1;
408 streamFunction[curPoints[pointI]] =
410 + phi[faceI]*sign(nHat.x());
412 else if (edgeHat.y() < -VSMALL)
414 visitedPoint[curPoints[pointI]] = 1;
417 streamFunction[curPoints[pointI]] =
419 - phi[faceI]*sign(nHat.x());
431 // Info<< "One pass, n visited = " << nVisited << endl;
433 if (nVisited == nVisitedOld)
435 // Find new seed. This must be a
436 // multiply connected domain
437 Info<< nl << "Exhausted a seed. Looking for new seed "
438 << "(this is correct for multiply connected "
445 nVisitedOld = nVisited;
452 streamFunction.boundaryField() = 0.0;
453 streamFunction.write();
457 WarningIn(args.executable())
458 << "Flux field does not exist."
459 << " Stream function not calculated" << endl;
463 Info<< "\nEnd\n" << endl;
469 // ************************************************************************* //