Loading...
Searching...
No Matches
fileOperation.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
29#include "fileOperation.H"
30#include "objectRegistry.H"
31#include "registerSwitch.H"
32#include "stringOps.H"
33#include "Time.H"
34#include "OSspecific.H" // for Foam::isDir etc
35#include <cinttypes>
37/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
38
39namespace Foam
40{
44
46 (
48 (
49 "fileHandler",
50 //Foam::fileOperations::uncollatedFileOperation::typeName,
51 "uncollated",
53 )
54 );
55}
56
57// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
58
61({
62 { fileOperation::NOTFOUND, "notFound" },
63 { fileOperation::ABSOLUTE, "absolute" },
64 { fileOperation::OBJECT, "objectPath" },
65 { fileOperation::WRITEOBJECT, "writeObject" },
66 { fileOperation::PROCUNCOLLATED, "uncollatedProc" },
67 { fileOperation::PROCBASEOBJECT, "globalProc" },
68 { fileOperation::PROCOBJECT, "localProc" },
69 { fileOperation::PARENTOBJECT, "parentObjectPath" },
70 { fileOperation::FINDINSTANCE, "findInstance" },
71 { fileOperation::PROCUNCOLLATEDINSTANCE, "uncollatedProcInstance" },
72 { fileOperation::PROCBASEINSTANCE, "globalProcInstance" },
73 { fileOperation::PROCINSTANCE, "localProcInstance" }
74});
75
76
78
79//- Caching (e.g. of time directories) - enabled by default
81
82int Foam::fileOperation::nProcsFilter_(-1);
83
84// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
85
86namespace
87{
88
89// Need to parse the numbers
90// from "processors(\d+)" and
91// from "processors(\d+)_(\d+)-(\d+)"
92//
93// Receive the string matching "^(\d+)(?:_(\d+)-(\d+))?/?$"
94//
95// \1 = numProcs
96// \2 = firstProc
97// \3 = lastProc
98//
99// Return true on success and set parameters numProcs and group (size,start)
100//
101// Use low-level C-string to integer parsing to drive the sequence.
102//
103// For simplicity, also skip INT_MAX checks everywhere but check for
104// - (errno) for success
105// - (nptr == endptr) for leading junk
106// - (*endptr != endChar) for trailing junk
107// - skip INT_MAX checks as being too pessimistic
108
109static bool parseProcsNumRange
110(
111 const std::string str,
112 int& numProcs,
114)
115{
116 const char * nptr = str.c_str();
117 char *endptr = nullptr;
118
119 // 1. numProcs
120 errno = 0;
121 intmax_t parsed = std::strtoimax(nptr, &endptr, 10);
122 if (errno || nptr == endptr) return false; // bad parse
123
124 const int nProcs = int(parsed);
125
126 // End of string? Then no range and we are done.
127 if (*endptr == '\0')
128 {
129 numProcs = nProcs;
130 return true;
131 }
132
133 // Parse point at start of range ('_' character)?
134 if (*endptr != '_') return false;
135 nptr = ++endptr;
136
137
138 // 2. firstProc
139 errno = 0;
140 parsed = std::strtoimax(nptr, &endptr, 10);
141 if (errno || nptr == endptr) return false; // bad parse
142
143 const int firstProc = int(parsed);
144
145 // Parse point at range separator ('-' character)?
146 if (*endptr != '-') return false;
147 nptr = ++endptr;
148
149
150 // 3. lastProc
151 errno = 0;
152 parsed = std::strtoimax(nptr, &endptr, 10);
153 if (errno || nptr == endptr) return false; // bad parse
154
155 const int lastProc = int(parsed);
156
157
158 if
159 (
160 // Parse point at end of string
161 (*endptr == '\0')
162
163 // Input plausibility
164 // Accept nProcs == 0 in case that becomes useful in the future
165 && (nProcs >= 0 && firstProc >= 0 && firstProc <= lastProc)
166 )
167 {
168 numProcs = nProcs;
169
170 // Convert first/last to start/size
171 group.reset(firstProc, lastProc-firstProc+1);
172
173 return true;
174 }
175
176 return false;
177}
178
179} // End anonymous namespace
180
181
182// Sorting of processor directories
183#include "stringOpsSort.H"
184namespace
185{
186
187// Sort processor directory names (natural order)
188// - not strictly necessary
189void sortProcessorDirs(Foam::UList<Foam::fileOperation::dirIndex>& dirs)
190{
191 if (dirs.size() > 1)
192 {
193 std::stable_sort
194 (
195 dirs.begin(),
196 dirs.end(),
197 []
198 (
201 ) -> bool
202 {
203 return
204 Foam::stringOps::natural_sort::compare
205 (
206 a.first(),
207 b.first()
208 ) < 0;
209 }
210 );
211 }
212}
213
214} // End anonymous namespace
216
217// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
218
221(
222 const fileNameList& dirEntries,
223 const word& constantName
224)
225{
226 // Check for "constant"
227 bool haveConstant = false;
228
229 if (!constantName.empty())
230 {
231 for (const fileName& dirName : dirEntries)
232 {
233 if (dirName == constantName)
234 {
235 haveConstant = true;
236 break;
237 }
238 }
239 }
240
241 instantList times(dirEntries.size() + 1);
242 label nTimes = 0;
243
244 if (haveConstant)
245 {
246 times[nTimes].value() = 0;
247 times[nTimes].name() = constantName;
248 ++nTimes;
249 }
250
251 // Parse directory entries for scalar values
252 for (const fileName& dirName : dirEntries)
253 {
254 if (readScalar(dirName, times[nTimes].value()))
255 {
256 times[nTimes].name() = dirName;
257 ++nTimes;
258 }
259 }
260
261 times.resize(nTimes);
262
263 if (haveConstant)
264 {
265 if (nTimes > 2)
266 {
267 std::sort(&times[1], times.end(), instant::less());
268 }
269 }
270 else if (nTimes > 1)
271 {
272 std::sort(times.begin(), times.end(), instant::less());
273 }
275 return times;
276}
277
278
280{
281 if (names.empty())
282 {
283 return false;
284 }
285
286 const auto& object0 = names[0];
287
288 for (label i = 1; i < names.size(); ++i)
289 {
290 if (object0 != names[i])
291 {
292 return false;
293 }
294 }
296 return true;
297}
298
299
300bool Foam::fileOperation::uniformFile(const label comm, const fileName& name)
301{
302 if (!UPstream::parRun())
303 {
304 return true;
305 }
306
307 fileName masterName(name);
308
309 Pstream::broadcast(masterName, comm);
310
311 return returnReduceAnd((masterName == name), comm);
313
314
315// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
316
318{
319 if (!monitorPtr_)
320 {
321 monitorPtr_.reset
322 (
323 new fileMonitor
324 (
327 )
328 );
330 return *monitorPtr_;
331}
332
333
335(
336 const UList<instant>& extraTimes,
337 const word& constantName,
338 instantList& times
339)
340{
341 if (extraTimes.size())
342 {
343 const bool haveConstant =
344 (
345 times.size()
346 && times[0].name() == constantName
347 );
348
349 const bool haveExtraConstant =
350 (
351 extraTimes.size()
352 && extraTimes[0].name() == constantName
353 );
354
355 // Combine times
356 instantList combinedTimes(times.size()+extraTimes.size());
357 label sz = 0;
358 label extrai = 0;
359 if (haveExtraConstant)
360 {
361 extrai = 1;
362 if (!haveConstant)
363 {
364 combinedTimes[sz++] = extraTimes[0]; // constant
365 }
366 }
367 forAll(times, i)
368 {
369 combinedTimes[sz++] = times[i];
370 }
371 for (; extrai < extraTimes.size(); extrai++)
372 {
373 combinedTimes[sz++] = extraTimes[extrai];
374 }
375 combinedTimes.setSize(sz);
376 times.transfer(combinedTimes);
377
378 // Sort
379 if (times.size() > 1)
380 {
381 label starti = 0;
382 if (times[0].name() == constantName)
383 {
384 starti = 1;
385 }
386 std::sort(&times[starti], times.end(), instant::less());
387
388 // Filter out duplicates
389 label newi = starti+1;
390 for (label i = newi; i < times.size(); i++)
391 {
392 if (times[i].value() != times[i-1].value())
393 {
394 if (newi != i)
395 {
396 times[newi] = times[i];
397 }
398 newi++;
399 }
400 }
401
402 times.setSize(newi);
404 }
405}
406
407
408bool Foam::fileOperation::isFileOrDir(const bool isFile, const fileName& f)
409{
411}
412
413
416(
417 const fileName& fName,
418 const bool syncPar
419) const
420{
421 // If path is local to a processor (e.g. contains 'processor2')
422 // find the corresponding actual processor directory (e.g. 'processors4')
423 // and index (2)
424
425 // Behaviour affected by
426 // - UPstream::parRun()
427 // - syncPar : usually true, only uncollated does false. Determines
428 // if directory status gets synchronised
429 // - distributed() : different processors have different roots
430 // - fileModificationChecking : (uncollated only) do IO on master only
431 // - nProcsFilter_ : if set to
432 // 0 : accept any directory (e.g. for redistributePar where we don't
433 // know yet number of read/write procs)
434 // -1 : accept only processorsDDD where DDD is nProcs(worldComm)
435 // >0 : accept the exact mentioned number of prcessors
436
437
438 // Collated : check whether/how to filter processorsXXX directory names
439 const label targetNProcs
440 (
441 (UPstream::parRun() && nProcsFilter_ < 0)
443 : nProcsFilter_
444 );
445
446
447 fileName path, pDir, local;
448 procRangeType group;
449 label numProcs;
450 const label proci =
451 splitProcessorPath(fName, path, pDir, local, group, numProcs);
452
453 if (proci != -1)
454 {
455 const fileName procPath(path/pDir);
456
457 if (cacheLevel() > 0)
458 {
459 const auto iter = procsDirs_.cfind(procPath);
460
461 if (iter.good())
462 {
463 return iter.val();
464 }
465 }
466
467 DynamicList<dirIndex> procDirs;
468 fileNameList dirEntries;
469
470 // Read all directories to see any beginning with processor
471 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
472
473 // Note: use parallel synchronised reading so cache will be same
474 // order on all processors
475
476 const bool readDirMasterOnly
477 (
478 UPstream::parRun() && !distributed()
480 );
481
482 // The above selection excludes masterUncollated, which uses inotify or
483 // timeStamp but provides its own internals for readDir() anyhow.
484
485 if (readDirMasterOnly)
486 {
487 // Parallel and non-distributed
488 // Read on master only and send to subProcs
489
491 {
493
495 << "readDir on master: send " << dirEntries.size()
496 << " names to sub-processes" << endl;
497 }
498
500 }
501 else
502 {
503 // Serial or distributed roots.
504 // Handle readDir() with virtual method
505
506 if (debug)
507 {
508 Pout<< "readDir without special master/send treatment"
509 << endl;
510 }
511
513 }
514
515 // Extract info from processorN or processorsNN
516 // - highest processor number
517 // - directory+offset containing data for proci
518
519 label nProcs = 0;
520 for (const fileName& dirN : dirEntries)
521 {
522 // Analyse directory name
523 label rNum(-1);
524 const label readProci =
525 fileOperation::detectProcessorPath(dirN, group, &rNum);
526
527 nProcs = Foam::max(nProcs, readProci+1);
528
529 Tuple2<pathType, int> pathTypeIdx(pathType::NOTFOUND, 0);
530
531 if (proci == readProci)
532 {
533 // Found "processorN"
534 pathTypeIdx.first() = pathType::PROCUNCOLLATED;
535 }
536 else if (rNum != -1)
537 {
538 if (targetNProcs > 1 && (targetNProcs != rNum))
539 {
540 // Current directory can never contain wanted proc
541 //Pout<< "For fName:" << fName
542 // << "Ignoring directory " << dirN
543 // << " since parsed rNum:" << rNum
544 // << " targetNProcs:" << targetNProcs
545 // << endl;
546 //error::printStack(Pout);
547
548 continue;
549 }
550
551 // "processorsNN" or "processorsNN_start-end"
552 nProcs = Foam::max(nProcs, rNum);
553
554 if (group.empty())
555 {
556 // "processorsNN"
557
558 if (proci < rNum || (nProcsFilter_ == 0))
559 {
560 // And it is also in range.
561 // Eg for "processors4": 3 is ok, 10 is not
562
563 pathTypeIdx.first() = pathType::PROCBASEOBJECT;
564 pathTypeIdx.second() = proci;
565 }
566 }
567 else if (group.contains(proci) || (nProcsFilter_ == 0))
568 {
569 // "processorsNN_start-end"
570 // - save the local proc offset
571
572 pathTypeIdx.first() = pathType::PROCOBJECT;
573 pathTypeIdx.second() = (proci - group.start());
574 }
575 }
576
577 if (pathTypeIdx.first() != pathType::NOTFOUND)
578 {
579 procDirs.emplace_back(dirN, pathTypeIdx);
580 }
581 }
582
583 // Sort processor directory names (natural order)
584 sortProcessorDirs(procDirs);
585
586
587 // Global check of empty/exists.
588 // 1 : empty directory
589 // 2 : non-empty directory
590 // 3 : mixed empty/non-empty directory (after reduce)
591 // Combines andOp<bool>() and orOp<bool>() in single operation
592
593 unsigned int procDirsStatus = (procDirs.empty() ? 1u : 2u);
594
595 if (debug)
596 {
597 Pout<< "fileOperation::lookupProcessorsPath " << procPath
598 << " detected:" << flatOutput(procDirs) << endl;
599 }
600
601 if (UPstream::parRun() && (!distributed() || syncPar))
602 {
603 reduce(procDirsStatus, bitOrOp<unsigned int>()); // worldComm
604
605 if (procDirsStatus == 3u)
606 {
607 // Mixed empty/exists for procDirs.
608 // Synthesize missing directory name (consistency in cache
609 // existence).
610 // Cannot reliably synthesize RANK-COLLATED, only COLLATED or
611 // UNCOLLATED.
612 //
613 // RANK-COLLATED should have been read from its corresponding
614 // master anyhow
615
616 int flavour(pathType::PROCUNCOLLATED);
617 for (const dirIndex& pDir : procDirs)
618 {
619 flavour = Foam::max(flavour, int(pDir.second().first()));
620 }
621
622 reduce(nProcs, maxOp<label>()); // worldComm
623 reduce(flavour, maxOp<int>()); // worldComm
624
625 if (procDirs.empty())
626 {
627 Tuple2<pathType, int> pathTypeIdx(pathType(flavour), 0);
628
629 if
630 (
631 pathTypeIdx.first() == pathType::PROCBASEOBJECT
632 // Do not restrict to currently used processors
633 // && proci < nProcs
634 )
635 {
636 pathTypeIdx.second() = proci;
637
638 procDirs.emplace_back
639 (
640 processorsBaseDir + Foam::name(nProcs),
641 pathTypeIdx
642 );
643 }
644 else
645 {
646 // - pathType::PROCUNCOLLATED
647 // - poor fallback for pathType::PROCOBJECT
648 // - out-of-range pathType::PROCBASEOBJECT
649
650 procDirs.emplace_back
651 (
652 "processor" + Foam::name(proci),
653 pathTypeIdx
654 );
655 }
656
657 if (debug)
658 {
659 Pout<< "fileOperation::lookupProcessorsPath "
660 << procPath
661 << " synthetic:" << procDirs << endl;
662 }
663 }
664 }
665 }
666 else if (!UPstream::parRun())
667 {
668 // Serial: use the number of decompositions (if found)
669 if (nProcs)
670 {
671 const_cast<fileOperation&>(*this).nProcs(nProcs);
672 }
673 }
674
675 if (procDirsStatus & 2u)
676 {
677 if (cacheLevel() > 0)
678 {
679 procsDirs_.insert(procPath, procDirs);
680
681 // Make sure to return a reference
682 return procsDirs_[procPath];
683 }
684 else
685 {
686 return refPtr<dirIndexList>::New(procDirs);
687 }
688 }
689 }
690
692}
693
694
698 return lookupAndCacheProcessorsPath(fName, true);
699}
700
701
703{
704 // Generate output filename for object
705 fileName objPath(objectPath(io, word::null));
706
707 // Test for either directory or a (valid) file & IOobject
708 bool ok;
709 if (io.name().empty())
710 {
711 ok = isDir(objPath);
712 }
713 else
714 {
715 ok =
716 (
717 isFile(objPath)
718 // object with local scope
719 && io.typeHeaderOk<regIOobject>(false)
720 );
721 }
722
723 if (!ok)
724 {
725 // Re-test with searched for objectPath. This is for backwards
726 // compatibility
727 fileName originalPath(filePath(io.objectPath()));
728 if (originalPath != objPath)
729 {
730 // Test for either directory or a (valid) file & IOobject
731 if (io.name().empty())
732 {
733 ok = isDir(originalPath);
734 }
735 else
736 {
737 ok =
738 (
739 isFile(originalPath)
740 // object with local scope
741 && io.typeHeaderOk<regIOobject>(false)
742 );
743 }
744 }
745 }
746
747 return ok;
749
750
751// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
752
754(
755 const Tuple2<label, labelList>& commAndIORanks,
756 const bool distributedRoots
757)
758:
759 comm_(commAndIORanks.first()),
760 nProcs_(UPstream::nProcs(UPstream::worldComm)),
761 distributed_(distributedRoots),
762 ioRanks_(commAndIORanks.second())
763{}
764
765
767(
768 const label comm,
769 const labelUList& ioRanks,
770 const bool distributedRoots
771)
772:
773 comm_(comm),
774 nProcs_(UPstream::nProcs(UPstream::worldComm)),
775 distributed_(distributedRoots),
776 ioRanks_(ioRanks)
778
779
780// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
781
783(
784 const IOobject& io,
785 const word& typeName
786) const
788 return io.objectPath();
789}
790
791
793(
794 const regIOobject& io,
795 IOstreamOption streamOpt,
796 const bool writeOnProc
797) const
798{
799 if (writeOnProc)
800 {
801 const fileName pathName(io.objectPath());
802
803 mkDir(pathName.path());
804
805 autoPtr<OSstream> osPtr(NewOFstream(pathName, streamOpt));
806
807 if (!osPtr)
808 {
809 return false;
810 }
811
812 OSstream& os = *osPtr;
813
814 // Update meta-data for current state
815 const_cast<regIOobject&>(io).updateMetaData();
816
817 // If any of these fail, return (leave error handling to Ostream class)
818
819 const bool ok =
820 (
821 os.good()
822 && io.writeHeader(os)
823 && io.writeData(os)
824 );
825
826 if (ok)
827 {
829 }
830
831 return ok;
833 return true;
834}
835
836
838(
839 const fileName& fName,
840 const bool checkGzip,
841 const bool followLink
842) const
843{
844 if (debug)
845 {
846 Pout<< "fileOperation::filePath :" << " fName:" << fName << endl;
847 }
848
849 fileName path, pDir, local;
850 procRangeType group;
851 label numProcs;
852 label proci =
853 splitProcessorPath(fName, path, pDir, local, group, numProcs);
854
855 if (numProcs != -1)
856 {
857 WarningInFunction << "Filename is already adapted:" << fName << endl;
858 }
859
860 // Give preference to processors variant
861 fileName foundName;
862 if (proci != -1)
863 {
864 // Get all processor directories
865 refPtr<dirIndexList> procDirs(lookupProcessorsPath(fName));
866 for (const dirIndex& dirIdx : procDirs())
867 {
868 const fileName& procDir = dirIdx.first();
869
870 fileName collatedName(path/procDir/local);
871 if (exists(collatedName, checkGzip, followLink))
872 {
873 if (debug)
874 {
875 Pout<< "fileOperation::filePath : " << collatedName << endl;
876 }
877 foundName = collatedName;
878 }
879 }
880 }
881
882 //if (returnReduceOr(foundName.empty())) // worldComm
883 if (foundName.empty())
884 {
885 // There is at least one processor that cannot find the processors
886 // directory. Re-do with straight supplied filename
887 if (exists(fName, checkGzip, followLink))
888 {
889 if (foundName.empty())
890 {
891 foundName = fName;
892 }
893 }
894 }
895
896 if (!foundName.empty())
897 {
898 if (debug)
899 {
900 Pout<< "fileOperation::filePath : " << foundName << endl;
901 }
902 }
903 else
904 {
905 if (debug)
906 {
907 Pout<< "fileOperation::filePath : Not found" << endl;
908 }
910 return foundName;
911}
912
913
914Foam::label Foam::fileOperation::addWatch(const fileName& fName) const
916 return monitor().addWatch(fName);
917}
918
919
920bool Foam::fileOperation::removeWatch(const label watchIndex) const
922 return monitor().removeWatch(watchIndex);
923}
924
925
927(
928 const labelList& watchIndices,
929 const fileName& fName
930) const
931{
932 forAll(watchIndices, i)
933 {
934 if (getFile(watchIndices[i]) == fName)
935 {
936 return i;
937 }
939 return -1;
940}
941
942
944(
945 regIOobject& rio,
946 const fileNameList& files
947) const
948{
949 const labelList& watchIndices = rio.watchIndices();
950
951 DynamicList<label> newWatchIndices;
952 labelHashSet removedWatches(watchIndices);
953
954 for (const fileName& f : files)
955 {
956 const label index = findWatch(watchIndices, f);
957
958 if (index == -1)
959 {
960 newWatchIndices.append(addWatch(f));
961 }
962 else
963 {
964 // Existing watch
965 newWatchIndices.append(watchIndices[index]);
966 removedWatches.erase(index);
967 }
968 }
969
970 // Remove any unused watches
971 for (const label index : removedWatches)
972 {
973 removeWatch(watchIndices[index]);
974 }
976 rio.watchIndices() = newWatchIndices;
977}
978
979
980Foam::fileName Foam::fileOperation::getFile(const label watchIndex) const
982 return monitor().getFile(watchIndex);
983}
984
985
987(
988 const bool masterOnly,
989 const bool syncPar
990) const
992 monitor().updateStates(masterOnly, UPstream::parRun());
993}
994
995
997(
998 const label watchFd
999) const
1001 return monitor().getState(watchFd);
1002}
1003
1004
1005void Foam::fileOperation::setUnmodified(const label watchFd) const
1007 monitor().setUnmodified(watchFd);
1008}
1009
1010
1012(
1013 const fileName& directory,
1014 const word& constantName
1015) const
1016{
1017 if (debug)
1018 {
1019 Pout<< "fileOperation::findTimes : Finding times in directory "
1020 << directory << endl;
1021 }
1022
1023 // Note: do NOT use master-only reading here (as per lookupProcessorsPath)
1024 // since this routine is called on an individual processorN directory
1025
1026 // Read directory entries into a list
1027 fileNameList dirEntries(Foam::readDir(directory, fileName::DIRECTORY));
1028 instantList times = sortTimes(dirEntries, constantName);
1029
1030
1031 // Get all processor directories
1032 refPtr<dirIndexList> procDirs(lookupProcessorsPath(directory));
1033 for (const dirIndex& dirIdx : procDirs())
1034 {
1035 const fileName& procDir = dirIdx.first();
1036 fileName collDir(processorsPath(directory, procDir));
1037 if (!collDir.empty() && collDir != directory)
1038 {
1039 fileNameList extraEntries
1040 (
1042 (
1043 collDir,
1045 )
1046 );
1047 mergeTimes
1048 (
1049 sortTimes(extraEntries, constantName),
1050 constantName,
1051 times
1052 );
1053 }
1054 }
1055
1056 if (debug)
1057 {
1058 Pout<< "fileOperation::findTimes : Found times:" << flatOutput(times)
1059 << endl;
1061 return times;
1062}
1063
1064
1066(
1067 const IOobject& startIO,
1068 const scalar startValue,
1069 const word& stopInstance,
1070 const bool constant_fallback
1071) const
1072{
1073 const Time& time = startIO.time();
1074 IOobject io(startIO);
1075
1076 // Note: - if name is empty, just check the directory itself
1077 // - check both for isFile and headerOk since the latter does a
1078 // filePath so searches for the file.
1079 // - check for an object with local file scope (so no looking up in
1080 // parent directory in case of parallel)
1081
1082 if (exists(io))
1083 {
1085 << "Found exact match for \"" << io.name()
1086 << "\" in " << io.instance()/io.local()
1087 << endl;
1088
1089 return io;
1090 }
1091
1092 // Handling failures afterwards
1093 const bool exitIfMissing = startIO.isReadRequired();
1094
1095 enum failureCodes { FAILED_STOPINST = 1, FAILED_CONSTINST = 2 };
1096 int failed(0);
1097
1098 // The timeDirs
1099 instantList ts
1100 (
1101 this->findTimes
1102 (
1103 time.path(), // time.path(layout)
1104 time.constant()
1105 )
1106 );
1107
1108 {
1109 label instIndex = ts.size()-1;
1110
1111 // Backward search for first time that is <= startValue
1112 for (; instIndex >= 0; --instIndex)
1113 {
1114 if (ts[instIndex] <= startValue)
1115 {
1116 break;
1117 }
1118 }
1119
1120 // Continue (forward) searching from here
1121 for (; instIndex >= 0; --instIndex)
1122 {
1123 io.instance() = ts[instIndex].name();
1124
1125 // Shortcut: if actual directory is the timeName we've
1126 // already tested it
1127 if
1128 (
1129 io.instance() == startIO.instance()
1130 && io.instance() != stopInstance
1131 )
1132 {
1133 continue;
1134 }
1135
1136 if (exists(io))
1137 {
1139 << "Found exact match for \"" << io.name()
1140 << "\" in " << io.instance()/io.local()
1141 << endl;
1142
1143 return io;
1144 }
1145
1146 // Check if hit minimum instance
1147 if (io.instance() == stopInstance)
1148 {
1150 << "Hit stopInstance " << stopInstance << endl;
1151
1152 if (exitIfMissing)
1153 {
1154 failed = failureCodes::FAILED_STOPINST;
1155 }
1156 else
1157 {
1158 // At the stopInstance
1159 return io;
1160 }
1161 break;
1162 }
1163 }
1164
1165
1166 // times() usually already includes the constant() so would
1167 // have been checked above. However, re-test under these conditions:
1168 // - times() is empty. Sometimes this can happen (e.g. decomposePar
1169 // with collated)
1170 // - times()[0] is not constant
1171 // - Times is empty.
1172 // Sometimes this can happen (eg, decomposePar with collated)
1173 // - Times[0] is not constant
1174 // - The startValue is negative (eg, kivaTest).
1175 // This plays havoc with the reverse search, causing it to miss
1176 // 'constant'
1177
1178 if
1179 (
1180 !failed
1181 && (ts.empty() || ts[0].name() != time.constant() || startValue < 0)
1182 )
1183 {
1184 io.instance() = time.constant();
1185
1186 if (exists(io))
1187 {
1189 << "Found constant match for \"" << io.name()
1190 << "\" in " << io.instance()/io.local()
1191 << endl;
1192
1193 return io;
1194 }
1195 }
1196 }
1197
1198
1199 if (!failed)
1200 {
1201 if (exitIfMissing)
1202 {
1203 failed = failureCodes::FAILED_CONSTINST;
1204 }
1205 else if (constant_fallback)
1206 {
1207 io.instance() = time.constant();
1208 }
1209 else
1210 {
1211 io.instance().clear();
1212 }
1213 }
1214
1215
1216 // Handle failures
1217 // ~~~~~~~~~~~~~~~
1218
1219 if (failed)
1220 {
1221 FatalErrorInFunction << "Cannot find";
1222
1223 if (!io.name().empty())
1224 {
1226 << " file \"" << io.name() << "\" in";
1227 }
1228
1230 << " directory "
1231 << io.local() << " in times "
1232 << startIO.instance() << " down to ";
1233
1234 if (failed == failureCodes::FAILED_STOPINST)
1235 {
1236 FatalError << stopInstance;
1237 }
1238 else // FAILED_CONSTINST
1239 {
1240 FatalError << "constant";
1241 }
1243 }
1245 return io;
1246}
1247
1248
1250(
1251 const objectRegistry& obr,
1252 const fileName& instance,
1253 const fileName& local,
1254 word& newInstance
1255) const
1256{
1258
1259 if (debug)
1260 {
1261 Pout<< "fileOperation::readObjects :"
1262 << " object-path:" << obr.objectPath()
1263 << " instance" << instance
1264 << " local:" << local
1265 << " layout:" << int(layout) << endl;
1266 }
1267
1268 // dbDir() is relative to Time,
1269 // so use dbDir() from self or from parent, but not both!
1270
1271 // NOTE: should not use IOobject::path(..) here since that generates
1272 // values based on the obr.db().dbDir() instead of obr.dbDir()
1273 // [issue #3458]
1274
1275 fileName path;
1276 if (obr.dbDir().empty())
1277 {
1278 // Fallback (old code) using obr.db().dbDir() ...
1279 path = obr.path(layout, instance, local);
1280 }
1281 else
1282 {
1283 // This could (should?) be a method in objectRegistry
1284 path = obr.rootPath()/obr.caseName(layout)/instance/obr.dbDir()/local;
1285 }
1286
1287 newInstance.clear();
1288 fileNameList objectNames;
1289
1290 if (Foam::isDir(path))
1291 {
1292 newInstance = instance;
1293 objectNames = Foam::readDir(path, fileName::Type::FILE);
1294 }
1295 else
1296 {
1297 // Get processors equivalent of path
1298 fileName procsPath(filePath(path));
1299
1300 if (!procsPath.empty())
1301 {
1302 newInstance = instance;
1303 objectNames = Foam::readDir(procsPath, fileName::Type::FILE);
1304 }
1306 return objectNames;
1307}
1308
1309
1311(
1312 const fileName& dir,
1313 const fileName& local,
1314 const label wanted // expected nProcs. 0 if not supplied
1315) const
1316{
1317 label nProcs = 0;
1318 if (UPstream::master(comm_))
1319 {
1321
1322 // E.g. (maybe left over)
1323 // processor0
1324 // processor1
1325 // processors5
1326 // processor90 // gap!
1327 // processors10
1328 //
1329 //- if wanted is 2 then processor0,1 is enough
1330 //- if wanted is not set then return highest valid range
1331 // (processors10 in above case)
1332 //- if wanted cannot be matched (e.g. 37) return 0
1333
1334 // For marking off contiguous ranges
1335 bitSet foundDirs;
1336 if (wanted > 0)
1337 {
1338 foundDirs.resize(wanted);
1339 }
1340
1341 // Detect any processorsDDD or processorDDD
1342 label maxProc = -1;
1343 for (const fileName& dirN : dirNames)
1344 {
1345 fileName rp, rd, rl;
1346 procRangeType group;
1347 label rNum;
1348
1349 const label readProci =
1350 splitProcessorPath(dirN, rp, rd, rl, group, rNum);
1351
1352 maxProc = Foam::max(maxProc, readProci);
1353
1354 if (rNum > 0) // processorsDDD where DDD>0
1355 {
1356 // Use processors number
1357 maxProc = Foam::max(maxProc, rNum-1);
1358 // Mark in cache. TBD separate handling for groups?
1359 foundDirs.set(labelRange(0, rNum));
1360
1361 if (wanted == rNum)
1362 {
1363 // Exact match of processorsDDD. Direct exit.
1364 maxProc = rNum-1;
1365 foundDirs.resize(rNum);
1366 break;
1367 }
1368 }
1369 else if (readProci >= 0)
1370 {
1371 // Mark in cache
1372 foundDirs.set(readProci);
1373 }
1374 }
1375 nProcs = maxProc+1;
1376
1377 // Override with any gaps in processorDDD numbering (can never happen
1378 // with collated)
1379 const label gapIndex = foundDirs.find_first_not();
1380 if (gapIndex > 0)
1381 {
1382 nProcs = gapIndex-1;
1383 }
1384
1385 if (nProcs == 0 && Foam::isDir(dir/processorsBaseDir))
1386 {
1388 << "Defunct collated naming: " << processorsBaseDir << nl
1389 << "Manually rename with the decomposition number. Eg,"
1390 << nl << nl
1391 << " mv processors processors16" << nl << nl
1392 << "...returning 1" << endl;
1393
1394 nProcs = 1;
1395 }
1396 }
1397 Pstream::broadcast(nProcs, comm_);
1398 return nProcs;
1399}
1401
1402void Foam::fileOperation::flush() const
1403{
1404 if (debug)
1405 {
1406 Pout<< "fileOperation::flush : clearing processor directories cache"
1407 << endl;
1408 }
1409 procsDirs_.clear();
1410}
1412
1414{
1415 if (debug)
1416 {
1417 Pout<< "fileOperation::sync : parallel synchronisation"
1418 << endl;
1419 }
1420
1422 (
1424 nProcs_,
1426 );
1427}
1429
1431(
1432 const IOobject& io,
1433 const word& procsDir
1434) const
1435{
1436 return io.rootPath()/io.globalCaseName()/procsDir;
1437}
1439
1441(
1442 const IOobject& io,
1443 const word& instance,
1444 const word& procsDir
1445) const
1446{
1447 return
1448 processorsCasePath(io, procsDir)
1449 /instance
1450 /io.db().dbDir()
1451 /io.local();
1452}
1454
1456(
1457 const fileName& dir,
1458 const word& procsDir
1459) const
1460{
1461 // Check if directory is processorDDD
1462
1463 const word caseName(dir.name());
1464 if (caseName.starts_with("processor"))
1465 {
1466 // Reject both '^processor$' and '^processors.*$'
1467
1468 if (!std::isdigit(caseName[9]))
1469 {
1470 WarningInFunction << "Directory " << dir
1471 << " does not end in old-style processorDDD" << endl;
1472 }
1473
1474 return dir.path()/procsDir;
1475 }
1476
1477 return fileName();
1478}
1480
1482(
1483 const fileName& objPath,
1484 fileName& path,
1485 fileName& procDir,
1486 fileName& local,
1487
1488 procRangeType& group,
1489 label& nProcs
1490)
1491{
1492 // Return value
1493 label returnProci = -1;
1494
1495 // Clear out the return parameters
1496
1497 path.clear();
1498 procDir.clear();
1499 local.clear();
1500 group.clear();
1501
1502 // Invalidate detected number of processors
1503 nProcs = -1;
1504
1505 // The local processor group is read as first/last, but stored as
1506 // start/size. Empty with start=0, size=0 if no range is detected
1507
1508
1509 // Start of 'processor..' directory name (the procDir)
1510 size_t pos = 0;
1511
1512 // The slash starting the trailing (local) directory
1513 size_t slashLocal = string::npos;
1514
1515
1516 // Search for processor at start of string or after /processor
1517 //
1518 // 'processor(\d+)'
1519 // 'processors(\d+)'
1520 // 'processors(\d+)_(\d+)-(\d+)'
1521
1522 for
1523 (
1524 /*nil*/;
1525 (pos = objPath.find("processor", pos)) != string::npos;
1526 pos += 9
1527 )
1528 {
1529 if (pos > 0 && objPath[pos-1] != '/')
1530 {
1531 // Not start of string or after /processor
1532 continue;
1533 }
1534
1535 // The parse point. One past 'processor'
1536 size_t firstp = pos + 9;
1537
1538 // normal: 'processor(\d+)'
1539 // plural: 'processors(\d+)'
1540
1541 const bool plural = (objPath[firstp] == 's');
1542
1543 if (plural)
1544 {
1545 ++firstp; // Skip over the 's'
1546 }
1547 else if (!std::isdigit(objPath[firstp]))
1548 {
1549 // Non-plural version (uncollated) requires digits only
1550 continue;
1551 }
1552
1553 // The next slash indicates there is a local directory
1554 slashLocal = objPath.find('/', firstp);
1555
1556 // The last parse point is the slash, or end of string
1557 const size_t lastp =
1558 (slashLocal == string::npos ? objPath.length() : slashLocal);
1559
1560 if (!std::isdigit(objPath[lastp-1]))
1561 {
1562 // Must end in a digit!
1563 // This traps entries that are too short or look quite wrong
1564 // and avoid a string to int conversion that will fail anyhow
1565 continue;
1566 }
1567
1568
1569 // Match: '^processors(\d+)$' -> nProcs
1570
1571 // Match: '^processors(\d+)_(\d+)-(\d+)$'
1572 // \1 = nProcs
1573 // \2 = beg processor group
1574 // \3 = end processor group (inclusive)
1575
1576 if (plural)
1577 {
1578 int nProcsRead = 0;
1579
1580 if
1581 (
1582 parseProcsNumRange
1583 (
1584 objPath.substr(firstp, lastp-firstp),
1585 nProcsRead,
1586 group
1587 )
1588 )
1589 {
1590 // Total number of processors
1591 nProcs = nProcsRead;
1592
1593 // We are done!
1594 break;
1595 }
1596 }
1597
1598 // Single
1599 // Match: '^processor(\d+)$' -> proci
1600
1601 label proci = 0;
1602 if
1603 (
1604 Foam::read(objPath.substr(firstp, lastp-firstp), proci)
1605 && (proci >= 0)
1606 )
1607 {
1608 // Capture value of an individual processor
1609 returnProci = proci;
1610
1611 // We are done!
1612 break;
1613 }
1614 }
1615
1616 if (pos != string::npos)
1617 {
1618 // The split succeeded, extract the components.
1619
1620 // The leading directory
1621 if (pos > 0)
1622 {
1623 path = objPath.substr(0, pos-1);
1624 }
1625
1626 // The slash starting the trailing (local) directory
1627 if (slashLocal != string::npos)
1628 {
1629 procDir = objPath.substr(pos, slashLocal-pos);
1630 local = objPath.substr(slashLocal+1);
1631 }
1632 else
1633 {
1634 procDir = objPath.substr(pos);
1635 }
1636 }
1637
1638 return returnProci;
1639}
1641
1643(
1644 const fileName& objPath,
1645 procRangeType& group,
1646 label* numProcs
1647)
1648{
1649 fileName path, procDir, local;
1650 label nProcs;
1651
1653 (
1654 objPath,
1655 path,
1656 procDir,
1657 local,
1658 group,
1659 nProcs
1660 );
1661
1662 if (numProcs)
1663 {
1664 *numProcs = nProcs;
1665 }
1666
1667 return proci;
1668}
1670
1671Foam::label Foam::fileOperation::detectProcessorPath(const fileName& fName)
1672{
1673 procRangeType group;
1674 return fileOperation::detectProcessorPath(fName, group);
1675}
1676
1677
1678// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
1679
1680Foam::Ostream& Foam::operator<<
1681(
1682 Ostream& os,
1683 const InfoProxy<fileOperation>& iproxy
1684)
1685{
1686 const auto& fp = *iproxy;
1687
1688 os << "fileHandler:" << fp.type()
1689 << " nProcs:" << fp.nProcs()
1690 << " comm:" << fp.comm()
1691 << " distributed:" << fp.distributed()
1692 << " ioranks: " << flatOutput(fp.ioRanks())
1693 << " ranks: ";
1694
1695 if (fp.comm() >= 0)
1696 {
1697 os << flatOutput(UPstream::procID(fp.comm()));
1698 }
1699 os << nl;
1700
1701 return os;
1702}
1703
1704// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
void append(const T &val)
Copy append an element to the end of this list.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition Enum.H:57
bool erase(const iterator &iter)
Erase an entry specified by given iterator.
Definition HashTable.C:489
Layout
The layout of the case structure.
@ regular
Regular case layout, eg processor-local locations.
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 fileName & rootPath() const noexcept
Return the Time::rootPath().
Definition IOobject.C:462
static Ostream & writeEndDivider(Ostream &os)
Write the standard end file divider.
static bool fileModificationChecking_masterOnly() noexcept
Test fileModificationChecking for master-only.
Definition IOobjectI.H:23
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 path() const
The complete path for the object (with instance, local,...).
Definition IOobject.C:500
fileName objectPath() const
The complete path + object name.
Definition IOobjectI.H:313
const fileName & caseName() const noexcept
Return the Time::caseName().
Definition IOobject.C:468
A simple container for options an IOstream can normally have.
A helper class for outputting values to Ostream.
Definition InfoProxy.H:49
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition List.C:347
void setSize(label n)
Alias for resize().
Definition List.H:536
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
Generic output stream using a standard (STL) stream.
Definition OSstream.H:53
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
void resize(const label numElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
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
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
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
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition UListI.H:410
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition UListI.H:454
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
Inter-processor communications stream.
Definition UPstream.H:69
static List< int > & procID(int communicator)
The list of ranks within a given communicator.
Definition UPstream.H:1767
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
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
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition bitSet.H:61
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition bitSetI.H:502
label find_first_not() const
Locate the first bit that is unset.
Definition bitSetI.H:289
Checking for changes to files.
Definition fileMonitor.H:62
fileState
Enumeration defining the file state.
Definition fileMonitor.H:71
A class for handling file names.
Definition fileName.H:75
@ FILE
A regular file.
Definition fileName.H:84
@ DIRECTORY
A directory.
Definition fileName.H:85
static std::string path(const std::string &str)
Return directory path name (part before last /).
Definition fileNameI.H:169
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.
virtual void addWatches(regIOobject &, const fileNameList &) const
Helper: add watches for list of regIOobjects.
static bool isFileOrDir(const bool isFile, const fileName &)
Helper: check for file (isFile) or directory (!isFile).
std::unique_ptr< fileMonitor > monitorPtr_
File-change monitor for all registered files.
virtual bool isFile(const fileName &, const bool checkGzip=true, const bool followLink=true) const =0
Does the name exist as a FILE in the file system?
virtual autoPtr< OSstream > NewOFstream(const fileName &pathname, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const =0
Generate an OSstream that writes a file.
bool distributed() const noexcept
Distributed roots (parallel run).
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.
Tuple2< fileName, Tuple2< pathType, int > > dirIndex
Augment fileName with pathType and local offset.
refPtr< dirIndexList > lookupAndCacheProcessorsPath(const fileName &objectPath, const bool syncPar) const
Lookup name of processorsDDD using cache.
static instantList sortTimes(const fileNameList &dirEntries, const word &constantName="constant")
Sort directory entries according to time value,.
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 bool removeWatch(const label) const
Remove watch on a file (using handle).
bool exists(IOobject &io) const
Does IOobject exist? Is either a directory (empty name()) or a file.
virtual fileNameList readObjects(const objectRegistry &db, const fileName &instance, const fileName &local, word &newInstance) const
Search directory for objects. Used in IOobjectList.
static word defaultFileHandler
Name of the default fileHandler.
virtual label findWatch(const labelList &watchIndices, const fileName &) const
Find index (or -1) of file in list of handles.
static void mergeTimes(const UList< instant > &extraTimes, const word &constantName, instantList &times)
Merge two times.
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.
fileName processorsCasePath(const IOobject &io, const word &procDir) const
Generate path (like io.path) from root+casename with any.
virtual refPtr< dirIndexList > lookupProcessorsPath(const fileName &objectPath) const
Lookup name of processorsDDD using cache.
label nProcs_
Overall number of processors.
const labelList & ioRanks() const noexcept
The list of IO ranks (global ranks).
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.
HashTable< dirIndexList > procsDirs_
Detected processors directories.
static label detectProcessorPath(const fileName &objPath)
Detect processor number from '/aa/bb/processorDDD/cc'.
pathType
Enumeration for the location of an IOobject.
@ PROCUNCOLLATED
objectPath exists in 'processorN'
@ PROCOBJECT
objectPath exists in 'processorsNN_first-last'
@ PROCBASEOBJECT
objectPath exists in 'processorsNN'
static int cacheLevel_
Cache level (eg, for caching time directories). Default: 1.
label comm_
Communicator to use.
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.
label comm() const noexcept
Communicator to use.
virtual void updateStates(const bool masterOnly, const bool syncPar) const
Update state of all files.
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.
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,...
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.
bool distributed_
Distributed roots (parallel run).
fileMonitor & monitor() const
Get or create fileMonitor singleton.
virtual bool writeObject(const regIOobject &io, IOstreamOption streamOpt=IOstreamOption(), const bool writeOnProc=true) const
Writes a regIOobject (so header, contents and divider).
virtual fileName filePath(const bool checkGlobal, const IOobject &, const word &typeName, const bool search=true) const =0
Search for an object.
static word processorsBaseDir
Return the processors directory name (usually "processors").
UPstream::rangeType procRangeType
For addressing a range of processors (an int range).
virtual fileName getFile(const label) const
Get name of file being watched (using handle).
virtual fileName objectPath(const IOobject &io, const word &typeName) const
Generate disk file name for object. Opposite of filePath.
@ LITERAL
String literal.
Definition keyType.H:82
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
Registry of regIOobjects.
virtual const fileName & dbDir() const
Local directory path of this objectRegistry relative to the time.
A class for managing references or pointers (no reference counting).
Definition refPtr.H:54
static refPtr< T > New(Args &&... args)
Construct refPtr with forwarding arguments.
Definition refPtr.H:187
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.
static std::string::size_type length(const char *s)
Length of the character sequence (with nullptr protection).
Definition string.H:259
bool starts_with(char c) const
True if string starts with given character (cf. C++20).
Definition string.H:436
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
regionProperties rp(runTime)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
const auto & io
auto & name
auto & names
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
constexpr const char *const group
Group name for atomic constants.
Namespace for handling debugging switches.
Definition debug.C:45
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition debug.C:216
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
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
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition POSIX.C:616
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
List< fileName > fileNameList
List of fileName.
List< instant > instantList
List of instants.
Definition instantList.H:41
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
static T getOrAdd(dictionary &dict, const char *name, const T deflt)
Definition debug.C:100
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.
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
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition POSIX.C:862
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::Type::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition POSIX.C:965
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
volScalarField & b
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Specialized string sorting.