diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/PV3FoamReader/vtkPV3FoamReader.cxx b/applications/utilities/postProcessing/graphics/PV3FoamReader/PV3FoamReader/vtkPV3FoamReader.cxx index c0a32e40daaba3e2d0535b5cf7fed51f8b6b3972..2a78ad0133ada4a796c427f832f135fc713098dc 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/PV3FoamReader/vtkPV3FoamReader.cxx +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/PV3FoamReader/vtkPV3FoamReader.cxx @@ -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 diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.C b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.C index 75baf87517f34d11602639d537743c3858751dbb..fea710ac1adb315a5d35fcb5bda0d88a89d9a36d 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.C +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.C @@ -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"; } // ************************************************************************* // diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.H b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.H index f4d7c32b112d45bb6238da2d2845f65e2132d49c..72d1edee5716aadb5037e57d1cdd91d09f9fc7ef 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.H +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3Foam.H @@ -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_; diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamFields.C b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamFields.C index bf5742e3a8671751db6527f789283ee78f00f65f..4f320c802c4e76ab22e85b8380d47fe847837309 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamFields.C +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamFields.C @@ -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, diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMesh.C b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMesh.C index 8539bca001ce85a70819c92cdefb85cfeaad790b..087790f9de41f295dac34b6288042dcc6e9fd960 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMesh.C +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMesh.C @@ -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); diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMeshLagrangian.C b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMeshLagrangian.C index ec5e87a4ba12b062c2d5d362142b42fed893aeda..ce050d1ae0499740db6e85c5bb1d118b2f1692ec 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMeshLagrangian.C +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamMeshLagrangian.C @@ -57,6 +57,8 @@ vtkPolyData* Foam::vtkPV3Foam::lagrangianVTKMesh printMemory(); } + + // the region name is already in the mesh db IOobjectList sprayObjs ( mesh, diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfo.C b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfo.C index 1c00a04a8573edf498772061a60d081b95e06a1c..32d78c9d17485e495e78f5c62fcb2d5bbd8c4735 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfo.C +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfo.C @@ -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> > diff --git a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfoFields.H b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfoFields.H index bd18d66d944640a02ad8fdc30bad1333d7117b28..89eb653c8369aa98ca7fd8982829230b46e74bd9 100644 --- a/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfoFields.H +++ b/applications/utilities/postProcessing/graphics/PV3FoamReader/vtkPV3Foam/vtkPV3FoamUpdateInfoFields.H @@ -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> >