From 05aa701c15617ea3adcd1a230cb8128f51b9a551 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 12 Sep 2017 11:38:05 +0200 Subject: [PATCH 1/2] ENH: handle all lagrangian fields in pv reader (issue #585) - previous only checked for clouds at the last instance and only detected lagrangian fields from the first cloud. Now check for clouds at all instances and detect all of their fields as well. --- .../graphics/PVReaders/foamPv/foamPvCore.H | 48 +++- .../PVReaders/foamPv/foamPvCoreTemplates.C | 114 +++++++- .../PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C | 245 ++++++++---------- 3 files changed, 254 insertions(+), 153 deletions(-) diff --git a/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCore.H b/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCore.H index 3bbc92855e..e7feca1f90 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCore.H +++ b/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCore.H @@ -160,13 +160,59 @@ public: const std::string& datasetName ); + //- Add names to array selection + template + static label addToArray + ( + vtkDataArraySelection* select, + const std::string& prefix, + const UList& names + ); + + //- Add names to array selection + template + static label addToArray + ( + vtkDataArraySelection* select, + const UList& names, + const std::string& suffix = string::null + ); + + //- Add objects of Type to array selection + template + static label addToSelection + ( + vtkDataArraySelection* select, + const std::string& prefix, + const IOobjectList& objects + ); + //- Add objects of Type to array selection template static label addToSelection ( vtkDataArraySelection* select, const IOobjectList& objects, - const std::string& prefix = string::null + const std::string& suffix = string::null + ); + + //- Add objects of Type to array selection + template + static label addToSelection + ( + vtkDataArraySelection* select, + const std::string& prefix, + const HashTable& objects + ); + + + //- Add objects of Type to array selection + template + static label addToSelection + ( + vtkDataArraySelection* select, + const HashTable& objects, + const std::string& suffix = string::null ); diff --git a/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCoreTemplates.C b/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCoreTemplates.C index 54eeee88c0..cd9e2302b2 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCoreTemplates.C +++ b/applications/utilities/postProcessing/graphics/PVReaders/foamPv/foamPvCoreTemplates.C @@ -28,29 +28,119 @@ License // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +template +Foam::label Foam::foamPvCore::addToArray +( + vtkDataArraySelection *select, + const std::string& prefix, + const UList& names +) +{ + if (prefix.empty()) + { + for (const auto& name : names) + { + select->AddArray(name.c_str()); + } + } + else + { + for (const auto& name : names) + { + select->AddArray((prefix + name).c_str()); + } + } + + return names.size(); +} + + +template +Foam::label Foam::foamPvCore::addToArray +( + vtkDataArraySelection *select, + const UList& names, + const std::string& suffix +) +{ + if (suffix.empty()) + { + for (const auto& name : names) + { + select->AddArray(name.c_str()); + } + } + else + { + for (const auto& name : names) + { + select->AddArray((name + suffix).c_str()); + } + } + + return names.size(); +} + + +template +Foam::label Foam::foamPvCore::addToSelection +( + vtkDataArraySelection *select, + const std::string& prefix, + const IOobjectList& objects +) +{ + return addToArray(select, prefix, objects.sortedNames(Type::typeName)); +} + + template Foam::label Foam::foamPvCore::addToSelection ( vtkDataArraySelection *select, const IOobjectList& objects, - const std::string& prefix + const std::string& suffix ) { - const wordList names = objects.sortedNames(Type::typeName); + return addToArray(select, objects.sortedNames(Type::typeName), suffix); +} - forAll(names, i) + +template +Foam::label Foam::foamPvCore::addToSelection +( + vtkDataArraySelection *select, + const std::string& prefix, + const HashTable& objects +) +{ + auto iter = objects.cfind(Type::typeName); + + if (iter.found()) { - if (prefix.empty()) - { - select->AddArray(names[i].c_str()); - } - else - { - select->AddArray((prefix + names[i]).c_str()); - } + return addToArray(select, prefix, iter.object().sortedToc()); } - return names.size(); + return 0; +} + + +template +Foam::label Foam::foamPvCore::addToSelection +( + vtkDataArraySelection *select, + const HashTable& objects, + const std::string& suffix +) +{ + auto iter = objects.cfind(Type::typeName); + + if (iter.found()) + { + return addToArray(select, iter.object().sortedToc(), suffix); + } + + return 0; } diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C index 335a975fc8..9e61618cab 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C +++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoamUpdateInfo.C @@ -85,11 +85,11 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames wordList names(zmesh.size()); label nZone = 0; - forAll(zmesh, zonei) + for (const auto& zn : zmesh) { - if (!zmesh[zonei].empty()) + if (!zn.empty()) { - names[nZone++] = zmesh[zonei].name(); + names[nZone++] = zn.name(); } } names.setSize(nZone); @@ -100,8 +100,6 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames Foam::wordList Foam::vtkPVFoam::getZoneNames(const word& zoneType) const { - wordList names; - // mesh not loaded - read from file IOobject ioObj ( @@ -119,14 +117,17 @@ Foam::wordList Foam::vtkPVFoam::getZoneNames(const word& zoneType) const false ); + wordList names; if (ioObj.typeHeaderOk(false, false)) { zonesEntries zones(ioObj); names.setSize(zones.size()); - forAll(zones, zonei) + label nZone = 0; + + for (const auto& zn : zones) { - names[zonei] = zones[zonei].keyword(); + names[nZone++] = zn.keyword(); } } @@ -167,7 +168,7 @@ void Foam::vtkPVFoam::updateInfoLagrangian << " " << dbPtr_->timePath()/cloud::prefix << endl; } - // use the db directly since this might be called without a mesh, + // Use the db directly since this might be called without a mesh, // but the region must get added back in fileName lagrangianPrefix(cloud::prefix); if (meshRegion_ != polyMesh::defaultRegion) @@ -175,22 +176,23 @@ void Foam::vtkPVFoam::updateInfoLagrangian lagrangianPrefix = meshRegion_/cloud::prefix; } - // Search for list of lagrangian objects for this time - fileNameList cloudDirs - ( - readDir(dbPtr_->timePath()/lagrangianPrefix, fileName::DIRECTORY) - ); + // List of lagrangian objects across all times + HashSet names; + + for (const instant& t : dbPtr_().times()) + { + names.insert + ( + readDir + ( + dbPtr_->path()/t.name()/lagrangianPrefix, + fileName::DIRECTORY + ) + ); + } rangeLagrangian_.reset(select->GetNumberOfArrays()); - forAll(cloudDirs, cloudi) - { - // Add cloud to GUI list - select->AddArray - ( - ("lagrangian/" + cloudDirs[cloudi]).c_str() - ); - ++rangeLagrangian_; - } + rangeLagrangian_ += addToArray(select, "lagrangian/", names.sortedToc()); if (debug) { @@ -257,39 +259,26 @@ void Foam::vtkPVFoam::updateInfoPatches const polyPatch& pp = patches[patchId]; if (pp.size()) { - enabledEntries.insert - ( - "patch/" + pp.name() - ); + enabledEntries.insert("patch/" + pp.name()); } } } } - // Sort group names - Foam::sort(displayNames); - for (const auto& name : displayNames) - { - select->AddArray(name.c_str()); - ++rangePatches_; - } + Foam::sort(displayNames); // Sorted group names + rangePatches_ += addToArray(select, displayNames); // Add (non-zero) patches to the list of mesh parts // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (!reader_->GetShowGroupsOnly()) { - forAll(patches, patchi) + for (const polyPatch& pp : patches) { - const polyPatch& pp = patches[patchi]; - if (pp.size()) { // Add patch to GUI list - select->AddArray - ( - ("patch/" + pp.name()).c_str() - ); + select->AddArray(("patch/" + pp.name()).c_str()); ++rangePatches_; } } @@ -339,9 +328,9 @@ void Foam::vtkPVFoam::updateInfoPatches && patchDict.readIfPresent("inGroups", groupNames) ) { - forAll(groupNames, groupI) + for (const auto& groupName : groupNames) { - groups(groupNames[groupI]).insert(patchi); + groups(groupName).insert(patchi); } } } @@ -370,21 +359,13 @@ void Foam::vtkPVFoam::updateInfoPatches { for (auto patchId : patchIDs) { - enabledEntries.insert - ( - "patch/" + names[patchId] - ); + enabledEntries.insert("patch/" + names[patchId]); } } } - // Sort group names - Foam::sort(displayNames); - for (const auto& name : displayNames) - { - select->AddArray(name.c_str()); - ++rangePatches_; - } + Foam::sort(displayNames); // Sorted group names + rangePatches_ += addToArray(select, displayNames); // Add (non-zero) patches to the list of mesh parts // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -396,10 +377,7 @@ void Foam::vtkPVFoam::updateInfoPatches // Valid patch if nFace > 0 - add patch to GUI list if (sizes[patchi]) { - select->AddArray - ( - ("patch/" + names[patchi]).c_str() - ); + select->AddArray(("patch/" + names[patchi]).c_str()); ++rangePatches_; } } @@ -430,74 +408,44 @@ void Foam::vtkPVFoam::updateInfoZones << " [meshPtr=" << (meshPtr_ ? "set" : "null") << "]" << endl; } - wordList namesLst; - // - // cellZones information - // ~~~~~~~~~~~~~~~~~~~~~ - if (meshPtr_) + // cellZones { - namesLst = getZoneNames(meshPtr_->cellZones()); - } - else - { - namesLst = getZoneNames("cellZones"); - } - - rangeCellZones_.reset(select->GetNumberOfArrays()); - forAll(namesLst, elemI) - { - select->AddArray + const wordList names = ( - ("cellZone/" + namesLst[elemI]).c_str() + meshPtr_ + ? getZoneNames(meshPtr_->cellZones()) + : getZoneNames("cellZones") ); - ++rangeCellZones_; + + rangeCellZones_.reset(select->GetNumberOfArrays()); + rangeCellZones_ += addToArray(select, "cellZone/", names); } - - // - // faceZones information - // ~~~~~~~~~~~~~~~~~~~~~ - if (meshPtr_) + // faceZones { - namesLst = getZoneNames(meshPtr_->faceZones()); - } - else - { - namesLst = getZoneNames("faceZones"); - } - - rangeFaceZones_.reset(select->GetNumberOfArrays()); - forAll(namesLst, elemI) - { - select->AddArray + const wordList names = ( - ("faceZone/" + namesLst[elemI]).c_str() + meshPtr_ + ? getZoneNames(meshPtr_->faceZones()) + : getZoneNames("faceZones") ); - ++rangeFaceZones_; + + rangeFaceZones_.reset(select->GetNumberOfArrays()); + rangeFaceZones_ += addToArray(select, "faceZone/", names); } - - // - // pointZones information - // ~~~~~~~~~~~~~~~~~~~~~~ - if (meshPtr_) + // pointZones { - namesLst = getZoneNames(meshPtr_->pointZones()); - } - else - { - namesLst = getZoneNames("pointZones"); - } - - rangePointZones_.reset(select->GetNumberOfArrays()); - forAll(namesLst, elemI) - { - select->AddArray + const wordList names = ( - ("pointZone/" + namesLst[elemI]).c_str() + meshPtr_ + ? getZoneNames(meshPtr_->pointZones()) + : getZoneNames("pointZones") ); - ++rangePointZones_; + + rangePointZones_.reset(select->GetNumberOfArrays()); + rangePointZones_ += addToArray(select, "pointZone/", names); } if (debug) @@ -525,14 +473,14 @@ void Foam::vtkPVFoam::updateInfoSets // Add names of sets. Search for last time directory with a sets // subdirectory. Take care not to search beyond the last mesh. - word facesInstance = dbPtr_().findInstance + const word facesInstance = dbPtr_().findInstance ( meshDir_, "faces", IOobject::READ_IF_PRESENT ); - word setsInstance = dbPtr_().findInstance + const word setsInstance = dbPtr_().findInstance ( meshDir_/"sets", word::null, @@ -540,7 +488,7 @@ void Foam::vtkPVFoam::updateInfoSets facesInstance ); - IOobjectList objects(dbPtr_(), setsInstance, meshDir_/"sets"); + const IOobjectList objects(dbPtr_(), setsInstance, meshDir_/"sets"); if (debug) { @@ -553,24 +501,24 @@ void Foam::vtkPVFoam::updateInfoSets rangeCellSets_ += addToSelection ( select, - objects, - "cellSet/" + "cellSet/", + objects ); rangeFaceSets_.reset(select->GetNumberOfArrays()); rangeFaceSets_ += addToSelection ( select, - objects, - "faceSet/" + "faceSet/", + objects ); rangePointSets_.reset(select->GetNumberOfArrays()); rangePointSets_ += addToSelection ( select, - objects, - "pointSet/" + "pointSet/", + objects ); if (debug) @@ -594,21 +542,20 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields HashSet enabled = getSelectedArraySet(select); select->RemoveAllArrays(); - // TODO - currently only get fields from ONE cloud - // have to decide if the second set of fields get mixed in - // or dealt with separately - const arrayRange& range = rangeLagrangian_; if (range.empty()) { return; } - // Add Lagrangian fields even if particles are not enabled? - const int partId = range.start(); - const word cloudName = getReaderPartName(partId); + // Reuse the previously determined cloud information. + DynamicList cloudNames(range.size()); + for (auto partId : range) + { + cloudNames.append(getReaderPartName(partId)); + } - // use the db directly since this might be called without a mesh, + // Use the db directly since this might be called without a mesh, // but the region must get added back in fileName lagrangianPrefix(cloud::prefix); if (meshRegion_ != polyMesh::defaultRegion) @@ -616,19 +563,37 @@ void Foam::vtkPVFoam::updateInfoLagrangianFields lagrangianPrefix = meshRegion_/cloud::prefix; } - IOobjectList objects - ( - dbPtr_(), - dbPtr_().timeName(), - lagrangianPrefix/cloudName - ); + // List of lagrangian fields across all clouds and all times. + // ParaView displays "(partial)" after field names that only apply + // to some of the clouds. + HashTable fields; - addToSelection>(select, objects); - addToSelection>(select, objects); - addToSelection>(select, objects); - addToSelection>(select, objects); - addToSelection>(select, objects); - addToSelection>(select, objects); + for (const instant& t : dbPtr_().times()) + { + for (const auto& cloudName : cloudNames) + { + const HashTable localFields = + IOobjectList + ( + dbPtr_(), + t.name(), + lagrangianPrefix/cloudName + ).classes(); + + forAllConstIters(localFields, iter) + { + fields(iter.key()) |= iter.object(); + } + } + } + + // Known/supported field-types + addToSelection>(select, fields); + addToSelection>(select, fields); + addToSelection>(select, fields); + addToSelection>(select, fields); + addToSelection>(select, fields); + addToSelection>(select, fields); // Restore the enabled selections setSelectedArrayEntries(select, enabled); From 2cfc88fa03d524b1048e0450a2bad986179769a9 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 12 Sep 2017 15:42:10 +0200 Subject: [PATCH 2/2] STYLE: paraview reader attempts to shallow copy nullptr (closes #586) - Can occur if the selected geometry does not actually exist. A non-critical bug since paraview catches this anyhow and just emits a warning message. --- .../graphics/PVReaders/vtkPVFoam/vtkPVFoam.H | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.H b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.H index 55ec9d73e1..226ff6b9bd 100644 --- a/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.H +++ b/applications/utilities/postProcessing/graphics/PVReaders/vtkPVFoam/vtkPVFoam.H @@ -155,7 +155,10 @@ class vtkPVFoam vtkSmartPointer getCopy() const { auto copy = vtkSmartPointer::New(); - copy->ShallowCopy(vtkgeom); + if (vtkgeom) + { + copy->ShallowCopy(vtkgeom); + } return copy; } @@ -163,7 +166,10 @@ class vtkPVFoam void reuse() { dataset = vtkSmartPointer::New(); - dataset->ShallowCopy(vtkgeom); + if (vtkgeom) + { + dataset->ShallowCopy(vtkgeom); + } } //- Set the geometry and make a shallow copy to dataset