Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
10License
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"
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
35namespace Foam
36{
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)
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),
124 fieldLevel_(),
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
162 close();
163}
164
165
166// * * * * * * * * * * * * * * * * * Controls * * * * * * * * * * * * * * * //
169{
170 currTime_ = inst;
171}
172
178
179
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
222{
223 outputPath_ = outputPath;
224 wroteGeom_ = false;
225}
226
227
229(
230 const coordSet& coords,
231 const fileName& outputPath
232)
234 close();
235 setCoordinates(coords);
236 open(outputPath);
237}
238
239
241(
242 const UPtrList<coordSet>& tracks,
243 const fileName& outputPath
244)
246 close();
247 setTracks(tracks);
248 open(outputPath);
249}
250
251
252void 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)
266 coords_.clear();
267 trackTimes_.clear();
268 }
269}
270
271
273{
274 close();
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
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
323void 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
336Foam::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
350Foam::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}
389
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
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 }
481 return changed;
482}
483
484
485// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
486
487Foam::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// ************************************************************************* //
@ LAZY_READ
Reading is optional [identical to READ_IF_PRESENT].
A helper class for outputting values to Ostream.
Definition InfoProxy.H:49
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
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
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition UPtrList.H:101
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
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.
coordSystem::cartesian geometryTransform_
Local coordinate system transformation.
virtual void open(const fileName &outputPath)
Write separate geometry to file.
fileName getExpectedPath(const word &fileExt=word::null) const
Get expected (characteristic) output file name - information only.
virtual void endTime()
End a time-step.
scalar geometryScale_
Output geometry scaling after rotate/translate.
bool useTimeDir_
Insert additional time sub-directory in the output path.
coordSetWriter()
Default construct.
label nDataColumns() const
The number of buffer data columns, after splitting into components.
bool wroteGeom_
Track if geometry has been written since the last open.
bool useTimeDir() const noexcept
Should a time directory be spliced into the output path?
bool buffering_
Writer with buffering output.
const word & timeName() const
The current time value/name.
void checkOpen() const
Verify that the outputPath_ has been set or FatalError.
void unsetTime()
Clear the current time.
virtual void beginTime(const Time &t)
Begin a time-step.
bool hasCoords() const
Writer is associated with content.
label nFields_
The number of fields.
coordSetWriter(const coordSetWriter &)=delete
No copy construct.
bool empty() const
Writer is not associated with content.
bool upToDate_
The content is up-to-date?
virtual bool writeBuffered()
Write buffered data.
label numPoints() const
The number of associated points (local processor).
dictionary fieldLevel_
Field level to remove (on output).
bool is_open() const noexcept
Test if outputPath has been set.
void setTime(const instant &inst)
Set the current time.
bool useTracks_
Prefer tracks to points during single set writing.
virtual bool merge() const
Perform any merging if not already upToDate (parallel) or simply mark as being up-to-date.
bool verbose_
Additional output verbosity.
void clearBuffers()
Clear out buffering.
dictionary fieldScale_
Field scaling (on output).
virtual bool expire()
Mark that content changed and the writer will need an update, and set nFields = 0.
UPtrList< const coordSet > coords_
Reference to coordinate set(s).
virtual bool needsUpdate() const
Does the writer need an update (eg, lagging behind other changes).
static word suffix(const word &fldName, const word &fileExt=word::null)
Name suffix based on fieldName (underscore separator).
instant currTime_
The current time value/name.
List< scalarField > trackTimes_
Track times (eg, streamlines), one per coords_ entry.
virtual void clear()
Close any open output, remove coordSet associations and expire the writer.
virtual void setCoordinates(const coordSet *coords)
Set coordinates, can also be nullptr.
fileName getFieldPrefixedPath(const word &fieldName, const word &fileExt=word::null) const
Get field-prefixed output file name.
point geometryCentre_
The centre of rotation (untranslate, translate).
scalar timeValue() const
The current time value/name.
virtual bool wroteData() const
Geometry or fields written since the last open?
virtual void setTrackTimes(const UList< scalarField > &times)
Set track times.
virtual void setTracks(const UPtrList< coordSet > &tracks)
Set track coordinates.
virtual void close(bool force=false)
Finish output, performing any necessary cleanup.
virtual ~coordSetWriter()
Destructor. Calls close().
fileName outputPath_
The full output directory and file (coords) name.
label numTracks() const
The number of coordinate tracks.
static dictionary formatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Same as fileFormats::getFormatOptions.
Holds list of sampling positions.
Definition coordSet.H:52
A Cartesian coordinate system.
Definition cartesianCS.H:68
virtual void clear()
Reset origin and rotation to an identity coordinateSystem.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
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
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
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...
const Type & value() const noexcept
Return const reference to value.
A class for handling file names.
Definition fileName.H:75
word ext() const
Return file name extension (part after last .).
Definition fileNameI.H:211
static std::string path(const std::string &str)
Return directory path name (part before last /).
Definition fileNameI.H:169
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name.
Definition instant.H:56
@ LITERAL
String literal.
Definition keyType.H:82
A class for handling words, derived from Foam::string.
Definition word.H:66
word ext() const
Return file name extension (part after last .).
Definition wordI.H:171
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
word timeName
Definition getTimeIndex.H:3
dictionary getFormatOptions(const dictionary &dict, const word &formatName, const word &entryName="formatOptions")
Find "formatOptions" in a top-level dictionary. Extract and merge 'default' + formatName values.
Definition fileFormats.C:80
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
messageStream Info
Information stream (stdout output on master, null elsewhere).
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition POSIX.C:801
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299