ENH: expand data mask for foamToEnsight (issue #231)

- Default is a width of 8 characters, but this can be extended up to 31
  characters via the '-width' command-line option.

- Now use a similar structure as foamToEnsightParts for the masking.
  This reduces the clutter within the directory, makes it easier to
  selectively delete some time steps (using shell commands).

- Added in a "time" information data in each sub-directory to
  make it possible to reconstruct the case file with an external
  script.

- Conversion of cloud data should now also work in parallel
  (may need more testing).

- Support binary output for cloud data.

- Better avoidance of illegal ensight variable names.
  But still partially incomplete (due to patch fields).

==================================================
Example of NEW file structure:

    EnSight/verticalChannel.case        # case name
    EnSight/geometry                    # for non-moving geometry

    EnSight/data/                       # time-varying data
    EnSight/data/00000000/
    EnSight/data/00000001/
    ...

  Fields are stored by name within the data/********/ directories:

    EnSight/data/00000001/time          # human-readable time info
    EnSight/data/00000001/U
    EnSight/data/00000001/p
    ...
    EnSight/data/00000001/geometry      # for moving geometry

  Clouds are stored at the next sub-directory level:

    EnSight/data/00000001/lagrangian/<cloudName>/positions
    EnSight/data/00000001/lagrangian/<cloudName>/U
    ...

==================================================
The old structure was significantly more cluttered:

    EnSight/verticalChannel.case
    EnSight/verticalChannel.0000.mesh
    EnSight/verticalChannel.0001.p
    EnSight/verticalChannel.0001.<cloudName>
    EnSight/verticalChannel.0001.<cloudName>.U

==================================================
This commit is contained in:
Mark Olesen
2016-09-13 18:26:00 +02:00
parent d56924624b
commit 9de4a75813
21 changed files with 844 additions and 833 deletions

View File

@ -23,12 +23,12 @@ License
\*---------------------------------------------------------------------------*/
#include "ensightFile.H"
#include "ensightField.H"
#include "fvMesh.H"
#include "volFields.H"
#include "OFstream.H"
#include "IOmanip.H"
#include "itoa.H"
#include "volPointInterpolation.H"
#include "ensightBinaryStream.H"
#include "ensightAsciiStream.H"
@ -121,10 +121,8 @@ volField
// const IOobject& io,
// const fvMesh& mesh,
// const ensightMesh& eMesh,
// const fileName& postProcPath,
// const word& prepend,
// const fileName& dataDir,
// const label timeIndex,
// const bool binary,
// const bool nodeValues,
// Ostream& ensightCaseFile
//)
@ -134,10 +132,8 @@ volField
// (
// volField<typename Container::value_type>(meshSubsetter, fld),
// eMesh,
// postProcPath,
// prepend,
// dataDir,
// timeIndex,
// binary,
// nodeValues,
// ensightCaseFile
// );
@ -175,26 +171,26 @@ void writeField
(
const char* key,
const Field<Type>& vf,
ensightStream& ensightFile
ensightStream& os
)
{
if (returnReduce(vf.size(), sumOp<label>()) > 0)
{
if (Pstream::master())
{
ensightFile.write(key);
os.write(key);
for (direction i=0; i < pTraits<Type>::nComponents; ++i)
{
label cmpt = ensightPTraits<Type>::componentOrder[i];
ensightFile.write(vf.component(cmpt));
os.write(vf.component(cmpt));
for (int slave=1; slave<Pstream::nProcs(); slave++)
{
IPstream fromSlave(Pstream::scheduled, slave);
scalarField slaveData(fromSlave);
ensightFile.write(slaveData);
os.write(slaveData);
}
}
}
@ -220,35 +216,35 @@ bool writePatchField
const label ensightPatchI,
const faceSets& boundaryFaceSet,
const ensightMesh::nFacePrimitives& nfp,
ensightStream& ensightFile
ensightStream& os
)
{
if (nfp.nTris || nfp.nQuads || nfp.nPolys)
{
if (Pstream::master())
{
ensightFile.writePartHeader(ensightPatchI);
os.writePartHeader(ensightPatchI);
}
writeField
(
"tria3",
Field<Type>(pf, boundaryFaceSet.tris),
ensightFile
os
);
writeField
(
"quad4",
Field<Type>(pf, boundaryFaceSet.quads),
ensightFile
os
);
writeField
(
"nsided",
Field<Type>(pf, boundaryFaceSet.polys),
ensightFile
os
);
return true;
@ -267,15 +263,11 @@ void writePatchField
const Field<Type>& pf,
const word& patchName,
const ensightMesh& eMesh,
const fileName& postProcPath,
const word& prepend,
const fileName& dataDir,
const label timeIndex,
const bool binary,
Ostream& ensightCaseFile
)
{
const Time& runTime = eMesh.mesh().time();
const List<faceSets>& boundaryFaceSets = eMesh.boundaryFaceSets();
const wordList& allPatchNames = eMesh.allPatchNames();
const HashTable<ensightMesh::nFacePrimitives>&
@ -295,53 +287,51 @@ void writePatchField
ensightPatchI++;
}
word pfName = patchName + '.' + fieldName;
word timeFile = prepend + itoa(timeIndex);
ensightStream* ensightFilePtr = NULL;
ensightStream* filePtr(nullptr);
if (Pstream::master())
{
// TODO: verify that these are indeed valid ensight variable names
const word varName = patchName + '.' + fieldName;
const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
// the data/ITER subdirectory must exist
mkDir(dataDir/postFileName.path());
if (timeIndex == 0)
{
ensightCaseFile.setf(ios_base::left);
const fileName dirName = dataDir.name()/ensightFile::mask();
ensightCaseFile.setf(ios_base::left);
ensightCaseFile
<< ensightPTraits<Type>::typeName
<< " per element: 1 "
<< setw(15) << pfName
<< (' ' + prepend + "****." + pfName).c_str()
<< ensightPTraits<Type>::typeName << " per "
<< setw(20)
<< "element:"
<< " 1 "
<< setw(15)
<< varName.c_str() << ' '
<< (dirName/varName).c_str()
<< nl;
}
// set the filename of the ensight file
fileName ensightFileName(timeFile + "." + pfName);
if (binary)
if (eMesh.format() == IOstream::BINARY)
{
ensightFilePtr = new ensightBinaryStream
filePtr = new ensightBinaryStream
(
postProcPath/ensightFileName,
runTime
dataDir/postFileName
);
}
else
{
ensightFilePtr = new ensightAsciiStream
filePtr = new ensightAsciiStream
(
postProcPath/ensightFileName,
runTime
dataDir/postFileName
);
}
filePtr->write(ensightPTraits<Type>::typeName);
}
ensightStream& ensightFile = *ensightFilePtr;
if (Pstream::master())
{
ensightFile.write(ensightPTraits<Type>::typeName);
}
ensightStream& os = *filePtr;
if (patchi >= 0)
{
@ -352,7 +342,7 @@ void writePatchField
ensightPatchI,
boundaryFaceSets[patchi],
nPatchPrims.find(patchName)(),
ensightFile
os
);
}
else
@ -366,13 +356,13 @@ void writePatchField
ensightPatchI,
nullFaceSets,
nPatchPrims.find(patchName)(),
ensightFile
os
);
}
if (Pstream::master())
if (filePtr) // on master only
{
delete ensightFilePtr;
delete filePtr;
}
}
@ -382,19 +372,14 @@ void ensightField
(
const GeometricField<Type, fvPatchField, volMesh>& vf,
const ensightMesh& eMesh,
const fileName& postProcPath,
const word& prepend,
const fileName& dataDir,
const label timeIndex,
const bool binary,
Ostream& ensightCaseFile
)
{
Info<< "Converting field " << vf.name() << endl;
word timeFile = prepend + itoa(timeIndex);
Info<< ' ' << vf.name();
const fvMesh& mesh = eMesh.mesh();
const Time& runTime = mesh.time();
const cellSets& meshCellSets = eMesh.meshCellSets();
const List<faceSets>& boundaryFaceSets = eMesh.boundaryFaceSets();
@ -414,48 +399,48 @@ void ensightField
const labelList& hexes = meshCellSets.hexes;
const labelList& polys = meshCellSets.polys;
ensightStream* ensightFilePtr = NULL;
ensightStream* filePtr(nullptr);
if (Pstream::master())
{
// set the filename of the ensight file
fileName ensightFileName(timeFile + "." + vf.name());
const ensight::VarName varName(vf.name());
const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
if (binary)
// the data/ITER subdirectory must exist
mkDir(dataDir/postFileName.path());
if (timeIndex == 0)
{
ensightFilePtr = new ensightBinaryStream
const fileName dirName = dataDir.name()/ensightFile::mask();
ensightCaseFile.setf(ios_base::left);
ensightCaseFile
<< ensightPTraits<Type>::typeName
<< " per element: 1 "
<< setw(15)
<< varName.c_str() << ' '
<< (dirName/varName).c_str()
<< nl;
}
if (eMesh.format() == IOstream::BINARY)
{
filePtr = new ensightBinaryStream
(
postProcPath/ensightFileName,
runTime
dataDir/postFileName
);
}
else
{
ensightFilePtr = new ensightAsciiStream
filePtr = new ensightAsciiStream
(
postProcPath/ensightFileName,
runTime
dataDir/postFileName
);
}
filePtr->write(ensightPTraits<Type>::typeName);
}
ensightStream& ensightFile = *ensightFilePtr;
if (Pstream::master())
{
if (timeIndex == 0)
{
ensightCaseFile.setf(ios_base::left);
ensightCaseFile
<< ensightPTraits<Type>::typeName
<< " per element: 1 "
<< setw(15) << vf.name()
<< (' ' + prepend + "****." + vf.name()).c_str()
<< nl;
}
ensightFile.write(ensightPTraits<Type>::typeName);
}
ensightStream& os = *filePtr;
if (patchNames.empty())
{
@ -463,42 +448,42 @@ void ensightField
if (Pstream::master())
{
ensightFile.writePartHeader(1);
os.writePartHeader(1);
}
writeField
(
"hexa8",
map(vf, hexes, wedges),
ensightFile
os
);
writeField
(
"penta6",
Field<Type>(vf, prisms),
ensightFile
os
);
writeField
(
"pyramid5",
Field<Type>(vf, pyrs),
ensightFile
os
);
writeField
(
"tetra4",
Field<Type>(vf, tets),
ensightFile
os
);
writeField
(
"nfaced",
Field<Type>(vf, polys),
ensightFile
os
);
}
@ -521,7 +506,7 @@ void ensightField
ensightPatchI,
boundaryFaceSets[patchi],
nPatchPrims.find(patchName)(),
ensightFile
os
)
)
{
@ -546,8 +531,7 @@ void ensightField
eMesh.barrier();
label zoneID = mesh.faceZones().findZoneID(faceZoneName);
const label zoneID = mesh.faceZones().findZoneID(faceZoneName);
const faceZone& fz = mesh.faceZones()[zoneID];
// Prepare data to write
@ -595,7 +579,7 @@ void ensightField
ensightPatchI,
faceZoneFaceSets[zoneID],
nFaceZonePrims.find(faceZoneName)(),
ensightFile
os
)
)
{
@ -603,9 +587,10 @@ void ensightField
}
}
}
if (Pstream::master())
if (filePtr) // on master only
{
delete ensightFilePtr;
delete filePtr;
}
}
@ -615,65 +600,63 @@ void ensightPointField
(
const GeometricField<Type, pointPatchField, pointMesh>& pf,
const ensightMesh& eMesh,
const fileName& postProcPath,
const word& prepend,
const fileName& dataDir,
const label timeIndex,
const bool binary,
Ostream& ensightCaseFile
)
{
Info<< "Converting field " << pf.name() << endl;
word timeFile = prepend + itoa(timeIndex);
Info<< ' ' << pf.name();
const fvMesh& mesh = eMesh.mesh();
const wordList& allPatchNames = eMesh.allPatchNames();
const wordHashSet& patchNames = eMesh.patchNames();
const wordHashSet& faceZoneNames = eMesh.faceZoneNames();
ensightStream* ensightFilePtr = NULL;
ensightStream* filePtr(nullptr);
if (Pstream::master())
{
// set the filename of the ensight file
fileName ensightFileName(timeFile + "." + pf.name());
const ensight::VarName varName(pf.name());
const fileName postFileName = ensightFile::subDir(timeIndex)/varName;
if (binary)
// the data/ITER subdirectory must exist
mkDir(dataDir/postFileName.path());
if (timeIndex == 0)
{
ensightFilePtr = new ensightBinaryStream
const fileName dirName = dataDir.name()/ensightFile::mask();
ensightCaseFile.setf(ios_base::left);
ensightCaseFile
<< ensightPTraits<Type>::typeName
<< " per "
<< setw(20)
<< " node:"
<< " 1 "
<< setw(15)
<< varName.c_str() << ' '
<< (dirName/varName).c_str()
<< nl;
}
if (eMesh.format() == IOstream::BINARY)
{
filePtr = new ensightBinaryStream
(
postProcPath/ensightFileName,
mesh.time()
dataDir/postFileName
);
}
else
{
ensightFilePtr = new ensightAsciiStream
filePtr = new ensightAsciiStream
(
postProcPath/ensightFileName,
mesh.time()
dataDir/postFileName
);
}
filePtr->write(ensightPTraits<Type>::typeName);
}
ensightStream& ensightFile = *ensightFilePtr;
if (Pstream::master())
{
if (timeIndex == 0)
{
ensightCaseFile.setf(ios_base::left);
ensightCaseFile
<< ensightPTraits<Type>::typeName
<< " per node: 1 "
<< setw(15) << pf.name()
<< (' ' + prepend + "****." + pf.name()).c_str()
<< nl;
}
ensightFile.write(ensightPTraits<Type>::typeName);
}
ensightStream& os = *filePtr;
if (eMesh.patchNames().empty())
{
@ -681,14 +664,14 @@ void ensightPointField
if (Pstream::master())
{
ensightFile.writePartHeader(1);
os.writePartHeader(1);
}
writeField
(
"coordinates",
Field<Type>(pf.internalField(), eMesh.uniquePointMap()),
ensightFile
os
);
}
@ -704,11 +687,8 @@ void ensightPointField
if (patchNames.empty() || patchNames.found(patchName))
{
const fvPatch& p = mesh.boundary()[patchi];
if
(
returnReduce(p.size(), sumOp<label>())
> 0
)
if (returnReduce(p.size(), sumOp<label>()) > 0)
{
// Renumber the patch points/faces into unique points
labelList pointToGlobal;
@ -724,14 +704,14 @@ void ensightPointField
if (Pstream::master())
{
ensightFile.writePartHeader(ensightPatchI);
os.writePartHeader(ensightPatchI);
}
writeField
(
"coordinates",
Field<Type>(pf.internalField(), uniqueMeshPointLabels),
ensightFile
os
);
ensightPatchI++;
@ -748,8 +728,7 @@ void ensightPointField
eMesh.barrier();
label zoneID = mesh.faceZones().findZoneID(faceZoneName);
const label zoneID = mesh.faceZones().findZoneID(faceZoneName);
const faceZone& fz = mesh.faceZones()[zoneID];
if (returnReduce(fz().nPoints(), sumOp<label>()) > 0)
@ -768,7 +747,7 @@ void ensightPointField
if (Pstream::master())
{
ensightFile.writePartHeader(ensightPatchI);
os.writePartHeader(ensightPatchI);
}
writeField
@ -779,7 +758,7 @@ void ensightPointField
pf.internalField(),
uniqueMeshPointLabels
),
ensightFile
os
);
ensightPatchI++;
@ -787,9 +766,9 @@ void ensightPointField
}
}
if (Pstream::master())
if (filePtr) // on master only
{
delete ensightFilePtr;
delete filePtr;
}
}
@ -799,10 +778,8 @@ void ensightField
(
const GeometricField<Type, fvPatchField, volMesh>& vf,
const ensightMesh& eMesh,
const fileName& postProcPath,
const word& prepend,
const fileName& dataDir,
const label timeIndex,
const bool binary,
const bool nodeValues,
Ostream& ensightCaseFile
)
@ -819,10 +796,8 @@ void ensightField
(
pfld,
eMesh,
postProcPath,
prepend,
dataDir,
timeIndex,
binary,
ensightCaseFile
);
}
@ -832,10 +807,8 @@ void ensightField
(
vf,
eMesh,
postProcPath,
prepend,
dataDir,
timeIndex,
binary,
ensightCaseFile
);
}