Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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"
43/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
44
45namespace Foam
46{
47namespace fileOperations
48{
51 (
54 word
55 );
57 (
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 (
79 word,
80 masterUncollated
81 );
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
191 if
192 (
193 const auto* instPtr = times_.get(io.time().path());
194 search && instPtr
195 )
196 {
197 newInstancePath =
199 (
200 *instPtr, // instantList (cached)
201 instant(io.instance())
202 );
203
204 if (newInstancePath.size() && newInstancePath != io.instance())
205 {
206 // 1. Try processors equivalent
207 for (const dirIndex& dirIdx : pDirs)
208 {
209 const fileName& pDir = dirIdx.first();
210
211 fileName fName
212 (
213 processorsPath(io, newInstancePath, pDir)
214 /io.name()
215 );
216 if (isFileOrDir(isFile, fName))
217 {
218 switch (dirIdx.second().first())
219 {
221 {
222 searchType =
224 }
225 break;
227 {
229 }
230 break;
232 {
233 searchType = fileOperation::PROCINSTANCE;
234 }
235 break;
236 default:
237 break;
238 }
239 procsDir = pDir;
240 return fName;
241 }
242 }
243
244
245 // 2. Check local
246 fileName fName
247 (
248 io.rootPath()/io.caseName()
249 /newInstancePath/io.db().dbDir()/io.local()/io.name()
250 );
251 if (isFileOrDir(isFile, fName))
252 {
253 searchType = fileOperation::FINDINSTANCE;
254 return fName;
255 }
256 }
257 }
258 }
259
260 // Nothing found
261 searchType = fileOperation::NOTFOUND;
262 return fileName();
263}
264
265
268(
269 const IOobject& io,
270 const pathType& searchType,
271 const word& procDir,
272 const word& instancePath
273) const
274{
275 // Replacement for IOobject::objectPath()
276
277 switch (searchType)
278 {
280 {
281 return io.instance()/io.name();
282 }
283 break;
284
286 {
287 return io.path()/io.name();
288 }
289 break;
290
292 {
293 return objectPath(io, io.headerClassName());
294 }
295 break;
296
298 {
299 // Uncollated type, e.g. processor1
300 const word procName
301 (
303 );
304 return
305 processorsPath
306 (
307 io,
308 io.instance(),
309 (
311 ? procName
312 : procDir
313 )
314 )
315 /io.name();
316 }
317 break;
318
320 {
321 // Collated, e.g. processors4
322 return
323 processorsPath(io, io.instance(), procDir)
324 /io.name();
325 }
326 break;
327
329 {
330 // Processors directory locally provided by the fileHandler itself
331 return
332 processorsPath(io, io.instance(), processorsDir(io))
333 /io.name();
334 }
335 break;
336
338 {
339 return
340 io.rootPath()/io.globalCaseName()
341 /io.instance()/io.db().dbDir()/io.local()/io.name();
342 }
343 break;
344
346 {
347 return
348 io.rootPath()/io.caseName()
349 /instancePath/io.db().dbDir()/io.local()/io.name();
350 }
351 break;
352
354 {
355 // Uncollated type, e.g. processor1
356 const word procName
357 (
358 "processor"
360 );
361 return
362 processorsPath
363 (
364 io,
365 instancePath,
366 (
368 ? procName
369 : procDir
370 )
371 )
372 /io.name();
373 }
374 break;
375
377 {
378 // Collated, e.g. processors4
379 return
380 processorsPath(io, instancePath, procDir)
381 /io.name();
382 }
383 break;
384
386 {
387 // Processors directory locally provided by the fileHandler itself
388 return
389 processorsPath(io, instancePath, processorsDir(io))
390 /io.name();
391 }
392 break;
393
395 {
396 return fileName();
397 }
398 break;
399
400 default:
401 {
403 return fileName();
404 }
405 }
406}
407
408
410(
411 const fileName& filePath,
412 const labelUList& recvProcs,
413 PstreamBuffers& pBufs
414)
415{
416 if (recvProcs.empty()) return;
417
418 IFstream ifs(filePath, IOstreamOption::BINARY);
419
420 if (!ifs.good())
421 {
422 FatalIOErrorInFunction(filePath)
423 << "Cannot open file " << filePath
424 << exit(FatalIOError);
425 }
426
427 // Read file contents (compressed or uncompressed) into a character buffer
428 DynamicList<char> buf(IFstream::readContents(ifs));
429
430 if (debug)
431 {
432 Info<< "masterUncollatedFileOperation::readAndSend :"
433 << filePath
434 << " (compressed:" << bool(ifs.compression())
435 << ") : " << " bytes" << endl;
436 }
437
438 for (const label proci : recvProcs)
439 {
440 UOPstream os(proci, pBufs);
441 os.write(buf.cdata_bytes(), buf.size_bytes());
442 }
443}
444
445
448(
449 IOobject& io,
450 const label comm,
451 const bool uniform, // on comms master only
452 const fileNameList& filePaths, // on comms master and sub-ranks
453 const boolUList& readOnProcs // on comms master and sub-ranks
454)
455{
456 autoPtr<ISstream> isPtr;
457
458 PstreamBuffers pBufs(comm);
459
460 if (UPstream::master(comm))
461 {
462 if (uniform)
463 {
464 if (readOnProcs[0])
465 {
466 if (filePaths[0].empty())
467 {
468 FatalIOErrorInFunction(filePaths[0])
469 << "Cannot find file " << io.objectPath()
470 << " fileHandler : comm:" << comm
471 << " ioRanks:" << UPstream::procID(comm)
472 << exit(FatalIOError);
473 }
474
475 DynamicList<label> recvProcs(UPstream::nProcs(comm));
476 for (const int proci : UPstream::allProcs(comm))
477 {
478 if (readOnProcs[proci])
479 {
480 recvProcs.push_back(proci);
481 }
482 }
483
484 // Read on master and send to all processors
485 // (including master for simplicity)
486 if (debug)
487 {
488 Pout<< "masterUncollatedFileOperation::readStream :"
489 << " For uniform file " << filePaths[0]
490 << " sending to " << recvProcs
491 << " in comm:" << comm << endl;
492 }
493 readAndSend(filePaths[0], recvProcs, pBufs);
494 }
495 }
496 else
497 {
498 if (readOnProcs[0])
499 {
500 if (filePaths[0].empty())
501 {
502 FatalIOErrorInFunction(filePaths[0])
503 << "Cannot find file " << io.objectPath()
504 << " fileHandler : comm:" << comm
505 << " ioRanks:" << UPstream::procID(comm)
506 << exit(FatalIOError);
507 }
508
509 // Open master
510 isPtr.reset(new IFstream(filePaths[0]));
511
512 // Read header
513 if (!io.readHeader(*isPtr))
514 {
516 << "problem while reading header for object "
517 << io.name()
518 << " fileHandler : comm:" << comm
519 << " ioRanks:" << UPstream::procID(comm)
520 << exit(FatalIOError);
521 }
522 }
523
524 // Read sub-rank files
525 for (const int proci : UPstream::subProcs(comm))
526 {
527 if (debug)
528 {
529 Pout<< "masterUncollatedFileOperation::readStream :"
530 << " For processor " << proci
531 << " opening " << filePaths[proci] << endl;
532 }
533
534 const fileName& fPath = filePaths[proci];
535
536 if (readOnProcs[proci] && !fPath.empty())
537 {
538 // Note: handle compression ourselves since size cannot
539 // be determined without actually uncompressing
540 readAndSend(fPath, labelList(one{}, proci), pBufs);
541 }
542 }
543 }
544 }
545
546 pBufs.finishedScatters();
547
548 // isPtr will be valid on master and will be the unbuffered
549 // IFstream. Else the information is in the PstreamBuffers (and
550 // the special case of a uniform file)
551
552 if (!isPtr)
553 {
554 if (readOnProcs[UPstream::myProcNo(comm)])
555 {
556 // This processor needs to return something
557 List<char> buf(pBufs.recvDataCount(UPstream::masterNo()));
558
559 if (!buf.empty())
560 {
561 UIPstream is(UPstream::masterNo(), pBufs);
562 is.read(buf.data(), buf.size());
563 }
564
565 if (debug)
566 {
567 Pout<< "masterUncollatedFileOperation::readStream :"
568 << " Done reading " << buf.size() << " bytes" << endl;
569 }
570
571 // A local character buffer copy of the Pstream contents.
572 // Construct with same parameters (ASCII, current version)
573 // as the IFstream so that it has the same characteristics.
574
575 isPtr.reset(new ICharStream(std::move(buf)));
576
577 // With the proper file name
578 isPtr->name() = filePaths[UPstream::myProcNo(comm)];
579
580 if (!io.readHeader(*isPtr))
581 {
583 << "problem while reading header for object "
584 << io.name()
585 << " fileHandler : comm:" << comm
586 << " ioRanks:" << UPstream::procID(comm)
587 << exit(FatalIOError);
588 }
589 }
590 else
591 {
592 return dummyISstream::New();
593 }
594 }
595
596 return isPtr;
597}
598
600// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
601
602namespace Foam
603{
604
605// Construction helper: self/world/local communicator and IO ranks
607{
608 // Default is COMM_WORLD (single master)
609 Tuple2<label, labelList> commAndIORanks
610 (
613 );
614
615 if (UPstream::parRun() && commAndIORanks.second().size() > 1)
616 {
617 // Multiple masters: ranks for my IO range
618 commAndIORanks.first() = UPstream::newCommunicator
619 (
621 fileOperation::subRanks(commAndIORanks.second())
622 );
623 }
624
625 return commAndIORanks;
626}
627
628} // End namespace Foam
629
630
631// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
632
633void Foam::fileOperations::masterUncollatedFileOperation::init(bool verbose)
634{
635 verbose = (verbose && Foam::infoDetailLevel > 0);
636
637 if (verbose)
638 {
640 << "I/O : " << typeName
641 << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
642 << endl;
643 }
644
645 if (IOobject::fileModificationChecking == IOobject::timeStampMaster)
646 {
647 if (verbose)
648 {
650 << "Resetting fileModificationChecking to timeStamp" << endl;
651 }
652 IOobject::fileModificationChecking = IOobject::timeStamp;
653 }
654 else if (IOobject::fileModificationChecking == IOobject::inotifyMaster)
655 {
656 if (verbose)
657 {
659 << "Resetting fileModificationChecking to inotify"
661 }
663 }
664}
665
666
669(
670 bool verbose
671)
672:
673 fileOperation
674 (
675 getCommPattern()
676 ),
677 managedComm_(getManagedComm(comm_)) // Possibly locally allocated
678{
679 init(verbose);
680
681 if (comm_ == -1)
682 {
683 FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
684 }
685 if (UPstream::nProcs(comm_) == -1)
686 {
687 FatalErrorInFunction<< "Problem comm_:" << comm_
688 << " nProcs:" << UPstream::nProcs(comm_)
689 << exit(FatalError);
690 }
691 if (UPstream::myProcNo(comm_) == -1)
692 {
693 FatalErrorInFunction<< "Problem comm_:" << comm_
694 << " myProcNo:" << UPstream::myProcNo(comm_)
695 << exit(FatalError);
696 }
697}
698
699
702(
703 const Tuple2<label, labelList>& commAndIORanks,
704 const bool distributedRoots,
705 bool verbose
706)
707:
708 fileOperation(commAndIORanks, distributedRoots),
709 managedComm_(-1) // Externally managed
710{
711 init(verbose);
712
713 if (comm_ == -1)
714 {
715 FatalErrorInFunction<< "Problem comm_:" << comm_ << exit(FatalError);
716 }
717 if (UPstream::nProcs(comm_) == -1)
718 {
719 FatalErrorInFunction<< "Problem comm_:" << comm_
720 << " nProcs:" << UPstream::nProcs(comm_)
721 << exit(FatalError);
722 }
723 if (UPstream::myProcNo(comm_) == -1)
724 {
725 FatalErrorInFunction<< "Problem comm_:" << comm_
726 << " myProcNo:" << UPstream::myProcNo(comm_)
727 << exit(FatalError);
728 }
729}
730
731
733{
734 // From externally -> locally managed
735 managedComm_ = getManagedComm(comm_);
736}
737
738
739// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
740
744 UPstream::freeCommunicator(managedComm_);
745}
746
747
748// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
749
751(
752 const fileName& dir,
753 mode_t mode
754) const
755{
756 return masterOp<bool>
757 (
758 dir,
761 comm_
762 );
763}
764
765
767(
768 const fileName& fName,
769 mode_t mode
770) const
771{
772 return masterOp<bool>
773 (
774 fName,
777 comm_
778 );
779}
780
781
783(
784 const fileName& fName,
785 const bool followLink
786) const
787{
788 return masterOp<mode_t>
789 (
790 fName,
791 modeOp(followLink),
793 comm_
794 );
795}
796
797
799(
800 const fileName& fName,
801 const bool followLink
802) const
803{
804 return fileName::Type
805 (
806 masterOp<int>
807 (
808 fName,
809 typeOp(followLink),
811 comm_
812 )
813 );
814}
815
816
818(
819 const fileName& fName,
820 const bool checkGzip,
821 const bool followLink
822) const
823{
824 return masterOp<bool>
825 (
826 fName,
827 existsOp(checkGzip, followLink),
829 comm_
830 );
831}
832
833
835(
836 const fileName& fName,
837 const bool followLink
838) const
839{
840 return masterOp<bool>
841 (
842 fName,
843 isDirOp(followLink),
845 comm_
846 );
847}
848
849
851(
852 const fileName& fName,
853 const bool checkGzip,
854 const bool followLink
855) const
856{
857 return masterOp<bool>
858 (
859 fName,
860 isFileOp(checkGzip, followLink),
862 comm_
863 );
864}
865
866
868(
869 const fileName& fName,
870 const bool followLink
871) const
872{
873 // Reduce as int64_t instead of off_t to avoid missing
874 // pTraits<long int> (or other ambiguities) on Mingw and Linux i586
875
876 return off_t
877 (
878 masterOp<int64_t>
879 (
880 fName,
881 fileSizeOp(followLink),
883 comm_
884 )
885 );
886}
887
888
890(
891 const fileName& fName,
892 const bool followLink
893) const
894{
895 // time_t is invariably an integer type, but verify that anyhow
896 // before doing the following:
897
898 if constexpr (std::is_integral_v<time_t>)
899 {
900 // Reduce as int64_t instead of time_t to avoid missing
901 // pTraits<long int> (or other ambiguities) on Linux i586
902 return time_t
903 (
904 masterOp<int64_t>
905 (
906 fName,
907 lastModifiedOp(followLink),
910 )
911 );
912 }
913 else
914 {
915 return masterOp<time_t>
916 (
917 fName,
918 lastModifiedOp(followLink),
921 );
922 }
923}
924
925
927(
928 const fileName& fName,
929 const bool followLink
930) const
931{
932 return masterOp<double>
933 (
934 fName,
938 );
939}
940
941
943(
944 const fileName& fName,
945 const std::string& ext
946) const
947{
948 return masterOp<bool>
949 (
950 fName,
953 comm_
954 );
955}
956
957
959(
960 const fileName& fName
961) const
962{
963 return masterOp<bool>
964 (
965 fName,
968 comm_
969 );
970}
971
972
974(
975 const fileName& dir,
976 const bool silent,
977 const bool emptyOnly
978) const
979{
980 return masterOp<bool>
981 (
982 dir,
983 rmDirOp(silent, emptyOnly),
985 comm_
986 );
987}
988
989
991(
992 const fileName& dir,
993 const fileName::Type type,
994 const bool filtergz,
995 const bool followLink
996) const
997{
998 return masterOp<fileNameList>
999 (
1000 dir,
1001 readDirOp(type, filtergz, followLink),
1003 comm_
1004 );
1005}
1006
1007
1009(
1010 const fileName& src,
1011 const fileName& dst,
1012 const bool followLink
1013) const
1014{
1015 return masterOp<bool>
1016 (
1017 src,
1018 dst,
1019 cpOp(followLink),
1021 comm_
1022 );
1023}
1024
1025
1027(
1028 const fileName& src,
1029 const fileName& dst
1030) const
1031{
1032 return masterOp<bool>
1033 (
1034 src,
1035 dst,
1038 comm_
1039 );
1040}
1041
1042
1044(
1045 const fileName& src,
1046 const fileName& dst,
1047 const bool followLink
1048) const
1049{
1050 return masterOp<bool>
1051 (
1052 src,
1053 dst,
1054 mvOp(followLink),
1057 );
1058}
1059
1060
1061// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1062
1064(
1065 const bool checkGlobal,
1066 const IOobject& io,
1067 const word& typeName,
1068 const bool search
1069) const
1070{
1071 if (debug)
1072 {
1073 Pout<< "masterUncollatedFileOperation::filePath :"
1074 << " objectPath:" << io.objectPath()
1075 << " checkGlobal:" << checkGlobal
1076 << " parRun:" << Pstream::parRun()
1077 << " localmaster:" << Pstream::master(comm_) << endl;
1078 }
1079
1080 // Now that we have an IOobject path use it to detect & cache
1081 // processor directory naming
1082 const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1083
1084 // Trigger caching of times
1085 if (cacheLevel() > 0)
1086 {
1087 (void)findTimes(io.time().path(), io.time().constant());
1088 }
1089
1090 // Determine master filePath and scatter
1091
1092 fileName objPath;
1093 pathType searchType = NOTFOUND;
1094 word procsDir;
1095 word newInstancePath;
1096
1097 if (Pstream::master(comm_))
1098 {
1099 const bool oldParRun = UPstream::parRun(false);
1100 const int oldCache = fileOperation::cacheLevel(0);
1101 const label oldNProcs = fileOperation::nProcs();
1102
1103 // All masters search locally. Note that global objects might
1104 // fail (except on master). This gets handled later on (in PARENTOBJECT)
1105 objPath =
1106 filePathInfo
1107 (
1108 checkGlobal,
1109 true,
1110 io,
1111 pDirs,
1112 search,
1113 searchType,
1114 procsDir,
1115 newInstancePath
1116 );
1117
1118 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1119 fileOperation::cacheLevel(oldCache);
1120 UPstream::parRun(oldParRun);
1121
1122 if (debug)
1123 {
1124 Pout<< "masterUncollatedFileOperation::filePath :"
1125 << " master objPath:" << objPath
1126 << " searchType:" << fileOperation::pathTypeNames_[searchType]
1127 << " procsDir:" << procsDir << " instance:" << newInstancePath
1128 << endl;
1129 }
1130 }
1131
1132 // Broadcast information about where the master found the object
1133 // Note: use the worldComm to make sure all processors decide
1134 // the same type. Only procsDir is allowed to differ; searchType
1135 // and instance have to be same
1136 if (UPstream::parRun())
1137 {
1138 int masterType(searchType);
1139 Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1140 searchType = pathType(masterType);
1141 }
1142
1143 if
1144 (
1145 checkGlobal
1146 || searchType == fileOperation::PARENTOBJECT
1147 || searchType == fileOperation::PROCBASEOBJECT
1148 || searchType == fileOperation::PROCBASEINSTANCE
1149 || io.local() == "uniform"
1150 )
1151 {
1152 // Distribute master path. This makes sure it is seen as uniform
1153 // and only gets read from the master.
1154 Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1155 }
1156 else
1157 {
1158 Pstream::broadcast(procsDir, comm_);
1159
1160 // Use the master type to determine if additional information is
1161 // needed to construct the local equivalent
1162 switch (searchType)
1163 {
1167 {
1168 // Already handled above
1169 }
1170 break;
1171
1179 {
1180 // Construct equivalent local path
1181 objPath = localObjectPath
1182 (
1183 io,
1184 searchType,
1185 procsDir,
1186 newInstancePath
1187 );
1188 }
1189 break;
1190
1193 {
1194 // Retest all processors separately since some processors might
1195 // have the file and some not (e.g. lagrangian data)
1196
1197 objPath = masterOp<fileName>
1198 (
1199 io.objectPath(),
1200 fileOrNullOp(true), // isFile=true
1202 comm_
1203 );
1204 }
1205 break;
1206 }
1207 }
1208
1209 if (debug)
1210 {
1211 Pout<< "masterUncollatedFileOperation::filePath :"
1212 << " Returning from file searching using type "
1213 << fileOperation::pathTypeNames_[searchType] << endl
1214 << " objectPath:" << io.objectPath() << endl
1215 << " filePath :" << objPath << endl << endl;
1216 }
1217 return objPath;
1218}
1219
1220
1222(
1223 const bool checkGlobal,
1224 const IOobject& io,
1225 const bool search
1226) const
1227{
1228 if (debug)
1229 {
1230 Pout<< "masterUncollatedFileOperation::dirPath :"
1231 << " objectPath:" << io.objectPath()
1232 << " checkGlobal:" << checkGlobal
1233 << " parRun:" << Pstream::parRun()
1234 << " localmaster:" << Pstream::master(comm_) << endl;
1235 }
1236
1237 // Now that we have an IOobject path use it to detect & cache
1238 // processor directory naming
1239 const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1240
1241 // Trigger caching of times
1242 if (cacheLevel() > 0)
1243 {
1244 (void)findTimes(io.time().path(), io.time().constant());
1245 }
1246
1247 // Determine master dirPath and broadcast
1248
1249 fileName objPath;
1250 pathType searchType = NOTFOUND;
1251 word procsDir;
1252 word newInstancePath;
1253
1254 // Local IO node searches for file
1255 if (Pstream::master(comm_))
1256 {
1257 const bool oldParRun = UPstream::parRun(false);
1258 const int oldCache = fileOperation::cacheLevel(0);
1259 const label oldNProcs = fileOperation::nProcs();
1260
1261 objPath = filePathInfo
1262 (
1263 checkGlobal,
1264 false,
1265 io,
1266 pDirs,
1267 search,
1268 searchType,
1269 procsDir,
1270 newInstancePath
1271 );
1272
1273 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1274 fileOperation::cacheLevel(oldCache);
1275 UPstream::parRun(oldParRun);
1276
1277 if (debug)
1278 {
1279 Pout<< "masterUncollatedFileOperation::dirPath :"
1280 << " master objPath:" << objPath
1281 << " searchType:" << fileOperation::pathTypeNames_[searchType]
1282 << " procsDir:" << procsDir << " instance:" << newInstancePath
1283 << endl;
1284 }
1285 }
1286
1287
1288 // Broadcast information about where the master found the object
1289 // Note: use the worldComm to make sure all processors decide
1290 // the same type. Only procsDir is allowed to differ; searchType
1291 // and instance have to be same
1292 if (UPstream::parRun())
1293 {
1294 int masterType(searchType);
1295 Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1296 searchType = pathType(masterType);
1297 }
1298
1299
1300 if
1301 (
1302 checkGlobal
1303 || searchType == fileOperation::PARENTOBJECT
1304 || searchType == fileOperation::PROCBASEOBJECT
1305 || searchType == fileOperation::PROCBASEINSTANCE
1306 || io.local() == "uniform"
1307 )
1308 {
1309 // Distribute master path. This makes sure it is seen as uniform
1310 // and only gets read from the master.
1311 Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1312 }
1313 else
1314 {
1315 // Broadcast local processors dir amongst all local nodes
1316 Pstream::broadcast(procsDir, comm_);
1317
1318 // Use the master type to determine if additional information is
1319 // needed to construct the local equivalent
1320 switch (searchType)
1321 {
1325 {
1326 // Already handled above
1327 }
1328 break;
1329
1337 {
1338 // Construct equivalent local path
1339 objPath = localObjectPath
1340 (
1341 io,
1342 searchType,
1343 procsDir,
1344 newInstancePath
1345 );
1346 }
1347 break;
1348
1351 {
1352 // Retest all processors separately since some processors might
1353 // have the file and some not (e.g. lagrangian data)
1354
1355 objPath = masterOp<fileName>
1356 (
1357 io.objectPath(),
1358 fileOrNullOp(false), // isFile=false
1360 comm_
1361 );
1362 }
1363 break;
1364 }
1365 }
1366
1367 if (debug)
1368 {
1369 Pout<< "masterUncollatedFileOperation::dirPath :"
1370 << " Returning from directory searching using type "
1371 << fileOperation::pathTypeNames_[searchType] << endl
1372 << " objectPath:" << io.objectPath() << endl
1373 << " filePath :" << objPath << endl << endl;
1374 }
1375 return objPath;
1376}
1377
1378
1380(
1381 const dirIndexList& pDirs,
1382 IOobject& io
1383) const
1384{
1385 // Cut-down version of filePathInfo that does not look for
1386 // different instance or parent directory
1387
1388 const bool isFile = !io.name().empty();
1389
1390 // Generate output filename for object
1391 const fileName writePath(objectPath(io, word::null));
1392
1393 // 1. Test writing name for either directory or a (valid) file
1394 if (isFileOrDir(isFile, writePath))
1395 {
1396 return true;
1397 }
1398
1399 // 2. Check processors/
1400 if (io.time().processorCase())
1401 {
1402 for (const dirIndex& dirIdx : pDirs)
1403 {
1404 const fileName& pDir = dirIdx.first();
1405 fileName procPath =
1406 processorsPath(io, io.instance(), pDir)
1407 /io.name();
1408 if (procPath != writePath && isFileOrDir(isFile, procPath))
1409 {
1410 return true;
1411 }
1412 }
1413 }
1414
1415 // 3. Check local
1416 fileName localPath = io.objectPath();
1417
1418 if (localPath != writePath && isFileOrDir(isFile, localPath))
1419 {
1420 return true;
1422
1423 return false;
1424}
1425
1426
1429(
1430 const IOobject& startIO,
1431 const scalar startValue,
1432 const word& stopInstance,
1433 const bool constant_fallback
1434) const
1435{
1436 if (debug)
1437 {
1438 Pout<< "masterUncollatedFileOperation::findInstance :"
1439 << " Starting searching for name:" << startIO.name()
1440 << " local:" << startIO.local()
1441 << " from instance:" << startIO.instance()
1442 << endl;
1443 }
1444
1445 const Time& time = startIO.time();
1446 IOobject io(startIO);
1447
1448 // Note: - if name is empty, just check the directory itself
1449 // - check both for isFile and headerOk since the latter does a
1450 // filePath so searches for the file.
1451 // - check for an object with local file scope (so no looking up in
1452 // parent directory in case of parallel)
1453
1454
1455 const refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1456
1457 word foundInstance;
1458
1459 // if (Pstream::master(comm_))
1461 {
1462 const bool oldParRun = UPstream::parRun(false);
1463 const int oldCache = fileOperation::cacheLevel(0);
1464 const label oldNProcs = fileOperation::nProcs();
1465
1466 if (exists(pDirs, io))
1467 {
1468 foundInstance = io.instance();
1469 }
1470 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1471 fileOperation::cacheLevel(oldCache);
1472 UPstream::parRun(oldParRun);
1473 }
1474
1475
1476 // Do parallel early exit to avoid calling time.times()
1478
1479 if (!foundInstance.empty())
1480 {
1481 io.instance() = foundInstance;
1482 if (debug)
1483 {
1484 Pout<< "masterUncollatedFileOperation::findInstance :"
1485 << " for name:" << io.name() << " local:" << io.local()
1486 << " found starting instance:" << io.instance() << endl;
1487 }
1488 return io;
1489 }
1490
1491
1492 // Handling failures afterwards
1493 const bool exitIfMissing = startIO.isReadRequired();
1494
1495 enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1496 int failed(0);
1497
1498 // The timeDirs
1499 instantList ts
1500 (
1501 this->findTimes
1502 (
1503 time.path(), // time.path(layout)
1504 time.constant()
1505 )
1506 );
1507
1508 // if (Pstream::master(comm_))
1510 {
1511 const bool oldParRun = UPstream::parRun(false);
1512 const int oldCache = fileOperation::cacheLevel(0);
1513 const label oldNProcs = fileOperation::nProcs();
1514
1515 label instIndex = ts.size()-1;
1516
1517 // Backward search for first time that is <= startValue
1518 for (; instIndex >= 0; --instIndex)
1519 {
1520 if (ts[instIndex] <= startValue)
1521 {
1522 break;
1523 }
1524 }
1525
1526 // Continue (forward) searching from here
1527 for (; instIndex >= 0; --instIndex)
1528 {
1529 // Shortcut: if actual directory is the timeName we've
1530 // already tested it
1531 if (ts[instIndex].name() == time.timeName())
1532 {
1533 continue;
1534 }
1535
1536 io.instance() = ts[instIndex].name();
1537 if (exists(pDirs, io))
1538 {
1539 foundInstance = io.instance();
1540 if (debug)
1541 {
1542 Pout<< "masterUncollatedFileOperation::findInstance :"
1543 << " for name:" << io.name() << " local:" << io.local()
1544 << " found at:" << io.instance()
1545 << endl;
1546 }
1547 break;
1548 }
1549
1550 // Check if hit minimum instance
1551 if (io.instance() == stopInstance)
1552 {
1553 if (debug)
1554 {
1555 Pout<< "masterUncollatedFileOperation::findInstance :"
1556 << " name:" << io.name()
1557 << " local:" << io.local()
1558 << " at stop-instance:" << io.instance() << endl;
1559 }
1560
1561 if (exitIfMissing)
1562 {
1563 failed = failureCodes::FAILED_STOPINST;
1564 }
1565 else
1566 {
1567 // At the stopInstance
1568 foundInstance = io.instance();
1569 }
1570 break;
1571 }
1572 }
1573
1574
1575 // times() usually already includes the constant() so would
1576 // have been checked above. However, re-test under these conditions:
1577 // - times() is empty. Sometimes this can happen (e.g. decomposePar
1578 // with collated)
1579 // - times()[0] is not constant
1580 // - Times is empty.
1581 // Sometimes this can happen (eg, decomposePar with collated)
1582 // - Times[0] is not constant
1583 // - The startValue is negative (eg, kivaTest).
1584 // This plays havoc with the reverse search, causing it to miss
1585 // 'constant'
1586
1587 if
1588 (
1589 !failed && foundInstance.empty()
1590 && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1591 )
1592 {
1593 // Note. This needs to be a hard-coded "constant" (not constant
1594 // function of Time), because the latter points to
1595 // the case constant directory in parallel cases.
1596 // However, parRun is disabled so they are actually the same.
1597
1598 io.instance() = time.constant();
1599
1600 if (exists(pDirs, io))
1601 {
1602 if (debug)
1603 {
1604 Pout<< "masterUncollatedFileOperation::findInstance :"
1605 << " name:" << io.name()
1606 << " local:" << io.local()
1607 << " at:" << io.instance() << endl;
1608 }
1609 foundInstance = io.instance();
1610 }
1611 }
1612
1613 if (!failed && foundInstance.empty())
1614 {
1615 if (exitIfMissing)
1616 {
1617 failed = failureCodes::FAILED_CONSTINST;
1618 }
1619 else if (constant_fallback)
1620 {
1621 foundInstance = time.constant();
1622 }
1623 else
1624 {
1625 foundInstance.clear();
1626 }
1627 }
1628
1629 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1630 fileOperation::cacheLevel(oldCache);
1631 UPstream::parRun(oldParRun); // Restore parallel state
1632 }
1633
1635
1636 io.instance() = foundInstance;
1637
1638
1639 // Handle failures
1640 // ~~~~~~~~~~~~~~~
1641 if (failed)
1642 {
1643 FatalErrorInFunction << "Cannot find";
1644
1645 if (!io.name().empty())
1646 {
1648 << " file \"" << io.name() << "\" in";
1649 }
1650
1652 << " directory "
1653 << io.local() << " in times "
1654 << startIO.instance() << " down to ";
1655
1656 if (failed == failureCodes::FAILED_STOPINST)
1657 {
1658 FatalError << stopInstance;
1659 }
1660 else // FAILED_CONSTINST
1661 {
1662 FatalError << "constant";
1663 }
1665 }
1666
1667 if (debug)
1668 {
1669 Pout<< "masterUncollatedFileOperation::findInstance :"
1670 << " name:" << io.name() << " local:" << io.local()
1671 << " returning instance:" << io.instance() << endl;
1672 }
1673 return io;
1674}
1675
1676
1679(
1680 const objectRegistry& db,
1681 const fileName& instance,
1682 const fileName& local,
1683 word& newInstance
1684) const
1685{
1686 if (debug)
1687 {
1688 Pout<< "masterUncollatedFileOperation::readObjects :"
1689 << " db:" << db.objectPath()
1690 << " local:" << local << " instance:" << instance << endl;
1691 }
1692
1693 fileNameList objectNames;
1694 newInstance.clear();
1695
1696 // Note: readObjects uses WORLD to make sure order of objects is the
1697 // same everywhere
1698
1700 {
1701 // Avoid fileOperation::readObjects from triggering parallel ops
1702 // (through call to filePath which triggers parallel )
1703 const bool oldParRun = UPstream::parRun(false);
1704 const int oldCache = fileOperation::cacheLevel(0);
1705 const label oldNProcs = fileOperation::nProcs();
1706
1707 //- Use non-time searching version
1708 objectNames = fileOperation::readObjects
1709 (
1710 db,
1711 instance,
1712 local,
1713 newInstance
1714 );
1715
1716 if (newInstance.empty())
1717 {
1718 // Find similar time
1719
1720 // Copy of Time::findInstancePath. We want to avoid the
1721 // parallel call to findTimes.
1722 const instantList timeDirs
1723 (
1725 (
1726 db.time().path(),
1727 db.time().constant()
1728 )
1729 );
1730
1731 fileName foundInst
1732 (
1733 Time::findInstancePath(timeDirs, instant(instance))
1734 );
1735
1736 if (!foundInst.empty())
1737 {
1738 objectNames = fileOperation::readObjects
1739 (
1740 db,
1741 foundInst, // newly found time
1742 local,
1743 newInstance
1744 );
1745 }
1746 }
1747
1748 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
1749 fileOperation::cacheLevel(oldCache);
1750 UPstream::parRun(oldParRun); // Restore parallel state
1751 }
1752
1753 Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1754
1755 if (debug)
1756 {
1757 Pout<< "masterUncollatedFileOperation::readObjects :"
1758 << " newInstance:" << newInstance
1759 << " objectNames:" << objectNames << endl;
1760 }
1762 return objectNames;
1763}
1764
1765
1767(
1768 IOobject& io,
1769 const fileName& fName,
1770 const word& typeName
1771) const
1772{
1773 bool ok = false;
1774
1775 if (debug)
1776 {
1777 Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1778 << " objectPath:" << io.objectPath() << endl
1779 << " filePath :" << fName << endl;
1780 }
1781
1782 // We assume if filePath is the same
1783 // - headerClassName
1784 // - note
1785 // are also the same, independent of where the file came from.
1786
1787 // Get filePaths on world master
1789 filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
1791
1792 bool uniform
1793 (
1795 && fileOperation::uniformFile(filePaths)
1796 );
1797
1799
1800 if (uniform)
1801 {
1803 {
1804 if (!fName.empty())
1805 {
1806 IFstream is(fName);
1807
1808 if (is.good())
1809 {
1810 // Regular header or from decomposed data
1812 }
1813 }
1814 }
1815
1817 (
1819 ok,
1820 io.headerClassName(),
1821 io.note()
1822 );
1823 }
1824 else
1825 {
1827 {
1828 // Assume if different nprocs the communicators are also
1829 // different. Re-gather file paths on local master
1830 filePaths.resize(UPstream::nProcs(comm_));
1831 filePaths[UPstream::myProcNo(comm_)] = fName;
1832 Pstream::gatherList(filePaths, UPstream::msgType(), comm_);
1833 }
1834
1835 // Intermediate storage arrays (master only)
1836 boolList result;
1837 wordList headerClassName;
1838 stringList note;
1839
1840 if (Pstream::master(comm_))
1841 {
1842 const label np = Pstream::nProcs(comm_);
1843
1844 result.resize(np, false);
1845 headerClassName.resize(np);
1846 note.resize(np);
1847
1848 forAll(filePaths, proci)
1849 {
1850 if (!filePaths[proci].empty())
1851 {
1852 if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1853 {
1854 result[proci] = result[proci-1];
1855 headerClassName[proci] = headerClassName[proci-1];
1856 note[proci] = note[proci-1];
1857 }
1858 else
1859 {
1860 IFstream is(filePaths[proci]);
1861
1862 if (is.good())
1863 {
1864 result[proci] =
1866 headerClassName[proci] = io.headerClassName();
1867 note[proci] = io.note();
1868 }
1869 }
1870 }
1871 }
1872 }
1873
1874 // Is a more efficient scatter possible?
1875 PstreamBuffers pBufs(comm_);
1876
1877 if (Pstream::master(comm_))
1878 {
1879 ok = result[0];
1880 io.headerClassName() = headerClassName[0];
1881 io.note() = note[0];
1882
1883 // Scatter to each proc
1884 for (const int proci : pBufs.subProcs())
1885 {
1886 UOPstream os(proci, pBufs);
1887 os << result[proci] << headerClassName[proci] << note[proci];
1888 }
1889 }
1890
1891 pBufs.finishedScatters();
1892
1893 if (!Pstream::master(comm_))
1894 {
1895 UIPstream is(Pstream::masterNo(), pBufs);
1896 is >> ok >> io.headerClassName() >> io.note();
1897 }
1898 }
1899
1900 if (debug)
1901 {
1902 Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1903 << " class:" << io.headerClassName()
1904 << " for file:" << fName << endl;
1905 }
1906 return ok;
1907}
1908
1909
1912(
1913 regIOobject& io,
1914 const fileName& fName,
1915 const word& typeName,
1916 const bool readOnProc
1917) const
1918{
1919 if (debug)
1920 {
1921 Pout<< "masterUncollatedFileOperation::readStream :"
1922 << " object : " << io.name()
1923 << " global : " << io.global()
1924 << " globalObject : " << io.globalObject()
1925 << " fName : " << fName << " readOnProc:" << readOnProc << endl;
1926 }
1927
1928 // Close old stream
1929 io.close();
1930
1931 autoPtr<ISstream> isPtr;
1932 bool isCollated = false;
1933 IOobject headerIO(io);
1934
1935 // Detect collated format. This could be done on the local communicator
1936 // but we do it on the master node only for now.
1938 {
1939 if (!fName.empty())
1940 {
1941 // This can happen in lagrangian field reading some processors
1942 // have no file to read from. This will only happen when using
1943 // normal writing since then the fName for the valid processors is
1944 // processorDDD/<instance>/.. . In case of collocated writing
1945 // the fName is already rewritten to processorsNN/.
1946
1947 isPtr.reset(new IFstream(fName));
1948
1949 if (isPtr->good())
1950 {
1951 // Read header data (on copy)
1952 headerIO.readHeader(*isPtr);
1953
1954 isCollated = decomposedBlockData::isCollatedType(headerIO);
1955
1956 if (!isCollated && !Pstream::parRun())
1957 {
1958 // Short circuit: non-collated format. No parallel bits.
1959 // Copy header and return.
1960 if (debug)
1961 {
1962 Pout<< "masterUncollatedFileOperation::readStream :"
1963 << " For object : " << io.name()
1964 << " doing straight IFstream input from "
1965 << fName << endl;
1966 }
1967
1968 // Copy IOobject header information
1969 io.IOobject::operator=(headerIO);
1970 return isPtr;
1971 }
1972 }
1973
1974 if (!isCollated)
1975 {
1976 // Close file. Reopened below.
1977 isPtr.clear();
1978 }
1979 }
1980 }
1981
1983
1984 if (isCollated)
1985 {
1986 if (debug)
1987 {
1988 Pout<< "masterUncollatedFileOperation::readStream :"
1989 << " For object : " << io.name()
1990 << " starting collating input from " << fName << endl;
1991 }
1992
1993
1994 // Analyse the file path (on (co)master) to see the processors type
1995 // Note: this should really be part of filePath() which should return
1996 // both file and index in file.
1997
1998 procRangeType group;
2000
2001
2002 if (!UPstream::parRun())
2003 {
2004 // Analyse the objectpath to find out the processor we're trying
2005 // to access
2006 label proci = fileOperation::detectProcessorPath(io.objectPath());
2007
2008 if (proci == -1)
2009 {
2011 << "Could not detect processor number"
2012 << " from objectPath:" << io.objectPath()
2013 << " fileHandler : comm:" << comm_
2014 << " ioRanks:" << flatOutput(ioRanks_)
2015 << exit(FatalIOError);
2016 }
2017
2018 // The local rank (offset)
2019 if (!group.empty())
2020 {
2021 proci -= group.start();
2022 }
2023
2024 if (debug)
2025 {
2026 Pout<< "masterUncollatedFileOperation::readStream :"
2027 << " For object : " << io.name()
2028 << " starting input from block " << proci
2029 << " of " << isPtr->name() << endl;
2030 }
2031
2032 return decomposedBlockData::readBlock(proci, *isPtr, io);
2033 }
2034 else
2035 {
2036 // Are we reading from single-master file ('processors256') or
2037 // from multi-master files ('processors256_0-9')
2038 label readComm = -1;
2039 if (!group.empty())
2040 {
2041 readComm = comm_;
2042 if (UPstream::master(comm_) && !isPtr && !fName.empty())
2043 {
2044 // In multi-master mode also open the file on the other
2045 // masters
2046 isPtr.reset(new IFstream(fName));
2047
2048 if (isPtr->good())
2049 {
2050 // Read header data (on copy)
2051 IOobject headerIO(io);
2052 headerIO.readHeader(*isPtr);
2053 }
2054 }
2055 }
2056 else
2057 {
2058 // Single master so read on world
2059 readComm = UPstream::worldComm;
2060 }
2061
2062 // Get size of file to determine communications type
2063 bool bigSize = false;
2064
2066 {
2067 // TBD: handle multiple masters?
2068 bigSize =
2069 (
2070 off_t(Foam::fileSize(fName))
2071 > off_t(maxMasterFileBufferSize)
2072 );
2073 }
2074 // Reduce (not broadcast)
2075 // - if we have multiple master files (FUTURE)
2077
2078 const UPstream::commsTypes myCommsType
2079 (
2080 bigSize
2083 );
2084
2085 // Read my data
2087 (
2088 readComm,
2089 fName,
2090 isPtr,
2091 io,
2092 myCommsType
2093 );
2094 }
2095 }
2096 else
2097 {
2098 if (debug)
2099 {
2100 Pout<< "masterUncollatedFileOperation::readStream :"
2101 << " For object : " << io.name()
2102 << " starting separated input from " << fName << endl;
2103 }
2104
2105 if (io.global() || io.globalObject())
2106 {
2107 // Use worldComm. Note: should not really need to gather filePaths
2108 // since we enforce sending from master anyway ...
2110 filePaths[UPstream::myProcNo(UPstream::worldComm)] = fName;
2112 (
2113 filePaths,
2116 );
2117
2118 boolList readOnProcs
2119 (
2121 (
2122 readOnProc,
2124 )
2125 );
2126 // NB: local proc validity information required on sub-ranks too!
2127 readOnProcs.resize(UPstream::nProcs(UPstream::worldComm));
2128 readOnProcs[UPstream::myProcNo(UPstream::worldComm)] = readOnProc;
2129
2130 // Uniform in local comm
2131 return read(io, UPstream::worldComm, true, filePaths, readOnProcs);
2132 }
2133 else
2134 {
2135 // Use local communicator
2136 fileNameList filePaths(UPstream::nProcs(comm_));
2137 filePaths[UPstream::myProcNo(comm_)] = fName;
2139 (
2140 filePaths,
2142 comm_
2143 );
2144
2145 boolList readOnProcs
2146 (
2148 (
2149 readOnProc,
2150 comm_
2151 )
2152 );
2153 // NB: local proc validity information required on sub-ranks too!
2154 readOnProcs.resize(UPstream::nProcs(comm_));
2155 readOnProcs[UPstream::myProcNo(comm_)] = readOnProc;
2156
2157 // Uniform in local comm
2158 const bool uniform = fileOperation::uniformFile(filePaths);
2159
2160 return read(io, comm_, uniform, filePaths, readOnProcs);
2162 }
2163}
2164
2165
2167(
2168 regIOobject& io,
2169 const bool masterOnly,
2171 const word& typeName
2172) const
2173{
2174 bool ok = true;
2175
2176 if (io.global() || io.globalObject())
2177 {
2178 if (debug)
2179 {
2180 Pout<< "masterUncollatedFileOperation::read :"
2181 << " Reading global object " << io.name()
2182 << " worldComm:" << UPstream::worldComm
2183 << " Pstream::myProcNo:"
2185 << " amMaster:" << Pstream::master(UPstream::worldComm)
2186 << endl;
2187 }
2188
2190 {
2191 // Do master-only reading always.
2192 const bool oldParRun = UPstream::parRun(false);
2193 const int oldCache = fileOperation::cacheLevel(0);
2194 const label oldNProcs = fileOperation::nProcs();
2195
2196 auto& is = io.readStream(typeName);
2197 ok = io.readData(is);
2198 io.close();
2199
2200 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2201 fileOperation::cacheLevel(oldCache);
2202 UPstream::parRun(oldParRun); // Restore parallel state
2203 }
2204
2205 // Broadcast regIOobject content, with writeData/readData handling
2206 if (UPstream::parRun())
2207 {
2209 {
2210 OPBstream os(UPstream::worldComm, format);
2211
2212 os << io.headerClassName() << io.note();
2213 bool okWrite = io.writeData(os);
2214 ok = ok && okWrite;
2215 }
2216 else
2217 {
2218 IPBstream is(UPstream::worldComm, format);
2219
2220 is >> io.headerClassName() >> io.note();
2221 ok = io.readData(is);
2222 }
2223 }
2224 }
2225 else
2226 {
2227 if (debug)
2228 {
2229 Pout<< "masterUncollatedFileOperation::read :"
2230 << " Reading local object " << io.name() << endl;
2231 }
2232
2233 ok = io.readData(io.readStream(typeName));
2234 io.close();
2235 }
2236
2237 if (debug)
2238 {
2239 Pout<< "masterUncollatedFileOperation::read :"
2240 << " Read object:" << io.name()
2241 << " isGlobal:" << (io.global() || io.globalObject())
2242 << " status:" << ok << endl;
2243 }
2245 return ok;
2246}
2247
2248
2250(
2251 const regIOobject& io,
2252 IOstreamOption streamOpt,
2253 const bool writeOnProc
2254) const
2255{
2256 fileName pathName(io.objectPath());
2257
2258 if (debug)
2259 {
2260 Pout<< "masterUncollatedFileOperation::writeObject :"
2261 << " io:" << pathName << " writeOnProc:" << writeOnProc << endl;
2262 }
2263
2264 // Make sure to pick up any new times
2265 setTime(io.time());
2266
2267 // Update meta-data for current state
2268 const_cast<regIOobject&>(io).updateMetaData();
2269
2270 autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, writeOnProc));
2271 OSstream& os = *osPtr;
2272
2273 // If any of these fail, return (leave error handling to Ostream class)
2274
2275 const bool ok =
2276 (
2277 os.good()
2278 && io.writeHeader(os)
2279 && io.writeData(os)
2280 );
2281
2282 if (ok)
2283 {
2285 }
2287 return ok;
2288}
2289
2290
2292(
2293 const fileName& directory,
2294 const word& constantName
2295) const
2296{
2297 if (const auto* instPtr = times_.get(directory); instPtr)
2298 {
2299 if (debug)
2300 {
2301 Pout<< "masterUncollatedFileOperation::findTimes :"
2302 << " Found " << instPtr->size() << " cached times" << nl
2303 << " for directory:" << directory << endl;
2304 }
2305 return *instPtr;
2306 }
2307 else
2308 {
2309 instantList times;
2311 {
2312 // Do master-only reading always.
2313 const bool oldParRun = UPstream::parRun(false);
2314 const int oldCache = fileOperation::cacheLevel(0);
2315 const label oldNProcs = fileOperation::nProcs();
2316
2317 times = fileOperation::findTimes(directory, constantName);
2318
2319 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2320 fileOperation::cacheLevel(oldCache);
2321 UPstream::parRun(oldParRun); // Restore parallel state
2322 }
2323
2325
2326 if (debug)
2327 {
2328 Pout<< "masterUncollatedFileOperation::findTimes :"
2329 << " Found times:" << flatOutput(times) << nl
2330 << " for directory:" << directory << endl;
2331 }
2332
2333 // Caching
2334 // - cache values even if no times were found since it might
2335 // indicate a directory that is being filled later on ...
2336 if (cacheLevel() > 0)
2337 {
2338 auto* tPtr = new DynamicList<instant>(std::move(times));
2339 times_.set(directory, tPtr);
2340
2341 return *tPtr;
2342 }
2343
2344 // Times found (not cached)
2345 return times;
2346 }
2347}
2348
2349
2351(
2352 const Time& tm
2353) const
2354{
2355 if (tm.subCycling())
2356 {
2357 return;
2358 }
2359
2360 // Mutable access to instant list for modification and sorting
2361 // - cannot use auto type deduction here
2362
2363 if (auto iter = times_.find(tm.path()); iter.good())
2364 {
2365 DynamicList<instant>& times = *(iter.val());
2366
2367 const instant timeNow(tm.value(), tm.timeName());
2368
2369 // The start index for checking and sorting (excluding "constant")
2370 const label startIdx =
2371 (
2372 (times.empty() || times[0].name() != tm.constant())
2373 ? 0
2374 : 1
2375 );
2376
2377 // This routine always results in a sorted list of times, so first
2378 // check if the new time is greater than the latest existing time.
2379 // Can then simply append without extra searching or sorting
2380
2381 if (times.size() <= startIdx || times.last() < timeNow)
2382 {
2383 times.push_back(timeNow);
2384 }
2385 else if (findSortedIndex(times, timeNow, startIdx) < 0)
2386 {
2387 if (debug)
2388 {
2389 Pout<< "masterUncollatedFileOperation::setTime :"
2390 << " Caching time " << tm.timeName()
2391 << " for case:" << tm.path() << endl;
2392 }
2393
2394 times.push_back(timeNow);
2395
2396 auto realTimes = times.slice(startIdx);
2397 Foam::stableSort(realTimes);
2398 }
2399 }
2400
2402}
2403
2404
2407(
2408 const fileName& filePath
2409) const
2410{
2411 autoPtr<ISstream> isPtr;
2412
2413 if (Pstream::parRun())
2414 {
2415 // Insert logic of filePath. We assume that if a file is absolute
2416 // on the master it is absolute also on the sub-ranks etc.
2417
2418 fileNameList filePaths(Pstream::nProcs(comm_));
2419 filePaths[Pstream::myProcNo(comm_)] = filePath;
2420 Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2421
2422 PstreamBuffers pBufs(comm_);
2423
2424 if (Pstream::master(comm_))
2425 {
2426 // Same filename on the IO node -> same file
2427 const bool uniform = fileOperation::uniformFile(filePaths);
2428
2429 if (uniform)
2430 {
2431 if (debug)
2432 {
2433 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2434 << " Opening global file " << filePath << endl;
2435 }
2436
2437 readAndSend
2438 (
2439 filePath,
2440 identity(Pstream::nProcs(comm_)-1, 1),
2441 pBufs
2442 );
2443 }
2444 else
2445 {
2446 for (const int proci : Pstream::subProcs(comm_))
2447 {
2448 if (debug)
2449 {
2450 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2451 << " Opening local file " << filePath
2452 << " for rank " << proci << endl;
2453 }
2454
2455 readAndSend
2456 (
2457 filePaths[proci],
2458 labelList(one{}, proci),
2459 pBufs
2460 );
2461 }
2462 }
2463 }
2464
2465
2466 pBufs.finishedSends();
2467
2468 if (Pstream::master(comm_))
2469 {
2470 // Read myself
2471 isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2472 }
2473 else
2474 {
2475 if (debug)
2476 {
2477 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2478 << " Reading " << filePath
2479 << " from processor " << Pstream::masterNo() << endl;
2480 }
2481
2482 List<char> buf(pBufs.recvDataCount(Pstream::masterNo()));
2483
2484 if (!buf.empty())
2485 {
2486 UIPstream is(Pstream::masterNo(), pBufs);
2487 is.read(buf.data(), buf.size());
2488 }
2489
2490 if (debug)
2491 {
2492 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2493 << " Done reading " << buf.size() << " bytes" << endl;
2494 }
2495
2496 // A local character buffer copy of the Pstream contents.
2497 // Construct with same parameters (ASCII, current version)
2498 // as the IFstream so that it has the same characteristics.
2499
2500 isPtr.reset(new ICharStream(std::move(buf)));
2501
2502 // With the proper file name
2503 isPtr->name() = filePath;
2504 }
2505 }
2506 else
2507 {
2508 // Read myself
2509 isPtr.reset(new IFstream(filePath));
2510 }
2511
2512 return isPtr;
2513}
2514
2515
2518(
2519 const fileName& pathName,
2520 IOstreamOption streamOpt,
2521 const bool writeOnProc
2522) const
2523{
2524 return autoPtr<OSstream>
2525 (
2526 new masterOFstream
2527 (
2528 comm_,
2529 pathName,
2530 streamOpt,
2532 writeOnProc
2533 )
2535}
2536
2537
2540(
2542 const fileName& pathName,
2543 IOstreamOption streamOpt,
2544 const bool writeOnProc
2545) const
2546{
2547 return autoPtr<OSstream>
2548 (
2549 new masterOFstream
2550 (
2551 atomic,
2552 comm_,
2553 pathName,
2554 streamOpt,
2556 writeOnProc
2558 );
2559}
2560
2561
2563{
2565 times_.clear();
2566}
2567
2568
2570{
2571 if (debug)
2572 {
2573 Pout<< "masterUncollatedFileOperation::sync :"
2574 << " syncing information across processors" << endl;
2575 }
2576
2578
2579
2580 wordList timeNames;
2581 List<DynamicList<instant>> instants;
2582
2584 {
2585 timeNames.resize(times_.size());
2586 instants.resize(times_.size());
2587
2588 // Flatten into two lists to preserve key/val pairing
2589 label i = 0;
2590 forAllConstIters(times_, iter)
2591 {
2592 timeNames[i] = iter.key();
2593 instants[i] = std::move(*(iter.val()));
2594 ++i;
2595 }
2596 }
2597
2598 Pstream::broadcasts(UPstream::worldComm, timeNames, instants);
2599
2600 times_.clear();
2601 forAll(timeNames, i)
2602 {
2603 fileName dir(timeNames[i]);
2604 auto ptr = autoPtr<DynamicList<instant>>::New(std::move(instants[i]));
2605
2607 {
2608 // Replace processor0 ending with processorDDD
2609 fileName path, pDir, local;
2610 procRangeType group;
2611 label numProcs;
2612 const label proci = fileOperation::splitProcessorPath
2613 (
2614 dir,
2615 path,
2616 pDir,
2617 local,
2618 group,
2619 numProcs
2620 );
2621
2622 //Pout<< "**sync : From dir : " << dir << nl
2623 // << " path : " << path << nl
2624 // << " pDir : " << pDir << nl
2625 // << " local: " << local << nl
2626 // << " proci: " << proci << nl
2627 // << endl;
2628
2629 const label myProci = Pstream::myProcNo(UPstream::worldComm);
2630
2631 if (proci != -1 && proci != myProci)
2632 {
2633 dir = path/"processor" + Foam::name(myProci);
2634 }
2635 }
2636
2637 times_.insert(dir, ptr);
2638 }
2639}
2640
2641
2643(
2644 const fileName& fName
2645) const
2646{
2647 label watchFd = -1;
2649 {
2650 watchFd = monitor().addWatch(fName);
2651 }
2652
2654 return watchFd;
2655}
2656
2657
2659(
2660 const label watchIndex
2661) const
2662{
2663 bool ok = false;
2665 {
2666 ok = monitor().removeWatch(watchIndex);
2667 }
2668
2670 return ok;
2671}
2672
2673
2675(
2676 const labelList& watchIndices,
2677 const fileName& fName
2678) const
2679{
2680 label index = -1;
2681
2683 {
2684 forAll(watchIndices, i)
2685 {
2686 if (monitor().getFile(watchIndices[i]) == fName)
2687 {
2688 index = i;
2689 break;
2690 }
2691 }
2692 }
2693
2695 return index;
2696}
2697
2698
2700(
2701 regIOobject& rio,
2702 const fileNameList& files
2703) const
2704{
2705 const labelList& watchIndices = rio.watchIndices();
2706
2707 // Do on master and distribute effect to subprocs such that after
2708 // all have consistent numbering & files
2709
2710 DynamicList<label> newWatchIndices;
2711 if (UPstream::master())
2712 {
2713 // Switch off comms inside findWatch/addWatch etc.
2714 const bool oldParRun = UPstream::parRun(false);
2715 const int oldCache = fileOperation::cacheLevel(0);
2716 const label oldNProcs = fileOperation::nProcs();
2717
2718 labelHashSet removedWatches(watchIndices);
2719
2720 for (const fileName& f : files)
2721 {
2722 const label index = findWatch(watchIndices, f);
2723
2724 if (index == -1)
2725 {
2726 newWatchIndices.push_back(addWatch(f));
2727 }
2728 else
2729 {
2730 // Existing watch
2731 newWatchIndices.push_back(watchIndices[index]);
2732 removedWatches.erase(index);
2733 }
2734 }
2735
2736 // Remove any unused watches
2737 for (const label index : removedWatches)
2738 {
2739 removeWatch(watchIndices[index]);
2740 }
2741
2742 const_cast<masterUncollatedFileOperation&>(*this).nProcs(oldNProcs);
2743 fileOperation::cacheLevel(oldCache);
2744 UPstream::parRun(oldParRun);
2745 }
2746 Pstream::broadcast(newWatchIndices);
2748 rio.watchIndices() = newWatchIndices;
2749}
2750
2751
2753(
2754 const label watchIndex
2755) const
2756{
2757 fileName fName;
2759 {
2760 fName = monitor().getFile(watchIndex);
2761 }
2762
2764 return fName;
2765}
2766
2767
2769(
2770 const bool masterOnly,
2771 const bool syncPar
2772) const
2773{
2775 {
2776 monitor().updateStates(true, false);
2778}
2779
2780
2783(
2784 const label watchFd
2785) const
2786{
2787 unsigned int state = fileMonitor::UNMODIFIED;
2789 {
2790 state = monitor().getState(watchFd);
2791 }
2792
2794 return fileMonitor::fileState(state);
2795}
2796
2797
2799(
2800 const label watchFd
2801) const
2802{
2804 {
2805 monitor().setUnmodified(watchFd);
2806 }
2807}
2808
2809
2810// ************************************************************************* //
Input/output streams with (internal or external) character storage.
Macros for easy insertion into run-time selection tables.
#define addNamedToRunTimeSelectionTable(baseType, thisType, argNames, lookupName)
Add to construction table with 'lookupName' as the key.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void push_back(const T &val)
Copy append an element to the end of this list.
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition HashTable.C:489
An ISstream with internal List storage. Always UNCOMPRESSED.
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
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
static bool isReadRequired(readOption opt) noexcept
True if (MUST_READ | READ_MODIFIED) bits are set.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition IOobject.C:456
const word & name() const noexcept
Return the object name.
Definition IOobjectI.H:205
bool readHeader(Istream &is)
Read header ('FoamFile' dictionary) and set the IOobject and stream characteristics.
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
const fileName & local() const noexcept
Read access to local path component.
Definition IOobjectI.H:301
const fileName & instance() const noexcept
Read access to instance path component.
Definition IOobjectI.H:289
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition IOobject.H:358
fileName objectPath() const
The complete path + object name.
Definition IOobjectI.H:313
A simple container for options an IOstream can normally have.
compressionType compression() const noexcept
Get the stream compression.
streamFormat
Data format (ascii | binary | coherent).
atomicType
Atomic operations (output).
@ NO_APPEND
no append (truncates existing)
bool good() const noexcept
True if next operation might succeed.
Definition IOstream.H:281
Input inter-processor communications stream using MPI broadcast.
Definition IPstream.H:114
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
Output inter-processor communications stream using MPI broadcast.
Definition OPstream.H:133
Generic output stream using a standard (STL) stream.
Definition OSstream.H:53
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name).
Definition OSstream.H:134
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedScatters(const bool wait=true)
Mark all sends to sub-procs as done.
label recvDataCount(const label proci) const
Number of unconsumed receive bytes for the specified processor. Must call finishedSends() or other fi...
void finishedSends(const bool wait=true)
Mark the send phase as being finished.
UPstream::rangeType subProcs() const noexcept
Range of sub-processes indices associated with PstreamBuffers.
static void broadcasts(const int communicator, Type &value, Args &&... values)
Broadcast multiple items to all communicator ranks. Does nothing in non-parallel.
const word & constant() const noexcept
Return constant name.
Definition TimePathsI.H:131
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:192
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
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
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
fileName path() const
The path for the case = rootPath/caseName.
Definition TimePathsI.H:102
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition Tuple2.H:51
const T1 & first() const noexcept
Access the first element.
Definition Tuple2.H:132
const T2 & second() const noexcept
Access the second element.
Definition Tuple2.H:142
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
Definition UIPstream.H:313
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.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition UListI.H:274
const char * cdata_bytes() const noexcept
Return pointer to the underlying array serving as data storage,.
Definition UListI.H:281
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
std::streamsize size_bytes() const noexcept
Number of contiguous bytes for the List data.
Definition UListI.H:295
Output inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
Definition UOPstream.H:408
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:1706
static List< int > & procID(int communicator)
The list of ranks within a given communicator.
Definition UPstream.H:1767
commsTypes
Communications types.
Definition UPstream.H:81
@ scheduled
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
Definition UPstream.H:83
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition UPstream.H:1691
static List< T > listGatherValues(const T &localValue, const int communicator=UPstream::worldComm)
Gather individual values into list locations.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static void reduceOr(bool &value, const int communicator=worldComm)
Logical (or) reduction (MPI_AllReduce).
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:1697
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
Definition UPstream.H:1857
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition UPstream.H:1866
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
@ gatherList
gatherList [manual algorithm]
Definition UPstream.H:194
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
static void freeCommunicator(const label communicator, const bool withComponents=true)
Free a previously allocated communicator.
Definition UPstream.C:622
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void clear() noexcept
Same as reset(nullptr).
Definition autoPtr.H:255
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
static autoPtr< ISstream > readBlock(const label blocki, ISstream &is, IOobject &headerIO)
Read selected block (non-seeking) + header information.
static bool isCollatedType(const word &objectType)
True if object type is a known collated type.
static bool readBlocks(const label comm, autoPtr< ISstream > &isPtr, List< char > &localData, const UPstream::commsTypes commsType)
Read data (on master) and transmit.
static bool readHeader(IOobject &io, Istream &is)
Read header as per IOobject with additional handling of decomposedBlockData.
const Type & value() const noexcept
Return const reference to value.
static autoPtr< ISstream > New()
Return a dummyISstream.
fileState
Enumeration defining the file state.
Definition fileMonitor.H:71
A class for handling file names.
Definition fileName.H:75
Type
Enumerations to handle directory entry types.
Definition fileName.H:82
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition fileNameI.H:192
An encapsulation of filesystem-related operations.
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile).
static labelRange subRanks(const labelUList &mainIOranks)
Get (contiguous) range/bounds of ranks addressed within the given main io-ranks.
static label getManagedComm(const label communicator)
Construction helper: check for locally allocated communicator.
virtual instantList findTimes(const fileName &directory, const word &constantName="constant") const
Get sorted list of times.
Tuple2< fileName, Tuple2< pathType, int > > dirIndex
Augment fileName with pathType and local offset.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
const labelList ioRanks_
The list of IO ranks (global ranks).
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
label nProcs() const noexcept
Overall number of processors, from UPstream::nProcs() or detected from directories/results.
fileName processorsPath(const IOobject &io, const word &instance, const word &procDir) const
Generate path (like io.path) with provided instance and any.
virtual refPtr< dirIndexList > lookupProcessorsPath(const fileName &objectPath) const
Lookup name of processorsDDD using cache.
List< dirIndex > dirIndexList
static label splitProcessorPath(const fileName &objectPath, fileName &path, fileName &procDir, fileName &local, procRangeType &group, label &nProcs)
Split objectPath into part before 'processor' and part after.
virtual word processorsDir(const IOobject &io) const
Actual name of processors dir (for use in mode PROCOBJECT, PROCINSTANCE).
static label detectProcessorPath(const fileName &objPath)
Detect processor number from '/aa/bb/processorDDD/cc'.
virtual void setTime(const Time &) const
Callback for time change.
pathType
Enumeration for the location of an IOobject.
@ PROCUNCOLLATEDINSTANCE
as PROCUNCOLLATED but with instance
@ WRITEOBJECT
write path exists
@ OBJECT
io.objectPath() exists
@ PROCINSTANCE
as PROCOBJECT but with instance
@ FINDINSTANCE
file found in time directory
@ PROCUNCOLLATED
objectPath exists in 'processorN'
@ ABSOLUTE
instance is absolute directory
@ PROCBASEINSTANCE
as PROCBASEOBJECT but with instance
@ PARENTOBJECT
parent of object path
@ PROCOBJECT
objectPath exists in 'processorsNN_first-last'
@ PROCBASEOBJECT
objectPath exists in 'processorsNN'
label comm_
Communicator to use.
static labelList getGlobalIORanks()
Get list of global IO ranks from FOAM_IORANKS env variable. If set, these correspond to the IO master...
label comm() const noexcept
Communicator to use.
static bool uniformFile(const fileNameList &names)
True if the file names are identical. False on an empty list.
static int cacheLevel() noexcept
Return cache level.
fileOperation(const label comm, const labelUList &ioRanks=labelUList::null(), const bool distributedRoots=false)
Construct from communicator, optionally with specified io-ranks and/or distributed roots.
static const Enum< pathType > pathTypeNames_
virtual void sync()
Forcibly parallel sync.
fileMonitor & monitor() const
Get or create fileMonitor singleton.
UPstream::rangeType procRangeType
For addressing a range of processors (an int range).
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
A fileOperation initialiser for unthreaded file handlers.
fileOperations that performs all file operations on the master processor. Requires the calls to be pa...
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
virtual double highResLastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
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.
virtual autoPtr< OSstream > NewOFstream(const fileName &pathname, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Generate an OSstream that writes a file.
const HashPtrTable< DynamicList< instant > > & times() const noexcept
Return cached times.
virtual instantList findTimes(const fileName &directory, const word &constantName="constant") const
Get sorted list of times.
virtual label addWatch(const fileName &) const
Add watching of a file. Returns handle.
static void readAndSend(const fileName &filePath, const labelUList &recvProcs, PstreamBuffers &pBufs)
Read file contents and send to processors.
virtual bool rmDir(const fileName &dir, const bool silent=false, const bool emptyOnly=false) const
Remove a directory and its contents.
virtual mode_t mode(const fileName &, const bool followLink=true) const
Return the file mode.
virtual void setTime(const Time &) const
Callback for time change.
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.
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.
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
static float maxMasterFileBufferSize
Max size of parallel communications. Switches from non-blocking.
virtual bool removeWatch(const label) const
Remove watch on a file (using handle).
virtual bool readHeader(IOobject &, const fileName &, const word &typeName) const
Read object header from supplied file.
virtual bool mvBak(const fileName &, const std::string &ext="bak") const
Rename to a corresponding backup file.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
virtual time_t lastModified(const fileName &, const bool followLink=true) const
Return time of last file modification.
virtual fileName dirPath(const bool checkGlobal, const IOobject &io, const bool search) const
Search for a directory.
virtual bool cp(const fileName &src, const fileName &dst, const bool followLink=true) const
Copy, recursively if necessary, the source to the destination.
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
Type masterOp(const fileName &fName, const FileOp &fop, const int tag, const label comm) const
bool exists(const dirIndexList &, IOobject &io) const
Helper: check IO for local existence. Like filePathInfo but.
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
masterUncollatedFileOperation(bool verbose=false)
Default construct.
virtual bool rm(const fileName &) const
Remove a file, returning true if successful otherwise false.
virtual autoPtr< ISstream > NewIFstream(const fileName &) const
Generate an ISstream that reads a file.
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 bool isDir(const fileName &, const bool followLink=true) const
Does the name exist as a DIRECTORY in the file system?
virtual fileMonitor::fileState getState(const label) const
Get current state of file (using handle).
virtual fileName filePath(const bool checkGlobal, const IOobject &io, const word &typeName, const bool search) const
Search for an object.
virtual void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
HashPtrTable< DynamicList< instant > > times_
Cached times for a given directory.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
virtual void storeComm() const
Transfer ownership of communicator to this fileOperation. Use with caution.
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
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,...
virtual fileName::Type type(const fileName &, const bool followLink=true) const
Return the file type: DIRECTORY, FILE or SYMLINK.
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Writes a regIOobject (so header, contents and divider).
static autoPtr< ISstream > read(IOobject &io, const label comm, const bool uniform, const fileNameList &filePaths, const boolUList &readOnProcs)
Read files on comms master.
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
virtual bool ln(const fileName &src, const fileName &dst) const
Create a softlink. dst should not exist. Returns true if.
fileName localObjectPath(const IOobject &, const pathType &searchType, const word &processorsDir, const word &instancePath) const
Construct filePath.
virtual fileName getFile(const label) const
Get name of file being watched (using handle).
An instant of time. Contains the time value and name. Uses Foam::Time when formatting the name.
Definition instant.H:56
Master-only drop-in replacement for OFstream.
Registry of regIOobjects.
const Time & time() const noexcept
Return time registry.
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition one.H:57
A class for managing references or pointers (no reference counting).
Definition refPtr.H:54
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
A class for handling words, derived from Foam::string.
Definition word.H:66
static const word null
An empty word.
Definition word.H:84
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool local
Definition EEqn.H:20
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition error.H:688
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition error.H:629
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define DetailInfo
Definition evalEntry.C:30
OBJstream os(runTime.globalPath()/outputName)
const auto & io
auto & name
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
#define WarningInFunction
Report a warning using Foam::Warning.
constexpr const char *const group
Group name for atomic constants.
Namespace for handling debugging switches.
Definition debug.C:45
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition debug.C:240
Namespace for implementations of a fileOperation.
Definition regIOobject.H:60
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
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.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
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
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
List< fileName > fileNameList
List of fileName.
messageStream Info
Information stream (stdout output on master, null elsewhere).
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition POSIX.C:775
List< instant > instantList
List of instants.
Definition instantList.H:41
List< string > stringList
List of string.
Definition stringList.H:32
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
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...
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
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
List< bool > boolList
A List of bools.
Definition List.H:60
int infoDetailLevel
Global for selective suppression of Info output.
UList< bool > boolUList
A UList of bools.
Definition UList.H:73
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
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
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.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
static Tuple2< label, labelList > getCommPattern()
void stableSort(UList< T > &list)
Stable sort the list.
Definition UList.C:299
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition fileName.C:642
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
#define registerOptSwitch(Name, Type, SwitchVar)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235
Extract type (as a word) from an object, typically using its type() method.
Definition word.H:362