Commit d8369415 authored by Mark Olesen's avatar Mark Olesen

PV3FoamReader gets (single) mesh region handling

  - handling multiple regions require multiple readers
  - a region is currently recognized by the file name, anything after the
    '=' delimiter (eg, "case=region.OpenFOAM") is used to determine the
    mesh region, but might be changed in the future
    eg, 'case%region', 'case^region', 'case~region', 'case{region}' ...

Note:
  - Having a separate reader for each region instead attempting to handle
    all the mesh regions in a single reader is the better solution.
    It is not only simpler, but allows distinct field selections for
    each region
Todo:
  - Haven't a test for Lagrangian and multi-regions.
parent d20b6fe6
......@@ -112,10 +112,7 @@ vtkPV3FoamReader::~vtkPV3FoamReader()
{
vtkDebugMacro(<<"Deconstructor");
if (foamData_)
{
delete foamData_;
}
delete foamData_;
if (FileName)
{
......@@ -186,6 +183,16 @@ int vtkPV3FoamReader::RequestInformation
int nTimeSteps = 0;
double* timeSteps = foamData_->findTimes(nTimeSteps);
if (!nTimeSteps)
{
vtkErrorMacro("could not find valid OpenFOAM mesh");
// delete foamData and flag it as fatal error
delete foamData_;
foamData_ = NULL;
return 0;
}
// set identical time steps for all ports
for (int infoI = 0; infoI < nInfo; ++infoI)
{
......@@ -248,6 +255,13 @@ int vtkPV3FoamReader::RequestData
return 0;
}
// catch previous error
if (!foamData_)
{
vtkErrorMacro("Reader failed - perhaps no mesh?");
return 0;
}
int nInfo = outputVector->GetNumberOfInformationObjects();
if (Foam::vtkPV3Foam::debug)
......@@ -262,6 +276,7 @@ int vtkPV3FoamReader::RequestData
// take port0 as the lead for other outputs
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::SafeDownCast
(
outInfo->Get
......
......@@ -204,7 +204,8 @@ Foam::vtkPV3Foam::vtkPV3Foam
reader_(reader),
dbPtr_(NULL),
meshPtr_(NULL),
nMesh_(0),
meshRegion_(polyMesh::defaultRegion),
meshDir_(polyMesh::meshSubDir),
timeIndex_(-1),
meshChanged_(true),
fieldsChanged_(true),
......@@ -246,10 +247,33 @@ Foam::vtkPV3Foam::vtkPV3Foam
setEnv("FOAM_CASE", fullCasePath, true);
}
// get the caseName, and look for '=regionName' in it
// we could also be more stringent and insist that the
// prefix match the directory name, etc ..
fileName caseName(fileName(FileName).lessExt());
string::size_type delimiter = caseName.find("=");
if (delimiter != string::npos)
{
meshRegion_ = caseName.substr(delimiter+1);
// some safety
if (!meshRegion_.size())
{
meshRegion_ = polyMesh::defaultRegion;
}
if (meshRegion_ != polyMesh::defaultRegion)
{
meshDir_ = meshRegion_/polyMesh::meshSubDir;
}
}
if (debug)
{
Info<< "fullCasePath=" << fullCasePath << nl
<< "FOAM_CASE=" << getEnv("FOAM_CASE") << endl;
<< "FOAM_CASE=" << getEnv("FOAM_CASE") << nl
<< "region=" << meshRegion_ << endl;
}
// Create time object
......@@ -366,15 +390,20 @@ void Foam::vtkPV3Foam::updateFoamMesh()
{
if (debug)
{
Info<< "Creating Foam mesh" << endl;
Info<< "Creating Foam mesh for region " << meshRegion_
<< " at time=" << dbPtr_().timeName()
<< endl;
}
meshPtr_ = new fvMesh
(
IOobject
(
fvMesh::defaultRegion,
meshRegion_,
dbPtr_().timeName(),
dbPtr_()
dbPtr_(),
IOobject::MUST_READ
)
);
......@@ -476,11 +505,26 @@ double* Foam::vtkPV3Foam::findTimes(int& nTimeSteps)
Time& runTime = dbPtr_();
instantList timeLst = runTime.times();
// always skip "constant" time, unless there are no other times
nTimes = timeLst.size();
// find the first time for which this mesh appears to exist
label timeI = 0;
for (; timeI < timeLst.size(); ++timeI)
{
const word& timeName = timeLst[timeI].name();
if
(
file(runTime.path()/timeName/meshDir_/"points")
&& IOobject("points", timeName, meshDir_, runTime).headerOk()
)
{
break;
}
}
if (nTimes > 1)
nTimes = timeLst.size() - timeI;
// always skip "constant" time if possible
if (timeI == 0 && nTimes > 1)
{
timeI = 1;
--nTimes;
......@@ -697,7 +741,6 @@ void Foam::vtkPV3Foam::removePatchNames(vtkRenderer* renderer)
void Foam::vtkPV3Foam::PrintSelf(ostream& os, vtkIndent indent) const
{
os << indent << "Number of meshes: " << nMesh_ << "\n";
os << indent << "Number of nodes: "
<< (meshPtr_ ? meshPtr_->nPoints() : 0) << "\n";
......@@ -706,6 +749,8 @@ void Foam::vtkPV3Foam::PrintSelf(ostream& os, vtkIndent indent) const
os << indent << "Number of available time steps: "
<< (dbPtr_.valid() ? dbPtr_().times().size() : 0) << endl;
os << indent << "mesh region: " << meshRegion_ << "\n";
}
// ************************************************************************* //
......@@ -92,11 +92,8 @@ class polyPatch;
class faceSet;
class pointSet;
template<class Type>
class IOField;
template<class Type>
class List;
template<class Type> class IOField;
template<class Type> class List;
/*---------------------------------------------------------------------------*\
Class vtkPV3Foam Declaration
......@@ -248,9 +245,11 @@ class vtkPV3Foam
//- Foam mesh
fvMesh* meshPtr_;
//- Number of meshes
// TODO - for info only - only set up to process ONE mesh
int nMesh_;
//- The mesh region
word meshRegion_;
//- The mesh directory for the region
fileName meshDir_;
//- The time index
int timeIndex_;
......
......@@ -72,6 +72,8 @@ void Foam::vtkPV3Foam::convertVolFields
vtkMultiBlockDataSet* output
)
{
const fvMesh& mesh = *meshPtr_;
wordHashSet selectedFields = getSelected
(
reader_->GetVolFieldSelection()
......@@ -82,8 +84,8 @@ void Foam::vtkPV3Foam::convertVolFields
return;
}
const fvMesh& mesh = *meshPtr_;
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
......@@ -158,6 +160,8 @@ void Foam::vtkPV3Foam::convertPointFields
vtkMultiBlockDataSet* output
)
{
const fvMesh& mesh = *meshPtr_;
wordHashSet selectedFields = getSelected
(
reader_->GetPointFieldSelection()
......@@ -168,8 +172,8 @@ void Foam::vtkPV3Foam::convertPointFields
return;
}
const fvMesh& mesh = *meshPtr_;
// Get objects (fields) for this time - only keep selected fields
// the region name is already in the mesh db
IOobjectList objects(mesh, dbPtr_().timeName());
pruneObjectList(objects, selectedFields);
......@@ -257,8 +261,10 @@ void Foam::vtkPV3Foam::convertLagrangianFields
continue;
}
// Get the Lagrangian fields for this time and this cloud
// but only keep selected fields
// the region name is already in the mesh db
IOobjectList objects
(
mesh,
......
......@@ -64,7 +64,7 @@ void Foam::vtkPV3Foam::convertMeshVolume
}
// Convert the internalMesh
// TODO: multiple mesh regions
// this looks like more than one part, but it isn't
for (int partId = selector.start(); partId < selector.end(); ++partId)
{
const word partName = "internalMesh";
......@@ -239,7 +239,6 @@ void Foam::vtkPV3Foam::convertMeshCellZones
}
const cellZoneMesh& zMesh = mesh.cellZones();
for (int partId = selector.start(); partId < selector.end(); ++partId)
{
const word zoneName = getPartName(partId);
......@@ -408,7 +407,6 @@ void Foam::vtkPV3Foam::convertMeshFaceZones
}
const faceZoneMesh& zMesh = mesh.faceZones();
for (int partId = selector.start(); partId < selector.end(); ++partId)
{
const word zoneName = getPartName(partId);
......@@ -515,6 +513,7 @@ void Foam::vtkPV3Foam::convertMeshPointZones
partInfo& selector = partInfoPointZones_;
selector.block(blockNo); // set output block
label datasetNo = 0; // restart at dataset 0
const fvMesh& mesh = *meshPtr_;
if (debug)
{
......@@ -522,12 +521,9 @@ void Foam::vtkPV3Foam::convertMeshPointZones
printMemory();
}
const fvMesh& mesh = *meshPtr_;
if (selector.size())
{
const pointZoneMesh& zMesh = mesh.pointZones();
for (int partId = selector.start(); partId < selector.end(); ++partId)
{
word zoneName = getPartName(partId);
......
......@@ -57,6 +57,8 @@ vtkPolyData* Foam::vtkPV3Foam::lagrangianVTKMesh
printMemory();
}
// the region name is already in the mesh db
IOobjectList sprayObjs
(
mesh,
......
......@@ -91,11 +91,11 @@ Foam::wordList Foam::vtkPV3Foam::readZoneNames(const word& zoneType)
zoneType,
dbPtr_().findInstance
(
polyMesh::meshSubDir,
meshDir_,
zoneType,
IOobject::READ_IF_PRESENT
),
polyMesh::meshSubDir,
meshDir_,
dbPtr_(),
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
......@@ -126,10 +126,6 @@ void Foam::vtkPV3Foam::updateInfoInternalMesh()
vtkDataArraySelection* partSelection = reader_->GetPartSelection();
// Determine number of meshes available
HashTable<const fvMesh*> meshObjects = dbPtr_().lookupClass<const fvMesh>();
nMesh_ = meshObjects.size();
// Determine mesh parts (internalMesh, patches...)
//- Add internal mesh as first entry
partInfoVolume_ = partSelection->GetNumberOfArrays();
......@@ -155,10 +151,19 @@ void Foam::vtkPV3Foam::updateInfoLagrangian()
<< " " << dbPtr_->timePath()/"lagrangian" << endl;
}
// use the db directly since this might be called without a mesh,
// but the region must get added back in
fileName lagrangianPrefix("lagrangian");
if (meshRegion_ != polyMesh::defaultRegion)
{
lagrangianPrefix = meshRegion_/"lagrangian";
}
// Search for list of lagrangian objects for this time
fileNameList cloudDirs
(
readDir(dbPtr_->timePath()/"lagrangian", fileName::DIRECTORY)
readDir(dbPtr_->timePath()/lagrangianPrefix, fileName::DIRECTORY)
);
vtkDataArraySelection* partSelection = reader_->GetPartSelection();
......@@ -221,43 +226,50 @@ void Foam::vtkPV3Foam::updateInfoPatches()
}
else
{
// Read patches
polyBoundaryMeshEntries patchEntries
// mesh not loaded - read from file
// but this could fail if we've supplied a bad region name
IOobject ioObj
(
IOobject
"boundary",
dbPtr_().findInstance
(
meshDir_,
"boundary",
dbPtr_().findInstance(polyMesh::meshSubDir, "boundary"),
polyMesh::meshSubDir,
dbPtr_(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
IOobject::READ_IF_PRESENT
),
meshDir_,
dbPtr_(),
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE,
false
);
// Add (non-zero) patches to the list of mesh parts
forAll(patchEntries, entryI)
// this should only ever fail if the mesh region doesn't exist
if (ioObj.headerOk())
{
label nFaces
(
readLabel(patchEntries[entryI].dict().lookup("nFaces"))
);
polyBoundaryMeshEntries patchEntries(ioObj);
// Valid patch if nFace > 0
if (nFaces)
// Add (non-zero) patches to the list of mesh parts
forAll(patchEntries, entryI)
{
// Add patch to GUI list
partSelection->AddArray
label nFaces
(
(patchEntries[entryI].keyword() + " - patch").c_str()
readLabel(patchEntries[entryI].dict().lookup("nFaces"))
);
++nPatches;
// Valid patch if nFace > 0 - add patch to GUI list
if (nFaces)
{
partSelection->AddArray
(
(patchEntries[entryI].keyword() + " - patch").c_str()
);
++nPatches;
}
}
}
}
partInfoPatches_ += nPatches;
if (debug)
......@@ -380,8 +392,8 @@ void Foam::vtkPV3Foam::updateInfoSets()
IOobjectList objects
(
dbPtr_(),
dbPtr_().findInstance(polyMesh::meshSubDir, "faces"),
polyMesh::meshSubDir/"sets"
dbPtr_().findInstance(meshDir_, "faces", IOobject::READ_IF_PRESENT),
meshDir_/"sets"
);
......@@ -449,11 +461,19 @@ void Foam::vtkPV3Foam::updateInfoLagrangianFields()
word cloudName = getPartName(partId);
// use the db directly since this might be called without a mesh,
// but the region must get added back in
fileName lagrangianPrefix("lagrangian");
if (meshRegion_ != polyMesh::defaultRegion)
{
lagrangianPrefix = meshRegion_/"lagrangian";
}
IOobjectList objects
(
dbPtr_(),
dbPtr_().timeName(),
"lagrangian"/cloudName
lagrangianPrefix/cloudName
);
addToSelection<IOField<label> >
......
......@@ -59,8 +59,16 @@ void Foam::vtkPV3Foam::updateInfoFields
select->RemoveAllArrays();
// Search for list of objects for this time
IOobjectList objects(dbPtr_(), dbPtr_().timeName());
// use the db directly since this might be called without a mesh,
// but the region must get added back in
word regionPrefix;
if (meshRegion_ != polyMesh::defaultRegion)
{
regionPrefix = meshRegion_;
}
// Search for list of objects for this time and mesh region
IOobjectList objects(dbPtr_(), dbPtr_().timeName(), regionPrefix);
//- Add volume fields to GUI
addToSelection<GeometricField<scalar, patchType, meshType> >
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment