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-2024 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.push_back(host);
275  sortedRoots.push_back(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.push_back(argName);
364 
365  // The first program argument starts at 1 - obtain index after push_back()
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.push_back(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  // addProfiling(argList, "argList");
1020 
1021  // ------------------------------------------------------------------------
1022 
1023  // Convert argv -> args_ and capture ( ... ) lists
1024  regroupArgv(argc, argv);
1025  commandLine_ += args_[0];
1026 
1027  // Set executable name immediately - useful when emitting errors.
1028  executable_ = fileName(args_[0]).name();
1029 
1030  // Check arguments and options, argv[0] was already handled
1031  int nArgs = 1;
1032  for (int argi = 1; argi < args_.size(); ++argi)
1033  {
1034  commandLine_ += ' ';
1035  commandLine_ += args_[argi];
1036 
1037  const char *optName = args_[argi].data();
1038 
1039  if (optName[0] == '-')
1040  {
1041  ++optName; // Looks like an option, skip leading '-'
1042 
1043  if (!*optName)
1044  {
1045  Warning
1046  << "Ignoring lone '-' on the command-line" << endl;
1047  continue;
1048  }
1049 
1050  // Option known and expects an argument?
1051  // - use Switch for a tri-state
1052  // True : known option, expects a parameter
1053  // False : known option, no parameter
1054  // bad() : unknown option
1055 
1056  Switch wantArg(Switch::INVALID);
1057  auto optIter = validOptions.cfind(optName);
1058  if
1059  (
1060  optIter.good()
1061  || (optIter = validParOptions.cfind(optName)).good()
1062  )
1063  {
1064  wantArg = !optIter.val().empty();
1065  }
1066 
1067 
1068  if (wantArg)
1069  {
1070  // Option expects a parameter
1071  // - get it or emit a FatalError.
1072 
1073  ++argi;
1074  if (argi >= args_.size())
1075  {
1077 
1078  Info<< nl
1079  <<"Error: option '-" << optName
1080  << "' requires an argument" << nl << nl
1081  << "See '" << executable_ << " -help' for usage" << nl
1082  << " or '" << executable_
1083  << " -help-full' for extended usage" << nl
1084  << nl;
1085 
1086  UPstream::exit(1); // works for serial and parallel
1087  }
1088 
1089  commandLine_ += ' ';
1090  commandLine_ += args_[argi];
1091 
1092  //
1093  // Special handling of these options
1094  //
1095 
1096  if (strcmp(optName, "lib") == 0)
1097  {
1098  // The '-lib' option:
1099  // Add name(s) to libs for later opening
1100  libs().push_back(this->getList<fileName>(argi));
1101  }
1102  else if (strcmp(optName, "debug-switch") == 0)
1103  {
1104  // The '-debug-switch' option:
1105  // change registered debug switch
1106  DetailInfo << "debug-switch ";
1108  .setNamedValue(args_[argi], 1, true);
1109  }
1110  else if (strcmp(optName, "info-switch") == 0)
1111  {
1112  // The '-info-switch' option:
1113  // change registered info switch
1114  DetailInfo << "info-switch ";
1116  .setNamedValue(args_[argi], 1, true);
1117  }
1118  else if (strcmp(optName, "opt-switch") == 0)
1119  {
1120  // The '-opt-switch' option:
1121  // change registered optimisation switch
1122  DetailInfo << "opt-switch ";
1124  .setNamedValue(args_[argi], 1, true);
1125  }
1126  else
1127  {
1128  // Regular option (with a parameter):
1129  // Duplicates handled by using the last -option specified
1130  options_.set(optName, args_[argi]);
1131  }
1132  }
1133  else
1134  {
1135  // All other options (including unknown ones) are simply
1136  // registered as existing.
1137 
1138  options_.insert(optName, "");
1139 
1140  // // Special increment handling for some known flags
1141  // if (wantArg.good())
1142  // {
1143  // ...
1144  // }
1145  }
1146  }
1147  else
1148  {
1149  if (nArgs != argi)
1150  {
1151  args_[nArgs] = args_[argi];
1152  }
1153  ++nArgs;
1154  }
1155  }
1156 
1157  args_.resize(nArgs);
1158 
1159  parse(checkArgs, checkOpts, initialise);
1160 }
1161 
1162 
1164 (
1165  const argList& args,
1166  const HashTable<string>& options,
1167  bool checkArgs,
1168  bool checkOpts,
1169  bool initialise
1170 )
1171 :
1172  runControl_(args.runControl_),
1173  args_(args.args_),
1174  options_(options),
1175  libs_(),
1176  executable_(args.executable_),
1177  rootPath_(args.rootPath_),
1178  globalCase_(args.globalCase_),
1179  case_(args.case_),
1180  commandLine_(args.commandLine_)
1181 {
1182  parse(checkArgs, checkOpts, initialise);
1183 }
1184 
1185 
1187 (
1188  bool checkArgs,
1189  bool checkOpts,
1190  bool initialise
1191 )
1192 {
1193  // Help/documentation options:
1194  // -doc Display documentation in browser
1195  // -doc-source Display source code in browser
1196  // -help Display short help and exit
1197  // -help-compat Display compatibility options
1198  // -help-full Display full help and exit
1199  {
1200  bool quickExit = false;
1201 
1202  // Display either application or source documentation, not both
1203  if (options_.contains("doc"))
1204  {
1205  displayDoc(false);
1206  quickExit = true;
1207  }
1208  else if (options_.contains("doc-source"))
1209  {
1210  displayDoc(true);
1211  quickExit = true;
1212  }
1213 
1214  // Display either short or full help, not both
1215  if (options_.contains("help-full"))
1216  {
1217  printUsage(true);
1218  quickExit = true;
1219  }
1220  else if (options_.contains("help-notes"))
1221  {
1222  printNotes();
1223  Info<< nl;
1224  quickExit = true;
1225  }
1226  else if (options_.contains("help"))
1227  {
1228  printUsage(false);
1229  quickExit = true;
1230  }
1231  else if (options_.contains("help-man"))
1232  {
1233  printMan();
1234  quickExit = true;
1235  }
1236 
1237  // Allow independent display of compatibility information
1238  if (options_.contains("help-compat"))
1239  {
1240  printCompat();
1241  quickExit = true;
1242  }
1243 
1244  if (quickExit)
1245  {
1246  std::exit(0);
1247  }
1248  }
1249 
1250  // Print the collected error messages and exit if check fails
1251  if (!check(checkArgs, checkOpts))
1252  {
1254  FatalError.write(Info, false);
1255 
1256  UPstream::exit(1); // works for serial and parallel
1257  }
1258 
1259  if (initialise)
1260  {
1261  const string dateString = clock::date();
1262  const string timeString = clock::clockTime();
1263 
1264  // Print the banner once only for parallel runs
1265  if (UPstream::master() && bannerEnabled())
1266  {
1268  << "Build : ";
1269 
1270  if (foamVersion::build.size())
1271  {
1272  Info<< foamVersion::build.c_str() << ' ';
1273  }
1274 
1275  Info<< "OPENFOAM=" << foamVersion::api;
1276 
1277  if (foamVersion::patched())
1278  {
1279  // Patch-level, when defined
1280  Info<< " patch=" << foamVersion::patch.c_str();
1281  }
1282 
1283  Info<< " version=" << foamVersion::version.c_str();
1284 
1285  Info<< nl
1286  << "Arch : " << foamVersion::buildArch << nl
1287  << "Exec : " << commandLine_.c_str() << nl
1288  << "Date : " << dateString.c_str() << nl
1289  << "Time : " << timeString.c_str() << nl
1290  << "Host : " << Foam::hostName().c_str() << nl
1291  << "PID : " << pid() << nl;
1292  }
1293 
1294  jobInfo.add("startDate", dateString);
1295  jobInfo.add("startTime", timeString);
1296  jobInfo.add("userName", userName());
1297 
1298  jobInfo.add("foamApi", foamVersion::api);
1299  jobInfo.add("foamVersion", word(foamVersion::version));
1300 
1301  // Add build information - only use the first word
1302  {
1303  std::string build(foamVersion::build);
1304  const auto space = build.find(' ');
1305  if (space != std::string::npos)
1306  {
1307  build.resize(space);
1308  }
1309  jobInfo.add("foamBuild", build);
1310  }
1311 
1312  jobInfo.add("code", executable_);
1313  jobInfo.add("argList", commandLine_);
1314  jobInfo.add("currentDir", cwd());
1315  jobInfo.add("PPID", ppid());
1316  jobInfo.add("PGID", pgid());
1317 
1318  // Load additional libraries (verbosity according to banner setting)
1319  libs().open(bannerEnabled());
1320  }
1321 
1322 
1323  // Set fileHandler. In increasing order of priority:
1324  // 1. default = uncollated
1325  // 2. env variable "FOAM_FILEHANDLER"
1326  // 3. etc/controlDict optimisationSwitches 'fileHandler'
1327  // 4. system/controlDict 'fileHandler' (not handled here; done in TimeIO.C)
1328  // 5. '-fileHandler' commmand-line option
1329 
1330  {
1331  word fileHandlerName
1332  (
1333  options_.lookup("fileHandler", Foam::getEnv("FOAM_FILEHANDLER"))
1334  );
1335 
1336  if (fileHandlerName.empty())
1337  {
1338  fileHandlerName = fileOperation::defaultFileHandler;
1339  }
1340 
1342  (
1343  fileOperation::New(fileHandlerName, bannerEnabled())
1344  );
1345  }
1346 
1347 
1348  stringList hostMachine;
1349  stringList hostProcs;
1350  const int writeHostsSwitch = Foam::debug::infoSwitch("writeHosts", 1);
1351  const int writeRootsSwitch = Foam::debug::infoSwitch("writeRoots", 1);
1352 
1353  // Collect machine/pid, and check that the build is identical
1354  if (runControl_.parRun())
1355  {
1356  if (UPstream::master())
1357  {
1358  hostMachine.resize(UPstream::nProcs()-1);
1359  hostProcs.resize(UPstream::nProcs()-1);
1360  string procBuild;
1361  label procPid;
1362  int proci = 0;
1363  for (const int subproci : UPstream::subProcs())
1364  {
1365  IPstream fromSubproc(UPstream::commsTypes::scheduled, subproci);
1366 
1367  fromSubproc >> procBuild >> hostMachine[proci] >> procPid;
1368 
1369  hostProcs[proci] = hostMachine[proci] + "." + name(procPid);
1370  ++proci;
1371 
1372  // Verify that all processors are running the same build
1373  if (procBuild != foamVersion::build)
1374  {
1375  FatalErrorIn(executable())
1376  << "Running build version " << foamVersion::build
1377  << " but proc " << subproci << " is running "
1378  << procBuild << nl
1379  << exit(FatalError);
1380  }
1381  }
1382  }
1383  else
1384  {
1385  OPstream toMaster
1386  (
1389  );
1390  toMaster << foamVersion::build << Foam::hostName() << Foam::pid();
1391  }
1392  }
1393 
1394 
1395  // Case is a single processor run unless it is running parallel
1396  int nProcs = 1;
1397 
1398  // Roots if running distributed. Only sized on the master
1399  fileNameList roots;
1400 
1401  enum distributedCodes
1402  {
1403  NON_DISTRIBUTED = 0,
1404  DISTRIBUTED = 1,
1405  DISTRIBUTED_SINGLE_ROOT = 2,
1406  DISTRIBUTED_MULTIPLE_ROOTS = 3
1407  };
1408 
1409  // Track which type of distributed roots etc are being used
1410  label distributedType
1411  (
1412  runControl_.distributed()
1413  ? distributedCodes::DISTRIBUTED
1414  : distributedCodes::NON_DISTRIBUTED
1415  );
1416 
1417  // Some cases where knowing the writeFormat can be useful...
1418  // label writeFormat(-1);
1419 
1420 
1421  // If this actually is a parallel run
1422  if (runControl_.parRun())
1423  {
1424  // For the master
1425  if (UPstream::master())
1426  {
1427  // Establish rootPath_/globalCase_/case_ for master
1428  setCasePaths();
1429 
1430  // The system/decomposeParDict (or equivalent)
1431  fileName source;
1432 
1433  if (this->readIfPresent("decomposeParDict", source))
1434  {
1435  bool adjustOpt = false;
1436 
1437  if (Foam::isDir(source))
1438  {
1439  source /= "decomposeParDict";
1440  adjustOpt = true;
1441  }
1442 
1443  // Case-relative if not absolute and not "./" etc
1444  if (!source.isAbsolute() && !source.starts_with('.'))
1445  {
1446  source = rootPath_/globalCase_/source;
1447  adjustOpt = true;
1448  }
1449 
1450  // Could also check for absolute path, but shouldn't be needed
1451  if (adjustOpt)
1452  {
1453  source.clean(); // Remove unneeded ".."
1454  options_.set("decomposeParDict", source);
1455  }
1456  }
1457 
1458  // If running distributed (different roots for different procs)
1459  label dictNProcs = -1;
1460  if (this->readListIfPresent("roots", roots))
1461  {
1462  source = "-roots";
1463  runControl_.distributed(true);
1464  distributedType = distributedCodes::DISTRIBUTED;
1465 
1466  if (roots.empty())
1467  {
1469  << "The -roots option must contain values"
1470  << exit(FatalError);
1471  }
1472  if (roots.size() > 1)
1473  {
1474  dictNProcs = roots.size()+1;
1475  }
1476  }
1477  else if (options_.contains("hostRoots"))
1478  {
1479  source = "-hostRoots";
1480  runControl_.distributed(true);
1481  distributedType = distributedCodes::DISTRIBUTED;
1482 
1483  ITstream is(this->lookup("hostRoots"));
1484 
1485  List<Tuple2<wordRe, fileName>> hostRoots(is);
1486  checkITstream(is, "hostRoots");
1487 
1488  if (hostRoots.empty())
1489  {
1491  << "The -hostRoots option must contain values"
1492  << exit(FatalError);
1493  }
1494 
1495  // Match machine names to roots
1496  roots.resize(UPstream::nProcs()-1, fileName::null);
1497  for (const auto& hostRoot : hostRoots)
1498  {
1499  labelList matched
1500  (
1501  wordRes::matching(hostRoot.first(), hostMachine)
1502  );
1503  for (const label matchi : matched)
1504  {
1505  if (!roots[matchi].empty())
1506  {
1508  << "Multiple matching roots for "
1509  << hostMachine[matchi] << " in "
1510  << hostRoots << nl
1511  << exit(FatalError);
1512  }
1513 
1514  roots[matchi] = hostRoot.second();
1515  }
1516  }
1517 
1518  // Check
1519  forAll(roots, hosti)
1520  {
1521  if (roots[hosti].empty())
1522  {
1524  << "No matching roots for "
1525  << hostMachine[hosti] << " in "
1526  << hostRoots << nl
1527  << exit(FatalError);
1528  }
1529  }
1530 
1531  if (roots.size() > 1)
1532  {
1533  dictNProcs = roots.size()+1;
1534  }
1535  }
1536  else if (checkProcessorDirectories_ && UPstream::nProcs() > 1)
1537  {
1538  // Check values from decomposeParDict
1539 
1540  const bool useDefault = source.empty();
1541  if (useDefault)
1542  {
1543  source = rootPath_/globalCase_/"system"/"decomposeParDict";
1544  }
1545 
1546  // Disable any parallel comms happening inside the fileHandler
1547  // since we are on master. This can happen e.g. inside
1548  // the masterUncollated/collated handler. Note that we
1549  // also have to protect the actual dictionary parsing since
1550  // it might trigger file access (e.g. #include, #codeStream)
1551  const bool oldParRun = UPstream::parRun(false);
1552  // Note: non-parallel running might update
1553  // fileOperation::nProcs() so store & restore below
1554  const label nOldProcs = fileHandler().nProcs();
1555 
1556  autoPtr<ISstream> dictStream
1557  (
1558  fileHandler().NewIFstream(source)
1559  );
1560 
1561  if (dictStream && dictStream->good())
1562  {
1563  // Get numberOfSubdomains if it exists.
1564  // - mandatory when running with distributed roots
1565 
1566  IOobjectOption::readOption nDomainsReadOpt
1568 
1569  dictionary decompDict(*dictStream);
1570 
1571  if (decompDict.getOrDefault("distributed", false))
1572  {
1573  nDomainsReadOpt = IOobjectOption::MUST_READ;
1574  runControl_.distributed(true);
1575  distributedType = distributedCodes::DISTRIBUTED;
1576 
1577  decompDict.readEntry("roots", roots);
1578 
1579  if (roots.empty())
1580  {
1581  DetailInfo
1582  << "WARNING: running distributed"
1583  << " but did not specify roots!" << nl;
1584  }
1585  }
1586 
1587  decompDict.readEntry
1588  (
1589  "numberOfSubdomains",
1590  dictNProcs,
1592  nDomainsReadOpt
1593  );
1594  }
1595  else
1596  {
1597  if (useDefault)
1598  {
1599  // Optional if using default location
1600  DetailInfo
1601  << "WARNING: running without decomposeParDict "
1602  << this->relativePath(source) << nl;
1603  }
1604  else
1605  {
1606  // Mandatory if specified as -decomposeParDict
1607  FatalError
1608  << "Cannot read decomposeParDict: "
1609  << this->relativePath(source) << nl
1610  << exit(FatalError);
1611  }
1612  }
1613 
1614  UPstream::parRun(oldParRun); // Restore parallel state
1615  const_cast<fileOperation&>(fileHandler()).nProcs(nOldProcs);
1616 
1617  if (UPstream::nProcs() == 1)
1618  {
1619  Warning
1620  << "Running parallel on single processor. This only"
1621  << " makes sense for multi-world simulation" << endl;
1622  dictNProcs = 1;
1623  }
1624  }
1625 
1626 
1627  // Distributed roots
1628  if (!roots.empty())
1629  {
1630  for (fileName& dir : roots)
1631  {
1632  dir.expand();
1633  }
1634 
1635  // Identical root specified everywhere?
1636  // - use optimized single-root variant
1637  if (roots.size() > 1 && roots.uniform())
1638  {
1639  roots.resize(1);
1640  }
1641 
1642  if (roots.size() == 1)
1643  {
1644  // Single root specified, use it for all processes
1645  distributedType =
1646  distributedCodes::DISTRIBUTED_SINGLE_ROOT;
1647 
1648  // Adjust dictNProcs for command-line '-roots' option
1649  if (dictNProcs <= 0)
1650  {
1651  dictNProcs = UPstream::nProcs();
1652  }
1653  }
1654  else if (roots.size() > 1)
1655  {
1656  distributedType =
1657  distributedCodes::DISTRIBUTED_MULTIPLE_ROOTS;
1658 
1659  if (roots.size() != UPstream::nProcs()-1)
1660  {
1661  FatalError
1662  << "Number of roots " << roots.size()
1663  << " != number of sub-ranks "
1664  << UPstream::nProcs()-1
1665  << exit(FatalError);
1666  }
1667  }
1668  }
1669 
1670 
1671  //
1672  // Check number of processors.
1673  //
1674 
1675  // nProcs => number of actual procs
1676  // dictNProcs => number of procs specified in decompositionDict
1677  // nProcDirs => number of processor directories
1678  // (n/a when running distributed)
1679  //
1680  // - normal running : nProcs = dictNProcs = nProcDirs
1681  // - decomposition to more processors : nProcs = dictNProcs
1682  // - decomposition to fewer processors : nProcs = nProcDirs
1683  if
1684  (
1685  checkProcessorDirectories_
1686  && UPstream::nProcs() > 1
1687  )
1688  {
1689  if (dictNProcs > UPstream::nProcs())
1690  {
1691  FatalError
1692  << this->relativePath(source)
1693  << " specifies " << dictNProcs
1694  << " processors but job was started with "
1695  << UPstream::nProcs() << " ranks."
1696  << exit(FatalError);
1697  }
1698 
1699  // Possibly going to fewer processors.
1700  // Check if all procDirs are there.
1701  // NOTE: Only works when not using distributed roots!
1702  if
1703  (
1704  // Can only rely on directory scanning *without* distributed roots!
1705  roots.empty()
1706  && dictNProcs >= 1
1707  && dictNProcs < UPstream::nProcs()
1708  )
1709  {
1710  label nProcDirs = 0;
1711  {
1712  const bool oldParRun = UPstream::parRun(false);
1713  // Don't cache processor directories (probably not
1714  // needed since master-only
1715  const int oldCacheLevel(fileOperation::cacheLevel(0));
1716  // Accept any processorsXXX
1717  const int oldFilter(fileOperation::nProcsFilter(0));
1718 
1719  nProcDirs = fileHandler().nProcs
1720  (
1721  rootPath_/globalCase_,
1722  "",
1723  dictNProcs // expected nProcs
1724  );
1725 
1726  fileOperation::nProcsFilter(oldFilter);
1727  fileOperation::cacheLevel(oldCacheLevel);
1728  UPstream::parRun(oldParRun);
1729  }
1730 
1731  if (nProcDirs < UPstream::nProcs())
1732  {
1733  FatalError
1734  << "Number of processor directories = " << nProcDirs
1735  << " is not equal to the number of ranks = "
1736  << UPstream::nProcs()
1737  << exit(FatalError);
1738  }
1739  }
1740  }
1741 
1742 
1743  // Broadcast the master's argument list (unaltered)
1744  {
1745  OPBstream toProcs(UPstream::worldComm);
1746 
1747  toProcs
1748  << args_ << options_
1749  << distributedType
1750  << label(runControl_.dryRun())
1751  << label(runControl_.verbose());
1752  }
1753  }
1754  else
1755  {
1756  // Receive the broadcasted master's argument list
1757  label numDryRun, numVerbose;
1758 
1759  IPBstream fromMaster(UPstream::worldComm);
1760 
1761  fromMaster
1762  >> args_ >> options_
1763  >> distributedType
1764  >> numDryRun >> numVerbose;
1765 
1766  runControl_.distributed(distributedType);
1767  runControl_.dryRun(numDryRun);
1768  runControl_.verbose(numVerbose);
1769  }
1770 
1771 
1772  // Final handling of distributed roots (if any)
1773  if
1774  (
1775  distributedType == distributedCodes::DISTRIBUTED_SINGLE_ROOT
1776  )
1777  {
1778  // The same root for all sub-ranks
1779  // - use broadcast to transmit value
1780 
1781  fileName newCasePath;
1782 
1783  if (UPstream::master())
1784  {
1785  newCasePath = roots[0]/globalCase_;
1786  OPBstream::send(newCasePath); // worldComm
1787  }
1788  else
1789  {
1790  IPBstream::recv(newCasePath); // worldComm
1791  options_.set("case", newCasePath);
1792  }
1793  }
1794  else if
1795  (
1796  distributedType == distributedCodes::DISTRIBUTED_MULTIPLE_ROOTS
1797  )
1798  {
1799  // Different roots for each sub-rank
1800  // - use point-to-point communication to transmit values
1801 
1802  fileName newCasePath;
1803 
1804  if (UPstream::master())
1805  {
1806  for (const int subproci : UPstream::subProcs())
1807  {
1808  newCasePath = roots[subproci-1]/globalCase_;
1809  OPstream::send(newCasePath, subproci); // worldComm
1810  }
1811  }
1812  else
1813  {
1814  IPstream::recv(newCasePath, UPstream::masterNo()); // worldComm
1815  options_.set("case", newCasePath);
1816  }
1817  }
1818 
1819 
1820  // Establish rootPath_/globalCase_/case_ for sub-process
1821  if (!UPstream::master())
1822  {
1823  setCasePaths();
1824  }
1825 
1826 
1827  nProcs = UPstream::nProcs();
1828  if (UPstream::nProcs() > 1)
1829  {
1830  case_ =
1831  (
1832  globalCase_
1833  / ("processor" + Foam::name(UPstream::myProcNo()))
1834  );
1835  }
1836  else
1837  {
1838  case_ = globalCase_;
1839  }
1840  }
1841  else
1842  {
1843  // Establish rootPath_/globalCase_/case_
1844  setCasePaths();
1845  case_ = globalCase_; // Redundant, but extra safety?
1846  }
1847 
1848 
1849  // If needed, adjust fileHandler for distributed roots
1850  if (runControl_.distributed() && fileOperation::fileHandlerPtr_)
1851  {
1852  fileOperation::fileHandlerPtr_->distributed(true);
1853 
1854  const labelList& ranks = fileHandler().ioRanks();
1855 
1856  if (runControl_.parRun() && ranks.size())
1857  {
1858  // Detect processor directories both on local proc and on
1859  // (world) master proc. If the local proc doesn't have them
1860  // but the master has it will attempt to copy them.
1861 
1862  // Expected local directory name
1863  const fileName procDir
1864  (
1865  rootPath_
1866  / globalCase_
1867  / ("processor" + Foam::name(UPstream::myProcNo()))
1868  );
1869 
1870  // Try and find my local directory using the fileHandler. This
1871  // will check the local disk on the IO rank
1872  // (since running distributed)
1873  fileNameList pathDirs(UPstream::nProcs());
1874  auto& pathDir = pathDirs[UPstream::myProcNo()];
1875  pathDir = fileHandler().filePath(procDir, false);
1876 
1877  if (returnReduceOr(pathDir.empty()))
1878  {
1879  // There is at least one processor that cannot find
1880  // the processor directory. Look for it on the master.
1881  // E.g. decomposed into 4 processors, two roots:
1882  // processors4_0-1/
1883  // processors4_2-3/
1884  // So:
1885  // - processor0 reads the same disk as processor0
1886  // - processor2 needs the whole directory sent over
1887  // - processor3 reads the same disk as processor2
1888  if (UPstream::master() && bannerEnabled())
1889  {
1890  Info<< "I/O :"
1891  << " distributed - copying missing directories"
1892  << nl;
1893  }
1894 
1895  // Collect all wanted directories (or empty). Note: could
1896  // just collect missing ones ...
1897 
1898  Pstream::gatherList(pathDirs);
1899  fileName masterRootPath(rootPath_);
1900  Pstream::broadcast(masterRootPath);
1901 
1902  List<fileNameList> rankToDirs(UPstream::nProcs());
1903  if (UPstream::master())
1904  {
1905  const bool oldParRun = UPstream::parRun(false);
1906  // Note: non-parallel running might update
1907  // fileOperation::nProcs() so store & restore below
1908  const label nOldProcs = fileHandler().nProcs();
1909 
1910  label rank = 0;
1911  for (label proci = 1; proci < pathDirs.size(); ++proci)
1912  {
1913  if (ranks.contains(proci))
1914  {
1915  rank = proci;
1916  }
1917 
1918  if (pathDirs[proci].empty())
1919  {
1920  // Synthesise corresponding name on the master
1921  // processor
1922  const fileName procDir
1923  (
1924  rootPath_
1925  / globalCase_
1926  / ("processor" + Foam::name(proci))
1927  );
1928  const fileName foundDir
1929  (
1930  fileHandler().filePath(procDir, false)
1931  );
1932 
1933  if
1934  (
1935  !foundDir.empty()
1936  && !rankToDirs[rank].contains(foundDir)
1937  )
1938  {
1939  rankToDirs[rank].push_back(foundDir);
1940  }
1941  }
1942  }
1943 
1944  UPstream::parRun(oldParRun);
1945  const_cast<fileOperation&>(fileHandler()).nProcs(nOldProcs);
1946  }
1947  Pstream::broadcast(rankToDirs);
1948 
1949  // Copy missing directories on all the IOranks.
1950  // Note: instead of passing 'writeOnProc' flag we could create
1951  // communicator just between master and IOrank, but that is
1952  // also expensive.
1953 
1954  forAll(rankToDirs, proci)
1955  {
1956  // Am I the reponsible IOrank for this processor
1957  const bool amIO = (UPstream::myProcNo() == proci);
1958 
1959  // Construct equivalent directory on proci
1960  for (const auto& srcDir : rankToDirs[proci])
1961  {
1962  const fileName tgtDir
1963  (
1964  rootPath_
1965  / srcDir.relative(masterRootPath)
1966  );
1967 
1968  if (amIO)
1969  {
1970  // I am the IO rank
1971  Pout<< "On rank " << proci << nl
1972  << " copying : " << srcDir << nl
1973  << " to : " << tgtDir << endl;
1974  }
1975 
1976  fileHandler().broadcastCopy
1977  (
1979  amIO,
1980  tgtDir,
1981  tgtDir
1982  );
1983  }
1984  }
1985  }
1986  }
1987  }
1988 
1989 
1990  // Keep/discard sub-process host/root information for reporting:
1991  if (UPstream::master() && runControl_.parRun())
1992  {
1993  if (!writeHostsSwitch)
1994  {
1995  // Clear here to ensures it doesn't show in the jobInfo
1996  hostProcs.clear();
1997  }
1998  if (!writeRootsSwitch)
1999  {
2000  roots.clear();
2001  }
2002  }
2003 
2004  if (UPstream::master() && bannerEnabled())
2005  {
2006  Info<< "Case : " << (rootPath_/globalCase_).c_str() << nl
2007  << "nProcs : " << nProcs << nl;
2008 
2009  if (runControl_.parRun())
2010  {
2011  if (hostProcs.size())
2012  {
2013  if (writeHostsSwitch == 1)
2014  {
2015  // Compact output (see etc/controlDict)
2016  printHostsSubscription(hostProcs);
2017  }
2018  else if (writeHostsSwitch)
2019  {
2020  // Full output of "host.pid"
2021  Info<< "Hosts :\n(" << nl;
2022 
2023  // Include master in the list
2024  Info<< " " << Foam::hostName().c_str() << '.'
2025  << Foam::pid() << nl;
2026 
2027  // Sub-processes
2028  for (const auto& str : hostProcs)
2029  {
2030  Info<< " " << str.c_str() << nl;
2031  }
2032  Info<< ')' << nl;
2033  }
2034  }
2035  if (roots.size())
2036  {
2037  bool hasPrinted = false;
2038  if (writeRootsSwitch == 1)
2039  {
2040  // Compact output
2041  hasPrinted = printRootsSubscription(hostProcs, roots);
2042  }
2043  if (writeRootsSwitch && !hasPrinted)
2044  {
2045  // Full output
2046  Info<< "Roots : " << roots << nl;
2047  }
2048  }
2049  Info<< "Pstream initialized with:" << nl
2050  << " floatTransfer : "
2052  << " maxCommsSize : "
2054  << " nProcsSimpleSum : "
2056  << " nonBlockingExchange: "
2058  << " (tuning: " << UPstream::tuning_NBX_ << ')' << nl
2059  << " exchange algorithm : "
2061  << " commsType : "
2063  << " polling iterations : "
2065 
2066  if (UPstream::allWorlds().size() > 1)
2067  {
2068  Info<< " worlds : "
2070  << " world : " << UPstream::myWorld()
2071  << nl;
2072  }
2073  }
2074  }
2075 
2076  if (initialise)
2077  {
2078  jobInfo.add("root", rootPath_);
2079  jobInfo.add("case", globalCase_);
2080  jobInfo.add("nProcs", nProcs);
2081  if (hostProcs.size())
2082  {
2083  jobInfo.add("hosts", hostProcs);
2084  }
2085  if (roots.size())
2086  {
2087  jobInfo.add("roots", roots);
2088  }
2089  jobInfo.write();
2090 
2091  // Switch on signal trapping. We have to wait until after Pstream::init
2092  // since this sets up its own ones.
2093  sigFpe::set(bannerEnabled());
2094  sigInt::set(bannerEnabled());
2095  sigQuit::set(bannerEnabled());
2096  sigSegv::set(bannerEnabled());
2097 
2098  if (UPstream::master() && bannerEnabled())
2099  {
2100  Info<< "fileModificationChecking : "
2101  << "Monitoring run-time modified files using "
2103  [
2105  ];
2106  if
2107  (
2110  )
2111  {
2113  {
2114  Info<< " (fileModificationSkew "
2116  << ")";
2117  }
2119  {
2120  Info<< " (fileModificationSkew "
2122  << ", maxFileModificationPolls "
2124  << ")";
2125  }
2126  else
2127  {
2129  << "Invalid setting for maxFileModificationPolls "
2131  << exit(FatalError);
2132  }
2133  }
2134  Info<< nl;
2135 
2136  Info<< "allowSystemOperations : ";
2138  {
2139  Info<< "Allowing";
2140  }
2141  else
2142  {
2143  Info<< "Disallowing";
2144  }
2145  Info<< " user-supplied system call operations" << nl
2146  << nl;
2148  }
2149  }
2150 }
2151 
2152 
2153 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
2154 
2156 {
2157  jobInfo.stop(); // Normal job termination
2158 
2159  // Delete file handler to flush any remaining IO
2160  (void) fileOperation::fileHandler(nullptr);
2161 }
2162 
2163 
2164 // * * * * * * * * * * * * * * * Capabilities * * * * * * * * * * * * * * * //
2165 
2167 {
2168  if (validOptions.contains("withFunctionObjects"))
2169  {
2170  // '-withFunctionObjects' is available and explicitly enabled
2171  return options_.contains("withFunctionObjects");
2172  }
2173  else if (validOptions.contains("noFunctionObjects"))
2174  {
2175  // '-noFunctionObjects' is available and not explicitly disabled
2176  return !options_.contains("noFunctionObjects");
2177  }
2178 
2179  // Disallow functions if there is no way to enable/disable them
2180  return false;
2181 }
2182 
2183 
2184 bool Foam::argList::allowLibs() const
2186  return !options_.contains("no-libs");
2187 }
2188 
2189 
2190 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2191 
2192 Foam::label Foam::argList::count(const UList<word>& optionNames) const
2193 {
2194  label num = 0;
2195  for (const word& optName : optionNames)
2196  {
2197  if (options_.contains(optName))
2198  {
2199  ++num;
2200  }
2201  }
2202  return num;
2203 }
2204 
2205 
2206 Foam::label Foam::argList::count(std::initializer_list<word> optionNames) const
2207 {
2208  label num = 0;
2209  for (const word& optName : optionNames)
2210  {
2211  if (options_.contains(optName))
2212  {
2213  ++num;
2214  }
2215  }
2216  return num;
2217 }
2218 
2219 
2220 bool Foam::argList::setOption(const word& optName, const string& param)
2221 {
2222  // Some options are always protected
2223  if
2224  (
2225  optName == "case"
2226  || optName == "parallel"
2227  || optName == "roots"
2228  )
2229  {
2231  <<"Option: '" << optName << "' is protected" << nl
2232  << exit(FatalError);
2233  return false;
2234  }
2235 
2236  const auto optIter = options_.cfind(optName);
2237 
2238  if (!optIter.good() || (optIter.val() != param))
2239  {
2240  options_.set(optName, param);
2241  return true;
2242  }
2243 
2244  return false;
2245 }
2246 
2247 
2248 bool Foam::argList::unsetOption(const word& optName)
2249 {
2250  // Some options are always protected
2251  if
2252  (
2253  optName == "case"
2254  || optName == "parallel"
2255  || optName == "roots"
2256  )
2257  {
2259  <<"Option: '" << optName << "' is protected" << nl
2260  << exit(FatalError);
2261  return false;
2262  }
2263 
2264  // Remove the option, return true if state changed
2265  return options_.erase(optName);
2266 }
2267 
2268 
2269 void Foam::argList::displayDoc(bool source) const
2270 {
2271  const dictionary& docDict = debug::controlDict().subDict("Documentation");
2272  fileNameList docDirs(docDict.get<fileNameList>("doxyDocDirs"));
2273  fileName docExt(docDict.get<fileName>("doxySourceFileExt"));
2274 
2275  // For source code: change xxx_8C.html to xxx_8C_source.html
2276  if (source)
2277  {
2278  docExt.replace(".", "_source.");
2279  }
2280 
2281  fileName url;
2282 
2283  for (const fileName& dir : docDirs)
2284  {
2285  // The http protocols are last in the list
2286  if (dir.starts_with("http:") || dir.starts_with("https:"))
2287  {
2288  url = dir/executable_ + docExt;
2289  break;
2290  }
2291 
2292  fileName docFile = stringOps::expand(dir/executable_ + docExt);
2293 
2294  if
2295  (
2296  docFile.starts_with("file://")
2297  ? isFile(docFile.substr(7)) // check part after "file://"
2298  : isFile(docFile)
2299  )
2300  {
2301  url = std::move(docFile);
2302  break;
2303  }
2304  }
2305 
2306  if (url.empty())
2307  {
2308  Info<< nl
2309  << "No documentation found for " << executable_
2310  << ", but you can use -help to display the usage\n" << endl;
2311 
2312  return;
2313  }
2314 
2315  string docBrowser = getEnv("FOAM_DOC_BROWSER");
2316  if (docBrowser.empty())
2317  {
2318  docDict.readEntry("docBrowser", docBrowser);
2319  }
2320 
2321  // Can use FOAM_DOC_BROWSER='application file://%f' if required
2322  if (docBrowser.contains("%f"))
2323  {
2324  docBrowser.replace("%f", url);
2325  }
2326  else
2327  {
2328  docBrowser += " " + url;
2329  }
2330 
2331  // Split on whitespace to use safer version of Foam::system()
2332 
2333  CStringList command(stringOps::splitSpace(docBrowser));
2334 
2335  Info
2336  << "OpenFOAM " << foamVersion::api << " documentation:" << nl
2337  << " " << command << nl << endl;
2338 
2339  Foam::system(command, true);
2340 }
2341 
2342 
2343 bool Foam::argList::check(bool checkArgs, bool checkOpts) const
2344 {
2345  bool ok = true;
2346 
2347  if (UPstream::master())
2348  {
2349  const label nargs = args_.size()-1;
2350  if (checkArgs && nargs != validArgs.size())
2351  {
2352  FatalError
2353  << "Expected " << validArgs.size()
2354  << " arguments but found " << nargs << endl;
2355  ok = false;
2356  }
2357 
2358  if (checkOpts)
2359  {
2360  forAllConstIters(options_, iter)
2361  {
2362  const word& optName = iter.key();
2363  if
2364  (
2365  !validOptions.contains(optName)
2366  && !validParOptions.contains(optName)
2367  )
2368  {
2369  FatalError
2370  << "Invalid option: -" << optName << endl;
2371  ok = false;
2372  }
2373  }
2374  }
2375 
2376  if (!ok)
2377  {
2378  FatalError
2379  << nl
2380  << "See '" << executable_ << " -help' for usage" << nl
2381  << " or '" << executable_
2382  << " -help-full' for extended usage" << nl
2383  << nl;
2384  }
2385  }
2386 
2387  return ok;
2388 }
2389 
2390 
2391 bool Foam::argList::checkRootCase() const
2392 {
2393  if (!fileHandler().isDir(rootPath()))
2394  {
2395  FatalError
2396  << executable_
2397  << ": cannot open root directory " << rootPath()
2398  << endl;
2399 
2400  return false;
2401  }
2402 
2403  const fileName pathDir(fileHandler().filePath(path(), false));
2404 
2405  if (checkProcessorDirectories_ && pathDir.empty() && UPstream::master())
2406  {
2407  // Allow non-existent processor directories on sub-processes,
2408  // to be created later (e.g. redistributePar)
2409  FatalError
2410  << executable_
2411  << ": cannot open case directory " << path()
2412  << endl;
2413 
2414  return false;
2415  }
2416 
2417  return true;
2418 }
2419 
2420 
2421 // ************************************************************************* //
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:376
static const word & myWorld()
My world.
Definition: UPstream.H:1177
bool checkRootCase() const
Check root path and case path.
Definition: argList.C:2384
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:89
static void setAdvanced(const word &optName, bool advanced=true)
Set an existing option as being &#39;advanced&#39; or normal.
Definition: argList.C:404
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:2241
static float fileModificationSkew
Time skew (seconds) for file modification checks.
Definition: IOobject.H:356
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:608
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 int maxCommsSize
Optional maximum message size (bytes)
Definition: UPstream.H:402
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:381
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 void gatherList(const UList< commsStruct > &comms, UList< T > &values, const int tag, const label comm)
Gather data, but keep individual values separate. Uses the specified communication schedule...
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
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:1086
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:421
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:2148
static int tuning_NBX_
Tuning parameters for non-blocking exchange (NBX)
Definition: UPstream.H:407
bool allowFunctionObjects() const
The controlDict &#39;functions&#39; entry is allowed to be used.
Definition: argList.C:2159
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:1180
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:387
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:2177
void displayDoc(bool source=false) const
Display documentation in browser.
Definition: argList.C:2262
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
static void send(const Type &value, const label comm=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Serialize a value and broadcast (root == UPstream::masterNo()). Uses operator<< for serialization...
Definition: OPstream.H:182
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:1077
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
Definition: IPstream.H:81
static int nPollProcInterfaces
Number of polling cycles in processor updates.
Definition: UPstream.H:392
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 standard) : (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 labelList matching(const wordRe &select, const UList< StringType > &input, const bool invert=false)
Determine the list indices for all matches.
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:1071
static int allowSystemOperations
Flag if system operations are allowed.
Definition: dynamicCode.H:193
bool push_back(const fileName &libName)
Add to the list of names, but do not yet open.
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:371
static int maxFileModificationPolls
Max number of times to poll for file modification changes.
Definition: IOobject.H:361
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:67
#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...
static void recv(Type &value, const label comm=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive (from broadcast, root == UPstream::masterNo()) and deserialize a value. Uses operator>> for d...
Definition: IPstream.H:164
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:211
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:351
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
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:397
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:2213
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:1094
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.
Foam::SubStrings< StringType > splitSpace(const StringType &str, std::string::size_type pos=0)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
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:1197
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:1153
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
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Definition: OPstreams.C:84
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:600
label count(const UList< word > &optionNames) const
Return how many of the specified options were used.
Definition: argList.C:2185
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:2336
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.