coordSetWriter.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) 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 "coordSet.H"
29 #include "coordSetWriter.H"
30 #include "fileFormats.H"
31 #include "Time.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
37  defineTypeNameAndDebug(coordSetWriter, 0);
38  defineRunTimeSelectionTable(coordSetWriter, word);
40 }
41 
42 
43 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
44 
46 (
47  const word& fldName,
48  const word& fileExt
49 )
50 {
51  word result;
52 
53  if (!fldName.empty())
54  {
55  result += '_' + fldName;
56  }
57 
58  return result.ext(fileExt);
59 }
60 
61 
63 (
64  const wordList& fieldNames,
65  const word& fileExt
66 )
67 {
68  word result;
69 
70  for (const word& fldName : fieldNames)
71  {
72  if (!fldName.empty())
73  {
74  result += '_' + fldName;
75  }
76  }
77 
78  return result.ext(fileExt);
79 }
80 
81 
83 (
84  const dictionary& dict,
85  const word& formatName,
86  const word& entryName
87 )
88 {
89  return fileFormats::getFormatOptions(dict, formatName, entryName);
90 }
91 
92 
94 (
95  const dictionary& dict,
96  const dictionary& setDict,
97  const word& formatName,
98  const word& entryName
99 )
100 {
101  return fileFormats::getFormatOptions(dict, setDict, formatName, entryName);
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 
108 :
109  coords_(),
110  trackTimes_(),
111  upToDate_(false),
112  wroteGeom_(false),
114  buffering_(false),
115  useTracks_(false),
116  useTimeDir_(false),
117  verbose_(false),
118  nFields_(0),
119  currTime_(),
120  outputPath_(),
121  geometryScale_(1),
122  geometryCentre_(Zero),
123  geometryTransform_(),
124  fieldLevel_(),
125  fieldScale_()
126 {}
127 
128 
130 :
132 {
133  options.readIfPresent("verbose", verbose_);
134 
135  geometryScale_ = 1;
138 
139  options.readIfPresent("scale", geometryScale_);
140 
141  // Optional cartesian coordinate system transform
142  const auto* dictptr = options.findDict("transform", keyType::LITERAL);
143 
144  if (dictptr)
145  {
146  dictptr->readIfPresent("rotationCentre", geometryCentre_);
147 
148  // 'origin' is optional within sub-dictionary
151  }
152 
153  fieldLevel_ = options.subOrEmptyDict("fieldLevel");
154  fieldScale_ = options.subOrEmptyDict("fieldScale");
155 }
156 
157 
158 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
159 
161 {
162  close();
163 }
164 
165 
166 // * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
168 void Foam::coordSetWriter::setTime(const instant& inst)
169 {
170  currTime_ = inst;
171 }
172 
174 void Foam::coordSetWriter::setTime(scalar timeValue)
175 {
176  currTime_ = instant(timeValue);
177 }
178 
179 
180 void Foam::coordSetWriter::setTime(scalar timeValue, const word& timeName)
181 {
182  currTime_.value() = timeValue;
183  currTime_.name() = timeName;
184 }
185 
186 
188 {
189  currTime_.value() = 0;
190  currTime_.name().clear();
191 }
192 
195 {
196  setTime(t.value(), t.timeName());
197 }
198 
201 {
202  setTime(inst);
203 }
204 
205 
207 {
208  // Flush bufferred data
209  if (nDataColumns())
210  {
211  writeBuffered();
212  }
213  clearBuffers();
215  unsetTime();
216 }
217 
218 
219 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
220 
221 void Foam::coordSetWriter::open(const fileName& outputPath)
222 {
223  outputPath_ = outputPath;
224  wroteGeom_ = false;
225 }
226 
227 
229 (
230  const coordSet& coords,
231  const fileName& outputPath
232 )
233 {
234  close();
235  setCoordinates(coords);
236  open(outputPath);
237 }
238 
239 
241 (
242  const UPtrList<coordSet>& tracks,
243  const fileName& outputPath
244 )
245 {
246  close();
247  setTracks(tracks);
248  open(outputPath);
249 }
250 
251 
252 void Foam::coordSetWriter::close(bool force)
253 {
254  if (nDataColumns())
255  {
256  if (verbose_) Info<< "Flush buffered data:" << nl;
257  writeBuffered();
258  }
259  clearBuffers();
260 
261  outputPath_.clear();
262  wroteGeom_ = false;
263 
264  if (force)
265  {
266  coords_.clear();
267  trackTimes_.clear();
268  }
269 }
270 
271 
273 {
274  close();
275  expire();
276  coords_.clear();
277  trackTimes_.clear();
278  clearBuffers(); // Reset any buffering
279 }
280 
281 
283 {
284  expire();
285  clearBuffers(); // Reset any buffering
286 
287  if (coords)
288  {
289  coords_.resize(1);
290  coords_.set(0, coords);
291  }
292  else
293  {
294  coords_.clear();
295  }
296  trackTimes_.clear();
297 }
298 
301 {
302  setCoordinates(&coords);
303 }
304 
305 
307 {
308  expire();
309  clearBuffers(); // Reset any buffering
310 
311  // Shallow copy (pointers)
312 
313  coords_.resize(tracks.size());
314  forAll(coords_, tracki)
315  {
316  coords_.set(tracki, tracks.get(tracki));
317  }
318  trackTimes_.clear();
319  useTracks_ = true;
320 }
321 
322 
323 void Foam::coordSetWriter::setTrackTimes(const UList<scalarField>& times)
324 {
325  if (times.size() == coords_.size())
326  {
327  trackTimes_ = times;
328  }
329  else
330  {
331  trackTimes_.clear();
332  }
333 }
334 
335 
336 Foam::label Foam::coordSetWriter::numPoints() const
337 {
338  label nTotal = 0;
339 
340  forAll(coords_, tracki)
341  {
342  const auto* ptr = coords_.get(tracki);
343  if (ptr) nTotal += ptr->size();
344  }
345 
346  return nTotal;
347 }
348 
350 Foam::label Foam::coordSetWriter::numTracks() const
351 {
352  return coords_.size();
353 }
354 
357 {
358  return !upToDate_;
359 }
360 
363 {
364  return wroteGeom_;
365 }
366 
367 
369 {
370  const bool changed = upToDate_;
371 
372  upToDate_ = false;
373  wroteGeom_ = false;
374  coords_.clear();
375  trackTimes_.clear();
376 
377  // Field count (nFields_) is a different type of accounting
378  // and is unaffected by geometry changes
379 
380  return changed;
381 }
382 
385 {
386  return !coords_.empty();
387 }
388 
390 bool Foam::coordSetWriter::empty() const
391 {
392  return coords_.empty();
393 }
394 
396 (
397  const word& fileExt
398 ) const
399 {
400  fileName file;
401 
402  if (!outputPath_.empty())
403  {
404  if (useTimeDir() && !timeName().empty())
405  {
406  // Splice in time-directory
407  file = outputPath_.path() / timeName() / outputPath_.name();
408  }
409  else
410  {
411  file = outputPath_;
412  }
413 
414  file.ext(fileExt); // Append extension - can also be empty
415  }
416 
417  return file;
418 }
419 
420 
422 (
423  const word& fieldName,
424  const word& fileExt
425 ) const
426 {
427  if (outputPath_.empty() || fieldName.empty())
428  {
429  return getExpectedPath(fileExt);
430  }
431 
432  // Field: rootdir/<TIME>/<field>_NAME.ext
433 
434  fileName file;
435  if (useTimeDir() && !timeName().empty())
436  {
437  // Splice in time-directory
438  file = outputPath_.path() / timeName();
439  }
440  else
441  {
442  file = outputPath_.path();
443  }
444 
445  // Append <field>_NAME.EXT
446  file /= (fieldName + '_' + outputPath_.name());
447  file.ext(fileExt); // Append extension - can also be empty
448 
449  return file;
450 }
451 
452 
454 {
455  if (!is_open())
456  {
458  << type() << " : Attempted to write without a path" << nl
459  << exit(FatalError);
460  }
461 }
462 
463 
464 bool Foam::coordSetWriter::merge() const
465 {
466  bool changed = false;
467 
468  // Possible future requirement...
469  //
470  // if (parallel_ && Pstream::parRun() && !upToDate_)
471  // {
472  // changed = merged_.merge(coords_, mergeDim_);
473  // }
474  upToDate_ = true;
475 
476  if (changed)
477  {
478  wroteGeom_ = false;
479  }
480 
481  return changed;
482 }
483 
484 
485 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
486 
487 Foam::Ostream& Foam::operator<<
488 (
489  Ostream& os,
490  const InfoProxy<coordSetWriter>& iproxy
491 )
492 {
493  const auto& w = *iproxy;
494 
495  os << "coordSetWriter:"
496  << " upToDate: " << w.upToDate_
497  << " nFields: " << w.nFields_
498  << " time: " << w.currTime_
499  << " path: " << w.outputPath_ << endl;
500 
501  return os;
502 }
503 
504 
505 // ************************************************************************* //
virtual void open(const fileName &outputPath)
Write separate geometry to file.
const Type & value() const noexcept
Return const reference to value.
dictionary dict
virtual void setCoordinates(const coordSet *coords)
Set coordinates, can also be nullptr.
A class for handling file names.
Definition: fileName.H:72
virtual bool expire()
Mark that content changed and the writer will need an update, and set nFields = 0.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void checkOpen() const
Verify that the outputPath_ has been set or FatalError.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
dictionary getFormatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Find "formatOptions" in a top-level dictionary. Extract and merge &#39;default&#39; + formatName values...
Definition: fileFormats.C:80
virtual ~coordSetWriter()
Destructor. Calls close()
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
void unsetTime()
Clear the current time.
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
const T * get(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrListI.H:134
bool hasCoords() const
Writer is associated with content.
virtual void setTracks(const UPtrList< coordSet > &tracks)
Set track coordinates.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:211
virtual void clear()
Reset origin and rotation to an identity coordinateSystem.
virtual bool wroteData() const
Geometry or fields written since the last open?
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
word ext() const
Return file name extension (part after last .)
Definition: wordI.H:171
A Cartesian coordinate system.
Definition: cartesianCS.H:65
static word suffix(const word &fldName, const word &fileExt=word::null)
Name suffix based on fieldName (underscore separator)
virtual void beginTime(const Time &t)
Begin a time-step.
word timeName
Definition: getTimeIndex.H:3
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
Holds list of sampling positions.
Definition: coordSet.H:49
A class for handling words, derived from Foam::string.
Definition: word.H:63
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
Base class for writing coordSet(s) and tracks with fields.
dictionary fieldScale_
Field scaling (on output)
String literal.
Definition: keyType.H:82
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
bool empty() const
Writer is not associated with content.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:106
coordSetWriter()
Default construct.
dictionary fieldLevel_
Field level to remove (on output)
void setTime(const instant &inst)
Set the current time.
scalar geometryScale_
Output geometry scaling after rotate/translate.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
label numTracks() const
The number of coordinate tracks.
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
virtual void clear()
Close any open output, remove coordSet associations and expire the writer.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
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...
OBJstream os(runTime.globalPath()/outputName)
fileName getFieldPrefixedPath(const word &fieldName, const word &fileExt=word::null) const
Get field-prefixed output file name.
defineTypeNameAndDebug(combustionModel, 0)
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Find and return a sub-dictionary as a copy, otherwise return an empty dictionary. ...
Definition: dictionary.C:521
virtual void endTime()
End a time-step.
coordSystem::cartesian geometryTransform_
Local coordinate system transformation.
List< word > wordList
List of word.
Definition: fileName.H:59
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
bool verbose_
Additional output verbosity.
virtual bool needsUpdate() const
Does the writer need an update (eg, lagging behind other changes)
virtual void setTrackTimes(const UList< scalarField > &times)
Set track times.
point geometryCentre_
The centre of rotation (untranslate, translate)
label numPoints() const
The number of associated points (local processor)
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool merge() const
Perform any merging if not already upToDate (parallel) or simply mark as being up-to-date.
Reading is optional [identical to READ_IF_PRESENT].
fileName getExpectedPath(const word &fileExt=word::null) const
Get expected (characteristic) output file name - information only.
virtual void close(bool force=false)
Finish output, performing any necessary cleanup.
Namespace for OpenFOAM.
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
Definition: dictionaryI.H:124
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127