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 "IListStream.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 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
87 
90 (
91  const instantList& timeDirs,
92  const instant& t
93 )
94 {
95  // Note:
96  // - times will include constant (with value 0) as first element.
97  // For backwards compatibility make sure to find 0 in preference
98  // to constant.
99  // - list is sorted so could use binary search
100 
101  forAllReverse(timeDirs, i)
102  {
103  if (t.equal(timeDirs[i].value()))
104  {
105  return timeDirs[i].name();
106  }
107  }
109  return word();
110 }
111 
112 
115 (
116  const bool checkGlobal,
117  const bool isFile,
118  const IOobject& io,
119  const dirIndexList& pDirs,
120  const bool search,
121  pathType& searchType,
122  word& procsDir,
123  word& newInstancePath
124 ) const
125 {
126  procsDir.clear();
127  newInstancePath.clear();
128 
129  if (io.instance().isAbsolute())
130  {
131  fileName objPath = io.instance()/io.name();
132 
133  if (isFileOrDir(isFile, objPath))
134  {
135  searchType = fileOperation::ABSOLUTE;
136  return objPath;
137  }
138  else
139  {
140  searchType = fileOperation::NOTFOUND;
141  return fileName();
142  }
143  }
144  else
145  {
146  // 1. Check the writing fileName
147  fileName writePath(objectPath(io, io.headerClassName()));
148 
149  if (isFileOrDir(isFile, writePath))
150  {
151  searchType = fileOperation::WRITEOBJECT;
152  return writePath;
153  }
154 
155  // 2. Check processors/
156  if (io.time().processorCase())
157  {
158  for (const dirIndex& dirIdx : pDirs)
159  {
160  const fileName& pDir = dirIdx.first();
161  fileName objPath =
162  processorsPath(io, io.instance(), pDir)
163  /io.name();
164  if (objPath != writePath && isFileOrDir(isFile, objPath))
165  {
166  searchType = dirIdx.second().first();
167  procsDir = pDir;
168  return objPath;
169  }
170  }
171  }
172  {
173  // 3. Check local
174  fileName localPath = io.objectPath();
175 
176  if
177  (
178  localPath != writePath
179  && isFileOrDir(isFile, localPath)
180  )
181  {
182  searchType = fileOperation::OBJECT;
183  return localPath;
184  }
185  }
186 
187 
188 
189  // Any global checks
190  if
191  (
192  checkGlobal
193  && io.time().processorCase()
194  && (
195  io.instance() == io.time().system()
196  || io.instance() == io.time().constant()
197  )
198  )
199  {
200  fileName parentPath =
201  io.rootPath()/io.time().globalCaseName()
202  /io.instance()/io.db().dbDir()/io.local()/io.name();
203 
204  if (isFileOrDir(isFile, parentPath))
205  {
206  searchType = fileOperation::PARENTOBJECT;
207  return parentPath;
208  }
209  }
210 
211  // Check for approximately same time. E.g. if time = 1e-2 and
212  // directory is 0.01 (due to different time formats)
213  const auto pathFnd = times_.cfind(io.time().path());
214 
215  if (search && pathFnd.good())
216  {
217  newInstancePath = findInstancePath
218  (
219  *pathFnd(),
220  instant(io.instance())
221  );
222 
223  if (newInstancePath.size() && newInstancePath != io.instance())
224  {
225  // 1. Try processors equivalent
226  for (const dirIndex& dirIdx : pDirs)
227  {
228  const fileName& pDir = dirIdx.first();
229 
230  fileName fName
231  (
232  processorsPath(io, newInstancePath, pDir)
233  /io.name()
234  );
235  if (isFileOrDir(isFile, fName))
236  {
237  switch (dirIdx.second().first())
238  {
240  {
241  searchType =
243  }
244  break;
246  {
247  searchType = fileOperation::PROCBASEINSTANCE;
248  }
249  break;
251  {
252  searchType = fileOperation::PROCINSTANCE;
253  }
254  break;
255  default:
256  break;
257  }
258  procsDir = pDir;
259  return fName;
260  }
261  }
262 
263 
264  // 2. Check local
265  fileName fName
266  (
267  io.rootPath()/io.caseName()
268  /newInstancePath/io.db().dbDir()/io.local()/io.name()
269  );
270  if (isFileOrDir(isFile, fName))
271  {
272  searchType = fileOperation::FINDINSTANCE;
273  return fName;
274  }
275  }
276  }
277  }
278 
279  // Nothing found
281  return fileName();
282 }
283 
284 
287 (
288  const IOobject& io,
289  const pathType& searchType,
290  const word& procDir,
291  const word& instancePath
292 ) const
293 {
294  // Replacement for IOobject::objectPath()
295 
296  switch (searchType)
297  {
299  {
300  return io.instance()/io.name();
301  }
302  break;
303 
305  {
306  return io.path()/io.name();
307  }
308  break;
309 
311  {
312  return objectPath(io, io.headerClassName());
313  }
314  break;
315 
317  {
318  // Uncollated type, e.g. processor1
319  const word procName
320  (
322  );
323  return
324  processorsPath
325  (
326  io,
327  io.instance(),
328  (
330  ? procName
331  : procDir
332  )
333  )
334  /io.name();
335  }
336  break;
337 
339  {
340  // Collated, e.g. processors4
341  return
342  processorsPath(io, io.instance(), procDir)
343  /io.name();
344  }
345  break;
346 
348  {
349  // Processors directory locally provided by the fileHandler itself
350  return
351  processorsPath(io, io.instance(), processorsDir(io))
352  /io.name();
353  }
354  break;
355 
357  {
358  return
359  io.rootPath()/io.time().globalCaseName()
360  /io.instance()/io.db().dbDir()/io.local()/io.name();
361  }
362  break;
363 
365  {
366  return
367  io.rootPath()/io.caseName()
368  /instancePath/io.db().dbDir()/io.local()/io.name();
369  }
370  break;
371 
373  {
374  // Uncollated type, e.g. processor1
375  const word procName
376  (
377  "processor"
379  );
380  return
381  processorsPath
382  (
383  io,
384  instancePath,
385  (
387  ? procName
388  : procDir
389  )
390  )
391  /io.name();
392  }
393  break;
394 
396  {
397  // Collated, e.g. processors4
398  return
399  processorsPath(io, instancePath, procDir)
400  /io.name();
401  }
402  break;
403 
405  {
406  // Processors directory locally provided by the fileHandler itself
407  return
408  processorsPath(io, instancePath, processorsDir(io))
409  /io.name();
410  }
411  break;
412 
414  {
415  return fileName();
416  }
417  break;
418 
419  default:
420  {
422  return fileName();
423  }
424  }
425 }
426 
427 
429 (
430  const fileName& filePath,
431  const labelUList& recvProcs,
432  PstreamBuffers& pBufs
433 )
434 {
435  if (recvProcs.empty()) return;
436 
437  IFstream ifs(filePath, IOstreamOption::BINARY);
438 
439  if (!ifs.good())
440  {
441  FatalIOErrorInFunction(filePath)
442  << "Cannot open file " << filePath
443  //<< " using communicator " << pBufs.comm()
444  //<< " ioRanks:" << UPstream::procID(pBufs.comm())
445  << exit(FatalIOError);
446  }
447 
448  if (debug)
449  {
450  Pout<< "masterUncollatedFileOperation::readAndSend :"
451  << " compressed:" << bool(ifs.compression()) << " "
452  << filePath << endl;
453  }
454 
455  if (ifs.compression() == IOstreamOption::COMPRESSED)
456  {
457  // Could use Foam::fileSize, estimate uncompressed size (eg, 2x)
458  // and then string reserve followed by string assign...
459 
460  // Uncompress and read file contents into a character buffer
461  const std::string buf
462  (
463  std::istreambuf_iterator<char>(ifs.stdStream()),
464  std::istreambuf_iterator<char>()
465  );
466 
467  for (const label proci : recvProcs)
468  {
469  UOPstream os(proci, pBufs);
470  os.write(buf.data(), buf.length());
471  }
472 
473  if (debug)
474  {
475  Pout<< "masterUncollatedFileOperation::readStream :"
476  << " From " << filePath << " sent " << buf.size()
477  << " bytes" << endl;
478  }
479  }
480  else
481  {
482  const off_t count(Foam::fileSize(filePath));
483 
484  // Read file contents into a character buffer
485  List<char> buf(static_cast<label>(count));
486  ifs.stdStream().read(buf.data(), count);
487 
488  for (const label proci : recvProcs)
489  {
490  UOPstream os(proci, pBufs);
491  os.write(buf.cdata(), count);
492  }
493 
494  if (debug)
495  {
496  Pout<< "masterUncollatedFileOperation::readStream :"
497  << " From " << filePath << " sent " << buf.size()
498  << " bytes" << endl;
499  }
500  }
501 }
502 
503 
506 (
507  IOobject& io,
508  const label comm,
509  const bool uniform, // on comms master only
510  const fileNameList& filePaths, // on comms master and sub-ranks
511  const boolUList& readOnProcs // on comms master and sub-ranks
512 )
513 {
514  autoPtr<ISstream> isPtr;
515 
516  PstreamBuffers pBufs(comm, UPstream::commsTypes::nonBlocking);
517 
518  if (UPstream::master(comm))
519  {
520  if (uniform)
521  {
522  if (readOnProcs[0])
523  {
524  if (filePaths[0].empty())
525  {
526  FatalIOErrorInFunction(filePaths[0])
527  << "Cannot find file " << io.objectPath()
528  << " fileHandler : comm:" << comm
529  << " ioRanks:" << UPstream::procID(comm)
530  << exit(FatalIOError);
531  }
532 
533  DynamicList<label> recvProcs(UPstream::nProcs(comm));
534  for (const int proci : UPstream::allProcs(comm))
535  {
536  if (readOnProcs[proci])
537  {
538  recvProcs.push_back(proci);
539  }
540  }
541 
542  // Read on master and send to all processors
543  // (including master for simplicity)
544  if (debug)
545  {
546  Pout<< "masterUncollatedFileOperation::readStream :"
547  << " For uniform file " << filePaths[0]
548  << " sending to " << recvProcs
549  << " in comm:" << comm << endl;
550  }
551  readAndSend(filePaths[0], recvProcs, pBufs);
552  }
553  }
554  else
555  {
556  if (readOnProcs[0])
557  {
558  if (filePaths[0].empty())
559  {
560  FatalIOErrorInFunction(filePaths[0])
561  << "Cannot find file " << io.objectPath()
562  << " fileHandler : comm:" << comm
563  << " ioRanks:" << UPstream::procID(comm)
564  << exit(FatalIOError);
565  }
566 
567  // Open master
568  isPtr.reset(new IFstream(filePaths[0]));
569 
570  // Read header
571  if (!io.readHeader(*isPtr))
572  {
573  FatalIOErrorInFunction(*isPtr)
574  << "problem while reading header for object "
575  << io.name()
576  << " fileHandler : comm:" << comm
577  << " ioRanks:" << UPstream::procID(comm)
578  << exit(FatalIOError);
579  }
580  }
581 
582  // Read sub-rank files
583  for (const int proci : UPstream::subProcs(comm))
584  {
585  if (debug)
586  {
587  Pout<< "masterUncollatedFileOperation::readStream :"
588  << " For processor " << proci
589  << " opening " << filePaths[proci] << endl;
590  }
591 
592  const fileName& fPath = filePaths[proci];
593 
594  if (readOnProcs[proci] && !fPath.empty())
595  {
596  // Note: handle compression ourselves since size cannot
597  // be determined without actually uncompressing
598  readAndSend(fPath, labelList(one{}, proci), pBufs);
599  }
600  }
601  }
602  }
603 
604  pBufs.finishedScatters();
605 
606  // isPtr will be valid on master and will be the unbuffered
607  // IFstream. Else the information is in the PstreamBuffers (and
608  // the special case of a uniform file)
609 
610  if (!isPtr)
611  {
612  if (readOnProcs[UPstream::myProcNo(comm)])
613  {
614  // This processor needs to return something
615  List<char> buf(pBufs.recvDataCount(UPstream::masterNo()));
616 
617  if (!buf.empty())
618  {
619  UIPstream is(UPstream::masterNo(), pBufs);
620  is.read(buf.data(), buf.size());
621  }
622 
623  if (debug)
624  {
625  Pout<< "masterUncollatedFileOperation::readStream :"
626  << " Done reading " << buf.size() << " bytes" << endl;
627  }
628 
629  // A local character buffer copy of the Pstream contents.
630  // Construct with same parameters (ASCII, current version)
631  // as the IFstream so that it has the same characteristics.
632 
633  isPtr.reset(new IListStream(std::move(buf)));
634 
635  // With the proper file name
636  isPtr->name() = filePaths[UPstream::myProcNo(comm)];
637 
638  if (!io.readHeader(*isPtr))
639  {
640  FatalIOErrorInFunction(*isPtr)
641  << "problem while reading header for object "
642  << io.name()
643  << " fileHandler : comm:" << comm
644  << " ioRanks:" << UPstream::procID(comm)
645  << exit(FatalIOError);
646  }
647  }
648  else
649  {
650  isPtr.reset(new dummyISstream());
651  }
652  }
653 
654  return isPtr;
655 }
656 
658 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
659 
660 namespace Foam
661 {
662 
663 // Construction helper: self/world/local communicator and IO ranks
665 {
666  // Default is COMM_WORLD (single master)
667  Tuple2<label, labelList> commAndIORanks
668  (
671  );
672 
673  if (UPstream::parRun() && commAndIORanks.second().size() > 1)
674  {
675  // Multiple masters: ranks for my IO range
676  commAndIORanks.first() = UPstream::allocateCommunicator
677  (
679  fileOperation::subRanks(commAndIORanks.second())
680  );
681  }
682 
683  return commAndIORanks;
684 }
685 
686 } // End namespace Foam
687 
688 
689 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
690 
691 void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
692 {
693  verbose = (verbose && Foam::infoDetailLevel > 0);
694 
695  if (verbose)
696  {
697  DetailInfo
698  << "I/O : " << typeName
699  << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
700  << endl;
701  }
702 
704  {
705  if (verbose)
706  {
708  << "Resetting fileModificationChecking to timeStamp" << endl;
709  }
711  }
713  {
714  if (verbose)
715  {
717  << "Resetting fileModificationChecking to inotify"
718  << endl;
719  }
721  }
722 }
723 
724 
727 (
728  bool verbose
729 )
730 :
732  (
734  ),
735  managedComm_(getManagedComm(comm_)) // Possibly locally allocated
736 {
737  init(verbose);
738 }
739 
740 
743 (
744  const Tuple2<label, labelList>& commAndIORanks,
745  const bool distributedRoots,
746  bool verbose
747 )
748 :
749  fileOperation(commAndIORanks, distributedRoots),
750  managedComm_(-1) // Externally managed
751 {
752  init(verbose);
753 }
754 
755 
757 {
758  // From externally -> locally managed
759  managedComm_ = getManagedComm(comm_);
760 }
761 
762 
763 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
764 
767 {
769 }
770 
771 
772 // * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
773 
775 (
776  const fileName& dir,
777  mode_t mode
778 ) const
779 {
780  return masterOp<mode_t>
781  (
782  dir,
783  mkDirOp(mode),
785  comm_
786  );
787 }
788 
789 
791 (
792  const fileName& fName,
793  mode_t mode
794 ) const
795 {
796  return masterOp<mode_t>
797  (
798  fName,
799  chModOp(mode),
801  comm_
802  );
803 }
804 
805 
807 (
808  const fileName& fName,
809  const bool followLink
810 ) const
811 {
812  return masterOp<mode_t>
813  (
814  fName,
815  modeOp(followLink),
817  comm_
818  );
819 }
820 
821 
823 (
824  const fileName& fName,
825  const bool followLink
826 ) const
827 {
828  return fileName::Type
829  (
830  masterOp<label>
831  (
832  fName,
833  typeOp(followLink),
835  comm_
836  )
837  );
838 }
839 
840 
842 (
843  const fileName& fName,
844  const bool checkGzip,
845  const bool followLink
846 ) const
847 {
848  return masterOp<bool>
849  (
850  fName,
851  existsOp(checkGzip, followLink),
853  comm_
854  );
855 }
856 
857 
859 (
860  const fileName& fName,
861  const bool followLink
862 ) const
863 {
864  return masterOp<bool>
865  (
866  fName,
867  isDirOp(followLink),
869  comm_
870  );
871 }
872 
873 
875 (
876  const fileName& fName,
877  const bool checkGzip,
878  const bool followLink
879 ) const
880 {
881  return masterOp<bool>
882  (
883  fName,
884  isFileOp(checkGzip, followLink),
886  comm_
887  );
888 }
889 
890 
892 (
893  const fileName& fName,
894  const bool followLink
895 ) const
896 {
897  return masterOp<off_t>
898  (
899  fName,
900  fileSizeOp(followLink),
902  comm_
903  );
904 }
905 
906 
908 (
909  const fileName& fName,
910  const bool followLink
911 ) const
912 {
913  return masterOp<time_t>
914  (
915  fName,
916  lastModifiedOp(followLink),
919  );
920 }
921 
922 
924 (
925  const fileName& fName,
926  const bool followLink
927 ) const
928 {
929  return masterOp<double>
930  (
931  fName,
932  highResLastModifiedOp(followLink),
935  );
936 }
937 
938 
940 (
941  const fileName& fName,
942  const std::string& ext
943 ) const
944 {
945  return masterOp<bool>
946  (
947  fName,
948  mvBakOp(ext),
950  comm_
951  );
952 }
953 
954 
956 (
957  const fileName& fName
958 ) const
959 {
960  return masterOp<bool>
961  (
962  fName,
963  rmOp(),
965  comm_
966  );
967 }
968 
969 
971 (
972  const fileName& dir,
973  const bool silent,
974  const bool emptyOnly
975 ) const
976 {
977  return masterOp<bool>
978  (
979  dir,
980  rmDirOp(silent, emptyOnly),
982  comm_
983  );
984 }
985 
986 
988 (
989  const fileName& dir,
990  const fileName::Type type,
991  const bool filtergz,
992  const bool followLink
993 ) const
994 {
995  return masterOp<fileNameList>
996  (
997  dir,
998  readDirOp(type, filtergz, followLink),
1000  comm_
1001  );
1002 }
1003 
1004 
1006 (
1007  const fileName& src,
1008  const fileName& dst,
1009  const bool followLink
1010 ) const
1011 {
1012  return masterOp<bool>
1013  (
1014  src,
1015  dst,
1016  cpOp(followLink),
1018  comm_
1019  );
1020 }
1021 
1022 
1024 (
1025  const fileName& src,
1026  const fileName& dst
1027 ) const
1028 {
1029  return masterOp<bool>
1030  (
1031  src,
1032  dst,
1033  lnOp(),
1035  comm_
1036  );
1037 }
1038 
1039 
1041 (
1042  const fileName& src,
1043  const fileName& dst,
1044  const bool followLink
1045 ) const
1046 {
1047  return masterOp<bool>
1048  (
1049  src,
1050  dst,
1051  mvOp(followLink),
1052  Pstream::msgType(),
1053  comm_
1054  );
1055 }
1056 
1057 
1058 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1059 
1061 (
1062  const bool checkGlobal,
1063  const IOobject& io,
1064  const word& typeName,
1065  const bool search
1066 ) const
1067 {
1068  if (debug)
1069  {
1070  Pout<< "masterUncollatedFileOperation::filePath :"
1071  << " objectPath:" << io.objectPath()
1072  << " checkGlobal:" << checkGlobal
1073  << " parRun:" << Pstream::parRun()
1074  << " localmaster:" << Pstream::master(comm_) << endl;
1075  }
1076 
1077  // Now that we have an IOobject path use it to detect & cache
1078  // processor directory naming
1079  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1080 
1081  // Trigger caching of times
1082  if (cacheLevel() > 0)
1083  {
1084  (void)findTimes(io.time().path(), io.time().constant());
1085  }
1086 
1087  // Determine master filePath and scatter
1088 
1089  fileName objPath;
1090  pathType searchType = NOTFOUND;
1091  word procsDir;
1092  word newInstancePath;
1093 
1094  if (Pstream::master(comm_))
1095  {
1096  const bool oldParRun = UPstream::parRun(false);
1097  const int oldCache = fileOperation::cacheLevel(0);
1098 
1099  // All masters search locally. Note that global objects might
1100  // fail (except on master). This gets handled later on (in PARENTOBJECT)
1101  objPath =
1102  filePathInfo
1103  (
1104  checkGlobal,
1105  true,
1106  io,
1107  pDirs,
1108  search,
1109  searchType,
1110  procsDir,
1111  newInstancePath
1112  );
1113 
1114  fileOperation::cacheLevel(oldCache);
1115  UPstream::parRun(oldParRun);
1116 
1117  if (debug)
1118  {
1119  Pout<< "masterUncollatedFileOperation::filePath :"
1120  << " master objPath:" << objPath
1121  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1122  << " procsDir:" << procsDir << " instance:" << newInstancePath
1123  << endl;
1124  }
1125  }
1126 
1127  // Broadcast information about where the master found the object
1128  // Note: use the worldComm to make sure all processors decide
1129  // the same type. Only procsDir is allowed to differ; searchType
1130  // and instance have to be same
1131  if (UPstream::parRun())
1132  {
1133  int masterType(searchType);
1134  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1135  searchType = pathType(masterType);
1136  }
1137 
1138  if
1139  (
1140  checkGlobal
1141  || searchType == fileOperation::PARENTOBJECT
1142  || searchType == fileOperation::PROCBASEOBJECT
1143  || searchType == fileOperation::PROCBASEINSTANCE
1144  || io.local() == "uniform"
1145  )
1146  {
1147  // Distribute master path. This makes sure it is seen as uniform
1148  // and only gets read from the master.
1149  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1150  }
1151  else
1152  {
1153  Pstream::broadcast(procsDir, comm_);
1154 
1155  // Use the master type to determine if additional information is
1156  // needed to construct the local equivalent
1157  switch (searchType)
1158  {
1162  {
1163  // Already handled above
1164  }
1165  break;
1166 
1174  {
1175  // Construct equivalent local path
1176  objPath = localObjectPath
1177  (
1178  io,
1179  searchType,
1180  procsDir,
1181  newInstancePath
1182  );
1183  }
1184  break;
1185 
1186  case fileOperation::OBJECT:
1188  {
1189  // Retest all processors separately since some processors might
1190  // have the file and some not (e.g. lagrangian data)
1191 
1192  objPath = masterOp<fileName>
1193  (
1194  io.objectPath(),
1195  fileOrNullOp(true), // isFile=true
1196  Pstream::msgType(),
1197  comm_
1198  );
1199  }
1200  break;
1201  }
1202  }
1203 
1204  if (debug)
1205  {
1206  Pout<< "masterUncollatedFileOperation::filePath :"
1207  << " Returning from file searching using type "
1208  << fileOperation::pathTypeNames_[searchType] << endl
1209  << " objectPath:" << io.objectPath() << endl
1210  << " filePath :" << objPath << endl << endl;
1211  }
1212  return objPath;
1213 }
1214 
1215 
1217 (
1218  const bool checkGlobal,
1219  const IOobject& io,
1220  const bool search
1221 ) const
1222 {
1223  if (debug)
1224  {
1225  Pout<< "masterUncollatedFileOperation::dirPath :"
1226  << " objectPath:" << io.objectPath()
1227  << " checkGlobal:" << checkGlobal
1228  << " parRun:" << Pstream::parRun()
1229  << " localmaster:" << Pstream::master(comm_) << endl;
1230  }
1231 
1232  // Now that we have an IOobject path use it to detect & cache
1233  // processor directory naming
1234  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1235 
1236  // Trigger caching of times
1237  if (cacheLevel() > 0)
1238  {
1239  (void)findTimes(io.time().path(), io.time().constant());
1240  }
1241 
1242  // Determine master dirPath and broadcast
1243 
1244  fileName objPath;
1245  pathType searchType = NOTFOUND;
1246  word procsDir;
1247  word newInstancePath;
1248 
1249  // Local IO node searches for file
1250  if (Pstream::master(comm_))
1251  {
1252  const bool oldParRun = UPstream::parRun(false);
1253  const int oldCache = fileOperation::cacheLevel(0);
1254 
1255  objPath = filePathInfo
1256  (
1257  checkGlobal,
1258  false,
1259  io,
1260  pDirs,
1261  search,
1262  searchType,
1263  procsDir,
1264  newInstancePath
1265  );
1266 
1267  fileOperation::cacheLevel(oldCache);
1268  UPstream::parRun(oldParRun);
1269 
1270  if (debug)
1271  {
1272  Pout<< "masterUncollatedFileOperation::dirPath :"
1273  << " master objPath:" << objPath
1274  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1275  << " procsDir:" << procsDir << " instance:" << newInstancePath
1276  << endl;
1277  }
1278  }
1279 
1280 
1281  // Broadcast information about where the master found the object
1282  // Note: use the worldComm to make sure all processors decide
1283  // the same type. Only procsDir is allowed to differ; searchType
1284  // and instance have to be same
1285  if (UPstream::parRun())
1286  {
1287  int masterType(searchType);
1288  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1289  searchType = pathType(masterType);
1290  }
1291 
1292 
1293  if
1294  (
1295  checkGlobal
1296  || searchType == fileOperation::PARENTOBJECT
1297  || searchType == fileOperation::PROCBASEOBJECT
1298  || searchType == fileOperation::PROCBASEINSTANCE
1299  || io.local() == "uniform"
1300  )
1301  {
1302  // Distribute master path. This makes sure it is seen as uniform
1303  // and only gets read from the master.
1304  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1305  }
1306  else
1307  {
1308  // Broadcast local processors dir amongst all local nodes
1309  Pstream::broadcast(procsDir, comm_);
1310 
1311  // Use the master type to determine if additional information is
1312  // needed to construct the local equivalent
1313  switch (searchType)
1314  {
1318  {
1319  // Already handled above
1320  }
1321  break;
1322 
1330  {
1331  // Construct equivalent local path
1332  objPath = localObjectPath
1333  (
1334  io,
1335  searchType,
1336  procsDir,
1337  newInstancePath
1338  );
1339  }
1340  break;
1341 
1342  case fileOperation::OBJECT:
1344  {
1345  // Retest all processors separately since some processors might
1346  // have the file and some not (e.g. lagrangian data)
1347 
1348  objPath = masterOp<fileName>
1349  (
1350  io.objectPath(),
1351  fileOrNullOp(false), // isFile=false
1352  Pstream::msgType(),
1353  comm_
1354  );
1355  }
1356  break;
1357  }
1358  }
1359 
1360  if (debug)
1361  {
1362  Pout<< "masterUncollatedFileOperation::dirPath :"
1363  << " Returning from directory searching using type "
1364  << fileOperation::pathTypeNames_[searchType] << endl
1365  << " objectPath:" << io.objectPath() << endl
1366  << " filePath :" << objPath << endl << endl;
1367  }
1368  return objPath;
1369 }
1370 
1371 
1373 (
1374  const dirIndexList& pDirs,
1375  IOobject& io
1376 ) const
1377 {
1378  // Cut-down version of filePathInfo that does not look for
1379  // different instance or parent directory
1380 
1381  const bool isFile = !io.name().empty();
1382 
1383  // Generate output filename for object
1384  const fileName writePath(objectPath(io, word::null));
1385 
1386  // 1. Test writing name for either directory or a (valid) file
1387  if (isFileOrDir(isFile, writePath))
1388  {
1389  return true;
1390  }
1391 
1392  // 2. Check processors/
1393  if (io.time().processorCase())
1394  {
1395  for (const dirIndex& dirIdx : pDirs)
1396  {
1397  const fileName& pDir = dirIdx.first();
1398  fileName procPath =
1399  processorsPath(io, io.instance(), pDir)
1400  /io.name();
1401  if (procPath != writePath && isFileOrDir(isFile, procPath))
1402  {
1403  return true;
1404  }
1405  }
1406  }
1407 
1408  // 3. Check local
1409  fileName localPath = io.objectPath();
1410 
1411  if (localPath != writePath && isFileOrDir(isFile, localPath))
1412  {
1413  return true;
1414  }
1416  return false;
1417 }
1418 
1419 
1422 (
1423  const IOobject& startIO,
1424  const scalar startValue,
1425  const word& stopInstance
1426 ) const
1427 {
1428  if (debug)
1429  {
1430  Pout<< "masterUncollatedFileOperation::findInstance :"
1431  << " Starting searching for name:" << startIO.name()
1432  << " local:" << startIO.local()
1433  << " from instance:" << startIO.instance()
1434  << endl;
1435  }
1436 
1437  const Time& time = startIO.time();
1438  IOobject io(startIO);
1439 
1440  // Note: - if name is empty, just check the directory itself
1441  // - check both for isFile and headerOk since the latter does a
1442  // filePath so searches for the file.
1443  // - check for an object with local file scope (so no looking up in
1444  // parent directory in case of parallel)
1445 
1446 
1447  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1448 
1449  word foundInstance;
1450 
1451  // if (Pstream::master(comm_))
1453  {
1454  const bool oldParRun = UPstream::parRun(false);
1455  const int oldCache = fileOperation::cacheLevel(0);
1456 
1457  if (exists(pDirs, io))
1458  {
1459  foundInstance = io.instance();
1460  }
1461  fileOperation::cacheLevel(oldCache);
1462  UPstream::parRun(oldParRun);
1463  }
1464 
1465 
1466  // Do parallel early exit to avoid calling time.times()
1467  Pstream::broadcast(foundInstance, UPstream::worldComm);
1468 
1469  if (!foundInstance.empty())
1470  {
1471  io.instance() = foundInstance;
1472  if (debug)
1473  {
1474  Pout<< "masterUncollatedFileOperation::findInstance :"
1475  << " for name:" << io.name() << " local:" << io.local()
1476  << " found starting instance:" << io.instance() << endl;
1477  }
1478  return io;
1479  }
1480 
1481 
1482  // Handling failures afterwards
1483  const bool exitIfMissing = startIO.isReadRequired();
1484 
1485  enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1486  int failed(0);
1487 
1488  instantList ts = time.times();
1489 
1490  // if (Pstream::master(comm_))
1492  {
1493  const bool oldParRun = UPstream::parRun(false);
1494  const int oldCache = fileOperation::cacheLevel(0);
1495 
1496  label instIndex = ts.size()-1;
1497 
1498  // Backward search for first time that is <= startValue
1499  for (; instIndex >= 0; --instIndex)
1500  {
1501  if (ts[instIndex].value() <= startValue)
1502  {
1503  break;
1504  }
1505  }
1506 
1507  // Continue (forward) searching from here
1508  for (; instIndex >= 0; --instIndex)
1509  {
1510  // Shortcut: if actual directory is the timeName we've
1511  // already tested it
1512  if (ts[instIndex].name() == time.timeName())
1513  {
1514  continue;
1515  }
1516 
1517  io.instance() = ts[instIndex].name();
1518  if (exists(pDirs, io))
1519  {
1520  foundInstance = io.instance();
1521  if (debug)
1522  {
1523  Pout<< "masterUncollatedFileOperation::findInstance :"
1524  << " for name:" << io.name() << " local:" << io.local()
1525  << " found at:" << io.instance()
1526  << endl;
1527  }
1528  break;
1529  }
1530 
1531  // Check if hit minimum instance
1532  if (io.instance() == stopInstance)
1533  {
1534  if (debug)
1535  {
1536  Pout<< "masterUncollatedFileOperation::findInstance :"
1537  << " name:" << io.name()
1538  << " local:" << io.local()
1539  << " at stop-instance:" << io.instance() << endl;
1540  }
1541 
1542  if (exitIfMissing)
1543  {
1544  failed = failureCodes::FAILED_STOPINST;
1545  }
1546  else
1547  {
1548  foundInstance = io.instance();
1549  }
1550  break;
1551  }
1552  }
1553 
1554 
1555  // times() usually already includes the constant() so would
1556  // have been checked above. However, re-test under these conditions:
1557  // - times() is empty. Sometimes this can happen (e.g. decomposePar
1558  // with collated)
1559  // - times()[0] is not constant
1560  // - Times is empty.
1561  // Sometimes this can happen (eg, decomposePar with collated)
1562  // - Times[0] is not constant
1563  // - The startValue is negative (eg, kivaTest).
1564  // This plays havoc with the reverse search, causing it to miss
1565  // 'constant'
1566 
1567  if
1568  (
1569  !failed && foundInstance.empty()
1570  && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1571  )
1572  {
1573  // Note. This needs to be a hard-coded "constant" (not constant
1574  // function of Time), because the latter points to
1575  // the case constant directory in parallel cases.
1576  // However, parRun is disabled so they are actually the same.
1577 
1578  io.instance() = time.constant();
1579 
1580  if (exists(pDirs, io))
1581  {
1582  if (debug)
1583  {
1584  Pout<< "masterUncollatedFileOperation::findInstance :"
1585  << " name:" << io.name()
1586  << " local:" << io.local()
1587  << " at:" << io.instance() << endl;
1588  }
1589  foundInstance = io.instance();
1590  }
1591  }
1592 
1593  if (!failed && foundInstance.empty())
1594  {
1595  if (exitIfMissing)
1596  {
1597  failed = failureCodes::FAILED_CONSTINST;
1598  }
1599  else
1600  {
1601  foundInstance = time.constant();
1602  }
1603  }
1604 
1605  fileOperation::cacheLevel(oldCache);
1606  UPstream::parRun(oldParRun); // Restore parallel state
1607  }
1608 
1609  Pstream::broadcast(foundInstance, UPstream::worldComm);
1610 
1611  io.instance() = foundInstance;
1612 
1613 
1614  // Handle failures
1615  // ~~~~~~~~~~~~~~~
1616  if (failed)
1617  {
1618  FatalErrorInFunction << "Cannot find";
1619 
1620  if (!io.name().empty())
1621  {
1622  FatalError
1623  << " file \"" << io.name() << "\" in";
1624  }
1625 
1626  FatalError
1627  << " directory "
1628  << io.local() << " in times "
1629  << startIO.instance() << " down to ";
1630 
1631  if (failed == failureCodes::FAILED_STOPINST)
1632  {
1633  FatalError << stopInstance;
1634  }
1635  else
1636  {
1637  FatalError << "constant";
1638  }
1640  }
1641 
1642  if (debug)
1643  {
1644  Pout<< "masterUncollatedFileOperation::findInstance :"
1645  << " name:" << io.name() << " local:" << io.local()
1646  << " returning instance:" << io.instance() << endl;
1647  }
1648  return io;
1649 }
1650 
1651 
1654 (
1655  const objectRegistry& db,
1656  const fileName& instance,
1657  const fileName& local,
1658  word& newInstance
1659 ) const
1660 {
1661  if (debug)
1662  {
1663  Pout<< "masterUncollatedFileOperation::readObjects :"
1664  << " db:" << db.objectPath()
1665  << " local:" << local << " instance:" << instance << endl;
1666  }
1667 
1668  fileNameList objectNames;
1669  newInstance.clear();
1670 
1671  // Note: readObjects uses WORLD to make sure order of objects is the
1672  // same everywhere
1673 
1675  {
1676  // Avoid fileOperation::readObjects from triggering parallel ops
1677  // (through call to filePath which triggers parallel )
1678  const bool oldParRun = UPstream::parRun(false);
1679  const int oldCache = fileOperation::cacheLevel(0);
1680 
1681  //- Use non-time searching version
1682  objectNames = fileOperation::readObjects
1683  (
1684  db,
1685  instance,
1686  local,
1687  newInstance
1688  );
1689 
1690  if (newInstance.empty())
1691  {
1692  // Find similar time
1693 
1694  // Copy of Time::findInstancePath. We want to avoid the
1695  // parallel call to findTimes. Alternative is to have
1696  // version of findInstancePath that takes instantList ...
1697  const instantList timeDirs
1698  (
1700  (
1701  db.time().path(),
1702  db.time().constant()
1703  )
1704  );
1705 
1706  const instant t(instance);
1707  forAllReverse(timeDirs, i)
1708  {
1709  if (t.equal(timeDirs[i].value()))
1710  {
1711  objectNames = fileOperation::readObjects
1712  (
1713  db,
1714  timeDirs[i].name(), // newly found time
1715  local,
1716  newInstance
1717  );
1718  break;
1719  }
1720  }
1721  }
1722 
1723  fileOperation::cacheLevel(oldCache);
1724  UPstream::parRun(oldParRun); // Restore parallel state
1725  }
1726 
1727  Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1728 
1729  if (debug)
1730  {
1731  Pout<< "masterUncollatedFileOperation::readObjects :"
1732  << " newInstance:" << newInstance
1733  << " objectNames:" << objectNames << endl;
1734  }
1735 
1736  return objectNames;
1737 }
1738 
1739 
1741 (
1742  IOobject& io,
1743  const fileName& fName,
1744  const word& typeName
1745 ) const
1746 {
1747  bool ok = false;
1748 
1749  if (debug)
1750  {
1751  Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1752  << " objectPath:" << io.objectPath() << endl
1753  << " filePath :" << fName << endl;
1754  }
1755 
1756  // We assume if filePath is the same
1757  // - headerClassName
1758  // - note
1759  // are also the same, independent of where the file came from.
1760 
1761  // Get filePaths on world master
1763  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
1765 
1766  bool uniform
1767  (
1769  && fileOperation::uniformFile(filePaths)
1770  );
1771 
1773 
1774  if (uniform)
1775  {
1777  {
1778  if (!fName.empty())
1779  {
1780  IFstream is(fName);
1781 
1782  if (is.good())
1783  {
1784  // Regular header or from decomposed data
1786  }
1787  }
1788  }
1789 
1791  (
1793  ok,
1794  io.headerClassName(),
1795  io.note()
1796  );
1797  }
1798  else
1799  {
1801  {
1802  // Assume if different nprocs the communicators are also
1803  // different. Re-gather file paths on local master
1804  filePaths.resize(UPstream::nProcs(comm_));
1805  filePaths[UPstream::myProcNo(comm_)] = fName;
1806  Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
1807  }
1808 
1809  // Intermediate storage arrays (master only)
1810  boolList result;
1811  wordList headerClassName;
1812  stringList note;
1813 
1814  if (Pstream::master(comm_))
1815  {
1816  const label np = Pstream::nProcs(comm_);
1817 
1818  result.resize(np, false);
1819  headerClassName.resize(np);
1820  note.resize(np);
1821 
1822  forAll(filePaths, proci)
1823  {
1824  if (!filePaths[proci].empty())
1825  {
1826  if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1827  {
1828  result[proci] = result[proci-1];
1829  headerClassName[proci] = headerClassName[proci-1];
1830  note[proci] = note[proci-1];
1831  }
1832  else
1833  {
1834  IFstream is(filePaths[proci]);
1835 
1836  if (is.good())
1837  {
1838  result[proci] =
1840  headerClassName[proci] = io.headerClassName();
1841  note[proci] = io.note();
1842  }
1843  }
1844  }
1845  }
1846  }
1847 
1848  // Is a more efficient scatter possible?
1849  PstreamBuffers pBufs(comm_, UPstream::commsTypes::nonBlocking);
1850 
1851  if (Pstream::master(comm_))
1852  {
1853  ok = result[0];
1854  io.headerClassName() = headerClassName[0];
1855  io.note() = note[0];
1856 
1857  // Scatter to each proc
1858  for (const int proci : pBufs.subProcs())
1859  {
1860  UOPstream os(proci, pBufs);
1861  os << result[proci] << headerClassName[proci] << note[proci];
1862  }
1863  }
1864 
1865  pBufs.finishedScatters();
1866 
1867  if (!Pstream::master(comm_))
1868  {
1869  UIPstream is(Pstream::masterNo(), pBufs);
1870  is >> ok >> io.headerClassName() >> io.note();
1871  }
1872  }
1873 
1874  if (debug)
1875  {
1876  Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1877  << " class:" << io.headerClassName()
1878  << " for file:" << fName << endl;;
1879  }
1880  return ok;
1882 
1883 
1886 (
1887  regIOobject& io,
1888  const fileName& fName,
1889  const word& typeName,
1890  const bool readOnProc
1891 ) const
1892 {
1893  if (debug)
1894  {
1895  Pout<< "masterUncollatedFileOperation::readStream :"
1896  << " object : " << io.name()
1897  << " global : " << io.global()
1898  << " globalObject : " << io.globalObject()
1899  << " fName : " << fName << " readOnProc:" << readOnProc << endl;
1900  }
1901 
1902 
1903  autoPtr<ISstream> isPtr;
1904  bool isCollated = false;
1905  IOobject headerIO(io);
1906 
1907  // Detect collated format. This could be done on the local communicator
1908  // but we do it on the master node only for now.
1910  {
1911  if (!fName.empty())
1912  {
1913  // This can happen in lagrangian field reading some processors
1914  // have no file to read from. This will only happen when using
1915  // normal writing since then the fName for the valid processors is
1916  // processorDDD/<instance>/.. . In case of collocated writing
1917  // the fName is already rewritten to processorsNN/.
1918 
1919  isPtr.reset(new IFstream(fName));
1920 
1921  if (isPtr->good())
1922  {
1923  // Read header data (on copy)
1924  headerIO.readHeader(*isPtr);
1925 
1926  isCollated = decomposedBlockData::isCollatedType(headerIO);
1927 
1928  if (!isCollated && !Pstream::parRun())
1929  {
1930  // Short circuit: non-collated format. No parallel bits.
1931  // Copy header and return.
1932  if (debug)
1933  {
1934  Pout<< "masterUncollatedFileOperation::readStream :"
1935  << " For object : " << io.name()
1936  << " doing straight IFstream input from "
1937  << fName << endl;
1938  }
1939  io = headerIO;
1940  return isPtr;
1941  }
1942  }
1943 
1944  if (!isCollated)
1945  {
1946  // Close file. Reopened below.
1947  isPtr.clear();
1948  }
1949  }
1950  }
1951 
1953 
1954  if (isCollated)
1955  {
1956  if (debug)
1957  {
1958  Pout<< "masterUncollatedFileOperation::readStream :"
1959  << " For object : " << io.name()
1960  << " starting collating input from " << fName << endl;
1961  }
1962 
1963 
1964  // Analyse the file path (on (co)master) to see the processors type
1965  // Note: this should really be part of filePath() which should return
1966  // both file and index in file.
1967 
1968  fileName path, procDir, local;
1969  procRangeType group;
1970  label nProcs;
1971  splitProcessorPath(fName, path, procDir, local, group, nProcs);
1972 
1973 
1974  if (!UPstream::parRun())
1975  {
1976  // Analyse the objectpath to find out the processor we're trying
1977  // to access
1978  label proci = detectProcessorPath(io.objectPath());
1979 
1980  if (proci == -1)
1981  {
1982  FatalIOErrorInFunction(*isPtr)
1983  << "Could not detect processor number"
1984  << " from objectPath:" << io.objectPath()
1985  << " fileHandler : comm:" << comm_
1986  << " ioRanks:" << flatOutput(ioRanks_)
1987  << exit(FatalIOError);
1988  }
1989 
1990  // The local rank (offset)
1991  if (!group.empty())
1992  {
1993  proci = proci - group.start();
1994  }
1995 
1996  if (debug)
1997  {
1998  Pout<< "masterUncollatedFileOperation::readStream :"
1999  << " For object : " << io.name()
2000  << " starting input from block " << proci
2001  << " of " << isPtr->name() << endl;
2002  }
2003 
2004  return decomposedBlockData::readBlock(proci, *isPtr, io);
2005  }
2006  else
2007  {
2008  // Are we reading from single-master file ('processors256') or
2009  // from multi-master files ('processors256_0-9')
2010  label readComm = -1;
2011  if (!group.empty())
2012  {
2013  readComm = comm_;
2014  if (UPstream::master(comm_) && !isPtr && !fName.empty())
2015  {
2016  // In multi-master mode also open the file on the other
2017  // masters
2018  isPtr.reset(new IFstream(fName));
2019 
2020  if (isPtr->good())
2021  {
2022  // Read header data (on copy)
2023  IOobject headerIO(io);
2024  headerIO.readHeader(*isPtr);
2025  }
2026  }
2027  }
2028  else
2029  {
2030  // Single master so read on world
2031  readComm = UPstream::worldComm;
2032  }
2033 
2034  // Get size of file to determine communications type
2035  bool bigSize = false;
2036 
2038  {
2039  // TBD: handle multiple masters?
2040  bigSize =
2041  (
2042  off_t(Foam::fileSize(fName))
2043  > off_t(maxMasterFileBufferSize)
2044  );
2045  }
2046  // Reduce (not broadcast)
2047  // - if we have multiple master files (FUTURE)
2049 
2050  const UPstream::commsTypes myCommsType
2051  (
2052  bigSize
2055  );
2056 
2057  // Read my data
2059  (
2060  readComm,
2061  fName,
2062  isPtr,
2063  io,
2064  myCommsType
2065  );
2066  }
2067  }
2068  else
2069  {
2070  if (debug)
2071  {
2072  Pout<< "masterUncollatedFileOperation::readStream :"
2073  << " For object : " << io.name()
2074  << " starting separated input from " << fName << endl;
2075  }
2076 
2077  if (io.global() || io.globalObject())
2078  {
2079  // Use worldComm. Note: should not really need to gather filePaths
2080  // since we enforce sending from master anyway ...
2082  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
2084  (
2085  filePaths,
2088  );
2089 
2090  boolList readOnProcs
2091  (
2092  UPstream::listGatherValues<bool>
2093  (
2094  readOnProc,
2096  )
2097  );
2098  // NB: local proc validity information required on sub-ranks too!
2099  readOnProcs.resize(UPstream::nProcs(UPstream::worldComm));
2100  readOnProcs[UPstream::myProcNo(UPstream::worldComm)] = readOnProc;
2101 
2102  // Uniform in local comm
2103  return read(io, UPstream::worldComm, true, filePaths, readOnProcs);
2104  }
2105  else
2106  {
2107  // Use local communicator
2108  fileNameList filePaths(UPstream::nProcs(comm_));
2109  filePaths[UPstream::myProcNo(comm_)] = fName;
2111  (
2112  filePaths,
2114  comm_
2115  );
2116 
2117  boolList readOnProcs
2118  (
2119  UPstream::listGatherValues<bool>
2120  (
2121  readOnProc,
2122  comm_
2123  )
2124  );
2125  // NB: local proc validity information required on sub-ranks too!
2126  readOnProcs.resize(UPstream::nProcs(comm_));
2127  readOnProcs[UPstream::myProcNo(comm_)] = readOnProc;
2128 
2129  // Uniform in local comm
2130  const bool uniform = fileOperation::uniformFile(filePaths);
2131 
2132  return read(io, comm_, uniform, filePaths, readOnProcs);
2133  }
2134  }
2135 }
2136 
2137 
2139 (
2140  regIOobject& io,
2141  const bool masterOnly,
2143  const word& typeName
2144 ) const
2145 {
2146  bool ok = true;
2147 
2148  if (io.global() || io.globalObject())
2149  {
2150  if (debug)
2151  {
2152  Pout<< "masterUncollatedFileOperation::read :"
2153  << " Reading global object " << io.name()
2154  << " worldComm:" << UPstream::worldComm
2155  << " Pstream::myProcNo:"
2157  << " amMaster:" << Pstream::master(UPstream::worldComm)
2158  << endl;
2159  }
2160 
2161  bool ok = false;
2163  {
2164  // Do master-only reading always.
2165  const bool oldParRun = UPstream::parRun(false);
2166  const int oldCache = fileOperation::cacheLevel(0);
2167 
2168  auto& is = io.readStream(typeName);
2169  ok = io.readData(is);
2170  io.close();
2171 
2172  fileOperation::cacheLevel(oldCache);
2173  UPstream::parRun(oldParRun); // Restore parallel state
2174  }
2175 
2176  // Broadcast regIOobjects content
2177  if (Pstream::parRun())
2178  {
2180  (
2182  ok,
2183  io.headerClassName(),
2184  io.note()
2185  );
2186 
2188  {
2189  OPBstream toAll
2190  (
2193  format
2194  );
2195  bool okWrite = io.writeData(toAll);
2196  ok = ok && okWrite;
2197  }
2198  else
2199  {
2200  IPBstream fromMaster
2201  (
2204  format
2205  );
2206  ok = io.readData(fromMaster);
2207  }
2208  }
2209  }
2210  else
2211  {
2212  if (debug)
2213  {
2214  Pout<< "masterUncollatedFileOperation::read :"
2215  << " Reading local object " << io.name() << endl;
2216  }
2217 
2218  ok = io.readData(io.readStream(typeName));
2219  io.close();
2220  }
2221 
2222  if (debug)
2223  {
2224  Pout<< "masterUncollatedFileOperation::read :"
2225  << " Read object:" << io.name()
2226  << " isGlobal:" << (io.global() || io.globalObject())
2227  << " status:" << ok << endl;
2228  }
2229 
2230  return ok;
2231 }
2232 
2233 
2235 (
2236  const regIOobject& io,
2237  IOstreamOption streamOpt,
2238  const bool writeOnProc
2239 ) const
2240 {
2241  fileName pathName(io.objectPath());
2242 
2243  if (debug)
2244  {
2245  Pout<< "masterUncollatedFileOperation::writeObject :"
2246  << " io:" << pathName << " writeOnProc:" << writeOnProc << endl;
2247  }
2248 
2249  // Make sure to pick up any new times
2250  setTime(io.time());
2251 
2252  // Update meta-data for current state
2253  const_cast<regIOobject&>(io).updateMetaData();
2254 
2255  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, writeOnProc));
2256  OSstream& os = *osPtr;
2257 
2258  // If any of these fail, return (leave error handling to Ostream class)
2259 
2260  const bool ok =
2261  (
2262  os.good()
2263  && io.writeHeader(os)
2264  && io.writeData(os)
2265  );
2266 
2267  if (ok)
2268  {
2270  }
2271 
2272  return ok;
2273 }
2274 
2275 
2277 (
2278  const fileName& directory,
2279  const word& constantName
2280 ) const
2281 {
2282  const auto iter = times_.cfind(directory);
2283  if (iter.good())
2284  {
2285  if (debug)
2286  {
2287  Pout<< "masterUncollatedFileOperation::findTimes :"
2288  << " Found " << iter.val()->size() << " cached times" << nl
2289  << " for directory:" << directory << endl;
2290  }
2291  return *(iter.val());
2292  }
2293  else
2294  {
2295  instantList times;
2297  {
2298  // Do master-only reading always.
2299  const bool oldParRun = UPstream::parRun(false);
2300  const int oldCache = fileOperation::cacheLevel(0);
2301 
2302  times = fileOperation::findTimes(directory, constantName);
2303 
2304  fileOperation::cacheLevel(oldCache);
2305  UPstream::parRun(oldParRun); // Restore parallel state
2306  }
2307 
2309 
2310  if (debug)
2311  {
2312  Pout<< "masterUncollatedFileOperation::findTimes :"
2313  << " Found times:" << flatOutput(times) << nl
2314  << " for directory:" << directory << endl;
2315  }
2316 
2317  // Caching
2318  // - cache values even if no times were found since it might
2319  // indicate a directory that is being filled later on ...
2320  if (cacheLevel() > 0)
2321  {
2322  auto* tPtr = new DynamicList<instant>(std::move(times));
2323  times_.set(directory, tPtr);
2324 
2325  return *tPtr;
2326  }
2327 
2328  // Times found (not cached)
2329  return times;
2330  }
2331 }
2332 
2333 
2335 (
2336  const Time& tm
2337 ) const
2338 {
2339  if (tm.subCycling())
2340  {
2341  return;
2342  }
2343 
2344  // Mutable access to instant list for modification and sorting
2345  // - cannot use auto type deduction here
2346 
2347  auto iter = times_.find(tm.path());
2348 
2349  if (iter.good())
2350  {
2351  DynamicList<instant>& times = *(iter.val());
2352 
2353  const instant timeNow(tm.value(), tm.timeName());
2354 
2355  // The start index for checking and sorting (excluding "constant")
2356  const label startIdx =
2357  (
2358  (times.empty() || times[0].name() != tm.constant())
2359  ? 0
2360  : 1
2361  );
2362 
2363  // This routine always results in a sorted list of times, so first
2364  // check if the new time is greater than the latest existing time.
2365  // Can then simply append without extra searching or sorting
2366 
2367  if (times.size() <= startIdx || times.last() < timeNow)
2368  {
2369  times.append(timeNow);
2370  }
2371  else if
2372  (
2374  (
2375  SubList<instant>(times, times.size()-startIdx, startIdx),
2376  timeNow
2377  ) < 0
2378  )
2379  {
2380  if (debug)
2381  {
2382  Pout<< "masterUncollatedFileOperation::setTime :"
2383  << " Caching time " << tm.timeName()
2384  << " for case:" << tm.path() << endl;
2385  }
2386 
2387  times.append(timeNow);
2388 
2389  SubList<instant> realTimes
2390  (
2391  times, times.size()-startIdx, startIdx
2392  );
2393  Foam::stableSort(realTimes);
2394  }
2395  }
2396 
2399 
2400 
2403 (
2404  const fileName& filePath
2405 ) const
2406 {
2407  autoPtr<ISstream> isPtr;
2408 
2409  if (Pstream::parRun())
2410  {
2411  // Insert logic of filePath. We assume that if a file is absolute
2412  // on the master it is absolute also on the sub-ranks etc.
2413 
2414  fileNameList filePaths(Pstream::nProcs(comm_));
2415  filePaths[Pstream::myProcNo(comm_)] = filePath;
2416  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2417 
2419 
2420  if (Pstream::master(comm_))
2421  {
2422  // Same filename on the IO node -> same file
2423  const bool uniform = fileOperation::uniformFile(filePaths);
2424 
2425  if (uniform)
2426  {
2427  if (debug)
2428  {
2429  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2430  << " Opening global file " << filePath << endl;
2431  }
2432 
2433  readAndSend
2434  (
2435  filePath,
2436  identity(Pstream::nProcs(comm_)-1, 1),
2437  pBufs
2438  );
2439  }
2440  else
2441  {
2442  for (const int proci : Pstream::subProcs(comm_))
2443  {
2444  if (debug)
2445  {
2446  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2447  << " Opening local file " << filePath
2448  << " for rank " << proci << endl;
2449  }
2450 
2451  readAndSend
2452  (
2453  filePaths[proci],
2454  labelList(one{}, proci),
2455  pBufs
2456  );
2457  }
2458  }
2459  }
2460 
2461 
2462  pBufs.finishedSends();
2463 
2464  if (Pstream::master(comm_))
2465  {
2466  // Read myself
2467  isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2468  }
2469  else
2470  {
2471  if (debug)
2472  {
2473  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2474  << " Reading " << filePath
2475  << " from processor " << Pstream::masterNo() << endl;
2476  }
2477 
2479 
2480  if (!buf.empty())
2481  {
2482  UIPstream is(Pstream::masterNo(), pBufs);
2483  is.read(buf.data(), buf.size());
2484  }
2485 
2486  if (debug)
2487  {
2488  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2489  << " Done reading " << buf.size() << " bytes" << endl;
2490  }
2491 
2492  // A local character buffer copy of the Pstream contents.
2493  // Construct with same parameters (ASCII, current version)
2494  // as the IFstream so that it has the same characteristics.
2495 
2496  isPtr.reset(new IListStream(std::move(buf)));
2497 
2498  // With the proper file name
2499  isPtr->name() = filePath;
2500  }
2501  }
2502  else
2503  {
2504  // Read myself
2505  isPtr.reset(new IFstream(filePath));
2506  }
2507 
2508  return isPtr;
2510 
2511 
2514 (
2515  const fileName& pathName,
2516  IOstreamOption streamOpt,
2517  const bool writeOnProc
2518 ) const
2519 {
2520  return autoPtr<OSstream>
2521  (
2522  new masterOFstream
2523  (
2524  comm_,
2525  pathName,
2526  streamOpt,
2528  writeOnProc
2529  )
2530  );
2532 
2533 
2536 (
2538  const fileName& pathName,
2539  IOstreamOption streamOpt,
2540  const bool writeOnProc
2541 ) const
2542 {
2543  return autoPtr<OSstream>
2544  (
2545  new masterOFstream
2546  (
2547  atomic,
2548  comm_,
2549  pathName,
2550  streamOpt,
2552  writeOnProc
2553  )
2554  );
2555 }
2556 
2557 
2559 {
2561  times_.clear();
2562 }
2563 
2564 
2566 {
2567  if (debug)
2568  {
2569  Pout<< "masterUncollatedFileOperation::sync :"
2570  << " syncing information across processors" << endl;
2571  }
2572 
2574 
2575 
2576  wordList timeNames;
2577  List<DynamicList<instant>> instants;
2578 
2580  {
2581  timeNames.resize(times_.size());
2582  instants.resize(times_.size());
2583 
2584  // Flatten into two lists to preserve key/val pairing
2585  label i = 0;
2586  forAllConstIters(times_, iter)
2587  {
2588  timeNames[i] = iter.key();
2589  instants[i] = std::move(*(iter.val()));
2590  ++i;
2591  }
2592  }
2593 
2594  Pstream::broadcasts(UPstream::worldComm, timeNames, instants);
2595 
2596  times_.clear();
2597  forAll(timeNames, i)
2598  {
2599  fileName dir(timeNames[i]);
2600  auto ptr = autoPtr<DynamicList<instant>>::New(std::move(instants[i]));
2601 
2603  {
2604  // Replace processor0 ending with processorDDD
2605  fileName path;
2606  fileName pDir;
2607  fileName local;
2608  procRangeType group;
2609  label numProcs;
2610  const label proci = splitProcessorPath
2611  (
2612  dir,
2613  path,
2614  pDir,
2615  local,
2616  group,
2617  numProcs
2618  );
2619 
2620  //Pout<< "**sync : From dir : " << dir << nl
2621  // << " path : " << path << nl
2622  // << " pDir : " << pDir << nl
2623  // << " local: " << local << nl
2624  // << " proci: " << proci << nl
2625  // << endl;
2626 
2627  const label myProci = Pstream::myProcNo(UPstream::worldComm);
2628 
2629  if (proci != -1 && proci != myProci)
2630  {
2631  dir = path/"processor" + Foam::name(myProci);
2632  }
2633  }
2634 
2635  times_.insert(dir, ptr);
2636  }
2637 }
2638 
2639 
2641 (
2642  const fileName& fName
2643 ) const
2644 {
2645  label watchFd = -1;
2647  {
2648  watchFd = monitor().addWatch(fName);
2649  }
2650 
2652  return watchFd;
2653 }
2654 
2655 
2657 (
2658  const label watchIndex
2659 ) const
2660 {
2661  bool ok = false;
2663  {
2664  ok = monitor().removeWatch(watchIndex);
2665  }
2666 
2668  return ok;
2669 }
2670 
2671 
2673 (
2674  const labelList& watchIndices,
2675  const fileName& fName
2676 ) const
2677 {
2678  label index = -1;
2679 
2681  {
2682  forAll(watchIndices, i)
2683  {
2684  if (monitor().getFile(watchIndices[i]) == fName)
2685  {
2686  index = i;
2687  break;
2688  }
2689  }
2690  }
2691 
2693  return index;
2694 }
2695 
2696 
2698 (
2699  regIOobject& rio,
2700  const fileNameList& files
2701 ) const
2702 {
2703  const labelList& watchIndices = rio.watchIndices();
2704 
2705  DynamicList<label> newWatchIndices;
2706  labelHashSet removedWatches(watchIndices);
2707 
2708  for (const fileName& f : files)
2709  {
2710  const label index = findWatch(watchIndices, f);
2711 
2712  if (index == -1)
2713  {
2714  newWatchIndices.append(addWatch(f));
2715  }
2716  else
2717  {
2718  // Existing watch
2719  newWatchIndices.append(watchIndices[index]);
2720  removedWatches.erase(index);
2721  }
2722  }
2723 
2724  // Remove any unused watches
2725  for (const label index : removedWatches)
2726  {
2727  removeWatch(watchIndices[index]);
2728  }
2729 
2730  rio.watchIndices() = newWatchIndices;
2731 }
2732 
2733 
2735 (
2736  const label watchIndex
2737 ) const
2738 {
2739  fileName fName;
2741  {
2742  fName = monitor().getFile(watchIndex);
2743  }
2744 
2746  return fName;
2747 }
2748 
2749 
2751 (
2752  const bool masterOnly,
2753  const bool syncPar
2754 ) const
2755 {
2757  {
2758  monitor().updateStates(true, false);
2759  }
2761 
2762 
2765 (
2766  const label watchFd
2767 ) const
2768 {
2769  unsigned int state = fileMonitor::UNMODIFIED;
2771  {
2772  state = monitor().getState(watchFd);
2773  }
2774 
2776  return fileMonitor::fileState(state);
2777 }
2778 
2779 
2781 (
2782  const label watchFd
2783 ) const
2784 {
2786  {
2787  monitor().setUnmodified(watchFd);
2788  }
2789 }
2790 
2791 
2792 // ************************************************************************* //
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_
List< instant > instantList
List of instants.
Definition: instantList.H:41
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.
Definition: Time.H:454
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.
A class for handling file names.
Definition: fileName.H:71
virtual const fileName & name() const
The name of the stream.
Definition: IOstream.C:33
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:132
commsTypes
Communications types.
Definition: UPstream.H:74
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:54
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:500
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:162
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
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:71
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition: UPstream.H:1131
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:49
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:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
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:362
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:1184
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:688
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:1029
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:411
List< string > stringList
List of string.
Definition: stringList.H:32
UList< bool > boolUList
A UList of bools.
Definition: UList.H:76
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:251
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 processes in communicator.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
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:293
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)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
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:1020
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 INVALID.
Definition: exprTraits.C:52
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)
Definition: labelList.C:31
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:1014
void finishedSends(const bool wait=true)
Mark sends as done.
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
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
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:570
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.
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition: IOobject.C:431
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
An ISstream with internal List storage. Always UNCOMPRESSED.
Definition: IListStream.H:144
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:195
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 time name of given scalar time formatted with the given precision.
Definition: Time.C:770
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:89
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:326
Input from file stream, using an ISstream.
Definition: IFstream.H:49
labelList f(nPoints)
static Tuple2< label, labelList > getCommPattern()
Buffers for inter-processor communications streams (UOPstream, UIPstream).
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:233
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 processes in communicator.
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:473
word format(conversionProperties.get< word >("format"))
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:58
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:142
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:1085
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
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:1037
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:65
"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.
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:640
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:430
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:1140
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.
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:245
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:666
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
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.
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:80
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
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 ...