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