volFieldValue.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "volFieldValue.H"
27 #include "fvMesh.H"
28 #include "volFields.H"
29 #include "writeFile.H"
30 #include "polyTopoChangeMap.H"
31 #include "polyMeshMap.H"
32 #include "polyDistributionMap.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 namespace functionObjects
40 {
41 namespace fieldValues
42 {
46 }
47 }
48 }
49 
50 const Foam::NamedEnum
51 <
53  12
55 {
56  "none",
57  "sum",
58  "sumMag",
59  "average",
60  "volAverage",
61  "volIntegrate",
62  "min",
63  "max",
64  "minMag",
65  "maxMag",
66  "CoV",
67  "UI"
68 };
69 
70 
71 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
72 
73 template<class Type>
76 {
77  switch (operation_)
78  {
81  file() << tab << "location" << tab << "cell";
82  if (Pstream::parRun())
83  {
84  file() << tab << "processor";
85  }
86  break;
87  default:
88  break;
89  }
90 }
91 
92 
93 template<>
94 void Foam::functionObjects::fieldValues::volFieldValue::
95 writeFileHeaderLocation<Foam::scalar>()
96 {
97  switch (operation_)
98  {
99  case operationType::min:
100  case operationType::max:
101  case operationType::minMag:
102  case operationType::maxMag:
103  file() << tab << "location" << tab << "cell";
104  if (Pstream::parRun())
105  {
106  file() << tab << "processor";
107  }
108  break;
109  default:
110  break;
111  }
112 }
113 
114 
116 (
117  const label i
118 )
119 {
120  if (operation_ != operationType::none)
121  {
122  zone_.writeFileHeader(*this, file());
123 
124  writeCommented(file(), "Time");
125 
126  if (writeNCells_) file() << tab << "Cells";
127  if (writeVolume_) file() << tab << "Volume";
128 
129  forAll(fields_, fieldi)
130  {
131  file() << tab << operationTypeNames_[operation_] << "(";
132 
133  forAll(weightFieldNames_, i)
134  {
135  file() << weightFieldNames_[i] << ',';
136  }
137 
138  file() << fields_[fieldi] << ")";
139 
140  if (writeLocation_)
141  {
142  #define writeFileHeaderLocationFieldType(fieldType, none) \
143  if (validField<fieldType>(fields_[fieldi])) \
144  { \
145  writeFileHeaderLocation<fieldType>(); \
146  }
148  #undef writeHeaderLocationFieldType
149  }
150  }
151 
152  file() << endl;
153  }
154 }
155 
156 
158 (
159  const Field<scalar>& values,
160  const scalarField& weights,
161  const scalarField& V,
162  Result<scalar>& result
163 ) const
164 {
165  switch (operation_)
166  {
167  case operationType::min:
168  {
169  compareScalars(values, vGreat, result, lessOp<scalar>());
170  return true;
171  }
172  case operationType::minMag:
173  {
174  compareScalars(mag(values), vGreat, result, lessOp<scalar>());
175  return true;
176  }
177  case operationType::max:
178  {
179  compareScalars(values, -vGreat, result, greaterOp<scalar>());
180  return true;
181  }
182  case operationType::maxMag:
183  {
184  compareScalars(mag(values), -vGreat, result, greaterOp<scalar>());
185  return true;
186  }
187  default:
188  {
189  // Fall through to same-type operations
190  return processValuesTypeType(values, weights, V, result);
191  }
192  }
193 }
194 
195 
196 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
197 
199 (
200  const word& name,
201  const Time& runTime,
202  const dictionary& dict
203 )
204 :
205  fieldValue(name, runTime, dict, typeName),
206  zone_(fieldValue::mesh_, dict),
207  operation_(operationTypeNames_.read(dict.lookup("operation"))),
208  scaleFactor_(1),
209  writeNCells_(dict.lookupOrDefault("writeNumberOfCells", false)),
210  writeVolume_(dict.lookupOrDefault("writeVolume", false)),
211  writeLocation_(dict.lookupOrDefault("writeLocation", false))
212 {
213  read(dict);
214 }
215 
216 
218 (
219  const word& name,
220  const objectRegistry& obr,
221  const dictionary& dict
222 )
223 :
224  fieldValue(name, obr, dict, typeName),
225  zone_(fieldValue::mesh_, dict),
226  operation_(operationTypeNames_.read(dict.lookup("operation"))),
227  scaleFactor_(1),
228  writeNCells_(dict.lookupOrDefault("writeNumberOfCells", false)),
229  writeVolume_(dict.lookupOrDefault("writeVolume", false)),
230  writeLocation_(dict.lookupOrDefault("writeLocation", false))
231 {
232  read(dict);
233 }
234 
235 
236 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
237 
239 {}
240 
241 
242 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
243 
245 (
246  const dictionary& dict
247 )
248 {
250 
251  if (dict.found("weightFields"))
252  {
253  dict.lookup("weightFields") >> weightFieldNames_;
254  }
255  else if (dict.found("weightField"))
256  {
257  weightFieldNames_.setSize(1);
258 
259  dict.lookup("weightField") >> weightFieldNames_[0];
260  }
261 
262  dict.readIfPresent("scaleFactor", scaleFactor_);
263 
264  // Report configuration
265  Info<< type() << ' ' << name() << " read:" << nl;
266  Info<< " number of cells = " << zone_.nGlobalCells() << nl;
267  if (zone_.nGlobalCells())
268  {
269  Info<< " volume = " << zone_.V() << nl;
270  }
271  Info<< " operation = " << operationTypeNames_[operation_] << nl;
272  if (weightFieldNames_.size() == 1)
273  {
274  Info<< " weight field = " << weightFieldNames_[0] << nl;
275  }
276  if (weightFieldNames_.size() > 1)
277  {
278  Info<< " weight fields =";
279  forAll(weightFieldNames_, i) Info<< ' ' << weightFieldNames_[i];
280  Info<< nl;
281  }
282  if (scaleFactor_ != scalar(1))
283  {
284  Info<< " scale factor = " << scaleFactor_;
285  }
286  Info<< endl;
287 
288  return true;
289 }
290 
291 
293 {
294  // Look to see if any fields exist. Use the flag to suppress output later.
295  bool anyFields = false;
296  forAll(fields_, i)
297  {
298  #define validFieldType(fieldType, none) \
299  anyFields = anyFields || validField<fieldType>(fields_[i]);
301  #undef validFieldType
302  }
303  if (!anyFields && fields_.size() > 1) // (error for 1 will happen below)
304  {
305  cannotFindObjects(fields_);
306  }
307 
308  // Initialise the file, write the header, etc...
309  if (anyFields && operation_ != operationType::none)
310  {
312  }
313 
314  // Write the time
315  if (anyFields && operation_ != operationType::none && Pstream::master())
316  {
317  writeTime(file());
318  }
319 
320  // Write the number of faces and/or the area if necessary
321  if (anyFields && operation_ != operationType::none && Pstream::master())
322  {
323  if (writeNCells_)
324  {
325  file() << tab << zone_.nGlobalCells();
326  }
327  if (writeVolume_)
328  {
329  file() << tab << zone_.V();
330  }
331  }
332  if (writeNCells_)
333  {
334  Log << " number of cells = " << zone_.nGlobalCells() << endl;
335  }
336  if (writeVolume_)
337  {
338  Log << " volume = " << zone_.V() << endl;
339  }
340 
341  // Construct the weight field and the volumes
342  scalarField weights(zone_.nCells(), 1);
343  forAll(weightFieldNames_, i)
344  {
345  weights *= getFieldValues<scalar>(weightFieldNames_[i]);
346  }
347  const scalarField V(filterField(fieldValue::mesh_.V()));
348 
349  // Process the fields
350  forAll(fields_, i)
351  {
352  const word& fieldName = fields_[i];
353  bool ok = false;
354 
355  #define writeValuesFieldType(fieldType, none) \
356  ok = ok || writeValues<fieldType>(fieldName, weights, V);
358  #undef writeValuesFieldType
359 
360  if (!ok)
361  {
362  cannotFindObject(fieldName);
363  }
364  }
365 
366  // Finalise
367  if (anyFields && operation_ != operationType::none && Pstream::master())
368  {
369  file() << endl;
370  }
371  Log << endl;
372 
373  return true;
374 }
375 
376 
378 (
379  const polyMesh& mesh
380 )
381 {
382  if (&mesh == &this->mesh())
383  {
385  zone_.movePoints();
386  }
387 }
388 
389 
391 (
392  const polyTopoChangeMap& map
393 )
394 {
395  if (&map.mesh() == &mesh())
396  {
398  zone_.topoChange(map);
399  }
400 }
401 
402 
404 (
405  const polyMeshMap& map
406 )
407 {
408  if (&map.mesh() == &mesh())
409  {
410  fieldValue::mapMesh(map);
411  zone_.mapMesh(map);
412  }
413 }
414 
415 
417 (
418  const polyDistributionMap& map
419 )
420 {
421  if (&map.mesh() == &mesh())
422  {
424  zone_.distribute(map);
425  }
426 }
427 
428 
429 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
Macros for easy insertion into run-time selection tables.
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:55
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:76
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
Abstract base-class for Time/database functionObjects.
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
virtual void movePoints(const polyMesh &mesh)
Update topology using the given map.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
virtual void topoChange(const polyTopoChangeMap &map)
Update topology using the given map.
Base class for field value -based function objects.
Definition: fieldValue.H:66
const dictionary & dict() const
Return the reference to the construction dictionary.
virtual bool read(const dictionary &dict)
Read from dictionary.
Definition: fieldValue.C:86
virtual bool write()
Write.
Definition: fieldValue.C:105
Provides a 'fvCellZone' specialisation of the fieldValue function object.
virtual void topoChange(const polyTopoChangeMap &)
Update topology using the given map.
virtual void distribute(const polyDistributionMap &)
Redistribute or update using the given distribution map.
void writeFileHeaderLocation()
Output file header location information for a given type.
Definition: volFieldValue.C:75
operationType operation_
Operation to apply to values.
volFieldValue(const word &name, const Time &runTime, const dictionary &dict)
Construct from name, Time and dictionary.
static const NamedEnum< operationType, 12 > operationTypeNames_
Operation type names.
virtual void mapMesh(const polyMeshMap &)
Update from another mesh using the given map.
virtual void writeFileHeader(const label i)
Output file header information.
virtual void movePoints(const polyMesh &)
Update for mesh motion.
virtual bool write()
Calculate and write.
bool processValues(const Field< Type > &values, const scalarField &weights, const scalarField &V, Result< ResultType > &result) const
Apply the operation to the values, and return true if successful.
virtual bool read(const dictionary &)
Read from dictionary.
const fvMesh & mesh_
Reference to the fvMesh.
OFstream & file()
Return access to the file (if only 1)
Definition: logFiles.C:113
Registry of regIOobjects.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
const polyMesh & mesh() const
Return polyMesh.
Class containing mesh-to-mesh mapping information.
Definition: polyMeshMap.H:51
const polyMesh & mesh() const
Return polyMesh.
Definition: polyMeshMap.H:75
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
const polyMesh & mesh() const
Return polyMesh.
A class for handling words, derived from string.
Definition: word.H:62
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define Log
Report write to Foam::Info if the local log switch is true.
defineTypeNameAndDebug(fieldValueDelta, 0)
addToRunTimeSelectionTable(functionObject, fieldValueDelta, dictionary)
Namespace for OpenFOAM.
bool read(const char *, int32_t &)
Definition: int32IO.C:85
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
static const char tab
Definition: Ostream.H:266
messageStream Info
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
FOR_ALL_FIELD_TYPES(makeFieldSourceTypedef)
static const char nl
Definition: Ostream.H:267
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
dictionary dict
#define writeFileHeaderLocationFieldType(fieldType, none)
#define writeValuesFieldType(fieldType, none)
#define validFieldType(fieldType, none)