Loading...
Searching...
No Matches
ensightFile.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) 2011-2015 OpenFOAM Foundation
9 Copyright (C) 2016-2024 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "ensightFile.H"
30#include "ensightReadFile.H"
31#include "error.H"
32#include "List.H"
33#include <cstring>
34#include <sstream>
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38bool Foam::ensightFile::allowUndef_ = false;
39
40float Foam::ensightFile::undefValue_ = Foam::floatScalarVGREAT;
41
42const char* const Foam::ensightFile::coordinates = "coordinates";
43
44
45// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
46
47namespace Foam
48{
49
50// Put integers, floats etc in binary or ascii.
51template<class Type>
52static inline void putPrimitive
53(
54 const Type& value,
55 OFstream& os,
56 const int fieldWidth
57)
58{
59 auto& oss = os.stdStream();
60
61 if (os.format() == IOstreamOption::BINARY)
62 {
63 oss.write(reinterpret_cast<const char*>(&value), sizeof(Type));
64 }
65 else
66 {
67 oss.width(fieldWidth);
68 oss << value;
69 }
70 os.syncState();
72
73} // End namespace Foam
74
75
76// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
77
78bool Foam::ensightFile::hasUndef(const UList<float>& field)
79{
80 for (const float val : field)
81 {
82 if (std::isnan(val))
83 {
84 return true;
85 }
86 }
87
88 return true;
89}
90
91
93{
94 for (const double val : field)
95 {
96 if (std::isnan(val))
97 {
98 return true;
99 }
100 }
101
102 return true;
103}
104
105
106// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
107
108void Foam::ensightFile::init()
109{
110 // The ASCII formatting specs for ensight files
111 setf
112 (
113 std::ios_base::scientific,
114 std::ios_base::floatfield
115 );
116 precision(5);
117
118 // Handle transient single-file timestep information
119 auto& oss = OFstream::stdStream();
120
122 {
123 // Already positioned at the EOF (in append mode), but be certain
124 oss.seekp(0, std::ios_base::end);
125 origFileSize_ = oss.tellp();
126 }
127 else
128 {
129 origFileSize_ = 0;
130 }
131
132 int64_t begin_footer(-1);
133 List<int64_t> offsets;
134
136 {
137 // Temporarily open for reading as well.
138 // No race condition since no writing is done concurrently with the
139 // reading
141
142 begin_footer =
144 (
145 is,
146 offsets
147 );
148 }
149
150 timeStepOffsets_ = std::move(offsets);
151
152 if (OFstream::is_appending() && begin_footer > 0)
153 {
154 oss.seekp(begin_footer);
156 }
157
158 // InfoErr << "output at: " << label(begin_footer) << nl;
159 // InfoErr
160 // << "footer: " << label(begin_footer)
161 // << " time-steps: " << offsets.size() << nl;
162}
163
164
165// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
166
167Foam::ensightFile::ensightFile
168(
169 std::nullptr_t, // dispatch tag
171 const fileName& pathname,
173)
174:
176 (
177 (
178 // Only use atomic when not appending
179 (append == IOstreamOption::NO_APPEND)
180 ? IOstreamOption::ATOMIC
181 : IOstreamOption::NON_ATOMIC
182 ),
183 pathname,
184 fmt,
185 (
186 // Change APPEND_APP -> APPEND_ATE (file rewriting)
187 (append == IOstreamOption::APPEND_APP)
188 ? IOstreamOption::APPEND_ATE
189 : append
190 )
191 ),
192 origFileSize_(0)
193{
194 init();
195}
196
197
198Foam::ensightFile::ensightFile
199(
201 const fileName& pathname,
203)
204:
206 (
207 nullptr,
209 ensight::FileName(pathname),
210 fmt
211 )
212{}
213
214
215Foam::ensightFile::ensightFile
216(
218 const fileName& path,
219 const fileName& name,
221)
222:
224 (
225 nullptr,
226 append,
227 path/ensight::FileName(name),
228 fmt
229 )
230{}
231
232
233// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
234
237 (void) writeTimeStepFooter();
238}
239
240
241// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
242
244{
245 return allowUndef_;
246}
247
249// float Foam::ensightFile::undefValue() noexcept
250// {
251// return undefValue_;
252// }
253
254
255bool Foam::ensightFile::allowUndef(bool on) noexcept
257 bool old = allowUndef_;
258 allowUndef_ = on;
259 return old;
260}
261
262
263float Foam::ensightFile::undefValue(float value) noexcept
264{
265 // enable its use too
266 allowUndef_ = true;
267
268 float old = undefValue_;
269 undefValue_ = value;
270 return old;
271}
272
273
274// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
275
276void Foam::ensightFile::writeString(const char* str, size_t len)
277{
278 // Output 79 chars (ASCII) or 80 chars (BINARY)
279 char buf[80];
280 if (len > 80) len = 80;
281
282 // TBD: truncate at newline? (shouldn't really occur anyhow)
283
284 std::copy_n(str, len, buf);
285 std::fill_n(buf + len, (80 - len), '\0'); // Pad trailing with nul
286
287 auto& oss = stdStream();
288
290 {
291 oss.write(buf, 80);
292 }
293 else
294 {
295 buf[79] = 0; // Max 79 in ASCII
296
297 // TBD: Extra safety - trap newline in ASCII?
298 // char* p = ::strchr(buf, '\n');
299 // if (p) *p = 0;
300
301 oss << buf;
302 }
303
304 syncState();
305}
306
308void Foam::ensightFile::writeString(const char* str)
309{
310 writeString(str, strlen(str));
311}
312
314void Foam::ensightFile::writeString(const std::string& str)
315{
316 writeString(str.data(), str.size());
317}
318
319
321{
322 writeString(str, strlen(str));
323 return *this;
324}
325
326
328{
329 writeString(str.data(), str.size());
330 return *this;
331}
332
333
334Foam::Ostream& Foam::ensightFile::write(const std::string& str)
336 writeString(str.data(), str.size());
337 return *this;
338}
339
340
341// Same as OFstream::writeRaw(buf, count)
343(
344 const char* buf,
345 std::streamsize count
346)
348 stdStream().write(buf, count);
349 syncState();
350 return *this;
351}
352
354void Foam::ensightFile::writeInt(const int32_t val, const int fieldWidth)
355{
356 putPrimitive<int32_t>(val, *this, fieldWidth);
357}
358
360void Foam::ensightFile::writeInt(const int64_t val, const int fieldWidth)
361{
362 putPrimitive<int32_t>(narrowInt32(val), *this, fieldWidth);
363}
364
366void Foam::ensightFile::writeFloat(const float val, const int fieldWidth)
367{
368 putPrimitive<float>(val, *this, fieldWidth);
369}
370
372void Foam::ensightFile::writeFloat(const double val, const int fieldWidth)
373{
374 putPrimitive<float>(narrowFloat(val), *this, fieldWidth);
375}
376
377
378Foam::Ostream& Foam::ensightFile::write(const int32_t val)
380 putPrimitive<int32_t>(val, *this, 10);
381
382 return *this;
383}
384
385
386Foam::Ostream& Foam::ensightFile::write(const int64_t val)
388 putPrimitive<int32_t>(narrowInt32(val), *this, 10);
389
390 return *this;
391}
392
393
396 putPrimitive<float>(val, *this, 12);
397
398 return *this;
399}
400
401
404 putPrimitive<float>(narrowFloat(val), *this, 12);
405
406 return *this;
407}
408
409
411{
413 {
414 OFstream::write('\n');
415 }
416}
417
420{
421 write(undefValue_);
422}
423
424
426{
427 if (allowUndef_)
428 {
429 writeString(key + " undef");
430 newline();
431 write(undefValue_);
432 newline();
433 }
434 else
435 {
436 writeString(key);
438 }
439
440 return *this;
441}
442
443
445{
447 {
448 writeString("C Binary");
449 // newline(); // A no-op in binary
450 }
451}
452
453
454// Footer information looks like this
455//
456/* |---------------|---------------|-----------------------|
457 * | ASCII | BINARY | element |
458 * |---------------|---------------|-----------------------|
459 * | "%20lld\n" | int32 | nSteps |
460 * | "%20lld\n" | int64 | offset step 1 |
461 * | "%20lld\n" | int64 | offset step 2 |
462 * | "%20lld\n" | .. | |
463 * | "%20lld\n" | int64 | offset step n |
464 * | "%20lld\n" | int32 | flag (unused) |
465 * | "%20lld\n" | int64 | offset to nSteps |
466 * | "%s\n" | char[80] | 'FILE_INDEX' |
467 * |---------------|---------------|-----------------------|
468 */
469
471{
472 if (timeStepOffsets_.empty())
473 {
474 return -1;
475 }
476
477 auto& oss = OFstream::stdStream();
478
479 // The footer begin, which is also the current position
480 const int64_t footer_begin(oss.tellp());
481
482 // nSteps
483 putPrimitive<int32_t>(int32_t(timeStepOffsets_.size()), *this, 20);
484 newline();
485
486 // offset step 1, 2, ... N
487 for (int64_t off : timeStepOffsets_)
488 {
489 putPrimitive<int64_t>(off, *this, 20);
490 newline();
491 }
492
493 // flag (unused)
494 putPrimitive<int32_t>(0, *this, 20);
495 newline();
496
497 // The footer begin == position of nSteps
498 putPrimitive<int64_t>(footer_begin, *this, 20);
499 newline();
500
501 // FILE_INDEX is "%s\n", not "%79s\n"
502 // but our ASCII strings are truncated (nul-padded) anyhow
503
504 writeString("FILE_INDEX");
505 newline();
506
507 // Reposition to begin of footer so that any subsequent output
508 // will overwrite the footer too
509 oss.seekp(footer_begin);
510
511 return footer_begin;
513
514
515//
516// Convenience Output Methods
517//
518
520{
521 writeString("BEGIN TIME STEP");
522 newline();
523
524 auto& oss = OFstream::stdStream();
525
526 const int64_t curr_pos(oss.tellp());
527 timeStepOffsets_.push_back(curr_pos);
528
529 // To avoid partly incomplete/incorrect footer information,
530 // overwrite original footer if needed.
531
532 if (curr_pos >= 0 && curr_pos < origFileSize_)
533 {
534 const char fill[] = "deadbeef";
535
536 for
537 (
538 int64_t pos = curr_pos;
539 pos < origFileSize_ && bool(oss);
540 pos += 8
541 )
542 {
543 // Overwrite with specified "junk" to avoid/detect corrupt
544 // files etc. Don't worry about slightly increasing the
545 // file size (ie, max 7 bytes) - it's unimportant
546 oss.write(fill, 8);
547 }
548
549 // Maintain the original output position
550 oss.seekp(curr_pos);
551
553 }
554
555 return curr_pos;
556}
557
558
560{
561 writeString("END TIME STEP");
562 newline();
563
564 return int64_t(stdStream().tellp());
565}
566
567
568void Foam::ensightFile::beginPart(const label index)
569{
570 writeString("part");
571 newline();
572 write(index+1); // Ensight starts with 1
573 newline();
574}
575
576
578(
579 const label index,
580 const std::string& description
581)
583 beginPart(index);
584 writeString(description);
585 newline();
586}
587
588
589void Foam::ensightFile::beginCoordinates(const label npoints)
590{
591 writeString("coordinates");
593
594 write(npoints);
595 newline();
596}
597
598
599void Foam::ensightFile::beginParticleCoordinates(const label nparticles)
600{
601 writeString("particle coordinates");
602 newline();
603 writeInt(nparticles, 8); // Warning: unusual width
604 newline();
605}
606
607
609{
610 for (const label val : list)
612 write(val);
613 newline();
614 }
615}
616
617
618void Foam::ensightFile::writeList(const UList<label>& field)
619{
620 for (const label val : field)
622 write(float(val));
623 newline();
624 }
625}
626
627
628void Foam::ensightFile::writeList(const UList<float>& field)
629{
630 for (const float val : field)
631 {
632 if (std::isnan(val))
633 {
634 writeUndef();
635 }
636 else
637 {
638 write(val);
639 }
640 newline();
641 }
642}
643
644
646{
647 for (const double val : field)
648 {
649 if (std::isnan(val))
650 {
651 writeUndef();
652 }
653 else
654 {
655 write(val);
656 }
657 newline();
658 }
659}
660
661
662// ************************************************************************* //
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
A simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
streamFormat
Data format (ascii | binary | coherent).
@ ASCII
"ascii" (normal default)
appendType
File appending (NO_APPEND | APPEND_APP | APPEND_ATE).
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition OSstream.H:134
bool is_appending() const noexcept
True if opened in append mode and file already existed.
Definition OFstream.H:191
virtual const std::ostream & stdStream() const override
Const access to underlying std::ostream.
Definition OFstream.C:125
virtual char fill() const override
Get the current padding character.
Definition OSstream.C:319
void syncState()
Set stream state to match that of the std::ostream.
Definition OSstream.H:182
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
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
A variant of OFstream with specialised handling for Ensight writing of strings, integers and floats (...
Definition ensightFile.H:50
void writeUndef()
Write undef value.
void writeString(const char *str, size_t len)
Write character/string content as "%79s" or as binary (max 80 chars).
int64_t writeTimeStepFooter()
Transient single-file: write the time-step file-offsets as footer information.
int64_t beginTimeStep()
Write "BEGIN TIME STEP" string and newline (for transient single-file format).
static bool allowUndef() noexcept
Return setting for whether 'undef' values are allowed in results.
static const char *const coordinates
The keyword "coordinates".
virtual bool write(const token &) override
Writing token does not make sense.
void writeBinaryHeader()
Write "C Binary" string for binary files (eg, geometry/measured).
void beginCoordinates(const label nparticles)
Begin a "coordinates" block. Only used for geometry files.
void beginPart(const label index)
Begin a part (0-based index internally).
int64_t endTimeStep()
Write "END TIME STEP" string and newline (for transient single-file format).
void writeList(const UList< label > &field)
Write a list of integers as float values.
void writeLabels(const UList< label > &list)
Write a list of integers.
static float undefValue(float value) noexcept
Assign the value to represent undef in the results.
void beginParticleCoordinates(const label nparticles)
Begin a "particle coordinates" block (measured data).
virtual Ostream & writeKeyword(const keyType &key) override
Write element keyword with trailing newline, optionally with undef and the value for undefined.
static bool hasUndef(const UList< float > &field)
Check for any NaN in the field.
Definition ensightFile.C:71
void writeFloat(const float val, const int fieldWidth)
Write floating-point with specified width or as binary.
void newline()
Add carriage return to ascii stream.
void writeInt(const int32_t val, const int fieldWidth)
Write integer value with specified width or as binary.
~ensightFile()
Destructor. Commits the time-step footer information (if any).
static int64_t getTimeStepFooter(IFstream &is, List< int64_t > &offsets)
Extract time step footer information (if any).
A class for handling file names.
Definition fileName.H:75
A class for handling keywords in dictionaries.
Definition keyType.H:69
A class for handling words, derived from Foam::string.
Definition word.H:66
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
rDeltaTY field()
OBJstream os(runTime.globalPath()/outputName)
rAUs append(new volScalarField(IOobject::groupName("rAU", phase1.name()), 1.0/(U1Eqn.A()+byDt(max(phase1.residualAlpha() - alpha1, scalar(0)) *rho1))))
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
constexpr floatScalar floatScalarVGREAT
Definition floatScalar.H:56
Smanip< std::ios_base::fmtflags > setf(std::ios_base::fmtflags flags)
Definition IOmanip.H:169
static void putPrimitive(const Type &value, OFstream &os, const int fieldWidth)
Definition ensightFile.C:46
constexpr int32_t narrowInt32(const int64_t val) noexcept
Type narrowing from int64_t to int32_t.
Definition label.H:248
const direction noexcept
Definition scalarImpl.H:265
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
constexpr float narrowFloat(const double val) noexcept
Type narrowing from double to float.
Definition scalar.H:278
runTime write()
word format(conversionProperties.get< word >("format"))