diff --git a/src/fileFormats/ensight/file/ensightCase.C b/src/fileFormats/ensight/file/ensightCase.C index 7e6e6be5f1..9c0e359537 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-2018 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,15 +26,10 @@ License \*---------------------------------------------------------------------------*/ #include "ensightCase.H" -#include "stringListOps.H" +#include "ensightGeoFile.H" #include "Time.H" #include "cloud.H" #include "IOmanip.H" -#include "globalIndex.H" - -#include "ensightFile.H" -#include "ensightGeoFile.H" -#include "demandDrivenData.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -69,7 +64,7 @@ void Foam::ensightCase::initialize() else { DetailInfo - <<"Warning: re-using existing directory" << nl + << "Warning: re-using existing directory" << nl << " " << ensightDir_ << endl; } } @@ -78,7 +73,7 @@ void Foam::ensightCase::initialize() mkDir(dataDir()); // The case file is always ASCII - os_ = new OFstream(ensightDir_/caseName_, IOstream::ASCII); + os_.reset(new OFstream(ensightDir_/caseName_, IOstream::ASCII)); // Format options os_->setf(ios_base::left); @@ -126,7 +121,7 @@ Foam::label Foam::ensightCase::checkTimeset(const labelHashSet& lookup) const void Foam::ensightCase::writeHeader() const { - if (os_) // master only + if (os_) // True on master only { this->rewind(); *os_ @@ -218,7 +213,7 @@ void Foam::ensightCase::writeTimeset const scalar timeCorrection ) const { - // make a copy + // Make a copy labelHashSet hashed(lookup); hashed.erase(-1); @@ -282,9 +277,10 @@ void Foam::ensightCase::noteGeometry(const bool moving) const void Foam::ensightCase::noteCloud(const word& cloudName) const { + // Force into existence if (!cloudVars_.found(cloudName)) { - cloudVars_.insert(cloudName, HashTable()); + cloudVars_.emplace(cloudName); } cloudTimes_.insert(timeIndex_); @@ -388,9 +384,9 @@ Foam::ensightCase::ensightCase ) : options_(new options(opts)), + os_(nullptr), ensightDir_(ensightDir), caseName_(caseName + ".case"), - os_(nullptr), changed_(false), timeIndex_(0), timeValue_(0), @@ -398,6 +394,7 @@ Foam::ensightCase::ensightCase geomTimes_(), cloudTimes_(), variables_(), + nodeVariables_(), cloudVars_() { initialize(); @@ -412,9 +409,9 @@ Foam::ensightCase::ensightCase ) : options_(new options(format)), + os_(nullptr), ensightDir_(ensightDir), caseName_(caseName + ".case"), - os_(nullptr), changed_(false), timeIndex_(0), timeValue_(0), @@ -422,21 +419,13 @@ Foam::ensightCase::ensightCase geomTimes_(), cloudTimes_(), variables_(), + nodeVariables_(), cloudVars_() { initialize(); } -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -Foam::ensightCase::~ensightCase() -{ - deleteDemandDrivenData(options_); - deleteDemandDrivenData(os_); -} - - // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::ensightCase::nextTime(const scalar value) @@ -580,7 +569,7 @@ void Foam::ensightCase::write() const // if (variables_.size() || cloudVars_.size()) { - // start of variables + // Start of variables *os_ << nl << "VARIABLE" << nl; @@ -598,7 +587,7 @@ void Foam::ensightCase::write() const << ensType.c_str() << ( - nodeValues() + (nodeVariables_.found(varName) || nodeValues()) ? " per node: 1 " // time-set 1 : " per element: 1 " // time-set 1 ) @@ -678,7 +667,7 @@ void Foam::ensightCase::write() const Foam::autoPtr Foam::ensightCase::newGeometry ( - const bool moving + bool moving ) const { autoPtr output; @@ -749,8 +738,12 @@ Foam::Ostream& Foam::ensightCase::printInfo(Ostream& os) const os << "Ensight case:" << nl << " path: " << ensightDir_ << nl << " name: " << caseName_ << nl - << " format: " << format() << nl - << " values per " << (nodeValues() ? "node" : "element") << nl; + << " format: " << format() << nl; + + if (nodeValues()) + { + os << " values per node" << nl; + } return os; } diff --git a/src/fileFormats/ensight/file/ensightCase.H b/src/fileFormats/ensight/file/ensightCase.H index 8479127939..2765522c4e 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 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -32,6 +32,9 @@ Description SourceFiles ensightCase.C + ensightCaseI.H + ensightCaseOptions.C + ensightCaseTemplates.C \*---------------------------------------------------------------------------*/ @@ -42,17 +45,18 @@ SourceFiles #include "HashSet.H" #include "InfoProxy.H" #include "Map.H" +#include "HashSet.H" #include "OSspecific.H" #include "Pstream.H" - #include "ensightGeoFile.H" +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { -// Forward declarations +// Forward Declarations class ensightCase; class instant; class Time; @@ -65,7 +69,7 @@ class ensightCase { public: - // Forward declarations + // Forward Declarations class options; // Public Data @@ -76,12 +80,16 @@ public: //- The name for geometry files static const char* geometryName; + private: - // Private data + // Private Data //- Case writing options - const options* options_; + const std::unique_ptr options_; + + //- Output stream (master only) + mutable std::unique_ptr os_; //- Output path (absolute) fileName ensightDir_; @@ -89,9 +97,6 @@ private: //- Case name (with ".case" ending) word caseName_; - //- Output stream (master only) - mutable OFstream* os_; - //- Track state changes since last write mutable bool changed_; @@ -119,6 +124,9 @@ private: //- Fields/Variables with the ensight type mutable HashTable variables_; + //- Remember fields that are to be treated as point data + mutable HashSet nodeVariables_; + //- Cloud names and variables mutable HashTable> cloudVars_; @@ -214,7 +222,7 @@ public: //- Destructor - ~ensightCase(); + ~ensightCase() = default; // Member Functions @@ -236,7 +244,7 @@ public: //- Consistent zero-padded integer value inline word padded(const label i) const; - //- Use values per nodes instead of per element + //- Force use of values per node instead of per element inline bool nodeValues() const; //- Write clouds into their own directory instead in "data" directory @@ -269,8 +277,7 @@ public: // Addition of entries to case file //- Open stream for new geometry file (on master). - autoPtr newGeometry(const bool moving = false) const; - + autoPtr newGeometry(bool moving = false) const; //- Open stream for new cloud positions (on master). // Note the use of ensightFile, not ensightGeoFile. @@ -279,11 +286,19 @@ public: const word& cloudName ) const; - //- Open stream for new data file (on master), with current index. + // Optionally marking as containing POINT_DATA template - autoPtr newData(const word& varName) const; + autoPtr newData + ( + const word& varName, + const bool isPointData = false + ) const; + //- Open stream for new data file (on master), with current index + //- and marking as containing POINT_DATA + template + autoPtr newPointData(const word& varName) const; //- Open stream for new cloud data file (on master), with current index. template @@ -313,28 +328,29 @@ public: //- Configuration options for the ensightCase class ensightCase::options { -private: + // Private Data - //- Ascii/Binary file output - IOstream::streamFormat format_; + //- Ascii/Binary file output + IOstream::streamFormat format_; - //- Width of mask for subdirectories - label width_; + //- Remove existing directory and sub-directories on creation + bool overwrite_; - //- The '*' mask appropriate for subdirectories - word mask_; + //- Force use of values per node instead of per element + bool nodeValues_; - //- The printf format for zero-padded subdirectory numbers - string printf_; + //- Write clouds into their own directory + bool separateCloud_; - //- Remove existing directory and sub-directories on creation - bool overwrite_; + //- Width of mask for subdirectories + label width_; - //- Write values at nodes - bool nodeValues_; + //- The '*' mask appropriate for subdirectories + word mask_; + + //- The printf format for zero-padded subdirectory numbers + string printf_; - //- Write clouds into their own directory - bool separateCloud_; public: @@ -363,9 +379,6 @@ public: //- Remove existing directory and sub-directories on creation bool overwrite() const; - //- Use values per nodes instead of per element - bool nodeValues() const; - //- Write clouds into their own directory instead in "data" directory bool separateCloud() const; @@ -379,12 +392,20 @@ public: //- Remove existing directory and sub-directories on creation void overwrite(bool); - //- Use values per nodes instead of per element - void nodeValues(bool); - //- Write clouds into their own directory instead in "data" directory void separateCloud(bool); + + // Housekeeping + + //- Force use of values per node instead of per element + bool nodeValues() const; + + //- Force use of values per node instead of per element + // Deprecated(2020-02) - The newData() method with a second parameter + // is more flexible. + // \deprecated(2020-02) - newData() with second parameter + void nodeValues(bool); }; diff --git a/src/fileFormats/ensight/file/ensightCaseOptions.C b/src/fileFormats/ensight/file/ensightCaseOptions.C index f74cc5a7e8..f3a1756385 100644 --- a/src/fileFormats/ensight/file/ensightCaseOptions.C +++ b/src/fileFormats/ensight/file/ensightCaseOptions.C @@ -32,14 +32,14 @@ License Foam::ensightCase::options::options(IOstream::streamFormat format) : format_(format), - width_(0), - mask_(), - printf_(), overwrite_(false), nodeValues_(false), - separateCloud_(false) + separateCloud_(false), + width_(0), + mask_(), + printf_() { - width(8); // Ensures that mask and printf-format are properly resized + width(8); // Fill mask and setup printf-format } diff --git a/src/fileFormats/ensight/file/ensightCaseTemplates.C b/src/fileFormats/ensight/file/ensightCaseTemplates.C index ae496c95c2..5cbadf5388 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 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -34,7 +34,8 @@ template Foam::autoPtr Foam::ensightCase::newData ( - const word& name + const word& name, + const bool isPointData ) const { autoPtr output; @@ -42,9 +43,10 @@ Foam::ensightCase::newData if (Pstream::master()) { const ensight::VarName varName(name); + output = createDataFile(varName); - // description + // Description output().write ( string @@ -55,14 +57,31 @@ Foam::ensightCase::newData ); output().newline(); - // note field variable for later use + // Remember the field variable for later use noteVariable(varName, ensightPTraits::typeName); + + // Could warn about existing variables that changed representation + if (isPointData) + { + nodeVariables_.set(varName); + } } return output; } +template +Foam::autoPtr +Foam::ensightCase::newPointData +( + const word& name +) const +{ + return newData(name, true); // POINT_DATA +} + + template Foam::autoPtr Foam::ensightCase::newCloudData @@ -78,7 +97,7 @@ Foam::ensightCase::newCloudData const ensight::VarName varName(name); output = createCloudFile(cloudName, varName); - // description + // Description output().write ( string @@ -89,7 +108,7 @@ Foam::ensightCase::newCloudData ); output().newline(); - // note cloud variable for later use + // Remember the cloud variable for later use noteCloud(cloudName, varName, ensightPTraits::typeName); } diff --git a/src/fileFormats/ensight/file/ensightFile.C b/src/fileFormats/ensight/file/ensightFile.C index 4cdb931fff..f9d041c89b 100644 --- a/src/fileFormats/ensight/file/ensightFile.C +++ b/src/fileFormats/ensight/file/ensightFile.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -29,7 +29,6 @@ License #include "ensightFile.H" #include "error.H" #include "UList.H" - #include #include @@ -39,10 +38,12 @@ bool Foam::ensightFile::allowUndef_ = false; Foam::scalar Foam::ensightFile::undefValue_ = Foam::floatScalarVGREAT; -// default is width 8 +// Default is width 8 Foam::string Foam::ensightFile::mask_ = "********"; Foam::string Foam::ensightFile::dirFmt_ = "%08d"; +const char* const Foam::ensightFile::coordinates = "coordinates"; + // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // @@ -85,6 +86,20 @@ Foam::label Foam::ensightFile::subDirWidth() } +bool Foam::ensightFile::isUndef(const UList& field) +{ + for (const scalar& val : field) + { + if (std::isnan(val)) + { + return true; + } + } + + return true; +} + + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::ensightFile::initialize() @@ -153,24 +168,13 @@ Foam::scalar Foam::ensightFile::undefValue(const scalar value) } -Foam::Ostream& Foam::ensightFile::write -( - const char* buf, - std::streamsize count -) -{ - stdStream().write(buf, count); - return *this; -} - - -Foam::Ostream& Foam::ensightFile::write(const char* value) +Foam::Ostream& Foam::ensightFile::writeString(const char* str) { // Output 80 chars, but allocate for trailing nul character // to avoid -Wstringop-truncation warnings/errors. char buf[80+1]; - strncpy(buf, value, 80); // max 80 chars or padded with nul if smaller + strncpy(buf, str, 80); // max 80 chars or padded with nul if smaller if (format() == IOstream::BINARY) { @@ -186,9 +190,38 @@ Foam::Ostream& Foam::ensightFile::write(const char* value) } -Foam::Ostream& Foam::ensightFile::write(const string& value) +Foam::Ostream& Foam::ensightFile::writeString(const std::string& str) { - return write(value.c_str()); + return writeString(str.c_str()); +} + + +Foam::Ostream& Foam::ensightFile::write(const char* str) +{ + return writeString(str); +} + + +Foam::Ostream& Foam::ensightFile::write(const word& str) +{ + return writeString(str); +} + + +Foam::Ostream& Foam::ensightFile::write(const string& str) +{ + return writeString(str); +} + + +Foam::Ostream& Foam::ensightFile::write +( + const char* buf, + std::streamsize count +) +{ + stdStream().write(buf, count); + return *this; } @@ -244,6 +277,14 @@ Foam::Ostream& Foam::ensightFile::write(const scalar value) { float fvalue(value); + // TBD: limit range? + // #if defined(WM_DP) + // if (mag(value) < scalar(floatScalarVSMALL)) + // { + // fvalue = 0; + // } + // #endif + if (format() == IOstream::BINARY) { write @@ -282,17 +323,17 @@ Foam::Ostream& Foam::ensightFile::writeKeyword(const keyType& key) { if (allowUndef_) { - write(string(static_cast(key) + " undef")); + writeString(key + " undef"); newline(); write(undefValue_); newline(); } else { - // ensure we get ensightFile::write(const string&) - write(static_cast(key)); + writeString(key); newline(); } + return *this; } @@ -301,7 +342,7 @@ Foam::Ostream& Foam::ensightFile::writeBinaryHeader() { if (format() == IOstream::BINARY) { - write("C Binary"); + writeString("C Binary"); } return *this; @@ -314,7 +355,7 @@ Foam::Ostream& Foam::ensightFile::writeBinaryHeader() void Foam::ensightFile::beginPart(const label index) { - write("part"); + writeString("part"); newline(); write(index+1); // Ensight starts with 1 newline(); @@ -323,13 +364,23 @@ void Foam::ensightFile::beginPart(const label index) void Foam::ensightFile::beginParticleCoordinates(const label nparticles) { - write("particle coordinates"); + writeString("particle coordinates"); newline(); write(nparticles, 8); // unusual width newline(); } +void Foam::ensightFile::writeLabels(const UList