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-2025 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::newCommunicator
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  // Reduce as int64_t instead of off_t to avoid missing
871  // pTraits<long int> (or other ambiguities) on Mingw and Linux i586
872 
873  return off_t
874  (
875  masterOp<int64_t>
876  (
877  fName,
878  fileSizeOp(followLink),
880  comm_
881  )
882  );
883 }
884 
885 
887 (
888  const fileName& fName,
889  const bool followLink
890 ) const
891 {
892  // time_t is invariably an integer type, but verify that anyhow
893  // before doing the following:
894 
895  if constexpr (std::is_integral_v<time_t>)
896  {
897  // Reduce as int64_t instead of time_t to avoid missing
898  // pTraits<long int> (or other ambiguities) on Linux i586
899  return time_t
900  (
901  masterOp<int64_t>
902  (
903  fName,
904  lastModifiedOp(followLink),
907  )
908  );
909  }
910  else
911  {
912  return masterOp<time_t>
913  (
914  fName,
915  lastModifiedOp(followLink),
918  );
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),
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  const label oldNProcs = fileOperation::nProcs();
1099 
1100  // All masters search locally. Note that global objects might
1101  // fail (except on master). This gets handled later on (in PARENTOBJECT)
1102  objPath =
1103  filePathInfo
1104  (
1105  checkGlobal,
1106  true,
1107  io,
1108  pDirs,
1109  search,
1110  searchType,
1111  procsDir,
1112  newInstancePath
1113  );
1114 
1115  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1116  fileOperation::cacheLevel(oldCache);
1117  UPstream::parRun(oldParRun);
1118 
1119  if (debug)
1120  {
1121  Pout<< "masterUncollatedFileOperation::filePath :"
1122  << " master objPath:" << objPath
1123  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1124  << " procsDir:" << procsDir << " instance:" << newInstancePath
1125  << endl;
1126  }
1127  }
1128 
1129  // Broadcast information about where the master found the object
1130  // Note: use the worldComm to make sure all processors decide
1131  // the same type. Only procsDir is allowed to differ; searchType
1132  // and instance have to be same
1133  if (UPstream::parRun())
1134  {
1135  int masterType(searchType);
1136  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1137  searchType = pathType(masterType);
1138  }
1139 
1140  if
1141  (
1142  checkGlobal
1143  || searchType == fileOperation::PARENTOBJECT
1144  || searchType == fileOperation::PROCBASEOBJECT
1145  || searchType == fileOperation::PROCBASEINSTANCE
1146  || io.local() == "uniform"
1147  )
1148  {
1149  // Distribute master path. This makes sure it is seen as uniform
1150  // and only gets read from the master.
1151  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1152  }
1153  else
1154  {
1155  Pstream::broadcast(procsDir, comm_);
1156 
1157  // Use the master type to determine if additional information is
1158  // needed to construct the local equivalent
1159  switch (searchType)
1160  {
1164  {
1165  // Already handled above
1166  }
1167  break;
1168 
1176  {
1177  // Construct equivalent local path
1178  objPath = localObjectPath
1179  (
1180  io,
1181  searchType,
1182  procsDir,
1183  newInstancePath
1184  );
1185  }
1186  break;
1187 
1188  case fileOperation::OBJECT:
1190  {
1191  // Retest all processors separately since some processors might
1192  // have the file and some not (e.g. lagrangian data)
1193 
1194  objPath = masterOp<fileName>
1195  (
1196  io.objectPath(),
1197  fileOrNullOp(true), // isFile=true
1199  comm_
1200  );
1201  }
1202  break;
1203  }
1204  }
1205 
1206  if (debug)
1207  {
1208  Pout<< "masterUncollatedFileOperation::filePath :"
1209  << " Returning from file searching using type "
1210  << fileOperation::pathTypeNames_[searchType] << endl
1211  << " objectPath:" << io.objectPath() << endl
1212  << " filePath :" << objPath << endl << endl;
1213  }
1214  return objPath;
1215 }
1216 
1217 
1219 (
1220  const bool checkGlobal,
1221  const IOobject& io,
1222  const bool search
1223 ) const
1224 {
1225  if (debug)
1226  {
1227  Pout<< "masterUncollatedFileOperation::dirPath :"
1228  << " objectPath:" << io.objectPath()
1229  << " checkGlobal:" << checkGlobal
1230  << " parRun:" << Pstream::parRun()
1231  << " localmaster:" << Pstream::master(comm_) << endl;
1232  }
1233 
1234  // Now that we have an IOobject path use it to detect & cache
1235  // processor directory naming
1236  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1237 
1238  // Trigger caching of times
1239  if (cacheLevel() > 0)
1240  {
1241  (void)findTimes(io.time().path(), io.time().constant());
1242  }
1243 
1244  // Determine master dirPath and broadcast
1245 
1246  fileName objPath;
1247  pathType searchType = NOTFOUND;
1248  word procsDir;
1249  word newInstancePath;
1250 
1251  // Local IO node searches for file
1252  if (Pstream::master(comm_))
1253  {
1254  const bool oldParRun = UPstream::parRun(false);
1255  const int oldCache = fileOperation::cacheLevel(0);
1256  const label oldNProcs = fileOperation::nProcs();
1257 
1258  objPath = filePathInfo
1259  (
1260  checkGlobal,
1261  false,
1262  io,
1263  pDirs,
1264  search,
1265  searchType,
1266  procsDir,
1267  newInstancePath
1268  );
1269 
1270  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1271  fileOperation::cacheLevel(oldCache);
1272  UPstream::parRun(oldParRun);
1273 
1274  if (debug)
1275  {
1276  Pout<< "masterUncollatedFileOperation::dirPath :"
1277  << " master objPath:" << objPath
1278  << " searchType:" << fileOperation::pathTypeNames_[searchType]
1279  << " procsDir:" << procsDir << " instance:" << newInstancePath
1280  << endl;
1281  }
1282  }
1283 
1284 
1285  // Broadcast information about where the master found the object
1286  // Note: use the worldComm to make sure all processors decide
1287  // the same type. Only procsDir is allowed to differ; searchType
1288  // and instance have to be same
1289  if (UPstream::parRun())
1290  {
1291  int masterType(searchType);
1292  Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1293  searchType = pathType(masterType);
1294  }
1295 
1296 
1297  if
1298  (
1299  checkGlobal
1300  || searchType == fileOperation::PARENTOBJECT
1301  || searchType == fileOperation::PROCBASEOBJECT
1302  || searchType == fileOperation::PROCBASEINSTANCE
1303  || io.local() == "uniform"
1304  )
1305  {
1306  // Distribute master path. This makes sure it is seen as uniform
1307  // and only gets read from the master.
1308  Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1309  }
1310  else
1311  {
1312  // Broadcast local processors dir amongst all local nodes
1313  Pstream::broadcast(procsDir, comm_);
1314 
1315  // Use the master type to determine if additional information is
1316  // needed to construct the local equivalent
1317  switch (searchType)
1318  {
1322  {
1323  // Already handled above
1324  }
1325  break;
1326 
1334  {
1335  // Construct equivalent local path
1336  objPath = localObjectPath
1337  (
1338  io,
1339  searchType,
1340  procsDir,
1341  newInstancePath
1342  );
1343  }
1344  break;
1345 
1346  case fileOperation::OBJECT:
1348  {
1349  // Retest all processors separately since some processors might
1350  // have the file and some not (e.g. lagrangian data)
1351 
1352  objPath = masterOp<fileName>
1353  (
1354  io.objectPath(),
1355  fileOrNullOp(false), // isFile=false
1357  comm_
1358  );
1359  }
1360  break;
1361  }
1362  }
1363 
1364  if (debug)
1365  {
1366  Pout<< "masterUncollatedFileOperation::dirPath :"
1367  << " Returning from directory searching using type "
1368  << fileOperation::pathTypeNames_[searchType] << endl
1369  << " objectPath:" << io.objectPath() << endl
1370  << " filePath :" << objPath << endl << endl;
1371  }
1372  return objPath;
1373 }
1374 
1375 
1377 (
1378  const dirIndexList& pDirs,
1379  IOobject& io
1380 ) const
1381 {
1382  // Cut-down version of filePathInfo that does not look for
1383  // different instance or parent directory
1384 
1385  const bool isFile = !io.name().empty();
1386 
1387  // Generate output filename for object
1388  const fileName writePath(objectPath(io, word::null));
1389 
1390  // 1. Test writing name for either directory or a (valid) file
1391  if (isFileOrDir(isFile, writePath))
1392  {
1393  return true;
1394  }
1395 
1396  // 2. Check processors/
1397  if (io.time().processorCase())
1398  {
1399  for (const dirIndex& dirIdx : pDirs)
1400  {
1401  const fileName& pDir = dirIdx.first();
1402  fileName procPath =
1403  processorsPath(io, io.instance(), pDir)
1404  /io.name();
1405  if (procPath != writePath && isFileOrDir(isFile, procPath))
1406  {
1407  return true;
1408  }
1409  }
1410  }
1411 
1412  // 3. Check local
1413  fileName localPath = io.objectPath();
1414 
1415  if (localPath != writePath && isFileOrDir(isFile, localPath))
1416  {
1417  return true;
1418  }
1420  return false;
1421 }
1422 
1423 
1426 (
1427  const IOobject& startIO,
1428  const scalar startValue,
1429  const word& stopInstance,
1430  const bool constant_fallback
1431 ) const
1432 {
1433  if (debug)
1434  {
1435  Pout<< "masterUncollatedFileOperation::findInstance :"
1436  << " Starting searching for name:" << startIO.name()
1437  << " local:" << startIO.local()
1438  << " from instance:" << startIO.instance()
1439  << endl;
1440  }
1441 
1442  const Time& time = startIO.time();
1443  IOobject io(startIO);
1444 
1445  // Note: - if name is empty, just check the directory itself
1446  // - check both for isFile and headerOk since the latter does a
1447  // filePath so searches for the file.
1448  // - check for an object with local file scope (so no looking up in
1449  // parent directory in case of parallel)
1450 
1451 
1452  const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1453 
1454  word foundInstance;
1455 
1456  // if (Pstream::master(comm_))
1458  {
1459  const bool oldParRun = UPstream::parRun(false);
1460  const int oldCache = fileOperation::cacheLevel(0);
1461  const label oldNProcs = fileOperation::nProcs();
1462 
1463  if (exists(pDirs, io))
1464  {
1465  foundInstance = io.instance();
1466  }
1467  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1468  fileOperation::cacheLevel(oldCache);
1469  UPstream::parRun(oldParRun);
1470  }
1471 
1472 
1473  // Do parallel early exit to avoid calling time.times()
1474  Pstream::broadcast(foundInstance, UPstream::worldComm);
1475 
1476  if (!foundInstance.empty())
1477  {
1478  io.instance() = foundInstance;
1479  if (debug)
1480  {
1481  Pout<< "masterUncollatedFileOperation::findInstance :"
1482  << " for name:" << io.name() << " local:" << io.local()
1483  << " found starting instance:" << io.instance() << endl;
1484  }
1485  return io;
1486  }
1487 
1488 
1489  // Handling failures afterwards
1490  const bool exitIfMissing = startIO.isReadRequired();
1491 
1492  enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1493  int failed(0);
1494 
1495  instantList ts = time.times();
1496 
1497  // if (Pstream::master(comm_))
1499  {
1500  const bool oldParRun = UPstream::parRun(false);
1501  const int oldCache = fileOperation::cacheLevel(0);
1502  const label oldNProcs = fileOperation::nProcs();
1503 
1504  label instIndex = ts.size()-1;
1505 
1506  // Backward search for first time that is <= startValue
1507  for (; instIndex >= 0; --instIndex)
1508  {
1509  if (ts[instIndex].value() <= startValue)
1510  {
1511  break;
1512  }
1513  }
1514 
1515  // Continue (forward) searching from here
1516  for (; instIndex >= 0; --instIndex)
1517  {
1518  // Shortcut: if actual directory is the timeName we've
1519  // already tested it
1520  if (ts[instIndex].name() == time.timeName())
1521  {
1522  continue;
1523  }
1524 
1525  io.instance() = ts[instIndex].name();
1526  if (exists(pDirs, io))
1527  {
1528  foundInstance = io.instance();
1529  if (debug)
1530  {
1531  Pout<< "masterUncollatedFileOperation::findInstance :"
1532  << " for name:" << io.name() << " local:" << io.local()
1533  << " found at:" << io.instance()
1534  << endl;
1535  }
1536  break;
1537  }
1538 
1539  // Check if hit minimum instance
1540  if (io.instance() == stopInstance)
1541  {
1542  if (debug)
1543  {
1544  Pout<< "masterUncollatedFileOperation::findInstance :"
1545  << " name:" << io.name()
1546  << " local:" << io.local()
1547  << " at stop-instance:" << io.instance() << endl;
1548  }
1549 
1550  if (exitIfMissing)
1551  {
1552  failed = failureCodes::FAILED_STOPINST;
1553  }
1554  else
1555  {
1556  // At the stopInstance
1557  foundInstance = io.instance();
1558  }
1559  break;
1560  }
1561  }
1562 
1563 
1564  // times() usually already includes the constant() so would
1565  // have been checked above. However, re-test under these conditions:
1566  // - times() is empty. Sometimes this can happen (e.g. decomposePar
1567  // with collated)
1568  // - times()[0] is not constant
1569  // - Times is empty.
1570  // Sometimes this can happen (eg, decomposePar with collated)
1571  // - Times[0] is not constant
1572  // - The startValue is negative (eg, kivaTest).
1573  // This plays havoc with the reverse search, causing it to miss
1574  // 'constant'
1575 
1576  if
1577  (
1578  !failed && foundInstance.empty()
1579  && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1580  )
1581  {
1582  // Note. This needs to be a hard-coded "constant" (not constant
1583  // function of Time), because the latter points to
1584  // the case constant directory in parallel cases.
1585  // However, parRun is disabled so they are actually the same.
1586 
1587  io.instance() = time.constant();
1588 
1589  if (exists(pDirs, io))
1590  {
1591  if (debug)
1592  {
1593  Pout<< "masterUncollatedFileOperation::findInstance :"
1594  << " name:" << io.name()
1595  << " local:" << io.local()
1596  << " at:" << io.instance() << endl;
1597  }
1598  foundInstance = io.instance();
1599  }
1600  }
1601 
1602  if (!failed && foundInstance.empty())
1603  {
1604  if (exitIfMissing)
1605  {
1606  failed = failureCodes::FAILED_CONSTINST;
1607  }
1608  else if (constant_fallback)
1609  {
1610  foundInstance = time.constant();
1611  }
1612  else
1613  {
1614  foundInstance.clear();
1615  }
1616  }
1617 
1618  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1619  fileOperation::cacheLevel(oldCache);
1620  UPstream::parRun(oldParRun); // Restore parallel state
1621  }
1622 
1623  Pstream::broadcast(foundInstance, UPstream::worldComm);
1624 
1625  io.instance() = foundInstance;
1626 
1627 
1628  // Handle failures
1629  // ~~~~~~~~~~~~~~~
1630  if (failed)
1631  {
1632  FatalErrorInFunction << "Cannot find";
1633 
1634  if (!io.name().empty())
1635  {
1636  FatalError
1637  << " file \"" << io.name() << "\" in";
1638  }
1639 
1640  FatalError
1641  << " directory "
1642  << io.local() << " in times "
1643  << startIO.instance() << " down to ";
1644 
1645  if (failed == failureCodes::FAILED_STOPINST)
1646  {
1647  FatalError << stopInstance;
1648  }
1649  else // FAILED_CONSTINST
1650  {
1651  FatalError << "constant";
1652  }
1654  }
1655 
1656  if (debug)
1657  {
1658  Pout<< "masterUncollatedFileOperation::findInstance :"
1659  << " name:" << io.name() << " local:" << io.local()
1660  << " returning instance:" << io.instance() << endl;
1661  }
1662  return io;
1663 }
1664 
1665 
1668 (
1669  const objectRegistry& db,
1670  const fileName& instance,
1671  const fileName& local,
1672  word& newInstance
1673 ) const
1674 {
1675  if (debug)
1676  {
1677  Pout<< "masterUncollatedFileOperation::readObjects :"
1678  << " db:" << db.objectPath()
1679  << " local:" << local << " instance:" << instance << endl;
1680  }
1681 
1682  fileNameList objectNames;
1683  newInstance.clear();
1684 
1685  // Note: readObjects uses WORLD to make sure order of objects is the
1686  // same everywhere
1687 
1689  {
1690  // Avoid fileOperation::readObjects from triggering parallel ops
1691  // (through call to filePath which triggers parallel )
1692  const bool oldParRun = UPstream::parRun(false);
1693  const int oldCache = fileOperation::cacheLevel(0);
1694  const label oldNProcs = fileOperation::nProcs();
1695 
1696  //- Use non-time searching version
1697  objectNames = fileOperation::readObjects
1698  (
1699  db,
1700  instance,
1701  local,
1702  newInstance
1703  );
1704 
1705  if (newInstance.empty())
1706  {
1707  // Find similar time
1708 
1709  // Copy of Time::findInstancePath. We want to avoid the
1710  // parallel call to findTimes.
1711  const instantList timeDirs
1712  (
1714  (
1715  db.time().path(),
1716  db.time().constant()
1717  )
1718  );
1719 
1720  fileName foundInst
1721  (
1722  Time::findInstancePath(timeDirs, instant(instance))
1723  );
1724 
1725  if (!foundInst.empty())
1726  {
1727  objectNames = fileOperation::readObjects
1728  (
1729  db,
1730  foundInst, // newly found time
1731  local,
1732  newInstance
1733  );
1734  }
1735  }
1736 
1737  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1738  fileOperation::cacheLevel(oldCache);
1739  UPstream::parRun(oldParRun); // Restore parallel state
1740  }
1741 
1742  Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1743 
1744  if (debug)
1745  {
1746  Pout<< "masterUncollatedFileOperation::readObjects :"
1747  << " newInstance:" << newInstance
1748  << " objectNames:" << objectNames << endl;
1749  }
1750 
1751  return objectNames;
1752 }
1753 
1754 
1756 (
1757  IOobject& io,
1758  const fileName& fName,
1759  const word& typeName
1760 ) const
1761 {
1762  bool ok = false;
1763 
1764  if (debug)
1765  {
1766  Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1767  << " objectPath:" << io.objectPath() << endl
1768  << " filePath :" << fName << endl;
1769  }
1770 
1771  // We assume if filePath is the same
1772  // - headerClassName
1773  // - note
1774  // are also the same, independent of where the file came from.
1775 
1776  // Get filePaths on world master
1778  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
1780 
1781  bool uniform
1782  (
1784  && fileOperation::uniformFile(filePaths)
1785  );
1786 
1788 
1789  if (uniform)
1790  {
1792  {
1793  if (!fName.empty())
1794  {
1795  IFstream is(fName);
1796 
1797  if (is.good())
1798  {
1799  // Regular header or from decomposed data
1801  }
1802  }
1803  }
1804 
1806  (
1808  ok,
1809  io.headerClassName(),
1810  io.note()
1811  );
1812  }
1813  else
1814  {
1816  {
1817  // Assume if different nprocs the communicators are also
1818  // different. Re-gather file paths on local master
1819  filePaths.resize(UPstream::nProcs(comm_));
1820  filePaths[UPstream::myProcNo(comm_)] = fName;
1821  Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
1822  }
1823 
1824  // Intermediate storage arrays (master only)
1825  boolList result;
1826  wordList headerClassName;
1827  stringList note;
1828 
1829  if (Pstream::master(comm_))
1830  {
1831  const label np = Pstream::nProcs(comm_);
1832 
1833  result.resize(np, false);
1834  headerClassName.resize(np);
1835  note.resize(np);
1836 
1837  forAll(filePaths, proci)
1838  {
1839  if (!filePaths[proci].empty())
1840  {
1841  if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1842  {
1843  result[proci] = result[proci-1];
1844  headerClassName[proci] = headerClassName[proci-1];
1845  note[proci] = note[proci-1];
1846  }
1847  else
1848  {
1849  IFstream is(filePaths[proci]);
1850 
1851  if (is.good())
1852  {
1853  result[proci] =
1855  headerClassName[proci] = io.headerClassName();
1856  note[proci] = io.note();
1857  }
1858  }
1859  }
1860  }
1861  }
1862 
1863  // Is a more efficient scatter possible?
1864  PstreamBuffers pBufs(comm_);
1865 
1866  if (Pstream::master(comm_))
1867  {
1868  ok = result[0];
1869  io.headerClassName() = headerClassName[0];
1870  io.note() = note[0];
1871 
1872  // Scatter to each proc
1873  for (const int proci : pBufs.subProcs())
1874  {
1875  UOPstream os(proci, pBufs);
1876  os << result[proci] << headerClassName[proci] << note[proci];
1877  }
1878  }
1879 
1880  pBufs.finishedScatters();
1881 
1882  if (!Pstream::master(comm_))
1883  {
1884  UIPstream is(Pstream::masterNo(), pBufs);
1885  is >> ok >> io.headerClassName() >> io.note();
1886  }
1887  }
1888 
1889  if (debug)
1890  {
1891  Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1892  << " class:" << io.headerClassName()
1893  << " for file:" << fName << endl;
1894  }
1895  return ok;
1897 
1898 
1901 (
1902  regIOobject& io,
1903  const fileName& fName,
1904  const word& typeName,
1905  const bool readOnProc
1906 ) const
1907 {
1908  if (debug)
1909  {
1910  Pout<< "masterUncollatedFileOperation::readStream :"
1911  << " object : " << io.name()
1912  << " global : " << io.global()
1913  << " globalObject : " << io.globalObject()
1914  << " fName : " << fName << " readOnProc:" << readOnProc << endl;
1915  }
1916 
1917  // Close old stream
1918  io.close();
1919 
1920  autoPtr<ISstream> isPtr;
1921  bool isCollated = false;
1922  IOobject headerIO(io);
1923 
1924  // Detect collated format. This could be done on the local communicator
1925  // but we do it on the master node only for now.
1927  {
1928  if (!fName.empty())
1929  {
1930  // This can happen in lagrangian field reading some processors
1931  // have no file to read from. This will only happen when using
1932  // normal writing since then the fName for the valid processors is
1933  // processorDDD/<instance>/.. . In case of collocated writing
1934  // the fName is already rewritten to processorsNN/.
1935 
1936  isPtr.reset(new IFstream(fName));
1937 
1938  if (isPtr->good())
1939  {
1940  // Read header data (on copy)
1941  headerIO.readHeader(*isPtr);
1942 
1943  isCollated = decomposedBlockData::isCollatedType(headerIO);
1944 
1945  if (!isCollated && !Pstream::parRun())
1946  {
1947  // Short circuit: non-collated format. No parallel bits.
1948  // Copy header and return.
1949  if (debug)
1950  {
1951  Pout<< "masterUncollatedFileOperation::readStream :"
1952  << " For object : " << io.name()
1953  << " doing straight IFstream input from "
1954  << fName << endl;
1955  }
1956 
1957  // Copy IOobject header information
1958  io.IOobject::operator=(headerIO);
1959  return isPtr;
1960  }
1961  }
1962 
1963  if (!isCollated)
1964  {
1965  // Close file. Reopened below.
1966  isPtr.clear();
1967  }
1968  }
1969  }
1970 
1972 
1973  if (isCollated)
1974  {
1975  if (debug)
1976  {
1977  Pout<< "masterUncollatedFileOperation::readStream :"
1978  << " For object : " << io.name()
1979  << " starting collating input from " << fName << endl;
1980  }
1981 
1982 
1983  // Analyse the file path (on (co)master) to see the processors type
1984  // Note: this should really be part of filePath() which should return
1985  // both file and index in file.
1986 
1987  fileName path, procDir, local;
1988  procRangeType group;
1989  label nProcs;
1990  splitProcessorPath(fName, path, procDir, local, group, nProcs);
1991 
1992 
1993  if (!UPstream::parRun())
1994  {
1995  // Analyse the objectpath to find out the processor we're trying
1996  // to access
1997  label proci = detectProcessorPath(io.objectPath());
1998 
1999  if (proci == -1)
2000  {
2001  FatalIOErrorInFunction(*isPtr)
2002  << "Could not detect processor number"
2003  << " from objectPath:" << io.objectPath()
2004  << " fileHandler : comm:" << comm_
2005  << " ioRanks:" << flatOutput(ioRanks_)
2006  << exit(FatalIOError);
2007  }
2008 
2009  // The local rank (offset)
2010  if (!group.empty())
2011  {
2012  proci = proci - group.start();
2013  }
2014 
2015  if (debug)
2016  {
2017  Pout<< "masterUncollatedFileOperation::readStream :"
2018  << " For object : " << io.name()
2019  << " starting input from block " << proci
2020  << " of " << isPtr->name() << endl;
2021  }
2022 
2023  return decomposedBlockData::readBlock(proci, *isPtr, io);
2024  }
2025  else
2026  {
2027  // Are we reading from single-master file ('processors256') or
2028  // from multi-master files ('processors256_0-9')
2029  label readComm = -1;
2030  if (!group.empty())
2031  {
2032  readComm = comm_;
2033  if (UPstream::master(comm_) && !isPtr && !fName.empty())
2034  {
2035  // In multi-master mode also open the file on the other
2036  // masters
2037  isPtr.reset(new IFstream(fName));
2038 
2039  if (isPtr->good())
2040  {
2041  // Read header data (on copy)
2042  IOobject headerIO(io);
2043  headerIO.readHeader(*isPtr);
2044  }
2045  }
2046  }
2047  else
2048  {
2049  // Single master so read on world
2050  readComm = UPstream::worldComm;
2051  }
2052 
2053  // Get size of file to determine communications type
2054  bool bigSize = false;
2055 
2057  {
2058  // TBD: handle multiple masters?
2059  bigSize =
2060  (
2061  off_t(Foam::fileSize(fName))
2062  > off_t(maxMasterFileBufferSize)
2063  );
2064  }
2065  // Reduce (not broadcast)
2066  // - if we have multiple master files (FUTURE)
2068 
2069  const UPstream::commsTypes myCommsType
2070  (
2071  bigSize
2074  );
2075 
2076  // Read my data
2078  (
2079  readComm,
2080  fName,
2081  isPtr,
2082  io,
2083  myCommsType
2084  );
2085  }
2086  }
2087  else
2088  {
2089  if (debug)
2090  {
2091  Pout<< "masterUncollatedFileOperation::readStream :"
2092  << " For object : " << io.name()
2093  << " starting separated input from " << fName << endl;
2094  }
2095 
2096  if (io.global() || io.globalObject())
2097  {
2098  // Use worldComm. Note: should not really need to gather filePaths
2099  // since we enforce sending from master anyway ...
2101  filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
2103  (
2104  filePaths,
2107  );
2108 
2109  boolList readOnProcs
2110  (
2111  UPstream::listGatherValues<bool>
2112  (
2113  readOnProc,
2115  )
2116  );
2117  // NB: local proc validity information required on sub-ranks too!
2118  readOnProcs.resize(UPstream::nProcs(UPstream::worldComm));
2119  readOnProcs[UPstream::myProcNo(UPstream::worldComm)] = readOnProc;
2120 
2121  // Uniform in local comm
2122  return read(io, UPstream::worldComm, true, filePaths, readOnProcs);
2123  }
2124  else
2125  {
2126  // Use local communicator
2127  fileNameList filePaths(UPstream::nProcs(comm_));
2128  filePaths[UPstream::myProcNo(comm_)] = fName;
2130  (
2131  filePaths,
2133  comm_
2134  );
2135 
2136  boolList readOnProcs
2137  (
2138  UPstream::listGatherValues<bool>
2139  (
2140  readOnProc,
2141  comm_
2142  )
2143  );
2144  // NB: local proc validity information required on sub-ranks too!
2145  readOnProcs.resize(UPstream::nProcs(comm_));
2146  readOnProcs[UPstream::myProcNo(comm_)] = readOnProc;
2147 
2148  // Uniform in local comm
2149  const bool uniform = fileOperation::uniformFile(filePaths);
2150 
2151  return read(io, comm_, uniform, filePaths, readOnProcs);
2152  }
2153  }
2154 }
2155 
2156 
2158 (
2159  regIOobject& io,
2160  const bool masterOnly,
2162  const word& typeName
2163 ) const
2164 {
2165  bool ok = true;
2166 
2167  if (io.global() || io.globalObject())
2168  {
2169  if (debug)
2170  {
2171  Pout<< "masterUncollatedFileOperation::read :"
2172  << " Reading global object " << io.name()
2173  << " worldComm:" << UPstream::worldComm
2174  << " Pstream::myProcNo:"
2176  << " amMaster:" << Pstream::master(UPstream::worldComm)
2177  << endl;
2178  }
2179 
2181  {
2182  // Do master-only reading always.
2183  const bool oldParRun = UPstream::parRun(false);
2184  const int oldCache = fileOperation::cacheLevel(0);
2185  const label oldNProcs = fileOperation::nProcs();
2186 
2187  auto& is = io.readStream(typeName);
2188  ok = io.readData(is);
2189  io.close();
2190 
2191  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2192  fileOperation::cacheLevel(oldCache);
2193  UPstream::parRun(oldParRun); // Restore parallel state
2194  }
2195 
2196  // Broadcast regIOobject content, with writeData/readData handling
2197  if (UPstream::parRun())
2198  {
2200  {
2201  OPBstream os(UPstream::worldComm, format);
2202 
2203  os << io.headerClassName() << io.note();
2204  bool okWrite = io.writeData(os);
2205  ok = ok && okWrite;
2206  }
2207  else
2208  {
2209  IPBstream is(UPstream::worldComm, format);
2210 
2211  is >> io.headerClassName() >> io.note();
2212  ok = io.readData(is);
2213  }
2214  }
2215  }
2216  else
2217  {
2218  if (debug)
2219  {
2220  Pout<< "masterUncollatedFileOperation::read :"
2221  << " Reading local object " << io.name() << endl;
2222  }
2223 
2224  ok = io.readData(io.readStream(typeName));
2225  io.close();
2226  }
2227 
2228  if (debug)
2229  {
2230  Pout<< "masterUncollatedFileOperation::read :"
2231  << " Read object:" << io.name()
2232  << " isGlobal:" << (io.global() || io.globalObject())
2233  << " status:" << ok << endl;
2234  }
2235 
2236  return ok;
2237 }
2238 
2239 
2241 (
2242  const regIOobject& io,
2243  IOstreamOption streamOpt,
2244  const bool writeOnProc
2245 ) const
2246 {
2247  fileName pathName(io.objectPath());
2248 
2249  if (debug)
2250  {
2251  Pout<< "masterUncollatedFileOperation::writeObject :"
2252  << " io:" << pathName << " writeOnProc:" << writeOnProc << endl;
2253  }
2254 
2255  // Make sure to pick up any new times
2256  setTime(io.time());
2257 
2258  // Update meta-data for current state
2259  const_cast<regIOobject&>(io).updateMetaData();
2260 
2261  autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, writeOnProc));
2262  OSstream& os = *osPtr;
2263 
2264  // If any of these fail, return (leave error handling to Ostream class)
2265 
2266  const bool ok =
2267  (
2268  os.good()
2269  && io.writeHeader(os)
2270  && io.writeData(os)
2271  );
2272 
2273  if (ok)
2274  {
2276  }
2277 
2278  return ok;
2279 }
2280 
2281 
2283 (
2284  const fileName& directory,
2285  const word& constantName
2286 ) const
2287 {
2288  const auto iter = times_.cfind(directory);
2289  if (iter.good())
2290  {
2291  if (debug)
2292  {
2293  Pout<< "masterUncollatedFileOperation::findTimes :"
2294  << " Found " << iter.val()->size() << " cached times" << nl
2295  << " for directory:" << directory << endl;
2296  }
2297  return *(iter.val());
2298  }
2299  else
2300  {
2301  instantList times;
2303  {
2304  // Do master-only reading always.
2305  const bool oldParRun = UPstream::parRun(false);
2306  const int oldCache = fileOperation::cacheLevel(0);
2307  const label oldNProcs = fileOperation::nProcs();
2308 
2309  times = fileOperation::findTimes(directory, constantName);
2310 
2311  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2312  fileOperation::cacheLevel(oldCache);
2313  UPstream::parRun(oldParRun); // Restore parallel state
2314  }
2315 
2317 
2318  if (debug)
2319  {
2320  Pout<< "masterUncollatedFileOperation::findTimes :"
2321  << " Found times:" << flatOutput(times) << nl
2322  << " for directory:" << directory << endl;
2323  }
2324 
2325  // Caching
2326  // - cache values even if no times were found since it might
2327  // indicate a directory that is being filled later on ...
2328  if (cacheLevel() > 0)
2329  {
2330  auto* tPtr = new DynamicList<instant>(std::move(times));
2331  times_.set(directory, tPtr);
2332 
2333  return *tPtr;
2334  }
2335 
2336  // Times found (not cached)
2337  return times;
2338  }
2339 }
2340 
2341 
2343 (
2344  const Time& tm
2345 ) const
2346 {
2347  if (tm.subCycling())
2348  {
2349  return;
2350  }
2351 
2352  // Mutable access to instant list for modification and sorting
2353  // - cannot use auto type deduction here
2354 
2355  auto iter = times_.find(tm.path());
2356 
2357  if (iter.good())
2358  {
2359  DynamicList<instant>& times = *(iter.val());
2360 
2361  const instant timeNow(tm.value(), tm.timeName());
2362 
2363  // The start index for checking and sorting (excluding "constant")
2364  const label startIdx =
2365  (
2366  (times.empty() || times[0].name() != tm.constant())
2367  ? 0
2368  : 1
2369  );
2370 
2371  // This routine always results in a sorted list of times, so first
2372  // check if the new time is greater than the latest existing time.
2373  // Can then simply append without extra searching or sorting
2374 
2375  if (times.size() <= startIdx || times.last() < timeNow)
2376  {
2377  times.append(timeNow);
2378  }
2379  else if
2380  (
2382  (
2383  SubList<instant>(times, times.size()-startIdx, startIdx),
2384  timeNow
2385  ) < 0
2386  )
2387  {
2388  if (debug)
2389  {
2390  Pout<< "masterUncollatedFileOperation::setTime :"
2391  << " Caching time " << tm.timeName()
2392  << " for case:" << tm.path() << endl;
2393  }
2394 
2395  times.append(timeNow);
2396 
2397  SubList<instant> realTimes
2398  (
2399  times, times.size()-startIdx, startIdx
2400  );
2401  Foam::stableSort(realTimes);
2402  }
2403  }
2404 
2407 
2408 
2411 (
2412  const fileName& filePath
2413 ) const
2414 {
2415  autoPtr<ISstream> isPtr;
2416 
2417  if (Pstream::parRun())
2418  {
2419  // Insert logic of filePath. We assume that if a file is absolute
2420  // on the master it is absolute also on the sub-ranks etc.
2421 
2422  fileNameList filePaths(Pstream::nProcs(comm_));
2423  filePaths[Pstream::myProcNo(comm_)] = filePath;
2424  Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2425 
2426  PstreamBuffers pBufs(comm_);
2427 
2428  if (Pstream::master(comm_))
2429  {
2430  // Same filename on the IO node -> same file
2431  const bool uniform = fileOperation::uniformFile(filePaths);
2432 
2433  if (uniform)
2434  {
2435  if (debug)
2436  {
2437  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2438  << " Opening global file " << filePath << endl;
2439  }
2440 
2441  readAndSend
2442  (
2443  filePath,
2444  identity(Pstream::nProcs(comm_)-1, 1),
2445  pBufs
2446  );
2447  }
2448  else
2449  {
2450  for (const int proci : Pstream::subProcs(comm_))
2451  {
2452  if (debug)
2453  {
2454  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2455  << " Opening local file " << filePath
2456  << " for rank " << proci << endl;
2457  }
2458 
2459  readAndSend
2460  (
2461  filePaths[proci],
2462  labelList(one{}, proci),
2463  pBufs
2464  );
2465  }
2466  }
2467  }
2468 
2469 
2470  pBufs.finishedSends();
2471 
2472  if (Pstream::master(comm_))
2473  {
2474  // Read myself
2475  isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2476  }
2477  else
2478  {
2479  if (debug)
2480  {
2481  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2482  << " Reading " << filePath
2483  << " from processor " << Pstream::masterNo() << endl;
2484  }
2485 
2487 
2488  if (!buf.empty())
2489  {
2490  UIPstream is(Pstream::masterNo(), pBufs);
2491  is.read(buf.data(), buf.size());
2492  }
2493 
2494  if (debug)
2495  {
2496  Pout<< "masterUncollatedFileOperation::NewIFstream :"
2497  << " Done reading " << buf.size() << " bytes" << endl;
2498  }
2499 
2500  // A local character buffer copy of the Pstream contents.
2501  // Construct with same parameters (ASCII, current version)
2502  // as the IFstream so that it has the same characteristics.
2503 
2504  isPtr.reset(new ICharStream(std::move(buf)));
2505 
2506  // With the proper file name
2507  isPtr->name() = filePath;
2508  }
2509  }
2510  else
2511  {
2512  // Read myself
2513  isPtr.reset(new IFstream(filePath));
2514  }
2515 
2516  return isPtr;
2518 
2519 
2522 (
2523  const fileName& pathName,
2524  IOstreamOption streamOpt,
2525  const bool writeOnProc
2526 ) const
2527 {
2528  return autoPtr<OSstream>
2529  (
2530  new masterOFstream
2531  (
2532  comm_,
2533  pathName,
2534  streamOpt,
2536  writeOnProc
2537  )
2538  );
2540 
2541 
2544 (
2546  const fileName& pathName,
2547  IOstreamOption streamOpt,
2548  const bool writeOnProc
2549 ) const
2550 {
2551  return autoPtr<OSstream>
2552  (
2553  new masterOFstream
2554  (
2555  atomic,
2556  comm_,
2557  pathName,
2558  streamOpt,
2560  writeOnProc
2561  )
2562  );
2563 }
2564 
2565 
2567 {
2569  times_.clear();
2570 }
2571 
2572 
2574 {
2575  if (debug)
2576  {
2577  Pout<< "masterUncollatedFileOperation::sync :"
2578  << " syncing information across processors" << endl;
2579  }
2580 
2582 
2583 
2584  wordList timeNames;
2585  List<DynamicList<instant>> instants;
2586 
2588  {
2589  timeNames.resize(times_.size());
2590  instants.resize(times_.size());
2591 
2592  // Flatten into two lists to preserve key/val pairing
2593  label i = 0;
2594  forAllConstIters(times_, iter)
2595  {
2596  timeNames[i] = iter.key();
2597  instants[i] = std::move(*(iter.val()));
2598  ++i;
2599  }
2600  }
2601 
2602  Pstream::broadcasts(UPstream::worldComm, timeNames, instants);
2603 
2604  times_.clear();
2605  forAll(timeNames, i)
2606  {
2607  fileName dir(timeNames[i]);
2608  auto ptr = autoPtr<DynamicList<instant>>::New(std::move(instants[i]));
2609 
2611  {
2612  // Replace processor0 ending with processorDDD
2613  fileName path;
2614  fileName pDir;
2615  fileName local;
2616  procRangeType group;
2617  label numProcs;
2618  const label proci = splitProcessorPath
2619  (
2620  dir,
2621  path,
2622  pDir,
2623  local,
2624  group,
2625  numProcs
2626  );
2627 
2628  //Pout<< "**sync : From dir : " << dir << nl
2629  // << " path : " << path << nl
2630  // << " pDir : " << pDir << nl
2631  // << " local: " << local << nl
2632  // << " proci: " << proci << nl
2633  // << endl;
2634 
2635  const label myProci = Pstream::myProcNo(UPstream::worldComm);
2636 
2637  if (proci != -1 && proci != myProci)
2638  {
2639  dir = path/"processor" + Foam::name(myProci);
2640  }
2641  }
2642 
2643  times_.insert(dir, ptr);
2644  }
2645 }
2646 
2647 
2649 (
2650  const fileName& fName
2651 ) const
2652 {
2653  label watchFd = -1;
2655  {
2656  watchFd = monitor().addWatch(fName);
2657  }
2658 
2660  return watchFd;
2661 }
2662 
2663 
2665 (
2666  const label watchIndex
2667 ) const
2668 {
2669  bool ok = false;
2671  {
2672  ok = monitor().removeWatch(watchIndex);
2673  }
2674 
2676  return ok;
2677 }
2678 
2679 
2681 (
2682  const labelList& watchIndices,
2683  const fileName& fName
2684 ) const
2685 {
2686  label index = -1;
2687 
2689  {
2690  forAll(watchIndices, i)
2691  {
2692  if (monitor().getFile(watchIndices[i]) == fName)
2693  {
2694  index = i;
2695  break;
2696  }
2697  }
2698  }
2699 
2701  return index;
2702 }
2703 
2704 
2706 (
2707  regIOobject& rio,
2708  const fileNameList& files
2709 ) const
2710 {
2711  const labelList& watchIndices = rio.watchIndices();
2712 
2713  // Do on master and distribute effect to subprocs such that after
2714  // all have consistent numbering & files
2715 
2716  DynamicList<label> newWatchIndices;
2717  if (UPstream::master())
2718  {
2719  // Switch off comms inside findWatch/addWatch etc.
2720  const bool oldParRun = UPstream::parRun(false);
2721  const int oldCache = fileOperation::cacheLevel(0);
2722  const label oldNProcs = fileOperation::nProcs();
2723 
2724  labelHashSet removedWatches(watchIndices);
2725 
2726  for (const fileName& f : files)
2727  {
2728  const label index = findWatch(watchIndices, f);
2729 
2730  if (index == -1)
2731  {
2732  newWatchIndices.push_back(addWatch(f));
2733  }
2734  else
2735  {
2736  // Existing watch
2737  newWatchIndices.push_back(watchIndices[index]);
2738  removedWatches.erase(index);
2739  }
2740  }
2741 
2742  // Remove any unused watches
2743  for (const label index : removedWatches)
2744  {
2745  removeWatch(watchIndices[index]);
2746  }
2747 
2748  const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2749  fileOperation::cacheLevel(oldCache);
2750  UPstream::parRun(oldParRun);
2751  }
2752  Pstream::broadcast(newWatchIndices);
2753 
2754  rio.watchIndices() = newWatchIndices;
2755 }
2756 
2757 
2759 (
2760  const label watchIndex
2761 ) const
2762 {
2763  fileName fName;
2765  {
2766  fName = monitor().getFile(watchIndex);
2767  }
2768 
2770  return fName;
2771 }
2772 
2773 
2775 (
2776  const bool masterOnly,
2777  const bool syncPar
2778 ) const
2779 {
2781  {
2782  monitor().updateStates(true, false);
2783  }
2785 
2786 
2789 (
2790  const label watchFd
2791 ) const
2792 {
2793  unsigned int state = fileMonitor::UNMODIFIED;
2795  {
2796  state = monitor().getState(watchFd);
2797  }
2798 
2800  return fileMonitor::fileState(state);
2801 }
2802 
2803 
2805 (
2806  const label watchFd
2807 ) const
2808 {
2810  {
2811  monitor().setUnmodified(watchFd);
2812  }
2813 }
2814 
2815 
2816 // ************************************************************************* //
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:907
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:150
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...
static void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel. ...
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:600
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:56
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:526
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:622
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:1718
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.
static label newCommunicator(const label parent, const labelRange &subRanks, const bool withComponents=true)
Create new communicator with sub-ranks on the parent communicator.
Definition: UPstream.C:272
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:529
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
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)
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:311
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:1787
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 std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr)
Receive buffer contents (contiguous types) from given processor.
static void broadcast(Type &value, const int communicator=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition: UPstream.H:1611
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition: UPstream.H:987
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:76
static void gatherList(UList< T > &values, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Gather data, but keep individual values separate.
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:286
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:295
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:801
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:1602
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:1596
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:837
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:558
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.
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:489
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:879
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.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:629
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:1619
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)
static List< int > & procID(int communicator)
The list of ranks within a given communicator.
Definition: UPstream.H:1672
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:61
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1727
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:688
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce)
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:775
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:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Type
Enumerations to handle directory entry types.
Definition: fileName.H:81
Extract type (as a word) from an object, typically using its type() method.
Definition: word.H:361
label comm_
Communicator to use.
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:56
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...