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 "FacePostProcessing.H"
28 #include "ListListOps.H"
29 #include "surfaceWriter.H"
30 #include "globalIndex.H"
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 template<class CloudType>
35 void Foam::FacePostProcessing<CloudType>::makeLogFile
43 // Create the output file if not already created
48 Info<< "Creating output file." << endl;
51 if (Pstream::master())
53 const fileName logDir = outputDir_/this->owner().time().timeName();
55 // Create directory if does not exist
58 // Open new file at start up
62 new OFstream(logDir/(type() + '_' + zoneName + ".dat"))
66 << "# Source : " << type() << nl
67 << "# Face zone : " << zoneName << nl
68 << "# Faces : " << nFaces << nl
69 << "# Area : " << totArea << nl
70 << "# Time" << tab << "mass" << tab << "massFlux" << endl;
76 template<class CloudType>
77 void Foam::FacePostProcessing<CloudType>::write()
79 const fvMesh& mesh = this->owner().mesh();
80 const Time& time = mesh.time();
81 const faceZoneMesh& fzm = mesh.faceZones();
82 const scalar dt = time.deltaTValue();
86 const scalar alpha = (totalTime_ - dt)/totalTime_;
87 const scalar beta = dt/totalTime_;
89 forAll(faceZoneIDs_, zoneI)
91 massTotal_[zoneI] += mass_[zoneI];
92 massFlux_[zoneI] = alpha*massFlux_[zoneI] + beta*mass_[zoneI]/dt;
95 const label procI = Pstream::myProcNo();
97 Info<< "particleFaceFlux output:" << nl;
99 List<scalarField> zoneMassTotal(mass_.size());
100 List<scalarField> zoneMassFlux(massFlux_.size());
101 forAll(faceZoneIDs_, zoneI)
103 const word& zoneName = fzm[faceZoneIDs_[zoneI]].name();
105 scalarListList allProcMass(Pstream::nProcs());
106 allProcMass[procI] = massTotal_[zoneI];
107 Pstream::gatherList(allProcMass);
108 zoneMassTotal[zoneI] =
109 ListListOps::combine<scalarList>
111 allProcMass, accessOp<scalarList>()
113 const scalar sumMassTotal = sum(zoneMassTotal[zoneI]);
115 scalarListList allProcMassFlux(Pstream::nProcs());
116 allProcMassFlux[procI] = massFlux_[zoneI];
117 Pstream::gatherList(allProcMassFlux);
118 zoneMassFlux[zoneI] =
119 ListListOps::combine<scalarList>
121 allProcMassFlux, accessOp<scalarList>()
123 const scalar sumMassFlux = sum(zoneMassFlux[zoneI]);
125 Info<< " " << zoneName
126 << ": total mass = " << sumMassTotal
127 << "; average mass flux = " << sumMassFlux
130 if (outputFilePtr_.set(zoneI))
132 OFstream& os = outputFilePtr_[zoneI];
133 os << time.timeName() << token::TAB << sumMassTotal << token::TAB
134 << sumMassFlux<< endl;
141 if (surfaceFormat_ != "none")
143 forAll(faceZoneIDs_, zoneI)
145 const faceZone& fZone = fzm[faceZoneIDs_[zoneI]];
147 labelList pointToGlobal;
148 labelList uniqueMeshPointLabels;
149 autoPtr<globalIndex> globalPointsPtr =
150 mesh.globalData().mergePoints
152 fZone().meshPoints(),
153 fZone().meshPointMap(),
155 uniqueMeshPointLabels
158 pointField uniquePoints(mesh.points(), uniqueMeshPointLabels);
159 List<pointField> allProcPoints(Pstream::nProcs());
160 allProcPoints[procI] = uniquePoints;
161 Pstream::gatherList(allProcPoints);
163 faceList faces(fZone().localFaces());
166 inplaceRenumber(pointToGlobal, faces[i]);
168 List<faceList> allProcFaces(Pstream::nProcs());
169 allProcFaces[procI] = faces;
170 Pstream::gatherList(allProcFaces);
172 if (Pstream::master())
176 ListListOps::combine<pointField>
178 allProcPoints, accessOp<pointField>()
184 ListListOps::combine<faceList>
186 allProcFaces, accessOp<faceList>()
190 autoPtr<surfaceWriter> writer
192 surfaceWriter::New(surfaceFormat_)
197 outputDir_/time.timeName(),
202 zoneMassTotal[zoneI],
208 outputDir_/time.timeName(),
223 forAll(faceZoneIDs_, zoneI)
225 massFlux_[zoneI] = 0.0;
235 // writeProperties();
239 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
241 template<class CloudType>
242 Foam::FacePostProcessing<CloudType>::FacePostProcessing
244 const dictionary& dict,
248 CloudFunctionObject<CloudType>(dict, owner, typeName),
250 surfaceFormat_(this->coeffDict().lookup("surfaceFormat")),
251 resetOnWrite_(this->coeffDict().lookup("resetOnWrite")),
256 log_(this->coeffDict().lookup("log")),
258 outputDir_(owner.mesh().time().path())
260 wordList faceZoneNames(this->coeffDict().lookup("faceZones"));
261 mass_.setSize(faceZoneNames.size());
262 massTotal_.setSize(faceZoneNames.size());
263 massFlux_.setSize(faceZoneNames.size());
265 outputFilePtr_.setSize(faceZoneNames.size());
267 if (Pstream::parRun())
269 // Put in undecomposed case (Note: gives problems for
270 // distributed data running)
272 outputDir_/".."/"postProcessing"/cloud::prefix/owner.name();
277 outputDir_/"postProcessing"/cloud::prefix/owner.name();
280 DynamicList<label> zoneIDs;
281 const faceZoneMesh& fzm = owner.mesh().faceZones();
282 const surfaceScalarField& magSf = owner.mesh().magSf();
283 const polyBoundaryMesh& pbm = owner.mesh().boundaryMesh();
284 forAll(faceZoneNames, i)
286 const word& zoneName = faceZoneNames[i];
287 label zoneI = fzm.findZoneID(zoneName);
290 zoneIDs.append(zoneI);
291 const faceZone& fz = fzm[zoneI];
292 mass_[i].setSize(fz.size(), 0.0);
293 massTotal_[i].setSize(fz.size(), 0.0);
294 massFlux_[i].setSize(fz.size(), 0.0);
296 label nFaces = returnReduce(fz.size(), sumOp<label>());
297 Info<< " " << zoneName << " faces: " << nFaces << nl;
299 scalar totArea = 0.0;
303 if (faceI < owner.mesh().nInternalFaces())
305 totArea += magSf[fz[j]];
309 label bFaceI = faceI - owner.mesh().nInternalFaces();
310 label patchI = pbm.patchID()[bFaceI];
311 const polyPatch& pp = pbm[patchI];
316 || refCast<const coupledPolyPatch>(pp).owner()
319 label localFaceI = pp.whichFace(faceI);
320 totArea += magSf.boundaryField()[patchI][localFaceI];
324 totArea = returnReduce(totArea, sumOp<scalar>());
326 makeLogFile(zoneName, i, nFaces, totArea);
330 faceZoneIDs_.transfer(zoneIDs);
332 // readProperties(); AND initialise mass... fields
336 template<class CloudType>
337 Foam::FacePostProcessing<CloudType>::FacePostProcessing
339 const FacePostProcessing<CloudType>& pff
342 CloudFunctionObject<CloudType>(pff),
343 faceZoneIDs_(pff.faceZoneIDs_),
344 surfaceFormat_(pff.surfaceFormat_),
345 resetOnWrite_(pff.resetOnWrite_),
346 totalTime_(pff.totalTime_),
348 massTotal_(pff.massTotal_),
349 massFlux_(pff.massFlux_),
352 outputDir_(pff.outputDir_)
356 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
358 template<class CloudType>
359 Foam::FacePostProcessing<CloudType>::~FacePostProcessing()
363 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
365 template<class CloudType>
366 void Foam::FacePostProcessing<CloudType>::postFace
374 this->owner().solution().output()
375 || this->owner().solution().transient()
378 const faceZoneMesh& fzm = this->owner().mesh().faceZones();
380 forAll(faceZoneIDs_, i)
382 const faceZone& fz = fzm[faceZoneIDs_[i]];
396 mass_[i][faceId] += p.mass()*p.nParticle();
403 // ************************************************************************* //