From 6dd5a5f35f567d2d1f9fab594a1437bc98613292 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 4 Jul 2017 13:19:16 +0200 Subject: [PATCH 1/3] BUG: foamToVTK -cellSet produces rubbish or segfault (closes #516) - erroneous double logic for subset meshes. The underlying vtk::vtuCells uses a cellMap to map into a global field, which also allows handling of decomposed polyhedral cells. If a mesh subset is involved (eg, cellSet, cellZone), then the set/zone cellMap can be used to ensure that the original number is properly adjusted. For foamToVTK, the meshSubsetHelper already does the subsetting and is used when loading fields. Does not affect ParaView reader module since there we work on the full field and do the subsetting manually (using the cellMap). --- .../dataConversion/foamToVTK/foamToVTK.C | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index a012136f01..ccc00ba5d4 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -831,16 +831,8 @@ int main(int argc, char *argv[]) { if (vtuMeshCells.empty()) { + // subMesh or baseMesh vtuMeshCells.reset(meshRef.mesh()); - - // Convert cellMap, addPointCellLabels to global cell ids - if (meshRef.useSubMesh()) - { - vtuMeshCells.renumberCells - ( - meshRef.subsetter().cellMap() - ); - } } // Create file and write header @@ -856,7 +848,7 @@ int main(int argc, char *argv[]) // Write mesh vtk::internalWriter writer ( - meshRef.baseMesh(), + meshRef.mesh(), vtuMeshCells, outputName, fmtType From c5bd5393df6f12dbc2dbfa260c1b9b788c2e3784 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 4 Jul 2017 11:57:54 +0200 Subject: [PATCH 2/3] ENH: lazier field loading in foamToVTK - avoid loading surface fields if there are no faceZones - avoid pointMesh if there are no appropriate point fields --- .../dataConversion/foamToVTK/foamToVTK.C | 146 ++++++++++++++---- .../dataConversion/foamToVTK/readFields.C | 21 +-- .../dataConversion/foamToVTK/readFields.H | 4 +- 3 files changed, 134 insertions(+), 37 deletions(-) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index ccc00ba5d4..7896889cb0 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -55,7 +55,7 @@ Usage - \par -fields \ Convert selected fields only. For example, \verbatim - -fields "( p T U )" + -fields '( p T U )' \endverbatim The quoting is required to avoid shell expansions and to pass the information as a single argument. @@ -231,10 +231,49 @@ labelList getSelectedPatches Info<< " patch " << patchi << " " << pp.name() << endl; } } + return patchIDs.shrink(); } +HashTable candidateObjects +( + const IOobjectList& objects, + const wordHashSet& supportedTypes, + const bool specifiedFields, + const wordHashSet& selectedFields +) +{ + // Special case = no fields + if (specifiedFields && selectedFields.empty()) + { + return HashTable(); + } + + HashTable usable = objects.classes(); + + // Limited to types that we explicitly handle + usable.retain(supportedTypes); + + // If specified, further limit to selected fields + if (specifiedFields) + { + forAllIters(usable, iter) + { + iter.object().retain(selectedFields); + } + + // Prune entries without any fields + usable.filterValues + ( + [](const wordHashSet& vals){ return !vals.empty(); } + ); + } + + return usable; +} + + // // Process args for output options // Default from foamVtkOutputOptions is inline ASCII xml @@ -527,9 +566,39 @@ int main(int argc, char *argv[]) #include "findClouds.H" - forAll(timeDirs, timeI) + // Supported volume field types + const wordHashSet vFieldTypes { - runTime.setTime(timeDirs[timeI], timeI); + volScalarField::typeName, + volVectorField::typeName, + volSphericalTensorField::typeName, + volSymmTensorField::typeName, + volTensorField::typeName + }; + + // Supported dimensioned field types + const wordHashSet dFieldTypes + { + volScalarField::Internal::typeName, + volVectorField::Internal::typeName, + volSphericalTensorField::Internal::typeName, + volSymmTensorField::Internal::typeName, + volTensorField::Internal::typeName + }; + + // Supported point field types + const wordHashSet pFieldTypes + { + pointScalarField::typeName, + pointVectorField::typeName, + pointSphericalTensorField::typeName, + pointSymmTensorField::typeName, + pointTensorField::typeName + }; + + forAll(timeDirs, timei) + { + runTime.setTime(timeDirs[timei], timei); Info<< "Time: " << runTime.timeName() << endl; @@ -611,14 +680,15 @@ int main(int argc, char *argv[]) // Search for list of objects for this time IOobjectList objects(mesh, runTime.timeName()); - HashSet selectedFields; + wordHashSet selectedFields; const bool specifiedFields = args.optionReadIfPresent ( "fields", selectedFields ); - // Construct the vol fields (on the original mesh if subsetted) + // Construct the vol fields + // References the original mesh, but uses subsetted portion only. PtrList vScalarFld; PtrList vVectorFld; @@ -626,7 +696,16 @@ int main(int argc, char *argv[]) PtrList vSymTensorFld; PtrList vTensorFld; - if (!specifiedFields || selectedFields.size()) + if + ( + candidateObjects + ( + objects, + vFieldTypes, + specifiedFields, + selectedFields + ).size() + ) { readFields ( @@ -696,7 +775,16 @@ int main(int argc, char *argv[]) PtrList dSymTensorFld; PtrList dTensorFld; - if (!specifiedFields || selectedFields.size()) + if + ( + candidateObjects + ( + objects, + dFieldTypes, + specifiedFields, + selectedFields + ).size() + ) { readFields ( @@ -767,12 +855,24 @@ int main(int argc, char *argv[]) // Construct pointMesh only if necessary since it constructs edge // addressing (expensive on polyhedral meshes) - if (!noPointValues && !(specifiedFields && selectedFields.empty())) + if + ( + !noPointValues + && candidateObjects + ( + objects, + pFieldTypes, + specifiedFields, + selectedFields + ).size() + ) { + const pointMesh& ptMesh = pointMesh::New(meshRef.baseMesh()); + readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pScalarFld @@ -782,7 +882,7 @@ int main(int argc, char *argv[]) readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pVectorFld @@ -792,7 +892,7 @@ int main(int argc, char *argv[]) readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pSphTensorFld @@ -802,7 +902,7 @@ int main(int argc, char *argv[]) readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pSymTensorFld @@ -812,7 +912,7 @@ int main(int argc, char *argv[]) readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pTensorFld @@ -1138,7 +1238,7 @@ int main(int argc, char *argv[]) // //--------------------------------------------------------------------- - if (doFaceZones) + if (doFaceZones && !mesh.faceZones().empty()) { PtrList sScalarFld; readFields @@ -1162,12 +1262,8 @@ int main(int argc, char *argv[]) ); print(" surfVector :", Info, sVectorFld); - const faceZoneMesh& zones = mesh.faceZones(); - - forAll(zones, zoneI) + for (const faceZone& fz : mesh.faceZones()) { - const faceZone& fz = zones[zoneI]; - mkDir(fvPath/fz.name()); fileName outputName = @@ -1213,10 +1309,8 @@ int main(int argc, char *argv[]) // //--------------------------------------------------------------------- - forAll(cloudNames, cloudNo) + for (const fileName& cloudName : cloudNames) { - const fileName& cloudName = cloudNames[cloudNo]; - // Always create the cloud directory. mkDir(fvPath/cloud::prefix/cloudName); @@ -1358,13 +1452,13 @@ int main(int argc, char *argv[]) dirs.setSize(sz+1); dirs[sz] = "."; - forAll(dirs, i) + for (const fileName& subDir : dirs) { - fileNameList subFiles(readDir(procVTK/dirs[i], fileName::FILE)); + fileNameList subFiles(readDir(procVTK/subDir, fileName::FILE)); - forAll(subFiles, j) + for (const fileName& subFile : subFiles) { - fileName procFile(procVTK/dirs[i]/subFiles[j]); + fileName procFile(procVTK/subDir/subFile); if (exists(procFile)) { diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C index 172a83cf23..1db40528a1 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.C @@ -34,7 +34,7 @@ namespace Foam // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // template -void readFields +label readFields ( const meshSubsetHelper& helper, const typename GeoField::Mesh& mesh, @@ -43,29 +43,32 @@ void readFields PtrList& fields ) { - // Search list of objects for fields of type GeomField - IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName)); - - // Construct the fields - fields.setSize(fieldObjects.size()); label nFields = 0; - forAllConstIter(IOobjectList, fieldObjects, iter) + // Available fields of type GeomField + const wordList fieldNames = objects.sortedNames(GeoField::typeName); + + fields.setSize(fieldNames.size()); + + // Construct the fields + for (const word& fieldName : fieldNames) { - if (selectedFields.empty() || selectedFields.found(iter()->name())) + if (selectedFields.empty() || selectedFields.found(fieldName)) { fields.set ( nFields++, helper.interpolate ( - GeoField(*iter(), mesh) + GeoField(*(objects[fieldName]), mesh) ).ptr() ); } } fields.setSize(nFields); + + return nFields; } diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.H index 085570d685..7021385255 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.H +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/readFields.H @@ -44,9 +44,9 @@ SourceFiles namespace Foam { -// Read the fields and optionally subset and put on the pointer list +// Read the fields, optionally subset, and place on the pointer list template -void readFields +label readFields ( const meshSubsetHelper& helper, const typename GeoField::Mesh& mesh, From e62e34f0f0ab78fd10fdd36081832d52a505de5a Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 4 Jul 2017 14:16:18 +0200 Subject: [PATCH 3/3] ENH: add -cellZone option to foamToVTK --- .../dataConversion/foamToVTK/foamToVTK.C | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index 7896889cb0..9575b36373 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -64,10 +64,12 @@ Usage Write surfaceScalarFields (e.g., phi) - \par -cellSet \ - - \par -faceSet \ + - \par -cellZone \ + Restrict conversion to either the cellSet or the cellZone. + - \par -faceSet \ - \par -pointSet \ - Restrict conversion to the cellSet, faceSet or pointSet. + Restrict conversion to the faceSet or pointSet. - \par -nearCellValue Output cell value on patches instead of patch value itself @@ -359,6 +361,12 @@ int main(int argc, char *argv[]) "convert a mesh subset corresponding to the specified cellSet" ); argList::addOption + ( + "cellZone", + "name", + "convert a mesh subset corresponding to the specified cellZone" + ); + argList::addOption ( "faceSet", "name", @@ -490,10 +498,17 @@ int main(int argc, char *argv[]) string vtkName = runTime.caseName(); - word cellSetName; - if (args.optionReadIfPresent("cellSet", cellSetName)) + meshSubsetHelper::subsetType cellSubsetType = meshSubsetHelper::NONE; + word cellSubsetName; + if (args.optionReadIfPresent("cellSet", cellSubsetName)) { - vtkName = cellSetName; + vtkName = cellSubsetName; + cellSubsetType = meshSubsetHelper::SET; + } + else if (args.optionReadIfPresent("cellZone", cellSubsetName)) + { + vtkName = cellSubsetName; + cellSubsetType = meshSubsetHelper::ZONE; } else if (Pstream::parRun()) { @@ -534,7 +549,7 @@ int main(int argc, char *argv[]) ( args.optionFound("time") || args.optionFound("latestTime") - || cellSetName.size() + || cellSubsetName.size() || faceSetName.size() || pointSetName.size() || regionName != polyMesh::defaultRegion @@ -555,7 +570,7 @@ int main(int argc, char *argv[]) instantList timeDirs = timeSelector::select0(runTime, args); // Mesh wrapper: does subsetting and decomposition - meshSubsetHelper meshRef(mesh, meshSubsetHelper::SET, cellSetName); + meshSubsetHelper meshRef(mesh, cellSubsetType, cellSubsetName); // Collect decomposition information etc. vtk::vtuCells vtuMeshCells(fmtType, decomposePoly); @@ -715,7 +730,7 @@ int main(int argc, char *argv[]) selectedFields, vScalarFld ); - print(" volScalar :", Info, vScalarFld); + print(" volScalar :", Info, vScalarFld); readFields ( @@ -725,7 +740,7 @@ int main(int argc, char *argv[]) selectedFields, vVectorFld ); - print(" volVector :", Info, vVectorFld); + print(" volVector :", Info, vVectorFld); readFields ( @@ -735,7 +750,7 @@ int main(int argc, char *argv[]) selectedFields, vSphTensorf ); - print(" volSphericalTensor :", Info, vSphTensorf); + print(" volSphTensor :", Info, vSphTensorf); readFields ( @@ -745,7 +760,7 @@ int main(int argc, char *argv[]) selectedFields, vSymTensorFld ); - print(" volSymmTensor :", Info, vSymTensorFld); + print(" volSymmTensor :", Info, vSymTensorFld); readFields ( @@ -755,7 +770,7 @@ int main(int argc, char *argv[]) selectedFields, vTensorFld ); - print(" volTensor :", Info, vTensorFld); + print(" volTensor :", Info, vTensorFld); } const label nVolFields = @@ -794,7 +809,7 @@ int main(int argc, char *argv[]) selectedFields, dScalarFld ); - print(" volScalar::Internal :", Info, dScalarFld); + print(" volScalar::Internal :", Info, dScalarFld); readFields ( @@ -804,7 +819,7 @@ int main(int argc, char *argv[]) selectedFields, dVectorFld ); - print(" volVector::Internal :", Info, dVectorFld); + print(" volVector::Internal :", Info, dVectorFld); readFields ( @@ -814,7 +829,7 @@ int main(int argc, char *argv[]) selectedFields, dSphTensorFld ); - print(" volSphericalTensor::Internal :", Info, dSphTensorFld); + print(" volSphTensor::Internal :", Info, dSphTensorFld); readFields ( @@ -824,7 +839,7 @@ int main(int argc, char *argv[]) selectedFields, dSymTensorFld ); - print(" volSymmTensor::Internal :", Info, dSymTensorFld); + print(" volSymmTensor::Internal :", Info, dSymTensorFld); readFields ( @@ -834,7 +849,7 @@ int main(int argc, char *argv[]) selectedFields, dTensorFld ); - print(" volTensor::Internal :", Info, dTensorFld); + print(" volTensor::Internal :", Info, dTensorFld); } const label nDimFields = @@ -877,7 +892,7 @@ int main(int argc, char *argv[]) selectedFields, pScalarFld ); - print(" pointScalar :", Info, pScalarFld); + print(" pointScalar :", Info, pScalarFld); readFields ( @@ -887,7 +902,7 @@ int main(int argc, char *argv[]) selectedFields, pVectorFld ); - print(" pointVector :", Info, pVectorFld); + print(" pointVector :", Info, pVectorFld); readFields ( @@ -897,7 +912,7 @@ int main(int argc, char *argv[]) selectedFields, pSphTensorFld ); - print(" pointSphTensor : ", Info, pSphTensorFld); + print(" pointSphTensor : ", Info, pSphTensorFld); readFields ( @@ -907,7 +922,7 @@ int main(int argc, char *argv[]) selectedFields, pSymTensorFld ); - print(" pointSymmTensor :", Info, pSymTensorFld); + print(" pointSymmTensor :", Info, pSymTensorFld); readFields ( @@ -917,7 +932,7 @@ int main(int argc, char *argv[]) selectedFields, pTensorFld ); - print(" pointTensor :", Info, pTensorFld); + print(" pointTensor :", Info, pTensorFld); } const label nPointFields = @@ -1028,7 +1043,7 @@ int main(int argc, char *argv[]) selectedFields, sScalarFld ); - print(" surfScalar :", Info, sScalarFld); + print(" surfScalar :", Info, sScalarFld); PtrList sVectorFld; readFields @@ -1039,7 +1054,7 @@ int main(int argc, char *argv[]) selectedFields, sVectorFld ); - print(" surfVector :", Info, sVectorFld); + print(" surfVector :", Info, sVectorFld); if (sScalarFld.size()) { @@ -1098,11 +1113,11 @@ int main(int argc, char *argv[]) fileName outputName ( fvPath/"allPatches" - / (meshRef.useSubMesh() ? cellSetName : "allPatches") + / (meshRef.useSubMesh() ? cellSubsetName : "allPatches") + "_" + timeDesc ); - Info<< " Combined patches : " + Info<< " Combined patches : " << relativeName(runTime, outputName) << nl; vtk::patchWriter writer @@ -1168,7 +1183,7 @@ int main(int argc, char *argv[]) fileName outputName ( fvPath/pp.name() - / (meshRef.useSubMesh() ? cellSetName : pp.name()) + / (meshRef.useSubMesh() ? cellSubsetName : pp.name()) + "_" + timeDesc ); @@ -1187,7 +1202,7 @@ int main(int argc, char *argv[]) if (!isA(pp)) { // VolFields + patchID - writer.beginCellData(1+nVolFields); + writer.beginCellData(1 + nVolFields); // Write patchID field writer.writePatchIDs(); @@ -1249,7 +1264,7 @@ int main(int argc, char *argv[]) selectedFields, sScalarFld ); - print(" surfScalar :", Info, sScalarFld); + print(" surfScalar :", Info, sScalarFld); PtrList sVectorFld; readFields @@ -1260,7 +1275,7 @@ int main(int argc, char *argv[]) selectedFields, sVectorFld ); - print(" surfVector :", Info, sVectorFld); + print(" surfVector :", Info, sVectorFld); for (const faceZone& fz : mesh.faceZones()) { @@ -1269,7 +1284,7 @@ int main(int argc, char *argv[]) fileName outputName = ( fvPath/fz.name() - / (meshRef.useSubMesh() ? cellSetName : fz.name()) + / (meshRef.useSubMesh() ? cellSubsetName : fz.name()) + "_" + timeDesc ); @@ -1332,15 +1347,15 @@ int main(int argc, char *argv[]) if (sprayObjs.found("positions")) { wordList labelNames(sprayObjs.names(labelIOField::typeName)); - Info<< " labels :"; + Info<< " labels :"; print(Info, labelNames); wordList scalarNames(sprayObjs.names(scalarIOField::typeName)); - Info<< " scalars :"; + Info<< " scalars :"; print(Info, scalarNames); wordList vectorNames(sprayObjs.names(vectorIOField::typeName)); - Info<< " vectors :"; + Info<< " vectors :"; print(Info, vectorNames); wordList sphereNames @@ -1350,7 +1365,7 @@ int main(int argc, char *argv[]) sphericalTensorIOField::typeName ) ); - Info<< " spherical tensors :"; + Info<< " sphTensors :"; print(Info, sphereNames); wordList symmNames @@ -1360,11 +1375,11 @@ int main(int argc, char *argv[]) symmTensorIOField::typeName ) ); - Info<< " symm tensors :"; + Info<< " symmTensors :"; print(Info, symmNames); wordList tensorNames(sprayObjs.names(tensorIOField::typeName)); - Info<< " tensors :"; + Info<< " tensors :"; print(Info, tensorNames); vtk::lagrangianWriter writer