diff --git a/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C b/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C index 4cae459e9c..d7469d9f05 100644 --- a/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C +++ b/applications/utilities/miscellaneous/foamListTimes/foamListTimes.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2018 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -39,7 +39,7 @@ Usage Options: - \par -processor - List times from processor0/ directory + Times from processor0/ directory - \par -rm Remove selected time directories @@ -58,9 +58,30 @@ Note #include "profiling.H" #include "timeSelector.H" #include "TimePaths.H" +#include "ListOps.H" +#include "stringOps.H" using namespace Foam; +// Many ways to name processor directories +// +// Uncollated | "processor0", "processor1" ... +// Collated (old) | "processors" +// Collated (new) | "processors" +// Host collated | "processors_-" + +const regExp matcher("processors?[0-9]+(_[0-9]+-[0-9]+)?"); + +bool isProcessorDir(const string& dir) +{ + return + ( + dir.starts_with("processor") + && (dir == "processors" || matcher.match(dir)) + ); +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) @@ -95,7 +116,7 @@ int main(int argc, char *argv[]) #include "setRootCase.H" const bool removeFiles(args.found("rm")); - const bool verbose(args.found("verbose")); + bool verbose(args.found("verbose")); // Get times list from the master processor and subset based on @@ -116,6 +137,7 @@ int main(int argc, char *argv[]) << exit(FatalError); } + // Obtain time directory names from "processor0/" only timePaths = autoPtr::New ( args.rootPath(), @@ -140,10 +162,34 @@ int main(int argc, char *argv[]) { if (nProcs) { + fileNameList procDirs + ( + Foam::readDir + ( + args.path(), + fileName::DIRECTORY, + false, // No gzip anyhow + false // Do not follow linkts + ) + ); + + inplaceSubsetList(procDirs, isProcessorDir); + + // Perhaps not needed + /// Foam::sort(procDirs, stringOps::natural_sort()); + if (verbose) { - Info<< "Removing " << nTimes - << " processor time directories" << endl; + InfoErr + << "Removing " << nTimes + << " times in " << procDirs.size() + << " processor directories" << endl; + } + + // No processor directories? - silence verbosity + if (procDirs.empty()) + { + verbose = false; } forAllReverse(timeDirs, timei) @@ -152,25 +198,15 @@ int main(int argc, char *argv[]) if (verbose) { - Info<< " rm " << timeName + InfoErr + << " rm " << timeName << " [" << (nTimes - timei) << '/' << nTimes << ']' << endl; } - fileName path(args.path()/"processors"/timeName); - - rmDir(path, true); - - for (label proci=0; proci" +// Host collated | "processors_-" + +const regExp matcher("processors?[0-9]+(_[0-9]+-[0-9]+)?"); + +bool isProcessorDir(const string& dir) +{ + return + ( + dir.starts_with("processor") + && (dir == "processors" || matcher.match(dir)) + ); +} + + //- The known and support types of operations enum restoreMethod { @@ -311,7 +332,6 @@ int main(int argc, char *argv[]) } // Obtain time directory names from "processor0/" only - timePaths = autoPtr::New ( args.rootPath(), @@ -329,10 +349,77 @@ int main(int argc, char *argv[]) const instantList timeDirs(timeSelector::select(timePaths->times(), args)); + fileNameList procDirs; + label leadProcIdx = -1; + if (timeDirs.empty()) { - Info<< "no times selected" << nl; + Info<< "No times selected" << nl; } + else if (nProcs) + { + procDirs = + Foam::readDir + ( + args.path(), + fileName::DIRECTORY, + false, // No gzip anyhow + false // Do not follow linkts + ); + + inplaceSubsetList(procDirs, isProcessorDir); + + // Perhaps not needed + Foam::sort(procDirs, stringOps::natural_sort()); + + // Decide who will be the "leading" processor for obtaining names + // - processor0 + // - processors + // - processors_0- + + // Uncollated + leadProcIdx = procDirs.find("processor0"); + + if (!procDirs.empty()) + { + if (leadProcIdx < 0) + { + // Collated (old) + leadProcIdx = procDirs.find("processors"); + } + + if (leadProcIdx < 0) + { + // Collated (new) + leadProcIdx = procDirs.find("processors" + Foam::name(nProcs)); + } + + if (leadProcIdx < 0) + { + // Host-collated + const std::string prefix + ( + "processors" + Foam::name(nProcs) + "_0-" + ); + + forAll(procDirs, idx) + { + if (procDirs[idx].starts_with(prefix)) + { + leadProcIdx = idx; + break; + } + } + } + + // Just default to anything (safety) + if (leadProcIdx < 0) + { + leadProcIdx = 0; + } + } + } + for (const instant& t : timeDirs) { @@ -341,28 +428,28 @@ int main(int argc, char *argv[]) Info<< "\nTime = " << timeName << nl; label count = 0; + wordList files; if (nProcs) { - const wordHashSet files - ( - getFiles(args.path()/"processor0", timeName) - ); + if (leadProcIdx >= 0) + { + files = getFiles(args.path()/procDirs[leadProcIdx], timeName); + } - for (label proci=0; proci < nProcs; ++proci) + for (const fileName& procDir : procDirs) { count += restoreFields ( method, - args.path()/("processor" + Foam::name(proci))/timeName, - files, + args.path()/procDir/timeName, + wordHashSet(files), targetNames ); } } else { - wordList files; if (Pstream::master()) { files = getFiles(args.path(), timeName);