From 7d203443c3450eedd73c5f709e5f0bf510f228bd Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Wed, 9 Sep 2020 09:50:09 +0200 Subject: [PATCH] ENH: refactor surface writer collated time management (#1600) - abstracted out from ensight surface writer for potential reuse by other surface writers. --- src/surfMesh/Make/files | 1 + .../writers/caching/surfaceWriterCaching.C | 275 +++++++++++++ .../writers/caching/surfaceWriterCaching.H | 163 ++++++++ .../writers/ensight/ensightSurfaceWriter.C | 14 +- .../writers/ensight/ensightSurfaceWriter.H | 24 +- .../ensight/ensightSurfaceWriterCollated.C | 361 +++++------------- .../ensight/ensightSurfaceWriterUncollated.C | 10 +- 7 files changed, 560 insertions(+), 288 deletions(-) create mode 100644 src/surfMesh/writers/caching/surfaceWriterCaching.C create mode 100644 src/surfMesh/writers/caching/surfaceWriterCaching.H diff --git a/src/surfMesh/Make/files b/src/surfMesh/Make/files index 0fe30852b3b..7c68022eb8b 100644 --- a/src/surfMesh/Make/files +++ b/src/surfMesh/Make/files @@ -62,6 +62,7 @@ triSurface/patches/surfacePatch.C writers = writers $(writers)/surfaceWriter.C +$(writers)/caching/surfaceWriterCaching.C $(writers)/boundaryData/boundaryDataSurfaceWriter.C $(writers)/ensight/ensightSurfaceWriter.C $(writers)/foam/foamSurfaceWriter.C diff --git a/src/surfMesh/writers/caching/surfaceWriterCaching.C b/src/surfMesh/writers/caching/surfaceWriterCaching.C new file mode 100644 index 00000000000..b4f5f156401 --- /dev/null +++ b/src/surfMesh/writers/caching/surfaceWriterCaching.C @@ -0,0 +1,275 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "surfaceWriterCaching.H" +#include "ListOps.H" +#include "Fstream.H" + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Compare time values with tolerance +static const equalOp<scalar> equalTimes(ROOTSMALL); + +// Use ListOps findLower (with tolerance), to find the location of the next +// time-related index. +// The returned index is always 0 or larger (no negative values). +static label findTimeIndex(const UList<scalar>& list, const scalar val) +{ + label idx = + findLower + ( + list, + val, + 0, + [](const scalar a, const scalar b) + { + return (a < b) && (Foam::mag(b - a) > ROOTSMALL); + } + ); + + if (idx < 0 || !equalTimes(list[idx], val)) + { + ++idx; + } + + return idx; +} + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::surfaceWriters::writerCaching::writerCaching(const word& cacheFileName) +: + dictName_(cacheFileName) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::dictionary& Foam::surfaceWriters::writerCaching::fieldsDict() const +{ + const dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL); + + if (!dictptr) + { + dictptr = &dictionary::null; + } + + return *dictptr; +} + + +Foam::dictionary& Foam::surfaceWriters::writerCaching::fieldDict +( + const word& fieldName +) +{ + return + cache_ + .subDictOrAdd("fields", keyType::LITERAL) + .subDictOrAdd(fieldName, keyType::LITERAL); +} + + +bool Foam::surfaceWriters::writerCaching::remove(const word& fieldName) +{ + dictionary* dictptr = cache_.findDict("fields", keyType::LITERAL); + + if (dictptr) + { + return dictptr->remove(fieldName); + } + + return false; +} + + +void Foam::surfaceWriters::writerCaching::clear() +{ + times_.clear(); + geoms_.clear(); + cache_.clear(); +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::surfaceWriters::writerCaching::readPreviousTimes +( + const fileName& dictFile, + const scalar timeValue +) +{ + // In 1906 and earlier, the fieldsDict contained "meshes" and "times" + // entries, each with their own time values. + // This makes it more difficult to define the exact correspondence + // between geometry intervals and times. + // + // Now track the used geometry intervals as a bitSet. + + + // Only called from master + label timeIndex = 0; + cache_.clear(); + + IFstream is(dictFile); + + if (is.good() && cache_.read(is)) + { + geoms_.clear(); + + cache_.readIfPresent("times", times_); + timeIndex = findTimeIndex(times_, timeValue); + + labelList geomIndices; + scalarList meshTimes; + + if (cache_.readIfPresent("geometry", geomIndices)) + { + // Convert indices to bitSet entries + geoms_.set(geomIndices); + } + else if (cache_.readIfPresent("meshes", meshTimes)) + { + WarningInFunction + << nl + << "Setting geometry timeset information from time values" + << " (cache from an older OpenFOAM version)." << nl + << "This may not be fully reliable." << nl + << nl; + + for (const scalar meshTime : meshTimes) + { + const label geomIndex = findTimeIndex(times_, meshTime); + geoms_.set(geomIndex); + } + } + + // Make length consistent with time information. + // We read/write the indices instead of simply dumping the bitSet. + // This makes the contents more human readable. + geoms_.resize(times_.size()); + } + + return timeIndex; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::surfaceWriters::writerCaching::update +( + const fileName& baseDir, + const scalar timeValue, + const bool geomChanged, + const word& fieldName, + const word& fieldType, + const word& varName +) +{ + const fileName dictFile(baseDir/dictName_); + + bool stateChanged = false; + + const label timeIndex = + ( + times_.empty() + ? readPreviousTimes(dictFile, timeValue) + : findTimeIndex(times_, timeValue) + ); + + + // Update stored times list and geometry index + + if (timeIndex < geoms_.size()-1) + { + // Clear old content when shrinking + geoms_.unset(timeIndex); + } + + // Extend or truncate list + geoms_.resize(timeIndex+1); + times_.resize(timeIndex+1, VGREAT); + + if (!equalTimes(times_[timeIndex], timeValue)) + { + stateChanged = true; + times_[timeIndex] = timeValue; + } + + if (geomChanged) + { + stateChanged = true; + geoms_.set(timeIndex); + } + + + // Update time/geometry information in dictionary + cache_.set("times", times_); + cache_.set("geometry", geoms_.sortedToc()); + + // Debugging, or if needed for older versions: + //// cache_.set + //// ( + //// "meshes", + //// IndirectList<scalar>(times_, geoms_.sortedToc()) + //// ); + + // Add field information to dictionary + dictionary& dict = fieldDict(fieldName); + + if (dict.empty()) + { + stateChanged = true; + + dict.set("type", fieldType); + if (!varName.empty() && varName != fieldName) + { + // Use variable name, if it differs from fieldName + dict.set("name", varName); + } + } + + if (stateChanged) + { + OFstream os(dictFile); + os << "// State file for surface writer output" << nl << nl; + cache_.write(os, false); + + os << nl << "// End" << nl; + } + + return stateChanged; +} + + +// ************************************************************************* // diff --git a/src/surfMesh/writers/caching/surfaceWriterCaching.H b/src/surfMesh/writers/caching/surfaceWriterCaching.H new file mode 100644 index 00000000000..3ad22142b00 --- /dev/null +++ b/src/surfMesh/writers/caching/surfaceWriterCaching.H @@ -0,0 +1,163 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2016-2020 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::surfaceWriters::writerCaching + +Description + Information for surface writers with collated times. + + The class maintains an internal list of the known times + as well as a file-cached version with the field information. + The information is used for restarts. + +SourceFiles + surfaceWriterCaching.C + +\*---------------------------------------------------------------------------*/ + +#ifndef surfaceWriters_writerCaching_H +#define surfaceWriters_writerCaching_H + +#include "bitSet.H" +#include "dictionary.H" +#include "scalarList.H" +#include "DynamicList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace surfaceWriters +{ + +/*---------------------------------------------------------------------------*\ + Class writerCaching Declaration +\*---------------------------------------------------------------------------*/ + +class writerCaching +{ + // Private Data + + //- Cache dictionary file name + word dictName_; + + //- The output times + DynamicList<scalar> times_; + + //- Indices in times_ when geometry (mesh) has been written + bitSet geoms_; + + //- Cached information for geometry, times, fields + dictionary cache_; + + + // Private Member Functions + + //- Read time information from dictFileName. + // Returns timeIndex corresponding to timeValue + label readPreviousTimes + ( + const fileName& dictFile, + const scalar timeValue + ); + + //- Get or create a sub-dictionary for named field + dictionary& fieldDict(const word& fieldName); + + //- Remove named field + bool remove(const word& fieldName); + + +public: + + // Constructors + + //- Construct with specified cache name + explicit writerCaching(const word& cacheFileName); + + + //- Destructor + virtual ~writerCaching() = default; + + + // Member Functions + + //- The output times for fields + const scalarList& times() const + { + return times_; + } + + //- Indices in times() when geometry (mesh) has been written + const bitSet& geometries() const + { + return geoms_; + } + + //- The most current time index + label latestTimeIndex() const + { + return max(0, times_.size()-1); + } + + //- The most current geometry index + label latestGeomIndex() const + { + return max(0, geoms_.find_last()); + } + + //- Get or create the 'fields' information dictionary. + const dictionary& fieldsDict() const; + + //- Clear all values + void clear(); + + //- Update time/geometry information and file cache. + //- This routine should only be called from the master process + // \return True if there is a state change, which is either a + // geometry change or a new time interval + bool update + ( + const fileName& baseDir, //!< Directory containing the cache file + const scalar timeValue, //!< The current time value + const bool geomChanged, //!< Monitored geometry changed + const word& fieldName, //!< Name of field + const word& fieldType, //!< Type of field + const word& varName = word::null //!< Alternative field name + ); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace surfaceWriters +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C index 63da8297517..e90c9d5f481 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriter.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriter.C @@ -56,7 +56,7 @@ void Foam::surfaceWriters::ensightWriter::printTimeset ( OSstream& os, const label ts, - const scalar& timeValue + const scalar timeValue ) { os @@ -176,7 +176,8 @@ Foam::surfaceWriters::ensightWriter::ensightWriter() : surfaceWriter(), writeFormat_(IOstream::ASCII), - collateTimes_(true) + collateTimes_(true), + caching_("fieldsDict") // Historic name {} @@ -190,7 +191,8 @@ Foam::surfaceWriters::ensightWriter::ensightWriter ( IOstreamOption::formatEnum("format", options, IOstream::ASCII) ), - collateTimes_(options.getOrDefault("collateTimes", true)) + collateTimes_(options.getOrDefault("collateTimes", true)), + caching_("fieldsDict") // Historic name {} @@ -227,15 +229,13 @@ Foam::surfaceWriters::ensightWriter::ensightWriter void Foam::surfaceWriters::ensightWriter::close() { - times_.clear(); - meshes_.clear(); - cache_.clear(); + caching_.clear(); surfaceWriter::close(); } // Note that ensight does supports geometry in a separate file, -// but setting this true leaves mesh files in the wrong places +// but setting this true leaves geometry files in the wrong places // (when there are fields). // // Make this false to let the field writers take back control diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriter.H b/src/surfMesh/writers/ensight/ensightSurfaceWriter.H index 9b95072db2a..4c4c97855e0 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-2019 OpenCFD Ltd. + Copyright (C) 2015-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -61,8 +61,7 @@ SourceFiles #define ensightSurfaceWriter_H #include "surfaceWriter.H" -#include "bitSet.H" -#include "DynamicList.H" +#include "surfaceWriterCaching.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -87,27 +86,12 @@ class ensightWriter //- Collate times (default: true) bool collateTimes_; - //- The collated output times - DynamicList<scalar> times_; - - //- Indices in times_ when geometry (mesh) has been written (collated) - bitSet meshes_; - //- Cached information for times, geometry, fields (collated) - dictionary cache_; + writerCaching caching_; // Private Member Functions - //- Read time information from baseDir / dictName. - // Returns timeIndex corresponding to timeValue - label readPreviousTimes - ( - const fileName& baseDir, - const word& dictName, - const scalar& timeValue - ); - //- The geometry can be any of the following: // // 0: constant/static @@ -120,7 +104,7 @@ class ensightWriter ( OSstream& os, const label ts, - const scalar& timeValue + const scalar timeValue ); //- Print time-set for ensight case file, with N times and 0-based diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C index 4dc8fdeeda3..010195a4e75 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterCollated.C @@ -26,122 +26,20 @@ License \*---------------------------------------------------------------------------*/ -// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // - -namespace Foam -{ - -// Compare time values with tolerance -static const equalOp<scalar> equalTimes(ROOTSMALL); - -// Use ListOps findLower (with tolerance), to find the location of the next -// time-related index. -// The returned index is always 0 or larger (no negative values). -static label findTimeIndex(const UList<scalar>& list, const scalar val) -{ - label idx = - findLower - ( - list, - val, - 0, - [](const scalar a, const scalar b) - { - return (a < b) && (Foam::mag(b - a) > ROOTSMALL); - } - ); - - if (idx < 0 || !equalTimes(list[idx], val)) - { - ++idx; - } - - return idx; -} - -} // End namespace Foam - - // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -Foam::label Foam::surfaceWriters::ensightWriter::readPreviousTimes -( - const fileName& baseDir, - const word& dictName, - const scalar& timeValue -) -{ - // In 1906 and earlier, the fieldsDict contained "meshes" and "times" - // entries, each with their own time values. - // This makes it more difficult to define the exact correspondence - // between geometry intervals and times. - // - // We now instead track used geometry intervals as a bitSet. - - - // Only called from master - - label timeIndex = 0; - - labelList geomIndices; - scalarList meshTimes; - - cache_.clear(); - - const fileName dictFile(baseDir/dictName); - - if (isFile(dictFile)) - { - IFstream is(dictFile); - - if (is.good() && cache_.read(is)) - { - meshes_.clear(); - - cache_.readIfPresent("times", times_); - timeIndex = findTimeIndex(times_, timeValue); - - if (cache_.readIfPresent("geometry", geomIndices)) - { - // Convert indices to bitSet entries - meshes_.set(geomIndices); - } - else if (cache_.readIfPresent("meshes", meshTimes)) - { - WarningInFunction - << nl - << "Setting geometry timeset information from time values" - << " (fieldsDict from an older OpenFOAM version)." << nl - << "This may not be fully reliable." << nl - << nl; - - for (const scalar& meshTime : meshTimes) - { - const label meshIndex = findTimeIndex(times_, meshTime); - meshes_.set(meshIndex); - } - } - - // Make length consistent with time information. - // We read/write the indices instead of simply dumping the bitSet. - // This makes the contents more human readable. - meshes_.resize(times_.size()); - } - } - - return timeIndex; -} - - int Foam::surfaceWriters::ensightWriter::geometryTimeset() const { - if (meshes_.count() <= 1) + const scalarList& times = caching_.times(); + const bitSet& geoms = caching_.geometries(); + + if (geoms.count() <= 1) { // Static return 0; } - if (meshes_.size() == times_.size() && meshes_.all()) + if (geoms.size() == times.size() && geoms.all()) { // Geometry changing is the same as fields changing return 1; @@ -158,7 +56,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated() { // Collated? // ======== - // Geometry: rootdir/surfaceName/surfaceName.case + // CaseFile: rootdir/surfaceName/surfaceName.case // Geometry: rootdir/surfaceName/surfaceName.mesh wroteGeom_ = true; @@ -173,6 +71,9 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated const Field<Type>& localValues ) { + // Geometry changed since last output? Capture now before any merging. + const bool geomChanged = (!upToDate_); + checkOpen(); const ensight::FileName surfName(outputPath_.name()); @@ -181,7 +82,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated // Collated // ======== - // Geometry: rootdir/surfaceName/surfaceName.case + // CaseFile: rootdir/surfaceName/surfaceName.case // Geometry: rootdir/surfaceName/data/<index>/geometry // Field: rootdir/surfaceName/data/<index>/field @@ -210,11 +111,8 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated } - // Mesh changed since last output? Do before any merging. - const bool meshChanged = (!upToDate_); - - // geometry merge() implicit + // Implicit geometry merge() tmp<Field<Type>> tfield = mergeField(localValues); const meshedSurf& surf = surface(); @@ -226,42 +124,21 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated mkDir(outputFile.path()); } - bool stateChanged = meshChanged; - - const label timeIndex = - ( - times_.empty() - ? readPreviousTimes(baseDir, "fieldsDict", timeValue) - : findTimeIndex(times_, timeValue) - ); - - - // Update stored times list and mesh index - - if (timeIndex < meshes_.size()-1) - { - // Clear old content when shrinking - meshes_.unset(timeIndex); - } - - // Extend or truncate list - meshes_.resize(timeIndex+1); - times_.resize(timeIndex+1, VGREAT); - - if (meshChanged) - { - meshes_.set(timeIndex); - } - - if (!equalTimes(times_[timeIndex], timeValue)) - { - stateChanged = true; - times_[timeIndex] = timeValue; - } + const bool stateChanged = + caching_.update + ( + baseDir, + timeValue, + geomChanged, + fieldName, + ensightPTraits<Type>::typeName, + varName + ); - // The most current geometry index - const label geomIndex(max(0, meshes_.find_last())); + // The most current time and geometry indices + const label timeIndex = caching_.latestTimeIndex(); + const label geomIndex = caching_.latestGeomIndex(); // This will be used for the name of a static geometry, @@ -273,126 +150,97 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated // Do case file + if (stateChanged) { - // Add time information to dictionary - cache_.set("geometry", meshes_.sortedToc()); - cache_.set("times", times_); - - // Debugging, or if needed for older versions: - //// cache_.set - //// ( - //// "meshes", - //// IndirectList<scalar>(times_, meshes_.sortedToc()) - //// ); - - // Add field information to dictionary - dictionary& fieldsDict = cache_.subDictOrAdd("fields"); - dictionary& fieldDict = fieldsDict.subDictOrAdd(fieldName); - - if (fieldDict.empty()) + OFstream osCase(outputFile, IOstream::ASCII); + + // Format options + osCase.setf(ios_base::left); + osCase.setf(ios_base::scientific, ios_base::floatfield); + osCase.precision(5); + + if (verbose_) { - fieldDict.set("type", ensightPTraits<Type>::typeName); - fieldDict.set("name", varName); // ensight variable name - stateChanged = true; + Info<< "Writing case file to " << osCase.name() << endl; } + // The geometry can be any of the following: + // 0: constant/static + // 1: moving, with the same frequency as the data + // 2: moving, with different frequency as the data - if (stateChanged) - { - if (verbose_) - { - Info<< "Writing state file to fieldsDict" << endl; - } - { - OFstream os(baseDir/"fieldsDict"); - os << "// Summary of Ensight fields, times" << nl << nl; - cache_.write(os, false); - } - - OFstream osCase(outputFile, IOstream::ASCII); - - // Format options - osCase.setf(ios_base::left); - osCase.setf(ios_base::scientific, ios_base::floatfield); - osCase.precision(5); - - if (verbose_) - { - Info<< "Writing case file to " << osCase.name() << endl; - } - - // The geometry can be any of the following: - // 0: constant/static - // 1: moving, with the same frequency as the data - // 2: moving, with different frequency as the data - - const label tsGeom = geometryTimeset(); + const label tsGeom = geometryTimeset(); + + osCase + << "FORMAT" << nl + << "type: ensight gold" << nl + << nl + << "GEOMETRY" << nl; - osCase - << "FORMAT" << nl - << "type: ensight gold" << nl - << nl - << "GEOMETRY" << nl; - - - if (tsGeom) - { - // moving - osCase - << "model: " << tsGeom << " " // time-set (1|2) - << mask << geometryName.name() << nl; - } - else - { - // steady - osCase - << "model: " - << geometryName.c_str() << nl; - } + if (tsGeom) + { + // moving + osCase + << "model: " << tsGeom << " " // time-set (1|2) + << mask << geometryName.name() << nl; + } + else + { + // steady osCase - << nl - << "VARIABLE" << nl; + << "model: " + << geometryName.c_str() << nl; + } + osCase + << nl + << "VARIABLE" << nl; - for (const entry& dEntry : fieldsDict) - { - const dictionary& subDict = dEntry.dict(); - const word fieldType(subDict.get<word>("type")); - const word varName + for (const entry& dEntry : caching_.fieldsDict()) + { + const dictionary& subDict = dEntry.dict(); + + const word varType(subDict.get<word>("type")); + const word varName + ( + subDict.getOrDefault<word> ( - subDict.getOrDefault<word> - ( - "name", - dEntry.keyword() // fieldName as fallback - ) - ); - - osCase - << fieldType - << - ( - this->isPointData() - ? " per node: 1 " // time-set 1 - : " per element: 1 " // time-set 1 - ) - << setw(15) << varName << ' ' - << mask << varName << nl; - } + "name", + dEntry.keyword() // fieldName as fallback + ) + ); osCase - << nl - << "TIME" << nl; + << varType + << + ( + this->isPointData() + ? " per node: 1 " // time-set 1 + : " per element: 1 " // time-set 1 + ) + << setw(15) << varName << ' ' + << mask << varName << nl; + } - printTimeset(osCase, 1, times_); - if (tsGeom == 2) - { - printTimeset(osCase, 2, times_, meshes_); - } + osCase + << nl + << "TIME" << nl; - osCase << "# end" << nl; + printTimeset(osCase, 1, caching_.times()); + if (tsGeom == 2) + { + printTimeset + ( + osCase, + tsGeom, + caching_.times(), + caching_.geometries() + ); } + + osCase << "# end" << nl; } @@ -403,27 +251,28 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeCollated mkDir(dataDir); - const fileName meshFile(baseDir/geometryName); + const fileName geomFile(baseDir/geometryName); // Ensight Geometry ensightOutputSurface part ( surf.points(), surf.faces(), - meshFile.name() + geomFile.name() ); - if (!exists(meshFile)) + if (!exists(geomFile)) { if (verbose_) { - Info<< "Writing mesh file to " << meshFile.name() << endl; + Info<< "Writing geometry to " << geomFile.name() << endl; } + // Two-argument form for path-name to avoid validating base-dir ensightGeoFile osGeom ( - meshFile.path(), - meshFile.name(), + geomFile.path(), + geomFile.name(), writeFormat_ ); part.write(osGeom); // serial diff --git a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C index 6a129ca0230..23ac92e38c4 100644 --- a/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C +++ b/src/surfMesh/writers/ensight/ensightSurfaceWriterUncollated.C @@ -37,7 +37,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated() // Uncollated // ========== - // Geometry: rootdir/<TIME>/surfaceName.case + // CaseFile: rootdir/<TIME>/surfaceName.case // Geometry: rootdir/<TIME>/surfaceName.00000000.mesh fileName outputDir; @@ -85,7 +85,7 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated() << nl << "TIME" << nl; - printTimeset(osCase, 1, 0.0); + printTimeset(osCase, 1, scalar(0)); ensightOutputSurface part ( @@ -116,9 +116,9 @@ Foam::fileName Foam::surfaceWriters::ensightWriter::writeUncollated // Uncollated // ========== - // geometry: rootdir/time/<field>/surfaceName.case - // geometry: rootdir/time/<field>/surfaceName.<index>.mesh - // field: rootdir/time/<field>/surfaceName.<index>.<field> + // CaseFile: rootdir/time/<field>/surfaceName.case + // Geometry: rootdir/time/<field>/surfaceName.<index>.mesh + // Field: rootdir/time/<field>/surfaceName.<index>.<field> // Variable name as sub-directory for results. Eg, // - VAR1/SURF1.case -- GitLab