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-2022 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
31#include "Pstream.H"
32#include "Time.H"
33#include "instant.H"
34#include "IFstream.H"
35#include "IListStream.H"
36#include "masterOFstream.H"
37#include "decomposedBlockData.H"
38#include "registerSwitch.H"
39#include "dummyISstream.H"
40#include "SubList.H"
42#include "bitSet.H"
43
44/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
45
46namespace Foam
47{
48namespace fileOperations
49{
52 (
55 word
56 );
57
59 (
60 Foam::debug::floatOptimisationSwitch("maxMasterFileBufferSize", 1e9)
61 );
63 (
64 "maxMasterFileBufferSize",
65 float,
67 );
68
69 // Mark as not needing threaded mpi
71 (
74 word,
75 masterUncollated
76 );
77}
78}
79
80
81// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
82
84(
85 const label n
86)
87{
89
90 if (mainRanks.empty())
91 {
92 return identity(n);
93 }
94 else
95 {
97
98 if (!mainRanks.found(0))
99 {
101 << "Rank 0 (master) should be in the IO ranks. Currently "
102 << mainRanks << nl
103 << exit(FatalError);
104 }
105
106 // The lowest numbered rank is the IO rank
107 const bitSet isIOrank(n, mainRanks);
108
109 for (label proci = Pstream::myProcNo(); proci >= 0; --proci)
110 {
111 if (isIOrank[proci])
112 {
113 // Found my master. Collect all processors with same master
114 subRanks.append(proci);
115 for
116 (
117 label rank = proci+1;
118 rank < n && !isIOrank[rank];
119 ++rank
120 )
121 {
122 subRanks.append(rank);
123 }
124 break;
125 }
126 }
127 return subRanks;
128 }
129}
130
131
134(
135 const instantList& timeDirs,
136 const instant& t
137)
138{
139 // Note:
140 // - times will include constant (with value 0) as first element.
141 // For backwards compatibility make sure to find 0 in preference
142 // to constant.
143 // - list is sorted so could use binary search
144
145 forAllReverse(timeDirs, i)
146 {
147 if (t.equal(timeDirs[i].value()))
148 {
149 return timeDirs[i].name();
150 }
151 }
152
153 return word::null;
154}
155
156
159(
160 const bool checkGlobal,
161 const bool isFile,
162 const IOobject& io,
163 const bool search,
164 pathType& searchType,
165 word& procsDir,
166 word& newInstancePath
167) const
168{
169 procsDir = word::null;
170 newInstancePath = word::null;
171
172 if (io.instance().isAbsolute())
173 {
174 fileName objPath = io.instance()/io.name();
175
176 if (isFileOrDir(isFile, objPath))
177 {
178 searchType = fileOperation::ABSOLUTE;
179 return objPath;
180 }
181 else
182 {
183 searchType = fileOperation::NOTFOUND;
184 return fileName::null;
185 }
186 }
187 else
188 {
189 // 1. Check the writing fileName
190 fileName writePath(objectPath(io, io.headerClassName()));
191
192 if (isFileOrDir(isFile, writePath))
193 {
194 searchType = fileOperation::WRITEOBJECT;
195 return writePath;
196 }
197
198 // 2. Check processors/
199 if (io.time().processorCase())
200 {
201 refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
202
203 for (const dirIndex& dirIdx : pDirs())
204 {
205 const fileName& pDir = dirIdx.first();
206 fileName objPath =
207 processorsPath(io, io.instance(), pDir)
208 /io.name();
209 if (objPath != writePath && isFileOrDir(isFile, objPath))
210 {
211 searchType = dirIdx.second().first();
212 procsDir = pDir;
213 return objPath;
214 }
215 }
216 }
217 {
218 // 3. Check local
219 fileName localPath = io.objectPath();
220
221 if
222 (
223 localPath != writePath
224 && isFileOrDir(isFile, localPath)
225 )
226 {
227 searchType = fileOperation::OBJECT;
228 return localPath;
229 }
230 }
231
232
233
234 // Any global checks
235 if
236 (
237 checkGlobal
238 && io.time().processorCase()
239 && (
240 io.instance() == io.time().system()
241 || io.instance() == io.time().constant()
242 )
243 )
244 {
245 fileName parentPath =
246 io.rootPath()/io.time().globalCaseName()
247 /io.instance()/io.db().dbDir()/io.local()/io.name();
248
249 if (isFileOrDir(isFile, parentPath))
250 {
251 searchType = fileOperation::PARENTOBJECT;
252 return parentPath;
253 }
254 }
255
256 // Check for approximately same time. E.g. if time = 1e-2 and
257 // directory is 0.01 (due to different time formats)
258 const auto pathFnd = times_.cfind(io.time().path());
259
260 if (search && pathFnd.found())
261 {
262 newInstancePath = findInstancePath
263 (
264 *pathFnd(),
265 instant(io.instance())
266 );
267
268 if (newInstancePath.size() && newInstancePath != io.instance())
269 {
270 // 1. Try processors equivalent
272 (
273 lookupProcessorsPath(io.objectPath())
274 );
275
276 for (const dirIndex& dirIdx : pDirs())
277 {
278 const fileName& pDir = dirIdx.first();
279
280 fileName fName
281 (
282 processorsPath(io, newInstancePath, pDir)
283 /io.name()
284 );
285 if (isFileOrDir(isFile, fName))
286 {
287 switch (dirIdx.second().first())
288 {
290 {
291 searchType =
293 }
294 break;
296 {
298 }
299 break;
301 {
302 searchType = fileOperation::PROCINSTANCE;
303 }
304 break;
305 default:
306 break;
307 }
308 procsDir = pDir;
309 return fName;
310 }
311 }
312
313
314 // 2. Check local
315 fileName fName
316 (
317 io.rootPath()/io.caseName()
318 /newInstancePath/io.db().dbDir()/io.local()/io.name()
319 );
320 if (isFileOrDir(isFile, fName))
321 {
322 searchType = fileOperation::FINDINSTANCE;
323 return fName;
324 }
325 }
326 }
327
328 searchType = fileOperation::NOTFOUND;
329 return fileName::null;
330 }
331}
332
333
336(
337 const IOobject& io,
338 const pathType& searchType,
339 const word& procDir,
340 const word& instancePath
341) const
342{
343 // Replacement for IOobject::objectPath()
344
345 switch (searchType)
346 {
348 {
349 return io.instance()/io.name();
350 }
351 break;
352
354 {
355 return io.path()/io.name();
356 }
357 break;
358
360 {
361 return objectPath(io, io.headerClassName());
362 }
363 break;
364
366 {
367 // Uncollated type, e.g. processor1
368 const word procName
369 (
371 );
372 return
373 processorsPath
374 (
375 io,
376 io.instance(),
377 (
379 ? procName
380 : procDir
381 )
382 )
383 /io.name();
384 }
385 break;
386
388 {
389 // Collated, e.g. processors4
390 return
391 processorsPath(io, io.instance(), procDir)
392 /io.name();
393 }
394 break;
395
397 {
398 // Processors directory locally provided by the fileHandler itself
399 return
400 processorsPath(io, io.instance(), processorsDir(io))
401 /io.name();
402 }
403 break;
404
406 {
407 return
408 io.rootPath()/io.time().globalCaseName()
409 /io.instance()/io.db().dbDir()/io.local()/io.name();
410 }
411 break;
412
414 {
415 return
416 io.rootPath()/io.caseName()
417 /instancePath/io.db().dbDir()/io.local()/io.name();
418 }
419 break;
420
422 {
423 // Uncollated type, e.g. processor1
424 const word procName
425 (
426 "processor"
428 );
429 return
430 processorsPath
431 (
432 io,
433 instancePath,
434 (
436 ? procName
437 : procDir
438 )
439 )
440 /io.name();
441 }
442 break;
443
445 {
446 // Collated, e.g. processors4
447 return
448 processorsPath(io, instancePath, procDir)
449 /io.name();
450 }
451 break;
452
454 {
455 // Processors directory locally provided by the fileHandler itself
456 return
457 processorsPath(io, instancePath, processorsDir(io))
458 /io.name();
459 }
460 break;
461
463 {
464 return fileName::null;
465 }
466 break;
467
468 default:
469 {
471 return fileName::null;
472 }
473 }
474}
475
476
478(
479 const fileNameList& filePaths
480)
481{
482 const fileName& object0 = filePaths[0];
483
484 for (label i = 1; i < filePaths.size(); i++)
485 {
486 if (filePaths[i] != object0)
487 {
488 return false;
489 }
490 }
491 return true;
492}
493
494
496(
497 const fileName& filePath,
498 const labelUList& procs,
499 PstreamBuffers& pBufs
500)
501{
502 IFstream ifs(filePath, IOstreamOption::BINARY);
503
504 if (!ifs.good())
505 {
506 FatalIOErrorInFunction(filePath)
507 << "Cannot open file " << filePath
508 << exit(FatalIOError);
509 }
510
511 if (debug)
512 {
513 Pout<< "masterUncollatedFileOperation::readAndSend :"
514 << " compressed:" << bool(ifs.compression()) << " "
515 << filePath << endl;
516 }
517
519 {
520 // Could use Foam::fileSize, estimate uncompressed size (eg, 2x)
521 // and then string reserve followed by string assign...
522
523 // Uncompress and read file contents into a character buffer
524 const std::string buf
525 (
526 std::istreambuf_iterator<char>(ifs.stdStream()),
527 std::istreambuf_iterator<char>()
528 );
529
530 for (const label proci : procs)
531 {
532 UOPstream os(proci, pBufs);
533 os.write(buf.data(), buf.length());
534 }
535
536 if (debug)
537 {
538 Pout<< "masterUncollatedFileOperation::readStream :"
539 << " From " << filePath << " sent " << buf.size()
540 << " bytes" << endl;
541 }
542 }
543 else
544 {
545 const off_t count(Foam::fileSize(filePath));
546
547 // Read file contents into a character buffer
548 List<char> buf(static_cast<label>(count));
549 ifs.stdStream().read(buf.data(), count);
550
551 for (const label proci : procs)
552 {
553 UOPstream os(proci, pBufs);
554 os.write(buf.cdata(), count);
555 }
556
557 if (debug)
558 {
559 Pout<< "masterUncollatedFileOperation::readStream :"
560 << " From " << filePath << " sent " << buf.size()
561 << " bytes" << endl;
562 }
563 }
564}
565
566
569(
570 IOobject& io,
571 const label comm,
572 const bool uniform, // on comms master only
573 const fileNameList& filePaths, // on comms master only
574 const boolList& procValid // on comms master and sub-ranks
575)
576{
577 autoPtr<ISstream> isPtr;
578
579 // const bool uniform = uniformFile(filePaths);
580
582
583 if (Pstream::master(comm))
584 {
585 if (uniform)
586 {
587 if (procValid[0])
588 {
589 if (filePaths[0].empty())
590 {
591 FatalIOErrorInFunction(filePaths[0])
592 << "cannot find file " << io.objectPath()
593 << exit(FatalIOError);
594 }
595
596 DynamicList<label> validProcs(Pstream::nProcs(comm));
597 for (const int proci : Pstream::allProcs(comm))
598 {
599 if (procValid[proci])
600 {
601 validProcs.append(proci);
602 }
603 }
604
605 // Read on master and send to all processors
606 // (including master for simplicity)
607 if (debug)
608 {
609 Pout<< "masterUncollatedFileOperation::readStream :"
610 << " For uniform file " << filePaths[0]
611 << " sending to " << validProcs
612 << " in comm:" << comm << endl;
613 }
614 readAndSend(filePaths[0], validProcs, pBufs);
615 }
616 }
617 else
618 {
619 if (procValid[0])
620 {
621 if (filePaths[0].empty())
622 {
623 FatalIOErrorInFunction(filePaths[0])
624 << "cannot find file " << io.objectPath()
625 << exit(FatalIOError);
626 }
627
628 // Open master
629 isPtr.reset(new IFstream(filePaths[0]));
630
631 // Read header
632 if (!io.readHeader(*isPtr))
633 {
635 << "problem while reading header for object "
636 << io.name() << exit(FatalIOError);
637 }
638 }
639
640 // Read sub-rank files
641 for (const int proci : Pstream::subProcs(comm))
642 {
643 if (debug)
644 {
645 Pout<< "masterUncollatedFileOperation::readStream :"
646 << " For processor " << proci
647 << " opening " << filePaths[proci] << endl;
648 }
649
650 const fileName& fPath = filePaths[proci];
651
652 if (procValid[proci] && !fPath.empty())
653 {
654 // Note: handle compression ourselves since size cannot
655 // be determined without actually uncompressing
656 readAndSend(fPath, labelList(one{}, proci), pBufs);
657 }
658 }
659 }
660 }
661
662 labelList recvSizes;
663 pBufs.finishedSends(recvSizes);
664
665 // isPtr will be valid on master and will be the unbuffered
666 // IFstream. Else the information is in the PstreamBuffers (and
667 // the special case of a uniform file)
668
669 if (!isPtr)
670 {
671 if (procValid[Pstream::myProcNo(comm)])
672 {
673 // This processor needs to return something
674
675 UIPstream is(Pstream::masterNo(), pBufs);
676
677 List<char> buf(recvSizes[Pstream::masterNo()]);
678 if (!buf.empty())
679 {
680 is.read(buf.data(), buf.size());
681 }
682
683 if (debug)
684 {
685 Pout<< "masterUncollatedFileOperation::readStream :"
686 << " Done reading " << buf.size() << " bytes" << endl;
687 }
688
689 // A local character buffer copy of the Pstream contents.
690 // Construct with same parameters (ASCII, current version)
691 // as the IFstream so that it has the same characteristics.
692
693 isPtr.reset(new IListStream(std::move(buf)));
694
695 // With the proper file name
696 isPtr->name() = filePaths[Pstream::myProcNo(comm)];
697
698 if (!io.readHeader(*isPtr))
699 {
701 << "problem while reading header for object "
702 << io.name() << exit(FatalIOError);
703 }
704 }
705 else
706 {
707 isPtr.reset(new dummyISstream());
708 }
709 }
710
711
712 return isPtr;
713}
714
715
716// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
717
718Foam::fileOperations::masterUncollatedFileOperation::
719masterUncollatedFileOperation
720(
721 bool verbose
722)
723:
725 (
726 UPstream::allocateCommunicator
727 (
728 UPstream::worldComm,
729 subRanks(Pstream::nProcs())
730 )
731 ),
732 myComm_(comm_)
733{
734 verbose = (verbose && Foam::infoDetailLevel > 0);
735
736 if (verbose)
737 {
739 << "I/O : " << typeName
740 << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
741 << endl;
742 }
743
745 {
746 if (verbose)
747 {
749 << "Resetting fileModificationChecking to timeStamp" << endl;
750 }
752 }
754 {
755 if (verbose)
756 {
758 << "Resetting fileModificationChecking to inotify"
759 << endl;
760 }
762 }
763}
764
765
766Foam::fileOperations::masterUncollatedFileOperation::
767masterUncollatedFileOperation
768(
769 const label comm,
770 bool verbose
771)
772:
773 fileOperation(comm),
774 myComm_(-1)
775{
776 verbose = (verbose && Foam::infoDetailLevel > 0);
777
778 if (verbose)
779 {
781 << "I/O : " << typeName
782 << " (maxMasterFileBufferSize " << maxMasterFileBufferSize << ')'
783 << endl;
784 }
785
787 {
788 if (verbose)
789 {
791 << "Resetting fileModificationChecking to timeStamp" << endl;
792 }
794 }
796 {
797 if (verbose)
798 {
800 << "Resetting fileModificationChecking to inotify"
801 << endl;
802 }
804 }
805}
806
807
808// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
809
812{
813 if (myComm_ != -1 && myComm_ != UPstream::worldComm)
814 {
816 }
817}
818
819
820// * * * * * * * * * * * * * Filesystem Operations * * * * * * * * * * * * * //
821
823(
824 const fileName& dir,
825 mode_t mode
826) const
827{
828 return masterOp<mode_t>
829 (
830 dir,
831 mkDirOp(mode),
833 comm_
834 );
835}
836
837
839(
840 const fileName& fName,
841 mode_t mode
842) const
843{
844 return masterOp<mode_t>
845 (
846 fName,
847 chModOp(mode),
849 comm_
850 );
851}
852
853
855(
856 const fileName& fName,
857 const bool followLink
858) const
859{
860 return masterOp<mode_t>
861 (
862 fName,
863 modeOp(followLink),
865 comm_
866 );
867}
868
869
871(
872 const fileName& fName,
873 const bool followLink
874) const
875{
876 return fileName::Type
877 (
878 masterOp<label>
879 (
880 fName,
881 typeOp(followLink),
883 comm_
884 )
885 );
886}
887
888
890(
891 const fileName& fName,
892 const bool checkGzip,
893 const bool followLink
894) const
895{
896 return masterOp<bool>
897 (
898 fName,
899 existsOp(checkGzip, followLink),
901 comm_
902 );
903}
904
905
907(
908 const fileName& fName,
909 const bool followLink
910) const
911{
912 return masterOp<bool>
913 (
914 fName,
915 isDirOp(followLink),
917 comm_
918 );
919}
920
921
923(
924 const fileName& fName,
925 const bool checkGzip,
926 const bool followLink
927) const
928{
929 return masterOp<bool>
930 (
931 fName,
932 isFileOp(checkGzip, followLink),
934 comm_
935 );
936}
937
938
940(
941 const fileName& fName,
942 const bool followLink
943) const
944{
945 return masterOp<off_t>
946 (
947 fName,
948 fileSizeOp(followLink),
950 comm_
951 );
952}
953
954
956(
957 const fileName& fName,
958 const bool followLink
959) const
960{
961 return masterOp<time_t>
962 (
963 fName,
964 lastModifiedOp(followLink),
966 comm_
967 );
968}
969
970
972(
973 const fileName& fName,
974 const bool followLink
975) const
976{
977 return masterOp<double>
978 (
979 fName,
980 highResLastModifiedOp(followLink),
982 comm_
983 );
984}
985
986
988(
989 const fileName& fName,
990 const std::string& ext
991) const
992{
993 return masterOp<bool>
994 (
995 fName,
996 mvBakOp(ext),
998 comm_
999 );
1000}
1001
1002
1004(
1005 const fileName& fName
1006) const
1007{
1008 return masterOp<bool>
1009 (
1010 fName,
1011 rmOp(),
1013 comm_
1014 );
1015}
1016
1017
1019(
1020 const fileName& dir,
1021 const bool silent
1022) const
1023{
1024 return masterOp<bool>
1025 (
1026 dir,
1027 rmDirOp(silent),
1029 comm_
1030 );
1031}
1032
1033
1035(
1036 const fileName& dir,
1037 const fileName::Type type,
1038 const bool filtergz,
1039 const bool followLink
1040) const
1041{
1042 return masterOp<fileNameList>
1043 (
1044 dir,
1045 readDirOp(type, filtergz, followLink),
1047 comm_
1048 );
1049}
1050
1051
1053(
1054 const fileName& src,
1055 const fileName& dst,
1056 const bool followLink
1057) const
1058{
1059 return masterOp<bool>
1060 (
1061 src,
1062 dst,
1063 cpOp(followLink),
1065 comm_
1066 );
1067}
1068
1069
1071(
1072 const fileName& src,
1073 const fileName& dst
1074) const
1075{
1076 return masterOp<bool>
1077 (
1078 src,
1079 dst,
1080 lnOp(),
1082 comm_
1083 );
1084}
1085
1086
1088(
1089 const fileName& src,
1090 const fileName& dst,
1091 const bool followLink
1092) const
1093{
1094 return masterOp<bool>
1095 (
1096 src,
1097 dst,
1098 mvOp(followLink),
1100 comm_
1101 );
1102}
1103
1104
1105// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1106
1108(
1109 const bool checkGlobal,
1110 const IOobject& io,
1111 const word& typeName,
1112 const bool search
1113) const
1114{
1115 if (debug)
1116 {
1117 Pout<< "masterUncollatedFileOperation::filePath :"
1118 << " objectPath:" << io.objectPath()
1119 << " checkGlobal:" << checkGlobal << endl;
1120 }
1121
1122 // Now that we have an IOobject path use it to detect & cache
1123 // processor directory naming
1124 (void)lookupProcessorsPath(io.objectPath());
1125
1126 // Trigger caching of times
1127 (void)findTimes(io.time().path(), io.time().constant());
1128
1129
1130 // Determine master filePath and scatter
1131
1132 fileName objPath;
1133 pathType searchType = NOTFOUND;
1134 word procsDir;
1135 word newInstancePath;
1136
1137 if (Pstream::master(comm_))
1138 {
1139 const bool oldParRun(Pstream::parRun(false));
1140
1141 // All masters search locally. Note that global objects might
1142 // fail (except on master). This gets handled later on (in PARENTOBJECT)
1143 objPath =
1144 filePathInfo
1145 (
1146 checkGlobal,
1147 true,
1148 io,
1149 search,
1150 searchType,
1151 procsDir,
1152 newInstancePath
1153 );
1154
1155 Pstream::parRun(oldParRun);
1156
1157 if (debug)
1158 {
1159 Pout<< "masterUncollatedFileOperation::filePath :"
1160 << " master objPath:" << objPath
1161 << " searchType:" << fileOperation::pathTypeNames_[searchType]
1162 << " procsDir:" << procsDir << " instance:" << newInstancePath
1163 << endl;
1164 }
1165 }
1166
1167 // Scatter the information about where the master found the object
1168 // Note: use the worldComm to make sure all processors decide
1169 // the same type. Only procsDir is allowed to differ; searchType
1170 // and instance have to be same
1171 {
1172 int masterType(searchType);
1173 Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1174 searchType = pathType(masterType);
1175 }
1176
1177 if
1178 (
1179 checkGlobal
1180 || searchType == fileOperation::PARENTOBJECT
1181 || searchType == fileOperation::PROCBASEOBJECT
1182 || searchType == fileOperation::PROCBASEINSTANCE
1183 || io.local() == "uniform"
1184 )
1185 {
1186 // Distribute master path. This makes sure it is seen as uniform
1187 // and only gets read from the master.
1188 Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1189 }
1190 else
1191 {
1192 Pstream::broadcast(procsDir, comm_);
1193
1194 // Use the master type to determine if additional information is
1195 // needed to construct the local equivalent
1196 switch (searchType)
1197 {
1201 {
1202 // Already handled above
1203 }
1204 break;
1205
1213 {
1214 // Construct equivalent local path
1215 objPath = localObjectPath
1216 (
1217 io,
1218 searchType,
1219 procsDir,
1220 newInstancePath
1221 );
1222 }
1223 break;
1224
1227 {
1228 // Retest all processors separately since some processors might
1229 // have the file and some not (e.g. lagrangian data)
1230
1231 objPath = masterOp<fileName>
1232 (
1233 io.objectPath(),
1234 fileOrNullOp(true), // isFile=true
1236 comm_
1237 );
1238 }
1239 break;
1240 }
1241 }
1242
1243 if (debug)
1244 {
1245 Pout<< "masterUncollatedFileOperation::filePath :"
1246 << " Returning from file searching:" << endl
1247 << " objectPath:" << io.objectPath() << endl
1248 << " filePath :" << objPath << endl << endl;
1249 }
1250 return objPath;
1251}
1252
1253
1255(
1256 const bool checkGlobal,
1257 const IOobject& io,
1258 const bool search
1259) const
1260{
1261 if (debug)
1262 {
1263 Pout<< "masterUncollatedFileOperation::dirPath :"
1264 << " objectPath:" << io.objectPath()
1265 << " checkGlobal:" << checkGlobal << endl;
1266 }
1267
1268 // Now that we have an IOobject path use it to detect & cache
1269 // processor directory naming
1270 (void)lookupProcessorsPath(io.objectPath());
1271
1272 // Determine master dirPath and broadcast
1273
1274 fileName objPath;
1275 pathType searchType = NOTFOUND;
1276 word procsDir;
1277 word newInstancePath;
1278
1279 if (Pstream::master(comm_))
1280 {
1281 const bool oldParRun(Pstream::parRun(false));
1282
1283 objPath = filePathInfo
1284 (
1285 checkGlobal,
1286 false,
1287 io,
1288 search,
1289 searchType,
1290 procsDir,
1291 newInstancePath
1292 );
1293
1294 Pstream::parRun(oldParRun);
1295 }
1296
1297 {
1298 int masterType(searchType);
1299 // Future?: comm_,
1300 Pstream::broadcasts(UPstream::worldComm, masterType, newInstancePath);
1301 searchType = pathType(masterType);
1302 }
1303
1304 if
1305 (
1306 checkGlobal
1307 || searchType == fileOperation::PARENTOBJECT
1308 || searchType == fileOperation::PROCBASEOBJECT
1309 || searchType == fileOperation::PROCBASEINSTANCE
1310 || io.local() == "uniform"
1311 )
1312 {
1313 // Distribute master path. This makes sure it is seen as uniform
1314 // and only gets read from the master.
1315 Pstream::broadcasts(UPstream::worldComm, objPath, procsDir);
1316 }
1317 else
1318 {
1319 Pstream::broadcast(procsDir, comm_);
1320
1321 // Use the master type to determine if additional information is
1322 // needed to construct the local equivalent
1323 switch (searchType)
1324 {
1328 {
1329 // Already handled above
1330 }
1331 break;
1332
1340 {
1341 // Construct equivalent local path
1342 objPath = localObjectPath
1343 (
1344 io,
1345 searchType,
1346 procsDir,
1347 newInstancePath
1348 );
1349 }
1350 break;
1351
1354 {
1355 // Retest all processors separately since some processors might
1356 // have the file and some not (e.g. lagrangian data)
1357
1358 objPath = masterOp<fileName>
1359 (
1360 io.objectPath(),
1361 fileOrNullOp(false), // isFile=false
1363 comm_
1364 );
1365 }
1366 break;
1367 }
1368 }
1369
1370 if (debug)
1371 {
1372 Pout<< "masterUncollatedFileOperation::dirPath :"
1373 << " Returning from file searching:" << endl
1374 << " objectPath:" << io.objectPath() << endl
1375 << " filePath :" << objPath << endl << endl;
1376 }
1377 return objPath;
1378}
1379
1380
1382(
1383 const dirIndexList& pDirs,
1384 IOobject& io
1385) const
1386{
1387 // Cut-down version of filePathInfo that does not look for
1388 // different instance or parent directory
1389
1390 const bool isFile = !io.name().empty();
1391
1392 // Generate output filename for object
1393 const fileName writePath(objectPath(io, word::null));
1394
1395 // 1. Test writing name for either directory or a (valid) file
1396 if (isFileOrDir(isFile, writePath))
1397 {
1398 return true;
1399 }
1400
1401 // 2. Check processors/
1402 if (io.time().processorCase())
1403 {
1404 for (const dirIndex& dirIdx : pDirs)
1405 {
1406 const fileName& pDir = dirIdx.first();
1407 fileName procPath =
1408 processorsPath(io, io.instance(), pDir)
1409 /io.name();
1410 if (procPath != writePath && isFileOrDir(isFile, procPath))
1411 {
1412 return true;
1413 }
1414 }
1415 }
1416
1417 // 3. Check local
1418 fileName localPath = io.objectPath();
1419
1420 if (localPath != writePath && isFileOrDir(isFile, localPath))
1421 {
1422 return true;
1423 }
1424
1425 return false;
1426}
1427
1428
1431(
1432 const IOobject& startIO,
1433 const scalar startValue,
1434 const word& stopInstance
1435) const
1436{
1437 if (debug)
1438 {
1439 Pout<< "masterUncollatedFileOperation::findInstance :"
1440 << " Starting searching for name:" << startIO.name()
1441 << " local:" << startIO.local()
1442 << " from instance:" << startIO.instance()
1443 << endl;
1444 }
1445
1446 const Time& time = startIO.time();
1447 IOobject io(startIO);
1448
1449 // Note: - if name is empty, just check the directory itself
1450 // - check both for isFile and headerOk since the latter does a
1451 // filePath so searches for the file.
1452 // - check for an object with local file scope (so no looking up in
1453 // parent directory in case of parallel)
1454
1455
1456 refPtr<dirIndexList> pDirs(lookupProcessorsPath(io.objectPath()));
1457
1458 word foundInstance;
1459
1460 // if (Pstream::master(comm_))
1462 {
1463 const bool oldParRun(Pstream::parRun(false));
1464 if (exists(pDirs, io))
1465 {
1466 foundInstance = io.instance();
1467 }
1468 Pstream::parRun(oldParRun);
1469 }
1470
1471 // Do parallel early exit to avoid calling time.times()
1472 // Pstream::broadcast(foundInstance, comm_);
1474 if (!foundInstance.empty())
1475 {
1476 io.instance() = foundInstance;
1477 if (debug)
1478 {
1479 Pout<< "masterUncollatedFileOperation::findInstance :"
1480 << " for name:" << io.name() << " local:" << io.local()
1481 << " found starting instance:" << io.instance() << endl;
1482 }
1483 return io;
1484 }
1485
1486
1487 // Handling failures afterwards
1488 const bool exitIfMissing
1489 (
1490 startIO.readOpt() == IOobject::MUST_READ
1492 );
1493
1494 enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1495 int failed(0);
1496
1497 instantList ts = time.times();
1498
1499 // if (Pstream::master(comm_))
1501 {
1502 const bool oldParRun(Pstream::parRun(false));
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 foundInstance = io.instance();
1557 }
1558 break;
1559 }
1560 }
1561
1562
1563 // times() usually already includes the constant() so would
1564 // have been checked above. However, re-test under these conditions:
1565 // - times() is empty. Sometimes this can happen (e.g. decomposePar
1566 // with collated)
1567 // - times()[0] is not constant
1568 // - Times is empty.
1569 // Sometimes this can happen (eg, decomposePar with collated)
1570 // - Times[0] is not constant
1571 // - The startValue is negative (eg, kivaTest).
1572 // This plays havoc with the reverse search, causing it to miss
1573 // 'constant'
1574
1575 if
1576 (
1577 !failed && foundInstance.empty()
1578 && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1579 )
1580 {
1581 // Note. This needs to be a hard-coded "constant" (not constant
1582 // function of Time), because the latter points to
1583 // the case constant directory in parallel cases.
1584 // However, parRun is disabled so they are actually the same.
1585
1586 io.instance() = time.constant();
1587
1588 if (exists(pDirs, io))
1589 {
1590 if (debug)
1591 {
1592 Pout<< "masterUncollatedFileOperation::findInstance :"
1593 << " name:" << io.name()
1594 << " local:" << io.local()
1595 << " at:" << io.instance() << endl;
1596 }
1597 foundInstance = io.instance();
1598 }
1599 }
1600
1601 if (!failed && foundInstance.empty())
1602 {
1603 if (exitIfMissing)
1604 {
1605 failed = failureCodes::FAILED_CONSTINST;
1606 }
1607 else
1608 {
1609 foundInstance = time.constant();
1610 }
1611 }
1612
1613 UPstream::parRun(oldParRun); // Restore parallel state
1614 }
1615
1616 // Pstream::broadcast(foundInstance, comm_);
1618 io.instance() = foundInstance;
1619
1620
1621 // Handle failures
1622 // ~~~~~~~~~~~~~~~
1623 if (failed)
1624 {
1625 FatalErrorInFunction << "Cannot find";
1626
1627 if (!io.name().empty())
1628 {
1630 << " file \"" << io.name() << "\" in";
1631 }
1632
1634 << " directory "
1635 << io.local() << " in times "
1636 << startIO.instance() << " down to ";
1637
1638 if (failed == failureCodes::FAILED_STOPINST)
1639 {
1640 FatalError << stopInstance;
1641 }
1642 else
1643 {
1644 FatalError << "constant";
1645 }
1647 }
1648
1649 if (debug)
1650 {
1651 Pout<< "masterUncollatedFileOperation::findInstance :"
1652 << " name:" << io.name() << " local:" << io.local()
1653 << " returning instance:" << io.instance() << endl;
1654 }
1655 return io;
1656}
1657
1658
1661(
1662 const objectRegistry& db,
1663 const fileName& instance,
1664 const fileName& local,
1665 word& newInstance
1666) const
1667{
1668 if (debug)
1669 {
1670 Pout<< "masterUncollatedFileOperation::readObjects :"
1671 << " db:" << db.objectPath()
1672 << " local:" << local << " instance:" << instance << endl;
1673 }
1674
1675 fileNameList objectNames;
1676 newInstance = word::null;
1677
1678 // Note: readObjects uses WORLD to make sure order of objects is the
1679 // same everywhere
1680
1681 if (Pstream::master()) // comm_))
1682 {
1683 // Avoid fileOperation::readObjects from triggering parallel ops
1684 // (through call to filePath which triggers parallel )
1685 const bool oldParRun = UPstream::parRun(false);
1686
1687 //- Use non-time searching version
1688 objectNames = fileOperation::readObjects
1689 (
1690 db,
1691 instance,
1692 local,
1693 newInstance
1694 );
1695
1696 if (newInstance.empty())
1697 {
1698 // Find similar time
1699
1700 // Copy of Time::findInstancePath. We want to avoid the
1701 // parallel call to findTimes. Alternative is to have
1702 // version of findInstancePath that takes instantList ...
1703 const instantList timeDirs
1704 (
1706 (
1707 db.time().path(),
1708 db.time().constant()
1709 )
1710 );
1711
1712 const instant t(instance);
1713 forAllReverse(timeDirs, i)
1714 {
1715 if (t.equal(timeDirs[i].value()))
1716 {
1717 objectNames = fileOperation::readObjects
1718 (
1719 db,
1720 timeDirs[i].name(), // newly found time
1721 local,
1722 newInstance
1723 );
1724 break;
1725 }
1726 }
1727 }
1728
1729 UPstream::parRun(oldParRun); // Restore parallel state
1730 }
1731
1732 // Future? comm_
1733 Pstream::broadcasts(UPstream::worldComm, newInstance, objectNames);
1734
1735 if (debug)
1736 {
1737 Pout<< "masterUncollatedFileOperation::readObjects :"
1738 << " newInstance:" << newInstance
1739 << " objectNames:" << objectNames << endl;
1740 }
1741
1742 return objectNames;
1743}
1744
1745
1747(
1748 IOobject& io,
1749 const fileName& fName,
1750 const word& typeName
1751) const
1752{
1753 bool ok = false;
1754
1755 if (debug)
1756 {
1757 Pout<< "masterUncollatedFileOperation::readHeader :" << endl
1758 << " objectPath:" << io.objectPath() << endl
1759 << " filePath :" << fName << endl;
1760 }
1761
1762 // Get filePaths on world master
1764 filePaths[Pstream::myProcNo(Pstream::worldComm)] = fName;
1766 bool uniform = uniformFile(filePaths);
1768
1769 if (uniform)
1770 {
1772 {
1773 if (!fName.empty())
1774 {
1775 IFstream is(fName);
1776
1777 if (is.good())
1778 {
1779 // Regular header or from decomposed data
1781 }
1782 }
1783 }
1784
1786 (
1788 ok,
1789 io.headerClassName(),
1790 io.note()
1791 );
1792 }
1793 else
1794 {
1796 {
1797 // Re-gather file paths on local master
1798 filePaths.resize(Pstream::nProcs(comm_));
1799 filePaths[Pstream::myProcNo(comm_)] = fName;
1800 Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
1801 }
1802
1803 // Intermediate storage arrays (master only)
1804 boolList result;
1805 wordList headerClassName;
1806 stringList note;
1807
1808 if (Pstream::master(comm_))
1809 {
1810 const label np = Pstream::nProcs(comm_);
1811
1812 result.resize(np, false);
1813 headerClassName.resize(np);
1814 note.resize(np);
1815
1816 forAll(filePaths, proci)
1817 {
1818 if (!filePaths[proci].empty())
1819 {
1820 if (proci > 0 && filePaths[proci] == filePaths[proci-1])
1821 {
1822 result[proci] = result[proci-1];
1823 headerClassName[proci] = headerClassName[proci-1];
1824 note[proci] = note[proci-1];
1825 }
1826 else
1827 {
1828 IFstream is(filePaths[proci]);
1829
1830 if (is.good())
1831 {
1832 result[proci] =
1834 headerClassName[proci] = io.headerClassName();
1835 note[proci] = io.note();
1836 }
1837 }
1838 }
1839 }
1840 }
1841
1842 // Is a more efficient scatter possible?
1844
1845 if (Pstream::master(comm_))
1846 {
1847 ok = result[0];
1848 io.headerClassName() = headerClassName[0];
1849 io.note() = note[0];
1850
1851 // Scatter to each proc
1852 for (const int proci : pBufs.subProcs())
1853 {
1854 UOPstream os(proci, pBufs);
1855 os << result[proci] << headerClassName[proci] << note[proci];
1856 }
1857 }
1858
1859 pBufs.finishedScatters();
1860
1861 if (!Pstream::master(comm_))
1862 {
1863 UIPstream is(Pstream::masterNo(), pBufs);
1864 is >> ok >> io.headerClassName() >> io.note();
1865 }
1866 }
1867
1868 if (debug)
1869 {
1870 Pout<< "masterUncollatedFileOperation::readHeader :" << " ok:" << ok
1871 << " class:" << io.headerClassName() << endl;
1872 }
1873 return ok;
1874}
1875
1876
1879(
1880 regIOobject& io,
1881 const fileName& fName,
1882 const word& typeName,
1883 const bool valid
1884) const
1885{
1886 if (debug)
1887 {
1888 Pout<< "masterUncollatedFileOperation::readStream :"
1889 << " object : " << io.name()
1890 << " global : " << io.global()
1891 << " fName : " << fName << " valid:" << valid << endl;
1892 }
1893
1894
1895 autoPtr<ISstream> isPtr;
1896 bool isCollated = false;
1897 IOobject headerIO(io);
1898
1899 // Detect collated format. This could be done on the local communicator
1900 // but we do it on the master node only for now.
1901 if (UPstream::master()) // comm_))
1902 {
1903 if (!fName.empty())
1904 {
1905 // This can happen in lagrangian field reading some processors
1906 // have no file to read from. This will only happen when using
1907 // normal writing since then the fName for the valid processors is
1908 // processorDDD/<instance>/.. . In case of collocated writing
1909 // the fName is already rewritten to processorsNN/.
1910
1911 isPtr.reset(new IFstream(fName));
1912
1913 if (isPtr->good())
1914 {
1915 // Read header data (on copy)
1916 headerIO.readHeader(*isPtr);
1917
1918 isCollated = decomposedBlockData::isCollatedType(headerIO);
1919
1920 if (!isCollated && !Pstream::parRun())
1921 {
1922 // Short circuit: non-collated format. No parallel bits.
1923 // Copy header and return.
1924 if (debug)
1925 {
1926 Pout<< "masterUncollatedFileOperation::readStream :"
1927 << " For object : " << io.name()
1928 << " doing straight IFstream input from "
1929 << fName << endl;
1930 }
1931 io = headerIO;
1932 return isPtr;
1933 }
1934 }
1935
1936 if (!isCollated)
1937 {
1938 // Close file. Reopened below.
1939 isPtr.clear();
1940 }
1941 }
1942 }
1943
1944 Pstream::broadcast(isCollated); //, comm_);
1945
1946 if (isCollated)
1947 {
1948 if (debug)
1949 {
1950 Pout<< "masterUncollatedFileOperation::readStream :"
1951 << " For object : " << io.name()
1952 << " starting collating input from " << fName << endl;
1953 }
1954
1955
1956 // Analyse the file path (on (co)master) to see the processors type
1957 // Note: this should really be part of filePath() which should return
1958 // both file and index in file.
1959
1960 fileName path, procDir, local;
1961 procRangeType group;
1962 label nProcs;
1963 splitProcessorPath(fName, path, procDir, local, group, nProcs);
1964
1965
1966 if (!Pstream::parRun())
1967 {
1968 // Analyse the objectpath to find out the processor we're trying
1969 // to access
1970 label proci = detectProcessorPath(io.objectPath());
1971
1972 if (proci == -1)
1973 {
1975 << "Could not detect processor number"
1976 << " from objectPath:" << io.objectPath()
1977 << exit(FatalIOError);
1978 }
1979
1980 // The local rank (offset)
1981 if (!group.empty())
1982 {
1983 proci = proci - group.start();
1984 }
1985
1986 if (debug)
1987 {
1988 Pout<< "masterUncollatedFileOperation::readStream :"
1989 << " For object : " << io.name()
1990 << " starting input from block " << proci
1991 << " of " << isPtr->name() << endl;
1992 }
1993
1994 return decomposedBlockData::readBlock(proci, *isPtr, io);
1995 }
1996 else
1997 {
1998 // Are we reading from single-master file ('processors256') or
1999 // from multi-master files ('processors256_0-9')
2000 label readComm = -1;
2001 if (!group.empty())
2002 {
2003 readComm = comm_;
2004 if (UPstream::master(comm_) && !isPtr && !fName.empty())
2005 {
2006 // In multi-master mode also open the file on the other
2007 // masters
2008 isPtr.reset(new IFstream(fName));
2009
2010 if (isPtr->good())
2011 {
2012 // Read header data (on copy)
2013 IOobject headerIO(io);
2014 headerIO.readHeader(*isPtr);
2015 }
2016 }
2017 }
2018 else
2019 {
2020 // Single master so read on world
2021 readComm = UPstream::worldComm;
2022 }
2023
2024 // Get size of file to determine communications type
2025 bool bigSize = false;
2026
2027 if (Pstream::master()) //, comm_))
2028 {
2029 // TBD: handle multiple masters?
2030 bigSize =
2031 (
2032 off_t(Foam::fileSize(fName))
2033 > off_t(maxMasterFileBufferSize)
2034 );
2035 }
2036 // Reduce (not broadcast)
2037 // - if we have multiple master files (FUTURE)
2038 reduce(bigSize, orOp<bool>()); //, UPstream::msgType(), comm_);
2039
2040 const UPstream::commsTypes myCommsType
2041 (
2042 bigSize
2045 );
2046
2047 // Read my data
2049 (
2050 readComm,
2051 fName,
2052 isPtr,
2053 io,
2054 myCommsType
2055 );
2056 }
2057 }
2058 else
2059 {
2060 if (debug)
2061 {
2062 Pout<< "masterUncollatedFileOperation::readStream :"
2063 << " For object : " << io.name()
2064 << " starting separated input from " << fName << endl;
2065 }
2066
2067 if (io.global())
2068 {
2069 // Use worldComm. Note: should not really need to gather filePaths
2070 // since we enforce sending from master anyway ...
2071 fileNameList filePaths(Pstream::nProcs());
2072 filePaths[Pstream::myProcNo()] = fName;
2073 Pstream::gatherList(filePaths);
2074
2075 boolList procValid(UPstream::listGatherValues<bool>(valid));
2076 // NB: local proc validity information required on sub-ranks too!
2077 procValid.resize(Pstream::nProcs());
2078 procValid[Pstream::myProcNo()] = valid;
2079
2080 return read(io, Pstream::worldComm, true, filePaths, procValid);
2081 }
2082 else
2083 {
2084 // Use local communicator
2085 fileNameList filePaths(Pstream::nProcs(comm_));
2086 filePaths[Pstream::myProcNo(comm_)] = fName;
2087 Pstream::gatherList(filePaths, Pstream::msgType(), comm_);
2088
2089 boolList procValid(UPstream::listGatherValues<bool>(valid, comm_));
2090 // NB: local proc validity information required on sub-ranks too!
2091 procValid.resize(Pstream::nProcs(comm_));
2092 procValid[Pstream::myProcNo(comm_)] = valid;
2093
2094 // Uniform in local comm
2095 const bool uniform = uniformFile(filePaths);
2096
2097 return read(io, comm_, uniform, filePaths, procValid);
2098 }
2099 }
2100}
2101
2102
2104(
2105 regIOobject& io,
2106 const bool masterOnly,
2108 const word& typeName
2109) const
2110{
2111 bool ok = true;
2112
2113 if (io.globalObject())
2114 {
2115 if (debug)
2116 {
2117 Pout<< "masterUncollatedFileOperation::read :"
2118 << " Reading global object " << io.name() << endl;
2119 }
2120
2121 bool ok = false;
2123 {
2124 // Do master-only reading always.
2125 const bool oldParRun = UPstream::parRun(false);
2126
2127 ok = io.readData(io.readStream(typeName));
2128 io.close();
2129
2130 UPstream::parRun(oldParRun); // Restore parallel state
2131 }
2132
2133 // Broadcast regIOobjects content
2134 if (Pstream::parRun())
2135 {
2137 (
2139 ok,
2140 io.headerClassName(),
2141 io.note()
2142 );
2143
2145 {
2146 OPBstream toAll
2147 (
2150 format
2151 );
2152 bool okWrite = io.writeData(toAll);
2153 ok = ok && okWrite;
2154 }
2155 else
2156 {
2157 IPBstream fromMaster
2158 (
2161 format
2162 );
2163 ok = io.readData(fromMaster);
2164 }
2165 }
2166 }
2167 else
2168 {
2169 if (debug)
2170 {
2171 Pout<< "masterUncollatedFileOperation::read :"
2172 << " Reading local object " << io.name() << endl;
2173 }
2174
2175 ok = io.readData(io.readStream(typeName));
2176 io.close();
2177 }
2178
2179 return ok;
2180}
2181
2182
2184(
2185 const regIOobject& io,
2186 IOstreamOption streamOpt,
2187 const bool valid
2188) const
2189{
2190 fileName pathName(io.objectPath());
2191
2192 if (debug)
2193 {
2194 Pout<< "masterUncollatedFileOperation::writeObject :"
2195 << " io:" << pathName << " valid:" << valid << endl;
2196 }
2197
2198 // Make sure to pick up any new times
2199 setTime(io.time());
2200
2201 // Update meta-data for current state
2202 const_cast<regIOobject&>(io).updateMetaData();
2203
2204 autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt, valid));
2205 OSstream& os = *osPtr;
2206
2207 // If any of these fail, return (leave error handling to Ostream class)
2208
2209 const bool ok =
2210 (
2211 os.good()
2212 && io.writeHeader(os)
2213 && io.writeData(os)
2214 );
2215
2216 if (ok)
2217 {
2219 }
2220
2221 return ok;
2222}
2223
2224
2226(
2227 const fileName& directory,
2228 const word& constantName
2229) const
2230{
2231 const auto iter = times_.cfind(directory);
2232 if (iter.found())
2233 {
2234 if (debug)
2235 {
2236 Pout<< "masterUncollatedFileOperation::findTimes :"
2237 << " Found " << iter.val()->size() << " cached times" << endl;
2238 }
2239 return *(iter.val());
2240 }
2241 else
2242 {
2243 instantList times;
2244 if (Pstream::master()) // comm_))
2245 {
2246 // Do master-only reading always.
2247 const bool oldParRun = UPstream::parRun(false);
2248
2249 times = fileOperation::findTimes(directory, constantName);
2250
2251 UPstream::parRun(oldParRun); // Restore parallel state
2252 }
2253 Pstream::broadcast(times); //, comm_);
2254
2255 if (debug)
2256 {
2257 Pout<< "masterUncollatedFileOperation::findTimes :"
2258 << " Caching times:" << times << nl
2259 << " for directory:" << directory << endl;
2260 }
2261
2262 // Note: do we also cache if no times have been found since it might
2263 // indicate a directory that is being filled later on ...
2264
2265 auto* tPtr = new DynamicList<instant>(std::move(times));
2266
2267 times_.set(directory, tPtr);
2268
2269 return *tPtr;
2270 }
2271}
2272
2273
2275(
2276 const Time& tm
2277) const
2278{
2279 if (tm.subCycling())
2280 {
2281 return;
2282 }
2283
2284 // Mutable access to instant list for modification and sorting
2285 // - cannot use auto type deduction here
2286
2287 HashPtrTable<DynamicList<instant>>::iterator iter = times_.find(tm.path());
2288
2289 if (iter.found())
2290 {
2291 DynamicList<instant>& times = *(iter.val());
2292
2293 const instant timeNow(tm.value(), tm.timeName());
2294
2295 // The start index for checking and sorting (excluding "constant")
2296 const label startIdx =
2297 (
2298 (times.empty() || times[0].name() != tm.constant())
2299 ? 0
2300 : 1
2301 );
2302
2303 // This routine always results in a sorted list of times, so first
2304 // check if the new time is greater than the latest existing time.
2305 // Can then simply append without extra searching or sorting
2306
2307 if (times.size() <= startIdx || times.last() < timeNow)
2308 {
2309 times.append(timeNow);
2310 }
2311 else if
2312 (
2314 (
2315 SubList<instant>(times, times.size()-startIdx, startIdx),
2316 timeNow
2317 ) < 0
2318 )
2319 {
2320 if (debug)
2321 {
2322 Pout<< "masterUncollatedFileOperation::setTime :"
2323 << " Caching time " << tm.timeName()
2324 << " for case:" << tm.path() << endl;
2325 }
2326
2327 times.append(timeNow);
2328
2329 SubList<instant> realTimes
2330 (
2331 times, times.size()-startIdx, startIdx
2332 );
2333 Foam::stableSort(realTimes);
2334 }
2335 }
2336
2338}
2339
2340
2343(
2344 const fileName& filePath
2345) const
2346{
2347 autoPtr<ISstream> isPtr;
2348
2349 if (Pstream::parRun())
2350 {
2351 // Insert logic of filePath. We assume that if a file is absolute
2352 // on the master it is absolute also on the sub-ranks etc.
2353
2355 filePaths[Pstream::myProcNo(Pstream::worldComm)] = filePath;
2357
2358 PstreamBuffers pBufs
2359 (
2363 );
2364
2366 {
2367 const bool uniform = uniformFile(filePaths);
2368
2369 if (uniform)
2370 {
2371 if (debug)
2372 {
2373 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2374 << " Opening global file " << filePath << endl;
2375 }
2376
2377 readAndSend
2378 (
2379 filePath,
2381 pBufs
2382 );
2383 }
2384 else
2385 {
2386 for (const int proci : Pstream::subProcs(Pstream::worldComm))
2387 {
2388 readAndSend
2389 (
2390 filePaths[proci],
2391 labelList(one{}, proci),
2392 pBufs
2393 );
2394 }
2395 }
2396 }
2397
2398
2399 labelList recvSizes;
2400 pBufs.finishedSends(recvSizes);
2401
2403 {
2404 // Read myself
2405 isPtr.reset(new IFstream(filePaths[Pstream::masterNo()]));
2406 }
2407 else
2408 {
2409 if (debug)
2410 {
2411 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2412 << " Reading " << filePath
2413 << " from processor " << Pstream::masterNo() << endl;
2414 }
2415
2416 UIPstream is(Pstream::masterNo(), pBufs);
2417
2418 List<char> buf(recvSizes[Pstream::masterNo()]);
2419 is.read(buf.data(), buf.size());
2420
2421 if (debug)
2422 {
2423 Pout<< "masterUncollatedFileOperation::NewIFstream :"
2424 << " Done reading " << buf.size() << " bytes" << endl;
2425 }
2426
2427 // A local character buffer copy of the Pstream contents.
2428 // Construct with same parameters (ASCII, current version)
2429 // as the IFstream so that it has the same characteristics.
2430
2431 isPtr.reset(new IListStream(std::move(buf)));
2432
2433 // With the proper file name
2434 isPtr->name() = filePath;
2435 }
2436 }
2437 else
2438 {
2439 // Read myself
2440 isPtr.reset(new IFstream(filePath));
2441 }
2442
2443 return isPtr;
2444}
2445
2446
2449(
2450 const fileName& pathName,
2451 IOstreamOption streamOpt,
2452 const bool valid
2453) const
2454{
2455 return autoPtr<OSstream>
2456 (
2457 new masterOFstream
2458 (
2459 pathName,
2460 streamOpt,
2461 false, // append=false
2462 valid
2463 )
2464 );
2465}
2466
2467
2469{
2471 times_.clear();
2472}
2473
2474
2476(
2477 const fileName& fName
2478) const
2479{
2480 label watchFd = -1;
2481 if (Pstream::master()) // comm_))
2482 {
2483 watchFd = monitor().addWatch(fName);
2484 }
2485 Pstream::broadcast(watchFd); //, comm_);
2486 return watchFd;
2487}
2488
2489
2491(
2492 const label watchIndex
2493) const
2494{
2495 bool ok = false;
2496 if (Pstream::master()) // comm_))
2497 {
2498 ok = monitor().removeWatch(watchIndex);
2499 }
2500 Pstream::broadcast(ok); //, comm_);
2501 return ok;
2502}
2503
2504
2506(
2507 const labelList& watchIndices,
2508 const fileName& fName
2509) const
2510{
2511 label index = -1;
2512
2513 if (Pstream::master()) // comm_))
2514 {
2515 forAll(watchIndices, i)
2516 {
2517 if (monitor().getFile(watchIndices[i]) == fName)
2518 {
2519 index = i;
2520 break;
2521 }
2522 }
2523 }
2524 Pstream::broadcast(index); //, comm_);
2525 return index;
2526}
2527
2528
2530(
2531 regIOobject& rio,
2532 const fileNameList& files
2533) const
2534{
2535 const labelList& watchIndices = rio.watchIndices();
2536
2537 DynamicList<label> newWatchIndices;
2538 labelHashSet removedWatches(watchIndices);
2539
2540 for (const fileName& f : files)
2541 {
2542 const label index = findWatch(watchIndices, f);
2543
2544 if (index == -1)
2545 {
2546 newWatchIndices.append(addWatch(f));
2547 }
2548 else
2549 {
2550 // Existing watch
2551 newWatchIndices.append(watchIndices[index]);
2552 removedWatches.erase(index);
2553 }
2554 }
2555
2556 // Remove any unused watches
2557 for (const label index : removedWatches)
2558 {
2559 removeWatch(watchIndices[index]);
2560 }
2561
2562 rio.watchIndices() = newWatchIndices;
2563}
2564
2565
2567(
2568 const label watchIndex
2569) const
2570{
2571 fileName fName;
2572 if (Pstream::master()) // comm_))
2573 {
2574 fName = monitor().getFile(watchIndex);
2575 }
2576 Pstream::broadcast(fName); //, comm_);
2577 return fName;
2578}
2579
2580
2582(
2583 const bool masterOnly,
2584 const bool syncPar
2585) const
2586{
2587 if (Pstream::master()) // comm_))
2588 {
2589 monitor().updateStates(true, false);
2590 }
2591}
2592
2593
2596(
2597 const label watchFd
2598) const
2599{
2600 unsigned int state = fileMonitor::UNMODIFIED;
2601 if (Pstream::master()) // comm_))
2602 {
2603 state = monitor().getState(watchFd);
2604 }
2605 Pstream::broadcast(state); //, comm_);
2606 return fileMonitor::fileState(state);
2607}
2608
2609
2611(
2612 const label watchFd
2613) const
2614{
2615 if (Pstream::master()) // comm_))
2616 {
2617 monitor().setUnmodified(watchFd);
2618 }
2619}
2620
2621
2622// ************************************************************************* //
label n
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:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
A HashTable of pointers to objects of type <T>, with deallocation management of the pointers.
Definition: HashPtrTable.H:68
bool found(const Key &key) const
Return true if hashed entry is found in table.
Definition: HashTableI.H:100
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
Definition: HashTableI.H:114
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition: HashTable.C:440
Input from file stream, using an ISstream.
Definition: IFstream.H:57
virtual std::istream & stdStream()
Access to underlying std::istream.
Definition: IFstream.C:94
An ISstream with internal List storage. Always UNCOMPRESSED.
Definition: IListStream.H:136
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
bool readHeader(Istream &is)
const Time & time() const
Return Time associated with the objectRegistry.
Definition: IOobject.C:506
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
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:208
const fileName & instance() const noexcept
Read access to instance path component.
Definition: IOobjectI.H:196
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:303
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:214
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:180
The IOstreamOption is a simple container for options an IOstream can normally have.
compressionType compression() const noexcept
Get the stream compression.
streamFormat
Data format (ascii | binary)
@ COMPRESSED
compression = true
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
bool equal(scalar val) const noexcept
True if values are equal (includes SMALL for rounding)
Definition: Instant.H:142
An interval of (signed) integers defined by a start and a size.
Definition: IntRange.H:64
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:57
Buffers for inter-processor communications streams (UOPstream, UIPstream).
UPstream::rangeType allProcs() const noexcept
Range of ranks indices associated with PstreamBuffers.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
void finishedScatters(const bool wait=true)
Mark all sends to sub-procs as done.
void finishedSends(const bool wait=true)
Mark sends as done.
UPstream::rangeType subProcs() const noexcept
Range of sub-processes indices associated with PstreamBuffers.
Inter-processor communications stream.
Definition: Pstream.H:63
static void gatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
static void broadcasts(const label comm, Type &arg1, Args &&... args)
Broadcast multiple items to all processes in communicator.
virtual bool read()
Re-read model coefficients if they have changed.
A List obtained as a section of another List.
Definition: SubList.H:70
instantList times() const
Search the case for valid time directories.
Definition: TimePaths.C:149
const word & constant() const
Return constant name.
Definition: TimePathsI.H:96
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
fileName path() const
Return path.
Definition: Time.H:358
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
label subCycling() const
Definition: Time.H:520
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: Tuple2.H:58
static label read(const commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Read buffer contents from given processor.
Definition: UIPstreamRead.C:42
bool found(const T &val, label pos=0) const
True if the value if found in the list.
Definition: UListI.H:265
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
const T * cdata() const noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:230
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:237
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:216
Inter-processor communications stream.
Definition: UPstream.H:59
commsTypes
Types of communications.
Definition: UPstream.H:67
@ nonBlocking
"nonBlocking"
static void freeCommunicator(const label communicator, const bool doPstream=true)
Free a previously allocated communicator.
Definition: UPstream.C:174
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:556
static constexpr int masterNo() noexcept
Process index of the master (always 0)
Definition: UPstream.H:451
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:293
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:176
bool good() const noexcept
True if the managed pointer is non-null.
Definition: autoPtr.H:145
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
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 readHeader(IOobject &io, Istream &is)
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.
const Type & value() const
Return const reference to value.
Dummy input stream, which can be used as a placeholder for interfaces taking an Istream or ISstream....
Definition: dummyISstream.H:59
fileState
Enumeration defining the file state.
Definition: fileMonitor.H:74
A class for handling file names.
Definition: fileName.H:76
Type
Enumerations to handle directory entry types.
Definition: fileName.H:81
static const fileName null
An empty fileName.
Definition: fileName.H:102
An encapsulation of filesystem-related operations.
Definition: fileOperation.H:69
virtual void flush() const
Forcibly wait until all output done. Flush any cached data.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
virtual void setTime(const Time &) const
Callback for time change.
pathType
Enumeration for the location of an IOobject.
Definition: fileOperation.H:74
@ PROCUNCOLLATEDINSTANCE
as PROCUNCOLLATED but with instance
Definition: fileOperation.H:91
@ WRITEOBJECT
write path exists
Definition: fileOperation.H:78
@ NOTFOUND
Not found.
Definition: fileOperation.H:75
@ OBJECT
io.objectPath() exists
Definition: fileOperation.H:77
@ PROCINSTANCE
as PROCOBJECT but with instance
Definition: fileOperation.H:93
@ FINDINSTANCE
file found in time directory
Definition: fileOperation.H:90
@ PROCUNCOLLATED
objectPath exists in 'processorN'
Definition: fileOperation.H:82
@ ABSOLUTE
instance is absolute directory
Definition: fileOperation.H:76
@ PROCBASEINSTANCE
as PROCBASEOBJECT but with instance
Definition: fileOperation.H:92
@ PARENTOBJECT
parent of object path
Definition: fileOperation.H:89
@ PROCOBJECT
objectPath exists in 'processorsNN_first-last'
Definition: fileOperation.H:86
@ PROCBASEOBJECT
objectPath exists in 'processorsNN'
Definition: fileOperation.H:84
static labelList ioRanks()
Retrieve list of IO ranks from FOAM_IORANKS env variable.
static const Enum< pathType > pathTypeNames_
Definition: fileOperation.H:95
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
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.
static word findInstancePath(const instantList &timeDirs, const instant &t)
Equivalent of Time::findInstance.
virtual autoPtr< ISstream > readStream(regIOobject &, const fileName &, const word &typeName, const bool valid=true) const
Reads header for regIOobject and returns an ISstream.
static labelList subRanks(const label n)
Get the list of processors that are part of this communicator.
virtual void setTime(const Time &) const
Callback for time change.
virtual fileName filePathInfo(const bool checkGlobal, const bool isFile, const IOobject &, 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 valid=true) const
Generate an OSstream that writes a file.
virtual bool rmDir(const fileName &dir, const bool silent=false) const
Remove a directory and its contents.
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. checkGlobal : also check undecomposed.
virtual bool chMod(const fileName &, const mode_t) const
Set the file mode.
virtual IOobject findInstance(const IOobject &io, const scalar startValue, const word &stopInstance) const
Find instance where IOobject is.
virtual off_t fileSize(const fileName &, const bool followLink=true) const
Return size of file.
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 void setUnmodified(const label) const
Set current state of file (using handle) to unmodified.
static void readAndSend(const fileName &filePath, const labelUList &procs, 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 uniformFile(const fileNameList &)
Same file?
virtual bool mkDir(const fileName &, mode_t=0777) const
Make directory.
virtual instantList findTimes(const fileName &, const word &) const
Get sorted list of times.
virtual bool mv(const fileName &src, const fileName &dst, const bool followLink=false) const
Rename src to dst.
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool valid=true) const
Writes a regIOobject (so header, contents and divider).
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)
mode
Enumeration for pressure calculation mode.
Definition: pressure.H:359
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:62
virtual fileName filePath() const
Return complete path + object name if the file exists.
int myProcNo() const noexcept
Return processor number.
A class for managing references or pointers (no reference counting)
Definition: refPtr.H:58
bool exists() const noexcept
True if expression is non-empty.
Definition: regExpCxxI.H:139
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:76
const labelList & watchIndices() const noexcept
Read access to file-monitoring handles.
Definition: regIOobjectI.H:202
splitCell * master() const
Definition: splitCell.H:113
label readDir()
Read directory and populate the 'available' files.
virtual void addWatch()
Add file watch on object (READ_IF_MODIFIED)
type
Volume classification types.
Definition: volumeType.H:66
A class for handling words, derived from Foam::string.
Definition: word.H:68
static const word null
An empty word.
Definition: word.H:80
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool
Definition: EEqn.H:20
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:517
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define DetailInfo
Definition: evalEntry.C:37
OBJstream os(runTime.globalPath()/outputName)
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
runTimeSource setTime(sourceTimes[sourceTimeIndex], sourceTimeIndex)
#define WarningInFunction
Report a warning using Foam::Warning.
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:243
Namespace for OpenFOAM.
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
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: MSwindows.C:633
List< label > labelList
A List of labels.
Definition: List.H:66
mode_t mode(const fileName &name, const bool followLink=true)
Return the file mode, normally following symbolic links.
Definition: MSwindows.C:572
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
off_t fileSize(const fileName &name, const bool followLink=true)
Return size of file or -1 on failure (normally follows symbolic links).
Definition: MSwindows.C:684
IOerror FatalIOError
int infoDetailLevel
Global for selective suppression of Info output.
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: MSwindows.C:666
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
label findSortedIndex(const ListType &input, typename ListType::const_reference val, const label start=0)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:356
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:624
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
word format(conversionProperties.get< word >("format"))
labelList f(nPoints)
#define registerOptSwitch(Name, Type, SwitchVar)
const volScalarField & cp
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:346