masterUncollatedFileOperation.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-2023 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 
32 #include "Pstream.H"
33 #include "Time.H"
34 #include "instant.H"
35 #include "IFstream.H"
36 #include "SpanStream.H"
37 #include "masterOFstream.H"
38 #include "decomposedBlockData.H"
39 #include "registerSwitch.H"
40 #include "dummyISstream.H"
41 #include "SubList.H"
42 
43 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
44 
45 namespace Foam
46 {
47 namespace fileOperations
48 {
49  defineTypeNameAndDebug(masterUncollatedFileOperation, 0);
51  (
52  fileOperation,
53  masterUncollatedFileOperation,
54  word
55  );
57  (
58  fileOperation,
59  masterUncollatedFileOperation,
60  comm
61  );
62 
64  (
65  Foam::debug::floatOptimisationSwitch("maxMasterFileBufferSize", 1e9)
66  );
68  (
69  "maxMasterFileBufferSize",
70  float,
72  );
73 
74  // Threaded MPI: not required
76  (
77  fileOperationInitialise,
78  fileOperationInitialise_unthreaded,
79  word,
80  masterUncollated
81  );
82 }
83 }
84 
85 
86 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
87 
88 namespace Foam
89 {
90 
91 // Get file contents (compressed or uncompressed)
93 {
94  DynamicList<char> buffer;
95 
96  auto& iss = ifs.stdStream();
97 
98  const auto inputSize = ifs.fileSize();
99 
101  {
102  // For compressed files, no idea how large the result will be.
103  // So read chunk-wise.
104  // Using the compressed size for the chunk size:
105  // 50% compression = 2 iterations
106  // 66% compression = 3 iterations
107  // ...
108 
109  const uint64_t chunkSize =
110  (
111  (inputSize <= 1024)
112  ? uint64_t(4096)
113  : uint64_t(2*inputSize)
114  );
115 
116  uint64_t beg = 0;
117 
118  for (int iter = 1; iter < 100000; ++iter)
119  {
120  // Manual resizing to use incremental vs doubling
121  buffer.setCapacity(label(iter * chunkSize));
122  buffer.resize(buffer.capacity());
123 
124  ifs.readRaw(buffer.data() + beg, chunkSize);
125  const std::streamsize nread = iss.gcount();
126 
127  if
128  (
129  nread < 0
131  )
132  {
133  // Failed, but treat as normal 'done'
134  buffer.resize(label(beg));
135  break;
136  }
137  else
138  {
139  beg += uint64_t(nread);
140  if (nread >= 0 && uint64_t(nread) < chunkSize)
141  {
142  // normalExit = true;
143  buffer.resize(label(beg));
144  break;
145  }
146  }
147  }
148  }
149  else
150  {
151  if (inputSize >= 0)
152  {
153  buffer.setCapacity(label(inputSize));
154  buffer.resize(buffer.capacity());
155 
156  ifs.readRaw(buffer.data(), buffer.size_bytes());
157  const std::streamsize nread = iss.gcount();
158 
159  if
160  (
161  nread < 0
163  )
164  {
165  // Failed, but treat as normal 'done'
166  buffer.clear();
167  }
168  else
169  {
170  buffer.resize(label(nread)); // Safety
171  }
172  }
173  }
174 
175  return buffer;
176 }
177 
178 } // End namespace Foam
179 
180 
181 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
182 
185 (
186  const instantList& timeDirs,
187  const instant& t
188 )
189 {
190  // Note:
191  // - times will include constant (with value 0) as first element.
192  // For backwards compatibility make sure to find 0 in preference
193  // to constant.
194  // - list is sorted so could use binary search
195 
196  forAllReverse(timeDirs, i)
197  {
198  if (t.equal(timeDirs[i].value()))
199  {
200  return timeDirs[i].name();
201  }
202  }
204  return word();
205 }
206 
207 
210 (
211  const bool checkGlobal,
212  const bool isFile,
213  const IOobject& io,
214  const dirIndexList& pDirs,
215  const bool search,
216  pathType& searchType,
217  word& procsDir,
218  word& newInstancePath
219 ) const
220 {
221  procsDir.clear();
222  newInstancePath.clear();
223 
224  if (io.instance().isAbsolute())
225  {
226  fileName objPath = io.instance()/io.name();
227 
228  if (isFileOrDir(isFile, objPath))
229  {
230  searchType = fileOperation::ABSOLUTE;
231  return objPath;
232  }
233  else
234  {
235  searchType = fileOperation::NOTFOUND;
236  return fileName();
237  }
238  }
239  else
240  {
241  // 1. Check the writing fileName
242  fileName writePath(objectPath(io, io.headerClassName()));
243 
244  if (isFileOrDir(isFile, writePath))
245  {
246  searchType = fileOperation::WRITEOBJECT;
247  return writePath;
248  }
249 
250  // 2. Check processors/
251  if (io.time().processorCase())
252  {
253  for (const dirIndex& dirIdx : pDirs)
254  {
255  const fileName& pDir = dirIdx.first();
256  fileName objPath =
257  processorsPath(io, io.instance(), pDir)
258  /io.name();
259  if (objPath != writePath && isFileOrDir(isFile, objPath))
260  {
261  searchType = dirIdx.second().first();
262  procsDir = pDir;
263  return objPath;
264  }
265  }
266  }
267  {
268  // 3. Check local
269  fileName localPath = io.objectPath();
270 
271  if
272  (
273  localPath != writePath
274  && isFileOrDir(isFile, localPath)
275  )
276  {
277  searchType = fileOperation::OBJECT;
278  return localPath;
279  }
280  }
281 
282 
283 
284  // Any global checks
285  if
286  (
287  checkGlobal
288  && io.time().processorCase()
289  && (
290  io.instance() == io.time().system()
291  || io.instance() == io.time().constant()
292  )
293  )
294  {
295  fileName parentPath =
296  io.rootPath()/io.time().globalCaseName()
297  /io.instance()/io.db().dbDir()/io.local()/io.name();
298 
299  if (isFileOrDir(isFile, parentPath))
300  {
301  searchType = fileOperation::PARENTOBJECT;
302  return parentPath;
303  }
304  }
305 
306  // Check for approximately same time. E.g. if time = 1e-2 and
307  // directory is 0.01 (due to different time formats)
308  const auto pathFnd = times_.cfind(io.time().path());
309 
310  if (search && pathFnd.good())
311  {
312  newInstancePath = findInstancePath
313  (
314  *pathFnd(),
315  instant(io.instance())
316  );
317 
318  if (newInstancePath.size() && newInstancePath != io.instance())
319  {
320  // 1. Try processors equivalent
321  for (const dirIndex& dirIdx : pDirs)
322  {
323  const fileName& pDir = dirIdx.first();
324 
325  fileName fName
326  (
327  processorsPath(io, newInstancePath, pDir)
328  /io.name()
329  );
330  if (isFileOrDir(isFile, fName))
331  {
332  switch (dirIdx.second().first())
333  {
335  {
336  searchType =
338  }
339  break;
341  {
342  searchType = fileOperation::PROCBASEINSTANCE;
343  }
344  break;
346  {
347  searchType = fileOperation::PROCINSTANCE;
348  }
349  break;
350  default:
351  break;
352  }
353  procsDir = pDir;
354  return fName;
355  }
356  }
357 
358 
359  // 2. Check local
360  fileName fName
361  (
362  io.rootPath()/io.caseName()
363  /newInstancePath/io.db().dbDir()/io.local()/io.name()
364  );
365  if (isFileOrDir(isFile, fName))
366  {
367  searchType = fileOperation::FINDINSTANCE;
368  return fName;
369  }
370  }
371  }
372  }
373 
374  // Nothing found
376  return fileName();
377 }
378 
379 
382 (
383  const IOobject& io,
384  const pathType& searchType,
385  const word& procDir,
386  const word& instancePath
387 ) const
388 {
389  // Replacement for IOobject::objectPath()
390 
391  switch (searchType)
392  {
394  {
395  return io.instance()/io.name();
396  }
397  break;
398 
400  {
401  return io.path()/io.name();
402  }
403  break;
404 
406  {
407  return objectPath(io, io.headerClassName());
408  }
409  break;
410 
412  {
413  // Uncollated type, e.g. processor1
414  const word procName
415  (
417  );
418  return
419  processorsPath
420  (
421  io,
422  io.instance(),
423  (
425  ? procName
426  : procDir
427  )
428  )
429  /io.name();
430  }
431  break;
432 
434  {
435  // Collated, e.g. processors4
436  return
437  processorsPath(io, io.instance(), procDir)
438  /io.name();
439  }
440  break;
441 
443  {
444  // Processors directory locally provided by the fileHandler itself
445  return
446  processorsPath(io, io.instance(), processorsDir(io))
447  /io.name();
448  }
449  break;
450 
452  {
453  return
454  io.rootPath()/io.time().globalCaseName()
455  /io.instance()/io.db().dbDir()/io.local()/io.name();
456  }
457  break;
458 
460  {
461  return
462  io.rootPath()/io.caseName()
463  /instancePath/io.db().dbDir()/io.local()/io.name();
464  }
465  break;
466 
468  {
469  // Uncollated type, e.g. processor1
470  const word procName
471  (
472  "processor"
474  );
475  return
476  processorsPath
477  (
478  io,
479  instancePath,
480  (
482  ? procName
483  : procDir
484  )
485  )
486  /io.name();
487  }
488  break;
489 
491  {
492  // Collated, e.g. processors4
493  return
494  processorsPath(io, instancePath, procDir)
495  /io.name();
496  }
497  break;
498 
500  {
501  // Processors directory locally provided by the fileHandler itself
502  return
503  processorsPath(io, instancePath, processorsDir(io))
504  /io.name();
505  }
506  break;
507 
509  {
510  return fileName();
511  }
512  break;
513 
514  default:
515  {
517  return fileName();
518  }
519  }
520 }
521 
522 
524 (
525  const fileName& filePath,
526  const labelUList& recvProcs,
527  PstreamBuffers& pBufs
528 )
529 {
530  if (recvProcs.empty()) return;
531 
532  IFstream ifs(filePath, IOstreamOption::BINARY);
533 
534  if (!ifs.good())
535  {
536  FatalIOErrorInFunction(filePath)
537  << "Cannot open file " << filePath
538  //<< " using communicator " << pBufs.comm()
539  //<< " ioRanks:" << UPstream::procID(pBufs.comm())
540  << exit(FatalIOError);
541  }
542 
543  if (debug)
544  {
545  Info<< "masterUncollatedFileOperation::readAndSend :"
546  << " compressed:" << bool(ifs.compression()) << " "
547  << filePath << endl;
548  }
549 
550  // Read file contents (compressed or uncompressed) into a character buffer
551  DynamicList<char> buf(slurpFile(ifs));
552 
553  for (const label proci : recvProcs)
554  {
555  UOPstream os(proci, pBufs);
556  os.write(buf.cdata_bytes(), buf.size_bytes());
557  }
558 
559  if (debug)
560  {
561  Info<< "masterUncollatedFileOperation::readStream :"
562  << " From " << filePath << " sent " << buf.size()
563  << " bytes" << endl;
564  }
565 }
566 
567 
570 (
571  IOobject& io,
572  const label comm,
573  const bool uniform, // on comms master only
574  const fileNameList& filePaths, // on comms master and sub-ranks
575  const boolUList& readOnProcs // on comms master and sub-ranks
576 )
577 {
578  autoPtr<ISstream> isPtr;
579 
581 
582  if (UPstream::master(comm))
583  {
584  if (uniform)
585  {
586  if (readOnProcs[0])
587  {
588  if (filePaths[0].empty())
589  {
590  FatalIOErrorInFunction(filePaths[0])
591  << "Cannot find file " << io.objectPath()
592  << " fileHandler : comm:" << comm
593  << " ioRanks:" << UPstream::procID(comm)
594  << exit(FatalIOError);
595  }
596 
597  DynamicList<label> recvProcs(UPstream::nProcs(comm));
598  for (const int proci : UPstream::allProcs(comm))
599  {
600  if (readOnProcs[proci])
601  {
602  recvProcs.push_back(proci);
603  }
604  }
605 
606  // Read on master and send to all processors
607  // (including master for simplicity)
608  if (debug)
609  {
610  Pout<< "masterUncollatedFileOperation::readStream :"
611  << " For uniform file " << filePaths[0]
612  << " sending to " << recvProcs
613  << " in comm:" << comm << endl;
614  }
615  readAndSend(filePaths[0], recvProcs, pBufs);
616  }
617  }
618  else
619  {
620  if (readOnProcs[0])
621  {
622  if (filePaths[0].empty())
623  {
624  FatalIOErrorInFunction(filePaths[0])
625  << "Cannot find file " << io.objectPath()
626  << " fileHandler : comm:" << comm
627  << " ioRanks:" << UPstream::procID(comm)
628  << exit(FatalIOError);
629  }
630 
631  // Open master
632  isPtr.reset(new IFstream(filePaths[0]));
633 
634  // Read header
635  if (!io.readHeader(*isPtr))
636  {
637  FatalIOErrorInFunction(*isPtr)
638  << "problem while reading header for object "
639  << io.name()
640  << " fileHandler : comm:" << comm
641  << " ioRanks:" << UPstream::procID(comm)
642  << exit(FatalIOError);
643  }
644  }
645 
646  // Read sub-rank files
647  for (const int proci : UPstream::subProcs(comm))
648  {
649  if (debug)
650  {
651  Pout<< "masterUncollatedFileOperation::readStream :"
652  << " For processor " << proci
653  << " opening " << filePaths[proci] << endl;
654  }
655 
656  const fileName& fPath = filePaths[proci];
657 
658  if (readOnProcs[proci] && !fPath.empty())
659  {
660  // Note: handle compression ourselves since size cannot
661  // be determined without actually uncompressing
662  readAndSend(fPath, labelList(one{}, proci), pBufs);
663  }
664  }
665  }
666  }
667 
668  pBufs.finishedScatters();
669 
670  // isPtr will be valid on master and will be the unbuffered
671  // IFstream. Else the information is in the PstreamBuffers (and
672  // the special case of a uniform file)
673 
674  if (!isPtr)
675  {
676  if (readOnProcs[UPstream::myProcNo(comm)])
677  {
678  // This processor needs to return something
679  List<char> buf(pBufs.recvDataCount(UPstream::masterNo()));
680 
681  if (!buf.empty())
682  {
683  UIPstream is(UPstream::masterNo(), pBufs);
684  is.read(buf.data(), buf.size());
685  }
686 
687  if (debug)
688  {
689  Pout<< "masterUncollatedFileOperation::readStream :"
690  << " Done reading " << buf.size() << " bytes" << endl;
691  }
692 
693  // A local character buffer copy of the Pstream contents.
694  // Construct with same parameters (ASCII, current version)
695  // as the IFstream so that it has the same characteristics.
696 
697  isPtr.reset(new ICharStream(std::move(buf)));
698 
699  // With the proper file name
700  isPtr->name() = filePaths[UPstream::myProcNo(comm)];
701 
702  if (!io.readHeader(*isPtr))
703  {
704  FatalIOErrorInFunction(*isPtr)
705  << "problem while reading header for object "
706  << io.name()
707  << " fileHandler : comm:" << comm
708  << " ioRanks:" << UPstream::procID(comm)
709  << exit(FatalIOError);
710  }
711  }
712  else
713  {
714  isPtr.reset(new dummyISstream());
715  }
716  }
717 
718  return isPtr;
719 }
720 
722 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
723 
724 namespace Foam
725 {
726 
727 // Construction helper: self/world/local communicator and IO ranks
729 {
730  // Default is COMM_WORLD (single master)
731  Tuple2<label, labelList> commAndIORanks
732  (
735  );
736 
737  if (UPstream::parRun() && commAndIORanks.second().size() > 1)
738  {
739  // Multiple masters: ranks for my IO range
740  commAndIORanks.first() = UPstream::allocateCommunicator
741  (
743  fileOperation::subRanks(commAndIORanks.second())
744  );
745  }
746 
747  return commAndIORanks;
748 }
749 
750 } // End namespace Foam
751 
752 
753 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
754 
755 void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
756 {
757  verbose = (verbose && Foam::infoDetailLevel > 0);
758 
759  if (verbose)
760  {
761  DetailInfo
762  << "I/O : " << typeName
763  << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
764  << endl;
765  }
766 
768  {
769  if (verbose)
770  {
772  << "Resetting fileModificationChecking to timeStamp" << endl;
773  }
775  }
777  {
778  if (verbose)
779  {
781  << "Resetting fileModificationChecking to inotify"
782  << endl;
783  }
785  }
786 }
787 
788 
791 (
792  bool verbose
793 )
794 :
796  (
798  ),
799  managedComm_(getManagedComm(comm_)) // Possibly locally allocated
800 {
801  init(verbose);
802 
803  if (comm_ == -1)
804  {
805  FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
806  }
807  if (UPstream::nProcs(comm_) == -1)
808  {
809  FatalErrorInFunction<< "Problem comm_:" << comm_
810  << " nProcs:" << UPstream::nProcs(comm_)
811  << exit(FatalError);
812  }
813  if (UPstream::myProcNo(comm_) == -1)
814  {
815  FatalErrorInFunction<< "Problem comm_:" << comm_
816  << " myProcNo:" << UPstream::myProcNo(comm_)
818  }
819 }
820 
821 
824 (
825  const Tuple2<label, labelList>& commAndIORanks,
826  const bool distributedRoots,
827  bool verbose
828 )
829 :
830  fileOperation(commAndIORanks, distributedRoots),
831  managedComm_(-1) // Externally managed
832 {
833  init(verbose);
834 
835  if (comm_ == -1)
836  {
837  FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
838  }
839  if (UPstream::nProcs(comm_) == -1)
840  {
841  FatalErrorInFunction<< "Problem comm_:" << comm_
842  << " nProcs:" << UPstream::nProcs(comm_)
843  << exit(FatalError);
844  }
845  if (UPstream::myProcNo(comm_) == -1)
846  {
847  FatalErrorInFunction<< "Problem comm_:" << comm_
848  << " myProcNo:" << UPstream::myProcNo(comm_)
849  << exit(FatalError);
850  }
851 }
852 
853 
855 {
856  // From externally -> locally managed
857  managedComm_ = getManagedComm(comm_);
858 }
859 
860 
861 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
862 
865 {
867 }
868 
869 
870 // * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
871 
873 (
874  const fileName& dir,
875  mode_t mode
876 ) const
877 {
878  return masterOp<mode_t>
879  (
880  dir,
881  mkDirOp(mode),
883  comm_
884  );
885 }
886 
887 
889 (
890  const fileName& fName,
891  mode_t mode
892 ) const
893 {
894  return masterOp<mode_t>
895  (
896  fName,
897  chModOp(mode),
899  comm_
900  );
901 }
902 
903 
905 (
906  const fileName& fName,
907  const bool followLink
908 ) const
909 {
910  return masterOp<mode_t>
911  (
912  fName,
913  modeOp(followLink),
915  comm_
916  );
917 }
918 
919 
921 (
922  const fileName& fName,
923  const bool followLink
924 ) const
925 {
926  return fileName::Type
927  (
928  masterOp<label>
929  (
930  fName,
931  typeOp(followLink),
933  comm_
934  )
935  );
936 }
937 
938 
940 (
941  const fileName& fName,
942  const bool checkGzip,
943  const bool followLink
944 ) const
945 {
946  return masterOp<bool>
947  (
948  fName,
949  existsOp(checkGzip, followLink),
951  comm_
952  );
953 }
954 
955 
957 (
958  const fileName& fName,
959  const bool followLink
960 ) const
961 {
962  return masterOp<bool>
963  (
964  fName,
965  isDirOp(followLink),
967  comm_
968  );
969 }
970 
971 
973 (
974  const fileName& fName,
975  const bool checkGzip,
976  const bool followLink
977 ) const
978 {
979  return masterOp<bool>
980  (
981  fName,
982  isFileOp(checkGzip, followLink),
984  comm_
985  );
986 }
987 
988 
990 (
991  const fileName& fName,
992  const bool followLink
993 ) const
994 {
995  return masterOp<off_t>
996  (
997  fName,
998  fileSizeOp(followLink),
1000  comm_
1001  );
1002 }
1003 
1004 
1006 (
1007  const fileName& fName,
1008  const bool followLink
1009 ) const
1010 {
1011  return masterOp<time_t>
1012  (
1013  fName,
1014  lastModifiedOp(followLink),
1017  );
1018 }
1019 
1020 
1022 (
1023  const fileName& fName,
1024  const bool followLink
1025 ) const
1026 {
1027  return masterOp<double>
1028  (
1029  fName,
1030  highResLastModifiedOp(followLink),
1033  );
1034 }
1035 
1036 
1038 (
1039  const fileName& fName,
1040  const std::string& ext
1041 ) const
1042 {
1043  return masterOp<bool>
1044  (
1045  fName,
1046  mvBakOp(ext),
1048  comm_
1049  );
1050 }
1051 
1052 
1054 (
1055  const fileName& fName
1056 ) const
1057 {
1058  return masterOp<bool>
1059  (
1060  fName,
1061  rmOp(),
1063  comm_
1064  );
1065 }
1066 
1067 
1069 (
1070  const fileName& dir,
1071  const bool silent,
1072  const bool emptyOnly
1073 ) const
1074 {
1075  return masterOp<bool>
1076  (
1077  dir,
1078  rmDirOp(silent, emptyOnly),
1080  comm_
1081  );
1082 }
1083 
1084 
1086 (
1087  const fileName& dir,
1088  const fileName::Type type,
1089  const bool filtergz,
1090  const bool followLink
1091 ) const
1092 {
1093  return masterOp<fileNameList>
1094  (
1095  dir,
1096  readDirOp(type, filtergz, followLink),
1098  comm_
1099  );
1100 }
1101 
1102 
1104 (
1105  const fileName& src,
1106  const fileName& dst,
1107  const bool followLink
1108 ) const
1109 {
1110  return masterOp<bool>
1111  (
1112  src,
1113  dst,
1114  cpOp(followLink),
1116  comm_
1117  );
1118 }
1119 
1120 
1122 (
1123  const fileName& src,
1124  const fileName& dst
1125 ) const
1126 {
1127  return masterOp<bool>
1128  (
1129  src,
1130  dst,
1131  lnOp(),
1133  comm_
1134  );
1135 }
1136 
1137 
1139 (
1140  const fileName& src,
1141  const fileName& dst,
1142  const bool followLink
1143 ) const
1144 {
1145  return masterOp<bool>
1146  (
1147  src,
1148  dst,
1149  mvOp(followLink),
1150  Pstream::msgType(),
1151  comm_
1152  );
1153 }
1154 
1155 
1156 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1157 
1159 (
1160  const bool checkGlobal,
1161  const IOobject& io,
1162  const word& typeName,
1163  const bool search
1164 ) const
1165 {
1166  if (debug)
1167  {
1168  Pout<< "masterUncollatedFileOperation::filePath :"
1169  << " objectPath:" << io.objectPath()
1170  << " checkGlobal:" << checkGlobal
1171  << " parRun:" << Pstream::parRun()
1172  << " localmaster:" << Pstream::master(comm_) << endl;
1173  }
1174 
1175  // Now that we have an IOobject path use it to detect & cache
1176  // processor directory naming
1177  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1178 
1179  // Trigger caching of times
1180  if (cacheLevel() > 0)
1181  {
1182  (void)findTimes(io.time().path(), io.time().constant());
1183  }
1184 
1185  // Determine master filePath and scatter
1186 
1187  fileName objPath;
1188  pathType searchType = NOTFOUND;
1189  word procsDir;
1190  word newInstancePath;
1191 
1192  if (Pstream::master(comm_))
1193  {
1194  const bool oldParRun = UPstream::parRun(false);
1195  const int oldCache = fileOperation::cacheLevel(0);
1196  const label oldNProcs = fileOperation::nProcs();
1197 
1198  // All masters search locally. Note that global objects might
1199  // fail (except on master). This gets handled later on (in PARENTOBJECT)
1200  objPath =
1201  filePathInfo
1202  (
1203  checkGlobal,
1204  true,
1205  io,
1206  pDirs,
1207  search,
1208  searchType,
1209  procsDir,
1210  newInstancePath
1211  );
1212 
1213  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1214  fileOperation::cacheLevel(oldCache);
1215  UPstream::parRun(oldParRun);
1216 
1217  if (debug)
1218  {
1219  Pout<< "masterUncollatedFileOperation::filePath :"
1220  << " master objPath:" << objPath
1221  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1222  << " procsDir:" << procsDir << " instance:" << newInstancePath
1223  << endl;
1224  }
1225  }
1226 
1227  // Broadcast information about where the master found the object
1228  // Note: use the worldComm to make sure all processors decide
1229  // the same type. Only procsDir is allowed to differ; searchType
1230  // and instance have to be same
1231  if (UPstream::parRun())
1232  {
1233  int masterType(searchType);
1234  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1235  searchType = pathType(masterType);
1236  }
1237 
1238  if
1239  (
1240  checkGlobal
1241  || searchType == fileOperation::PARENTOBJECT
1242  || searchType == fileOperation::PROCBASEOBJECT
1243  || searchType == fileOperation::PROCBASEINSTANCE
1244  || io.local() == "uniform"
1245  )
1246  {
1247  // Distribute master path. This makes sure it is seen as uniform
1248  // and only gets read from the master.
1249  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1250  }
1251  else
1252  {
1253  Pstream::broadcast(procsDir, comm_);
1254 
1255  // Use the master type to determine if additional information is
1256  // needed to construct the local equivalent
1257  switch (searchType)
1258  {
1262  {
1263  // Already handled above
1264  }
1265  break;
1266 
1274  {
1275  // Construct equivalent local path
1276  objPath = localObjectPath
1277  (
1278  io,
1279  searchType,
1280  procsDir,
1281  newInstancePath
1282  );
1283  }
1284  break;
1285 
1286  case fileOperation::OBJECT:
1288  {
1289  // Retest all processors separately since some processors might
1290  // have the file and some not (e.g. lagrangian data)
1291 
1292  objPath = masterOp<fileName>
1293  (
1294  io.objectPath(),
1295  fileOrNullOp(true), // isFile=true
1296  Pstream::msgType(),
1297  comm_
1298  );
1299  }
1300  break;
1301  }
1302  }
1303 
1304  if (debug)
1305  {
1306  Pout<< "masterUncollatedFileOperation::filePath :"
1307  << " Returning from file searching using type "
1308  << fileOperation::pathTypeNames_[searchType] << endl
1309  << " objectPath:" << io.objectPath() << endl
1310  << " filePath :" << objPath << endl << endl;
1311  }
1312  return objPath;
1313 }
1314 
1315 
1317 (
1318  const bool checkGlobal,
1319  const IOobject& io,
1320  const bool search
1321 ) const
1322 {
1323  if (debug)
1324  {
1325  Pout<< "masterUncollatedFileOperation::dirPath :"
1326  << " objectPath:" << io.objectPath()
1327  << " checkGlobal:" << checkGlobal
1328  << " parRun:" << Pstream::parRun()
1329  << " localmaster:" << Pstream::master(comm_) << endl;
1330  }
1331 
1332  // Now that we have an IOobject path use it to detect & cache
1333  // processor directory naming
1334  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1335 
1336  // Trigger caching of times
1337  if (cacheLevel() > 0)
1338  {
1339  (void)findTimes(io.time().path(), io.time().constant());
1340  }
1341 
1342  // Determine master dirPath and broadcast
1343 
1344  fileName objPath;
1345  pathType searchType = NOTFOUND;
1346  word procsDir;
1347  word newInstancePath;
1348 
1349  // Local IO node searches for file
1350  if (Pstream::master(comm_))
1351  {
1352  const bool oldParRun = UPstream::parRun(false);
1353  const int oldCache = fileOperation::cacheLevel(0);
1354  const label oldNProcs = fileOperation::nProcs();
1355 
1356  objPath = filePathInfo
1357  (
1358  checkGlobal,
1359  false,
1360  io,
1361  pDirs,
1362  search,
1363  searchType,
1364  procsDir,
1365  newInstancePath
1366  );
1367 
1368  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1369  fileOperation::cacheLevel(oldCache);
1370  UPstream::parRun(oldParRun);
1371 
1372  if (debug)
1373  {
1374  Pout<< "masterUncollatedFileOperation::dirPath :"
1375  << " master objPath:" << objPath
1376  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1377  << " procsDir:" << procsDir << " instance:" << newInstancePath
1378  << endl;
1379  }
1380  }
1381 
1382 
1383  // Broadcast information about where the master found the object
1384  // Note: use the worldComm to make sure all processors decide
1385  // the same type. Only procsDir is allowed to differ; searchType
1386  // and instance have to be same
1387  if (UPstream::parRun())
1388  {
1389  int masterType(searchType);
1390  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1391  searchType = pathType(masterType);
1392  }
1393 
1394 
1395  if
1396  (
1397  checkGlobal
1398  || searchType == fileOperation::PARENTOBJECT
1399  || searchType == fileOperation::PROCBASEOBJECT
1400  || searchType == fileOperation::PROCBASEINSTANCE
1401  || io.local() == "uniform"
1402  )
1403  {
1404  // Distribute master path. This makes sure it is seen as uniform
1405  // and only gets read from the master.
1406  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1407  }
1408  else
1409  {
1410  // Broadcast local processors dir amongst all local nodes
1411  Pstream::broadcast(procsDir, comm_);
1412 
1413  // Use the master type to determine if additional information is
1414  // needed to construct the local equivalent
1415  switch (searchType)
1416  {
1420  {
1421  // Already handled above
1422  }
1423  break;
1424 
1432  {
1433  // Construct equivalent local path
1434  objPath = localObjectPath
1435  (
1436  io,
1437  searchType,
1438  procsDir,
1439  newInstancePath
1440  );
1441  }
1442  break;
1443 
1444  case fileOperation::OBJECT:
1446  {
1447  // Retest all processors separately since some processors might
1448  // have the file and some not (e.g. lagrangian data)
1449 
1450  objPath = masterOp<fileName>
1451  (
1452  io.objectPath(),
1453  fileOrNullOp(false), // isFile=false
1454  Pstream::msgType(),
1455  comm_
1456  );
1457  }
1458  break;
1459  }
1460  }
1461 
1462  if (debug)
1463  {
1464  Pout<< "masterUncollatedFileOperation::dirPath :"
1465  << " Returning from directory searching using type "
1466  << fileOperation::pathTypeNames_[searchType] << endl
1467  << " objectPath:" << io.objectPath() << endl
1468  << " filePath :" << objPath << endl << endl;
1469  }
1470  return objPath;
1471 }
1472 
1473 
1475 (
1476  const dirIndexList& pDirs,
1477  IOobject& io
1478 ) const
1479 {
1480  // Cut-down version of filePathInfo that does not look for
1481  // different instance or parent directory
1482 
1483  const bool isFile = !io.name().empty();
1484 
1485  // Generate output filename for object
1486  const fileName writePath(objectPath(io, word::null));
1487 
1488  // 1. Test writing name for either directory or a (valid) file
1489  if (isFileOrDir(isFile, writePath))
1490  {
1491  return true;
1492  }
1493 
1494  // 2. Check processors/
1495  if (io.time().processorCase())
1496  {
1497  for (const dirIndex& dirIdx : pDirs)
1498  {
1499  const fileName& pDir = dirIdx.first();
1500  fileName procPath =
1501  processorsPath(io, io.instance(), pDir)
1502  /io.name();
1503  if (procPath != writePath && isFileOrDir(isFile, procPath))
1504  {
1505  return true;
1506  }
1507  }
1508  }
1509 
1510  // 3. Check local
1511  fileName localPath = io.objectPath();
1512 
1513  if (localPath != writePath && isFileOrDir(isFile, localPath))
1514  {
1515  return true;
1516  }
1518  return false;
1519 }
1520 
1521 
1524 (
1525  const IOobject& startIO,
1526  const scalar startValue,
1527  const word& stopInstance
1528 ) const
1529 {
1530  if (debug)
1531  {
1532  Pout<< "masterUncollatedFileOperation::findInstance :"
1533  << " Starting searching for name:" << startIO.name()
1534  << " local:" << startIO.local()
1535  << " from instance:" << startIO.instance()
1536  << endl;
1537  }
1538 
1539  const Time& time = startIO.time();
1540  IOobject io(startIO);
1541 
1542  // Note: - if name is empty, just check the directory itself
1543  // - check both for isFile and headerOk since the latter does a
1544  // filePath so searches for the file.
1545  // - check for an object with local file scope (so no looking up in
1546  // parent directory in case of parallel)
1547 
1548 
1549  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1550 
1551  word foundInstance;
1552 
1553  // if (Pstream::master(comm_))
1555  {
1556  const bool oldParRun = UPstream::parRun(false);
1557  const int oldCache = fileOperation::cacheLevel(0);
1558  const label oldNProcs = fileOperation::nProcs();
1559 
1560  if (exists(pDirs, io))
1561  {
1562  foundInstance = io.instance();
1563  }
1564  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1565  fileOperation::cacheLevel(oldCache);
1566  UPstream::parRun(oldParRun);
1567  }
1568 
1569 
1570  // Do parallel early exit to avoid calling time.times()
1571  Pstream::broadcast(foundInstance, UPstream::worldComm);
1572 
1573  if (!foundInstance.empty())
1574  {
1575  io.instance() = foundInstance;
1576  if (debug)
1577  {
1578  Pout<< "masterUncollatedFileOperation::findInstance :"
1579  << " for name:" << io.name() << " local:" << io.local()
1580  << " found starting instance:" << io.instance() << endl;
1581  }
1582  return io;
1583  }
1584 
1585 
1586  // Handling failures afterwards
1587  const bool exitIfMissing = startIO.isReadRequired();
1588 
1589  enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1590  int failed(0);
1591 
1592  instantList ts = time.times();
1593 
1594  // if (Pstream::master(comm_))
1596  {
1597  const bool oldParRun = UPstream::parRun(false);
1598  const int oldCache = fileOperation::cacheLevel(0);
1599  const label oldNProcs = fileOperation::nProcs();
1600 
1601  label instIndex = ts.size()-1;
1602 
1603  // Backward search for first time that is <= startValue
1604  for (; instIndex >= 0; --instIndex)
1605  {
1606  if (ts[instIndex].value() <= startValue)
1607  {
1608  break;
1609  }
1610  }
1611 
1612  // Continue (forward) searching from here
1613  for (; instIndex >= 0; --instIndex)
1614  {
1615  // Shortcut: if actual directory is the timeName we've
1616  // already tested it
1617  if (ts[instIndex].name() == time.timeName())
1618  {
1619  continue;
1620  }
1621 
1622  io.instance() = ts[instIndex].name();
1623  if (exists(pDirs, io))
1624  {
1625  foundInstance = io.instance();
1626  if (debug)
1627  {
1628  Pout<< "masterUncollatedFileOperation::findInstance :"
1629  << " for name:" << io.name() << " local:" << io.local()
1630  << " found at:" << io.instance()
1631  << endl;
1632  }
1633  break;
1634  }
1635 
1636  // Check if hit minimum instance
1637  if (io.instance() == stopInstance)
1638  {
1639  if (debug)
1640  {
1641  Pout<< "masterUncollatedFileOperation::findInstance :"
1642  << " name:" << io.name()
1643  << " local:" << io.local()
1644  << " at stop-instance:" << io.instance() << endl;
1645  }
1646 
1647  if (exitIfMissing)
1648  {
1649  failed = failureCodes::FAILED_STOPINST;
1650  }
1651  else
1652  {
1653  foundInstance = io.instance();
1654  }
1655  break;
1656  }
1657  }
1658 
1659 
1660  // times() usually already includes the constant() so would
1661  // have been checked above. However, re-test under these conditions:
1662  // - times() is empty. Sometimes this can happen (e.g. decomposePar
1663  // with collated)
1664  // - times()[0] is not constant
1665  // - Times is empty.
1666  // Sometimes this can happen (eg, decomposePar with collated)
1667  // - Times[0] is not constant
1668  // - The startValue is negative (eg, kivaTest).
1669  // This plays havoc with the reverse search, causing it to miss
1670  // 'constant'
1671 
1672  if
1673  (
1674  !failed && foundInstance.empty()
1675  && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1676  )
1677  {
1678  // Note. This needs to be a hard-coded "constant" (not constant
1679  // function of Time), because the latter points to
1680  // the case constant directory in parallel cases.
1681  // However, parRun is disabled so they are actually the same.
1682 
1683  io.instance() = time.constant();
1684 
1685  if (exists(pDirs, io))
1686  {
1687  if (debug)
1688  {
1689  Pout<< "masterUncollatedFileOperation::findInstance :"
1690  << " name:" << io.name()
1691  << " local:" << io.local()
1692  << " at:" << io.instance() << endl;
1693  }
1694  foundInstance = io.instance();
1695  }
1696  }
1697 
1698  if (!failed && foundInstance.empty())
1699  {
1700  if (exitIfMissing)
1701  {
1702  failed = failureCodes::FAILED_CONSTINST;
1703  }
1704  else
1705  {
1706  foundInstance = time.constant();
1707  }
1708  }
1709 
1710  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1711  fileOperation::cacheLevel(oldCache);
1712  UPstream::parRun(oldParRun); // Restore parallel state
1713  }
1714 
1715  Pstream::broadcast(foundInstance, UPstream::worldComm);
1716 
1717  io.instance() = foundInstance;
1718 
1719 
1720  // Handle failures
1721  // ~~~~~~~~~~~~~~~
1722  if (failed)
1723  {
1724  FatalErrorInFunction << "Cannot find";
1725 
1726  if (!io.name().empty())
1727  {
1728  FatalError
1729  << " file \"" << io.name() << "\" in";
1730  }
1731 
1732  FatalError
1733  << " directory "
1734  << io.local() << " in times "
1735  << startIO.instance() << " down to ";
1736 
1737  if (failed == failureCodes::FAILED_STOPINST)
1738  {
1739  FatalError << stopInstance;
1740  }
1741  else
1742  {
1743  FatalError << "constant";
1744  }
1746  }
1747 
1748  if (debug)
1749  {
1750  Pout<< "masterUncollatedFileOperation::findInstance :"
1751  << " name:" << io.name() << " local:" << io.local()
1752  << " returning instance:" << io.instance() << endl;
1753  }
1754  return io;
1755 }
1756 
1757 
1760 (
1761  const objectRegistry& db,
1762  const fileName& instance,
1763  const fileName& local,
1764  word& newInstance
1765 ) const
1766 {
1767  if (debug)
1768  {
1769  Pout<< "masterUncollatedFileOperation::readObjects :"
1770  << " db:" << db.objectPath()
1771  << " local:" << local << " instance:" << instance << endl;
1772  }
1773 
1774  fileNameList objectNames;
1775  newInstance.clear();
1776 
1777  // Note: readObjects uses WORLD to make sure order of objects is the
1778  // same everywhere
1779 
1781  {
1782  // Avoid fileOperation::readObjects from triggering parallel ops
1783  // (through call to filePath which triggers parallel )
1784  const bool oldParRun = UPstream::parRun(false);
1785  const int oldCache = fileOperation::cacheLevel(0);
1786  const label oldNProcs = fileOperation::nProcs();
1787 
1788  //- Use non-time searching version
1789  objectNames = fileOperation::readObjects
1790  (
1791  db,
1792  instance,
1793  local,
1794  newInstance
1795  );
1796 
1797  if (newInstance.empty())
1798  {
1799  // Find similar time
1800 
1801  // Copy of Time::findInstancePath. We want to avoid the
1802  // parallel call to findTimes. Alternative is to have
1803  // version of findInstancePath that takes instantList ...
1804  const instantList timeDirs
1805  (
1807  (
1808  db.time().path(),
1809  db.time().constant()
1810  )
1811  );
1812 
1813  const instant t(instance);
1814  forAllReverse(timeDirs, i)
1815  {
1816  if (t.equal(timeDirs[i].value()))
1817  {
1818  objectNames = fileOperation::readObjects
1819  (
1820  db,
1821  timeDirs[i].name(), // newly found time
1822  local,
1823  newInstance
1824  );
1825  break;
1826  }
1827  }
1828  }
1829 
1830  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1831  fileOperation::cacheLevel(oldCache);
1832  UPstream::parRun(oldParRun); // Restore parallel state
1833  }
1834 
1835  Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1836 
1837  if (debug)
1838  {
1839  Pout<< "masterUncollatedFileOperation::readObjects :"
1840  << " newInstance:" << newInstance
1841  << " objectNames:" << objectNames << endl;
1842  }
1843 
1844  return objectNames;
1845 }
1846 
1847 
1849 (
1850  IOobject& io,
1851  const fileName& fName,
1852  const word& typeName
1853 ) const
1854 {
1855  bool ok = false;
1856 
1857  if (debug)
1858  {
1859  Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1860  << " objectPath:" << io.objectPath() << endl
1861  << " filePath :" << fName << endl;
1862  }
1863 
1864  // We assume if filePath is the same
1865  // - headerClassName
1866  // - note
1867  // are also the same, independent of where the file came from.
1868 
1869  // Get filePaths on world master
1871  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
1873 
1874  bool uniform
1875  (
1877  && fileOperation::uniformFile(filePaths)
1878  );
1879 
1881 
1882  if (uniform)
1883  {
1885  {
1886  if (!fName.empty())
1887  {
1888  IFstream is(fName);
1889 
1890  if (is.good())
1891  {
1892  // Regular header or from decomposed data
1894  }
1895  }
1896  }
1897 
1899  (
1901  ok,
1902  io.headerClassName(),
1903  io.note()
1904  );
1905  }
1906  else
1907  {
1909  {
1910  // Assume if different nprocs the communicators are also
1911  // different. Re-gather file paths on local master
1912  filePaths.resize(UPstream::nProcs(comm_));
1913  filePaths[UPstream::myProcNo(comm_)] = fName;
1914  Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
1915  }
1916 
1917  // Intermediate storage arrays (master only)
1918  boolList result;
1919  wordList headerClassName;
1920  stringList note;
1921 
1922  if (Pstream::master(comm_))
1923  {
1924  const label np = Pstream::nProcs(comm_);
1925 
1926  result.resize(np, false);
1927  headerClassName.resize(np);
1928  note.resize(np);
1929 
1930  forAll(filePaths, proci)
1931  {
1932  if (!filePaths[proci].empty())
1933  {
1934  if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1935  {
1936  result[proci] = result[proci-1];
1937  headerClassName[proci] = headerClassName[proci-1];
1938  note[proci] = note[proci-1];
1939  }
1940  else
1941  {
1942  IFstream is(filePaths[proci]);
1943 
1944  if (is.good())
1945  {
1946  result[proci] =
1948  headerClassName[proci] = io.headerClassName();
1949  note[proci] = io.note();
1950  }
1951  }
1952  }
1953  }
1954  }
1955 
1956  // Is a more efficient scatter possible?
1957  PstreamBuffers pBufs(comm_, UPstream::commsTypes::nonBlocking);
1958 
1959  if (Pstream::master(comm_))
1960  {
1961  ok = result[0];
1962  io.headerClassName() = headerClassName[0];
1963  io.note() = note[0];
1964 
1965  // Scatter to each proc
1966  for (const int proci : pBufs.subProcs())
1967  {
1968  UOPstream os(proci, pBufs);
1969  os << result[proci] << headerClassName[proci] << note[proci];
1970  }
1971  }
1972 
1973  pBufs.finishedScatters();
1974 
1975  if (!Pstream::master(comm_))
1976  {
1977  UIPstream is(Pstream::masterNo(), pBufs);
1978  is >> ok >> io.headerClassName() >> io.note();
1979  }
1980  }
1981 
1982  if (debug)
1983  {
1984  Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1985  << " class:" << io.headerClassName()
1986  << " for file:" << fName << endl;
1987  }
1988  return ok;
1990 
1991 
1994 (
1995  regIOobject& io,
1996  const fileName& fName,
1997  const word& typeName,
1998  const bool readOnProc
1999 ) const
2000 {
2001  if (debug)
2002  {
2003  Pout<< "masterUncollatedFileOperation::readStream :"
2004  << " object : " << io.name()
2005  << " global : " << io.global()
2006  << " globalObject : " << io.globalObject()
2007  << " fName : " << fName << " readOnProc:" << readOnProc << endl;
2008  }
2009 
2010  // Close old stream
2011  io.close();
2012 
2013  autoPtr<ISstream> isPtr;
2014  bool isCollated = false;
2015  IOobject headerIO(io);
2016 
2017  // Detect collated format. This could be done on the local communicator
2018  // but we do it on the master node only for now.
2020  {
2021  if (!fName.empty())
2022  {
2023  // This can happen in lagrangian field reading some processors
2024  // have no file to read from. This will only happen when using
2025  // normal writing since then the fName for the valid processors is
2026  // processorDDD/<instance>/.. . In case of collocated writing
2027  // the fName is already rewritten to processorsNN/.
2028 
2029  isPtr.reset(new IFstream(fName));
2030 
2031  if (isPtr->good())
2032  {
2033  // Read header data (on copy)
2034  headerIO.readHeader(*isPtr);
2035 
2036  isCollated = decomposedBlockData::isCollatedType(headerIO);
2037 
2038  if (!isCollated && !Pstream::parRun())
2039  {
2040  // Short circuit: non-collated format. No parallel bits.
2041  // Copy header and return.
2042  if (debug)
2043  {
2044  Pout<< "masterUncollatedFileOperation::readStream :"
2045  << " For object : " << io.name()
2046  << " doing straight IFstream input from "
2047  << fName << endl;
2048  }
2049 
2050  // Copy IOobject header information
2051  io.IOobject::operator=(headerIO);
2052  return isPtr;
2053  }
2054  }
2055 
2056  if (!isCollated)
2057  {
2058  // Close file. Reopened below.
2059  isPtr.clear();
2060  }
2061  }
2062  }
2063 
2065 
2066  if (isCollated)
2067  {
2068  if (debug)
2069  {
2070  Pout<< "masterUncollatedFileOperation::readStream :"
2071  << " For object : " << io.name()
2072  << " starting collating input from " << fName << endl;
2073  }
2074 
2075 
2076  // Analyse the file path (on (co)master) to see the processors type
2077  // Note: this should really be part of filePath() which should return
2078  // both file and index in file.
2079 
2080  fileName path, procDir, local;
2081  procRangeType group;
2082  label nProcs;
2083  splitProcessorPath(fName, path, procDir, local, group, nProcs);
2084 
2085 
2086  if (!UPstream::parRun())
2087  {
2088  // Analyse the objectpath to find out the processor we're trying
2089  // to access
2090  label proci = detectProcessorPath(io.objectPath());
2091 
2092  if (proci == -1)
2093  {
2094  FatalIOErrorInFunction(*isPtr)
2095  << "Could not detect processor number"
2096  << " from objectPath:" << io.objectPath()
2097  << " fileHandler : comm:" << comm_
2098  << " ioRanks:" << flatOutput(ioRanks_)
2099  << exit(FatalIOError);
2100  }
2101 
2102  // The local rank (offset)
2103  if (!group.empty())
2104  {
2105  proci = proci - group.start();
2106  }
2107 
2108  if (debug)
2109  {
2110  Pout<< "masterUncollatedFileOperation::readStream :"
2111  << " For object : " << io.name()
2112  << " starting input from block " << proci
2113  << " of " << isPtr->name() << endl;
2114  }
2115 
2116  return decomposedBlockData::readBlock(proci, *isPtr, io);
2117  }
2118  else
2119  {
2120  // Are we reading from single-master file ('processors256') or
2121  // from multi-master files ('processors256_0-9')
2122  label readComm = -1;
2123  if (!group.empty())
2124  {
2125  readComm = comm_;
2126  if (UPstream::master(comm_) && !isPtr && !fName.empty())
2127  {
2128  // In multi-master mode also open the file on the other
2129  // masters
2130  isPtr.reset(new IFstream(fName));
2131 
2132  if (isPtr->good())
2133  {
2134  // Read header data (on copy)
2135  IOobject headerIO(io);
2136  headerIO.readHeader(*isPtr);
2137  }
2138  }
2139  }
2140  else
2141  {
2142  // Single master so read on world
2143  readComm = UPstream::worldComm;
2144  }
2145 
2146  // Get size of file to determine communications type
2147  bool bigSize = false;
2148 
2150  {
2151  // TBD: handle multiple masters?
2152  bigSize =
2153  (
2154  off_t(Foam::fileSize(fName))
2155  > off_t(maxMasterFileBufferSize)
2156  );
2157  }
2158  // Reduce (not broadcast)
2159  // - if we have multiple master files (FUTURE)
2161 
2162  const UPstream::commsTypes myCommsType
2163  (
2164  bigSize
2167  );
2168 
2169  // Read my data
2171  (
2172  readComm,
2173  fName,
2174  isPtr,
2175  io,
2176  myCommsType
2177  );
2178  }
2179  }
2180  else
2181  {
2182  if (debug)
2183  {
2184  Pout<< "masterUncollatedFileOperation::readStream :"
2185  << " For object : " << io.name()
2186  << " starting separated input from " << fName << endl;
2187  }
2188 
2189  if (io.global() || io.globalObject())
2190  {
2191  // Use worldComm. Note: should not really need to gather filePaths
2192  // since we enforce sending from master anyway ...
2194  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
2196  (
2197  filePaths,
2200  );
2201 
2202  boolList readOnProcs
2203  (
2204  UPstream::listGatherValues<bool>
2205  (
2206  readOnProc,
2208  )
2209  );
2210  // NB: local proc validity information required on sub-ranks too!
2211  readOnProcs.resize(UPstream::nProcs(UPstream::worldComm));
2212  readOnProcs[UPstream::myProcNo(UPstream::worldComm)] = readOnProc;
2213 
2214  // Uniform in local comm
2215  return read(io, UPstream::worldComm, true, filePaths, readOnProcs);
2216  }
2217  else
2218  {
2219  // Use local communicator
2220  fileNameList filePaths(UPstream::nProcs(comm_));
2221  filePaths[UPstream::myProcNo(comm_)] = fName;
2223  (
2224  filePaths,
2226  comm_
2227  );
2228 
2229  boolList readOnProcs
2230  (
2231  UPstream::listGatherValues<bool>
2232  (
2233  readOnProc,
2234  comm_
2235  )
2236  );
2237  // NB: local proc validity information required on sub-ranks too!
2238  readOnProcs.resize(UPstream::nProcs(comm_));
2239  readOnProcs[UPstream::myProcNo(comm_)] = readOnProc;
2240 
2241  // Uniform in local comm
2242  const bool uniform = fileOperation::uniformFile(filePaths);
2243 
2244  return read(io, comm_, uniform, filePaths, readOnProcs);
2245  }
2246  }
2247 }
2248 
2249 
2251 (
2252  regIOobject& io,
2253  const bool masterOnly,
2255  const word& typeName
2256 ) const
2257 {
2258  bool ok = true;
2259 
2260  if (io.global() || io.globalObject())
2261  {
2262  if (debug)
2263  {
2264  Pout<< "masterUncollatedFileOperation::read :"
2265  << " Reading global object " << io.name()
2266  << " worldComm:" << UPstream::worldComm
2267  << " Pstream::myProcNo:"
2269  << " amMaster:" << Pstream::master(UPstream::worldComm)
2270  << endl;
2271  }
2272 
2273  bool ok = false;
2275  {
2276  // Do master-only reading always.
2277  const bool oldParRun = UPstream::parRun(false);
2278  const int oldCache = fileOperation::cacheLevel(0);
2279  const label oldNProcs = fileOperation::nProcs();
2280 
2281  auto& is = io.readStream(typeName);
2282  ok = io.readData(is);
2283  io.close();
2284 
2285  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2286  fileOperation::cacheLevel(oldCache);
2287  UPstream::parRun(oldParRun); // Restore parallel state
2288  }
2289 
2290  // Broadcast regIOobjects content
2291  if (Pstream::parRun())
2292  {
2294  (
2296  ok,
2297  io.headerClassName(),
2298  io.note()
2299  );
2300 
2302  {
2303  OPBstream toAll
2304  (
2307  format
2308  );
2309  bool okWrite = io.writeData(toAll);
2310  ok = ok && okWrite;
2311  }
2312  else
2313  {
2314  IPBstream fromMaster
2315  (
2318  format
2319  );
2320  ok = io.readData(fromMaster);
2321  }
2322  }
2323  }
2324  else
2325  {
2326  if (debug)
2327  {
2328  Pout<< "masterUncollatedFileOperation::read :"
2329  << " Reading local object " << io.name() << endl;
2330  }
2331 
2332  ok = io.readData(io.readStream(typeName));
2333  io.close();
2334  }
2335 
2336  if (debug)
2337  {
2338  Pout<< "masterUncollatedFileOperation::read :"
2339  << " Read object:" << io.name()
2340  << " isGlobal:" << (io.global() || io.globalObject())
2341  << " status:" << ok << endl;
2342  }
2343 
2344  return ok;
2345 }
2346 
2347 
2349 (
2350  const regIOobject& io,
2351  IOstreamOption streamOpt,
2352  const bool writeOnProc
2353 ) const
2354 {
2355  fileName pathName(io.objectPath());
2356 
2357  if (debug)
2358  {
2359  Pout<< "masterUncollatedFileOperation::writeObject :"
2360  << " io:" << pathName << " writeOnProc:" << writeOnProc << endl;
2361  }
2362 
2363  // Make sure to pick up any new times
2364  setTime(io.time());
2365 
2366  // Update meta-data for current state
2367  const_cast<regIOobject&>(io).updateMetaData();
2368 
2369  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, writeOnProc));
2370  OSstream& os = *osPtr;
2371 
2372  // If any of these fail, return (leave error handling to Ostream class)
2373 
2374  const bool ok =
2375  (
2376  os.good()
2377  && io.writeHeader(os)
2378  && io.writeData(os)
2379  );
2380 
2381  if (ok)
2382  {
2384  }
2385 
2386  return ok;
2387 }
2388 
2389 
2391 (
2392  const fileName& directory,
2393  const word& constantName
2394 ) const
2395 {
2396  const auto iter = times_.cfind(directory);
2397  if (iter.good())
2398  {
2399  if (debug)
2400  {
2401  Pout<< "masterUncollatedFileOperation::findTimes :"
2402  << " Found " << iter.val()->size() << " cached times" << nl
2403  << " for directory:" << directory << endl;
2404  }
2405  return *(iter.val());
2406  }
2407  else
2408  {
2409  instantList times;
2411  {
2412  // Do master-only reading always.
2413  const bool oldParRun = UPstream::parRun(false);
2414  const int oldCache = fileOperation::cacheLevel(0);
2415  const label oldNProcs = fileOperation::nProcs();
2416 
2417  times = fileOperation::findTimes(directory, constantName);
2418 
2419  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2420  fileOperation::cacheLevel(oldCache);
2421  UPstream::parRun(oldParRun); // Restore parallel state
2422  }
2423 
2425 
2426  if (debug)
2427  {
2428  Pout<< "masterUncollatedFileOperation::findTimes :"
2429  << " Found times:" << flatOutput(times) << nl
2430  << " for directory:" << directory << endl;
2431  }
2432 
2433  // Caching
2434  // - cache values even if no times were found since it might
2435  // indicate a directory that is being filled later on ...
2436  if (cacheLevel() > 0)
2437  {
2438  auto* tPtr = new DynamicList<instant>(std::move(times));
2439  times_.set(directory, tPtr);
2440 
2441  return *tPtr;
2442  }
2443 
2444  // Times found (not cached)
2445  return times;
2446  }
2447 }
2448 
2449 
2451 (
2452  const Time& tm
2453 ) const
2454 {
2455  if (tm.subCycling())
2456  {
2457  return;
2458  }
2459 
2460  // Mutable access to instant list for modification and sorting
2461  // - cannot use auto type deduction here
2462 
2463  auto iter = times_.find(tm.path());
2464 
2465  if (iter.good())
2466  {
2467  DynamicList<instant>& times = *(iter.val());
2468 
2469  const instant timeNow(tm.value(), tm.timeName());
2470 
2471  // The start index for checking and sorting (excluding "constant")
2472  const label startIdx =
2473  (
2474  (times.empty() || times[0].name() != tm.constant())
2475  ? 0
2476  : 1
2477  );
2478 
2479  // This routine always results in a sorted list of times, so first
2480  // check if the new time is greater than the latest existing time.
2481  // Can then simply append without extra searching or sorting
2482 
2483  if (times.size() <= startIdx || times.last() < timeNow)
2484  {
2485  times.append(timeNow);
2486  }
2487  else if
2488  (
2490  (
2491  SubList<instant>(times, times.size()-startIdx, startIdx),
2492  timeNow
2493  ) < 0
2494  )
2495  {
2496  if (debug)
2497  {
2498  Pout<< "masterUncollatedFileOperation::setTime :"
2499  << " Caching time " << tm.timeName()
2500  << " for case:" << tm.path() << endl;
2501  }
2502 
2503  times.append(timeNow);
2504 
2505  SubList<instant> realTimes
2506  (
2507  times, times.size()-startIdx, startIdx
2508  );
2509  Foam::stableSort(realTimes);
2510  }
2511  }
2512 
2515 
2516 
2519 (
2520  const fileName& filePath
2521 ) const
2522 {
2523  autoPtr<ISstream> isPtr;
2524 
2525  if (Pstream::parRun())
2526  {
2527  // Insert logic of filePath. We assume that if a file is absolute
2528  // on the master it is absolute also on the sub-ranks etc.
2529 
2530  fileNameList filePaths(Pstream::nProcs(comm_));
2531  filePaths[Pstream::myProcNo(comm_)] = filePath;
2532  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2533 
2535 
2536  if (Pstream::master(comm_))
2537  {
2538  // Same filename on the IO node -> same file
2539  const bool uniform = fileOperation::uniformFile(filePaths);
2540 
2541  if (uniform)
2542  {
2543  if (debug)
2544  {
2545  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2546  << " Opening global file " << filePath << endl;
2547  }
2548 
2549  readAndSend
2550  (
2551  filePath,
2552  identity(Pstream::nProcs(comm_)-1, 1),
2553  pBufs
2554  );
2555  }
2556  else
2557  {
2558  for (const int proci : Pstream::subProcs(comm_))
2559  {
2560  if (debug)
2561  {
2562  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2563  << " Opening local file " << filePath
2564  << " for rank " << proci << endl;
2565  }
2566 
2567  readAndSend
2568  (
2569  filePaths[proci],
2570  labelList(one{}, proci),
2571  pBufs
2572  );
2573  }
2574  }
2575  }
2576 
2577 
2578  pBufs.finishedSends();
2579 
2580  if (Pstream::master(comm_))
2581  {
2582  // Read myself
2583  isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2584  }
2585  else
2586  {
2587  if (debug)
2588  {
2589  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2590  << " Reading " << filePath
2591  << " from processor " << Pstream::masterNo() << endl;
2592  }
2593 
2595 
2596  if (!buf.empty())
2597  {
2598  UIPstream is(Pstream::masterNo(), pBufs);
2599  is.read(buf.data(), buf.size());
2600  }
2601 
2602  if (debug)
2603  {
2604  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2605  << " Done reading " << buf.size() << " bytes" << endl;
2606  }
2607 
2608  // A local character buffer copy of the Pstream contents.
2609  // Construct with same parameters (ASCII, current version)
2610  // as the IFstream so that it has the same characteristics.
2611 
2612  isPtr.reset(new ICharStream(std::move(buf)));
2613 
2614  // With the proper file name
2615  isPtr->name() = filePath;
2616  }
2617  }
2618  else
2619  {
2620  // Read myself
2621  isPtr.reset(new IFstream(filePath));
2622  }
2623 
2624  return isPtr;
2626 
2627 
2630 (
2631  const fileName& pathName,
2632  IOstreamOption streamOpt,
2633  const bool writeOnProc
2634 ) const
2635 {
2636  return autoPtr<OSstream>
2637  (
2638  new masterOFstream
2639  (
2640  comm_,
2641  pathName,
2642  streamOpt,
2644  writeOnProc
2645  )
2646  );
2648 
2649 
2652 (
2654  const fileName& pathName,
2655  IOstreamOption streamOpt,
2656  const bool writeOnProc
2657 ) const
2658 {
2659  return autoPtr<OSstream>
2660  (
2661  new masterOFstream
2662  (
2663  atomic,
2664  comm_,
2665  pathName,
2666  streamOpt,
2668  writeOnProc
2669  )
2670  );
2671 }
2672 
2673 
2675 {
2677  times_.clear();
2678 }
2679 
2680 
2682 {
2683  if (debug)
2684  {
2685  Pout<< "masterUncollatedFileOperation::sync :"
2686  << " syncing information across processors" << endl;
2687  }
2688 
2690 
2691 
2692  wordList timeNames;
2693  List<DynamicList<instant>> instants;
2694 
2696  {
2697  timeNames.resize(times_.size());
2698  instants.resize(times_.size());
2699 
2700  // Flatten into two lists to preserve key/val pairing
2701  label i = 0;
2702  forAllConstIters(times_, iter)
2703  {
2704  timeNames[i] = iter.key();
2705  instants[i] = std::move(*(iter.val()));
2706  ++i;
2707  }
2708  }
2709 
2710  Pstream::broadcasts(UPstream::worldComm, timeNames, instants);
2711 
2712  times_.clear();
2713  forAll(timeNames, i)
2714  {
2715  fileName dir(timeNames[i]);
2716  auto ptr = autoPtr<DynamicList<instant>>::New(std::move(instants[i]));
2717 
2719  {
2720  // Replace processor0 ending with processorDDD
2721  fileName path;
2722  fileName pDir;
2723  fileName local;
2724  procRangeType group;
2725  label numProcs;
2726  const label proci = splitProcessorPath
2727  (
2728  dir,
2729  path,
2730  pDir,
2731  local,
2732  group,
2733  numProcs
2734  );
2735 
2736  //Pout<< "**sync : From dir : " << dir << nl
2737  // << " path : " << path << nl
2738  // << " pDir : " << pDir << nl
2739  // << " local: " << local << nl
2740  // << " proci: " << proci << nl
2741  // << endl;
2742 
2743  const label myProci = Pstream::myProcNo(UPstream::worldComm);
2744 
2745  if (proci != -1 && proci != myProci)
2746  {
2747  dir = path/"processor" + Foam::name(myProci);
2748  }
2749  }
2750 
2751  times_.insert(dir, ptr);
2752  }
2753 }
2754 
2755 
2757 (
2758  const fileName& fName
2759 ) const
2760 {
2761  label watchFd = -1;
2763  {
2764  watchFd = monitor().addWatch(fName);
2765  }
2766 
2768  return watchFd;
2769 }
2770 
2771 
2773 (
2774  const label watchIndex
2775 ) const
2776 {
2777  bool ok = false;
2779  {
2780  ok = monitor().removeWatch(watchIndex);
2781  }
2782 
2784  return ok;
2785 }
2786 
2787 
2789 (
2790  const labelList& watchIndices,
2791  const fileName& fName
2792 ) const
2793 {
2794  label index = -1;
2795 
2797  {
2798  forAll(watchIndices, i)
2799  {
2800  if (monitor().getFile(watchIndices[i]) == fName)
2801  {
2802  index = i;
2803  break;
2804  }
2805  }
2806  }
2807 
2809  return index;
2810 }
2811 
2812 
2814 (
2815  regIOobject& rio,
2816  const fileNameList& files
2817 ) const
2818 {
2819  const labelList& watchIndices = rio.watchIndices();
2820 
2821  // Do on master and distribute effect to subprocs such that after
2822  // all have consistent numbering & files
2823 
2824  DynamicList<label> newWatchIndices;
2825  if (UPstream::master())
2826  {
2827  // Switch off comms inside findWatch/addWatch etc.
2828  const bool oldParRun = UPstream::parRun(false);
2829  const int oldCache = fileOperation::cacheLevel(0);
2830  const label oldNProcs = fileOperation::nProcs();
2831 
2832  labelHashSet removedWatches(watchIndices);
2833 
2834  for (const fileName& f : files)
2835  {
2836  const label index = findWatch(watchIndices, f);
2837 
2838  if (index == -1)
2839  {
2840  newWatchIndices.push_back(addWatch(f));
2841  }
2842  else
2843  {
2844  // Existing watch
2845  newWatchIndices.push_back(watchIndices[index]);
2846  removedWatches.erase(index);
2847  }
2848  }
2849 
2850  // Remove any unused watches
2851  for (const label index : removedWatches)
2852  {
2853  removeWatch(watchIndices[index]);
2854  }
2855 
2856  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2857  fileOperation::cacheLevel(oldCache);
2858  UPstream::parRun(oldParRun);
2859  }
2860  Pstream::broadcast(newWatchIndices);
2861 
2862  rio.watchIndices() = newWatchIndices;
2863 }
2864 
2865 
2867 (
2868  const label watchIndex
2869 ) const
2870 {
2871  fileName fName;
2873  {
2874  fName = monitor().getFile(watchIndex);
2875  }
2876 
2878  return fName;
2879 }
2880 
2881 
2883 (
2884  const bool masterOnly,
2885  const bool syncPar
2886 ) const
2887 {
2889  {
2890  monitor().updateStates(true, false);
2891  }
2893 
2894 
2897 (
2898  const label watchFd
2899 ) const
2900 {
2901  unsigned int state = fileMonitor::UNMODIFIED;
2903  {
2904  state = monitor().getState(watchFd);
2905  }
2906 
2908  return fileMonitor::fileState(state);
2909 }
2910 
2911 
2913 (
2914  const label watchFd
2915 ) const
2916 {
2918  {
2919  monitor().setUnmodified(watchFd);
2920  }
2921 }
2922 
2923 
2924 // ************************************************************************* //
virtual void storeComm() const
Transfer ownership of communicator to this fileOperation. Use with caution.
virtual mode_t mode(const fileName &, const bool followLink=true) const
Return the file mode.
static word findInstancePath(const instantList &timeDirs, const instant &t)
Equivalent of Time::findInstance.
fileName localObjectPath(const IOobject &, const pathType &searchType, const word &processorsDir, const word &instancePath) const
Construct filePath.
virtual bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true) const
Does the name exist as a FILE in the file system?
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle)
static const Enum< pathType > pathTypeNames_
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const
Copy, recursively if necessary, the source to the destination.
const Type & value() const noexcept
Return const reference to value.
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
fileName path() const
Return path = rootPath/caseName. Same as TimePaths::path()
Definition: Time.H:503
virtual Istream & readRaw(char *data, std::streamsize count) override
Low-level raw binary read (without possible block delimiters). Reading into a null pointer behaves li...
Definition: ISstream.C:1037
virtual fileNameList readDir(const fileName &, const fileName::Type=fileName::FILE, const bool filtergz=true, const bool followLink=true) const
Read a directory and return the entries as a string list.
Input/output streams with (internal or external) character storage.
A class for handling file names.
Definition: fileName.H:72
off_t fileSize(const fileName &name, const bool followLink=true)
Return size of file or -1 on failure (normally follows symbolic links).
Definition: POSIX.C:905
virtual time_t lastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
io.objectPath() exists
static label read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:35
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
as PROCUNCOLLATED but with instance
masterUncollatedFileOperation(bool verbose=false)
Default construct.
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
commsTypes
Communications types.
Definition: UPstream.H:72
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
void finishedScatters(const bool wait=true)
Mark all sends to sub-procs as done.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:54
label nProcs() const noexcept
Overall number of processors, from UPstream::nProcs() or detected from directories/results.
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
static autoPtr< ISstream > read(IOobject &io, const label comm, const bool uniform, const fileNameList &filePaths, const boolUList &readOnProcs)
Read files on comms master.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
virtual autoPtr< ISstream > NewIFstream(const fileName &) const
Generate an ISstream that reads a file.
static autoPtr< ISstream > readBlock(const label blocki, ISstream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
static void freeCommunicator(const label communicator, const bool withComponents=true)
Free a previously allocated communicator.
Definition: UPstream.C:565
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:70
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:1176
int infoDetailLevel
Global for selective suppression of Info output.
virtual double highResLastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:272
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:353
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const
Read object header from supplied file.
virtual bool isDir(const fileName &, const bool followLink=true) const
Does the name exist as a DIRECTORY in the file system?
label findSortedIndex(const ListType &input, typename ListType::const_reference val, const label start=0)
Binary search to find the index of the last element in a sorted list that is less than value...
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
virtual bool rmDir(const fileName &dir, const bool silent=false, const bool emptyOnly=false) const
Remove a directory and its contents.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:255
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
static void reduceOr(bool &value, const label communicator=worldComm)
Logical (or) reduction (MPI_AllReduce)
file found in time directory
virtual autoPtr< ISstream > readStream(regIOobject &, const fileName &, const word &typeName, const bool readOnProc=true) const
Reads header for regIOobject and returns an ISstream to read the contents.
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:312
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:303
static bool readBlocks(const label comm, autoPtr< ISstream > &isPtr, List< char > &contentChars, const UPstream::commsTypes commsType)
Read data into *this. ISstream is only valid on master.
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
label subCycling() const noexcept
Zero (tests as false) if time is not being sub-cycled, otherwise the current sub-cycle index or the t...
Definition: Time.H:743
A simple container for options an IOstream can normally have.
virtual bool ln(const fileName &src, const fileName &dst) const
Create a softlink. dst should not exist. Returns true if.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:409
List< string > stringList
List of string.
Definition: stringList.H:32
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
A class for managing references or pointers (no reference counting)
Definition: HashPtrTable.H:49
bool exists(const dirIndexList &, IOobject &io) const
Helper: check IO for local existence. Like filePathInfo but.
An encapsulation of filesystem-related operations.
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
Macros for easy insertion into run-time selection tables.
as PROCOBJECT but with instance
static bool isReadRequired(readOption opt) noexcept
True if (MUST_READ | READ_MODIFIED) bits are set.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:225
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
constexpr const char *const group
Group name for atomic constants.
virtual fileName filePath(const bool checkGlobal, const IOobject &io, const word &typeName, const bool search) const
Search for an object. checkGlobal : also check undecomposed case.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
addToRunTimeSelectionTable(fileOperation, collatedFileOperation, word)
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Writes a regIOobject (so header, contents and divider).
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer...
Definition: UIPstream.H:287
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
atomicType
Atomic operations (output)
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1065
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
instance is absolute directory
"scheduled" : (MPI_Send, MPI_Recv)
bool good() const noexcept
True if the managed pointer is non-null.
Definition: autoPtr.H:206
objectPath exists in &#39;processorsNN&#39;
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
static float maxMasterFileBufferSize
Max size of parallel communications. Switches from non-blocking.
A class for handling words, derived from Foam::string.
Definition: word.H:63
const Time & time() const noexcept
Return time registry.
Master-only drop-in replacement for OFstream.
objectPath exists in &#39;processorN&#39;
virtual fileName dirPath(const bool checkGlobal, const IOobject &io, const bool search) const
Search for a directory. checkGlobal : also check undecomposed.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1059
void finishedSends(const bool wait=true)
Mark the send phase as being finished.
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
static DynamicList< char > slurpFile(IFstream &ifs)
static const word null
An empty word.
Definition: word.H:84
addNamedToRunTimeSelectionTable(fileOperationInitialise, fileOperationInitialise_collated, word, collated)
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: POSIX.C:835
bool local
Definition: EEqn.H:20
as PROCBASEOBJECT but with instance
objectPath exists in &#39;processorsNN_first-last&#39;
static bool isCollatedType(const word &objectType)
True if object type is a known collated type.
virtual bool removeWatch(const label) const
Remove watch on a file (using handle)
#define DetailInfo
Definition: evalEntry.C:30
static void readAndSend(const fileName &filePath, const labelUList &recvProcs, PstreamBuffers &pBufs)
Read file contents and send to processors.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
static bool readHeader(IOobject &io, Istream &is)
Read header as per IOobject with additional handling of decomposedBlockData.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:456
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
UPstream::rangeType subProcs() const noexcept
Range of sub-processes indices associated with PstreamBuffers.
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:197
virtual bool mvBak(const fileName &, const std::string &ext="bak") const
Rename to a corresponding backup file.
virtual void sync()
Forcibly parallel sync.
static int cacheLevel() noexcept
Return cache level.
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
virtual std::istream & stdStream() override
Access to underlying std::istream.
Definition: IFstream.C:126
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
label recvDataCount(const label proci) const
Number of unconsumed receive bytes for the specified processor. Must call finishedSends() or other fi...
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:343
compressionType compression() const noexcept
Get the stream compression.
Input from file stream, using an ISstream.
Definition: IFstream.H:49
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
labelList f(nPoints)
static Tuple2< label, labelList > getCommPattern()
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:555
static bool uniformFile(const fileNameList &names)
True if the file names are identical. False on an empty list.
static labelRange subRanks(const labelUList &mainIOranks)
Get (contiguous) range/bounds of ranks addressed within the given main io-ranks.
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:266
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:472
word format(conversionProperties.get< word >("format"))
std::streamsize fileSize() const
Return the size of the underlying file (-1 on error). This corresponds to Foam::fileSize() but with e...
Definition: IFstream.C:87
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: POSIX.C:877
List< word > wordList
List of word.
Definition: fileName.H:59
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name...
Definition: instant.H:53
virtual bool rm(const fileName &) const
Remove a file, returning true if successful otherwise false.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
virtual fileName filePathInfo(const bool checkGlobal, const bool isFile, const IOobject &io, const dirIndexList &pDirs, const bool search, pathType &searchType, word &processorsDir, word &instance) const
Search (locally!) for object; return info on how it was found.
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:118
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:240
virtual void setTime(const Time &) const
Callback for time change.
#define WarningInFunction
Report a warning using Foam::Warning.
static List< int > & procID(const label communicator)
The list of ranks within a given communicator.
Definition: UPstream.H:1130
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
const T2 & second() const noexcept
Access the second element.
Definition: Tuple2.H:142
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
An ISstream with internal List storage. Always UNCOMPRESSED.
Definition: ICharStream.H:276
registerOptSwitch("maxThreadFileBufferSize", float, collatedFileOperation::maxThreadFileBufferSize)
streamFormat
Data format (ascii | binary)
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
"nonBlocking" : (MPI_Isend, MPI_Irecv)
virtual autoPtr< OSstream > NewOFstream(const fileName &pathname, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Generate an OSstream that writes a file.
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual fileName::Type type(const fileName &, const bool followLink=true) const
Return the file type: DIRECTORY, FILE or SYMLINK.
virtual fileName getFile(const label) const
Get name of file being watched (using handle)
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:642
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:437
static labelList getGlobalIORanks()
Get list of global IO ranks from FOAM_IORANKS env variable. If set, these correspond to the IO master...
defineTypeNameAndDebug(collatedFileOperation, 0)
List< label > labelList
A List of labels.
Definition: List.H:62
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1185
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
List< instant > instantList
List of instants.
Definition: instantList.H:41
Registry of regIOobjects.
bool equal(scalar val) const noexcept
True if values are equal (includes SMALL for rounding)
Definition: Instant.H:155
const T1 & first() const noexcept
Access the first element.
Definition: Tuple2.H:132
virtual void setTime(const Time &) const
Callback for time change.
const fileName & local() const noexcept
Read access to local path component.
Definition: IOobjectI.H:278
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
fileOperations that performs all file operations on the master processor. Requires the calls to be pa...
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:686
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: POSIX.C:773
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition: UListI.H:293
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is.
Type
Enumerations to handle directory entry types.
Definition: fileName.H:81
static label allocateCommunicator(const label parent, const labelRange &subRanks, const bool withComponents=true)
Allocate new communicator with contiguous sub-ranks on the parent communicator.
Definition: UPstream.C:258
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:361
label comm_
Communicator to use.
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:56
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...