FacePostProcessing.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2016-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "FacePostProcessing.H"
30 #include "Pstream.H"
31 #include "ListListOps.H"
32 #include "globalIndex.H"
33 #include "surfaceWriter.H"
34 
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
36 
37 template<class CloudType>
39 (
40  const word& zoneName,
41  const label zoneI,
42  const label nFaces,
43  const scalar totArea
44 )
45 {
46  // Create the output file if not already created
47  if (log_)
48  {
49  if (debug)
50  {
51  Info<< "Creating output file." << endl;
52  }
53 
54  if (Pstream::master())
55  {
56  // Create directory if does not exist
57  mkDir(this->writeTimeDir());
58 
59  // Open new file at start up
60  outputFilePtr_.set
61  (
62  zoneI,
63  new OFstream
64  (
65  this->writeTimeDir()/(type() + '_' + zoneName + ".dat")
66  )
67  );
68 
69  outputFilePtr_[zoneI]
70  << "# Source : " << type() << nl
71  << "# Face zone : " << zoneName << nl
72  << "# Faces : " << nFaces << nl
73  << "# Area : " << totArea << nl
74  << "# Time" << tab << "mass" << tab << "massFlowRate" << endl;
75  }
76  }
77 }
78 
79 
80 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
81 
82 template<class CloudType>
84 {
85  const fvMesh& mesh = this->owner().mesh();
86  const Time& time = mesh.time();
87  const faceZoneMesh& fzm = mesh.faceZones();
88  scalar timeNew = time.value();
89  scalar timeElapsed = timeNew - timeOld_;
90 
91  totalTime_ += timeElapsed;
92 
93  const scalar alpha = (totalTime_ - timeElapsed)/totalTime_;
94  const scalar beta = timeElapsed/totalTime_;
95 
96  forAll(faceZoneIDs_, zoneI)
97  {
98  massFlowRate_[zoneI] =
99  alpha*massFlowRate_[zoneI] + beta*mass_[zoneI]/timeElapsed;
100  massTotal_[zoneI] += mass_[zoneI];
101  }
102 
103  const label proci = Pstream::myProcNo();
104 
105  Info<< type() << " output:" << nl;
106 
107  List<scalarField> zoneMassTotal(mass_.size());
108  List<scalarField> zoneMassFlowRate(massFlowRate_.size());
109  forAll(faceZoneIDs_, zoneI)
110  {
111  const word& zoneName = fzm[faceZoneIDs_[zoneI]].name();
112 
113  scalarListList allProcMass(Pstream::nProcs());
114  allProcMass[proci] = massTotal_[zoneI];
115  Pstream::gatherList(allProcMass);
116  zoneMassTotal[zoneI] =
117  ListListOps::combine<scalarList>
118  (
119  allProcMass, accessOp<scalarList>()
120  );
121  const scalar sumMassTotal = sum(zoneMassTotal[zoneI]);
122 
123  scalarListList allProcMassFlowRate(Pstream::nProcs());
124  allProcMassFlowRate[proci] = massFlowRate_[zoneI];
125  Pstream::gatherList(allProcMassFlowRate);
126  zoneMassFlowRate[zoneI] =
127  ListListOps::combine<scalarList>
128  (
129  allProcMassFlowRate, accessOp<scalarList>()
130  );
131  const scalar sumMassFlowRate = sum(zoneMassFlowRate[zoneI]);
132 
133  Info<< " " << zoneName
134  << ": total mass = " << sumMassTotal
135  << "; average mass flow rate = " << sumMassFlowRate
136  << nl;
137 
138  if (outputFilePtr_.set(zoneI))
139  {
140  OFstream& os = outputFilePtr_[zoneI];
141  os << time.timeName() << token::TAB << sumMassTotal << token::TAB
142  << sumMassFlowRate<< endl;
143  }
144  }
145 
146  Info<< endl;
147 
148 
149  if (surfaceFormat_ != "none")
150  {
151  forAll(faceZoneIDs_, zoneI)
152  {
153  const faceZone& fZone = fzm[faceZoneIDs_[zoneI]];
154 
155  labelList pointToGlobal;
156  labelList uniqueMeshPointLabels;
157  autoPtr<globalIndex> globalPointsPtr =
158  mesh.globalData().mergePoints
159  (
160  fZone().meshPoints(),
161  fZone().meshPointMap(),
162  pointToGlobal,
163  uniqueMeshPointLabels
164  );
165 
166  pointField uniquePoints(mesh.points(), uniqueMeshPointLabels);
167  List<pointField> allProcPoints(Pstream::nProcs());
168  allProcPoints[proci] = uniquePoints;
169  Pstream::gatherList(allProcPoints);
170 
171  faceList faces(fZone().localFaces());
172  forAll(faces, i)
173  {
174  inplaceRenumber(pointToGlobal, faces[i]);
175  }
176  List<faceList> allProcFaces(Pstream::nProcs());
177  allProcFaces[proci] = faces;
178  Pstream::gatherList(allProcFaces);
179 
180  if (Pstream::master())
181  {
183  (
184  ListListOps::combine<pointField>
185  (
186  allProcPoints, accessOp<pointField>()
187  )
188  );
189 
190  faceList allFaces
191  (
192  ListListOps::combine<faceList>
193  (
194  allProcFaces, accessOp<faceList>()
195  )
196  );
197 
199  (
200  surfaceFormat_,
201  this->coeffDict().subOrEmptyDict("formatOptions")
202  .subOrEmptyDict(surfaceFormat_)
203  );
204 
205  if (debug)
206  {
207  writer->verbose(true);
208  }
209 
210  writer->open
211  (
212  allPoints,
213  allFaces,
214  (this->writeTimeDir() / fZone.name()),
215  false // serial - already merged
216  );
217 
218  writer->nFields(2); // Legacy VTK
219  writer->write("massTotal", zoneMassTotal[zoneI]);
220  writer->write("massFlowRate", zoneMassFlowRate[zoneI]);
221  }
222  }
223  }
224 
225 
226  if (resetOnWrite_)
227  {
228  forAll(faceZoneIDs_, zoneI)
229  {
230  massFlowRate_[zoneI] = 0.0;
231  }
232  timeOld_ = timeNew;
233  totalTime_ = 0.0;
234  }
235 
236  forAll(mass_, zoneI)
237  {
238  mass_[zoneI] = 0.0;
239  }
240 
241  // writeProperties();
242 }
243 
244 
245 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
246 
247 template<class CloudType>
249 (
250  const dictionary& dict,
251  CloudType& owner,
252  const word& modelName
253 )
254 :
255  CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
256  faceZoneIDs_(),
257  surfaceFormat_(this->coeffDict().lookup("surfaceFormat")),
258  resetOnWrite_(this->coeffDict().getBool("resetOnWrite")),
259  log_(this->coeffDict().getBool("log")),
260  totalTime_(0.0),
261  mass_(),
262  massTotal_(),
263  massFlowRate_(),
264  outputFilePtr_(),
265  timeOld_(owner.mesh().time().value())
266 {
267  wordList faceZoneNames(this->coeffDict().lookup("faceZones"));
268  mass_.setSize(faceZoneNames.size());
269  massTotal_.setSize(faceZoneNames.size());
270  massFlowRate_.setSize(faceZoneNames.size());
271 
272  outputFilePtr_.setSize(faceZoneNames.size());
273 
275  const faceZoneMesh& fzm = owner.mesh().faceZones();
276  const surfaceScalarField& magSf = owner.mesh().magSf();
277  const polyBoundaryMesh& pbm = owner.mesh().boundaryMesh();
278  forAll(faceZoneNames, i)
279  {
280  const word& zoneName = faceZoneNames[i];
281  label zoneI = fzm.findZoneID(zoneName);
282  if (zoneI != -1)
283  {
284  zoneIDs.append(zoneI);
285  const faceZone& fz = fzm[zoneI];
286  mass_[i].setSize(fz.size(), 0.0);
287  massTotal_[i].setSize(fz.size(), 0.0);
288  massFlowRate_[i].setSize(fz.size(), 0.0);
289 
290  label nFaces = returnReduce(fz.size(), sumOp<label>());
291  Info<< " " << zoneName << " faces: " << nFaces << nl;
292 
293  scalar totArea = 0.0;
294  forAll(fz, j)
295  {
296  label facei = fz[j];
297  if (facei < owner.mesh().nInternalFaces())
298  {
299  totArea += magSf[fz[j]];
300  }
301  else
302  {
303  label bFacei = facei - owner.mesh().nInternalFaces();
304  label patchi = pbm.patchID()[bFacei];
305  const polyPatch& pp = pbm[patchi];
306 
307  if
308  (
309  !magSf.boundaryField()[patchi].coupled()
310  || refCast<const coupledPolyPatch>(pp).owner()
311  )
312  {
313  label localFacei = pp.whichFace(facei);
314  totArea += magSf.boundaryField()[patchi][localFacei];
315  }
316  }
317  }
318  totArea = returnReduce(totArea, sumOp<scalar>());
319 
320  makeLogFile(zoneName, i, nFaces, totArea);
321  }
322  }
323 
324  faceZoneIDs_.transfer(zoneIDs);
325 
326  // readProperties(); AND initialise mass... fields
327 }
328 
329 
330 template<class CloudType>
332 (
334 )
335 :
337  faceZoneIDs_(pff.faceZoneIDs_),
338  surfaceFormat_(pff.surfaceFormat_),
339  resetOnWrite_(pff.resetOnWrite_),
340  log_(pff.log_),
341  totalTime_(pff.totalTime_),
342  mass_(pff.mass_),
343  massTotal_(pff.massTotal_),
344  massFlowRate_(pff.massFlowRate_),
345  outputFilePtr_(),
346  timeOld_(0.0)
347 {}
348 
349 
350 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
351 
352 template<class CloudType>
353 void Foam::FacePostProcessing<CloudType>::postFace(const parcelType& p, bool&)
354 {
355  if
356  (
357  this->owner().solution().output()
358  || this->owner().solution().transient()
359  )
360  {
361  const faceZoneMesh& fzm = this->owner().mesh().faceZones();
362 
363  forAll(faceZoneIDs_, i)
364  {
365  const faceZone& fz = fzm[faceZoneIDs_[i]];
366 
367  label faceId = -1;
368  forAll(fz, j)
369  {
370  if (fz[j] == p.face())
371  {
372  faceId = j;
373  break;
374  }
375  }
376 
377  if (faceId != -1)
378  {
379  mass_[i][faceId] += p.mass()*p.nParticle();
380  }
381  }
382  }
383 }
384 
385 
386 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
Foam::accessOp
Definition: UList.H:668
Foam::solution
Selector class for relaxation factors, solver type and solution.
Definition: solution.H:55
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::DynamicList< label >
ListListOps.H
Foam::constant::atomic::alpha
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Definition: readThermalProperties.H:212
globalIndex.H
Foam::Time::timeName
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
Foam::writer::write
virtual void write(const coordSet &, const wordList &, const List< const Field< Type > * > &, Ostream &) const =0
General entry point for writing.
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::dimensioned::value
const Type & value() const
Return const reference to value.
Definition: dimensionedType.C:434
surfaceWriter.H
zoneIDs
const labelIOList & zoneIDs
Definition: correctPhi.H:59
Foam::FacePostProcessing
Records particle face quantities on used-specified face zone.
Definition: FacePostProcessing.H:60
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::polyBoundaryMesh::patchID
const labelList & patchID() const
Per boundary face label the patch index.
Definition: polyBoundaryMesh.C:456
Foam::Field< vector >
Foam::fvMesh::magSf
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
Definition: fvMeshGeometry.C:330
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::DSMCCloud::mesh
const fvMesh & mesh() const
Return reference to the mesh.
Definition: DSMCCloudI.H:44
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
faceId
label faceId(-1)
beta
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
Foam::ZoneMesh< faceZone, polyMesh >
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::ListListOps::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &lists)
Inplace renumber the values (not the indices) of a list of lists.
Definition: ensightOutput.H:89
Foam::radiation::lookup
Lookup type of boundary radiation properties.
Definition: lookup.H:63
Foam::DSMCCloud
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:71
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::writer
Base class for graphics format writing. Entry points are.
Definition: writer.H:81
Pstream.H
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::ZoneMesh::findZoneID
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
Definition: ZoneMesh.C:519
Foam::FacePostProcessing::postFace
virtual void postFace(const parcelType &p, bool &keepParticle)
Post-face hook.
Definition: FacePostProcessing.C:353
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::FacePostProcessing::FacePostProcessing
FacePostProcessing(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
Definition: FacePostProcessing.C:249
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::polyPatch::whichFace
label whichFace(const label l) const
Return label of face in patch from global face label.
Definition: polyPatch.H:448
Foam::tab
constexpr char tab
Definition: Ostream.H:403
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::zoneIdentifier::name
const word & name() const noexcept
The zone name.
Definition: zoneIdentifier.H:123
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::List< scalarField >
Foam::CloudFunctionObject
Templated cloud function object base class.
Definition: CloudFunctionObject.H:62
Foam::FacePostProcessing::write
void write()
Write post-processing info.
Definition: FacePostProcessing.C:83
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::roots::type
type
Types of root.
Definition: Roots.H:54
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:280
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
FacePostProcessing.H
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62