Loading...
Searching...
No Matches
argList.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) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2015-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 "argList.H"
30#include "OSspecific.H"
31#include "Switch.H"
32#include "clock.H"
33#include "dictionary.H"
34#include "IOobject.H"
35#include "JobInfo.H"
36#include "labelList.H"
37#include "IOobject.H"
38#include "dynamicCode.H"
40#include "MemoryPool.H"
41#include "sigFpe.H"
42#include "sigInt.H"
43#include "sigQuit.H"
44#include "sigSegv.H"
45#include "foamVersion.H"
46#include "stringOps.H"
47#include "CStringList.H"
48#include "stringListOps.H"
49#include "fileOperation.H"
51#include "Field.H" // Ugly handling of localBoundaryConsistency switches
52
53#include <cctype>
54
55// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
56
57bool Foam::argList::argsMandatory_ = true;
58bool Foam::argList::checkProcessorDirectories_ = true;
59bool Foam::argList::parallelThreads_ = false;
60
72
73std::string::size_type Foam::argList::usageMin = 20;
74std::string::size_type Foam::argList::usageMax = 80;
75
76Foam::argList::initValidTables::initValidTables()
77{
78 argList::addOption
79 (
80 "case",
81 "dir",
82 "Case directory (instead of current directory)"
83 );
84 argList::addOption
85 (
86 "lib",
87 "name",
88 "Additional library or library list to load.\n"
89 "[Can be used multiple times]",
90 true // advanced option
91 );
92 argList::addBoolOption
93 (
94 "no-libs",
95 "Disable use of the controlDict 'libs' entry",
96 true // advanced option
97 );
98
99 argList::addOption
100 (
101 "debug-switch",
102 "name=val",
103 "Set named DebugSwitch (default value: 1).\n"
104 "[Can be used multiple times]",
105 true // advanced option
106 );
107
108 argList::addOption
109 (
110 "info-switch",
111 "name=val",
112 "Set named InfoSwitch (default value: 1).\n"
113 "[Can be used multiple times]",
114 true // advanced option
115 );
116
117 argList::addOption
118 (
119 "opt-switch",
120 "name=val",
121 "Set named OptimisationSwitch (default value: 1).\n"
122 "[Can be used multiple times]",
123 true // advanced option
124 );
125
126 argList::addBoolOption("parallel", "Run in parallel");
127 validParOptions.set("parallel", "");
128
129 argList::addBoolOption
130 (
131 "mpi-threads",
132 "Request use of MPI threads",
133 true // advanced option
134 );
135
136 argList::addBoolOption
137 (
138 "mpi-no-comm-dup",
139 "Disable initial MPI_Comm_dup()",
140 true // advanced option
141 );
142
143 argList::addOption
144 (
145 "roots",
146 "(dir1 .. dirN)",
147 "Subprocess root directories for distributed running",
148 true // advanced option
149 );
150 validParOptions.set
151 (
152 "roots",
153 "(dir1 .. dirN)"
154 );
155
156 argList::addOption
157 (
158 "decomposeParDict",
159 "file",
160 "Alternative decomposePar dictionary file"
161 );
162 argList::addOption
163 (
164 "hostRoots",
165 "((host1 dir1) .. (hostN dirN))",
166 "Per-subprocess root directories for distributed running."
167 " The host specification can be a regex.",
168 true // advanced option
169 );
170 validParOptions.set
171 (
172 "hostRoots",
173 "((host1 dir1) .. (hostN dirN))"
174 );
175
176 argList::addBoolOption
177 (
178 "noFunctionObjects",
179 "Do not execute function objects",
180 true // advanced option
181 );
182
183 argList::addOption
184 (
185 "fileHandler",
186 "handler",
187 "Override the file handler type",
188 true // advanced option
189 );
190
191 argList::addOption
192 (
193 "world",
194 "name",
195 "Name of the local world for parallel communication",
196 true // advanced option
197 );
198 validParOptions.set
199 (
200 "world",
201 "name"
202 );
203
204 argList::addBoolOption
205 (
206 "mpi-split-by-appnum",
207 "Split world communicator based on the APPNUM",
208 true // advanced option
209 );
210
211 // Some standard option aliases (with or without version warnings)
212// argList::addOptionCompat
213// (
214// "noFunctionObjects", {"no-function-objects", 0}
215// );
216
217 Pstream::addValidParOptions(validParOptions);
218}
219
220Foam::argList::initValidTables dummyInitValidTables;
221
222
223// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
224
225namespace Foam
226{
228// Counted per machine name
229// Does not include any sorting since we wish to know the ordering according to
230// mpi rank.
231//
232// Always include the master too.
233// This provides a better overview of the subscription
234static void printHostsSubscription(const UList<string>& hostProcs)
235{
236 Info<< "Hosts :\n(" << nl;
237
238 std::string prev = Foam::hostName();
239 int count = 1;
240
241 for (const auto& str : hostProcs)
242 {
243 std::string curr(str.substr(0, str.rfind('.')));
244
245 if (prev != curr)
246 {
247 if (count)
248 {
249 // Finish previous
250 Info<< " (" << prev.c_str() << ' ' << count << ')' << nl;
251 count = 0;
252 }
253
254 prev = std::move(curr);
255 }
256 ++count;
257 }
258
259 if (count)
260 {
261 // Finished last one
262 Info<< " (" << prev.c_str() << ' ' << count << ')' << nl;
263 }
264
265 Info<< ')' << nl;
266}
267
268
269static bool printRootsSubscription
270(
271 const UList<string>& hostProcs,
273)
274{
275 if (hostProcs.size() == roots.size()+1)
276 {
277 // Sort roots according to hostProc
278 DynamicList<string> sortedProcs;
279 DynamicList<label> sortedRoots;
280
281 forAll(roots, i)
282 {
283 const fileName& root = roots[i];
284 const string& host = hostProcs[i+1];
285 const label index = sortedProcs.find(host);
286
287 if (index == -1)
288 {
289 sortedProcs.push_back(host);
290 sortedRoots.push_back(i);
291 }
292 else if (roots[sortedRoots[index]] != root)
293 {
294 // Not properly sorted...
295 return false;
296 }
297 }
298
299 Info<< "Roots :\n(" << nl;
300 forAll(sortedProcs, i)
301 {
302 Info<< " (" << sortedProcs[i].c_str() << ' '
303 << roots[sortedRoots[i]] << ')' << nl;
304 }
305 Info<< ')' << nl;
306
307 return true;
308 }
309
310 return false;
311}
312
313} // End namespace Foam
314
315
316// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
317
318void Foam::argList::checkITstream(const ITstream& is, const label index)
319{
320 const label remaining = is.nRemainingTokens();
321
322 if (remaining)
323 {
324 std::cerr
325 << nl
326 << "--> FOAM WARNING:" << nl
327 << "Argument " << index << " has "
328 << remaining << " excess tokens" << nl << nl;
329 }
330 else if (!is.size())
331 {
332 std::cerr
333 << nl
334 << "--> FOAM WARNING:" << nl
335 << "Argument " << index << " had no tokens" << nl << nl;
336 }
337}
338
339
340void Foam::argList::checkITstream(const ITstream& is, const word& optName)
341{
342 const label remaining = is.nRemainingTokens();
343
344 if (remaining)
345 {
346 std::cerr
347 << nl
348 << "--> FOAM WARNING:" << nl
349 << "Option -" << optName << " has "
350 << remaining << " excess tokens" << nl << nl;
351 }
352 else if (!is.size())
353 {
354 std::cerr
355 << nl
356 << "--> FOAM WARNING:" << nl
357 << "Option -" << optName << " had no tokens" << nl << nl;
358 }
359}
360
361
362void Foam::argList::raiseBadInput(const word& optName) const
363{
364 // Can use FatalError
365 // predicate checks are not used at the earliest stages
367 << "Option -" << optName << " with invalid input" << nl
368 << exit(FatalError);
369}
370
371
373(
374 const string& argName,
375 const string& usage
376)
377{
378 validArgs.push_back(argName);
379
380 // The first program argument starts at 1 - obtain index after push_back()
381
382 const label index = validArgs.size();
383
384 if (usage.empty())
385 {
386 argUsage.erase(index);
387 }
388 else
389 {
390 argUsage.set(index, usage);
391 }
392}
393
394
396(
397 const word& optName,
398 const string& usage,
399 bool advanced
400)
401{
402 argList::addOption(optName, "", usage, advanced);
403}
404
405
407(
408 const word& optName,
409 const string& param,
410 const string& usage,
411 bool advanced
412)
413{
414 validOptions.set(optName, param);
415 if (!usage.empty())
416 {
417 optionUsage.set(optName, usage);
418 }
419 if (advanced)
420 {
421 advancedOptions.set(optName);
422 }
423}
424
425
426void Foam::argList::setAdvanced(const word& optName, bool advanced)
427{
428 if (advanced && validOptions.contains(optName))
429 {
430 advancedOptions.set(optName);
431 }
432 else
433 {
434 advancedOptions.erase(optName);
435 }
436}
437
438
440(
441 const word& optName,
442 std::pair<const char*,int> compat
443)
444{
445 validOptionsCompat.insert
447 compat.first,
448 std::pair<word,int>(optName, compat.second)
449 );
450}
451
452
454(
455 std::pair<const char*,int> compat,
456 bool expectArg
457)
458{
459 ignoreOptionsCompat.insert
461 compat.first,
462 std::pair<bool,int>(expectArg, compat.second)
463 );
464}
465
466
468(
469 const word& optName,
470 const string& usage
471)
472{
473 if (usage.empty())
474 {
475 optionUsage.erase(optName);
476 }
477 else
478 {
479 optionUsage.set(optName, usage);
480 }
481}
482
483
484void Foam::argList::addNote(const string& note)
485{
486 if (!note.empty())
487 {
488 notes.push_back(note);
489 }
490}
491
492
493void Foam::argList::removeOption(const word& optName)
495 validOptions.erase(optName);
496 optionUsage.erase(optName);
497 advancedOptions.erase(optName);
498}
499
502{
503 argsMandatory_ = false;
504}
505
508{
509 return argsMandatory_;
510}
511
516}
517
520{
521 return (::Foam::infoDetailLevel > 0);
522}
523
524
526(
527 const string& usage,
528 bool advanced
529)
530{
531 const word optName("dry-run", false);
532
533 argList::addBoolOption(optName, usage, advanced);
534 if (!advanced)
535 {
536 advancedOptions.erase(optName); // Avoid 'stickiness'
537 }
538}
539
540
542(
543 const string& usage,
544 bool advanced
545)
546{
547 const word optName("verbose", false);
548
549 if (usage.empty())
550 {
552 (
553 optName,
554 "Additional verbosity (can be used multiple times)",
555 advanced
556 );
557 }
558 else
559 {
560 argList::addBoolOption(optName, usage, advanced);
561 }
562 if (!advanced)
563 {
564 advancedOptions.erase(optName); // Avoid 'stickiness'
565 }
566}
567
568
569void Foam::argList::noFunctionObjects(bool addWithOption)
570{
571 removeOption("noFunctionObjects");
572
573 // Ignore this bool option without warning
574 // - cannot tie to any particular version anyhow
575 ignoreOptionCompat({"noFunctionObjects", 0}, false);
576
577 if (addWithOption)
578 {
580 (
581 "withFunctionObjects",
582 "Execute functionObjects"
583 // An advanced option, but seldom used so expose it more
584 );
585 }
586}
587
590{
592}
593
594
596{
598 (
599 "no-libs",
600 "Disable use of the controlDict libs entry",
601 true // advanced option
602 );
603}
604
605
607{
608 removeOption("parallel");
609 removeOption("roots");
610 removeOption("decomposeParDict");
611 removeOption("hostRoots");
612 removeOption("world");
613 removeOption("mpi-threads");
614 removeOption("mpi-no-comm-dup");
615 removeOption("mpi-split-by-appnum");
616 validParOptions.clear();
617}
618
621{
622 parallelThreads_ = true;
623}
624
627{
628 checkProcessorDirectories_ = false;
629}
630
631
632bool Foam::argList::postProcess(int argc, char *argv[])
633{
634 for (int argi = 1; argi < argc; ++argi)
635 {
636 const char *optName = argv[argi];
637
638 if (optName[0] == '-')
639 {
640 ++optName; // Looks like an option, skip leading '-'
641
642 if (optName == postProcessOptionName)
643 {
644 return true;
645 }
647 }
648
649 return false;
650}
651
652
653int Foam::argList::verbose(int argc, char *argv[])
654{
655 int num = 0;
656 for (int argi = 1; argi < argc; ++argi)
657 {
658 if (strcmp(argv[argi], "-verbose") == 0)
659 {
660 ++num;
661 }
663 return num;
664}
665
666
667// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
670{
671 return Foam::getEnv("FOAM_EXECUTABLE");
672}
673
676{
677 return Foam::getEnv("FOAM_CASE");
678}
679
680
682(
683 const fileName& input,
684 const bool caseTag
685)
686{
687 if (input.isAbsolute())
688 {
689 return input.relative(envGlobalPath(), caseTag);
690 }
691
692 return input;
693}
694
695
696// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
697
698Foam::word Foam::argList::optionCompat(const word& optName)
699{
700 // NB: optName includes the leading '-' so that the return value
701 // can be used directly
702
703 if (!validOptionsCompat.empty())
704 {
705 const auto fnd = validOptionsCompat.cfind(optName.substr(1));
706
707 if (fnd.good())
708 {
709 const auto& alt = fnd.val();
710
711 // No error::master() guard - only called on master anyhow
712 if (error::warnAboutAge(alt.second))
713 {
714 std::cerr
715 << "--> FOAM IOWarning :" << nl
716 << " Found [v" << alt.second << "] '"
717 << optName << "' instead of '-"
718 << alt.first << "' option"
719 << nl
720 << std::endl;
721
722 error::warnAboutAge("option", alt.second);
723 }
724
725 return "-" + alt.first;
726 }
727 }
728
729 // Nothing found - pass through the original input
730 return optName;
731}
732
733
734int Foam::argList::optionIgnore(const word& optName)
735{
736 // NB: optName is without the leading '-'
737
738 if (!ignoreOptionsCompat.empty())
739 {
740 const auto fnd = ignoreOptionsCompat.cfind(optName);
741
742 if (fnd.good())
743 {
744 const auto& alt = fnd.val();
745
746 // Number to skip (including the option itself)
747 // '-option ARG' or '-option'
748 const int nskip = (alt.first ? 2 : 1);
749
750 // No error::master() guard - only called on master anyhow
751 if (error::warnAboutAge(alt.second))
752 {
753 std::cerr
754 << "--> FOAM IOWarning :" << nl
755 << " Ignoring [v" << alt.second << "] '-"
756 << optName << (nskip > 1 ? " ARG" : "")
757 << "' option"
758 << nl
759 << std::endl;
760
761 error::warnAboutAge("option", alt.second);
762 }
763
764 return nskip;
765 }
766 }
767
768 // TBD: could ignore -verbose, -dry-run etc if they are not active...
769
770 return 0; // Do not skip
771}
772
773
774bool Foam::argList::regroupArgv(int& argc, char**& argv)
775{
776 int nArgs = 1;
777 int ignore = 0;
778 unsigned depth = 0;
779 string group; // For grouping ( ... ) arguments
780
781 // Note: we rewrite directly into args_
782 // and use a second pass to sort out args/options
783
784 args_[0] = fileName(argv[0]);
785 for (int argi = 1; argi < argc; ++argi)
786 {
787 const char *optName = argv[argi];
788
789 if (optName[0] == '(' && optName[1] == '\0')
790 {
791 // Begin list
792 ++depth;
793 group += '(';
794 }
795 else if (optName[0] == ')' && optName[1] == '\0')
796 {
797 if (depth)
798 {
799 // End list
800 --depth;
801 group += ')';
802 if (!depth)
803 {
804 args_[nArgs++] = group;
805 group.clear();
806 }
807 }
808 else
809 {
810 // A stray ')' - likely never happens
811 args_[nArgs++] = argv[argi];
812 }
813 }
814 else if (depth)
815 {
816 // Quote each string element
817 group += '"';
818 group += argv[argi];
819 group += '"';
820 }
821 else if (optName[0] == '-')
822 {
823 ++optName; // Looks like an option, skip leading '-'
824
825 if (validOptions.contains(optName))
826 {
827 // Known option name
828 args_[nArgs++] = argv[argi];
829 }
830 else if ((ignore = optionIgnore(optName)) > 0)
831 {
832 // Option to be ignored (with/without an argument)
833 if (ignore > 1)
834 {
835 ++argi;
836 }
837 }
838 else
839 {
840 // Try alias for the option name
841 args_[nArgs++] = optionCompat(argv[argi]);
842 }
843 }
844 else
845 {
846 args_[nArgs++] = argv[argi];
847 }
848 }
849
850 if (group.size())
851 {
852 // Group(s) not closed, but flush anything still pending
853 args_[nArgs++] = group;
854 }
855
856 args_.resize(nArgs);
857
858 std::string::size_type len = (nArgs-1); // Spaces between args
859 for (const auto& s : args_)
860 {
861 len += s.length();
862 }
863
864 // Length needed for regrouped command-line
865 commandLine_.reserve(len);
866
867 return nArgs < argc;
868}
869
870
871void Foam::argList::setCasePaths()
872{
873 fileName caseDir;
874
875 const auto optIter = options_.cfind("case"); // [-case dir] specified?
876
877 if (optIter.good())
878 {
879 caseDir = fileName::validate(optIter.val()); // includes 'clean'
880
881 if (caseDir.empty() || caseDir == ".")
882 {
883 // Treat "", "." and "./" as if -case was not specified
884 caseDir = cwd();
885 options_.erase("case");
886 }
887 else
888 {
889 caseDir.expand();
890 caseDir.toAbsolute();
891 }
892 }
893 else
894 {
895 // Nothing specified, use the current dir
896 caseDir = cwd();
897 }
898
899 // The caseDir is a cleaned, absolute path
900
901 rootPath_ = caseDir.path();
902 globalCase_ = caseDir.name();
903 case_ = globalCase_; // The (processor) local case name
904
905 // OPENFOAM API
906 setEnv("FOAM_API", std::to_string(foamVersion::api), true);
907
908 // Global case (directory) and case-name as environment variables
909 setEnv("FOAM_CASE", caseDir, true);
910 setEnv("FOAM_CASENAME", globalCase_, true);
911
912 // Executable name, unless already present in the environment
913 setEnv("FOAM_EXECUTABLE", executable_, false);
914}
915
916
917// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
918
920(
921 int& argc,
922 char**& argv,
923 bool checkArgs,
924 bool checkOpts,
925 bool initialise
926)
927:
928 runControl_(),
929 args_(argc),
930 options_(argc),
931 libs_()
932{
933 // Pre-scan for some options needed for initial setup:
934 // -fileHandler (takes an argument)
935 // -mpi-threads (bool option)
936 // -debug-switch, -info-switch, -opt-switch
937 // so their values can also influence the initial setup
938 //
939 // Also handle -dry-run and -verbose counting
940 // (it is left to the application to decide what to do with them).
941 // Detect any parallel run options
942
943 word fileHandlerName;
944
945 if (parallelThreads_)
946 {
947 // Default -mpi-threads configured statically from application
948 runControl_.threads(true);
949 }
950
951 for (int argi = 1; argi < argc; ++argi)
952 {
953 const char *optName = argv[argi];
954
955 if (optName[0] == '-')
956 {
957 ++optName; // Looks like an option, skip leading '-'
958 bool emitErrorMessage = false;
959
960 if (strcmp(optName, "dry-run") == 0)
961 {
962 runControl_.incrDryRun();
963 }
964 else if (strcmp(optName, "verbose") == 0)
965 {
966 runControl_.incrVerbose();
967 }
968 else if (strcmp(optName, "mpi-threads") == 0)
969 {
970 runControl_.threads(true);
971 }
972 else if (strcmp(optName, "fileHandler") == 0)
973 {
974 // Requires a parameter
975 if (argi < argc-1)
976 {
977 ++argi;
978 fileHandlerName = argv[argi];
979 }
980 else
981 {
982 emitErrorMessage = true;
983 }
984 }
985 else if (strcmp(optName, "debug-switch") == 0)
986 {
987 // The '-debug-switch' option:
988 // change registered debug switch
989 if (argi < argc-1)
990 {
991 ++argi;
993 .setNamedValue(argv[argi], 1); // silent
994 }
995 else
996 {
997 // emit error on the second pass
998 }
999 }
1000 else if (strcmp(optName, "info-switch") == 0)
1001 {
1002 // The '-info-switch' option:
1003 // change registered info switch
1004 if (argi < argc-1)
1005 {
1006 ++argi;
1008 .setNamedValue(argv[argi], 1); // silent
1009 }
1010 else
1011 {
1012 // emit error on the second pass
1013 }
1014 }
1015 else if (strcmp(optName, "opt-switch") == 0)
1016 {
1017 // The '-opt-switch' option:
1018 // change registered optimisation switch
1019 if (argi < argc-1)
1020 {
1021 ++argi;
1023 .setNamedValue(argv[argi], 1); // silent
1024 }
1025 else
1026 {
1027 // emit error on the second pass
1028 }
1029 }
1030 else if (validParOptions.contains(optName))
1031 {
1032 // Contains a parallel run option
1033 runControl_.parRun(true);
1034 }
1035
1036 if (emitErrorMessage)
1037 {
1038 // Missing argument: emit message but not exit or
1039 // FatalError since Pstream etc are not yet initialised
1040
1041 Info<< nl
1042 << "Error: option '-" << optName
1043 << "' requires an argument" << nl << nl;
1044 }
1045 }
1046 }
1047
1048 // No -fileHandler specifed, get from environment or use default
1049 if (fileHandlerName.empty())
1050 {
1051 fileHandlerName = Foam::getEnv("FOAM_FILEHANDLER");
1052 if (fileHandlerName.empty())
1053 {
1054 fileHandlerName = fileOperation::defaultFileHandler;
1055 }
1056 }
1057
1058 // Parse out any additional fileHandler-specific options
1059 // (may alter argv list). Recover its threading requirements
1060 {
1061 auto fileOperationInit = fileOperations::fileOperationInitialise::New
1062 (
1063 fileHandlerName,
1064 argc,
1065 argv
1066 );
1067
1068 if (fileOperationInit && fileOperationInit->needsThreading())
1069 {
1070 runControl_.threads(true);
1071 }
1072 }
1073
1074 // Parallel job options detected?
1075 // - start parallel run (possibly filters argv as a side-effect)
1076 if (runControl_.parRun())
1077 {
1078 runControl_.runPar(argc, argv);
1079 }
1080
1081 // addProfiling(argList, "argList");
1082
1083 // ------------------------------------------------------------------------
1084
1085 // Convert argv -> args_ and capture ( ... ) lists
1086 regroupArgv(argc, argv);
1087 commandLine_ += args_[0];
1088
1089 // Set executable name immediately - useful when emitting errors.
1090 executable_ = fileName(args_[0]).name();
1091
1092 // Check arguments and options, argv[0] was already handled
1093 int nArgs = 1;
1094 for (int argi = 1; argi < args_.size(); ++argi)
1095 {
1096 commandLine_ += ' ';
1097 commandLine_ += args_[argi];
1098
1099 const char *optName = args_[argi].data();
1100
1101 if (optName[0] == '-')
1102 {
1103 ++optName; // Looks like an option, skip leading '-'
1104
1105 if (!*optName)
1106 {
1107 Warning
1108 << "Ignoring lone '-' on the command-line" << endl;
1109 continue;
1110 }
1111
1112 // Option known and expects an argument?
1113 // - use Switch for a tri-state
1114 // True : known option, expects a parameter
1115 // False : known option, no parameter
1116 // bad() : unknown option
1117
1118 Switch wantArg(Switch::INVALID);
1119 auto optIter = validOptions.cfind(optName);
1120 if
1121 (
1122 optIter.good()
1123 || (optIter = validParOptions.cfind(optName)).good()
1124 )
1125 {
1126 wantArg = !optIter.val().empty();
1127 }
1128
1129
1130 if (wantArg)
1131 {
1132 // Option expects a parameter
1133 // - get it or emit a FatalError.
1134
1135 ++argi;
1136 if (argi >= args_.size())
1137 {
1138 foamVersion::printBuildInfo(Info.stdStream(), false);
1139
1140 Info<< nl
1141 <<"Error: option '-" << optName
1142 << "' requires an argument" << nl << nl
1143 << "See '" << executable_ << " -help' for usage" << nl
1144 << " or '" << executable_
1145 << " -help-full' for extended usage" << nl
1146 << nl;
1147
1148 UPstream::exit(1); // works for serial and parallel
1149 }
1150
1151 commandLine_ += ' ';
1152 commandLine_ += args_[argi];
1153
1154 //
1155 // Special handling of these options
1156 //
1157
1158 if (strcmp(optName, "lib") == 0)
1159 {
1160 // The '-lib' option:
1161 // Add name(s) to libs for later opening
1162 libs().push_back(this->getList<fileName>(argi));
1163 }
1164 else if (strcmp(optName, "debug-switch") == 0)
1165 {
1166 // The '-debug-switch' option:
1167 // dryrun reporting only (already set above)
1168 DetailInfo << "debug-switch ";
1170 .setNamedValue(args_[argi], 1, true, true); // dryrun
1171 }
1172 else if (strcmp(optName, "info-switch") == 0)
1173 {
1174 // The '-info-switch' option:
1175 // dryrun reporting only (already set above)
1176 DetailInfo << "info-switch ";
1178 .setNamedValue(args_[argi], 1, true, true); // dryrun
1179 }
1180 else if (strcmp(optName, "opt-switch") == 0)
1181 {
1182 // The '-opt-switch' option:
1183 // dryrun reporting only (already set above)
1184 DetailInfo << "opt-switch ";
1186 .setNamedValue(args_[argi], 1, true, true); // dryrun
1187 }
1188 else
1189 {
1190 // Regular option (with a parameter):
1191 // Duplicates handled by using the last -option specified
1192 options_.set(optName, args_[argi]);
1193 }
1194 }
1195 else
1196 {
1197 // All other options (including unknown ones) are simply
1198 // registered as existing.
1199
1200 options_.insert(optName, "");
1201
1202 // // Special increment handling for some known flags
1203 // if (wantArg.good())
1204 // {
1205 // ...
1206 // }
1207 }
1208 }
1209 else
1210 {
1211 if (nArgs != argi)
1212 {
1213 args_[nArgs] = args_[argi];
1214 }
1215 ++nArgs;
1216 }
1217 }
1219 args_.resize(nArgs);
1220
1221 parse(checkArgs, checkOpts, initialise);
1222}
1223
1224
1226(
1227 const argList& args,
1228 const HashTable<string>& options,
1229 bool checkArgs,
1230 bool checkOpts,
1231 bool initialise
1232)
1233:
1234 runControl_(args.runControl_),
1235 args_(args.args_),
1236 options_(options),
1237 libs_(),
1238 executable_(args.executable_),
1239 rootPath_(args.rootPath_),
1240 globalCase_(args.globalCase_),
1241 case_(args.case_),
1242 commandLine_(args.commandLine_)
1243{
1244 parse(checkArgs, checkOpts, initialise);
1245}
1246
1247
1249(
1250 bool checkArgs,
1251 bool checkOpts,
1252 bool initialise
1253)
1254{
1255 // Help/documentation options:
1256 // -doc Display documentation in browser
1257 // -doc-source Display source code in browser
1258 // -help Display short help and exit
1259 // -help-compat Display compatibility options
1260 // -help-full Display full help and exit
1261 {
1262 bool quickExit = false;
1263
1264 // Display either application or source documentation, not both
1265 if (options_.contains("doc"))
1266 {
1267 displayDoc(false);
1268 quickExit = true;
1269 }
1270 else if (options_.contains("doc-source"))
1271 {
1272 displayDoc(true);
1273 quickExit = true;
1274 }
1275
1276 // Display either short or full help, not both
1277 if (options_.contains("help-full"))
1278 {
1279 printUsage(true);
1280 quickExit = true;
1281 }
1282 else if (options_.contains("help-notes"))
1283 {
1284 printNotes();
1285 Info<< nl;
1286 quickExit = true;
1287 }
1288 else if (options_.contains("help"))
1289 {
1290 printUsage(false);
1291 quickExit = true;
1292 }
1293 else if (options_.contains("help-man"))
1294 {
1295 printMan();
1296 quickExit = true;
1297 }
1298
1299 // Allow independent display of compatibility information
1300 if (options_.contains("help-compat"))
1301 {
1302 printCompat();
1303 quickExit = true;
1304 }
1305
1306 if (quickExit)
1307 {
1308 std::exit(0);
1309 }
1310 }
1311
1312 // Print the collected error messages and exit if check fails
1313 if (!check(checkArgs, checkOpts))
1314 {
1315 foamVersion::printBuildInfo(Info.stdStream(), false);
1316 FatalError.write(Info, false);
1317
1318 UPstream::exit(1); // works for serial and parallel
1319 }
1320
1321 if (initialise)
1322 {
1323 const string dateString = clock::date();
1324 const string timeString = clock::clockTime();
1325
1326 // Print the banner once only for parallel runs
1327 if (UPstream::master() && bannerEnabled())
1328 {
1330 << "Build : ";
1331
1332 if (foamVersion::build.size())
1333 {
1334 Info<< foamVersion::build.c_str() << ' ';
1335 }
1336
1337 Info<< "OPENFOAM=" << foamVersion::api;
1338
1340 {
1341 // Patch-level, when defined
1342 Info<< " patch=" << foamVersion::patch.c_str();
1343 }
1344
1345 Info<< " version=" << foamVersion::version.c_str();
1346
1347 Info<< nl
1348 << "Arch : " << foamVersion::buildArch << nl
1349 << "Exec : " << commandLine_.c_str() << nl
1350 << "Date : " << dateString.c_str() << nl
1351 << "Time : " << timeString.c_str() << nl
1352 << "Host : " << Foam::hostName().c_str() << nl
1353 << "PID : " << pid() << nl;
1354 }
1355
1356 jobInfo.add("startDate", dateString);
1357 jobInfo.add("startTime", timeString);
1358 jobInfo.add("userName", userName());
1359
1360 jobInfo.add("foamApi", foamVersion::api);
1361 jobInfo.add("foamVersion", word(foamVersion::version));
1362
1363 // Add build information - only use the first word
1364 {
1365 std::string build(foamVersion::build);
1366 const auto space = build.find(' ');
1367 if (space != std::string::npos)
1368 {
1369 build.resize(space);
1370 }
1371 jobInfo.add("foamBuild", build);
1372 }
1373
1374 jobInfo.add("code", executable_);
1375 jobInfo.add("argList", commandLine_);
1376 jobInfo.add("currentDir", cwd());
1377 jobInfo.add("PPID", ppid());
1378 jobInfo.add("PGID", pgid());
1379
1380 // Load additional libraries (verbosity according to banner setting)
1381 libs().open(bannerEnabled());
1382 }
1383
1384
1385 // Set fileHandler. In increasing order of priority:
1386 // 1. default = uncollated
1387 // 2. env variable "FOAM_FILEHANDLER"
1388 // 3. etc/controlDict optimisationSwitches 'fileHandler'
1389 // 4. system/controlDict 'fileHandler' (not handled here; done in TimeIO.C)
1390 // 5. '-fileHandler' commmand-line option
1391
1392 {
1393 word fileHandlerName
1394 (
1395 options_.lookup("fileHandler", Foam::getEnv("FOAM_FILEHANDLER"))
1396 );
1397
1398 if (fileHandlerName.empty())
1399 {
1400 fileHandlerName = fileOperation::defaultFileHandler;
1401 }
1402
1404 (
1405 fileOperation::New(fileHandlerName, bannerEnabled())
1406 );
1407 }
1408
1409
1410 stringList hostMachine;
1411 stringList hostProcs;
1412 const int writeHostsSwitch = Foam::debug::infoSwitch("writeHosts", 1);
1413 const int writeRootsSwitch = Foam::debug::infoSwitch("writeRoots", 1);
1414
1415 // Collect machine/pid, and check that the build is identical
1416 if (runControl_.parRun())
1417 {
1418 if (UPstream::master())
1419 {
1420 hostMachine.resize(UPstream::nProcs()-1);
1421 hostProcs.resize(UPstream::nProcs()-1);
1422 string procBuild;
1423 label procPid;
1424 int proci = 0;
1425 for (const int subproci : UPstream::subProcs())
1426 {
1427 IPstream fromSubproc(UPstream::commsTypes::scheduled, subproci);
1428
1429 fromSubproc >> procBuild >> hostMachine[proci] >> procPid;
1430
1431 hostProcs[proci] = hostMachine[proci] + "." + name(procPid);
1432 ++proci;
1433
1434 // Verify that all processors are running the same build
1435 if (procBuild != foamVersion::build)
1436 {
1437 FatalErrorIn(executable())
1438 << "Running build version " << foamVersion::build
1439 << " but proc " << subproci << " is running "
1440 << procBuild << nl
1441 << exit(FatalError);
1442 }
1443 }
1444 }
1445 else
1446 {
1447 OPstream toMaster
1448 (
1451 );
1452 toMaster << foamVersion::build << Foam::hostName() << Foam::pid();
1453 }
1454 }
1455
1456
1457 // Case is a single processor run unless it is running parallel
1458 int nProcs = 1;
1459
1460 // Roots if running distributed. Only sized on the master
1462
1463 enum distributedCodes
1464 {
1465 NON_DISTRIBUTED = 0,
1466 DISTRIBUTED = 1,
1467 DISTRIBUTED_SINGLE_ROOT = 2,
1468 DISTRIBUTED_MULTIPLE_ROOTS = 3
1469 };
1470
1471 // Track which type of distributed roots etc are being used
1472 label distributedType
1473 (
1474 runControl_.distributed()
1475 ? distributedCodes::DISTRIBUTED
1476 : distributedCodes::NON_DISTRIBUTED
1477 );
1478
1479 // Some cases where knowing the writeFormat can be useful...
1480 // label writeFormat(-1);
1481
1482
1483 // If this actually is a parallel run
1484 if (runControl_.parRun())
1485 {
1486 // For the master
1487 if (UPstream::master())
1488 {
1489 // Establish rootPath_/globalCase_/case_ for master
1490 setCasePaths();
1491
1492 // The system/decomposeParDict (or equivalent)
1493 fileName source;
1494
1495 if (this->readIfPresent("decomposeParDict", source))
1496 {
1497 bool adjustOpt = false;
1498
1499 if (Foam::isDir(source))
1500 {
1501 source /= "decomposeParDict";
1502 adjustOpt = true;
1503 }
1504
1505 // Case-relative if not absolute and not "./" etc
1506 if (!source.isAbsolute() && !source.starts_with('.'))
1507 {
1508 source = rootPath_/globalCase_/source;
1509 adjustOpt = true;
1510 }
1511
1512 // Could also check for absolute path, but shouldn't be needed
1513 if (adjustOpt)
1514 {
1515 source.clean(); // Remove unneeded ".."
1516 options_.set("decomposeParDict", source);
1517 }
1518 }
1519
1520 // If running distributed (different roots for different procs)
1521 label dictNProcs = -1;
1522 if (this->readListIfPresent("roots", roots))
1523 {
1524 source = "-roots";
1525 runControl_.distributed(true);
1526 distributedType = distributedCodes::DISTRIBUTED;
1527
1528 if (roots.empty())
1529 {
1531 << "The -roots option must contain values"
1532 << exit(FatalError);
1533 }
1534 if (roots.size() > 1)
1535 {
1536 dictNProcs = roots.size()+1;
1537 }
1538 }
1539 else if (options_.contains("hostRoots"))
1540 {
1541 source = "-hostRoots";
1542 runControl_.distributed(true);
1543 distributedType = distributedCodes::DISTRIBUTED;
1544
1545 ITstream is(this->lookup("hostRoots"));
1546
1547 List<Tuple2<wordRe, fileName>> hostRoots(is);
1548 checkITstream(is, "hostRoots");
1549
1550 if (hostRoots.empty())
1551 {
1553 << "The -hostRoots option must contain values"
1554 << exit(FatalError);
1555 }
1556
1557 // Match machine names to roots
1559 for (const auto& hostRoot : hostRoots)
1560 {
1561 labelList matched
1562 (
1563 wordRes::matching(hostRoot.first(), hostMachine)
1564 );
1565 for (const label matchi : matched)
1566 {
1567 if (!roots[matchi].empty())
1568 {
1570 << "Multiple matching roots for "
1571 << hostMachine[matchi] << " in "
1572 << hostRoots << nl
1573 << exit(FatalError);
1574 }
1575
1576 roots[matchi] = hostRoot.second();
1577 }
1578 }
1579
1580 // Check
1581 forAll(roots, hosti)
1582 {
1583 if (roots[hosti].empty())
1584 {
1586 << "No matching roots for "
1587 << hostMachine[hosti] << " in "
1588 << hostRoots << nl
1589 << exit(FatalError);
1590 }
1591 }
1592
1593 if (roots.size() > 1)
1594 {
1595 dictNProcs = roots.size()+1;
1596 }
1597 }
1598 else if (checkProcessorDirectories_ && UPstream::nProcs() > 1)
1599 {
1600 // Check values from decomposeParDict
1601
1602 const bool useDefault = source.empty();
1603 if (useDefault)
1604 {
1605 source = rootPath_/globalCase_/"system"/"decomposeParDict";
1606 }
1607
1608 // Disable any parallel comms happening inside the fileHandler
1609 // since we are on master. This can happen e.g. inside
1610 // the masterUncollated/collated handler. Note that we
1611 // also have to protect the actual dictionary parsing since
1612 // it might trigger file access (e.g. #include, #codeStream)
1613 const bool oldParRun = UPstream::parRun(false);
1614 // Note: non-parallel running might update
1615 // fileOperation::nProcs() so store & restore below
1616 const label nOldProcs = fileHandler().nProcs();
1617
1618 autoPtr<ISstream> dictStream
1619 (
1620 fileHandler().NewIFstream(source)
1621 );
1622
1623 if (dictStream && dictStream->good())
1624 {
1625 // Get numberOfSubdomains if it exists.
1626 // - mandatory when running with distributed roots
1627
1628 IOobjectOption::readOption nDomainsReadOpt
1630
1631 dictionary decompDict(*dictStream);
1632
1633 if (decompDict.getOrDefault("distributed", false))
1634 {
1635 nDomainsReadOpt = IOobjectOption::MUST_READ;
1636 runControl_.distributed(true);
1637 distributedType = distributedCodes::DISTRIBUTED;
1638
1639 decompDict.readEntry("roots", roots);
1640
1641 if (roots.empty())
1642 {
1644 << "WARNING: running distributed"
1645 << " but did not specify roots!" << nl;
1646 }
1647 }
1648
1649 decompDict.readEntry
1650 (
1651 "numberOfSubdomains",
1652 dictNProcs,
1654 nDomainsReadOpt
1655 );
1656 }
1657 else
1658 {
1659 if (useDefault)
1660 {
1661 // Optional if using default location
1663 << "WARNING: running without decomposeParDict "
1664 << this->relativePath(source) << nl;
1665 }
1666 else
1667 {
1668 // Mandatory if specified as -decomposeParDict
1670 << "Cannot read decomposeParDict: "
1671 << this->relativePath(source) << nl
1672 << exit(FatalError);
1673 }
1674 }
1675
1676 UPstream::parRun(oldParRun); // Restore parallel state
1677 const_cast<fileOperation&>(fileHandler()).nProcs(nOldProcs);
1678
1679 if (UPstream::nProcs() == 1)
1680 {
1681 Warning
1682 << "Running parallel on single processor. This only"
1683 << " makes sense for multi-world simulation" << endl;
1684 dictNProcs = 1;
1685 }
1686 }
1687
1688
1689 // Distributed roots
1690 if (!roots.empty())
1691 {
1692 for (fileName& dir : roots)
1693 {
1694 dir.expand();
1695 }
1696
1697 // Identical root specified everywhere?
1698 // - use optimized single-root variant
1699 if (roots.size() > 1 && roots.uniform())
1700 {
1701 roots.resize(1);
1702 }
1703
1704 if (roots.size() == 1)
1705 {
1706 // Single root specified, use it for all processes
1707 distributedType =
1708 distributedCodes::DISTRIBUTED_SINGLE_ROOT;
1709
1710 // Adjust dictNProcs for command-line '-roots' option
1711 if (dictNProcs <= 0)
1712 {
1713 dictNProcs = UPstream::nProcs();
1714 }
1715 }
1716 else if (roots.size() > 1)
1717 {
1718 distributedType =
1719 distributedCodes::DISTRIBUTED_MULTIPLE_ROOTS;
1720
1721 if (roots.size() != UPstream::nProcs()-1)
1722 {
1724 << "Number of roots " << roots.size()
1725 << " != number of sub-ranks "
1726 << UPstream::nProcs()-1
1727 << exit(FatalError);
1728 }
1729 }
1730 }
1731
1732
1733 //
1734 // Check number of processors.
1735 //
1736
1737 // nProcs => number of actual procs
1738 // dictNProcs => number of procs specified in decompositionDict
1739 // nProcDirs => number of processor directories
1740 // (n/a when running distributed)
1741 //
1742 // - normal running : nProcs = dictNProcs = nProcDirs
1743 // - decomposition to more processors : nProcs = dictNProcs
1744 // - decomposition to fewer processors : nProcs = nProcDirs
1745 if
1746 (
1747 checkProcessorDirectories_
1748 && UPstream::nProcs() > 1
1749 )
1750 {
1751 if (dictNProcs > UPstream::nProcs())
1752 {
1754 << this->relativePath(source)
1755 << " specifies " << dictNProcs
1756 << " processors but job was started with "
1757 << UPstream::nProcs() << " ranks."
1758 << exit(FatalError);
1759 }
1760
1761 // Possibly going to fewer processors.
1762 // Check if all procDirs are there.
1763 // NOTE: Only works when not using distributed roots!
1764 if
1765 (
1766 // Can only rely on directory scanning *without* distributed roots!
1767 roots.empty()
1768 && dictNProcs >= 1
1769 && dictNProcs < UPstream::nProcs()
1770 )
1771 {
1772 label nProcDirs = 0;
1773 {
1774 const bool oldParRun = UPstream::parRun(false);
1775 // Don't cache processor directories (probably not
1776 // needed since master-only
1777 const int oldCacheLevel(fileOperation::cacheLevel(0));
1778 // Accept any processorsXXX
1779 const int oldFilter(fileOperation::nProcsFilter(0));
1780
1781 nProcDirs = fileHandler().nProcs
1782 (
1783 rootPath_/globalCase_,
1784 "",
1785 dictNProcs // expected nProcs
1786 );
1787
1788 fileOperation::nProcsFilter(oldFilter);
1789 fileOperation::cacheLevel(oldCacheLevel);
1790 UPstream::parRun(oldParRun);
1791 }
1792
1793 if (nProcDirs < UPstream::nProcs())
1794 {
1796 << "Number of processor directories = " << nProcDirs
1797 << " is not equal to the number of ranks = "
1798 << UPstream::nProcs()
1799 << exit(FatalError);
1800 }
1801 }
1802 }
1803
1804
1805 // Broadcast the master's argument list (unaltered)
1806 {
1808
1809 toProcs
1810 << args_ << options_
1811 << distributedType
1812 << label(runControl_.dryRun())
1813 << label(runControl_.verbose());
1814 }
1815 }
1816 else
1817 {
1818 // Receive the broadcasted master's argument list
1819 label numDryRun, numVerbose;
1820
1821 IPBstream fromMaster(UPstream::worldComm);
1822
1823 fromMaster
1824 >> args_ >> options_
1825 >> distributedType
1826 >> numDryRun >> numVerbose;
1827
1828 runControl_.distributed(distributedType);
1829 runControl_.dryRun(numDryRun);
1830 runControl_.verbose(numVerbose);
1831 }
1832
1833
1834 // Final handling of distributed roots (if any)
1835 if
1836 (
1837 distributedType == distributedCodes::DISTRIBUTED_SINGLE_ROOT
1838 )
1839 {
1840 // The same root for all sub-ranks
1841 // - use broadcast to transmit value
1842
1843 fileName newCasePath;
1844
1845 if (UPstream::master())
1846 {
1847 newCasePath = roots[0]/globalCase_;
1848 OPBstream::send(newCasePath); // worldComm
1849 }
1850 else
1851 {
1852 IPBstream::recv(newCasePath); // worldComm
1853 options_.set("case", newCasePath);
1854 }
1855 }
1856 else if
1857 (
1858 distributedType == distributedCodes::DISTRIBUTED_MULTIPLE_ROOTS
1859 )
1860 {
1861 // Different roots for each sub-rank
1862 // - use point-to-point communication to transmit values
1863
1864 fileName newCasePath;
1865
1866 if (UPstream::master())
1867 {
1868 for (const int subproci : UPstream::subProcs())
1869 {
1870 newCasePath = roots[subproci-1]/globalCase_;
1871 OPstream::send(newCasePath, subproci); // worldComm
1872 }
1873 }
1874 else
1875 {
1876 IPstream::recv(newCasePath, UPstream::masterNo()); // worldComm
1877 options_.set("case", newCasePath);
1878 }
1879 }
1880
1881
1882 // Establish rootPath_/globalCase_/case_ for sub-process
1883 if (!UPstream::master())
1884 {
1885 setCasePaths();
1886 }
1887
1888
1889 nProcs = UPstream::nProcs();
1890 if (UPstream::nProcs() > 1)
1891 {
1892 case_ =
1893 (
1894 globalCase_
1895 / ("processor" + Foam::name(UPstream::myProcNo()))
1896 );
1897 }
1898 else
1899 {
1900 case_ = globalCase_;
1901 }
1902 }
1903 else
1904 {
1905 // Establish rootPath_/globalCase_/case_
1906 setCasePaths();
1907 case_ = globalCase_; // Redundant, but extra safety?
1908 }
1909
1910
1911 // If needed, adjust fileHandler for distributed roots
1912 if (runControl_.distributed() && fileOperation::fileHandlerPtr_)
1913 {
1914 fileOperation::fileHandlerPtr_->distributed(true);
1915
1916 const labelList& ranks = fileHandler().ioRanks();
1917
1918 if (runControl_.parRun() && ranks.size())
1919 {
1920 // Detect processor directories both on local proc and on
1921 // (world) master proc. If the local proc doesn't have them
1922 // but the master has it will attempt to copy them.
1923
1924 // Expected local directory name
1925 const fileName procDir
1926 (
1927 rootPath_
1928 / globalCase_
1929 / ("processor" + Foam::name(UPstream::myProcNo()))
1930 );
1931
1932 // Try and find my local directory using the fileHandler. This
1933 // will check the local disk on the IO rank
1934 // (since running distributed)
1935 fileNameList pathDirs(UPstream::nProcs());
1936 auto& pathDir = pathDirs[UPstream::myProcNo()];
1937 pathDir = fileHandler().filePath(procDir, false);
1938
1939 if (returnReduceOr(pathDir.empty()))
1940 {
1941 // There is at least one processor that cannot find
1942 // the processor directory. Look for it on the master.
1943 // E.g. decomposed into 4 processors, two roots:
1944 // processors4_0-1/
1945 // processors4_2-3/
1946 // So:
1947 // - processor0 reads the same disk as processor0
1948 // - processor2 needs the whole directory sent over
1949 // - processor3 reads the same disk as processor2
1950 if (UPstream::master() && bannerEnabled())
1951 {
1952 Info<< "I/O :"
1953 << " distributed - copying missing directories"
1954 << nl;
1955 }
1956
1957 // Collect all wanted directories (or empty). Note: could
1958 // just collect missing ones ...
1959
1960 Pstream::gatherList(pathDirs);
1961 fileName masterRootPath(rootPath_);
1962 Pstream::broadcast(masterRootPath);
1963
1965 if (UPstream::master())
1966 {
1967 const bool oldParRun = UPstream::parRun(false);
1968 // Note: non-parallel running might update
1969 // fileOperation::nProcs() so store & restore below
1970 const label nOldProcs = fileHandler().nProcs();
1971
1972 label rank = 0;
1973 for (label proci = 1; proci < pathDirs.size(); ++proci)
1974 {
1975 if (ranks.contains(proci))
1976 {
1977 rank = proci;
1978 }
1979
1980 if (pathDirs[proci].empty())
1981 {
1982 // Synthesise corresponding name on the master
1983 // processor
1984 const fileName procDir
1985 (
1986 rootPath_
1987 / globalCase_
1988 / ("processor" + Foam::name(proci))
1989 );
1990 const fileName foundDir
1991 (
1992 fileHandler().filePath(procDir, false)
1993 );
1994
1995 if
1996 (
1997 !foundDir.empty()
1998 && !rankToDirs[rank].contains(foundDir)
1999 )
2000 {
2001 rankToDirs[rank].push_back(foundDir);
2002 }
2003 }
2004 }
2005
2006 UPstream::parRun(oldParRun);
2007 const_cast<fileOperation&>(fileHandler()).nProcs(nOldProcs);
2008 }
2009 Pstream::broadcast(rankToDirs);
2010
2011 // Copy missing directories on all the IOranks.
2012 // Note: instead of passing 'writeOnProc' flag we could create
2013 // communicator just between master and IOrank, but that is
2014 // also expensive.
2015
2016 forAll(rankToDirs, proci)
2017 {
2018 // Am I the reponsible IOrank for this processor
2019 const bool amIO = (UPstream::myProcNo() == proci);
2020
2021 // Construct equivalent directory on proci
2022 for (const auto& srcDir : rankToDirs[proci])
2023 {
2024 const fileName tgtDir
2025 (
2026 rootPath_
2027 / srcDir.relative(masterRootPath)
2028 );
2029
2030 if (amIO)
2031 {
2032 // I am the IO rank
2033 Pout<< "On rank " << proci << nl
2034 << " copying : " << srcDir << nl
2035 << " to : " << tgtDir << endl;
2036 }
2037
2038 fileHandler().broadcastCopy
2039 (
2041 amIO,
2042 tgtDir,
2043 tgtDir
2044 );
2045 }
2046 }
2047 }
2048 }
2049 }
2050
2051
2052 // Keep/discard sub-process host/root information for reporting:
2053 if (UPstream::master() && runControl_.parRun())
2054 {
2055 if (!writeHostsSwitch)
2056 {
2057 // Clear here to ensures it doesn't show in the jobInfo
2058 hostProcs.clear();
2059 }
2060 if (!writeRootsSwitch)
2061 {
2062 roots.clear();
2063 }
2064 }
2065
2066 if (UPstream::master() && bannerEnabled())
2067 {
2068 Info<< "Case : " << (rootPath_/globalCase_).c_str() << nl
2069 << "nProcs : " << nProcs << nl;
2070
2071 if (runControl_.parRun())
2072 {
2073 if (hostProcs.size())
2074 {
2075 if (writeHostsSwitch == 1)
2076 {
2077 // Compact output (see etc/controlDict)
2078 printHostsSubscription(hostProcs);
2079 }
2080 else if (writeHostsSwitch)
2081 {
2082 // Full output of "host.pid"
2083 Info<< "Hosts :\n(" << nl;
2084
2085 // Include master in the list
2086 Info<< " " << Foam::hostName().c_str() << '.'
2087 << Foam::pid() << nl;
2088
2089 // Sub-processes
2090 for (const auto& str : hostProcs)
2091 {
2092 Info<< " " << str.c_str() << nl;
2093 }
2094 Info<< ')' << nl;
2095 }
2096 }
2097 if (roots.size())
2098 {
2099 bool hasPrinted = false;
2100 if (writeRootsSwitch == 1)
2101 {
2102 // Compact output
2103 hasPrinted = printRootsSubscription(hostProcs, roots);
2104 }
2105 if (writeRootsSwitch && !hasPrinted)
2106 {
2107 // Full output
2108 Info<< "Roots : " << roots << nl;
2109 }
2110 }
2111
2112 Info<< "Pstream initialized with:" << nl;
2113 {
2114 Info<< " node communication : ";
2116 Info<< nl;
2117 }
2118 {
2119 Info<< " topology controls : ";
2121 Info<< nl;
2122 }
2123
2125 {
2126 Info<< " floatTransfer : enabled" << nl;
2127 }
2129 {
2130 Info<< " maxCommsSize : "
2132 }
2134 {
2135 Info<< " nProcsSimpleSum : "
2137 }
2138 {
2139 const auto& commsType =
2141
2142 Info<< " consensus exchange : "
2144 << " (tuning: " << UPstream::tuning_NBX_ << ')' << nl
2145 << " exchange algorithm : "
2147 << " commsType : " << commsType << nl
2148 << " polling iterations : "
2150 }
2151
2152 if (UPstream::allWorlds().size() > 1)
2153 {
2154 Info<< " worlds : "
2156 << " world : " << UPstream::myWorld()
2157 << nl;
2158 }
2159 }
2160 }
2161
2162 if (initialise)
2163 {
2164 jobInfo.add("root", rootPath_);
2165 jobInfo.add("case", globalCase_);
2166 jobInfo.add("nProcs", nProcs);
2167 if (hostProcs.size())
2168 {
2169 jobInfo.add("hosts", hostProcs);
2170 }
2171 if (roots.size())
2172 {
2173 jobInfo.add("roots", roots);
2174 }
2175 jobInfo.write();
2176
2177 // Switch on signal trapping. We have to wait until after Pstream::init
2178 // since this sets up its own ones.
2179 sigFpe::set(bannerEnabled());
2180 sigInt::set(bannerEnabled());
2181 sigQuit::set(bannerEnabled());
2182 sigSegv::set(bannerEnabled());
2183
2184 // Create memory pool (if any) after MPI has been setup
2185 MemoryPool::create(bannerEnabled());
2186
2187 if (UPstream::master() && bannerEnabled())
2188 {
2189 Info<< "fileModificationChecking : "
2190 << "Monitoring run-time modified files using "
2192 [
2194 ];
2195 if
2196 (
2199 )
2200 {
2202 {
2203 Info<< " (fileModificationSkew "
2205 << ")";
2206 }
2208 {
2209 Info<< " (fileModificationSkew "
2211 << ", maxFileModificationPolls "
2213 << ")";
2214 }
2215 else
2216 {
2218 << "Invalid setting for maxFileModificationPolls "
2220 << exit(FatalError);
2221 }
2222 }
2223 Info<< nl;
2224
2225 Info<< "allowSystemOperations : ";
2227 {
2228 Info<< "Allowing";
2229 }
2230 else
2231 {
2232 Info<< "Disallowing";
2233 }
2234 Info<< " user-supplied system call operations" << nl
2235 << nl;
2237
2238 // Ugly handling of localBoundaryConsistency switches
2240 (
2242 );
2244 }
2245}
2246
2247
2248// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
2249
2251{
2252 jobInfo.stop(); // Normal job termination
2253
2254 // Delete file handler to flush any remaining IO
2255 (void) fileOperation::fileHandler(nullptr);
2256}
2257
2258
2259// * * * * * * * * * * * * * * * Capabilities * * * * * * * * * * * * * * * //
2260
2262{
2263 if (validOptions.contains("withFunctionObjects"))
2264 {
2265 // '-withFunctionObjects' is available and explicitly enabled
2266 return options_.contains("withFunctionObjects");
2267 }
2268 else if (validOptions.contains("noFunctionObjects"))
2269 {
2270 // '-noFunctionObjects' is available and not explicitly disabled
2271 return !options_.contains("noFunctionObjects");
2273
2274 // Disallow functions if there is no way to enable/disable them
2275 return false;
2276}
2277
2278
2279bool Foam::argList::allowLibs() const
2281 return !options_.contains("no-libs");
2282}
2283
2284
2285// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2286
2287Foam::label Foam::argList::count(const UList<word>& optionNames) const
2288{
2289 label num = 0;
2290 for (const word& optName : optionNames)
2291 {
2292 if (options_.contains(optName))
2293 {
2294 ++num;
2295 }
2296 }
2297 return num;
2298}
2299
2300
2301Foam::label Foam::argList::count(std::initializer_list<word> optionNames) const
2302{
2303 label num = 0;
2304 for (const word& optName : optionNames)
2305 {
2306 if (options_.contains(optName))
2307 {
2308 ++num;
2309 }
2310 }
2311 return num;
2312}
2313
2314
2315bool Foam::argList::setOption(const word& optName, const string& param)
2316{
2317 // Some options are always protected
2318 if
2319 (
2320 optName == "case"
2321 || optName == "parallel"
2322 || optName == "roots"
2323 )
2324 {
2326 <<"Option: '" << optName << "' is protected" << nl
2327 << exit(FatalError);
2328 return false;
2329 }
2330
2331 const auto optIter = options_.cfind(optName);
2332
2333 if (!optIter.good() || (optIter.val() != param))
2334 {
2335 options_.set(optName, param);
2336 return true;
2337 }
2338
2339 return false;
2340}
2341
2342
2343bool Foam::argList::unsetOption(const word& optName)
2344{
2345 // Some options are always protected
2346 if
2347 (
2348 optName == "case"
2349 || optName == "parallel"
2350 || optName == "roots"
2351 )
2352 {
2354 <<"Option: '" << optName << "' is protected" << nl
2355 << exit(FatalError);
2356 return false;
2358
2359 // Remove the option, return true if state changed
2360 return options_.erase(optName);
2361}
2362
2363
2364void Foam::argList::displayDoc(bool source) const
2365{
2366 const dictionary& docDict = debug::controlDict().subDict("Documentation");
2367 fileNameList docDirs(docDict.get<fileNameList>("doxyDocDirs"));
2368 fileName docExt(docDict.get<fileName>("doxySourceFileExt"));
2369
2370 // For source code: change xxx_8C.html to xxx_8C_source.html
2371 if (source)
2372 {
2373 docExt.replace(".", "_source.");
2374 }
2375
2376 fileName url;
2377
2378 for (const fileName& dir : docDirs)
2379 {
2380 // The http protocols are last in the list
2381 if (dir.starts_with("http:") || dir.starts_with("https:"))
2382 {
2383 url = dir/executable_ + docExt;
2384 break;
2385 }
2386
2387 fileName docFile = stringOps::expand(dir/executable_ + docExt);
2388
2389 if
2390 (
2391 docFile.starts_with("file://")
2392 ? isFile(docFile.substr(7)) // check part after "file://"
2393 : isFile(docFile)
2394 )
2395 {
2396 url = std::move(docFile);
2397 break;
2398 }
2399 }
2400
2401 if (url.empty())
2402 {
2403 Info<< nl
2404 << "No documentation found for " << executable_
2405 << ", but you can use -help to display the usage\n" << endl;
2406
2407 return;
2408 }
2409
2410 string docBrowser = getEnv("FOAM_DOC_BROWSER");
2411 if (docBrowser.empty())
2412 {
2413 docDict.readEntry("docBrowser", docBrowser);
2414 }
2415
2416 // Can use FOAM_DOC_BROWSER='application file://%f' if required
2417 if (docBrowser.contains("%f"))
2418 {
2419 docBrowser.replace("%f", url);
2420 }
2421 else
2422 {
2423 docBrowser += " " + url;
2424 }
2425
2426 // Split on whitespace to use safer version of Foam::system()
2427
2428 CStringList command(stringOps::splitSpace(docBrowser));
2429
2430 Info
2431 << "OpenFOAM " << foamVersion::api << " documentation:" << nl
2432 << " " << command << nl << endl;
2433
2434 Foam::system(command, true);
2435}
2436
2437
2438bool Foam::argList::check(bool checkArgs, bool checkOpts) const
2439{
2440 bool ok = true;
2441
2442 if (UPstream::master())
2443 {
2444 const label nargs = args_.size()-1;
2445 if (checkArgs && nargs != validArgs.size())
2446 {
2448 << "Expected " << validArgs.size()
2449 << " arguments but found " << nargs << endl;
2450 ok = false;
2451 }
2452
2453 if (checkOpts)
2454 {
2455 forAllConstIters(options_, iter)
2456 {
2457 const word& optName = iter.key();
2458 if
2459 (
2460 !validOptions.contains(optName)
2461 && !validParOptions.contains(optName)
2462 )
2463 {
2465 << "Invalid option: -" << optName << endl;
2466 ok = false;
2467 }
2468 }
2469 }
2470
2471 if (!ok)
2472 {
2474 << nl
2475 << "See '" << executable_ << " -help' for usage" << nl
2476 << " or '" << executable_
2477 << " -help-full' for extended usage" << nl
2478 << nl;
2480 }
2481
2482 return ok;
2483}
2484
2485
2487{
2488 if (!fileHandler().isDir(rootPath()))
2489 {
2491 << executable_
2492 << ": cannot open root directory " << rootPath()
2493 << endl;
2494
2495 return false;
2496 }
2497
2498 const fileName pathDir(fileHandler().filePath(path(), false));
2499
2500 if (checkProcessorDirectories_ && pathDir.empty() && UPstream::master())
2501 {
2502 // Allow non-existent processor directories on sub-processes,
2503 // to be created later (e.g. redistributePar)
2505 << executable_
2506 << ": cannot open case directory " << path()
2507 << endl;
2508
2509 return false;
2510 }
2511
2512 return true;
2513}
2514
2515
2516// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
propsDict readIfPresent("fields", acceptFields)
Foam::argList::initValidTables dummyInitValidTables
Definition argList.C:213
An adapter for copying a list of C++ strings into a list of C-style strings for passing to C code tha...
Definition CStringList.H:68
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void push_back(const T &val)
Copy append an element to the end of this list.
static void warnLocalBoundaryConsistencyCompat(const dictionary &)
Warn about keyword changes for local boundary consistency checks.
Definition FieldBase.C:77
A HashTable with keys but without contents that is similar to std::unordered_set.
Definition HashSet.H:96
A HashTable similar to std::unordered_map.
Definition HashTable.H:124
readOption
Enumeration defining read preferences.
@ READ_IF_PRESENT
Reading is optional [identical to LAZY_READ].
@ MUST_READ
Reading required.
static Ostream & writeDivider(Ostream &os)
Write the standard file section divider.
static Ostream & writeBanner(Ostream &os, const bool noSyntaxHint=false)
Write the standard OpenFOAM file/dictionary banner.
static float fileModificationSkew
Time skew (seconds) for file modification checks.
Definition IOobject.H:363
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition IOobject.H:358
static const Enum< fileCheckTypes > fileCheckTypesNames
Names for the fileCheckTypes.
Definition IOobject.H:218
static int maxFileModificationPolls
Max number of times to poll for file modification changes.
Definition IOobject.H:368
Input inter-processor communications stream using MPI broadcast.
Definition IPstream.H:114
static void recv(Type &value, const int communicator=UPstream::worldComm)
Receive (from broadcast, root == UPstream::masterNo()) and deserialize a value. Uses operator>> for d...
Definition IPstream.H:139
Input inter-processor communications stream.
Definition IPstream.H:53
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
Definition IPstream.H:80
An input stream of tokens.
Definition ITstream.H:56
static void disable() noexcept
Disallow JobInfo by forcing writeJobInfo (InfoSwitch) off.
Definition JobInfo.C:88
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void push_back(const T &val)
Append an element at the end of the list.
Definition ListI.H:221
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
static bool create(bool verbose=false)
Create a memory pool instance (if not already active).
Output inter-processor communications stream using MPI broadcast.
Definition OPstream.H:133
static void send(const Type &value, const int communicator=UPstream::worldComm)
Serialize a value and broadcast (root == UPstream::masterNo()). Uses operator<< for serialization.
Definition OPstream.H:161
Output inter-processor communications stream.
Definition OPstream.H:53
bool threads() const noexcept
True if MPI threads are desired (default: false).
Definition parRun.H:195
void incrDryRun(int i=1) noexcept
Increase the dry-run level.
Definition parRun.H:120
static int algorithm
Preferred exchange algorithm (may change or be removed in future).
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition Switch.H:81
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
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
bool contains(const T &val) const
True if the value is contained in the list.
Definition UListI.H:302
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
label find(const T &val) const
Find index of the first occurrence of the value.
Definition UList.C:160
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Definition OPstreams.C:84
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
@ scheduled
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
Definition UPstream.H:83
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition UPstream.H:92
static bool floatTransfer
Should compact transfer be used in which floats replace doubles reducing the bandwidth requirement at...
Definition UPstream.H:1024
static void printTopoControl(Ostream &os)
Report the topology routines settings.
Definition UPstream.C:100
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition UPstream.H:1691
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
static int nProcsNonblockingExchange
Number of processors to change to nonBlocking consensual exchange (NBX). Ignored for zero or negative...
Definition UPstream.H:1035
static void exit(int errNo=1)
Shutdown (finalize) MPI as required and exit program with errNo.
Definition UPstream.C:61
static int tuning_NBX_
Tuning parameters for non-blocking exchange (NBX).
Definition UPstream.H:1055
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run.
Definition UPstream.H:1697
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition UPstream.H:1866
static int nProcsSimpleSum
Number of processors to change from linear to tree communication.
Definition UPstream.H:1029
static int nPollProcInterfaces
Number of polling cycles in processor updates.
Definition UPstream.H:1040
static const wordList & allWorlds() noexcept
All worlds.
Definition UPstream.H:1822
static int maxCommsSize
Optional maximum message size (bytes).
Definition UPstream.H:1050
@ gatherList
gatherList [manual algorithm]
Definition UPstream.H:194
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
static void printNodeCommsControl(Ostream &os)
Report the node-communication settings.
Definition UPstream.C:56
static commsTypes defaultCommsType
Default commsType.
Definition UPstream.H:1045
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
static const word & myWorld()
My world.
Definition UPstream.H:1846
Extract command arguments and options from the supplied argc and argv parameters.
Definition argList.H:119
void parse(bool checkArgs, bool checkOpts, bool initialise)
Scan for -help, -doc options etc prior to checking the validity of other args/opts and finally initia...
Definition argList.C:1242
static word postProcessOptionName
Standard name for the post-processing option.
Definition argList.H:304
static HashTable< string, label, Hash< label > > argUsage
Short description for program arguments.
Definition argList.H:279
static void noBanner()
Disable emitting the banner information.
Definition argList.C:506
static std::string::size_type usageMin
Min indentation when displaying usage (default: 20).
Definition argList.H:294
static void noFunctionObjects(bool addWithOption=false)
Remove '-noFunctionObjects' option and ignore any occurrences.
Definition argList.C:562
static HashTable< std::pair< word, int > > validOptionsCompat
A list of aliases for options.
Definition argList.H:267
static HashTable< string > validParOptions
A list of valid parallel options.
Definition argList.H:260
static void removeOption(const word &optName)
Remove option from validOptions and from optionUsage.
Definition argList.C:486
const stringList & args() const noexcept
Return arguments.
Definition argListI.H:145
static void addVerboseOption(const string &usage="", bool advanced=false)
Enable a 'verbose' bool option, with usage information.
Definition argList.C:535
argList(int &argc, char **&argv, bool checkArgs=argList::argsMandatory(), bool checkOpts=true, bool initialise=true)
Construct from argc and argv checking the arguments and options as requested.
Definition argList.C:913
static std::string::size_type usageMax
Max screen width when displaying usage (default: 80).
Definition argList.H:299
bool unsetOption(const word &optName)
Unset option directly (use with caution).
Definition argList.C:2336
static bool postProcess(int argc, char *argv[])
True if the post-processing option is found in the argv list.
Definition argList.C:625
const HashTable< string > & options() const noexcept
Return options.
Definition argListI.H:158
int verbose() const noexcept
Return the verbose flag.
Definition argListI.H:121
const fileName & rootPath() const noexcept
Return root path.
Definition argListI.H:56
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition argList.C:366
static bool bannerEnabled()
Banner status (enabled/disabled).
Definition argList.C:512
static fileName envGlobalPath()
Global case (directory) from environment variable.
Definition argList.C:668
static void noLibs()
Add the '-no-libs' command line option.
Definition argList.C:588
static void noJobInfo()
Suppress JobInfo, overriding controlDict setting.
Definition argList.C:582
bool allowLibs() const
The controlDict 'libs' entry is allowed to be used. (eg, has not been disabled by the -no-libs option...
Definition argList.C:2272
void printUsage(bool full=true) const
Print usage.
static void setAdvanced(const word &optName, bool advanced=true)
Set an existing option as being 'advanced' or normal.
Definition argList.C:419
bool check(bool checkArgs=argList::argsMandatory(), bool checkOpts=true) const
Check the parsed command-line for mandatory arguments and that all the options are correct.
Definition argList.C:2431
virtual ~argList()
Destructor.
Definition argList.C:2243
fileName relativePath(const fileName &input, const bool caseTag=false) const
Return the input relative to the globalPath by stripping off a leading value of the globalPath.
Definition argListI.H:87
bool readListIfPresent(const word &optName, List< T > &list) const
If named option is present, get a List of values treating a single entry like a list of size 1.
Definition argListI.H:387
static HashTable< string > optionUsage
Short description for validOptions.
Definition argList.H:284
bool allowFunctionObjects() const
The controlDict 'functions' entry is allowed to be used.
Definition argList.C:2254
static fileName envRelativePath(const fileName &input, const bool caseTag=false)
Return the input relative to the globalPath by stripping off a leading value of the envGlobalPath.
Definition argList.C:675
static bool argsMandatory()
Command arguments type (optional/mandatory).
Definition argList.C:500
label count(const UList< word > &optionNames) const
Return how many of the specified options were used.
Definition argList.C:2280
static HashSet< string > advancedOptions
The "advanced" options are shown with -help-full (not with –help).
Definition argList.H:250
bool setOption(const word &optName, const string &param="")
Set option directly (use with caution).
Definition argList.C:2308
static void addDryRunOption(const string &usage, bool advanced=false)
Enable a 'dry-run' bool option, with usage information.
Definition argList.C:519
label size() const noexcept
The number of arguments.
Definition argListI.H:139
static void noCheckProcessorDirectories()
Disable checking of processor directories.
Definition argList.C:619
static SLList< string > notes
General usage notes.
Definition argList.H:289
bool checkRootCase() const
Check root path and case path.
Definition argList.C:2479
void displayDoc(bool source=false) const
Display documentation in browser.
Definition argList.C:2357
static void noMandatoryArgs()
Flag command arguments as being optional (non-mandatory).
Definition argList.C:494
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition argList.C:389
void printCompat() const
Print option compatibility.
static void noParallel()
Remove the parallel options.
Definition argList.C:599
static void addUsage(const word &optName, const string &usage)
Add option usage information to optionUsage.
Definition argList.C:461
void printMan() const
Print usage as nroff-man format (Experimental).
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition argList.C:400
void printNotes() const
Print notes (if any).
static void parallelThreads_on()
MPI threads are desired for the application.
Definition argList.C:613
static HashTable< string > validOptions
A list of valid options.
Definition argList.H:255
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition argList.H:245
ITstream lookup(const word &optName) const
Return an input stream from the named option.
Definition argListI.H:177
const word & executable() const noexcept
Name of executable without the path.
Definition argListI.H:44
static word envExecutable()
Name of the executable from environment variable.
Definition argList.C:662
static HashTable< std::pair< bool, int > > ignoreOptionsCompat
A list of options to ignore.
Definition argList.H:274
static void addNote(const string &note)
Add extra notes for the usage information.
Definition argList.C:477
static void ignoreOptionCompat(std::pair< const char *, int > compat, bool expectArg)
Specify an option to be ignored.
Definition argList.C:447
dlLibraryTable & libs() const noexcept
Mutable access to the loaded dynamic libraries.
Definition argListI.H:133
static void addOptionCompat(const word &optName, std::pair< const char *, int > compat)
Specify an alias for the option name.
Definition argList.C:433
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
static std::string date()
The current wall-clock date as a string formatted as (MON dd yyyy), where MON is Jan,...
Definition clock.C:73
static std::string clockTime()
The current wall-clock (in local time) as a string formatted as as (hh:mm:ss).
Definition clock.C:88
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition dictionary.C:441
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect,...
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
static int allowSystemOperations
Flag if system operations are allowed.
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition error.C:67
A class for handling file names.
Definition fileName.H:75
fileName relative(const fileName &parent, const bool caseTag=false) const
Return a relative name by stripping off the parent directory where possible.
Definition fileName.C:443
static fileName validate(const std::string &, const bool doClean=true)
Construct fileName without invalid characters, possibly applying other transformations such as changi...
Definition fileName.C:199
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition fileName.C:192
static const fileName null
An empty fileName.
Definition fileName.H:111
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
static bool isAbsolute(const std::string &str)
Return true if filename starts with a '/' or '\' or (windows-only) with a filesystem-root.
Definition fileNameI.H:129
An encapsulation of filesystem-related operations.
static const fileOperation & fileHandler()
Return the current file handler. Will create the default file handler if necessary.
static refPtr< fileOperation > fileHandlerPtr_
The currently active file handler. Avoid accessing directly.
static word defaultFileHandler
Name of the default fileHandler.
static int cacheLevel() noexcept
Return cache level.
static autoPtr< fileOperation > New(const word &handlerType, bool verbose=false)
Select fileHandler-type. Uses defaultFileHandler if the handlerType is empty.
static int nProcsFilter() noexcept
Return collated 'processorsDDD' filtering.
static autoPtr< fileOperationInitialise > New(const word &type, int &argc, char **&argv)
Select initialisation type.
@ LITERAL
String literal.
Definition keyType.H:82
Lookup type of boundary radiation properties.
Definition lookup.H:60
static void set(bool verbose=false)
Activate SIGFPE handler when FOAM_SIGFPE is enabled. Activate fill memory with signaling_NaN when FOA...
static void set(bool verbose=false)
Activate SIGINT signal handler.
static void set(bool verbose=false)
Activate SIGQUIT signal handler.
static void set(bool verbose=false)
Activate SIGSEGV signal handler.
void setNamedValue(const std::string_view name, int val, bool verbose=false, bool dryrun=false)
Set named value, but also handle embedded 'name=value' syntax.
bool contains(char c) const noexcept
True if string contains given character (cf. C++23).
Definition string.H:412
bool starts_with(char c) const
True if string starts with given character (cf. C++20).
Definition string.H:436
string & replace(const std::string &s1, const std::string &s2, size_type pos=0)
Replace first occurrence of sub-string s1 with s2, beginning at pos.
Definition string.C:101
static labelList matching(const wordRe &select, const UList< StringType > &input, const bool invert=false)
Determine the list indices for all matches.
A class for handling words, derived from Foam::string.
Definition word.H:66
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition error.H:592
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define DetailInfo
Definition evalEntry.C:30
auto & name
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
constexpr const char *const group
Group name for atomic constants.
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition debug.C:228
simpleObjectRegistry & infoObjects()
Access to registered InfoSwitch objects.
Definition debug.C:299
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition debug.C:216
dictionary & controlDict()
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition debug.C:142
simpleObjectRegistry & optimisationObjects()
Access to registered OptimisationSwitch objects.
Definition debug.C:310
simpleObjectRegistry & debugObjects()
Access to registered DebugSwitch objects.
Definition debug.C:288
::Foam::direction rank(const expressions::valueTypeCode) noexcept
The vector-space rank associated with given valueTypeCode.
Definition exprTraits.C:70
const std::string patch
OpenFOAM patch number as a std::string.
const std::string build
OpenFOAM build information as a std::string.
const int api
OpenFOAM api number (integer) corresponding to the value of OPENFOAM at the time of compilation.
bool patched()
Test if the patch string appears to be in use, which is when it is defined (non-zero).
const std::string buildArch
OpenFOAM build architecture information (machine endian, label/scalar sizes) as a std::string.
void printBuildInfo(std::ostream &os, const bool full=true)
Print information about version, build, arch to output stream.
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Foam::SubStrings splitSpace(const std::string &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC).
string expand(const std::string &s, const HashTable< string > &mapping, const char sigil='$')
Expand occurrences of variables according to the mapping and return the expanded string.
Namespace for OpenFOAM.
fileName cwd()
The physical or logical current working directory path name.
Definition POSIX.C:592
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition POSIX.C:341
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable, return true on success.
Definition POSIX.C:358
bool returnReduceOr(const bool value, const int communicator=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
LList< SLListBase, T > SLList
Definition SLListFwd.H:41
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition POSIX.C:1704
List< label > labelList
A List of labels.
Definition List.H:62
List< fileName > fileNameList
List of fileName.
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler().
messageStream Info
Information stream (stdout output on master, null elsewhere).
static bool printRootsSubscription(const UList< string > &hostProcs, const UList< fileName > &roots)
Definition argList.C:263
static void check(const int retVal, const char *what)
string userName()
Return the user's login name.
Definition POSIX.C:424
List< string > stringList
List of string.
Definition stringList.H:32
pid_t pgid()
Return the group PID of this process.
Definition POSIX.C:328
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
string hostName()
Return the system's host name, as per hostname(1).
Definition POSIX.C:373
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
pid_t ppid()
Return the parent PID of this process.
Definition POSIX.C:322
static void printHostsSubscription(const UList< string > &hostProcs)
Definition argList.C:227
pid_t pid()
Return the PID of this process.
Definition POSIX.C:316
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 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.
JobInfo jobInfo
Definition JobInfo.C:45
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition POSIX.C:862
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional 'FOAM Warning' header text.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Foam::argList args(argc, argv)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235
Operations on lists of strings.