From dafae668d121247a6415ff9f421198a07008cf68 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 17 Oct 2023 15:00:29 +0200 Subject: [PATCH] ENH: support user specification of ensight time format/precision (#2999) - new format option keywords: timeFormat, timePrecision CONFIG: default ensight output is now consistently BINARY - this removes some uncertainty with the ensightWrite functionObject which was previously dependent on the simulation writeFormat and makes its behaviour consistent with foamToEnsight Note: binary Ensight output is consistent with the defaults for VTP output (inline binary) ENH: minor adjustment of ensight writing methods --- src/OpenFOAM/db/Time/Time.C | 5 +- src/OpenFOAM/db/Time/Time.H | 14 +- src/OpenFOAM/db/Time/TimeIO.C | 25 +--- src/OpenFOAM/db/options/IOstreamOption.C | 77 ++++++++-- src/OpenFOAM/db/options/IOstreamOption.H | 135 +++++++++++------- src/fileFormats/ensight/file/ensightCase.C | 58 ++++++-- src/fileFormats/ensight/file/ensightCase.H | 74 +++++++++- .../ensight/file/ensightCaseOptions.C | 49 ++++++- .../ensight/file/ensightCaseTemplates.C | 24 ++-- src/fileFormats/ensight/file/ensightFile.C | 46 ++++-- src/fileFormats/ensight/file/ensightFile.H | 16 ++- src/fileFormats/ensight/file/ensightGeoFile.C | 19 ++- src/fileFormats/ensight/file/ensightGeoFile.H | 11 +- .../utilities/ensightWrite/ensightWrite.C | 10 +- .../utilities/ensightWrite/ensightWrite.H | 9 +- .../writers/ensight/ensightCoordSetWriter.C | 14 +- .../writers/ensight/ensightCoordSetWriter.H | 12 +- .../ensight/ensightCoordSetWriterCollated.C | 12 +- .../ensight/ensightCoordSetWriterUncollated.C | 12 +- .../writers/ensight/ensightSurfaceWriter.C | 14 +- .../writers/ensight/ensightSurfaceWriter.H | 11 +- .../ensight/ensightSurfaceWriterCollated.C | 12 +- .../ensight/ensightSurfaceWriterUncollated.C | 18 ++- 23 files changed, 455 insertions(+), 222 deletions(-) diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C index ae83aad0929..b6827deac59 100644 --- a/src/OpenFOAM/db/Time/Time.C +++ b/src/OpenFOAM/db/Time/Time.C @@ -73,7 +73,10 @@ Foam::Time::writeControlNames }); -Foam::Time::fmtflags Foam::Time::format_(Foam::Time::fmtflags::general); +Foam::IOstreamOption::floatFormat Foam::Time::format_ +( + IOstreamOption::floatFormat::general +); int Foam::Time::precision_(6); diff --git a/src/OpenFOAM/db/Time/Time.H b/src/OpenFOAM/db/Time/Time.H index 249858e5b6a..54245b8ee99 100644 --- a/src/OpenFOAM/db/Time/Time.H +++ b/src/OpenFOAM/db/Time/Time.H @@ -104,15 +104,6 @@ public: saUnknown //!< Dummy no-op. Do not change current value. }; - //- Supported time directory name formats - enum fmtflags - { - general = 0, //!< default float notation - fixed = ios_base::fixed, //!< fixed-point notation - scientific = ios_base::scientific //!< scientific notation - }; - - //- Names for writeControls static const Enum<writeControls> writeControlNames; @@ -179,9 +170,8 @@ protected: //- Signal handler for write and clean exit upon signal sigStopAtWriteNow sigStopAtWriteNow_; - - //- Time directory name format - static fmtflags format_; + //- Format for time directory names (general | fixed | scientific) + static IOstreamOption::floatFormat format_; //- Time directory name precision static int precision_; diff --git a/src/OpenFOAM/db/Time/TimeIO.C b/src/OpenFOAM/db/Time/TimeIO.C index 30848008657..1312df395ae 100644 --- a/src/OpenFOAM/db/Time/TimeIO.C +++ b/src/OpenFOAM/db/Time/TimeIO.C @@ -329,29 +329,8 @@ void Foam::Time::readDict() } } - if (controlDict_.found("timeFormat")) - { - const word formatName(controlDict_.get<word>("timeFormat")); - - if (formatName == "general") - { - format_ = fmtflags::general; - } - else if (formatName == "fixed") - { - format_ = fmtflags::fixed; - } - else if (formatName == "scientific") - { - format_ = fmtflags::scientific; - } - else - { - WarningInFunction - << "Unsupported time format " << formatName - << endl; - } - } + format_ = + IOstreamOption::floatFormatEnum("timeFormat", controlDict_, format_); controlDict_.readIfPresent("timePrecision", precision_); diff --git a/src/OpenFOAM/db/options/IOstreamOption.C b/src/OpenFOAM/db/options/IOstreamOption.C index 08be7382397..32e588aaa25 100644 --- a/src/OpenFOAM/db/options/IOstreamOption.C +++ b/src/OpenFOAM/db/options/IOstreamOption.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2018-2020 OpenCFD Ltd. + Copyright (C) 2018-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -35,6 +35,17 @@ License const Foam::IOstreamOption::versionNumber Foam::IOstreamOption::currentVersion; +const Foam::Enum +< + Foam::IOstreamOption::floatFormat +> +Foam::IOstreamOption::floatFormatNames +({ + { floatFormat::general, "general" }, + { floatFormat::fixed, "fixed" }, + { floatFormat::scientific, "scientific" }, +}); + const Foam::Enum < Foam::IOstreamOption::streamFormat @@ -48,27 +59,72 @@ Foam::IOstreamOption::formatNames // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // +Foam::IOstreamOption::floatFormat +Foam::IOstreamOption::floatFormatEnum +( + const word& fmtName, + const floatFormat deflt +) +{ + // Handle bad input graciously. A no-op for an empty string + + if (!fmtName.empty()) + { + const auto iter = floatFormatNames.cfind(fmtName); + + if (iter.good()) + { + return iter.val(); + } + + // Fall-through to warning + + WarningInFunction + << "Unknown float format specifier '" << fmtName + << "' using '" << floatFormatNames[deflt] + << "' from " << floatFormatNames << nl; + } + + return deflt; +} + + +Foam::IOstreamOption::floatFormat +Foam::IOstreamOption::floatFormatEnum +( + const word& key, + const dictionary& dict, + const floatFormat deflt +) +{ + return floatFormatNames.getOrDefault(key, dict, deflt, true); // warnOnly +} + + Foam::IOstreamOption::streamFormat Foam::IOstreamOption::formatEnum ( - const word& formatName, + const word& fmtName, const streamFormat deflt ) { // Handle bad input graciously. A no-op for an empty string - if (!formatName.empty()) + if (!fmtName.empty()) { - if (formatNames.contains(formatName)) + const auto iter = formatNames.cfind(fmtName); + + if (iter.good()) { - return formatNames[formatName]; + return iter.val(); } // Fall-through to warning WarningInFunction - << "Unknown format specifier '" << formatName - << "', using '" << formatNames[deflt] << "'\n"; + << "Unknown stream format specifier '" << fmtName + << "' using '" << formatNames[deflt] + << "' from " << formatNames << nl; } return deflt; @@ -83,7 +139,7 @@ Foam::IOstreamOption::formatEnum const streamFormat deflt ) { - return formatNames.getOrDefault(key, dict, deflt, true); // failsafe=true + return formatNames.getOrDefault(key, dict, deflt, true); // warnOnly } @@ -114,8 +170,7 @@ Foam::IOstreamOption::compressionEnum WarningInFunction << "Unknown compression specifier '" << compName - << "', using compression " - << (deflt ? "on" : "off" ) << nl; + << "' using compression " << (deflt ? "on" : "off") << nl; } return deflt; @@ -132,7 +187,7 @@ Foam::IOstreamOption::compressionEnum { return ( - Switch(key, dict, Switch(bool(deflt)), true) // failsafe=true + Switch(key, dict, Switch(bool(deflt)), true) // warnOnly ? compressionType::COMPRESSED : compressionType::UNCOMPRESSED ); diff --git a/src/OpenFOAM/db/options/IOstreamOption.H b/src/OpenFOAM/db/options/IOstreamOption.H index 5b16cd3e3dc..15f243eb245 100644 --- a/src/OpenFOAM/db/options/IOstreamOption.H +++ b/src/OpenFOAM/db/options/IOstreamOption.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2018-2022 OpenCFD Ltd. + Copyright (C) 2018-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -48,6 +48,7 @@ SourceFiles #define Foam_IOstreamOption_H #include "word.H" +#include <ios> // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -97,6 +98,17 @@ public: ATOMIC //!< atomic = true }; + //- Float formats (eg, time directory name formats) + enum class floatFormat : unsigned + { + //! default float notation + general = unsigned(0), + //! fixed-point notation + fixed = unsigned(std::ios_base::fixed), + //! scientific notation + scientific = unsigned(std::ios_base::scientific) + }; + //- Representation of a major/minor version number class versionNumber @@ -134,7 +146,7 @@ public: explicit versionNumber(const token& tok); //- Failsafe construct from dictionary lookup. - versionNumber(const word& keyword, const dictionary& dict); + versionNumber(const word& key, const dictionary& dict); // Member Functions @@ -168,13 +180,16 @@ public: // Positive when 'this' is greater than other. int compare(const versionNumber& other) const noexcept { - return number_ - other.number_; + return (number_ - other.number_); } }; // Public Static Data + //- Names for float formats (general, fixed, scientific) + static const Enum<floatFormat> floatFormatNames; + //- Stream format names (ascii, binary) static const Enum<streamFormat> formatNames; @@ -182,6 +197,75 @@ public: static const versionNumber currentVersion; + // Static Helpers + + //- Lookup floatFormat enum corresponding to the string + //- (general | fixed | scientific). + // + // If the string is not recognized, emit warning and return default. + // Silent if the string itself is empty. + // + // \note Can be used as constructor substitute for the enumeration + static floatFormat floatFormatEnum + ( + const word& fmtName, + const floatFormat deflt = floatFormat::general + ); + + //- getOrDefault floatFormat from dictionary, + //- warn only on bad enumeration. + static floatFormat floatFormatEnum + ( + const word& key, //!< Lookup key. Uses LITERAL (not REGEX) + const dictionary& dict, //!< dictionary + const floatFormat deflt = floatFormat::general + ); + + //- Lookup streamFormat enum corresponding to the string + //- (ascii | binary). + // + // If the string is not recognized, emit warning and return default. + // Silent if the string itself is empty. + // + // \note Can be used as constructor substitute for the enumeration + static streamFormat formatEnum + ( + const word& fmtName, + const streamFormat deflt = streamFormat::ASCII + ); + + //- getOrDefault streamFormat from dictionary, + //- warn only on bad enumeration. + static streamFormat formatEnum + ( + const word& key, //!< Lookup key. Uses LITERAL (not REGEX) + const dictionary& dict, //!< dictionary + const streamFormat deflt = streamFormat::ASCII + ); + + //- The compression enum corresponding to the string. + // Expects switch values (true/false, on/off, ...) + // + // If the string is not recognized, emit warning and return default. + // Silent if the string itself is empty. + // + // \note Can be used as constructor substitute for the enumeration + static compressionType compressionEnum + ( + const word& compName, + const compressionType deflt = compressionType::UNCOMPRESSED + ); + + //- getOrDefault compressionType from dictionary, + //- warn only on bad enumeration. + static compressionType compressionEnum + ( + const word& key, //!< Lookup key. Uses LITERAL (not REGEX) + const dictionary& dict, //!< dictionary + const compressionType deflt = compressionType::UNCOMPRESSED + ); + + private: // Private Data @@ -252,51 +336,6 @@ public: {} - // Static Member Functions - - //- The stream format enum corresponding to the string - //- (ascii | binary). - // - // If the string is not recognized, emit warning and return default. - // Silent if the string itself is empty. - // - // \note Can be used as constructor substitute for the enumeration - static streamFormat formatEnum - ( - const word& formatName, - const streamFormat deflt = streamFormat::ASCII - ); - - //- Failsafe construct streamFormat from optional dictionary lookup - static streamFormat formatEnum - ( - const word& key, //!< Lookup key. Uses LITERAL (not REGEX) - const dictionary& dict, //!< dictionary - const streamFormat deflt = streamFormat::ASCII - ); - - //- The compression enum corresponding to the string. - // Expects switch values (true/false, on/off, ...) - // - // If the string is not recognized, emit warning and return default. - // Silent if the string itself is empty. - // - // \note Can be used as constructor substitute for the enumeration - static compressionType compressionEnum - ( - const word& compName, - const compressionType deflt = compressionType::UNCOMPRESSED - ); - - //- Failsafe construct compressionType from optional dictionary lookup - static compressionType compressionEnum - ( - const word& key, //!< Lookup key. Uses LITERAL (not REGEX) - const dictionary& dict, //!< dictionary - const compressionType deflt = compressionType::UNCOMPRESSED - ); - - // Member Functions //- Get the current stream format diff --git a/src/fileFormats/ensight/file/ensightCase.C b/src/fileFormats/ensight/file/ensightCase.C index 144afad96a2..648ae075f78 100644 --- a/src/fileFormats/ensight/file/ensightCase.C +++ b/src/fileFormats/ensight/file/ensightCase.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -56,6 +56,44 @@ Foam::word Foam::ensightCase::padded(const int nwidth, const label value) } +void Foam::ensightCase::setTimeFormat +( + OSstream& os, + IOstreamOption::floatFormat timeFmt, + const int timePrec +) +{ + os.setf(std::ios_base::left); + os.setf + ( + std::ios_base::fmtflags(timeFmt), + std::ios_base::floatfield + ); + + if (timePrec > 0) + { + os.precision(timePrec); + } +} + + +void Foam::ensightCase::setTimeFormat +( + OSstream& os, + const ensightCase::options& opts +) +{ + os.setf(std::ios_base::left); + os.setf + ( + std::ios_base::fmtflags(opts.timeFormat()), + std::ios_base::floatfield + ); + + os.precision(opts.timePrecision()); +} + + void Foam::ensightCase::printTimeset ( OSstream& os, @@ -184,7 +222,7 @@ Foam::fileName Foam::ensightCase::dataDir() const void Foam::ensightCase::initialize() { - if (Pstream::master()) + if (UPstream::master()) { // EnSight and EnSight/data directories must exist @@ -211,11 +249,7 @@ void Foam::ensightCase::initialize() // The case file is always ASCII os_.reset(new OFstream(ensightDir_/caseName_, IOstreamOption::ASCII)); - - // Format options - os_->setf(ios_base::left); - os_->setf(ios_base::scientific, ios_base::floatfield); - os_->precision(5); + ensightCase::setTimeFormat(*os_, *options_); // Format options writeHeader(); } @@ -468,7 +502,7 @@ Foam::ensightCase::createDataFile const word& name ) const { - if (Pstream::master()) + if (UPstream::master()) { // The data/ITER subdirectory must exist // Note that data/ITER is indeed a valid ensight::FileName @@ -490,7 +524,7 @@ Foam::ensightCase::createCloudFile const word& name ) const { - if (Pstream::master()) + if (UPstream::master()) { // Write // eg -> "data/********/lagrangian/<cloudName>/positions" @@ -584,7 +618,7 @@ void Foam::ensightCase::setTime(const scalar value, const label index) timeIndex_ = index; timeValue_ = value; - if (Pstream::master()) + if (UPstream::master()) { // The data/ITER subdirectory must exist // Note that data/ITER is indeed a valid ensight::FileName @@ -810,7 +844,7 @@ Foam::ensightCase::newGeometry { autoPtr<Foam::ensightGeoFile> output; - if (Pstream::master()) + if (UPstream::master()) { // Set the path of the ensight file fileName path; @@ -844,7 +878,7 @@ Foam::ensightCase::newCloud { autoPtr<Foam::ensightFile> output; - if (Pstream::master()) + if (UPstream::master()) { output = createCloudFile(cloudName, "positions"); diff --git a/src/fileFormats/ensight/file/ensightCase.H b/src/fileFormats/ensight/file/ensightCase.H index c6247f4cf41..185e59dcfbb 100644 --- a/src/fileFormats/ensight/file/ensightCase.H +++ b/src/fileFormats/ensight/file/ensightCase.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -57,6 +57,7 @@ namespace Foam // Forward Declarations class bitSet; +class dictionary; class ensightCase; class instant; class OSstream; @@ -333,6 +334,21 @@ public: // Output Helpers + //- Set output time format for ensight case file + static void setTimeFormat + ( + OSstream& os, + IOstreamOption::floatFormat timeFmt, + const int timePrec + ); + + //- Set output time format for ensight case file + static void setTimeFormat + ( + OSstream& os, + const ensightCase::options& opts + ); + //- Print time-set for ensight case file with a single time static void printTimeset ( @@ -388,7 +404,7 @@ class ensightCase::options { // Private Data - //- Ascii/Binary file output + //- The output file format (ascii/binary) IOstreamOption::streamFormat format_; //- Remove existing directory and sub-directories on creation @@ -400,8 +416,14 @@ class ensightCase::options //- Write clouds into their own directory bool separateCloud_; + //- Time format for case file (default: scientific) + IOstreamOption::floatFormat timeFormat_; + + //- Time precision for case file (default: 5) + int timePrecision_; + //- Width of mask for subdirectories - label width_; + int width_; //- The '*' mask appropriate for subdirectories word mask_; @@ -415,16 +437,39 @@ public: // Constructors //- Construct with the specified format (default is binary) - options(IOstreamOption::streamFormat fmt = IOstreamOption::BINARY); + explicit options + ( + IOstreamOption::streamFormat fmt = IOstreamOption::BINARY + ); + + //- If present, construct with the format specified in the dictionary + //- or use default (binary) + options + ( + //! The lookup name for the format, typically 'format' + //! or 'writeFormat' etc. + const word& formatKeyword, + const dictionary& dict, + IOstreamOption::streamFormat fmt = IOstreamOption::BINARY + ); // Member Functions // Access - //- Ascii/Binary file output + //- The output file format (ascii/binary) IOstreamOption::streamFormat format() const noexcept { return format_; } + //- Time format for case file (general/fixed/scientific) + IOstreamOption::floatFormat timeFormat() const noexcept + { + return timeFormat_; + } + + //- Time precision for case file + int timePrecision() const noexcept { return timePrecision_; } + //- The '*' mask appropriate for sub-directories const word& mask() const noexcept { return mask_; } @@ -432,7 +477,7 @@ public: word padded(const label i) const; //- Return current width of mask and padded. - label width() const noexcept { return width_; } + int width() const noexcept { return width_; } //- Remove existing directory and sub-directories on creation bool overwrite() const noexcept { return overwrite_; } @@ -445,7 +490,22 @@ public: //- Set width of mask and padded. // Default width is 8 digits, max width is 31 digits. - void width(const label i); + void width(const int i); + + //- Set the time format for case file + void timeFormat(IOstreamOption::floatFormat fmt) noexcept + { + timeFormat_ = fmt; + } + + //- Set the time precision for case file + void timePrecision(int prec) noexcept { timePrecision_ = prec; } + + //- Set the time format for case file + void timeFormat(const word& key, const dictionary& dict); + + //- Set the time precision for case file + void timePrecision(const word& key, const dictionary& dict); //- Remove existing directory and sub-directories on creation void overwrite(bool on) noexcept { overwrite_ = on; } diff --git a/src/fileFormats/ensight/file/ensightCaseOptions.C b/src/fileFormats/ensight/file/ensightCaseOptions.C index ec159410763..515701bb6b5 100644 --- a/src/fileFormats/ensight/file/ensightCaseOptions.C +++ b/src/fileFormats/ensight/file/ensightCaseOptions.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,15 +26,24 @@ License \*---------------------------------------------------------------------------*/ #include "ensightCase.H" +#include "dictionary.H" // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::ensightCase::options::options(IOstreamOption::streamFormat fmt) : - format_(fmt), + format_ + ( + // Can only be ASCII or BINARY + (fmt == IOstreamOption::streamFormat::ASCII) + ? IOstreamOption::streamFormat::ASCII + : IOstreamOption::streamFormat::BINARY + ), overwrite_(false), nodeValues_(false), separateCloud_(false), + timeFormat_(IOstreamOption::floatFormat::scientific), + timePrecision_(5), width_(0), mask_(), printf_() @@ -43,6 +52,17 @@ Foam::ensightCase::options::options(IOstreamOption::streamFormat fmt) } +Foam::ensightCase::options::options +( + const word& formatKeyword, + const dictionary& dict, + IOstreamOption::streamFormat fmt +) +: + options(IOstreamOption::formatEnum(formatKeyword, dict, fmt)) +{} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // Foam::word Foam::ensightCase::options::padded(const label i) const @@ -58,7 +78,7 @@ Foam::word Foam::ensightCase::options::padded(const label i) const } -void Foam::ensightCase::options::width(const label n) +void Foam::ensightCase::options::width(const int n) { // Enforce min/max sanity limits if (n < 1 || n > 31) @@ -74,4 +94,27 @@ void Foam::ensightCase::options::width(const label n) } +void Foam::ensightCase::options::timeFormat +( + const word& key, + const dictionary& dict +) +{ + timeFormat_ = IOstreamOption::floatFormatEnum(key, dict, timeFormat_); +} + + +void Foam::ensightCase::options::timePrecision +( + const word& key, + const dictionary& dict +) +{ + if (!key.empty()) + { + dict.readIfPresent(key, timePrecision_, keyType::LITERAL); + } +} + + // ************************************************************************* // diff --git a/src/fileFormats/ensight/file/ensightCaseTemplates.C b/src/fileFormats/ensight/file/ensightCaseTemplates.C index e5e7d455e9c..8b1105ead66 100644 --- a/src/fileFormats/ensight/file/ensightCaseTemplates.C +++ b/src/fileFormats/ensight/file/ensightCaseTemplates.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,19 +40,16 @@ Foam::ensightCase::newData { autoPtr<ensightFile> output; - if (Pstream::master()) + if (UPstream::master()) { const ensight::VarName varName(name); output = createDataFile(varName); // Description - output().write + output().writeString ( - string - ( - padded(timeIndex_) / varName - + " <" + pTraits<Type>::typeName + ">" - ) + padded(timeIndex_) / varName + + " <" + pTraits<Type>::typeName + ">" ); output().newline(); @@ -91,19 +88,16 @@ Foam::ensightCase::newCloudData { autoPtr<ensightFile> output; - if (Pstream::master()) + if (UPstream::master()) { const ensight::VarName varName(name); output = createCloudFile(cloudName, varName); // Description - output().write + output().writeString ( - string - ( - padded(timeIndex_) / cloudName / varName - + " <" + pTraits<Type>::typeName + ">" - ) + padded(timeIndex_) / cloudName / varName + + " <" + pTraits<Type>::typeName + ">" ); output().newline(); diff --git a/src/fileFormats/ensight/file/ensightFile.C b/src/fileFormats/ensight/file/ensightFile.C index e10cb056d84..dca789e4c15 100644 --- a/src/fileFormats/ensight/file/ensightFile.C +++ b/src/fileFormats/ensight/file/ensightFile.C @@ -147,7 +147,7 @@ float Foam::ensightFile::undefValue(float value) noexcept // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -Foam::Ostream& Foam::ensightFile::writeString(const char* str, size_t len) +void Foam::ensightFile::writeString(const char* str, size_t len) { // Output 79 chars (ASCII) or 80 chars (BINARY) char buf[80]; @@ -165,41 +165,47 @@ Foam::Ostream& Foam::ensightFile::writeString(const char* str, size_t len) else { buf[79] = 0; // Max 79 in ASCII + + // TBD: Extra safety - trap newline in ASCII? + // char* p = ::strchr(buf, '\n'); + // if (p) *p = 0; + stdStream() << buf; syncState(); } - - return *this; } -Foam::Ostream& Foam::ensightFile::writeString(const char* str) +void Foam::ensightFile::writeString(const char* str) { - return writeString(str, strlen(str)); + writeString(str, strlen(str)); } -Foam::Ostream& Foam::ensightFile::writeString(const std::string& str) +void Foam::ensightFile::writeString(const std::string& str) { - return writeString(str.data(), str.size()); + writeString(str.data(), str.size()); } Foam::Ostream& Foam::ensightFile::write(const char* str) { - return writeString(str, strlen(str)); + writeString(str, strlen(str)); + return *this; } Foam::Ostream& Foam::ensightFile::write(const word& str) { - return writeString(str.data(), str.size()); + writeString(str.data(), str.size()); + return *this; } Foam::Ostream& Foam::ensightFile::write(const std::string& str) { - return writeString(str.data(), str.size()); + writeString(str.data(), str.size()); + return *this; } @@ -304,10 +310,9 @@ void Foam::ensightFile::newline() } -Foam::Ostream& Foam::ensightFile::writeUndef() +void Foam::ensightFile::writeUndef() { write(undefValue_); - return *this; } @@ -330,14 +335,27 @@ Foam::Ostream& Foam::ensightFile::writeKeyword(const keyType& key) } -Foam::Ostream& Foam::ensightFile::writeBinaryHeader() +void Foam::ensightFile::writeBinaryHeader() { if (format() == IOstreamOption::BINARY) { writeString("C Binary"); + // Is binary: newline() is a no-op } +} - return *this; + +void Foam::ensightFile::beginTimeStep() +{ + writeString("BEGIN TIME STEP"); + newline(); +} + + +void Foam::ensightFile::endTimeStep() +{ + writeString("END TIME STEP"); + newline(); } diff --git a/src/fileFormats/ensight/file/ensightFile.H b/src/fileFormats/ensight/file/ensightFile.H index e472f25720a..e565f3eb2cb 100644 --- a/src/fileFormats/ensight/file/ensightFile.H +++ b/src/fileFormats/ensight/file/ensightFile.H @@ -146,19 +146,25 @@ public: // Output //- Write "C Binary" string for binary files (eg, geometry/measured) - Ostream& writeBinaryHeader(); + void writeBinaryHeader(); + + //- Write "BEGIN TIME STEP" string and newline + void beginTimeStep(); + + //- Write "END TIME STEP" string and newline + void endTimeStep(); //- Write character/string content as "%79s" or as binary (max 80 chars) - Ostream& writeString(const char* str, size_t len); + void writeString(const char* str, size_t len); //- Write C-string as "%79s" or as binary (max 80 chars) - Ostream& writeString(const char* str); + void writeString(const char* str); //- Write string as "%79s" or as binary (max 80 chars) - Ostream& writeString(const std::string& str); + void writeString(const std::string& str); //- Write undef value - Ostream& writeUndef(); + void writeUndef(); //- Write element keyword with trailing newline, diff --git a/src/fileFormats/ensight/file/ensightGeoFile.C b/src/fileFormats/ensight/file/ensightGeoFile.C index 46ab3066ceb..f5da0c33ca1 100644 --- a/src/fileFormats/ensight/file/ensightGeoFile.C +++ b/src/fileFormats/ensight/file/ensightGeoFile.C @@ -34,23 +34,32 @@ License void Foam::ensightGeoFile::init() { writeBinaryHeader(); + beginGeometry(); +} + +void Foam::ensightGeoFile::beginGeometry() +{ // Description line 1 - write("Ensight Geometry File"); + writeString("Ensight Geometry File"); newline(); // Description line 2 - write(string("Written by OpenFOAM " + std::to_string(foamVersion::api))); + writeString("Written by OpenFOAM " + std::to_string(foamVersion::api)); newline(); - write("node id assign"); + writeString("node id assign"); newline(); - write("element id assign"); + writeString("element id assign"); newline(); } +void Foam::ensightGeoFile::endGeometry() +{} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::ensightGeoFile::ensightGeoFile @@ -96,7 +105,7 @@ Foam::Ostream& Foam::ensightGeoFile::writeKeyword(const keyType& key) void Foam::ensightGeoFile::beginPart ( const label index, - const string& description + const std::string& description ) { beginPart(index); diff --git a/src/fileFormats/ensight/file/ensightGeoFile.H b/src/fileFormats/ensight/file/ensightGeoFile.H index 9fbc1249022..86d2d9beed7 100644 --- a/src/fileFormats/ensight/file/ensightGeoFile.H +++ b/src/fileFormats/ensight/file/ensightGeoFile.H @@ -52,16 +52,21 @@ class ensightGeoFile { // Private Member Functions - //- Initialize outputs the header information + //- Initialize outputs the header information and beginGeometry void init(); + //- Start of geometry information + void beginGeometry(); + + //- End of geometry information + void endGeometry(); + //- No copy construct ensightGeoFile(const ensightGeoFile&) = delete; //- No copy assignment void operator=(const ensightGeoFile&) = delete; - public: // Static Functions @@ -111,7 +116,7 @@ public: using ensightFile::beginPart; //- Begin a "part" (0-based index), with a description. - void beginPart(const label index, const string& description); + void beginPart(const label index, const std::string& description); //- Begin a "coordinates" block void beginCoordinates(const label npoints); diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.C b/src/functionObjects/utilities/ensightWrite/ensightWrite.C index c25755e45be..7b203564170 100644 --- a/src/functionObjects/utilities/ensightWrite/ensightWrite.C +++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -97,10 +97,7 @@ Foam::functionObjects::ensightWrite::ensightWrite : fvMeshFunctionObject(name, runTime, dict), writeOpts_(), - caseOpts_ - ( - IOstreamOption::formatEnum("format", dict, runTime.writeFormat()) - ), + caseOpts_("format", dict, IOstreamOption::BINARY), outputDir_(), consecutive_(false), meshState_(polyMesh::TOPO_CHANGE), @@ -180,6 +177,9 @@ bool Foam::functionObjects::ensightWrite::read(const dictionary& dict) caseOpts_.width(dict.getOrDefault<label>("width", 8)); caseOpts_.overwrite(dict.getOrDefault("overwrite", false)); + caseOpts_.timeFormat("timeFormat", dict); + caseOpts_.timePrecision("timePrecision", dict); + // Output directory diff --git a/src/functionObjects/utilities/ensightWrite/ensightWrite.H b/src/functionObjects/utilities/ensightWrite/ensightWrite.H index c8dc1e3a5d1..3ba712be80c 100644 --- a/src/functionObjects/utilities/ensightWrite/ensightWrite.H +++ b/src/functionObjects/utilities/ensightWrite/ensightWrite.H @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2016-2022 OpenCFD Ltd. + Copyright (C) 2016-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -42,6 +42,9 @@ Description writeInterval 1; format binary; + timeFormat scientific; + timePrecision 5; + overwrite true; width 12; @@ -95,11 +98,13 @@ Description \heading Ensight Output Options \table Property | Description | Required | Default - format | ascii or binary format | no | same as simulation + format | ascii or binary format | no | binary width | Mask width for \c data/XXXX | no | 8 directory | The output directory name | no | postProcessing/NAME overwrite | Remove existing directory | no | false consecutive | Consecutive output numbering | no | false + timeFormat | Time format (ensight case) | no | scientific + timePrecision | Time precision (ensight case) | no | 5 \endtable \heading Output Selection diff --git a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C index 91b20276d35..e32da21c519 100644 --- a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C +++ b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2021-2022 OpenCFD Ltd. + Copyright (C) 2021-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -176,7 +176,7 @@ void Foam::coordSetWriters::ensightWriter::writeGeometry Foam::coordSetWriters::ensightWriter::ensightWriter() : coordSetWriter(), - writeFormat_(IOstreamOption::ASCII), + caseOpts_(IOstreamOption::BINARY), collateTimes_(true), caching_("fieldsDict") // Historic name {} @@ -185,13 +185,13 @@ Foam::coordSetWriters::ensightWriter::ensightWriter() Foam::coordSetWriters::ensightWriter::ensightWriter(const dictionary& options) : coordSetWriter(options), - writeFormat_ - ( - IOstreamOption::formatEnum("format", options, IOstreamOption::ASCII) - ), + caseOpts_("format", options, IOstreamOption::BINARY), collateTimes_(options.getOrDefault("collateTimes", true)), caching_("fieldsDict") // Historic name -{} +{ + caseOpts_.timeFormat("timeFormat", options); + caseOpts_.timePrecision("timePrecision", options); +} Foam::coordSetWriters::ensightWriter::ensightWriter diff --git a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H index fc03292a6a6..28d53709060 100644 --- a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H +++ b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriter.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2021-2022 OpenCFD Ltd. + Copyright (C) 2021-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -44,8 +44,11 @@ Description Format options: \table Property | Description | Required | Default - format | ascii/binary | no | ascii + format | ascii/binary | no | binary collateTimes | use common geometry for times | no | true + timeFormat | Time format (ensight case) | no | scientific + timePrecision | Time precision (ensight case) | no | 5 + \endtable \endtable SourceFiles @@ -57,6 +60,7 @@ SourceFiles #define Foam_coordSetWriters_ensightWriter_H #include "coordSetWriter.H" +#include "ensightCase.H" #include "ensightWriterCaching.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -91,8 +95,8 @@ class ensightWriter // Private Data - //- Output format option (default: ASCII) - IOstreamOption::streamFormat writeFormat_; + //- Ensight case options + ensightCase::options caseOpts_; //- Collate times (default: true) bool collateTimes_; diff --git a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterCollated.C b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterCollated.C index c6babf60516..3e378c2933c 100644 --- a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterCollated.C +++ b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterCollated.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022 OpenCFD Ltd. + Copyright (C) 2022-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -148,7 +148,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated ( geomFile.path(), geomFile.name(), - writeFormat_ + caseOpts_.format() ); writeGeometry(osGeom, elemOutput); @@ -160,7 +160,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated ( dataDir, varName, - writeFormat_ + caseOpts_.format() ); if (verbose_) @@ -177,11 +177,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeCollated if (stateChanged) { OFstream osCase(outputFile, IOstreamOption::ASCII); - - // Format options - osCase.setf(ios_base::left); - osCase.setf(ios_base::scientific, ios_base::floatfield); - osCase.precision(5); + ensightCase::setTimeFormat(osCase, caseOpts_); // time-format if (verbose_) { diff --git a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterUncollated.C b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterUncollated.C index 1bfa2933f36..f4a56dcce84 100644 --- a/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterUncollated.C +++ b/src/meshTools/coordSet/writers/ensight/ensightCoordSetWriterUncollated.C @@ -5,7 +5,7 @@ \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- - Copyright (C) 2022 OpenCFD Ltd. + Copyright (C) 2022-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -101,13 +101,13 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated ( baseDir, baseName + ".00000000.mesh", - writeFormat_ + caseOpts_.format() ); ensightFile osField ( baseDir, baseName + ".00000000." + varName, - writeFormat_ + caseOpts_.format() ); writeGeometry(osGeom, elemOutput); @@ -119,11 +119,7 @@ Foam::fileName Foam::coordSetWriters::ensightWriter::writeUncollated // Update case file { OFstream osCase(outputFile, IOstreamOption::ASCII); - - // Format options - osCase.setf(ios_base::left); - osCase.setf(ios_base::scientific, ios_base::floatfield); - osCase.precision(5); + ensightCase::setTimeFormat(osCase, caseOpts_); // time-format osCase << "FORMAT" << nl diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C index 8cdcc1bd2f7..253ad3fa8f1 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -55,7 +55,7 @@ namespace surfaceWriters Foam::surfaceWriters::ensightWriter::ensightWriter() : surfaceWriter(), - writeFormat_(IOstreamOption::ASCII), + caseOpts_(IOstreamOption::BINARY), collateTimes_(true), caching_("fieldsDict") // Historic name {} @@ -67,13 +67,13 @@ Foam::surfaceWriters::ensightWriter::ensightWriter ) : surfaceWriter(options), - writeFormat_ - ( - IOstreamOption::formatEnum("format", options, IOstreamOption::ASCII) - ), + caseOpts_("format", options, IOstreamOption::BINARY), collateTimes_(options.getOrDefault("collateTimes", true)), caching_("fieldsDict") // Historic name -{} +{ + caseOpts_.timeFormat("timeFormat", options); + caseOpts_.timePrecision("timePrecision", options); +} Foam::surfaceWriters::ensightWriter::ensightWriter diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriter.H b/src/surfMesh/writers/ensight/ensightSurfaceWriter.H index e0c3a4b3166..1fc8e184404 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriter.H +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriter.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -44,12 +44,14 @@ Description Format options for ensight: \table Property | Description | Required | Default - format | ascii/binary | no | ascii + format | ascii/binary | no | binary collateTimes | Use common geometry for times | no | true scale | Output geometry scaling | no | 1 transform | Output coordinate transform | no | fieldLevel | Subtract field level before scaling | no | empty dict fieldScale | Output field scaling | no | empty dict + timeFormat | Time format (ensight case) | no | scientific + timePrecision | Time precision (ensight case) | no | 5 \endtable The collated format maintains an internal list of the known times @@ -65,6 +67,7 @@ SourceFiles #define Foam_surfaceWriters_ensightWriter_H #include "surfaceWriter.H" +#include "ensightCase.H" #include "ensightWriterCaching.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -84,8 +87,8 @@ class ensightWriter { // Private Data - //- Output format option (default: ASCII) - IOstreamOption::streamFormat writeFormat_; + //- Ensight case options + ensightCase::options caseOpts_; //- Collate times (default: true) bool collateTimes_; diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C index 378ee23109b..1d5595564ec 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -163,7 +163,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated ( geomFile.path(), geomFile.name(), - writeFormat_ + caseOpts_.format() ); part.write(osGeom); // serial } @@ -173,7 +173,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated ( dataDir, varName, - writeFormat_ + caseOpts_.format() ); if (verbose_) @@ -191,11 +191,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated if (stateChanged) { OFstream osCase(outputFile, IOstreamOption::ASCII); - - // Format options - osCase.setf(ios_base::left); - osCase.setf(ios_base::scientific, ios_base::floatfield); - osCase.precision(5); + ensightCase::setTimeFormat(osCase, caseOpts_); // time-format if (verbose_) { diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C index 6e1f65f682a..27f5e9e6d51 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2014 OpenFOAM Foundation - Copyright (C) 2015-2022 OpenCFD Ltd. + Copyright (C) 2015-2023 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -73,7 +73,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated() ( outputDir, baseName + ".00000000.mesh", - writeFormat_ + caseOpts_.format() ); ensightOutputSurface part @@ -85,7 +85,9 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated() part.write(osGeom); // serial // Update case file - OFstream osCase(outputFile); + OFstream osCase(outputFile, IOstreamOption::ASCII); + ensightCase::setTimeFormat(osCase, caseOpts_); // time-format + osCase << "FORMAT" << nl << "type: ensight gold" << nl @@ -176,13 +178,13 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated ( baseDir, baseName + ".00000000.mesh", - writeFormat_ + caseOpts_.format() ); ensightFile osField ( baseDir, baseName + ".00000000." + varName, - writeFormat_ + caseOpts_.format() ); // Ensight Geometry @@ -203,11 +205,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated // Update case file { OFstream osCase(outputFile, IOstreamOption::ASCII); - - // Format options - osCase.setf(ios_base::left); - osCase.setf(ios_base::scientific, ios_base::floatfield); - osCase.precision(5); + ensightCase::setTimeFormat(osCase, caseOpts_); // time-format osCase << "FORMAT" << nl -- GitLab