foamRestoreFields.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2018-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Application
27  foamRestoreFields
28 
29 Group
30  grpMiscUtilities
31 
32 Description
33  Adjust (restore) field names by removing the ending.
34  The fields are selected automatically or can be specified as optional
35  command arguments.
36 
37  The operation 'mean' renames files ending with 'Mean' and makes
38  a backup of existing names, using the '.orig' ending.
39 
40  The operation 'orig' renames files ending with '.orig'.
41 
42 Usage
43  \b foamRestoreFields [OPTION]
44 
45  Options:
46  - \par -method mean | orig
47  The renaming method.
48 
49  - \par -processor
50  Use processor directories, taking information from processor0/
51 
52  - \par -dry-run
53  Test without actually moving/renaming files.
54 
55  - \par -verbose
56  Additional verbosity.
57 
58 \*---------------------------------------------------------------------------*/
59 
60 #include "argList.H"
61 #include "autoPtr.H"
62 #include "profiling.H"
63 #include "timeSelector.H"
64 #include "Enum.H"
65 #include "TimePaths.H"
66 #include "ListOps.H"
67 #include "stringOps.H"
68 
69 using namespace Foam;
70 
71 // Many ways to name processor directories
72 //
73 // Uncollated | "processor0", "processor1" ...
74 // Collated | "processors<N>"
75 // Host collated | "processors<N>_<low>-<high>"
76 
77 const regExp matcher("processors?[0-9]+(_[0-9]+-[0-9]+)?");
78 
79 bool isProcessorDir(const string& dir)
80 {
81  return (dir.starts_with("processor") && matcher.match(dir));
82 }
83 
84 
85 //- The known and support types of operations
86 enum restoreMethod
87 {
88  MEAN,
89  ORIG
90 };
91 
92 
93 static const Enum<restoreMethod> methodNames
94 {
95  { restoreMethod::MEAN, "mean" },
96  { restoreMethod::ORIG, "orig" },
97 };
98 
99 
100 static const Enum<restoreMethod> methodEndings
101 {
102  { restoreMethod::MEAN, "Mean" },
103  { restoreMethod::ORIG, ".orig" },
104 };
105 
106 
107 // Files in given directory at time instant
108 inline wordList getFiles(const fileName& dir, const word& instance)
109 {
110  return ListOps::create<word>
111  (
112  Foam::readDir(dir/instance, fileName::FILE),
114  );
115 }
116 
117 
118 // Command-line options: -dry-run, -verbose
119 bool dryrun = false, verbose = false;
120 
121 
122 // Use predefined method to walk the directory and rename the files.
123 //
124 // If no target names are specified, the existing files are scanned for
125 // candidates.
126 label restoreFields
127 (
128  const restoreMethod method,
129  const fileName& dirName,
130  const wordHashSet& existingFiles,
131  const wordList& targetNames
132 )
133 {
134  // The file ending to search for.
135  const word ending(methodEndings[method]);
136 
137  // The backup ending for existing (if any)
138  word bak;
139 
140  switch (method)
141  {
142  case restoreMethod::MEAN:
143  bak = methodEndings[restoreMethod::ORIG];
144  break;
145 
146  default:
147  break;
148  }
149 
150  wordHashSet targets(targetNames);
151 
152  if (targets.empty())
153  {
154  // No target names specified - scan existing files for candidates.
155 
156  for (word f : existingFiles) // Operate on a copy
157  {
158  // Eg, check for "UMean" and save as "U"
159  if (f.removeEnd(ending) && f.size())
160  {
161  targets.insert(f);
162  }
163  }
164  }
165 
166  if (verbose)
167  {
168  Info<< "directory " << dirName.name() << nl;
169  }
170 
171  // Count of files moved, including backups
172  label count = 0;
173 
174  for (const word& dst : targets)
175  {
176  const word src(dst + ending);
177 
178  if (!existingFiles.found(src))
179  {
180  continue;
181  }
182 
183  if (bak.size() && existingFiles.found(dst))
184  {
185  if (dryrun || Foam::mv(dirName/dst, dirName/dst + bak))
186  {
187  Info<< " mv " << dst << " " << word(dst + bak) << nl;
188  ++count;
189  }
190  }
191 
192  if (dryrun || Foam::mv(dirName/src, dirName/dst))
193  {
194  Info<< " mv " << src << " " << dst << nl;
195  ++count;
196  }
197  }
198 
199  return count;
200 }
201 
202 
203 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
204 
205 int main(int argc, char *argv[])
206 {
208  (
209  "Restore field names by removing the ending. Fields are selected"
210  " automatically or can be specified as optional command arguments"
211  );
212 
213  profiling::disable(); // Disable profiling (and its output)
215  argList::noFunctionObjects(); // Never use function objects
217  (
218  "method",
219  "name",
220  "The restore method (mean|orig) [MANDATORY]. "
221  "With <mean> renames files ending with 'Mean' "
222  "(with backup of existing as '.orig'). "
223  "With <orig> renames files ending with '.orig'"
224  );
226  (
227  "processor",
228  "In serial mode use times from processor0/ directory, but operate on "
229  "processor\\d+ directories"
230  );
232  (
233  "Report action without moving/renaming"
234  );
236  (
237  "Additional verbosity"
238  );
239 
240  // Arguments are optional (non-mandatory)
242  argList::addArgument("fieldName ... fieldName");
243 
244  timeSelector::addOptions(true, true); // constant(true), zero(true)
245 
246  #include "setRootCase.H"
247 
248  dryrun = args.dryRun();
249  verbose = args.verbose();
250 
251 
252  // Construct time
253  // ~~~~~~~~~~~~~~
254 
255  restoreMethod method = restoreMethod::ORIG;
256  {
257  word methodName;
258 
259  if
260  (
261  args.readIfPresent("method", methodName)
262  && methodNames.found(methodName)
263  )
264  {
265  method = methodNames[methodName];
266  }
267  else
268  {
269  Info<< "Unspecified or unknown method name" << nl
270  << "Valid methods: "
271  << flatOutput(methodNames.sortedToc()) << nl
272  << "... stopping" << nl << nl;
273  return 1;
274  }
275  }
276 
277  // Optional base or target field names (eg, 'U', 'T' etc)
278  wordList targetNames;
279  if (args.size() > 1)
280  {
281  targetNames.resize(args.size()-1);
282  wordHashSet uniq;
283 
284  for (label argi=1; argi < args.size(); ++argi)
285  {
286  if (uniq.insert(args[argi]))
287  {
288  targetNames[uniq.size()-1] = args[argi];
289  }
290  }
291 
292  targetNames.resize(uniq.size());
293 
294  if (verbose)
295  {
296  Info<< nl
297  << "using method=" << methodNames[method] << nl
298  << "with fields " << flatOutput(targetNames) << nl;
299  }
300  }
301  else if (verbose)
302  {
303  Info<< nl
304  << "using method=" << methodNames[method] << nl
305  << "autodetect fields" << nl;
306  }
307 
308 
309  // Get times list from the master processor and subset based on
310  // command-line options
311 
312  label nProcs = 0;
313  autoPtr<TimePaths> timePaths;
314 
315  if (args.found("processor") && !Pstream::parRun())
316  {
317  // Determine the processor count
318  nProcs = fileHandler().nProcs(args.path());
319 
320  if (!nProcs)
321  {
323  << "No processor* directories found"
324  << exit(FatalError);
325  }
326 
327  // Obtain time directory names from "processor0/" only
328  timePaths = autoPtr<TimePaths>::New
329  (
330  args.rootPath(),
331  args.caseName()/"processor0"
332  );
333  }
334  else
335  {
336  timePaths = autoPtr<TimePaths>::New
337  (
338  args.rootPath(),
339  args.caseName()
340  );
341  }
342 
343  const instantList timeDirs(timeSelector::select(timePaths->times(), args));
344 
345  fileNameList procDirs;
346  label leadProcIdx = -1;
347 
348  if (timeDirs.empty())
349  {
350  Info<< "No times selected" << nl;
351  }
352  else if (nProcs)
353  {
354  procDirs =
356  (
357  args.path(),
359  false, // No gzip anyhow
360  false // Do not follow linkts
361  );
362 
363  inplaceSubsetList(procDirs, isProcessorDir);
364 
365  // Perhaps not needed
366  Foam::sort(procDirs, stringOps::natural_sort());
367 
368  // Decide who will be the "leading" processor for obtaining names
369  // - processor0
370  // - processors<N>
371  // - processors<N>_0-<high>
372 
373  // Uncollated
374  leadProcIdx = procDirs.find("processor0");
375 
376  if (!procDirs.empty())
377  {
378  if (leadProcIdx < 0)
379  {
380  // Collated
381  leadProcIdx = procDirs.find("processors" + Foam::name(nProcs));
382  }
383 
384  if (leadProcIdx < 0)
385  {
386  // Host-collated
387  const std::string prefix
388  (
389  "processors" + Foam::name(nProcs) + "_0-"
390  );
391 
392  forAll(procDirs, idx)
393  {
394  if (procDirs[idx].starts_with(prefix))
395  {
396  leadProcIdx = idx;
397  break;
398  }
399  }
400  }
401 
402  // Just default to anything (safety)
403  if (leadProcIdx < 0)
404  {
405  leadProcIdx = 0;
406  }
407  }
408  }
409 
410 
411  for (const instant& t : timeDirs)
412  {
413  const word& timeName = t.name();
414 
415  Info<< "\nTime = " << timeName << nl;
416 
417  label count = 0;
418  wordList files;
419 
420  if (nProcs)
421  {
422  if (leadProcIdx >= 0)
423  {
424  files = getFiles(args.path()/procDirs[leadProcIdx], timeName);
425  }
426 
427  for (const fileName& procDir : procDirs)
428  {
429  count += restoreFields
430  (
431  method,
432  args.path()/procDir/timeName,
433  wordHashSet(files),
434  targetNames
435  );
436  }
437  }
438  else
439  {
440  if (Pstream::master())
441  {
442  files = getFiles(args.path(), timeName);
443  }
444  Pstream::scatter(files);
445 
446  count += restoreFields
447  (
448  method,
449  args.path()/timeName,
450  wordHashSet(files),
451  targetNames
452  );
453  }
454 
455  if (dryrun)
456  {
457  Info<< "dry-run: ";
458  }
459  Info<< "moved " << count << " files" << nl;
460  }
461 
462  Info<< "\nEnd\n" << endl;
463  return 0;
464 }
465 
466 
467 // ************************************************************************* //
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
profiling.H
Foam::regExpPosix
Wrapper around POSIX extended regular expressions with some additional prefix-handling....
Definition: regExpPosix.H:80
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:53
Foam::fileName::FILE
@ FILE
A file.
Definition: fileName.H:81
Foam::inplaceSubsetList
void inplaceSubsetList(ListType &input, const UnaryPredicate &pred, const bool invert=false)
Definition: ListOpsTemplates.C:687
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:63
Foam::fileName
A class for handling file names.
Definition: fileName.H:71
Foam::List::resize
void resize(const label len)
Definition: ListI.H:132
TimePaths.H
Foam::string::starts_with
bool starts_with(const std::string &s) const
Definition: string.H:293
Foam::argList::caseName
const fileName & caseName() const noexcept
Definition: argListI.H:62
Foam::fileName::name
static std::string name(const std::string &str)
Definition: fileNameI.H:192
Foam::argList::addNote
static void addNote(const string &note)
Definition: argList.C:405
Foam::timeSelector::select
instantList select(const instantList &times) const
Definition: timeSelector.C:82
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Definition: UPstream.H:453
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Definition: gatherScatter.C:144
Foam::fileHandler
const fileOperation & fileHandler()
Definition: fileOperation.C:1478
Foam::endl
Ostream & endl(Ostream &os)
Definition: Ostream.H:381
Foam::HashSet
A HashTable with keys but without contents that is similar to std::unordered_set.
Definition: HashSet.H:73
Foam::argList::readIfPresent
bool readIfPresent(const word &optName, T &val) const
Definition: argListI.H:316
Foam::argList::noMandatoryArgs
static void noMandatoryArgs()
Definition: argList.C:422
forAll
#define forAll(list, i)
Definition: stdFoam.H:349
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Definition: argList.C:294
Foam::argList::noFunctionObjects
static void noFunctionObjects(bool addWithOption=false)
Definition: argList.C:466
Foam::argList::dryRun
int dryRun() const noexcept
Definition: argListI.H:109
Foam::argList::noJobInfo
static void noJobInfo()
Definition: argList.C:486
Foam::Info
messageStream Info
Foam::fileOperation::nProcs
virtual label nProcs(const fileName &dir, const fileName &local="") const
Definition: fileOperation.C:1186
argList.H
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:254
Foam::nameOp
Definition: word.H:247
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::argList::path
fileName path() const
Definition: argListI.H:74
Foam::FatalError
error FatalError
Foam::mv
bool mv(const fileName &src, const fileName &dst, const bool followLink=false)
Definition: POSIX.C:1202
Foam::argList::verbose
int verbose() const noexcept
Definition: argListI.H:121
Foam
Definition: atmBoundaryLayer.C:26
Foam::profiling::disable
static void disable()
Definition: profiling.C:110
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Definition: FlatOutput.H:217
Foam::argList::addDryRunOption
static void addDryRunOption(const string &usage, bool advanced=false)
Definition: argList.C:447
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Foam::argList::addBoolOption
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Definition: argList.C:317
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:49
setRootCase.H
Foam::argList::size
label size() const noexcept
Definition: argListI.H:139
FatalErrorInFunction
#define FatalErrorInFunction
Definition: error.H:465
Foam::nl
constexpr char nl
Definition: Ostream.H:424
f
labelList f(nPoints)
Foam::BitOps::count
unsigned int count(const UList< bool > &bools, const bool val=true)
Definition: BitOps.H:75
Foam::timeSelector::addOptions
static void addOptions(const bool constant=true, const bool withZero=false)
Definition: timeSelector.C:95
Foam::UPstream::parRun
static bool & parRun() noexcept
Definition: UPstream.H:429
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:58
Foam::HashSet::insert
bool insert(const Key &key)
Definition: HashSet.H:191
Foam::fileName::DIRECTORY
@ DIRECTORY
A directory.
Definition: fileName.H:82
timeSelector.H
Foam::stringOps::natural_sort
Definition: stringOpsSort.H:58
Foam::name
word name(const expressions::valueTypeCode typeCode)
Definition: exprTraits.C:52
ListOps.H
Various functions to operate on Lists.
Foam::instant
An instant of time. Contains the time value and name.
Definition: instant.H:48
Foam::argList::addOption
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Definition: argList.C:328
args
Foam::argList args(argc, argv)
stringOps.H
Foam::readDir
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Definition: POSIX.C:878
Foam::argList::rootPath
const fileName & rootPath() const noexcept
Definition: argListI.H:56
Foam::argList::addVerboseOption
static void addVerboseOption(const string &usage, bool advanced=false)
Definition: argList.C:457
Foam::argList::found
bool found(const word &optName) const
Definition: argListI.H:171
autoPtr.H
Enum.H