fileOperation.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) 2017-2018 OpenFOAM Foundation
9  Copyright (C) 2019-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "fileOperation.H"
31 #include "regIOobject.H"
32 #include "argList.H"
33 #include "HashSet.H"
34 #include "objectRegistry.H"
35 #include "decomposedBlockData.H"
36 #include "polyMesh.H"
37 #include "registerSwitch.H"
38 #include "Time.H"
39 #include <cerrno>
40 #include <cinttypes>
41 
42 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
43 
44 namespace Foam
45 {
46  defineTypeNameAndDebug(fileOperation, 0);
47  defineRunTimeSelectionTable(fileOperation, word);
48 
50  (
51  debug::optimisationSwitches().getOrAdd<word>
52  (
53  "fileHandler",
54  //Foam::fileOperations::uncollatedFileOperation::typeName,
55  "uncollated",
57  )
58  );
59 }
60 
63 ({
64  { fileOperation::NOTFOUND, "notFound" },
65  { fileOperation::ABSOLUTE, "absolute" },
66  { fileOperation::OBJECT, "objectPath" },
67  { fileOperation::WRITEOBJECT, "writeObject" },
68  { fileOperation::PROCUNCOLLATED, "uncollatedProc" },
69  { fileOperation::PROCBASEOBJECT, "globalProc" },
70  { fileOperation::PROCOBJECT, "localProc" },
71  { fileOperation::PARENTOBJECT, "parentObjectPath" },
72  { fileOperation::FINDINSTANCE, "findInstance" },
73  { fileOperation::PROCUNCOLLATEDINSTANCE, "uncollatedProcInstance" },
74  { fileOperation::PROCBASEINSTANCE, "globalProcInstance" },
75  { fileOperation::PROCINSTANCE, "localProcInstance" }
76 });
77 
78 
80 
82 
83 
84 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
85 
86 namespace
87 {
88 
89 // Need to parse the numbers
90 // from "processors(\d+)" and
91 // from "processors(\d+)_(\d+)-(\d+)"
92 //
93 // Receive the string matching "^(\d+)(?:_(\d+)-(\d+))?/?$"
94 //
95 // \1 = numProcs
96 // \2 = firstProc
97 // \3 = lastProc
98 //
99 // Return true on success and set parameters numProcs and group (size,start)
100 //
101 // Use low-level C-string to integer parsing to drive the sequence.
102 //
103 // For simplicity, also skip INT_MAX checks everywhere but check for
104 // - (errno) for success
105 // - (nptr == endptr) for leading junk
106 // - (*endptr != endChar) for trailing junk
107 // - skip INT_MAX checks as being too pessimistic
108 
109 static bool parseProcsNumRange
110 (
111  const std::string str,
112  int& numProcs,
114 )
115 {
116  const char * nptr = str.c_str();
117  char *endptr = nullptr;
118 
119  // 1. numProcs
120  errno = 0;
121  intmax_t parsed = std::strtoimax(nptr, &endptr, 10);
122  if (errno || nptr == endptr) return false; // bad parse
123 
124  const int nProcs = int(parsed);
125 
126  // End of string? Then no range and we are done.
127  if (*endptr == '\0')
128  {
129  numProcs = nProcs;
130  return true;
131  }
132 
133  // Parse point at start of range ('_' character)?
134  if (*endptr != '_') return false;
135  nptr = ++endptr;
136 
137 
138  // 2. firstProc
139  errno = 0;
140  parsed = std::strtoimax(nptr, &endptr, 10);
141  if (errno || nptr == endptr) return false; // bad parse
142 
143  const int firstProc = int(parsed);
144 
145  // Parse point at range separator ('-' character)?
146  if (*endptr != '-') return false;
147  nptr = ++endptr;
148 
149 
150  // 3. lastProc
151  errno = 0;
152  parsed = std::strtoimax(nptr, &endptr, 10);
153  if (errno || nptr == endptr) return false; // bad parse
154 
155  const int lastProc = int(parsed);
156 
157 
158  if
159  (
160  // Parse point at end of string
161  (*endptr == '\0')
162 
163  // Input plausibility
164  // Accept nProcs == 0 in case that becomes useful in the future
165  && (nProcs >= 0 && firstProc >= 0 && firstProc <= lastProc)
166  )
167  {
168  numProcs = nProcs;
169 
170  // Convert first/last to start/size
171  group.reset(firstProc, lastProc-firstProc+1);
172 
173  return true;
174  }
175 
176  return false;
177 }
178 
179 } // End anonymous namespace
180 
181 
182 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
183 
186 (
187  const fileNameList& dirEntries,
188  const word& constantName
189 )
190 {
191  // Check for "constant"
192  bool haveConstant = false;
193 
194  if (!constantName.empty())
195  {
196  for (const fileName& dirName : dirEntries)
197  {
198  if (dirName == constantName)
199  {
200  haveConstant = true;
201  break;
202  }
203  }
204  }
205 
206  instantList times(dirEntries.size() + 1);
207  label nTimes = 0;
208 
209  if (haveConstant)
210  {
211  times[nTimes].value() = 0;
212  times[nTimes].name() = constantName;
213  ++nTimes;
214  }
215 
216  // Parse directory entries for scalar values
217  for (const fileName& dirName : dirEntries)
218  {
219  if (readScalar(dirName, times[nTimes].value()))
220  {
221  times[nTimes].name() = dirName;
222  ++nTimes;
223  }
224  }
225 
226  times.resize(nTimes);
227 
228  if (haveConstant)
229  {
230  if (nTimes > 2)
231  {
232  std::sort(&times[1], times.end(), instant::less());
233  }
234  }
235  else if (nTimes > 1)
236  {
237  std::sort(times.begin(), times.end(), instant::less());
238  }
239 
240  return times;
241 }
242 
243 
244 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
245 
247 {
248  if (!monitorPtr_)
249  {
250  monitorPtr_.reset
251  (
252  new fileMonitor
253  (
256  )
257  );
258  }
259  return *monitorPtr_;
260 }
261 
262 
264 (
265  const instantList& extraTimes,
266  const word& constantName,
267  instantList& times
268 )
269 {
270  if (extraTimes.size())
271  {
272  const bool haveConstant =
273  (
274  times.size()
275  && times[0].name() == constantName
276  );
277 
278  const bool haveExtraConstant =
279  (
280  extraTimes.size()
281  && extraTimes[0].name() == constantName
282  );
283 
284  // Combine times
285  instantList combinedTimes(times.size()+extraTimes.size());
286  label sz = 0;
287  label extrai = 0;
288  if (haveExtraConstant)
289  {
290  extrai = 1;
291  if (!haveConstant)
292  {
293  combinedTimes[sz++] = extraTimes[0]; // constant
294  }
295  }
296  forAll(times, i)
297  {
298  combinedTimes[sz++] = times[i];
299  }
300  for (; extrai < extraTimes.size(); extrai++)
301  {
302  combinedTimes[sz++] = extraTimes[extrai];
303  }
304  combinedTimes.setSize(sz);
305  times.transfer(combinedTimes);
306 
307  // Sort
308  if (times.size() > 1)
309  {
310  label starti = 0;
311  if (times[0].name() == constantName)
312  {
313  starti = 1;
314  }
315  std::sort(&times[starti], times.end(), instant::less());
316 
317  // Filter out duplicates
318  label newi = starti+1;
319  for (label i = newi; i < times.size(); i++)
320  {
321  if (times[i].value() != times[i-1].value())
322  {
323  if (newi != i)
324  {
325  times[newi] = times[i];
326  }
327  newi++;
328  }
329  }
330 
331  times.setSize(newi);
332  }
333  }
334 }
335 
336 
338 {
339  return (isFile ? Foam::isFile(f) : Foam::isDir(f));
340 }
341 
342 
345 (
346  const fileName& fName,
347  const bool syncPar
348 ) const
349 {
350  // If path is local to a processor (e.g. contains 'processor2')
351  // find the corresponding actual processor directory (e.g. 'processors4')
352  // and index (2)
353 
354  fileName path, pDir, local;
356  label numProcs;
357  const label proci =
358  splitProcessorPath(fName, path, pDir, local, group, numProcs);
359 
360  if (proci != -1)
361  {
362  const fileName procPath(path/pDir);
363 
364  const auto iter = procsDirs_.cfind(procPath);
365 
366  if (iter.found())
367  {
368  return iter.val();
369  }
370 
371  DynamicList<dirIndex> procDirs;
372  fileNameList dirEntries;
373 
374  // Read all directories to see any beginning with processor
375  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
376 
377  // Note: use parallel synchronised reading so cache will be same
378  // order on all processors
379 
380  const bool readDirMasterOnly
381  (
384  );
385 
386  // As byproduct of the above selection, we exclude masterUncollated
387  // from using read/send, but that doesn't matter since that is what
388  // its own internals for readDir() do anyhow.
389 
390  if (readDirMasterOnly && Pstream::parRun() && !distributed())
391  {
392  // Non-distributed.
393  // Read on master only and send to subProcs
394 
395  if (Pstream::master())
396  {
397  dirEntries = Foam::readDir(path, fileName::Type::DIRECTORY);
398 
399  DebugInfo
400  << "readDir on master: send " << dirEntries.size()
401  << " names to sub-processes" << endl;
402  }
403 
404  Pstream::scatter(dirEntries, Pstream::msgType(), comm_);
405  }
406  else
407  {
408  // Serial or distributed roots.
409  // Handle readDir() with virtual method
410 
411  if (debug)
412  {
413  Pout<< "readDir without special master/send treatment"
414  << endl;
415  }
416 
417  dirEntries = readDir(path, fileName::Type::DIRECTORY);
418  }
419 
420 
421  // Extract info from processorsDDD or processorDDD:
422  // - highest processor number
423  // - directory+offset containing data for proci
424  label maxProc = -1;
425 
426  for (const fileName& dirN : dirEntries)
427  {
428  // Analyse directory name
429  fileName rp, rd, rl;
430  label rNum;
431  const label readProci =
432  splitProcessorPath(dirN, rp, rd, rl, group, rNum);
433 
434  maxProc = max(maxProc, readProci);
435 
436  if (proci == readProci)
437  {
438  // Found "processorDDD". No need for index.
439  procDirs.append
440  (
441  dirIndex
442  (
443  dirN,
444  Tuple2<pathType, label>(PROCUNCOLLATED, -1)
445  )
446  );
447  }
448  else if (group.found(proci))
449  {
450  // "processorsDDD_start-end"
451  // Found the file that contains the data for proci
452  const label localProci = proci - group.start();
453  procDirs.append
454  (
455  dirIndex
456  (
457  dirN,
458  Tuple2<pathType, label>(PROCOBJECT, localProci)
459  )
460  );
461  }
462  if (rNum != -1)
463  {
464  // Direct detection of processorsDDD
465  maxProc = rNum-1;
466 
467  if (group.empty())
468  {
469  // "processorsDDD"
470  procDirs.append
471  (
472  dirIndex
473  (
474  dirN,
475  Tuple2<pathType, label>(PROCBASEOBJECT, proci)
476  )
477  );
478  }
479  }
480  }
481  if (!Pstream::parRun())
482  {
483  // If (as a side effect) we found the number of decompositions
484  // use it
485  if (maxProc != -1)
486  {
487  const_cast<fileOperation&>(*this).setNProcs(maxProc+1);
488  }
489  }
490 
491  if
492  (
493  (syncPar && returnReduce(procDirs.size(), sumOp<label>()))
494  || (!syncPar && procDirs.size())
495  )
496  {
497  procsDirs_.insert(procPath, procDirs);
498 
499  if (debug)
500  {
501  Pout<< "fileOperation::lookupProcessorsPath : For:" << procPath
502  << " detected:" << procDirs << endl;
503  }
504 
505  // Make sure to return a reference
506  return procsDirs_[procPath];
507  }
508  }
509 
510  return refPtr<dirIndexList>::New();
511 }
512 
513 
516 {
517  // Use parallel synchronisation
518  return lookupAndCacheProcessorsPath(fName, true);
519 }
520 
521 
523 {
524  // Generate output filename for object
525  fileName objPath(objectPath(io, word::null));
526 
527  // Test for either directory or a (valid) file & IOobject
528  bool ok;
529  if (io.name().empty())
530  {
531  ok = isDir(objPath);
532  }
533  else
534  {
535  ok =
536  isFile(objPath)
537  && io.typeHeaderOk<IOList<label>>(false);// object with local scope
538  }
539 
540  if (!ok)
541  {
542  // Re-test with searched for objectPath. This is for backwards
543  // compatibility
544  fileName originalPath(filePath(io.objectPath()));
545  if (originalPath != objPath)
546  {
547  // Test for either directory or a (valid) file & IOobject
548  if (io.name().empty())
549  {
550  ok = isDir(originalPath);
551  }
552  else
553  {
554  ok =
555  isFile(originalPath)
556  && io.typeHeaderOk<IOList<label>>(false);
557  }
558  }
559  }
560 
561  return ok;
562 }
563 
564 
565 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
566 
568 (
569  const label comm,
570  const bool distributedRoots
571 )
572 :
573  comm_(comm),
574  distributed_(distributedRoots)
575 {}
576 
577 
580 (
581  const word& handlerType,
582  bool verbose
583 )
584 {
586  << "Constructing fileHandler" << endl;
587 
588  auto cstrIter = wordConstructorTablePtr_->cfind(handlerType);
589 
590  if (!cstrIter.found())
591  {
593  (
594  "fileHandler",
595  handlerType,
596  *wordConstructorTablePtr_
597  ) << abort(FatalError);
598  }
599 
600  return autoPtr<fileOperation>(cstrIter()(verbose));
601 }
602 
603 
604 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
605 
607 (
608  const IOobject& io,
609  const word& typeName
610 ) const
611 {
612  return io.objectPath();
613 }
614 
615 
617 (
618  const regIOobject& io,
619  IOstreamOption streamOpt,
620  const bool valid
621 ) const
622 {
623  if (valid)
624  {
625  const fileName pathName(io.objectPath());
626 
627  mkDir(pathName.path());
628 
629  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt));
630 
631  if (!osPtr)
632  {
633  return false;
634  }
635 
636  OSstream& os = *osPtr;
637 
638  // If any of these fail, return (leave error handling to Ostream class)
639  if (!os.good())
640  {
641  return false;
642  }
643 
644  if (!io.writeHeader(os))
645  {
646  return false;
647  }
648 
649  // Write the data to the Ostream
650  if (!io.writeData(os))
651  {
652  return false;
653  }
654 
656  }
657  return true;
658 }
659 
660 
662 {
663  if (debug)
664  {
665  Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
666  }
667 
668  fileName path, pDir, local;
670  label numProcs;
671  label proci =
672  splitProcessorPath(fName, path, pDir, local, group, numProcs);
673 
674  if (numProcs != -1)
675  {
676  WarningInFunction << "Filename is already adapted:" << fName << endl;
677  }
678 
679  // Give preference to processors variant
680  if (proci != -1)
681  {
682  // Get all processor directories
683  refPtr<dirIndexList> procDirs(lookupProcessorsPath(fName));
684  for (const dirIndex& dirIdx : procDirs())
685  {
686  const fileName& procDir = dirIdx.first();
687 
688  fileName collatedName(path/procDir/local);
689  if (exists(collatedName))
690  {
691  if (debug)
692  {
693  Pout<< "fileOperation::filePath : " << collatedName << endl;
694  }
695  return collatedName;
696  }
697  }
698  }
699 
700  if (exists(fName))
701  {
702  if (debug)
703  {
704  Pout<< "fileOperation::filePath : " << fName << endl;
705  }
706  return fName;
707  }
708 
709  if (debug)
710  {
711  Pout<< "fileOperation::filePath : Not found" << endl;
712  }
713  return fileName::null;
714 }
715 
716 
717 Foam::label Foam::fileOperation::addWatch(const fileName& fName) const
718 {
719  return monitor().addWatch(fName);
720 }
721 
722 
723 bool Foam::fileOperation::removeWatch(const label watchIndex) const
724 {
725  return monitor().removeWatch(watchIndex);
726 }
727 
728 
730 (
731  const labelList& watchIndices,
732  const fileName& fName
733 ) const
734 {
735  forAll(watchIndices, i)
736  {
737  if (getFile(watchIndices[i]) == fName)
738  {
739  return i;
740  }
741  }
742  return -1;
743 }
744 
745 
747 (
748  regIOobject& rio,
749  const fileNameList& files
750 ) const
751 {
752  const labelList& watchIndices = rio.watchIndices();
753 
754  DynamicList<label> newWatchIndices;
755  labelHashSet removedWatches(watchIndices);
756 
757  for (const fileName& f : files)
758  {
759  const label index = findWatch(watchIndices, f);
760 
761  if (index == -1)
762  {
763  newWatchIndices.append(addWatch(f));
764  }
765  else
766  {
767  // Existing watch
768  newWatchIndices.append(watchIndices[index]);
769  removedWatches.erase(index);
770  }
771  }
772 
773  // Remove any unused watches
774  for (const label index : removedWatches)
775  {
776  removeWatch(watchIndices[index]);
777  }
778 
779  rio.watchIndices() = newWatchIndices;
780 }
781 
782 
783 Foam::fileName Foam::fileOperation::getFile(const label watchIndex) const
784 {
785  return monitor().getFile(watchIndex);
786 }
787 
788 
790 (
791  const bool masterOnly,
792  const bool syncPar
793 ) const
794 {
795  monitor().updateStates(masterOnly, Pstream::parRun());
796 }
797 
798 
800 (
801  const label watchFd
802 ) const
803 {
804  return monitor().getState(watchFd);
805 }
806 
807 
808 void Foam::fileOperation::setUnmodified(const label watchFd) const
809 {
810  monitor().setUnmodified(watchFd);
811 }
812 
813 
815 (
816  const fileName& directory,
817  const word& constantName
818 ) const
819 {
820  if (debug)
821  {
822  Pout<< "fileOperation::findTimes : Finding times in directory "
823  << directory << endl;
824  }
825 
826  // Note: do NOT use master-only reading here (as per lookupProcessorsPath)
827  // since this routine is called on an individual processorN directory
828 
829  // Read directory entries into a list
830  fileNameList dirEntries(Foam::readDir(directory, fileName::DIRECTORY));
831  instantList times = sortTimes(dirEntries, constantName);
832 
833 
834  // Get all processor directories
835  refPtr<dirIndexList> procDirs(lookupProcessorsPath(directory));
836  for (const dirIndex& dirIdx : procDirs())
837  {
838  const fileName& procDir = dirIdx.first();
839  fileName collDir(processorsPath(directory, procDir));
840  if (!collDir.empty() && collDir != directory)
841  {
842  fileNameList extraEntries
843  (
845  (
846  collDir,
848  )
849  );
850  mergeTimes
851  (
852  sortTimes(extraEntries, constantName),
853  constantName,
854  times
855  );
856  }
857  }
858 
859  if (debug)
860  {
861  Pout<< "fileOperation::findTimes : Found times:" << times << endl;
862  }
863  return times;
864 }
865 
866 
868 (
869  const IOobject& startIO,
870  const scalar startValue,
871  const word& stopInstance
872 ) const
873 {
874  const Time& time = startIO.time();
875 
876  IOobject io(startIO);
877 
878  // Note: - if name is empty, just check the directory itself
879  // - check both for isFile and headerOk since the latter does a
880  // filePath so searches for the file.
881  // - check for an object with local file scope (so no looking up in
882  // parent directory in case of parallel)
883 
884  if (exists(io))
885  {
887  << "Found exact match for \"" << io.name()
888  << "\" in " << io.instance()/io.local()
889  << endl;
890 
891  return io;
892  }
893 
894  // Search back through the time directories to find the first time
895  // that is less than or equal to the current time
896 
897  instantList ts = time.times();
898  label instanceI = ts.size()-1;
899 
900  for (; instanceI >= 0; --instanceI)
901  {
902  if (ts[instanceI].value() <= startValue)
903  {
904  break;
905  }
906  }
907 
908  // Found the time, continue from here
909  for (; instanceI >= 0; --instanceI)
910  {
911  io.instance() = ts[instanceI].name();
912 
913  // Shortcut: if actual directory is the timeName we've already tested it
914  if
915  (
916  io.instance() == startIO.instance()
917  && io.instance() != stopInstance
918  )
919  {
920  continue;
921  }
922 
923  if (exists(io))
924  {
926  << "Found exact match for \"" << io.name()
927  << "\" in " << io.instance()/io.local()
928  << endl;
929 
930  return io;
931  }
932 
933  // Check if hit minimum instance
934  if (io.instance() == stopInstance)
935  {
937  << "Hit stopInstance " << stopInstance << endl;
938 
939  if
940  (
941  startIO.readOpt() == IOobject::MUST_READ
943  )
944  {
945  if (io.name().empty())
946  {
948  << "Cannot find directory "
949  << io.local() << " in times " << startIO.instance()
950  << " down to " << stopInstance
951  << exit(FatalError);
952  }
953  else
954  {
956  << "Cannot find file \"" << io.name()
957  << "\" in directory " << io.local()
958  << " in times " << startIO.instance()
959  << " down to " << stopInstance
960  << exit(FatalError);
961  }
962  }
963 
964  return io;
965  }
966  }
967 
968  // Times usually already includes 'constant' so would have been checked
969  // above.
970  // However, re-test under these conditions:
971  // - Times is empty.
972  // Sometimes this can happen (eg, decomposePar with collated)
973  // - Times[0] is not constant
974  // - The startValue is negative (eg, kivaTest).
975  // This plays havoc with the reverse search, causing it to miss 'constant'
976 
977  if
978  (
979  ts.empty()
980  || ts.first().name() != time.constant()
981  || startValue < 0
982  )
983  {
984  io.instance() = time.constant();
985  if (exists(io))
986  {
988  << "Found constant match for \"" << io.name()
989  << "\" in " << io.instance()/io.local()
990  << endl;
991 
992  return io;
993  }
994  }
995 
996 
997  if
998  (
999  startIO.readOpt() == IOobject::MUST_READ
1001  )
1002  {
1004  << "Cannot find file \"" << io.name() << "\" in directory "
1005  << io.local() << " in times " << startIO.instance()
1006  << " down to " << time.constant()
1007  << exit(FatalError);
1008  }
1009 
1010  return io;
1011 }
1012 
1013 
1016  const objectRegistry& db,
1017  const fileName& instance,
1018  const fileName& local,
1019  word& newInstance
1020 ) const
1021 {
1022  if (debug)
1023  {
1024  Pout<< "fileOperation::readObjects :"
1025  << " db:" << db.objectPath()
1026  << " instance:" << instance << endl;
1027  }
1028 
1029  fileName path(db.path(instance, db.dbDir()/local));
1030 
1031  newInstance = word::null;
1032  fileNameList objectNames;
1033 
1034  if (Foam::isDir(path))
1035  {
1036  newInstance = instance;
1037  objectNames = Foam::readDir(path, fileName::FILE);
1038  }
1039  else
1040  {
1041  // Get processors equivalent of path
1042  fileName procsPath(filePath(path));
1043 
1044  if (!procsPath.empty())
1045  {
1046  newInstance = instance;
1047  objectNames = Foam::readDir(procsPath, fileName::FILE);
1048  }
1049  }
1050  return objectNames;
1051 }
1052 
1053 
1054 void Foam::fileOperation::setNProcs(const label nProcs)
1055 {}
1056 
1057 
1058 Foam::label Foam::fileOperation::nProcs
1060  const fileName& dir,
1061  const fileName& local
1062 ) const
1063 {
1064  label nProcs = 0;
1065  if (Pstream::master(comm_))
1066  {
1067  fileNameList dirNames(Foam::readDir(dir, fileName::Type::DIRECTORY));
1068 
1069  // Detect any processorsDDD or processorDDD
1070  label maxProc = -1;
1071  for (const fileName& dirN : dirNames)
1072  {
1073  fileName rp, rd, rl;
1075  label rNum;
1076 
1077  const label readProci =
1078  splitProcessorPath(dirN, rp, rd, rl, group, rNum);
1079 
1080  maxProc = max(maxProc, readProci);
1081  if (rNum != -1)
1082  {
1083  // Direct detection of processorsDDD
1084  maxProc = rNum-1;
1085  break;
1086  }
1087  }
1088  nProcs = maxProc+1;
1089 
1090 
1091  if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
1092  {
1093  fileName pointsFile
1094  (
1095  dir
1096  /processorsBaseDir
1097  /"constant"
1098  /local
1100  /"points"
1101  );
1102 
1103  if (Foam::isFile(pointsFile))
1104  {
1105  nProcs = decomposedBlockData::numBlocks(pointsFile);
1106  }
1107  else
1108  {
1109  WarningInFunction << "Cannot read file " << pointsFile
1110  << " to determine the number of decompositions."
1111  << " Returning 1" << endl;
1112  }
1113  }
1114  }
1115  Pstream::scatter(nProcs, Pstream::msgType(), comm_);
1116  return nProcs;
1117 }
1118 
1119 
1121 {
1122  if (debug)
1123  {
1124  Pout<< "fileOperation::flush : clearing processor directories cache"
1125  << endl;
1126  }
1127  procsDirs_.clear();
1128 }
1129 
1130 
1133  const IOobject& io,
1134  const word& procsDir
1135 ) const
1136 {
1137  return io.rootPath()/io.time().globalCaseName()/procsDir;
1138 }
1139 
1140 
1143  const IOobject& io,
1144  const word& instance,
1145  const word& procsDir
1146 ) const
1147 {
1148  return
1149  processorsCasePath(io, procsDir)
1150  /instance
1151  /io.db().dbDir()
1152  /io.local();
1153 }
1154 
1155 
1158  const fileName& dir,
1159  const word& procsDir
1160 ) const
1161 {
1162  // Check if directory is processorDDD
1163 
1164  const word caseName(dir.name());
1165  if (caseName.starts_with("processor"))
1166  {
1167  // Reject both '^processor$' and '^processors.*$'
1168 
1169  if (!std::isdigit(caseName[9]))
1170  {
1171  WarningInFunction << "Directory " << dir
1172  << " does not end in old-style processorDDD" << endl;
1173  }
1174 
1175  return dir.path()/procsDir;
1176  }
1177 
1178  return fileName::null;
1179 }
1180 
1181 
1184  const fileName& objPath,
1185  fileName& path,
1186  fileName& procDir,
1187  fileName& local,
1188 
1190  label& nProcs
1191 )
1192 {
1193  // Return value
1194  label returnProci = -1;
1195 
1196  // Clear out the return parameters
1197 
1198  path.clear();
1199  procDir.clear();
1200  local.clear();
1201  group.clear();
1202 
1203  // Invalidate detected number of processors
1204  nProcs = -1;
1205 
1206  // The local processor group is read as first/last, but stored as
1207  // start/size. Empty with start=0, size=0 if no range is detected
1208 
1209 
1210  // Start of 'processor..' directory name (the procDir)
1211  size_t pos = 0;
1212 
1213  // The slash starting the trailing (local) directory
1214  size_t slashLocal = string::npos;
1215 
1216 
1217  // Search for processor at start of string or after /processor
1218  //
1219  // 'processor(\d+)'
1220  // 'processors(\d+)'
1221  // 'processors(\d+)_(\d+)-(\d+)'
1222 
1223  for
1224  (
1225  /*nil*/;
1226  (pos = objPath.find("processor", pos)) != string::npos;
1227  pos += 9
1228  )
1229  {
1230  if (pos > 0 && objPath[pos-1] != '/')
1231  {
1232  // Not start of string or after /processor
1233  continue;
1234  }
1235 
1236  // The parse point. One past 'processor'
1237  size_t firstp = pos + 9;
1238 
1239  // normal: 'processor(\d+)'
1240  // plural: 'processors(\d+)'
1241 
1242  const bool plural = (objPath[firstp] == 's');
1243 
1244  if (plural)
1245  {
1246  ++firstp; // Skip over the 's'
1247  }
1248  else if (!std::isdigit(objPath[firstp]))
1249  {
1250  // Non-plural version (uncollated) requires digits only
1251  continue;
1252  }
1253 
1254  // The next slash indicates there is a local directory
1255  slashLocal = objPath.find('/', firstp);
1256 
1257  // The last parse point is the slash, or end of string
1258  const size_t lastp =
1259  (slashLocal == string::npos ? objPath.length() : slashLocal);
1260 
1261  if (!std::isdigit(objPath[lastp-1]))
1262  {
1263  // Must end in a digit!
1264  // This traps entries that are too short or look quite wrong
1265  // and avoid a string to int conversion that will fail anyhow
1266  continue;
1267  }
1268 
1269 
1270  // Match: '^processors(\d+)$' -> nProcs
1271 
1272  // Match: '^processors(\d+)_(\d+)-(\d+)$'
1273  // \1 = nProcs
1274  // \2 = beg processor group
1275  // \3 = end processor group (inclusive)
1276 
1277  if (plural)
1278  {
1279  int nProcsRead = 0;
1280 
1281  if
1282  (
1283  parseProcsNumRange
1284  (
1285  objPath.substr(firstp, lastp-firstp),
1286  nProcsRead,
1287  group
1288  )
1289  )
1290  {
1291  // Total number of processors
1292  nProcs = nProcsRead;
1293 
1294  // We are done!
1295  break;
1296  }
1297  }
1298 
1299  // Single
1300  // Match: '^processor(\d+)$' -> proci
1301 
1302  label proci = 0;
1303  if
1304  (
1305  Foam::read(objPath.substr(firstp, lastp-firstp), proci)
1306  && (proci >= 0)
1307  )
1308  {
1309  // Capture value of an individual processor
1310  returnProci = proci;
1311 
1312  // We are done!
1313  break;
1314  }
1315  }
1316 
1317  if (pos != string::npos)
1318  {
1319  // The split succeeded, extract the components.
1320 
1321  // The leading directory
1322  if (pos > 0)
1323  {
1324  path = objPath.substr(0, pos-1);
1325  }
1326 
1327  // The slash starting the trailing (local) directory
1328  if (slashLocal != string::npos)
1329  {
1330  procDir = objPath.substr(pos, slashLocal-pos);
1331  local = objPath.substr(slashLocal+1);
1332  }
1333  else
1334  {
1335  procDir = objPath.substr(pos);
1336  }
1337  }
1338 
1339  return returnProci;
1340 }
1341 
1342 
1344 {
1345  fileName path, pDir, local;
1347  label nProcs;
1348  return splitProcessorPath(fName, path, pDir, local, group, nProcs);
1349 }
1350 
1351 
1352 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
1353 
1355 {
1357  {
1358  word handler(getEnv("FOAM_FILEHANDLER"));
1359 
1360  if (handler.empty())
1361  {
1363  }
1364 
1366  }
1367 
1369 }
1370 
1371 
1373 {
1374  if
1375  (
1376  newHandler
1378  && newHandler->type() == fileOperation::fileHandlerPtr_->type()
1379  )
1380  {
1381  return;
1382  }
1383 
1384  fileOperation::fileHandlerPtr_ = std::move(newHandler);
1385 }
1386 
1387 
1388 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
regIOobject.H
Foam::refPtr::New
static refPtr< T > New(Args &&... args)
Construct refPtr of T with forwarding arguments.
uncollatedFileOperation.H
Foam::TimePaths::globalCaseName
const fileName & globalCaseName() const
Return global case name.
Definition: TimePathsI.H:48
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Foam::exists
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: MSwindows.C:625
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::fileName::FILE
A file.
Definition: fileName.H:79
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:70
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::fileOperation::mergeTimes
static void mergeTimes(const instantList &extraTimes, const word &constantName, instantList &times)
Merge two times.
Definition: fileOperation.C:264
Foam::fileOperation
An encapsulation of filesystem-related operations.
Definition: fileOperation.H:77
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::constant::atomic::group
constexpr const char *const group
Group name for atomic constants.
Definition: atomicConstants.H:52
Foam::fileOperation::processorsPath
fileName processorsPath(const IOobject &, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
Definition: fileOperation.C:1142
Foam::fileOperation::fileHandlerPtr_
static autoPtr< fileOperation > fileHandlerPtr_
Static fileOperation.
Definition: fileOperation.H:183
Foam::fileOperation::addWatches
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
Definition: fileOperation.C:747
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:186
Foam::regIOobject::watchIndices
const labelList & watchIndices() const
Return file-monitoring handles.
Definition: regIOobjectI.H:196
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::IntRange
An interval of (signed) integers defined by a start and a size.
Definition: IntRange.H:63
Foam::less
static bool less(const vector &x, const vector &y)
To compare normals.
Definition: meshRefinementRefine.C:57
Foam::IOobject::typeHeaderOk
bool typeHeaderOk(const bool checkType=true, const bool search=true, const bool verbose=true)
Read header (uses typeFilePath to find file) and check its info.
Definition: IOobjectTemplates.C:39
Foam::defineRunTimeSelectionTable
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
Foam::IOobject::writeEndDivider
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
Definition: IOobjectWriteHeader.C:109
Foam::regIOobject::writeData
virtual bool writeData(Ostream &) const =0
Pure virtual writeData function.
Foam::IOobject::rootPath
const fileName & rootPath() const
Definition: IOobject.C:469
Foam::IOobject::instance
const fileName & instance() const
Definition: IOobjectI.H:191
Foam::fileName::name
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:209
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::IOobject::inotifyMaster
Definition: IOobject.H:139
Foam::polyMesh::meshSubDir
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:321
Foam::UPstream::parRun
static bool & parRun()
Test if this a parallel run, or allow modify access.
Definition: UPstream.H:434
Foam::IOobject::timeStampMaster
Definition: IOobject.H:137
Foam::fileOperation::pathTypeNames_
static const Enum< pathType > pathTypeNames_
Definition: fileOperation.H:99
Foam::fileOperation::flush
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
Definition: fileOperation.C:1120
objectRegistry.H
Foam::IOobject::fileModificationChecking
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:211
Foam::fileOperation::filePath
virtual fileName filePath(const bool checkGlobal, const IOobject &, const word &typeName, const bool search=true) const =0
Search for an object. checkGlobal : also check undecomposed case.
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:458
Foam::Pstream::scatter
static void scatter(const List< commsStruct > &comms, T &Value, const int tag, const label comm)
Scatter data. Distribute without modification. Reverse of gather.
Definition: gatherScatter.C:150
Foam::fileMonitor::fileState
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:73
Foam::isFile
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: MSwindows.C:658
Foam::fileHandler
const fileOperation & fileHandler()
Get current file handler.
Definition: fileOperation.C:1354
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::fileOperation::isFileOrDir
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile)
Definition: fileOperation.C:337
Foam::fileOperation::setNProcs
virtual void setNProcs(const label nProcs)
Set number of processor directories/results. Only used in.
Definition: fileOperation.C:1054
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::decomposedBlockData::numBlocks
static label numBlocks(const fileName &fName)
Detect number of blocks in a file.
Definition: decomposedBlockData.C:1067
polyMesh.H
Foam::HashSet< label, Hash< label > >
Foam::IOobject::time
const Time & time() const
Return time.
Definition: IOobject.C:463
Foam::fileOperation::updateStates
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
Definition: fileOperation.C:790
Foam::fileOperation::lookupAndCacheProcessorsPath
refPtr< dirIndexList > lookupAndCacheProcessorsPath(const fileName &, const bool syncPar) const
Lookup name of processorsDDD using cache.
Definition: fileOperation.C:345
Foam::IOobject::inotify
Definition: IOobject.H:138
Foam::getEnv
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
Foam::fileOperation::findTimes
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
Definition: fileOperation.C:815
Foam::fileOperation::sortTimes
static instantList sortTimes(const fileNameList &dirEntries, const word &constantName="constant")
Sort directory entries according to time value,.
Definition: fileOperation.C:186
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::fileOperation::getFile
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
Definition: fileOperation.C:783
Foam::fileOperation::findInstance
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is. Fails if cannot be found.
Definition: fileOperation.C:868
Foam::IOobject::db
const objectRegistry & db() const
Return the local objectRegistry.
Definition: IOobject.C:457
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::fileOperation::New
static autoPtr< fileOperation > New(const word &handlerType, bool verbose=false)
Select fileHandler-type.
Definition: fileOperation.C:580
Foam::objectRegistry::dbDir
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
Definition: objectRegistry.H:198
Foam::IOobject::local
const fileName & local() const
Definition: IOobjectI.H:203
Foam::HashTable::erase
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:392
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:365
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:474
Foam::fileOperation::nProcs
virtual label nProcs(const fileName &dir, const fileName &local="") const
Get number of processor directories/results. Used for e.g.
Definition: fileOperation.C:1059
argList.H
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:459
Foam::fileMonitor
Checking for changes to files.
Definition: fileMonitor.H:66
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:254
Foam::TimePaths::times
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:149
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::fileOperation::writeObject
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
Definition: fileOperation.C:617
Foam::fileOperation::getState
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
Definition: fileOperation.C:800
Foam::OSstream
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:54
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::List::resize
void resize(const label newSize)
Adjust allocated size of list.
Definition: ListI.H:139
HashSet.H
Foam::FatalError
error FatalError
FatalErrorInLookup
#define FatalErrorInLookup(lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalError.
Definition: error.H:385
fileOperation.H
Foam::fileOperation::monitorPtr_
autoPtr< fileMonitor > monitorPtr_
File-change monitor for all registered files.
Definition: fileOperation.H:125
Foam::fileOperation::defaultFileHandler
static word defaultFileHandler
Name of the default fileHandler.
Definition: fileOperation.H:173
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::fileOperation::objectPath
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
Definition: fileOperation.C:607
Foam::fileName::null
static const fileName null
An empty fileName.
Definition: fileName.H:97
Foam::fileOperation::addWatch
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
Definition: fileOperation.C:717
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::fileOperation::removeWatch
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
Definition: fileOperation.C:723
Foam::fileOperation::setUnmodified
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
Definition: fileOperation.C:808
Foam::fileOperation::monitor
fileMonitor & monitor() const
Get or create fileMonitor singleton.
Definition: fileOperation.C:246
Time.H
Foam::autoPtr< Foam::fileOperation >
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:71
Foam::fileOperation::fileOperation
fileOperation(const label comm, const bool distributedRoots=false)
Construct from communicator, optionally with distributed roots.
Definition: fileOperation.C:568
Foam::UPstream::msgType
static int & msgType()
Message tag of standard messages.
Definition: UPstream.H:541
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:359
f
labelList f(nPoints)
decomposedBlockData.H
Foam::fileOperation::exists
bool exists(IOobject &io) const
Does ioobject exist. Is either a directory (empty name()) or.
Definition: fileOperation.C:522
Foam::List< instant >
Foam::IOobject::readOpt
readOption readOpt() const
The read option.
Definition: IOobjectI.H:165
Foam::fileOperation::splitProcessorPath
static label splitProcessorPath(const fileName &objectPath, fileName &path, fileName &procDir, fileName &local, procRangeType &group, label &nProcs)
Split objectPath into part before 'processor' and part after.
Definition: fileOperation.C:1183
Foam::IOList< label >
Foam::fileOperation::readObjects
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Definition: fileOperation.C:1015
Foam::fileName::DIRECTORY
A directory.
Definition: fileName.H:80
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::word::null
static const word null
An empty word.
Definition: word.H:77
Foam::IOobject::MUST_READ_IF_MODIFIED
Definition: IOobject.H:121
Foam::fileOperation::findWatch
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
Definition: fileOperation.C:730
Foam::fileOperation::lookupProcessorsPath
virtual refPtr< dirIndexList > lookupProcessorsPath(const fileName &objectPath) const
Lookup name of processorsDDD using cache.
Definition: fileOperation.C:515
Foam::IOobject::writeHeader
bool writeHeader(Ostream &os) const
Write header.
Definition: IOobjectWriteHeader.C:156
registerSwitch.H
Foam::fileOperation::processorsBaseDir
static word processorsBaseDir
Return the processors directory name (usually "processors")
Definition: fileOperation.H:170
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:73
Foam::Tuple2
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:57
rp
regionProperties rp(runTime)
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:224
Foam::IOobject::objectPath
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:209
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::TimePaths::constant
const word & constant() const
Return constant name.
Definition: TimePathsI.H:88
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
Foam::IOobject::path
fileName path() const
The complete path.
Definition: IOobject.C:481
Foam::debug::optimisationSwitches
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:219
Foam::fileOperation::processorsCasePath
fileName processorsCasePath(const IOobject &, const word &procDir) const
Generate path (like io.path) from root+casename with any.
Definition: fileOperation.C:1132
Foam::readDir
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:707
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::fileOperation::detectProcessorPath
static label detectProcessorPath(const fileName &objPath)
Detect processor number from '/aa/bb/processorDDD/cc'.
Definition: fileOperation.C:1343
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643
Foam::refPtr
A class for managing references or pointers (no reference counting)
Definition: PtrList.H:60
Foam::IOobject::MUST_READ
Definition: IOobject.H:120
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:177