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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "argList.H"
27 #include "OSspecific.H"
28 #include "clock.H"
29 #include "IFstream.H"
30 #include "dictionary.H"
31 #include "IOobject.H"
32 #include "JobInfo.H"
33 #include "labelList.H"
34 #include "regIOobject.H"
35 #include "dynamicCode.H"
36 #include "sigFpe.H"
37 #include "sigInt.H"
38 #include "sigQuit.H"
39 #include "sigSegv.H"
40 
41 #include <cctype>
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
53 
54 
55 Foam::argList::initValidTables::initValidTables()
56 {
57  argList::addOption
58  (
59  "case", "dir",
60  "specify alternate case directory, default is the cwd"
61  );
62  argList::addBoolOption("parallel", "run in parallel");
63  validParOptions.set("parallel", "");
64  argList::addOption
65  (
66  "roots", "(dir1 .. dirN)",
67  "slave root directories for distributed running"
68  );
69  validParOptions.set("roots", "(dir1 .. dirN)");
70 
71  argList::addOption
72  (
73  "decomposeParDict", "file",
74  "read decomposePar dictionary from specified location"
75  );
76  validParOptions.set
77  (
78  "decomposeParDict",
79  "file"
80  );
81 
82  argList::addBoolOption
83  (
84  "noFunctionObjects",
85  "do not execute functionObjects"
86  );
87 
88  Pstream::addValidParOptions(validParOptions);
89 }
90 
91 
92 Foam::argList::initValidTables dummyInitValidTables;
93 
94 
95 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
96 
98 (
99  const word& opt,
100  const string& usage
101 )
102 {
103  addOption(opt, "", usage);
104 }
105 
106 
108 (
109  const word& opt,
110  const string& param,
111  const string& usage
112 )
113 {
114  validOptions.set(opt, param);
115  if (!usage.empty())
116  {
117  optionUsage.set(opt, usage);
118  }
119 }
120 
121 
123 (
124  const word& opt,
125  const string& usage
126 )
127 {
128  if (usage.empty())
129  {
130  optionUsage.erase(opt);
131  }
132  else
133  {
134  optionUsage.set(opt, usage);
135  }
136 }
137 
138 
139 void Foam::argList::addNote(const string& note)
140 {
141  if (!note.empty())
142  {
143  notes.append(note);
144  }
145 }
146 
147 
149 {
150  validOptions.erase(opt);
151  optionUsage.erase(opt);
152 }
153 
154 
156 {
157  bannerEnabled = false;
158 }
159 
160 
162 {
163  removeOption("parallel");
164  removeOption("roots");
165  removeOption("decomposeParDict");
166  validParOptions.clear();
167 }
168 
169 
171 (
172  const label location,
173  const string& str
174 )
175 {
176  const string::size_type textWidth = usageMax - usageMin;
177  const string::size_type strLen = str.size();
178 
179  if (strLen)
180  {
181  // minimum of 2 spaces between option and usage:
182  if (string::size_type(location) + 2 <= usageMin)
183  {
184  for (string::size_type i = location; i < usageMin; ++i)
185  {
186  Info<<' ';
187  }
188  }
189  else
190  {
191  // or start a new line
192  Info<< nl;
193  for (string::size_type i = 0; i < usageMin; ++i)
194  {
195  Info<<' ';
196  }
197  }
198 
199  // text wrap
201  while (pos != string::npos && pos + textWidth < strLen)
202  {
203  // potential end point and next point
204  string::size_type curr = pos + textWidth - 1;
205  string::size_type next = string::npos;
206 
207  if (isspace(str[curr]))
208  {
209  // we were lucky: ended on a space
210  next = str.find_first_not_of(" \t\n", curr);
211  }
212  else if (isspace(str[curr+1]))
213  {
214  // the next one is a space - so we are okay
215  curr++; // otherwise the length is wrong
216  next = str.find_first_not_of(" \t\n", curr);
217  }
218  else
219  {
220  // search for end of a previous word break
221  string::size_type prev = str.find_last_of(" \t\n", curr);
222 
223  // reposition to the end of previous word if possible
224  if (prev != string::npos && prev > pos)
225  {
226  curr = prev;
227  }
228  }
229 
230  if (next == string::npos)
231  {
232  next = curr + 1;
233  }
234 
235  // indent following lines (not the first one)
236  if (pos)
237  {
238  for (string::size_type i = 0; i < usageMin; ++i)
239  {
240  Info<<' ';
241  }
242  }
243 
244  Info<< str.substr(pos, (curr - pos)).c_str() << nl;
245  pos = next;
246  }
247 
248  // output the remainder of the string
249  if (pos != string::npos)
250  {
251  // indent following lines (not the first one)
252  if (pos)
253  {
254  for (string::size_type i = 0; i < usageMin; ++i)
255  {
256  Info<<' ';
257  }
258  }
259 
260  Info<< str.substr(pos).c_str() << nl;
261  }
262  }
263  else
264  {
265  Info<< nl;
266  }
267 }
268 
269 
270 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
271 
272 // convert argv -> args_
273 // transform sequences with "(" ... ")" into string lists in the process
274 bool Foam::argList::regroupArgv(int& argc, char**& argv)
275 {
276  int nArgs = 0;
277  int listDepth = 0;
278  string tmpString;
279 
280  // note: we also re-write directly into args_
281  // and use a second pass to sort out args/options
282  for (int argI = 0; argI < argc; ++argI)
283  {
284  if (strcmp(argv[argI], "(") == 0)
285  {
286  ++listDepth;
287  tmpString += "(";
288  }
289  else if (strcmp(argv[argI], ")") == 0)
290  {
291  if (listDepth)
292  {
293  --listDepth;
294  tmpString += ")";
295  if (listDepth == 0)
296  {
297  args_[nArgs++] = tmpString;
298  tmpString.clear();
299  }
300  }
301  else
302  {
303  args_[nArgs++] = argv[argI];
304  }
305  }
306  else if (listDepth)
307  {
308  // quote each string element
309  tmpString += "\"";
310  tmpString += argv[argI];
311  tmpString += "\"";
312  }
313  else
314  {
315  args_[nArgs++] = argv[argI];
316  }
317  }
318 
319  if (tmpString.size())
320  {
321  args_[nArgs++] = tmpString;
322  }
323 
324  args_.setSize(nArgs);
325 
326  return nArgs < argc;
327 }
328 
329 
331 {
332  fileName casePath;
333 
334  // [-case dir] specified
335  HashTable<string>::const_iterator iter = options_.find("case");
336 
337  if (iter != options_.end())
338  {
339  casePath = toUnixPath(iter());
340  casePath.clean();
341 
342  if (casePath.empty() || casePath == ".")
343  {
344  // handle degenerate form and '-case .' like no -case specified
345  casePath = cwd();
346  options_.erase("case");
347  }
348  else if (!casePath.isAbsolute() && casePath.name() == "..")
349  {
350  // avoid relative cases ending in '..' - makes for very ugly names
351  casePath = cwd()/casePath;
352  casePath.clean();
353  }
354  }
355  else
356  {
357  // nothing specified, use the current dir
358  casePath = cwd();
359  }
360 
361  rootPath_ = casePath.path();
362  globalCase_ = casePath.name();
363  case_ = globalCase_;
364 
365 
366  // Set the case and case-name as an environment variable
367  if (rootPath_.isAbsolute())
368  {
369  // absolute path - use as-is
370  setEnv("FOAM_CASE", rootPath_/globalCase_, true);
371  setEnv("FOAM_CASENAME", globalCase_, true);
372  }
373  else
374  {
375  // qualify relative path
376  casePath = cwd()/rootPath_/globalCase_;
377  casePath.clean();
378 
379  setEnv("FOAM_CASE", casePath, true);
380  setEnv("FOAM_CASENAME", casePath.name(), true);
381  }
382 }
383 
384 
385 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
386 
388 (
389  int& argc,
390  char**& argv,
391  bool checkArgs,
392  bool checkOpts,
393  const bool initialise
394 )
395 :
396  args_(argc),
397  options_(argc)
398 {
399  // Check if this run is a parallel run by searching for any parallel option
400  // If found call runPar which might filter argv
401  for (int argI = 0; argI < argc; ++argI)
402  {
403  if (argv[argI][0] == '-')
404  {
405  const char *optionName = &argv[argI][1];
406 
407  if (validParOptions.found(optionName))
408  {
409  parRunControl_.runPar(argc, argv);
410  break;
411  }
412  }
413  }
414 
415  // convert argv -> args_ and capture ( ... ) lists
416  // for normal arguments and for options
417  regroupArgv(argc, argv);
418 
419  // Get executable name
420  args_[0] = fileName(argv[0]);
421  executable_ = fileName(argv[0]).name();
422 
423  // Check arguments and options, we already have argv[0]
424  int nArgs = 1;
425  argListStr_ = args_[0];
426 
427  for (int argI = 1; argI < args_.size(); ++argI)
428  {
429  argListStr_ += ' ';
430  argListStr_ += args_[argI];
431 
432  if (args_[argI][0] == '-')
433  {
434  const char *optionName = &args_[argI][1];
435 
436  if
437  (
438  (
439  validOptions.found(optionName)
440  && !validOptions[optionName].empty()
441  )
442  || (
443  validParOptions.found(optionName)
444  && !validParOptions[optionName].empty()
445  )
446  )
447  {
448  ++argI;
449  if (argI >= args_.size())
450  {
451  FatalError
452  <<"Option '-" << optionName
453  << "' requires an argument" << endl;
454  printUsage();
455  FatalError.exit();
456  }
457 
458  argListStr_ += ' ';
459  argListStr_ += args_[argI];
460  options_.insert(optionName, args_[argI]);
461  }
462  else
463  {
464  options_.insert(optionName, "");
465  }
466  }
467  else
468  {
469  if (nArgs != argI)
470  {
471  args_[nArgs] = args_[argI];
472  }
473  ++nArgs;
474  }
475  }
476 
477  args_.setSize(nArgs);
478 
479  parse(checkArgs, checkOpts, initialise);
480 }
481 
482 
484 (
485  const argList& args,
486  const HashTable<string>& options,
487  bool checkArgs,
488  bool checkOpts,
489  bool initialise
490 )
491 :
492  parRunControl_(args.parRunControl_),
493  args_(args.args_),
494  options_(options),
495  executable_(args.executable_),
496  rootPath_(args.rootPath_),
497  globalCase_(args.globalCase_),
498  case_(args.case_),
499  argListStr_(args.argListStr_)
500 {
501  parse(checkArgs, checkOpts, initialise);
502 }
503 
504 
506 (
507  bool checkArgs,
508  bool checkOpts,
509  bool initialise
510 )
511 {
512  // Help/documentation options:
513  // -help print the usage
514  // -doc display application documentation in browser
515  // -srcDoc display source code in browser
516  if
517  (
518  options_.found("help")
519  || options_.found("doc")
520  || options_.found("srcDoc")
521  )
522  {
523  if (options_.found("help"))
524  {
525  printUsage();
526  }
527 
528  // only display one or the other
529  if (options_.found("srcDoc"))
530  {
531  displayDoc(true);
532  }
533  else if (options_.found("doc"))
534  {
535  displayDoc(false);
536  }
537 
538  ::exit(0);
539  }
540 
541  // Print the usage message and exit if the number of arguments is incorrect
542  if (!check(checkArgs, checkOpts))
543  {
544  FatalError.exit();
545  }
546 
547 
548  if (initialise)
549  {
550  string dateString = clock::date();
551  string timeString = clock::clockTime();
552 
553  // Print the banner once only for parallel runs
554  if (Pstream::master() && bannerEnabled)
555  {
557  << "Build : " << Foam::FOAMbuild << nl
558  << "Exec : " << argListStr_.c_str() << nl
559  << "Date : " << dateString.c_str() << nl
560  << "Time : " << timeString.c_str() << nl
561  << "Host : " << hostName() << nl
562  << "PID : " << pid() << endl;
563  }
564 
565  jobInfo.add("startDate", dateString);
566  jobInfo.add("startTime", timeString);
567  jobInfo.add("userName", userName());
568  jobInfo.add("foamVersion", word(FOAMversion));
569  jobInfo.add("code", executable_);
570  jobInfo.add("argList", argListStr_);
571  jobInfo.add("currentDir", cwd());
572  jobInfo.add("PPID", ppid());
573  jobInfo.add("PGID", pgid());
574 
575  // add build information - only use the first word
576  {
577  std::string build(Foam::FOAMbuild);
578  std::string::size_type found = build.find(' ');
579  if (found != std::string::npos)
580  {
581  build.resize(found);
582  }
583  jobInfo.add("foamBuild", build);
584  }
585  }
586 
587  // Case is a single processor run unless it is running parallel
588  int nProcs = 1;
589 
590  // Roots if running distributed
591  fileNameList roots;
592 
593 
594  // If this actually is a parallel run
595  if (parRunControl_.parRun())
596  {
597  // For the master
598  if (Pstream::master())
599  {
600  // establish rootPath_/globalCase_/case_ for master
601  getRootCase();
602 
603  // See if running distributed (different roots for different procs)
604  label dictNProcs = -1;
605  fileName source;
606 
607  if (options_.found("roots"))
608  {
609  source = "-roots";
610  IStringStream is(options_["roots"]);
611  roots = readList<fileName>(is);
612 
613  if (roots.size() != 1)
614  {
615  dictNProcs = roots.size()+1;
616  }
617  }
618  else
619  {
620  source = rootPath_/globalCase_/"system"/"decomposeParDict";
621  // Override with -decomposeParDict
622  if (options_.found("decomposeParDict"))
623  {
624  source = options_["decomposeParDict"];
625  if (isDir(source))
626  {
627  source = source/"decomposeParDict";
628  }
629  }
630 
631  IFstream decompDictStream(source);
632 
633  if (!decompDictStream.good())
634  {
635  FatalError
636  << "Cannot read decomposeParDict from "
637  << decompDictStream.name()
638  << exit(FatalError);
639  }
640 
641  dictionary decompDict(decompDictStream);
642 
643  dictNProcs = readLabel
644  (
645  decompDict.lookup("numberOfSubdomains")
646  );
647 
648  if (decompDict.lookupOrDefault("distributed", false))
649  {
650  decompDict.lookup("roots") >> roots;
651  }
652  }
653 
654  // convenience:
655  // when a single root is specified, use it for all processes
656  if (roots.size() == 1)
657  {
658  const fileName rootName(roots[0]);
659  roots.setSize(Pstream::nProcs()-1, rootName);
660 
661  // adjust dictNProcs for command-line '-roots' option
662  if (dictNProcs < 0)
663  {
664  dictNProcs = roots.size()+1;
665  }
666  }
667 
668 
669  // Check number of processors.
670  // nProcs => number of actual procs
671  // dictNProcs => number of procs specified in decompositionDict
672  // nProcDirs => number of processor directories
673  // (n/a when running distributed)
674  //
675  // - normal running : nProcs = dictNProcs = nProcDirs
676  // - decomposition to more processors : nProcs = dictNProcs
677  // - decomposition to fewer processors : nProcs = nProcDirs
678  if (dictNProcs > Pstream::nProcs())
679  {
680  FatalError
681  << source
682  << " specifies " << dictNProcs
683  << " processors but job was started with "
684  << Pstream::nProcs() << " processors."
685  << exit(FatalError);
686  }
687 
688 
689  // distributed data
690  if (roots.size())
691  {
692  if (roots.size() != Pstream::nProcs()-1)
693  {
694  FatalError
695  << "number of entries in roots "
696  << roots.size()
697  << " is not equal to the number of slaves "
698  << Pstream::nProcs()-1
699  << exit(FatalError);
700  }
701 
702  forAll(roots, i)
703  {
704  roots[i].expand();
705  }
706 
707  // Distribute the master's argument list (with new root)
708  bool hadCaseOpt = options_.found("case");
709  for
710  (
711  int slave = Pstream::firstSlave();
712  slave <= Pstream::lastSlave();
713  slave++
714  )
715  {
716  options_.set("case", roots[slave-1]/globalCase_);
717 
718  OPstream toSlave(Pstream::scheduled, slave);
719  toSlave << args_ << options_;
720  }
721  options_.erase("case");
722 
723  // restore [-case dir]
724  if (hadCaseOpt)
725  {
726  options_.set("case", rootPath_/globalCase_);
727  }
728  }
729  else
730  {
731  // Possibly going to fewer processors.
732  // Check if all procDirs are there.
733  if (dictNProcs < Pstream::nProcs())
734  {
735  label nProcDirs = 0;
736  while
737  (
738  isDir
739  (
740  rootPath_/globalCase_/"processor"
741  + name(++nProcDirs)
742  )
743  )
744  {}
745 
746  if (nProcDirs != Pstream::nProcs())
747  {
748  FatalError
749  << "number of processor directories = "
750  << nProcDirs
751  << " is not equal to the number of processors = "
752  << Pstream::nProcs()
753  << exit(FatalError);
754  }
755  }
756 
757  // Distribute the master's argument list (unaltered)
758  for
759  (
760  int slave = Pstream::firstSlave();
761  slave <= Pstream::lastSlave();
762  slave++
763  )
764  {
765  OPstream toSlave(Pstream::scheduled, slave);
766  toSlave << args_ << options_;
767  }
768  }
769  }
770  else
771  {
772  // Collect the master's argument list
774  fromMaster >> args_ >> options_;
775 
776  // establish rootPath_/globalCase_/case_ for slave
777  getRootCase();
778  }
779 
780  nProcs = Pstream::nProcs();
781  case_ = globalCase_/(word("processor") + name(Pstream::myProcNo()));
782  }
783  else
784  {
785  // establish rootPath_/globalCase_/case_
786  getRootCase();
787  case_ = globalCase_;
788  }
789 
790 
791  stringList slaveProcs;
792 
793  // collect slave machine/pid
794  if (parRunControl_.parRun())
795  {
796  if (Pstream::master())
797  {
798  slaveProcs.setSize(Pstream::nProcs() - 1);
799  label procI = 0;
800  for
801  (
802  int slave = Pstream::firstSlave();
803  slave <= Pstream::lastSlave();
804  slave++
805  )
806  {
807  IPstream fromSlave(Pstream::scheduled, slave);
808 
809  string slaveBuild;
810  string slaveMachine;
811  label slavePid;
812  fromSlave >> slaveBuild >> slaveMachine >> slavePid;
813 
814  slaveProcs[procI++] = slaveMachine + "." + name(slavePid);
815 
816  // Check build string to make sure all processors are running
817  // the same build
818  if (slaveBuild != Foam::FOAMbuild)
819  {
820  FatalError
821  << "Master is running version " << Foam::FOAMbuild
822  << "; slave " << procI << " is running version "
823  << slaveBuild
824  << exit(FatalError);
825  }
826  }
827  }
828  else
829  {
831  toMaster << string(Foam::FOAMbuild) << hostName() << pid();
832  }
833  }
834 
835 
836  if (Pstream::master() && bannerEnabled)
837  {
838  Info<< "Case : " << (rootPath_/globalCase_).c_str() << nl
839  << "nProcs : " << nProcs << endl;
840 
841  if (parRunControl_.parRun())
842  {
843  Info<< "Slaves : " << slaveProcs << nl;
844  if (roots.size())
845  {
846  Info<< "Roots : " << roots << nl;
847  }
848  Info<< "Pstream initialized with:" << nl
849  << " floatTransfer : " << Pstream::floatTransfer << nl
850  << " nProcsSimpleSum : " << Pstream::nProcsSimpleSum << nl
851  << " commsType : "
853  << " polling iterations : " << Pstream::nPollProcInterfaces
854  << endl;
855  }
856  }
857 
858  if (initialise)
859  {
860  jobInfo.add("root", rootPath_);
861  jobInfo.add("case", globalCase_);
862  jobInfo.add("nProcs", nProcs);
863  if (slaveProcs.size())
864  {
865  jobInfo.add("slaves", slaveProcs);
866  }
867  if (roots.size())
868  {
869  jobInfo.add("roots", roots);
870  }
871  jobInfo.write();
872 
873  // Switch on signal trapping. We have to wait until after Pstream::init
874  // since this sets up its own ones.
875  sigFpe::set(bannerEnabled);
876  sigInt::set(bannerEnabled);
877  sigQuit::set(bannerEnabled);
878  sigSegv::set(bannerEnabled);
879 
880  if (bannerEnabled)
881  {
882  Info<< "fileModificationChecking : "
883  << "Monitoring run-time modified files using "
885  [
887  ]
888  << endl;
889 
890  Info<< "allowSystemOperations : ";
892  {
893  Info<< "Allowing user-supplied system call operations" << endl;
894  }
895  else
896  {
897  Info<< "Disallowing user-supplied system call operations"
898  << endl;
899  }
900  }
901 
902  if (Pstream::master() && bannerEnabled)
903  {
904  Info<< endl;
906  }
907  }
908 }
909 
910 
911 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
912 
914 {
915  jobInfo.end();
916 }
917 
918 
919 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
920 
921 bool Foam::argList::setOption(const word& opt, const string& param)
922 {
923  bool changed = false;
924 
925  // only allow valid options
926  if (validOptions.found(opt))
927  {
928  // some options are to be protected
929  if
930  (
931  opt == "case"
932  || opt == "parallel"
933  || opt == "roots"
934  )
935  {
936  FatalError
937  <<"used argList::setOption on a protected option: '"
938  << opt << "'" << endl;
939  FatalError.exit();
940  }
941 
942  if (validOptions[opt].empty())
943  {
944  // bool option
945  if (!param.empty())
946  {
947  // disallow change of type
948  FatalError
949  <<"used argList::setOption to change bool to non-bool: '"
950  << opt << "'" << endl;
951  FatalError.exit();
952  }
953  else
954  {
955  // did not previously exist
956  changed = !options_.found(opt);
957  }
958  }
959  else
960  {
961  // non-bool option
962  if (param.empty())
963  {
964  // disallow change of type
965  FatalError
966  <<"used argList::setOption to change non-bool to bool: '"
967  << opt << "'" << endl;
968  FatalError.exit();
969  }
970  else
971  {
972  // existing value needs changing, or did not previously exist
973  changed = options_.found(opt) ? options_[opt] != param : true;
974  }
975  }
976  }
977  else
978  {
979  FatalError
980  <<"used argList::setOption on an invalid option: '"
981  << opt << "'" << nl << "allowed are the following:"
982  << validOptions << endl;
983  FatalError.exit();
984  }
985 
986  // set/change the option as required
987  if (changed)
988  {
989  options_.set(opt, param);
990  }
991 
992  return changed;
993 }
994 
995 
997 {
998  // only allow valid options
999  if (validOptions.found(opt))
1000  {
1001  // some options are to be protected
1002  if
1003  (
1004  opt == "case"
1005  || opt == "parallel"
1006  || opt == "roots"
1007  )
1008  {
1009  FatalError
1010  <<"used argList::unsetOption on a protected option: '"
1011  << opt << "'" << endl;
1012  FatalError.exit();
1013  }
1014 
1015  // remove the option, return true if state changed
1016  return options_.erase(opt);
1017  }
1018  else
1019  {
1020  FatalError
1021  <<"used argList::unsetOption on an invalid option: '"
1022  << opt << "'" << nl << "allowed are the following:"
1023  << validOptions << endl;
1024  FatalError.exit();
1025  }
1026 
1027  return false;
1028 }
1029 
1030 
1032 {
1033  // output notes directly - no automatic text wrapping
1034  if (!notes.empty())
1035  {
1036  Info<< nl;
1037  forAllConstIter(SLList<string>, notes, iter)
1038  {
1039  Info<< iter().c_str() << nl;
1040  }
1041  }
1042 }
1043 
1044 
1046 {
1047  Info<< "\nUsage: " << executable_ << " [OPTIONS]";
1048 
1049  forAllConstIter(SLList<string>, validArgs, iter)
1050  {
1051  Info<< " <" << iter().c_str() << '>';
1052  }
1053 
1054  Info<< "\noptions:\n";
1055 
1056  wordList opts = validOptions.sortedToc();
1057  forAll(opts, optI)
1058  {
1059  const word& optionName = opts[optI];
1060 
1061  HashTable<string>::const_iterator iter = validOptions.find(optionName);
1062  Info<< " -" << optionName;
1063  label len = optionName.size() + 3; // length includes leading ' -'
1064 
1065  if (iter().size())
1066  {
1067  // length includes space and between option/param and '<>'
1068  len += iter().size() + 3;
1069  Info<< " <" << iter().c_str() << '>';
1070  }
1071 
1073  optionUsage.find(optionName);
1074 
1075  if (usageIter != optionUsage.end())
1076  {
1077  printOptionUsage
1078  (
1079  len,
1080  usageIter()
1081  );
1082  }
1083  else
1084  {
1085  Info<< nl;
1086  }
1087  }
1088 
1089  //
1090  // place srcDoc/doc/help options at the end
1091  //
1092  Info<< " -srcDoc";
1093  printOptionUsage
1094  (
1095  9,
1096  "display source code in browser"
1097  );
1098 
1099  Info<< " -doc";
1100  printOptionUsage
1101  (
1102  6,
1103  "display application documentation in browser"
1104  );
1105 
1106  Info<< " -help";
1107  printOptionUsage
1108  (
1109  7,
1110  "print the usage"
1111  );
1112 
1113 
1114  printNotes();
1115 
1116  Info<< nl
1117  <<"Using: OpenFOAM-" << Foam::FOAMversion
1118  << " (see www.OpenFOAM.com)" << nl
1119  <<"Build: " << Foam::FOAMbuild << nl
1120  << endl;
1121 }
1122 
1123 
1124 void Foam::argList::displayDoc(bool source) const
1125 {
1126  const dictionary& docDict = debug::controlDict().subDict("Documentation");
1127  List<fileName> docDirs(docDict.lookup("doxyDocDirs"));
1128  List<fileName> docExts(docDict.lookup("doxySourceFileExts"));
1129 
1130  // for source code: change foo_8C.html to foo_8C_source.html
1131  if (source)
1132  {
1133  forAll(docExts, extI)
1134  {
1135  docExts[extI].replace(".", "_source.");
1136  }
1137  }
1138 
1139  fileName docFile;
1140  bool found = false;
1141 
1142  forAll(docDirs, dirI)
1143  {
1144  forAll(docExts, extI)
1145  {
1146  docFile = docDirs[dirI]/executable_ + docExts[extI];
1147  docFile.expand();
1148 
1149  if (isFile(docFile))
1150  {
1151  found = true;
1152  break;
1153  }
1154  }
1155  if (found)
1156  {
1157  break;
1158  }
1159  }
1160 
1161  if (found)
1162  {
1163  string docBrowser = getEnv("FOAM_DOC_BROWSER");
1164  if (docBrowser.empty())
1165  {
1166  docDict.lookup("docBrowser") >> docBrowser;
1167  }
1168  // can use FOAM_DOC_BROWSER='application file://%f' if required
1169  docBrowser.replaceAll("%f", docFile);
1170 
1171  Info<< "Show documentation: " << docBrowser.c_str() << endl;
1172 
1173  system(docBrowser);
1174  }
1175  else
1176  {
1177  Info<< nl
1178  << "No documentation found for " << executable_
1179  << ", but you can use -help to display the usage\n" << endl;
1180  }
1181 }
1182 
1183 
1184 bool Foam::argList::check(bool checkArgs, bool checkOpts) const
1185 {
1186  bool ok = true;
1187 
1188  if (Pstream::master())
1189  {
1190  if (checkArgs && args_.size() - 1 != validArgs.size())
1191  {
1192  FatalError
1193  << "Wrong number of arguments, expected " << validArgs.size()
1194  << " found " << args_.size() - 1 << endl;
1195  ok = false;
1196  }
1197 
1198  if (checkOpts)
1199  {
1200  forAllConstIter(HashTable<string>, options_, iter)
1201  {
1202  if
1203  (
1204  !validOptions.found(iter.key())
1205  && !validParOptions.found(iter.key())
1206  )
1207  {
1208  FatalError
1209  << "Invalid option: -" << iter.key() << endl;
1210  ok = false;
1211  }
1212  }
1213  }
1214 
1215  if (!ok)
1216  {
1217  printUsage();
1218  }
1219  }
1220 
1221  return ok;
1222 }
1223 
1224 
1226 {
1227  if (!isDir(rootPath()))
1228  {
1229  FatalError
1230  << executable_
1231  << ": cannot open root directory " << rootPath()
1232  << endl;
1233 
1234  return false;
1235  }
1236 
1237  if (!isDir(path()) && Pstream::master())
1238  {
1239  // Allow slaves on non-existing processor directories, created later
1240  FatalError
1241  << executable_
1242  << ": cannot open case directory " << path()
1243  << endl;
1244 
1245  return false;
1246  }
1247 
1248  return true;
1249 }
1250 
1251 
1252 // ************************************************************************* //
Foam::argList::validArgs
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:143
Foam::argList::noBanner
static void noBanner()
Disable emitting the banner information.
Definition: argList.C:155
regIOobject.H
Foam::sigFpe::set
static void set(const bool verbose)
Activate SIGFPE signal handler when FOAM_SIGFPE is set.
Definition: sigFpe.C:131
Foam::argList::argListStr_
string argListStr_
Definition: argList.H:113
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::JobInfo::write
bool write(Ostream &) const
Definition: JobInfo.C:101
Foam::IFstream::name
const fileName & name() const
Return the name of the stream.
Definition: IFstream.H:116
Foam::string::replaceAll
string & replaceAll(const string &oldStr, const string &newStr, size_type start=0)
Replace all occurences of sub-string oldStr with newStr.
Definition: string.C:77
Foam::ppid
PID_T ppid()
Return the parent PID of this process.
Definition: POSIX.C:83
Foam::word
A class for handling words, derived from string.
Definition: word.H:59
dummyInitValidTables
Foam::argList::initValidTables dummyInitValidTables
Definition: argList.C:92
Foam::argList::args_
stringList args_
Definition: argList.H:106
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
sigInt.H
Foam::argList::addOption
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:108
Foam::argList::addNote
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:139
Foam::SLList< Foam::string >
Foam::UPstream::scheduled
@ scheduled
Definition: UPstream.H:67
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::regIOobject::fileCheckTypesNames
static const NamedEnum< fileCheckTypes, 4 > fileCheckTypesNames
Definition: regIOobject.H:76
Foam::argList::regroupArgv
bool regroupArgv(int &argc, char **&argv)
Transcribe argv into internal args_.
Definition: argList.C:274
Foam::IFstream
Input from file stream.
Definition: IFstream.H:81
Foam::argList::usageMin
static string::size_type usageMin
Min offset for displaying usage (default: 20)
Definition: argList.H:158
Foam::OPstream
Output inter-processor communications stream.
Definition: OPstream.H:50
Foam::argList::optionUsage
static HashTable< string > optionUsage
Short usage information for validOptions.
Definition: argList.H:152
Foam::argList::executable_
word executable_
Definition: argList.H:109
Foam::UPstream::nProcs
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:387
Foam::HashTable::const_iterator
An STL-conforming const_iterator.
Definition: HashTable.H:470
Foam::dictionary::lookup
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:449
Foam::fileName::path
fileName path() const
Return directory path name (part before last /)
Definition: fileName.C:293
Foam::argList::addBoolOption
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:98
Foam::fileName::isAbsolute
bool isAbsolute() const
Return true if file name is absolute.
Definition: fileName.C:57
Foam::UPstream::commsTypeNames
static const NamedEnum< commsTypes, 3 > commsTypeNames
Definition: UPstream.H:71
Foam::dictionary::lookupOrDefault
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
Definition: dictionaryTemplates.C:33
Foam::argList::bannerEnabled
static bool bannerEnabled
Definition: argList.H:100
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:97
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::setEnv
bool setEnv(const word &name, const std::string &value, const bool overwrite)
Set an environment variable.
Definition: POSIX.C:119
Foam::UPstream::defaultCommsType
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:252
Foam::clock::date
static string date()
Return the current wall-clock date as a string.
Definition: clock.C:77
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:74
sigSegv.H
Foam::sigSegv::set
static void set(const bool verbose)
Activate SIGSEGV signal handler.
Definition: sigSegv.C:78
Foam::argList::rootPath_
fileName rootPath_
Definition: argList.H:110
Foam::clock::clockTime
static string clockTime()
Return the current wall-clock time as a string.
Definition: clock.C:93
Foam::fileName::name
word name() const
Return file name (part beyond last /)
Definition: fileName.C:212
Foam::dynamicCode::allowSystemOperations
static int allowSystemOperations
Flag if system operations are allowed.
Definition: dynamicCode.H:161
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
Foam::argList::addUsage
static void addUsage(const word &opt, const string &usage)
Add option usage information to optionUsage.
Definition: argList.C:123
Foam::argList::validParOptions
static HashTable< string > validParOptions
A list of valid parallel options.
Definition: argList.H:149
Foam::argList::printNotes
void printNotes() const
Print notes (if any)
Definition: argList.C:1031
Foam::toUnixPath
std::string toUnixPath(const std::string &path)
Convert to unix path separators.
Definition: POSIX.C:1351
Foam::argList::parse
void parse(bool checkArgs, bool checkOpts, bool initialise)
Parse.
Definition: argList.C:506
Foam::userName
string userName()
Return the user's login name.
Definition: POSIX.C:169
Foam::pid
PID_T pid()
Return the PID of this process.
Definition: POSIX.C:77
Foam::getEnv
string getEnv(const word &)
Return environment variable of given name.
Definition: POSIX.C:101
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::sigInt::set
static void set(const bool verbose)
Activate SIGINT signal handler.
Definition: sigInt.C:76
labelList.H
Foam::sigQuit::set
static void set(const bool verbose)
Activate SIGQUIT signal handler.
Definition: sigQuit.C:78
Foam::UPstream::lastSlave
static int lastSlave(const label communicator=0)
Process index of last slave.
Definition: UPstream.H:428
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::Info
messageStream Info
clock.H
Foam::UPstream::floatTransfer
static bool floatTransfer
Should compact transfer be used in which floats replace doubles.
Definition: UPstream.H:245
argList.H
Foam::argList::setOption
bool setOption(const word &opt, const string &param="")
Set option directly (use with caution)
Definition: argList.C:921
Foam::argList::getRootCase
void getRootCase()
Get rootPath_ / globalCase_ from one of the following forms.
Definition: argList.C:330
Foam::argList::printUsage
void printUsage() const
Print usage.
Definition: argList.C:1045
dynamicCode.H
size_type
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
Foam::argList::printOptionUsage
static void printOptionUsage(const label location, const string &str)
Helper function for printUsage.
Definition: argList.C:171
Foam::argList::case_
fileName case_
Definition: argList.H:112
Foam::UPstream::masterNo
static int masterNo()
Process index of the master.
Definition: UPstream.H:393
IFstream.H
Foam::pgid
PID_T pgid()
Return the group PID of this process.
Definition: POSIX.C:89
Foam::FOAMbuild
const char *const FOAMbuild
IOobject.H
Foam::argList::validOptions
static HashTable< string > validOptions
A list of valid options.
Definition: argList.H:146
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
Foam::UPstream::firstSlave
static int firstSlave()
Process index of first slave.
Definition: UPstream.H:422
Foam::IStringStream
Input from memory buffer stream.
Definition: IStringStream.H:49
Foam::isFile
bool isFile(const fileName &, const bool checkGzip=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:622
Foam::isDir
bool isDir(const fileName &)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:615
Foam::error::exit
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
Definition: error.C:165
Foam::IOobject::writeDivider
static Stream & writeDivider(Stream &os)
Write the standard file section divider.
Definition: IOobjectI.H:108
Foam::IOobject::writeBanner
static Stream & writeBanner(Stream &os, bool noHint=false)
Write the standard OpenFOAM file/dictionary banner.
Definition: IOobjectI.H:45
Foam::argList::globalCase_
fileName globalCase_
Definition: argList.H:111
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:405
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:399
Foam::UPstream::nProcsSimpleSum
static int nProcsSimpleSum
Number of processors at which the sum algorithm changes from linear.
Definition: UPstream.H:249
Foam::HashTable< Foam::string >
Foam::jobInfo
JobInfo jobInfo
Definition: JobInfo.C:35
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::regIOobject::fileModificationChecking
static fileCheckTypes fileModificationChecking
Definition: regIOobject.H:128
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::argList::unsetOption
bool unsetOption(const word &opt)
Unset option directly (use with caution)
Definition: argList.C:996
Foam::argList::parRunControl_
ParRunControl parRunControl_
Switch on/off parallel mode. Has to be first to be constructed.
Definition: argList.H:104
Foam::JobInfo::end
void end(const word &terminationType)
Definition: JobInfo.C:137
Foam::argList::usageMax
static string::size_type usageMax
Max screen width for displaying usage (default: 80)
Definition: argList.H:161
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
Foam::string::expand
string & expand(const bool allowEmpty=false)
Expand initial tildes and all occurences of environment variables.
Definition: string.C:98
dictionary.H
Foam::hostName
string hostName(const bool full=false)
Return the system's host name, as per hostname(1)
Definition: POSIX.C:129
path
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Foam::argList::notes
static SLList< string > notes
Additional notes for usage.
Definition: argList.H:155
Foam::argList::checkRootCase
bool checkRootCase() const
Check root path and case path.
Definition: argList.C:1225
Foam::readLabel
label readLabel(Istream &is)
Definition: label.H:64
Foam::argList::removeOption
static void removeOption(const word &opt)
Remove option from validOptions and from optionUsage.
Definition: argList.C:148
JobInfo.H
Foam::cwd
fileName cwd()
Return current working directory path name.
Definition: POSIX.C:246
Foam::IPstream
Input inter-processor communications stream.
Definition: IPstream.H:50
Foam::fileName::clean
bool clean()
Cleanup file name.
Definition: fileName.C:97
Foam::debug::controlDict
dictionary & controlDict()
The central control dictionary.
Definition: debug.C:90
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::argList::noParallel
static void noParallel()
Remove the parallel options.
Definition: argList.C:161
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
Foam::dictionary::subDict
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:631
args
Foam::argList args(argc, argv)
Foam::FOAMversion
const char *const FOAMversion
Foam::isspace
bool isspace(char c)
Definition: char.H:53
sigFpe.H
Foam::system
int system(const std::string &command)
Execute the specified command.
Definition: POSIX.C:1155
sigQuit.H
Foam::argList::~argList
virtual ~argList()
Destructor.
Definition: argList.C:913
Foam::argList::check
bool check(bool checkArgs=true, bool checkOpts=true) const
Check argument list.
Definition: argList.C:1184
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Foam::argList::displayDoc
void displayDoc(bool source=false) const
Display documentation in browser.
Definition: argList.C:1124
Foam::dictionary::add
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:729
Foam::UPstream::nPollProcInterfaces
static int nPollProcInterfaces
Number of polling cycles in processor updates.
Definition: UPstream.H:255
Foam::argList::argList
argList(int &argc, char **&argv, bool checkArgs=true, bool checkOpts=true, bool initialise=true)
Construct from argc and argv.
Definition: argList.C:388
Foam::pos
dimensionedScalar pos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:190