Commit 1452cc08 authored by Mark Olesen's avatar Mark Olesen
Browse files

BUG: ensight writers not catching special reserved characters (fixes #122)

- most notably the '%' which is used as a separator in places
  caused problems.

EHN: only use valid ensight file/variable names for writers

- fixed:   foamToEnsightParts, ensightSurfaceWriter
- pending: foamToEnsight

BUG: no geometry written for foamToEnsightParts with moving mesh (fixes #142)

- an incorrect path was causing the issue
parent 9066ecfd
Test-ensightFile.C
EXE = $(FOAM_USER_APPBIN)/Test-ensightFile
EXE_INC = \
-I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lconversion \
-lfileFormats \
-lmeshTools
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Application
Test-ensightFile
Description
check cleanup of ensight file and variable names
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "ensightFileName.H"
#include "ensightVarName.H"
#include "IOstreams.H"
using namespace Foam;
void printCleaning(const fileName& pathName)
{
Info<< "input = " << pathName << nl;
Info<< "file = " << ensight::FileName(pathName) << nl;
Info<< "var = " << ensight::VarName(pathName) << nl;
Info<< nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
argList::validArgs.insert("fileName .. fileNameN");
argList args(argc, argv, false, true);
if (args.size() <= 1 && args.options().empty())
{
args.printUsage();
}
fileName pathName;
for (label argI=1; argI < args.size(); ++argI)
{
pathName = args[argI];
printCleaning(pathName);
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //
// check for "points" in all of the result directories
// - could restrict to the selected times
bool hasMovingMesh = false;
if (timeDirs.size() > 1)
......
......@@ -8,7 +8,7 @@ if (timeDirs[0].value() < 0)
}
// the case file is always ASCII
Info << "write case: " << caseFileName.c_str() << endl;
Info<< "write case: " << caseFileName.c_str() << endl;
OFstream caseFile(ensightDir/caseFileName, IOstream::ASCII);
caseFile.setf(ios_base::left);
......@@ -20,7 +20,9 @@ caseFile
<< "FORMAT" << nl
<< setw(16) << "type:" << "ensight gold" << nl << nl;
if (hasMovingMesh)
// time-set for geometries
// TODO: split off into separate time-set, but need to verify ensight spec
if (geometryTimesUsed.size())
{
caseFile
<< "GEOMETRY" << nl
......@@ -43,7 +45,7 @@ forAllConstIter(HashTable<HashTable<word>>, cloudFields, cloudIter)
caseFile
<< setw(16) << "measured: 2"
<< fileName(dataMask/cloud::prefix/cloudName/"positions").c_str()
<< nl;
<< nl;
}
caseFile
<< nl << "VARIABLE" << nl;
......@@ -87,9 +89,8 @@ forAllConstIter(HashTable<word>, volumeFields, fieldIter)
}
}
// TODO: allow similar/different time-steps for each cloud
// TODO: allow similar/different time-steps for each cloud
label cloudNo = 0;
forAllConstIter(HashTable<HashTable<word>>, cloudFields, cloudIter)
{
......@@ -135,7 +136,7 @@ forAllConstIter(HashTable<HashTable<word>>, cloudFields, cloudIter)
// add time values
caseFile << nl << "TIME" << nl;
// time set 1 - geometry and volume fields
// time set 1 - volume fields
if (fieldTimesUsed.size())
{
caseFile
......@@ -161,9 +162,50 @@ if (fieldTimesUsed.size())
count = 0;
forAll(fieldTimesUsed, i)
{
const label& index = fieldTimesUsed[i];
caseFile
<< " " << setw(12) << timeIndices[index] + timeCorrection;
if (++count % 6 == 0)
{
caseFile << nl;
}
}
caseFile << nl << nl;
}
// time set 2 - geometry
// THIS NEEDS MORE CHECKING
#if 0
if (geometryTimesUsed.size())
{
caseFile
<< "time set: " << 2 << nl
<< "number of steps: " << geometryTimesUsed.size() << nl
<< "filename numbers:" << nl;
label count = 0;
forAll(geometryTimesUsed, i)
{
caseFile
<< " " << setw(12) << geometryTimesUsed[i];
if (++count % 6 == 0)
{
caseFile << nl;
}
}
caseFile
<< nl << "time values:" << nl;
count = 0;
forAll(geometryTimesUsed, i)
{
const label& index = geometryTimesUsed[i];
caseFile
<< " " << setw(12)
<< timeIndices[fieldTimesUsed[i]] + timeCorrection;
<< " " << setw(12) << timeIndices[index] + timeCorrection;
if (++count % 6 == 0)
{
......@@ -172,7 +214,9 @@ if (fieldTimesUsed.size())
}
caseFile << nl << nl;
}
#endif
// time set - clouds
// TODO: allow similar/different time-steps for each cloud
cloudNo = 0;
forAllConstIter(HashTable<DynamicList<label>>, cloudTimesUsed, cloudIter)
......@@ -205,9 +249,9 @@ forAllConstIter(HashTable<DynamicList<label>>, cloudTimesUsed, cloudIter)
count = 0;
forAll(timesUsed, i)
{
const label& index = timesUsed[i];
caseFile
<< " " << setw(12)
<< timeIndices[timesUsed[i]] + timeCorrection;
<< " " << setw(12) << timeIndices[index] + timeCorrection;
if (++count % 6 == 0)
{
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -47,6 +47,8 @@ void Foam::ensightCaseEntry
const label timeSet
)
{
const ensight::VarName varName(fieldName);
caseFile.setf(ios_base::left);
fileName dirName(dataMask);
......@@ -68,9 +70,9 @@ void Foam::ensightCaseEntry
<< ensightType.c_str()
<< " per measured node: " << ts << " "
<< setw(15)
<< ("c" + Foam::name(cloudNo) + fieldName).c_str()
<< ("c" + Foam::name(cloudNo) + varName).c_str()
<< " "
<< (dirName/fieldName).c_str()
<< (dirName/varName).c_str()
<< nl;
}
else
......@@ -78,9 +80,9 @@ void Foam::ensightCaseEntry
caseFile
<< ensightType.c_str()
<< " per element: "
<< setw(15) << fieldName
<< setw(15) << varName
<< " "
<< (dirName/fieldName).c_str()
<< (dirName/varName).c_str()
<< nl;
}
}
......@@ -97,16 +99,16 @@ void Foam::ensightParticlePositions
{
Cloud<passiveParticle> parcels(mesh, cloudName, false);
fileName cloudDir = subDir/cloud::prefix/cloudName;
fileName postFileName = cloudDir/"positions";
const fileName postFileName =
subDir/cloud::prefix/cloudName/"positions";
// the ITER/lagrangian subdirectory must exist
mkDir(dataDir/cloudDir);
ensightFile os(dataDir/postFileName, format);
mkDir(dataDir/postFileName.path());
ensightFile os(dataDir, postFileName, format);
// tag binary format (just like geometry files)
os.writeBinaryHeader();
os.write(postFileName);
os.write(postFileName); // description
os.newline();
os.write("particle coordinates");
os.newline();
......@@ -161,14 +163,19 @@ void Foam::ensightLagrangianField
{
Info<< " " << fieldObject.name() << flush;
fileName cloudDir = subDir/cloud::prefix/cloudName;
fileName postFileName = cloudDir/fieldObject.name();
const fileName postFileName =
subDir/cloud::prefix/cloudName
/ensight::VarName(fieldObject.name());
string title =
postFileName + " with " + pTraits<Type>::typeName + " values";
// the ITER/lagrangian subdirectory was already created
// when writing positions
ensightFile os(dataDir/postFileName, format);
os.write(title);
ensightFile os(dataDir, postFileName, format);
os.write
(
// description
string(postFileName + " with " + pTraits<Type>::typeName + " values")
);
os.newline();
IOField<Type> field(fieldObject);
......@@ -219,10 +226,10 @@ void Foam::ensightVolField
{
Info<< " " << fieldObject.name() << flush;
fileName postFileName = subDir/fieldObject.name();
const fileName postFileName = subDir/ensight::VarName(fieldObject.name());
ensightFile os(dataDir/postFileName, format);
os.write(postFileName);
ensightFile os(dataDir, postFileName, format);
os.write(postFileName); // description
os.newline();
// ie, volField<Type>
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -166,9 +166,9 @@ int main(int argc, char *argv[])
ensightDir = args.rootPath()/args.globalCaseName()/ensightDir;
}
fileName dataDir = ensightDir/"data";
fileName caseFileName = "Ensight.case";
fileName dataMask = fileName("data")/ensightFile::mask();
const fileName caseFileName = "Ensight.case";
const fileName dataDir = ensightDir/"data";
const fileName dataMask = dataDir.name()/ensightFile::mask();
// Ensight and Ensight/data directories must exist
// do not remove old data - we might wish to convert new results
......@@ -178,6 +178,8 @@ int main(int argc, char *argv[])
Info<<"Warning: re-using existing directory" << nl
<< " " << ensightDir << endl;
}
// as per mkdir -p "Ensight/data"
mkDir(ensightDir);
mkDir(dataDir);
......@@ -216,6 +218,9 @@ int main(int argc, char *argv[])
// map times used
Map<scalar> timeIndices;
// TODO: Track the time indices used by the geometry
DynamicList<label> geometryTimesUsed;
// Track the time indices used by the volume fields
DynamicList<label> fieldTimesUsed;
......@@ -235,11 +240,12 @@ int main(int argc, char *argv[])
#include "getTimeIndex.H"
// remember the time index
// remember the time index for the volume fields
fieldTimesUsed.append(timeIndex);
// the data/ITER subdirectory must exist
fileName subDir = ensightFile::subDir(timeIndex);
// Note that data/ITER is indeed a valid ensight::FileName
const fileName subDir = ensightFile::subDir(timeIndex);
mkDir(dataDir/subDir);
// place a timestamp in the directory for future reference
......@@ -261,15 +267,19 @@ int main(int argc, char *argv[])
if (!optNoMesh)
{
fileName geomDir;
if (hasMovingMesh)
{
geomDir = dataDir/subDir;
// remember the time index for the geometry
geometryTimesUsed.append(timeIndex);
}
ensightGeoFile geoFile(ensightDir/geomDir/geometryName, format);
ensightGeoFile geoFile
(
(hasMovingMesh ? dataDir/subDir : ensightDir),
geometryName,
format
);
partsList.writeGeometry(geoFile);
Info<< nl;
}
}
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -24,6 +24,9 @@ License
\*---------------------------------------------------------------------------*/
#include "ensightFile.H"
#include "error.H"
#include <cstring>
#include <sstream>
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
......@@ -33,8 +36,7 @@ bool Foam::ensightFile::allowUndef_ = false;
Foam::scalar Foam::ensightFile::undefValue_ = Foam::floatScalarVGREAT;
// default is width 8
Foam::string Foam::ensightFile::mask_ = "********";
Foam::string Foam::ensightFile::mask_ = "********";
Foam::string Foam::ensightFile::dirFmt_ = "%08d";
......@@ -79,15 +81,9 @@ Foam::label Foam::ensightFile::subDirWidth()
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::ensightFile::ensightFile
(
const fileName& pathname,
IOstream::streamFormat format
)
:
OFstream(pathname, format)
void Foam::ensightFile::initialize()
{
// ascii formatting specs
setf
......@@ -99,6 +95,33 @@ Foam::ensightFile::ensightFile
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ensightFile::ensightFile
(
const fileName& pathname,
IOstream::streamFormat format
)
:
OFstream(ensight::FileName(pathname), format)
{
initialize();
}
Foam::ensightFile::ensightFile
(
const fileName& path,
const fileName& name,
IOstream::streamFormat format
)
:
OFstream(path/ensight::FileName(name), format)
{
initialize();
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::ensightFile::~ensightFile()
......@@ -144,30 +167,9 @@ Foam::Ostream& Foam::ensightFile::write
Foam::Ostream& Foam::ensightFile::write(const char* value)
{
return write(string(value));
}
Foam::Ostream& Foam::ensightFile::write(const string& value)
{
char buf[80];
for (string::size_type i = 0; i < 80; ++i)
{
buf[i] = 0;
}
string::size_type n = value.size();
if (n >= 80)
{
n = 79;
}
for (string::size_type i = 0; i < n; ++i)
{
buf[i] = value[i];
}
strncpy(buf, value, 80); // max 80 chars or padded with nul if smaller
if (format() == IOstream::BINARY)
{
......@@ -179,10 +181,18 @@ Foam::Ostream& Foam::ensightFile::write(const string& value)
}
else
{
buf[79] = 0; // max 79 in ASCII, ensure it is indeed nul-terminated
stdStream() << buf;
}
return *this;
}
Foam::Ostream& Foam::ensightFile::write(const string& value)
{
return write(value.c_str());
}
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -36,13 +36,16 @@ Description
#include "OFstream.H"
#include "IOstream.H"
#include "ensightFileName.H"
#include "ensightVarName.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ensightFile Declaration
Class ensightFile Declaration
\*---------------------------------------------------------------------------*/
class ensightFile
......@@ -66,24 +69,41 @@ class ensightFile
// Private Member Functions
//- Initialize by setting the ASCII output formatting
void initialize();
//- Disallow default bitwise assignment
void operator=(const ensightFile&);
void operator=(const ensightFile&) = delete;
//- Disallow default copy constructor
ensightFile(const ensightFile&);
ensightFile(const ensightFile&) = delete;
public:
// Forward declarations
class FileName;
class VarName;
// Constructors
//- Construct from pathname
//- Construct from pathname.
// The entire pathname is checked for valid ensight naming.
ensightFile
(
const fileName& pathname,
IOstream::streamFormat format=IOstream::BINARY
);
//- Construct from path and name.
// Only the name portion is checked for valid ensight naming.
ensightFile
(
const fileName& path,
const fileName& name,