ENH: improve ensightWrite handling of moving mesh

- now treat all mesh geometries as moving, since we cannot know
  beforehand if this is the case.
This commit is contained in:
Mark Olesen
2018-05-08 12:41:06 +02:00
parent f99880cbea
commit 5c60cbe34d
8 changed files with 105 additions and 71 deletions

View File

@ -103,14 +103,13 @@ Foam::label Foam::ensightCase::checkTimeset(const labelHashSet& lookup) const
} }
else if (tsTimes.size() == timesUsed_.size()) else if (tsTimes.size() == timesUsed_.size())
{ {
forAllConstIter(Map<scalar>, timesUsed_, iter) forAllConstIters(timesUsed_, iter)
{ {
tsTimes.erase(iter.key()); tsTimes.erase(iter.key());
} }
// OR // OR
// tsTimes -= timesUsed_.toc(); // tsTimes.unsetMany(timesUsed_.toc());
// tsTimes -= timesUsed_;
if (tsTimes.empty()) if (tsTimes.empty())
{ {
@ -489,17 +488,27 @@ void Foam::ensightCase::write() const
const bool staticGeom = (geomTimes_.size() == 1 && geomTimes_.found(-1)); const bool staticGeom = (geomTimes_.size() == 1 && geomTimes_.found(-1));
label tsGeom = staticGeom ? 0 : checkTimeset(geomTimes_); label tsGeom = staticGeom ? 0 : checkTimeset(geomTimes_);
// geometry index, when mesh is not moving but stored under data/XXX/
label meshIndex = -1;
// cloud timeset // cloud timeset
label tsCloud = checkTimeset(cloudTimes_); label tsCloud = checkTimeset(cloudTimes_);
// increment time-sets to the correct indices // Increment time-sets to the correct indices
if (tsGeom < 0) if (tsGeom < 0)
{ {
tsGeom = 2; // next available timeset tsGeom = 2; // Next available timeset
// Saved under data/XXX/geometry, but not actually moving
if (geomTimes_.size() == 1)
{
tsGeom = 0;
meshIndex = *(geomTimes_.begin());
}
} }
if (tsCloud < 0) if (tsCloud < 0)
{ {
tsCloud = tsGeom + 1; // next available timeset tsCloud = 1 + std::max(1, tsGeom); // Next available timeset
} }
writeHeader(); writeHeader();
@ -521,27 +530,34 @@ void Foam::ensightCase::write() const
if (staticGeom) if (staticGeom)
{ {
// steady // Steady
*os_ *os_
<< setw(16) << "model:" << setw(16) << "model:"
<< geometryName << geometryName
<< nl; << nl;
} }
else if (meshIndex >= 0)
{
// Not really moving, but stored under data/XXXX/geometry
*os_
<< setw(16) << "model:"
<< (dataDirName/padded(meshIndex)/geometryName).c_str()
<< nl;
}
else if (!geomTimes_.empty()) else if (!geomTimes_.empty())
{ {
// moving // Moving
*os_ *os_
<< word::printf("model: %-9d", tsGeom) // width 16 (no quotes) << word::printf("model: %-9d", tsGeom) // width 16 (no quotes)
<< (dataMask/geometryName).c_str() << (dataMask/geometryName).c_str()
<< nl; << nl;
} }
// clouds and cloud variables // Clouds and cloud variables
const wordList cloudNames = cloudVars_.sortedToc(); const wordList cloudNames(cloudVars_.sortedToc());
forAll(cloudNames, cloudNo)
{
const word& cloudName = cloudNames[cloudNo];
for (const word& cloudName : cloudNames)
{
const fileName masked = const fileName masked =
( (
separateCloud() separateCloud()
@ -568,11 +584,11 @@ void Foam::ensightCase::write() const
} }
// field variables (always use timeset 1) // Field variables (always use timeset 1)
const wordList varNames = variables_.sortedToc(); const wordList varNames(variables_.sortedToc());
forAll(varNames, vari)
for (const word& varName : varNames)
{ {
const word& varName = varNames[vari];
const string& ensType = variables_[varName]; const string& ensType = variables_[varName];
*os_ *os_
@ -588,13 +604,14 @@ void Foam::ensightCase::write() const
} }
// clouds and cloud variables (using cloud timeset) // Clouds and cloud variables (using cloud timeset)
// Write // Write
// as -> "data/********/lagrangian/<cloudName>/positions" // as -> "data/********/lagrangian/<cloudName>/positions"
// or -> "lagrangian/<cloudName>/********/positions" // or -> "lagrangian/<cloudName>/********/positions"
forAll(cloudNames, cloudNo)
label cloudNo = 0;
for (const word& cloudName : cloudNames)
{ {
const word& cloudName = cloudNames[cloudNo];
const fileName masked = const fileName masked =
( (
separateCloud() separateCloud()
@ -603,11 +620,9 @@ void Foam::ensightCase::write() const
); );
const HashTable<string>& vars = cloudVars_[cloudName]; const HashTable<string>& vars = cloudVars_[cloudName];
const wordList tocVars = vars.sortedToc();
forAll(tocVars, vari) for (const word& varName : vars.sortedToc())
{ {
const word& varName = tocVars[vari];
const string& ensType = vars[varName]; const string& ensType = vars[varName];
// prefix variables with 'c' (cloud) and cloud index // prefix variables with 'c' (cloud) and cloud index
@ -619,6 +634,8 @@ void Foam::ensightCase::write() const
<< (masked/varName).c_str() << (masked/varName).c_str()
<< nl; << nl;
} }
++cloudNo;
} }
@ -665,7 +682,7 @@ Foam::ensightCase::newGeometry
if (Pstream::master()) if (Pstream::master())
{ {
// set the path of the ensight file // Set the path of the ensight file
fileName path; fileName path;
if (moving) if (moving)
@ -701,10 +718,10 @@ Foam::ensightCase::newCloud
{ {
output = createCloudFile(cloudName, "positions"); output = createCloudFile(cloudName, "positions");
// tag binary format (just like geometry files) // Tag binary format (just like geometry files)
output().writeBinaryHeader(); output().writeBinaryHeader();
// description // Description
output().write(cloud::prefix/cloudName); output().write(cloud::prefix/cloudName);
output().newline(); output().newline();

View File

@ -148,13 +148,13 @@ private:
) const; ) const;
//- Note geometry being used //- Note the geometry being used
void noteGeometry(const bool moving) const; void noteGeometry(const bool moving) const;
//- Note cloud being used //- Note the cloud being used
void noteCloud(const word& cloudName) const; void noteCloud(const word& cloudName) const;
//- Note cloud/variable being used //- Note the cloud/variable being used
void noteCloud void noteCloud
( (
const word& cloudName, const word& cloudName,
@ -162,7 +162,7 @@ private:
const char* ensightType const char* ensightType
) const; ) const;
//- Note field variable being used //- Note the field variable being used
void noteVariable void noteVariable
( (
const word& varName, const word& varName,
@ -172,7 +172,7 @@ private:
//- Open stream for new data file (on master), using the current index. //- Open stream for new data file (on master), using the current index.
// File is without initial description lines. // File is without initial description lines.
autoPtr<ensightFile> createDataFile(const word&) const; autoPtr<ensightFile> createDataFile(const word& name) const;
//- Open stream for new cloud file (on master). //- Open stream for new cloud file (on master).
// File is without initial description lines. // File is without initial description lines.
@ -211,7 +211,6 @@ public:
); );
//- Destructor //- Destructor
~ensightCase(); ~ensightCase();
@ -223,7 +222,7 @@ public:
//- Reference to the case options //- Reference to the case options
inline const ensightCase::options& option() const; inline const ensightCase::options& option() const;
//- Ascii/Binary file output //- The output file format (ascii/binary)
inline IOstream::streamFormat format() const; inline IOstream::streamFormat format() const;
//- The nominal path to the case file //- The nominal path to the case file
@ -256,12 +255,12 @@ public:
//- Set current index and time for time-set 1. //- Set current index and time for time-set 1.
// Create corresponding sub-directory // Create corresponding sub-directory
// Do not mix between nextTime and setTime in an application. // \note do not mix between nextTime and setTime in an application.
void setTime(const scalar t, const label index); void setTime(const scalar t, const label index);
//- Set current index and time for time-set 1. //- Set current index and time for time-set 1.
// Create corresponding sub-directory // Create corresponding sub-directory
// Do not mix between nextTime and setTime in an application. // \note do not mix between nextTime and setTime in an application.
void setTime(const instant& t, const label index); void setTime(const instant& t, const label index);
@ -305,7 +304,7 @@ public:
inline Ostream& operator()() const; inline Ostream& operator()() const;
//- Print some general information. //- Print some general information.
Ostream& printInfo(Ostream&) const; Ostream& printInfo(Ostream& os) const;
}; };

View File

@ -90,7 +90,6 @@ void Foam::ensightCase::options::width(const label n)
} }
bool Foam::ensightCase::options::overwrite() const bool Foam::ensightCase::options::overwrite() const
{ {
return overwrite_; return overwrite_;

View File

@ -26,8 +26,7 @@ License
#include "cloud.H" #include "cloud.H"
#include "ensightPTraits.H" #include "ensightPTraits.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type> template<class Type>
Foam::autoPtr<Foam::ensightFile> Foam::autoPtr<Foam::ensightFile>
@ -54,7 +53,7 @@ Foam::ensightCase::newData
); );
output().newline(); output().newline();
// note variable for later use // note field variable for later use
noteVariable(varName, ensightPTraits<Type>::typeName); noteVariable(varName, ensightPTraits<Type>::typeName);
} }

View File

@ -335,15 +335,15 @@ void Foam::ensightFile::writeList
const UList<scalar>& field const UList<scalar>& field
) )
{ {
forAll(field, i) for (const scalar& val : field)
{ {
if (std::isnan(field[i])) if (std::isnan(val))
{ {
writeUndef(); writeUndef();
} }
else else
{ {
write(field[i]); write(val);
} }
newline(); newline();
@ -359,15 +359,15 @@ void Foam::ensightFile::writeList
{ {
if (notNull(idList)) if (notNull(idList))
{ {
forAll(idList, i) for (const label idx : idList)
{ {
if (idList[i] >= field.size() || std::isnan(field[idList[i]])) if (idx >= field.size() || std::isnan(field[idx]))
{ {
writeUndef(); writeUndef();
} }
else else
{ {
write(field[idList[i]]); write(field[idx]);
} }
newline(); newline();
@ -375,7 +375,7 @@ void Foam::ensightFile::writeList
} }
else else
{ {
// no idList => perNode // No idList => perNode
writeList(field); writeList(field);
} }
} }

View File

@ -187,30 +187,6 @@ bool Foam::functionObjects::ensightWrite::write()
); );
} }
if (!ensMesh_.valid())
{
ensMesh_.reset(new ensightMesh(mesh_, writeOpts_));
if (ensMesh_().needsUpdate())
{
ensMesh_().correct();
}
// assume static geometry - need to fix later
autoPtr<ensightGeoFile> os = ensCase_().newGeometry(false);
ensMesh_().write(os);
}
else if (ensMesh_().needsUpdate())
{
// appears to have moved
ensMesh_().correct();
autoPtr<ensightGeoFile> os = ensCase_().newGeometry(true);
ensMesh_().write(os);
}
Log << type() << " " << name() << " write: (";
if (consecutive_) if (consecutive_)
{ {
ensCase().nextTime(t.value()); ensCase().nextTime(t.value());
@ -220,6 +196,28 @@ bool Foam::functionObjects::ensightWrite::write()
ensCase().setTime(t.value(), t.timeIndex()); ensCase().setTime(t.value(), t.timeIndex());
} }
bool writeGeom = false;
if (!ensMesh_.valid())
{
writeGeom = true;
ensMesh_.reset(new ensightMesh(mesh_, writeOpts_));
}
if (ensMesh_().needsUpdate())
{
writeGeom = true;
ensMesh_().correct();
}
if (writeGeom)
{
// Treat all geometry as moving, since we do not know a priori
// if the simulation has mesh motion later on.
autoPtr<ensightGeoFile> os = ensCase_().newGeometry(true);
ensMesh_().write(os);
}
Log << type() << " " << name() << " write: (";
wordHashSet candidates(subsetStrings(selectFields_, mesh_.names())); wordHashSet candidates(subsetStrings(selectFields_, mesh_.names()));
DynamicList<word> missing(selectFields_.size()); DynamicList<word> missing(selectFields_.size());
DynamicList<word> ignored(selectFields_.size()); DynamicList<word> ignored(selectFields_.size());

View File

@ -57,6 +57,8 @@ functions
libs ("libsixDoFRigidBodyState.so"); libs ("libsixDoFRigidBodyState.so");
angleFormat degrees; angleFormat degrees;
} }
#include "ensightWrite"
} }
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,20 @@
// -*- C++ -*-
ensightWrite
{
type ensightWrite;
libs ("libutilityFunctionObjects.so");
log true;
fields (U p);
format ascii;
overwrite true;
writeControl writeTime;
consecutive false;
}
// ************************************************************************* //