areaWrite.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) 2019-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "areaWrite.H"
29 #include "polySurface.H"
30 
31 #include "fvMesh.H"
32 #include "mapPolyMesh.H"
33 #include "areaFields.H"
34 #include "HashOps.H"
35 #include "ListOps.H"
36 #include "Time.H"
37 #include "IndirectList.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44  defineTypeNameAndDebug(areaWrite, 0);
45 
47  (
48  functionObject,
49  areaWrite,
50  dictionary
51  );
52 }
53 
54 Foam::scalar Foam::areaWrite::mergeTol_ = 1e-10;
55 
56 
57 // Implementation
58 #include "areaWriteImpl.C"
59 
60 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
61 
62 Foam::areaWrite::areaWrite
63 (
64  const word& name,
65  const Time& runTime,
66  const dictionary& dict
67 )
68 :
69  functionObjects::fvMeshFunctionObject(name, runTime, dict),
70  loadFromFiles_(false),
71  verbose_(false),
72  outputPath_
73  (
74  time_.globalPath()/functionObject::outputPrefix/name
75  ),
76  selectAreas_(),
77  fieldSelection_(),
78  meshes_(),
79  surfaces_(nullptr),
80  writers_()
81 {
82  outputPath_.clean(); // Remove unneeded ".."
83 
84  read(dict);
85 }
86 
87 
88 Foam::areaWrite::areaWrite
89 (
90  const word& name,
91  const objectRegistry& obr,
92  const dictionary& dict,
93  const bool loadFromFiles
94 )
95 :
96  functionObjects::fvMeshFunctionObject(name, obr, dict),
97  loadFromFiles_(loadFromFiles),
98  verbose_(false),
99  outputPath_
100  (
101  time_.globalPath()/functionObject::outputPrefix/name
102  ),
103  selectAreas_(),
104  fieldSelection_(),
105  meshes_(),
106  surfaces_(nullptr),
107  writers_()
108 {
109  outputPath_.clean(); // Remove unneeded ".."
111  read(dict);
112 }
113 
114 
115 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
116 
117 bool Foam::areaWrite::verbose(const bool on) noexcept
118 {
119  bool old(verbose_);
120  verbose_ = on;
121  return old;
122 }
123 
124 
126 {
128 
129  writers_.clear();
130  selectAreas_.clear();
131  fieldSelection_.clear();
132 
133  surfaces_.reset
134  (
135  new objectRegistry
136  (
137  IOobject
138  (
139  "::areaWrite::",
140  obr_.time().constant(),
141  obr_,
145  )
146  )
147  );
148 
149  verbose_ = dict.getOrDefault("verbose", false);
150 
151  // All possible area meshes for the given fvMesh region
152  meshes_ = obr().lookupClass<faMesh>();
153 
154  dict.readIfPresent("areas", selectAreas_);
155 
156  if (selectAreas_.empty())
157  {
158  word areaName;
159  if (!dict.readIfPresent("area", areaName))
160  {
161  wordList available = obr().sortedNames<faMesh>();
162 
163  if (available.size())
164  {
165  areaName = available.first();
166  }
167  }
168 
169  if (!areaName.empty())
170  {
171  selectAreas_.resize(1);
172  selectAreas_.first() = areaName;
173  }
174  }
175 
176  // Restrict to specified meshes
177  meshes_.filterKeys(selectAreas_);
178 
179  dict.readEntry("fields", fieldSelection_);
180  fieldSelection_.uniq();
181 
182 
183  // Surface writer type and format options
184  const word writerType = dict.get<word>("surfaceFormat");
185 
186  const dictionary writerOptions
187  (
189  );
190 
191  for (const word& areaName : meshes_.keys())
192  {
193  // Define surface writer, but do NOT yet attach a surface
194 
195  auto surfWriter = surfaceWriter::New(writerType, writerOptions);
196 
197  // Use outputDir/TIME/surface-name
198  surfWriter->useTimeDir(true);
199  surfWriter->verbose(verbose_);
200 
201  writers_.set(areaName, surfWriter);
202  }
203 
204  // Ensure all surfaces and merge information are expired
205  expire();
206 
207  return true;
208 }
209 
212 {
213  return true;
214 }
215 
216 
218 {
219  // Just needed for warnings
220  wordList allFields;
221  HashTable<wordHashSet> selected;
222  DynamicList<label> missed(fieldSelection_.size());
223 
224 
225  for (const word& areaName : meshes_.sortedToc())
226  {
227  const faMesh& areaMesh = *meshes_[areaName];
228 
229  polySurface* surfptr = surfaces_->getObjectPtr<polySurface>(areaName);
230 
231  if (!surfptr)
232  {
233  // Construct null and add to registry (owned by registry)
234  surfptr = new polySurface(areaName, *surfaces_, true);
235  }
236 
237  pointField pts(areaMesh.patch().localPoints());
238  faceList fcs(areaMesh.patch().localFaces());
239 
240  // Copy in geometry
241  surfptr->transfer(std::move(pts), std::move(fcs));
242 
243  surfaceWriter& outWriter = *writers_[areaName];
244 
245  if (outWriter.needsUpdate())
246  {
247  outWriter.setSurface(*surfptr);
248  }
249 
250 
251  // Determine the per-surface number of fields
252  // Only seems to be needed for VTK legacy
253 
254  selected.clear();
255 
256  IOobjectList objects(0);
257 
258  if (loadFromFiles_)
259  {
260  // Check files for a particular time
261  objects = IOobjectList(areaMesh.thisDb(), obr_.time().timeName());
262 
263  allFields = objects.names();
264  selected = objects.classes(fieldSelection_);
265  }
266  else
267  {
268  // Check currently available fields
269  allFields = areaMesh.thisDb().names();
270  selected = areaMesh.thisDb().classes(fieldSelection_);
271  }
272 
273  // Parallel consistency (no-op in serial)
274  Pstream::mapCombineReduce(selected, HashSetOps::plusEqOp<word>());
275 
276  missed.clear();
277 
278  // Detect missing fields
279  forAll(fieldSelection_, i)
280  {
281  if (!ListOps::found(allFields, fieldSelection_[i]))
282  {
283  missed.append(i);
284  }
285  }
286 
287  if (missed.size())
288  {
290  << nl
291  << "Cannot find "
292  << (loadFromFiles_ ? "field file" : "registered field")
293  << " matching "
294  << UIndirectList<wordRe>(fieldSelection_, missed) << endl;
295  }
296 
297 
298  // Currently only support area field types
299  label nAreaFields = 0;
300 
301  forAllConstIters(selected, iter)
302  {
303  const word& clsName = iter.key();
304  const label n = iter.val().size();
305 
306  if
307  (
308  fieldTypes::area.found(clsName)
309  || fieldTypes::area_internal.found(clsName)
310  )
311  {
312  nAreaFields += n;
313  }
314  }
315 
316 
317  // Propagate field counts (per surface)
318  outWriter.nFields(nAreaFields);
319 
320 
321  // Begin writing
322 
323  outWriter.open(outputPath_/areaName);
324 
325  outWriter.beginTime(obr_.time());
326 
327  // Write fields
328 
329  {
330  // Area fields
331  #undef doLocalCode
332  #define doLocalCode(Type) \
333  performAction \
334  < \
335  GeometricField<Type, Foam::faPatchField, Foam::areaMesh> \
336  > \
337  ( \
338  outWriter, areaMesh, objects \
339  ); \
340 
341  doLocalCode(scalar);
346 
347  // Area internal fields
348  #undef doLocalCode
349  #define doLocalCode(Type) \
350  performAction \
351  < \
352  DimensionedField<Type, Foam::areaMesh> \
353  > \
354  ( \
355  outWriter, areaMesh, objects \
356  );
357 
358  doLocalCode(scalar);
363 
364  #undef doLocalCode
365  }
366 
367  // Finish this time step
368 
369  // Write geometry if no fields were written so that we still
370  // can have something to look at
371 
372  if (!outWriter.wroteData())
373  {
374  outWriter.write();
375  }
376 
377  outWriter.endTime();
378  }
379 
380  return true;
381 }
382 
383 
384 void Foam::areaWrite::expire()
385 {
386  surfaces_->clear();
387 
388  // Dimension as fraction of mesh bounding box
389  const scalar mergeDim = mergeTol_ * mesh_.bounds().mag();
390 
391  forAllIters(writers_, iter)
392  {
393  surfaceWriter& writer = *(iter.val());
394  writer.expire();
395  writer.mergeDim(mergeDim);
396  }
397 }
398 
399 
400 void Foam::areaWrite::updateMesh(const mapPolyMesh& mpm)
401 {
402  if (&mpm.mesh() == &mesh_)
403  {
404  expire();
405  }
406 }
407 
408 
409 void Foam::areaWrite::movePoints(const polyMesh& mesh)
410 {
411  if (&mesh == &mesh_)
412  {
413  expire();
414  }
415 }
416 
417 
419 {
420  if (state != polyMesh::UNCHANGED)
421  {
422  expire();
423  }
424 }
425 
427 Foam::scalar Foam::areaWrite::mergeTol() noexcept
428 {
429  return mergeTol_;
430 }
431 
432 
433 Foam::scalar Foam::areaWrite::mergeTol(const scalar tol) noexcept
434 {
435  scalar old(mergeTol_);
436  mergeTol_ = tol;
437  return old;
438 }
439 
440 
441 // ************************************************************************* //
A surface mesh consisting of general polygon faces and capable of holding fields. ...
Definition: polySurface.H:62
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:88
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
virtual void readUpdate(const polyMesh::readUpdateState state)
Update for changes of mesh due to readUpdate - expires the surfaces.
Definition: areaWrite.C:411
const Field< point_type > & localPoints() const
Return pointField of points in patch.
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition: ListOps.H:821
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
List< face > faceList
A List of faces.
Definition: faceListFwd.H:41
wordList names() const
The unsorted names of all objects.
T & first()
Access first element of the list, position [0].
Definition: UList.H:798
engineTime & runTime
Tensor< scalar > tensor
Definition: symmTensor.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
Ignore writing from objectRegistry::writeObject()
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
Abstract base-class for Time/database function objects.
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
Definition: surfaceWriter.C:57
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
virtual const objectRegistry & thisDb() const
Return reference to the mesh database.
Definition: faMesh.C:708
Macros for easy insertion into run-time selection tables.
virtual void updateMesh(const mapPolyMesh &mpm)
Update for changes of mesh - expires the surfaces.
Definition: areaWrite.C:393
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
const uindirectPrimitivePatch & patch() const
Return constant reference to primitive patch.
Definition: faMeshI.H:121
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
static scalar mergeTol() noexcept
Get merge tolerance.
Definition: areaWrite.C:420
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const wordList area
Standard area field types (scalar, vector, tensor, etc)
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition: symmTensor.H:55
A class for handling words, derived from Foam::string.
Definition: word.H:63
Type * getObjectPtr(const word &name, const bool recursive=false) const
Return non-const pointer to the object of the given Type, using a const-cast to have it behave like a...
const Time & time() const noexcept
Return time registry.
virtual bool write()
Sample and write.
Definition: areaWrite.C:210
void clear()
Clear all entries from table.
Definition: HashTable.C:671
wordList sortedNames() const
The sorted names of all objects.
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:328
Vector< scalar > vector
Definition: vector.H:57
A HashTable similar to std::unordered_map.
Definition: HashTable.H:102
const direction noexcept
Definition: Scalar.H:258
#define doLocalCode(Type)
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
defineTypeNameAndDebug(combustionModel, 0)
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition: fileName.C:192
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
bool verbose(const bool on) noexcept
Enable/disable verbose output.
Definition: areaWrite.C:110
void transfer(pointField &&points, faceList &&faces, labelList &&zoneIds=labelList())
Transfer the contents of the argument and annul the argument.
Definition: polySurface.C:364
#define WarningInFunction
Report a warning using Foam::Warning.
const wordList area_internal
Standard dimensioned field types (scalar, vector, tensor, etc)
virtual bool read(const dictionary &dict)
Read the areaWrite dictionary.
Definition: areaWrite.C:118
Mesh data needed to do the Finite Area discretisation.
Definition: areaFaMesh.H:47
Nothing to be read.
label n
virtual void movePoints(const polyMesh &mesh)
Update for mesh point-motion - expires the surfaces.
Definition: areaWrite.C:402
Base class for surface writers.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
readUpdateState
Enumeration defining the state of the mesh after a read update.
Definition: polyMesh.H:89
Registry of regIOobjects.
static void mapCombineReduce(Container &values, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine map values from different processo...
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
HashTable< const Type * > lookupClass(const bool strict=false) const
Return all objects with a class satisfying isA<Type>
bool found
virtual bool execute()
Execute, currently does nothing.
Definition: areaWrite.C:204
Do not request registration (bool: false)
static autoPtr< surfaceWriter > New(const word &writeType)
Return a reference to the selected surfaceWriter.
Definition: surfaceWriter.C:80
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
const pointField & pts
HashTable< wordHashSet > classes() const
A summary hash of classes used and their associated object names.