diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index a012136f01..9575b36373 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. @@ -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 @@ -231,10 +233,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 @@ -320,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", @@ -451,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()) { @@ -495,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 @@ -516,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); @@ -527,9 +581,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 +695,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 +711,16 @@ int main(int argc, char *argv[]) PtrList vSymTensorFld; PtrList vTensorFld; - if (!specifiedFields || selectedFields.size()) + if + ( + candidateObjects + ( + objects, + vFieldTypes, + specifiedFields, + selectedFields + ).size() + ) { readFields ( @@ -636,7 +730,7 @@ int main(int argc, char *argv[]) selectedFields, vScalarFld ); - print(" volScalar :", Info, vScalarFld); + print(" volScalar :", Info, vScalarFld); readFields ( @@ -646,7 +740,7 @@ int main(int argc, char *argv[]) selectedFields, vVectorFld ); - print(" volVector :", Info, vVectorFld); + print(" volVector :", Info, vVectorFld); readFields ( @@ -656,7 +750,7 @@ int main(int argc, char *argv[]) selectedFields, vSphTensorf ); - print(" volSphericalTensor :", Info, vSphTensorf); + print(" volSphTensor :", Info, vSphTensorf); readFields ( @@ -666,7 +760,7 @@ int main(int argc, char *argv[]) selectedFields, vSymTensorFld ); - print(" volSymmTensor :", Info, vSymTensorFld); + print(" volSymmTensor :", Info, vSymTensorFld); readFields ( @@ -676,7 +770,7 @@ int main(int argc, char *argv[]) selectedFields, vTensorFld ); - print(" volTensor :", Info, vTensorFld); + print(" volTensor :", Info, vTensorFld); } const label nVolFields = @@ -696,7 +790,16 @@ int main(int argc, char *argv[]) PtrList dSymTensorFld; PtrList dTensorFld; - if (!specifiedFields || selectedFields.size()) + if + ( + candidateObjects + ( + objects, + dFieldTypes, + specifiedFields, + selectedFields + ).size() + ) { readFields ( @@ -706,7 +809,7 @@ int main(int argc, char *argv[]) selectedFields, dScalarFld ); - print(" volScalar::Internal :", Info, dScalarFld); + print(" volScalar::Internal :", Info, dScalarFld); readFields ( @@ -716,7 +819,7 @@ int main(int argc, char *argv[]) selectedFields, dVectorFld ); - print(" volVector::Internal :", Info, dVectorFld); + print(" volVector::Internal :", Info, dVectorFld); readFields ( @@ -726,7 +829,7 @@ int main(int argc, char *argv[]) selectedFields, dSphTensorFld ); - print(" volSphericalTensor::Internal :", Info, dSphTensorFld); + print(" volSphTensor::Internal :", Info, dSphTensorFld); readFields ( @@ -736,7 +839,7 @@ int main(int argc, char *argv[]) selectedFields, dSymTensorFld ); - print(" volSymmTensor::Internal :", Info, dSymTensorFld); + print(" volSymmTensor::Internal :", Info, dSymTensorFld); readFields ( @@ -746,7 +849,7 @@ int main(int argc, char *argv[]) selectedFields, dTensorFld ); - print(" volTensor::Internal :", Info, dTensorFld); + print(" volTensor::Internal :", Info, dTensorFld); } const label nDimFields = @@ -767,57 +870,69 @@ 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 ); - print(" pointScalar :", Info, pScalarFld); + print(" pointScalar :", Info, pScalarFld); readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pVectorFld ); - print(" pointVector :", Info, pVectorFld); + print(" pointVector :", Info, pVectorFld); readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pSphTensorFld ); - print(" pointSphTensor : ", Info, pSphTensorFld); + print(" pointSphTensor : ", Info, pSphTensorFld); readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pSymTensorFld ); - print(" pointSymmTensor :", Info, pSymTensorFld); + print(" pointSymmTensor :", Info, pSymTensorFld); readFields ( meshRef, - pointMesh::New(meshRef.baseMesh()), + ptMesh, objects, selectedFields, pTensorFld ); - print(" pointTensor :", Info, pTensorFld); + print(" pointTensor :", Info, pTensorFld); } const label nPointFields = @@ -831,16 +946,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 +963,7 @@ int main(int argc, char *argv[]) // Write mesh vtk::internalWriter writer ( - meshRef.baseMesh(), + meshRef.mesh(), vtuMeshCells, outputName, fmtType @@ -936,7 +1043,7 @@ int main(int argc, char *argv[]) selectedFields, sScalarFld ); - print(" surfScalar :", Info, sScalarFld); + print(" surfScalar :", Info, sScalarFld); PtrList sVectorFld; readFields @@ -947,7 +1054,7 @@ int main(int argc, char *argv[]) selectedFields, sVectorFld ); - print(" surfVector :", Info, sVectorFld); + print(" surfVector :", Info, sVectorFld); if (sScalarFld.size()) { @@ -1006,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 @@ -1076,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 ); @@ -1095,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(); @@ -1146,7 +1253,7 @@ int main(int argc, char *argv[]) // //--------------------------------------------------------------------- - if (doFaceZones) + if (doFaceZones && !mesh.faceZones().empty()) { PtrList sScalarFld; readFields @@ -1157,7 +1264,7 @@ int main(int argc, char *argv[]) selectedFields, sScalarFld ); - print(" surfScalar :", Info, sScalarFld); + print(" surfScalar :", Info, sScalarFld); PtrList sVectorFld; readFields @@ -1168,20 +1275,16 @@ int main(int argc, char *argv[]) selectedFields, sVectorFld ); - print(" surfVector :", Info, sVectorFld); + 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 = ( fvPath/fz.name() - / (meshRef.useSubMesh() ? cellSetName : fz.name()) + / (meshRef.useSubMesh() ? cellSubsetName : fz.name()) + "_" + timeDesc ); @@ -1221,10 +1324,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); @@ -1246,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 @@ -1264,7 +1365,7 @@ int main(int argc, char *argv[]) sphericalTensorIOField::typeName ) ); - Info<< " spherical tensors :"; + Info<< " sphTensors :"; print(Info, sphereNames); wordList symmNames @@ -1274,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 @@ -1366,13 +1467,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,