Commit d8a55e46 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: align foamToEnsightParts internals with foamToEnsight

- add -region option and -fields filtering
parent b5432011
......@@ -39,8 +39,15 @@ Usage
- \par -ascii
Write Ensight data in ASCII format instead of "C Binary"
- \par -noZero
Exclude the often incomplete initial conditions.
- \par -fields \<fields\>
Specify single or multiple fields to write (all by default)
For example,
\verbatim
-fields T
-fields '(p T U \"alpha.*\")'
\endverbatim
The quoting is required to avoid shell expansions and to pass the
information as a single argument.
- \par -no-boundary
Suppress writing any patches.
......@@ -60,6 +67,12 @@ Usage
- \par -cellZone zoneName
Specify single cellZone to write (not lagrangian)
- \par -noZero
Exclude the often incomplete initial conditions.
- \par -name \<subdir\>
Define sub-directory name to use for Ensight data (default: "EnSight")
- \par -width \<n\>
Width of Ensight data subdir (default: 8)
......@@ -78,11 +91,10 @@ Note
#include "HashOps.H"
#include "fvc.H"
#include "fieldTypes.H"
#include "volFields.H"
#include "labelIOField.H"
#include "scalarIOField.H"
#include "tensorIOField.H"
#include "IOobjectList.H"
#include "vectorIOField.H"
// file-format/conversion
#include "ensightCase.H"
......@@ -372,7 +384,7 @@ int main(int argc, char *argv[])
ensCase.write();
Info<< "End: "
Info<< "\nEnd: "
<< timer.elapsedCpuTime() << " s, "
<< mem.update().peak() << " kB (peak)" << nl << endl;
......
......@@ -24,6 +24,7 @@ License
\*---------------------------------------------------------------------------*/
#include "readFields.H"
#include "volFields.H"
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
......
......@@ -46,7 +46,7 @@ template<class Type>
label writeDimFields
(
ensightCase& ensCase,
ensightMesh& ensMesh,
const ensightMesh& ensMesh,
const fvMeshSubsetProxy& proxy,
const IOobjectList& objects,
const bool nodeValues
......@@ -79,6 +79,7 @@ label writeDimFields
)
)
{
Info<< ' ' << fieldName;
++count;
}
}
......@@ -90,7 +91,7 @@ label writeDimFields
label writeAllDimFields
(
ensightCase& ensCase,
ensightMesh& ensMesh,
const ensightMesh& ensMesh,
const fvMeshSubsetProxy& proxy,
const IOobjectList& objects,
const bool nodeValues
......
......@@ -47,7 +47,7 @@ template<class Type>
bool writeVolField
(
ensightCase& ensCase,
ensightMesh& ensMesh,
const ensightMesh& ensMesh,
const fvMeshSubsetProxy& proxy,
const tmp<GeometricField<Type, fvPatchField, volMesh>>& tfield,
const bool nodeValues
......@@ -79,7 +79,7 @@ template<class Type>
label writeVolFields
(
ensightCase& ensCase,
ensightMesh& ensMesh,
const ensightMesh& ensMesh,
const fvMeshSubsetProxy& proxy,
const IOobjectList& objects,
const bool nodeValues
......@@ -103,6 +103,7 @@ label writeVolFields
)
)
{
Info<< ' ' << fieldName;
++count;
}
}
......@@ -114,7 +115,7 @@ label writeVolFields
label writeAllVolFields
(
ensightCase& ensCase,
ensightMesh& ensMesh,
const ensightMesh& ensMesh,
const fvMeshSubsetProxy& proxy,
const IOobjectList& objects,
const bool nodeValues
......
foamToEnsightParts.C
readFields.C
EXE = $(FOAM_APPBIN)/foamToEnsightParts
......@@ -3,11 +3,11 @@ EXE_INC = \
-I$(LIB_SRC)/fileFormats/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/lagrangian/intermediate/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-ldynamicMesh \
-lgenericPatchFields \
-llagrangianIntermediate \
-lmeshTools \
-lconversion \
-lgenericPatchFields
-lconversion
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
Description
Code chunk for post-processing conversion of cloud(s) to Ensight
\*---------------------------------------------------------------------------*/
// Cloud field data output
if (doLagrangian)
{
forAll(cloudNames, cloudNo)
{
const word& cloudName = cloudNames[cloudNo];
const HashTable<word>& theseCloudFields = cloudFields[cloudName];
fileNameList currentCloudDirs
(
readDir
(
runTime.timePath()/regionPrefix/cloud::prefix,
fileName::DIRECTORY
)
);
Info<< "Write " << cloudName << " (";
const bool cloudExists =
returnReduce
(
currentCloudDirs.found(cloudName),
orOp<bool>()
);
{
autoPtr<ensightFile> os = ensCase.newCloud(cloudName);
ensightCloud::writePositions
(
mesh,
cloudName,
cloudExists,
os
);
Info<< " positions";
if (!cloudExists)
{
Info<< "{0}"; // report empty field
}
}
forAllConstIters(theseCloudFields, fieldIter)
{
const word& fieldName = fieldIter.key();
const word& fieldType = fieldIter.object();
IOobject fieldObject
(
fieldName,
mesh.time().timeName(),
cloud::prefix/cloudName,
mesh,
IOobject::MUST_READ
);
bool fieldExists = cloudExists; // No field without positions
if (cloudExists)
{
// Want MUST_READ (globally) and valid=false (locally),
// but that combination does not work.
// So check the header and sync globally
fieldExists =
fieldObject.typeHeaderOk<IOField<scalar>>(false);
reduce(fieldExists, orOp<bool>());
}
bool wrote = false;
if (fieldType == scalarIOField::typeName)
{
autoPtr<ensightFile> os =
ensCase.newCloudData<scalar>(cloudName, fieldName);
wrote = ensightCloud::writeCloudField<scalar>
(
fieldObject, fieldExists, os
);
}
else if (fieldType == vectorIOField::typeName)
{
autoPtr<ensightFile> os =
ensCase.newCloudData<vector>(cloudName, fieldName);
wrote = ensightCloud::writeCloudField<vector>
(
fieldObject, fieldExists, os
);
}
if (wrote)
{
Info<< ' ' << fieldName;
if (!fieldExists)
{
Info<< "{0}"; // report empty field
}
}
}
Info<< " )" << nl;
}
}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
Description
Code chunk for converting volume and dimensioned fields
included by foamToEnsightParts.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Cell field data output
{
Info<< "Write volume field (";
writeAllVolFields
(
ensCase,
ensParts,
mesh,
objects
);
writeAllDimFields
(
ensCase,
ensParts,
mesh,
objects
);
Info<< " )" << nl;
}
// ************************************************************************* //
// check all time directories for the following:
// The fields for each cloud:
HashTable<HashTable<word>> cloudFields;
// Identify if lagrangian data exist at any time step.
if (timeDirs.size() && doLagrangian)
{
const fileName& baseDir = mesh.time().path();
const fileName cloudPrefix(regionPrefix/cloud::prefix);
Info<< "Searching for lagrangian ... " << flush;
for (const instant& inst : timeDirs)
{
const word& timeName = inst.name();
// DO NOT USE -->> runTime.setTime(timeDirs[timeI], timeI); <<--
// It incurs a large overhead when done so frequently.
fileNameList cloudDirs
(
readDir
(
baseDir/timeName/cloudPrefix,
fileName::DIRECTORY
)
);
for (fileName& cloudDir : cloudDirs)
{
const word cloudName(std::move(cloudDir));
IOobjectList cloudObjs
(
mesh,
timeName,
cloudPrefix/cloudName
);
// Clouds require "coordinates".
// The "positions" are for v1706 and lower.
// - detect and remove since these are treated specially
bool isCloud = false;
if (cloudObjs.erase("coordinates"))
{
isCloud = true;
}
if (cloudObjs.erase("positions"))
{
isCloud = true;
}
if (isCloud)
{
// Save the cloud fields on a per cloud basis
auto& fieldsPerCloud = cloudFields(cloudName);
forAllConstIters(cloudObjs, fieldIter)
{
const IOobject* io = *fieldIter;
// Field name/type
fieldsPerCloud.insert(io->name(), io->headerClassName());
}
}
}
}
if (Pstream::parRun())
{
Pstream::mapCombineGather(cloudFields, HashTableOps::plusEqOp<word>());
Pstream::mapCombineScatter(cloudFields);
}
if (cloudFields.empty())
{
Info<< "none detected." << endl;
}
}
// Sorted list of cloud names
const wordList cloudNames(cloudFields.sortedToc());
if (cloudNames.size())
{
// Complete the echo information - as flatOutput
cloudNames.writeList(Info) << endl;
}
// ************************************************************************* //
// check the final time directory for the following:
// 1. volume fields
HashTable<word> volumeFields;
// 2. the fields for each cloud:
HashTable<HashTable<word>> cloudFields;
if (timeDirs.size())
{
const word& lastTimeName = timeDirs.last().name();
const fileName cloudPrefix(regionPrefix/cloud::prefix);
IOobjectList objs(mesh, lastTimeName);
forAllConstIters(objs, fieldIter)
{
const IOobject& obj = *fieldIter();
const word& fieldName = obj.name();
const word& fieldType = obj.headerClassName();
if (volFieldTypes.found(fieldType) && !fieldName.endsWith("_0"))
{
// ignore types that we don't handle, and ignore _0 fields
volumeFields.insert(fieldName, fieldType);
}
}
//
// Now check for lagrangian/<cloudName>
//
fileNameList cloudDirs;
if (doLagrangian)
{
cloudDirs = readDir
(
runTime.path()
/ lastTimeName
/ cloudPrefix,
fileName::DIRECTORY
);
}
forAll(cloudDirs, cloudI)
{
const word& cloudName = cloudDirs[cloudI];
IOobjectList cloudObjs
(
mesh,
lastTimeName,
cloudPrefix/cloudName
);
// Clouds require "coordinates".
// The "positions" are for v1706 and lower.
if (cloudObjs.found("coordinates") || cloudObjs.found("positions"))
{
// Save the cloud fields on a per cloud basis
auto& fieldsPerCloud = cloudFields(cloudName);
forAllConstIters(cloudObjs, fieldIter)
{
const IOobject* obj = fieldIter();
const word& fieldName = obj->name();
const word& fieldType = obj->headerClassName();
if (cloudFieldTypes.found(fieldType))
{
// Field name/type - ignore types that we don't handle
fieldsPerCloud.insert(fieldName, fieldType);
}
}
}
}
// Only retain a cloud that actually has fields
cloudFields.filterValues
(
[](const HashTable<word>& v){ return v.size(); }
);
//
// Verify that the variable is present for all times
//
for (label i=0; volumeFields.size() && i < timeDirs.size(); ++i)
{
const word& timeName = timeDirs[i].name();
// Everything is potentially missing, unless we discover otherwise
wordHashSet missing(volumeFields);
// Avoid -->> IOobjectList objs(mesh, timeName); <<--
// Too much overhead when done so frequently.
fileNameList contents = readDir
(
runTime.path()
/ timeName,
fileName::FILE
);
for (const fileName& file : contents)
{
missing.erase(file.name());
}
volumeFields.erase(missing);
}
}
// ************************************************************************* //
......@@ -38,8 +38,15 @@ Usage
- \par -ascii
Write Ensight data in ASCII format instead of "C Binary"
- \par -name \<subdir\>
Define sub-directory name to use for Ensight data (default: "Ensight")
- \par -fields \<fields\>
Specify single or multiple fields to write (all by default)
For example,
\verbatim
-fields T
-fields '(p T U \"alpha.*\")'
\endverbatim
The quoting is required to avoid shell expansions and to pass the
information as a single argument.
- \par -noZero
Exclude the often incomplete initial conditions.
......@@ -55,6 +62,12 @@ Usage
Suppress writing the geometry. Can be useful for converting partial
results for a static geometry.
- \par -noZero
Exclude the often incomplete initial conditions.
- \par -name \<subdir\>
Define sub-directory name to use for Ensight data (default: "Ensight")
- \par -width \<n\>
Width of Ensight data subdir
......@@ -66,13 +79,16 @@ Note
#include "argList.H"
#include "timeSelector.H"
#include "IOobjectList.H"
#include "IOmanip.H"
#include "OFstream.H"
#include "PstreamCombineReduceOps.H"