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 {}
122 
123 
125 :
127 {
128  options.readIfPresent("verbose", verbose_);
129 }
130 
131 
132 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
133 
135 {
136  close();
137 }
138 
139 
140 // * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
142 void Foam::coordSetWriter::setTime(const instant& inst)
143 {
144  currTime_ = inst;
145 }
146 
148 void Foam::coordSetWriter::setTime(scalar timeValue)
149 {
150  currTime_ = instant(timeValue);
151 }
152 
153 
154 void Foam::coordSetWriter::setTime(scalar timeValue, const word& timeName)
155 {
156  currTime_.value() = timeValue;
157  currTime_.name() = timeName;
158 }
159 
160 
162 {
163  currTime_.value() = 0;
164  currTime_.name().clear();
165 }
166 
169 {
170  setTime(t.value(), t.timeName());
171 }
172 
175 {
176  setTime(inst);
177 }
178 
179 
181 {
182  // Flush bufferred data
183  if (nDataColumns())
184  {
185  writeBuffered();
186  }
187  clearBuffers();
189  unsetTime();
190 }
191 
192 
193 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
194 
195 void Foam::coordSetWriter::open(const fileName& outputPath)
196 {
197  outputPath_ = outputPath;
198  wroteGeom_ = false;
199 }
200 
201 
203 (
204  const coordSet& coords,
205  const fileName& outputPath
206 )
207 {
208  close();
209  setCoordinates(coords);
210  open(outputPath);
211 }
212 
213 
215 (
216  const UPtrList<coordSet>& tracks,
217  const fileName& outputPath
218 )
219 {
220  close();
221  setTracks(tracks);
222  open(outputPath);
223 }
224 
225 
226 void Foam::coordSetWriter::close(bool force)
227 {
228  if (nDataColumns())
229  {
230  if (verbose_) Info<< "Flush buffered data:" << nl;
231  writeBuffered();
232  }
233  clearBuffers();
234 
235  outputPath_.clear();
236  wroteGeom_ = false;
237 
238  if (force)
239  {
240  coords_.clear();
241  trackTimes_.clear();
242  }
243 }
244 
245 
247 {
248  close();
249  expire();
250  coords_.clear();
251  trackTimes_.clear();
252  clearBuffers(); // Reset any buffering
253 }
254 
255 
257 {
258  expire();
259  clearBuffers(); // Reset any buffering
260 
261  if (coords)
262  {
263  coords_.resize(1);
264  coords_.set(0, coords);
265  }
266  else
267  {
268  coords_.clear();
269  }
270  trackTimes_.clear();
271 }
272 
275 {
276  setCoordinates(&coords);
277 }
278 
279 
281 {
282  expire();
283  clearBuffers(); // Reset any buffering
284 
285  // Shallow copy (pointers)
286 
287  coords_.resize(tracks.size());
288  forAll(coords_, tracki)
289  {
290  coords_.set(tracki, tracks.get(tracki));
291  }
292  trackTimes_.clear();
293  useTracks_ = true;
294 }
295 
296 
297 void Foam::coordSetWriter::setTrackTimes(const UList<scalarField>& times)
298 {
299  if (times.size() == coords_.size())
300  {
301  trackTimes_ = times;
302  }
303  else
304  {
305  trackTimes_.clear();
306  }
307 }
308 
309 
310 Foam::label Foam::coordSetWriter::numPoints() const
311 {
312  label nTotal = 0;
313 
314  forAll(coords_, tracki)
315  {
316  const auto* ptr = coords_.get(tracki);
317  if (ptr) nTotal += ptr->size();
318  }
319 
320  return nTotal;
321 }
322 
324 Foam::label Foam::coordSetWriter::numTracks() const
325 {
326  return coords_.size();
327 }
328 
331 {
332  return !upToDate_;
333 }
334 
337 {
338  return wroteGeom_;
339 }
340 
341 
343 {
344  const bool changed = upToDate_;
345 
346  upToDate_ = false;
347  wroteGeom_ = false;
348  coords_.clear();
349  trackTimes_.clear();
350 
351  // Field count (nFields_) is a different type of accounting
352  // and is unaffected by geometry changes
353 
354  return changed;
355 }
356 
359 {
360  return !coords_.empty();
361 }
362 
364 bool Foam::coordSetWriter::empty() const
365 {
366  return coords_.empty();
367 }
368 
370 (
371  const word& fileExt
372 ) const
373 {
374  fileName file;
375 
376  if (!outputPath_.empty())
377  {
378  if (useTimeDir() && !timeName().empty())
379  {
380  // Splice in time-directory
381  file = outputPath_.path() / timeName() / outputPath_.name();
382  }
383  else
384  {
385  file = outputPath_;
386  }
387 
388  file.ext(fileExt); // Append extension - can also be empty
389  }
390 
391  return file;
392 }
393 
394 
396 (
397  const word& fieldName,
398  const word& fileExt
399 ) const
400 {
401  if (outputPath_.empty() || fieldName.empty())
402  {
403  return getExpectedPath(fileExt);
404  }
405 
406  // Field: rootdir/<TIME>/<field>_NAME.ext
407 
408  fileName file;
409  if (useTimeDir() && !timeName().empty())
410  {
411  // Splice in time-directory
412  file = outputPath_.path() / timeName();
413  }
414  else
415  {
416  file = outputPath_.path();
417  }
418 
419  // Append <field>_NAME.EXT
420  file /= (fieldName + '_' + outputPath_.name());
421  file.ext(fileExt); // Append extension - can also be empty
422 
423  return file;
424 }
425 
426 
428 {
429  if (!is_open())
430  {
432  << type() << " : Attempted to write without a path" << nl
433  << exit(FatalError);
434  }
435 }
436 
437 
438 bool Foam::coordSetWriter::merge() const
439 {
440  bool changed = false;
441 
442  // Possible future requirement...
443  //
444  // if (parallel_ && Pstream::parRun() && !upToDate_)
445  // {
446  // changed = merged_.merge(coords_, mergeDim_);
447  // }
448  upToDate_ = true;
449 
450  if (changed)
451  {
452  wroteGeom_ = false;
453  }
454 
455  return changed;
456 }
457 
458 
459 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
460 
461 Foam::Ostream& Foam::operator<<
462 (
463  Ostream& os,
464  const InfoProxy<coordSetWriter>& ip
465 )
466 {
467  const coordSetWriter& w = ip.t_;
468 
469  os << "coordSetWriter:"
470  << " upToDate: " << w.upToDate_
471  << " nFields: " << w.nFields_
472  << " time: " << w.currTime_
473  << " path: " << w.outputPath_ << endl;
474 
475  return os;
476 }
477 
478 
479 // ************************************************************************* //
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:71
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:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
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:120
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 bool wroteData() const
Geometry or fields written since the last open?
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
word ext() const
Return file name extension (part after last .)
Definition: wordI.H:171
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:752
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 elements in the list.
Definition: UPtrListI.H:99
Base class for writing coordSet(s) and tracks with fields.
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:100
coordSetWriter()
Default construct.
void setTime(const instant &inst)
Set the current time.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
label numTracks() const
The number of coordinate tracks.
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
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)
virtual void endTime()
End a time-step.
List< word > wordList
A List of words.
Definition: fileName.H:58
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
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.
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.
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.