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