MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
mbdyn.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/mbdyn.cc,v 1.156 2017/05/12 17:29:16 morandini Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 /* Portions Copyright 2008 Marco Morandini */
32 
33 /* Driver del programma */
34 
35 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
36 
37 #include <cerrno>
38 #include <fstream>
39 
40 #include "ac/getopt.h"
41 
42 extern "C" {
43 #include <time.h>
44 #ifdef HAVE_SYS_TIMES_H
45 #include <sys/times.h>
46 #endif /* HAVE_SYS_TIMES_H */
47 }
48 
49 #if 0
50 #define _GNU_SOURCE 1
51 #include <fenv.h>
52 static void __attribute__ ((constructor))
53 trapfpe ()
54 {
55  /* Enable some exceptions. At startup all exceptions are masked. */
56 
57  feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW);
58 }
59 #endif
60 
61 #ifdef USE_MPI
62 #include "mbcomm.h"
63 MPI::Intracomm MBDynComm = MPI::COMM_SELF;
64 #ifdef USE_EXTERNAL
65 #include <list>
66 std::list<MPI::Intercomm> InterfaceComms;
67 #include <external.h>
68 #include <vector>
69 
70 #define MB_EXIT(what, err) \
71  do { \
72  if (mbp.using_mpi) { \
73  External::SendClose(); \
74  if ((err) != EXIT_SUCCESS) { \
75  MBDynComm.Abort((err)); \
76  } \
77  MPI::Finalize(); \
78  } \
79  what((err)); \
80  } while (0)
81 
82 #else // !USE_EXTERNAL
83 
84 #define MB_EXIT(what, err) \
85  do { \
86  if (mbp.using_mpi) { \
87  if ((err) != EXIT_SUCCESS) { \
88  MBDynComm.Abort((err)); \
89  } \
90  MPI::Finalize(); \
91  } \
92  what((err)); \
93  } while (0)
94 #endif // !USE_EXTERNAL
95 #else // !USE_MPI
96 
97 #define MB_EXIT(what, err) \
98  what((err))
99 
100 #endif // !USE_MPI
101 
102 #ifdef USE_RTAI
103 #include "mbrtai_utils.h"
104 void *rtmbdyn_rtai_task = NULL;
105 #endif /* USE_RTAI */
106 
107 #include <sys/stat.h>
108 #ifndef PATH_MAX
109 #define PATH_MAX 4096
110 #endif // !PATH_MAX
111 
112 #ifdef HAVE_FENV_H
113 #define _GNU_SOURCE 1
114 #include <fenv.h>
115 #endif // HAVE_FENV_H
116 
117 const char sDefaultOutputFileName[] = "MBDyn";
118 
119 #include "myassert.h"
120 #include "mynewmem.h"
121 #include "except.h"
122 
123 #include "solver.h"
124 #include "invsolver.h"
125 #include "modules.h"
126 #include "legalese.h"
127 
128 #include "cleanup.h"
129 
133 };
134 
140 };
141 
142 struct mbdyn_proc_t {
145  std::ifstream FileStreamIn;
146  std::istream* pIn;
147  std::string sInputFileName;
148  std::string sOutputFileName;
150  bool bRedefine;
151  bool bTable;
156  unsigned int nThreads;
157  bool using_mpi;
158 #ifdef USE_MPI
159  int MyRank;
160  char *ProcessorName;
161  int WorldSize;
162  int parallel_fSilent;
163  int parallel_fPedantic;
164 #ifdef HAVE_GETPID
165  pid_t pid;
166 #else // ! HAVE_GETPID
167  int pid;
168 #endif // ! HAVE_GETPID
169 #endif // USE_MPI
170 };
171 
172 /* Note: DEBUG_* codes are declared in "mbdyn.h" */
173 #ifdef DEBUG
174 const debug_array da[] = {
175  { "input", MYDEBUG_INPUT },
176  { "sol", MYDEBUG_SOL },
177  { "assembly", MYDEBUG_ASSEMBLY },
178  { "derivatives", MYDEBUG_DERIVATIVES },
179  { "fsteps", MYDEBUG_FSTEPS },
180  { "mem", MYDEBUG_MEM },
181  { "fnames", MYDEBUG_FNAMES },
182 #if defined(__GNUC__)
183  { "prettyfn", MYDEBUG_FNAMES|MYDEBUG_PRETTYFN },
184 #endif /* __GNUC__ */
185  { "mpi", MYDEBUG_MPI },
186  { "pred", MYDEBUG_PRED },
187  { "residual", MYDEBUG_RESIDUAL },
188  { "jacobian", MYDEBUG_JAC },
189  { "init", MYDEBUG_INIT },
190  { "output", MYDEBUG_OUTPUT },
191 
192  { NULL, MYDEBUG_NONE }
193 };
194 #endif /* DEBUG */
195 
196 static void
198 {
199  silent_cout(std::endl
200  << "MBDyn - MultiBody Dynamics " << VERSION << std::endl
201  << "configured on " << __DATE__ << " at " << __TIME__
202  << std::endl);
203 }
204 
205 #ifdef HAVE_GETOPT
206 static void
207 mbdyn_usage(const char *sShortOpts)
208 {
209  mbdyn_version();
210  silent_cout(std::endl
211  << "mbdyn is a multibody simulation program." << std::endl
212  << std::endl
213  << "usage: mbdyn [" << sShortOpts << "] [input-file list] " << std::endl
214  << std::endl
215  << " -f, --input-file {file} reads from 'file' instead of stdin" << std::endl
216  << " -o, --output-file {file} writes to '{file}.<ext>'" << std::endl
217  << " instead of '{input-file}.<ext>'" << std::endl
218  << " (or 'Mbdyn.<ext>' when input from stdin)" << std::endl
219  << std::endl);
220 #ifdef DEBUG
221  silent_cout(
222  " -d, --debug {level[:level[...]]} when using the debug version of the code," << std::endl
223  << " enables debug levels; available:" << std::endl
224  << " none" << std::endl);
225  for (int i = 0; da[i].s != NULL; i++) {
226  silent_cout(
227  " " << da[i].s << std::endl);
228  }
229  silent_cout(
230  " any" << std::endl);
231 #endif /* DEBUG */
232  silent_cout(
233  " -e, --exceptions don't trap exceptions to ease debugging" << std::endl
234  << " -E, --fp-mask[=...] enable some floating point checks" << std::endl
235  << " -h, --help prints this message" << std::endl
236  << " -H, --show-table print symbol table and exit" << std::endl
237  << " -l, --license prints the licensing terms" << std::endl
238  /*
239  << " -N, --threads number of threads (need multithread support)" << std::endl
240  */
241  );
242 #ifdef USE_MPI
243  silent_cout(
244  " -p, --parallel required when run in parallel (invoked by mpirun)" << std::endl);
245 #endif /* USE_MPI */
246  silent_cout(
247  " -P, --pedantic pedantic warning messages (more p's: noisier)" << std::endl
248  << " -r, --redefine" << std::endl
249  << " -R, --no-redefine redefine/don't redefine symbols in table" << std::endl
250  << " -s, --silent runs quietly (more s': quieter)" << std::endl
251  << " -S, --sleep [rank={n}] {time} sleep {time} (on process {n}) before" << std::endl
252  << " starting the analysis" << std::endl
253  << " -t, --same-table" << std::endl
254  << " -T, --no-same-table use/don't use same symbol table for multiple runs" << std::endl
255  << " -v, --version show version and exit" << std::endl
256  << " -w, --warranty prints the warranty conditions" << std::endl
257  << " -W, --working-dir {dir} sets the working directory" << std::endl
258  << std::endl
259  << "Usually mbdyn reads the input from stdin and writes messages on stdout; a log" << std::endl
260  << "is put in '{file}.out', and data output is sent to various '{file}.<ext>'" << std::endl
261  << "files ('Mbdyn.<ext>' if input from stdin)" << std::endl
262  << std::endl
263  << std::endl);
264 }
265 
266 static void
267 mbdyn_welcome(void)
268 {
269  mbdyn_version();
270  silent_cout(std::endl
271  << "Copyright 1996-2017 (C) Paolo Mantegazza "
272  "and Pierangelo Masarati," << std::endl
273  << "Dipartimento di Ingegneria Aerospaziale "
274  "<http://www.aero.polimi.it/>" << std::endl
275  << "Politecnico di Milano "
276  "<http://www.polimi.it/>" << std::endl
277  << std::endl
278  << "MBDyn is free software, covered by the"
279  " GNU General Public License," << std::endl
280  << "and you are welcome to change it and/or "
281  "distribute copies of it" << std::endl
282  << "under certain conditions. Use 'mbdyn --license' "
283  "to see the conditions." << std::endl
284  << "There is absolutely no warranty for"
285  " MBDyn. Use \"mbdyn --warranty\"" << std::endl
286  << "for details." << std::endl
287  << std::endl);
288 }
289 
290 /* Dati di getopt */
291 static char sShortOpts[] = "d:eE::f:hHlN:o:pPrRsS:tTvwW:";
292 
293 #ifdef HAVE_GETOPT_LONG
294 static struct option LongOpts[] = {
295  { "debug", required_argument, NULL, int('d') },
296  { "exceptions", no_argument, NULL, int('e') },
297  { "fp-mask", optional_argument, NULL, int('E') },
298  { "input-file", required_argument, NULL, int('f') },
299  { "help", no_argument, NULL, int('h') },
300  { "show-table", no_argument, NULL, int('H') },
301  { "license", no_argument, NULL, int('l') },
302  { "threads", required_argument, NULL, int('N') },
303  { "output-file", required_argument, NULL, int('o') },
304  { "parallel", no_argument, NULL, int('p') },
305  { "pedantic", no_argument, NULL, int('P') },
306  { "redefine", no_argument, NULL, int('r') },
307  { "no-redefine", no_argument, NULL, int('R') },
308  { "silent", no_argument, NULL, int('s') },
309  { "sleep", required_argument, NULL, int('S') },
310  { "same-table", no_argument, NULL, int('t') },
311  { "no-same-table", no_argument, NULL, int('T') },
312  { "version", no_argument, NULL, int('v') },
313  { "warranty", no_argument, NULL, int('w') },
314  { "working-dir", required_argument, NULL, int('W') },
315 
316  { NULL, 0, NULL, 0 }
317 };
318 #endif /* HAVE_GETOPT_LONG */
319 #endif /* HAVE_GETOPT */
320 
321 const std::string sDefaultInputFileName("MBDyn");
322 
323 extern void GetEnviron(MathParser&);
324 
325 static Solver* RunMBDyn(MBDynParser&, const std::string&, const std::string&, unsigned int, bool, bool);
326 
327 #ifdef USE_MPI
328 static int
329 parse_parallel_args(mbdyn_proc_t& mbp, int argc, char *argv[])
330 {
331  for (int i = 1; i < argc; i++) {
332  if (!mbp.using_mpi && strncmp(argv[i], "-p", 2) == 0) {
333  mbp.using_mpi = true;
334  continue;
335  }
336 
337  /* intercept silence/pedantic flags */
338  if (strncmp(argv[i], "-s", 2) == 0) {
339  mbp.parallel_fSilent++;
340 
341  for (unsigned j = 2; argv[i][j] == 's'; j++) {
342  mbp.parallel_fSilent++;
343  }
344 
345  } else if (strncmp(argv[i], "-P", 2) == 0) {
346  mbp.parallel_fPedantic++;
347 
348  for (unsigned j = 2; argv[i][j] == 'P'; j++) {
349  mbp.parallel_fPedantic++;
350  }
351  }
352  }
353 
354  return 0;
355 }
356 #endif /* USE_MPI */
357 
358 
359 void
360 mbdyn_parse_arguments(mbdyn_proc_t& mbp, int argc, char *argv[], int& currarg)
361 {
362 #ifdef HAVE_GETOPT
363  /* Dati acquisibili da linea di comando */
364  int iIndexPtr = 0;
365 
366  mbp.iSleepTime = -1;
367 
368  /* Parsing della linea di comando */
369  opterr = 0;
370  while (true) {
371 #ifdef HAVE_GETOPT_LONG
372  int iCurrOpt = getopt_long(argc, argv, sShortOpts,
373  LongOpts, &iIndexPtr);
374 #else /* !HAVE_GETOPT_LONG */
375  int iCurrOpt = getopt(argc, argv, sShortOpts);
376 #endif /* !HAVE_GETOPT_LONG */
377 
378  if (iCurrOpt == EOF) {
379  break;
380  }
381 
382  switch (iCurrOpt) {
383  case int('d'):
384 #ifdef DEBUG
385  if (get_debug_options(optarg, da)) {
386  silent_cerr("Unable to interpret debug"
387  " option argument;"
388  " using default" << std::endl);
389  ::debug_level = DEFAULT_DEBUG_LEVEL;
390  /* throw ErrGeneric(MBDYN_EXCEPT_ARGS); */
391  }
392 #else /* !DEBUG */
393  silent_cerr("Compile with '-DDEBUG'"
394  " to use debug features" << std::endl);
395 #endif /* !DEBUG */
396  break;
397 
398  case int('e'):
399  mbp.bException = true;
400  break;
401 
402  case int('E'): {
403 #if defined(HAVE_FENV_H) && defined(HAVE_FEENABLEEXCEPT)
404  int excepts = FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW;
405  if (optarg != 0) {
406  excepts = 0;
407  char *start = optarg, *next;
408  do {
409  next = strchr(start, ',');
410  size_t len;
411  if (next != NULL) {
412  len = next - start;
413  next++;
414  } else {
415  len = strlen(start);
416  }
417 
418  if (strncasecmp(start, "invalid", len) == 0) {
419  excepts |= FE_INVALID;
420  } else if (strncasecmp(start, "divbyzero", len) == 0) {
421  excepts |= FE_DIVBYZERO;
422  } else if (strncasecmp(start, "overflow", len) == 0) {
423  excepts |= FE_OVERFLOW;
424  } else {
425  silent_cerr("option 'E': unrecognized arg \"" << std::string(start, len) << "\"" << std::endl);
427  }
428 
429  start = next;
430  } while (next != 0);
431 
432  pedantic_cout("Option 'E': exceptions=" << excepts << std::endl);
433  }
434  /* Enable some exceptions. At startup all exceptions are masked. */
435  feenableexcept(excepts);
436 #else // ! HAVE_FENV_H
437  silent_cerr("Option 'E' unsupported; ignored" << std::endl);
438 #endif // ! HAVE_FENV_H
439  } break;
440 
441  case int('f'):
442  mbp.CurrInputFormat = MBDYN;
444  mbp.sInputFileName = optarg;
445 #ifdef _WIN32
446  // open the file in non translated mode in order not to break seek operations
447  mbp.FileStreamIn.open(mbp.sInputFileName.c_str(), std::ios::binary);
448 #else
449  mbp.FileStreamIn.open(mbp.sInputFileName.c_str());
450 #endif
451  if (!mbp.FileStreamIn) {
452  silent_cerr(std::endl
453  << "Unable to open file \""
454  << mbp.sInputFileName << "\"");
455 #ifdef USE_MPI
456  if (mbp.using_mpi) {
457  silent_cerr(" on " << mbp.ProcessorName);
458  }
459 #endif /* USE_MPI */
460  silent_cerr(";" << std::endl
461  << "aborting..."
462  << std::endl);
464  }
465  mbp.pIn = dynamic_cast<std::istream *>(&mbp.FileStreamIn);
466  break;
467 
468  case int('h'):
469  mbdyn_usage(sShortOpts);
470  throw NoErr(MBDYN_EXCEPT_ARGS);
471 
472  case int('H'):
473  mbp.bShowSymbolTable = true;
474  break;
475 
476  case int('l'):
477  mbdyn_welcome();
478  mbdyn_license();
479  throw NoErr(MBDYN_EXCEPT_ARGS);
480 
481  case int('N'):
482  if (strcmp(optarg, "auto") == 0) {
483  mbp.nThreads = 0;
484 
485  } else {
486  char *next;
487  long n = strtoul(optarg, &next, 10);
488  if (next[0] != '\0' || next == optarg) {
489  silent_cerr("Unable to parse threads number, option \"-N " << optarg << "\"" << std::endl);
491  }
492 
493  if (n < 1 || n >= std::numeric_limits<unsigned>::max()) {
494  silent_cerr("Invalid number of threads, option \"-N " << n << "\"" << std::endl);
496  }
497 
498  mbp.nThreads = unsigned(n);
499  }
500  break;
501 
502  case int('o'):
503 #ifdef HAVE_GETCWD
504  if (!is_abs_path(optarg)) {
505  char cwd[PATH_MAX];
506  if (getcwd(cwd, sizeof(cwd)) == 0) {
507  silent_cerr("Unable to set output file: getcwd failed" << std::endl);
509  }
510  mbp.sOutputFileName = std::string(cwd) + DIR_SEP + optarg;
511 
512  } else
513 #endif // HAVE_GETCWD
514  {
515  mbp.sOutputFileName = optarg;
516  }
517  break;
518 
519  case int('p'):
520 #ifdef USE_MPI
521  ASSERT(mbp.using_mpi);
522 #else /* !USE_MPI */
523  silent_cerr("switch '-p' is meaningless "
524  "without MPI" << std::endl);
525 #endif /* !USE_MPI */
526  break;
527 
528  case int('P'):
529 #ifdef USE_MPI
530  if (mbp.parallel_fPedantic > 0) {
531  mbp.parallel_fPedantic--;
532  } else
533 #endif /* USE_MPI */
534  {
535  ::fPedantic++;
536  }
537  break;
538 
539  case int('r'):
540  mbp.bRedefine = true;
541  break;
542 
543  case int('R'):
544  mbp.bRedefine = false;
545  break;
546 
547  case int('s'):
548 #ifdef USE_MPI
549  if (mbp.parallel_fSilent > 0) {
550  mbp.parallel_fSilent--;
551  } else
552 #endif /* USE_MPI */
553  {
554  ::fSilent++;
555  }
556  break;
557 
558  case int('S'):
559  if (optarg) {
560  char *s = optarg;
561 
562  if (strncasecmp(s, "rank=", STRLENOF("rank=")) == 0) {
563 #ifdef USE_MPI
564  char *next;
565  long r;
566 
567  s += STRLENOF("rank=");
568  errno = 0;
569  r = strtol(s, &next, 10);
570  int save_errno = errno;
571  if (next[0] != '\0') {
572  if (next[0] != ',') {
573  silent_cerr("error in argument -S " << optarg << std::endl);
575  }
576  s = &next[1];
577 
578  } else if (save_errno == ERANGE) {
579  silent_cerr("rank=" << s << ": overflow" << std::endl);
581  }
582 
583  if (mbp.using_mpi && r != mbp.MyRank) {
584  break;
585  }
586 #else /* ! USE_MPI */
587  silent_cerr("option -S " << optarg << " valid only when --with-mpi" << std::endl);
588 #endif /* ! USE_MPI */
589  }
590 
591  if (s[0]) {
592  char *next;
593 
594  errno = 0;
595  mbp.iSleepTime = strtol(s, &next, 10);
596  int save_errno = errno;
597  if (next[0] != '\0') {
598  silent_cerr("error in argument -S " << optarg << std::endl);
600 
601  } else if (save_errno == ERANGE) {
602  silent_cerr("argument of -S " << s << " overflows" << std::endl);
604  }
605  }
606 
607  } else {
608  /* default: 10 s */
609  mbp.iSleepTime = 10;
610  }
611 
612  break;
613 
614  case int('t'):
615  mbp.bTable = true;
616  break;
617 
618  case int('T'):
619  mbp.bTable = false;
620  break;
621 
622  case int('v'):
623  mbdyn_version();
624  throw NoErr(MBDYN_EXCEPT_ARGS);
625 
626  case int('w'):
627  mbdyn_welcome();
628  mbdyn_warranty();
629  throw NoErr(MBDYN_EXCEPT_ARGS);
630 
631  case int('W'):
632 #ifdef HAVE_CHDIR
633  if (chdir(optarg)) {
634  int save_errno = errno;
635  silent_cerr("Error in chdir(\"" << optarg << "\") "
636  "(" << save_errno << ": " << strerror(save_errno) << ")"
637  << std::endl);
639  }
640 #else /* !HAVE_CHDIR */
641  silent_cerr("chdir() not available"
642  << std::endl);
643 #endif /* !HAVE_CHDIR */
644  break;
645 
646  case int('?'):
647  silent_cerr("Unknown option -" << char(optopt) << std::endl);
648  mbdyn_usage(sShortOpts);
649  throw NoErr(MBDYN_EXCEPT_ARGS);
650 
651  default:
652  silent_cerr(std::endl
653  << "Unrecoverable error; aborting..."
654  << std::endl);
656  }
657  } // while (true) end of endless loop
658 
659  /*
660  * primo argomento utile (potenziale nome di file di ingresso)
661  */
662  currarg = optind;
663 #endif /* HAVE_GETOPT */
664 }
665 
666 static int
667 mbdyn_prepare_files(const std::string& sInputFileName, std::string& sOutputFileName)
668 {
669  std::string sNormalizedInputFileName;
670  const char *dirsep = std::strrchr(sInputFileName.c_str(), DIR_SEP);
671  const char *dot = std::strrchr(sInputFileName.c_str(), '.');
672  if (dot != 0 && (dirsep == 0 || dot > dirsep)) {
673  sNormalizedInputFileName = std::string(sInputFileName, 0, dot - sInputFileName.c_str());
674 
675  } else {
676  sNormalizedInputFileName = sInputFileName;
677  }
678 
679  // fix output file name
680  if (sOutputFileName.empty()) {
681  if (!sInputFileName.empty()) {
682  sOutputFileName = sNormalizedInputFileName;
683 
684  } else {
685  sOutputFileName = ::sDefaultOutputFileName;
686  }
687 
688  } else {
689  struct stat s;
690 
691  if (stat(sOutputFileName.c_str(), &s) != 0) {
692  int save_errno = errno;
693 
694  /* if does not exist, check path */
695  if (save_errno != ENOENT) {
696  char *errmsg = strerror(save_errno);
697 
698  silent_cerr("stat(" << sOutputFileName << ") failed "
699  "(" << save_errno << ": " << errmsg << ")" << std::endl);
701  }
702 
703  // note: use a reverse iterator find?
704  const char *path = std::strrchr(sOutputFileName.c_str(), DIR_SEP);
705  if (path != NULL) {
706  std::string sOutputFilePath(sOutputFileName, 0, path - sOutputFileName.c_str());
707  // sOutputFilePath.erase(path - sOutputFileName.c_str());
708 
709  if (stat(sOutputFilePath.c_str(), &s) != 0) {
710  save_errno = errno;
711  char *errmsg = strerror(save_errno);
712 
713  silent_cerr("stat(" << sOutputFileName << ") failed because "
714  "stat(" << sOutputFilePath << ") failed "
715  "(" << save_errno << ": " << errmsg << ")" << std::endl);
717 
718  } else if (!S_ISDIR(s.st_mode)) {
719  silent_cerr("path to file \"" << sOutputFileName << "\" is invalid ("
720  "\"" << sOutputFilePath << "\" is not a dir)" << std::endl);
722  }
723  }
724 
725  } else if (S_ISDIR(s.st_mode)) {
726  std::string tmpIn;
727 
728  if (!sInputFileName.empty()) {
729  if (dirsep != 0) {
730  tmpIn = dirsep;
731 
732  } else {
733  tmpIn = sNormalizedInputFileName;
734  }
735 
736  } else {
737  tmpIn = ::sDefaultOutputFileName;
738  }
739 
740  if (sOutputFileName[sOutputFileName.size() - 1] != DIR_SEP && tmpIn[0] != DIR_SEP) {
741  sOutputFileName += DIR_SEP;
742  }
743  sOutputFileName += tmpIn;
744  }
745  }
746 
747 #ifdef HAVE_GETCWD
748  if (!is_abs_path(sOutputFileName.c_str())) {
749  char cwd[PATH_MAX];
750  if (getcwd(cwd, sizeof(cwd)) == 0) {
751  silent_cerr("Error in getcwd()" << std::endl);
753  }
754  sOutputFileName = std::string(cwd) + DIR_SEP + sOutputFileName;
755  }
756 #endif // HAVE_GETCWD
757 
758  // chdir to input file's folder
759  if (dirsep != 0) {
760  std::string sInputDir(sInputFileName.c_str(), dirsep - sInputFileName.c_str());
761 #ifdef HAVE_CHDIR
762  if (chdir(sInputDir.c_str())) {
763  int save_errno = errno;
764  silent_cerr("Error in chdir(" << sInputDir << ") (" << save_errno << ": " << strerror(save_errno) << ")" << std::endl);
766  }
767 #else // !HAVE_CHDIR
768  silent_cerr("warning: chdir(2) not available; chdir(" << sInputDir.c_str() << ") not performed" << std::endl);
769 #endif // !HAVE_CHDIR
770  }
771 
772  return 0;
773 }
774 
775 static int
776 mbdyn_program(mbdyn_proc_t& mbp, int argc, char *argv[], int& currarg)
777 {
778 #ifndef HAVE_SYS_TIMES_H
779  const clock_t start = clock();
780 #endif
781  mbdyn_welcome();
782 #ifdef USE_MPI
783  if (mbp.using_mpi) {
784  silent_cerr("PID=" << mbp.pid << " Process " << mbp.MyRank
785  << " (" << mbp.MyRank + 1 << " of " << mbp.WorldSize
786  << ") is alive on " << mbp.ProcessorName
787  << std::endl);
788  }
789 #endif /* USE_MPI */
790 
791  /* Mostra la tabella dei simboli ed esce */
792  if (mbp.bShowSymbolTable) {
793 #ifdef USE_MPI
794  if (mbp.MyRank == 0)
795 #endif /* USE_MPI */
796  {
797  Table t(true);
798  MathParser mp(t);
799  GetEnviron(mp);
800  silent_cout("default symbol table:"
801  << std::endl << mp.GetSymbolTable() << std::endl);
802  }
803 
804  throw NoErr(MBDYN_EXCEPT_ARGS);
805  }
806 
807 #ifdef USE_SLEEP
808  if (mbp.iSleepTime > -1) {
809  silent_cerr("sleeping " << mbp.iSleepTime << "s" << std::endl);
810  sleep(mbp.iSleepTime);
811  }
812 #endif // USE_SLEEP
813 
814  /* risolve l'input */
815  if (mbp.CurrInputSource == MBFILE_UNKNOWN) {
816  if (currarg < argc) {
818 
819  } else {
820  /*
821  * se non e' un argomento prende
822  * lo standard input
823  */
825  mbp.CurrInputFormat = MBDYN;
826  ASSERT(mbp.pIn == NULL);
827  mbp.pIn = dynamic_cast<std::istream *>(&std::cin);
828  }
829  }
830 
831  /* Gestione di input/output */
832  int last = 0;
833  while (last == 0) {
834  if (mbp.CurrInputSource == MBFILE_STDIN) {
835  silent_cout("reading from stdin" << std::endl);
836  last = 1;
837 
838  } else if (mbp.CurrInputSource == MBFILE_OPT) {
839  silent_cout("reading from file \""
840  << mbp.sInputFileName
841  << "\"" << std::endl);
842  last = 1;
843 
844  } else if (mbp.CurrInputSource == MBFILE_ARGS) {
845  mbp.sInputFileName = argv[currarg];
846  silent_cout("reading from file \""
847  << mbp.sInputFileName
848  << "\"" << std::endl);
849 
850  /* incrementa il numero di argomento */
851  if (++currarg == argc) {
852  last = 1;
853  }
854 
855  {
856  mbp.CurrInputFormat = MBDYN;
857 #ifdef _WIN32
858  // open the file in non translated mode in order not to break seek operations
859  mbp.FileStreamIn.open(mbp.sInputFileName.c_str(), std::ios::binary);
860 #else
861  mbp.FileStreamIn.open(mbp.sInputFileName.c_str());
862 #endif
863  if (!mbp.FileStreamIn) {
864  silent_cerr(std::endl
865  << "Unable to open file "
866  "\"" << mbp.sInputFileName << "\";"
867  " aborting..." << std::endl);
869  }
870  }
871  mbp.pIn = &mbp.FileStreamIn;
872  }
873 
874  Solver* pSolv = NULL;
875  switch (mbp.CurrInputFormat) {
876  case MBDYN: {
877  if (mbp.pT == NULL) {
878  SAFENEWWITHCONSTRUCTOR(mbp.pT, Table, Table(true));
879  }
880  if (mbp.pMP == NULL) {
882  MathParser,
883  MathParser(*mbp.pT, mbp.bRedefine));
884 
885  /* legge l'environment */
886  GetEnviron(*mbp.pMP);
887  }
888 
889 #if defined(HAVE_GETCWD) && defined(HAVE_CHDIR)
890  char buf[PATH_MAX];
891  if (getcwd(buf, sizeof(buf)) == 0) {
892  int save_errno = errno;
893  silent_cerr("getcwd() failed (" << save_errno << ": " << strerror(save_errno) << ")" << std::endl);
895  }
896  std::string sOrigCWD(buf);
897 #endif // HAVE_GETCWD && HAVE_CHDIR
898 
899  std::string sOutputFileName = mbp.sOutputFileName;
900  mbdyn_prepare_files(mbp.sInputFileName, sOutputFileName);
901 
902  /* stream in ingresso */
903  InputStream In(*mbp.pIn);
904  MBDynParser HP(*mbp.pMP, In,
905  mbp.sInputFileName == sDefaultInputFileName ? "initial file" : mbp.sInputFileName.c_str());
906 
907  pSolv = RunMBDyn(HP, mbp.sInputFileName,
908  sOutputFileName,
909  mbp.nThreads, mbp.using_mpi, mbp.bException);
910  if (mbp.FileStreamIn.is_open()) {
911  mbp.FileStreamIn.close();
912  }
913 #if defined(HAVE_GETCWD) && defined(HAVE_CHDIR)
914  if (chdir(sOrigCWD.c_str())) {
915  int save_errno = errno;
916  silent_cerr("chdir(" << sOrigCWD.c_str() << ") failed (" << save_errno << ": " << strerror(save_errno) << ")" << std::endl);
918  }
919 #endif // HAVE_GETCWD && HAVE_CHDIR
920  break;
921  }
922 
923  default:
924  silent_cerr("You shouldn't be here!" << std::endl);
926  } // switch (CurrInputFormat)
927 
928  clock_t ct = 0;
929 
930  if (pSolv != NULL) {
931  ct += pSolv->GetCPUTime();
932  SAFEDELETE(pSolv);
933  }
934 
935  if (!mbp.bTable || currarg == argc) {
936  if (mbp.pMP != NULL) {
937  SAFEDELETE(mbp.pMP);
938  mbp.pMP = NULL;
939  }
940  if (mbp.pT != NULL) {
941  SAFEDELETE(mbp.pT);
942  mbp.pT = NULL;
943  }
944  }
945 
946 #ifdef HAVE_SYS_TIMES_H
947  time_t tSecs = 0;
948  time_t tMils = 0;
949 
950  /* Tempo di CPU impiegato */
951  struct tms tmsbuf;
952  times(&tmsbuf);
953 
954  ct += tmsbuf.tms_utime + tmsbuf.tms_cutime
955  + tmsbuf.tms_stime + tmsbuf.tms_cstime;
956 
957  long clk_tck = sysconf(_SC_CLK_TCK);
958  tSecs = ct/clk_tck;
959  tMils = ((ct*1000)/clk_tck)%1000;
960 
961  char timebuf[sizeof(" (1000000000h 59m 59s 999ms)")];
962  char *s = timebuf;
963  size_t l = sizeof(timebuf), n;
964 
965  n = snprintf(s, l, "%ld.%03ld", tSecs, tMils);
966 
967  silent_cout(std::endl << "The simulation required "
968  << timebuf << " seconds of CPU time");
969 
970  if (tSecs > 60) {
971  n = snprintf(s, l, " (" /* ) */ );
972  s += n;
973  l -= n;
974 
975  if (tSecs > 3600) {
976  n = snprintf(s, l, "%ldh ", tSecs/3600);
977  if (n >= l) {
979  }
980  s += n;
981  l -= n;
982  }
983 
984  n = snprintf(s, l,
985  /* ( */ "%02ldm %02lds %03ldms)",
986  (tSecs%3600)/60,
987  (tSecs%3600)%60, tMils);
988 
989  s += n;
990  l -= n;
991 
992  silent_cout(timebuf);
993  }
994 #ifdef USE_MPI
995  if (mbp.using_mpi) {
996  silent_cout(" on " << mbp.ProcessorName
997  << " (" << mbp.MyRank + 1
998  << " of " << mbp.WorldSize << ")");
999  }
1000 #endif /* USE_MPI */
1001  silent_cout(std::endl);
1002 
1003 #else /* ! HAVE_SYS_TIMES_H */
1004  silent_cout(std::endl << "Elapsed time "
1005  << double(clock() - start)/CLOCKS_PER_SEC << " seconds\n");
1006 #endif /* ! HAVE_SYS_TIMES_H */
1007  } // while (last == 0)
1008  throw NoErr(MBDYN_EXCEPT_ARGS);
1009 }
1010 
1011 int
1012 main(int argc, char* argv[])
1013 {
1014  int rc = EXIT_SUCCESS;
1015 
1016  mbdyn_proc_t mbp;
1017  mbp.bException = false;
1018  mbp.bRedefine = false;
1019  mbp.bTable = false;
1020  mbp.pT = 0;
1021  mbp.pMP = 0;
1022  mbp.bShowSymbolTable = false;
1023  mbp.pIn = NULL;
1025  mbp.nThreads = 0;
1026  mbp.iSleepTime = -1;
1027  mbp.CurrInputFormat = MBDYN;
1029 
1030  atexit(mbdyn_cleanup_destroy);
1031 
1032 #ifdef USE_MPI
1033  char ProcessorName_[1024] = "localhost";
1034 
1035  mbp.ProcessorName = ProcessorName_;
1036  mbp.WorldSize = 1;
1037  mbp.MyRank = 0;
1038  mbp.parallel_fSilent = 0,
1039  mbp.parallel_fPedantic = 0;
1040 
1041 #ifdef HAVE_GETPID
1042  mbp.pid = getpid();
1043 #endif // HAVE_GETPID
1044 
1045  /*
1046  * FIXME: this is a hack to detect whether mbdyn has been
1047  * invoked thru mpirun (which means we need to initialize
1048  * MPI) or not (which means we don't); need to check how
1049  * portable it is ...
1050  *
1051  * the check is on the first two chars because "most" of
1052  * the mpirun/MPI extra args start with -p<something>
1053  */
1054  parse_parallel_args(mbp, argc, argv);
1055 
1056  ::fSilent = mbp.parallel_fSilent;
1057  ::fPedantic = mbp.parallel_fPedantic;
1058 
1059  if (mbp.using_mpi) {
1060  MPI::Init(argc, argv);
1061  mbp.WorldSize = MPI::COMM_WORLD.Get_size();
1062  mbp.MyRank = MPI::COMM_WORLD.Get_rank();
1063 
1064  if (mbp.MyRank > 0) {
1065  /*
1066  * need a second take because MPI::Init()
1067  * restores the inital args, so if Get_rank() > 0
1068  * the eventual -s/-P flags have been restored
1069  */
1070  parse_parallel_args(mbp, argc, argv);
1071 
1072  ::fSilent = mbp.parallel_fSilent;
1073  ::fPedantic = mbp.parallel_fPedantic;
1074  }
1075 
1076  /*
1077  * all these temporaries are to avoid complains from
1078  * the compiler (MPI's API is really messy ):
1079  */
1080  int ProcessorNameLength = sizeof(ProcessorName_);
1081  MPI::Get_processor_name(mbp.ProcessorName, ProcessorNameLength);
1082 
1083  silent_cerr("using MPI (explicitly required by '-p*' switch)"
1084  << std::endl);
1085  }
1086 #endif /* USE_MPI */
1087 
1088  /* primo argomento valido (potenziale nome di file di ingresso) */
1089  int currarg = 0;
1090 
1091  if (argc > 0) {
1092  currarg = 1;
1093  }
1094 
1095  try {
1096  mbdyn_parse_arguments(mbp, argc, argv, currarg);
1097  } catch (NoErr) {
1098  silent_cout("MBDyn terminated normally" << std::endl);
1099  rc = EXIT_SUCCESS;
1100  MB_EXIT(return, rc);
1101  } catch (ErrInterrupted) {
1102  silent_cout("MBDyn was interrupted" << std::endl);
1103  rc = 2;
1104  MB_EXIT(exit, rc);
1105  }
1106 
1107  if (mbp.bException) {
1108  mbdyn_program(mbp, argc, argv, currarg);
1109 
1110  } else {
1111  /* The program is a big try block */
1112  try {
1113  mbdyn_program(mbp, argc, argv, currarg);
1114  } catch (NoErr) {
1115  silent_cout("MBDyn terminated normally" << std::endl);
1116  rc = EXIT_SUCCESS;
1117  } catch (ErrInterrupted) {
1118  silent_cout("MBDyn was interrupted" << std::endl);
1119  rc = 2;
1120  } catch (std::ios::failure err) {
1121  silent_cerr("An IO error occurred during the execution of MBDyn (" << err.what() << ");"
1122  " aborting... " << std::endl);
1123  rc = EXIT_FAILURE;
1124  } catch (...) {
1125  silent_cerr("An error occurred during the execution of MBDyn;"
1126  " aborting... " << std::endl);
1127  rc = EXIT_FAILURE;
1128  MB_EXIT(exit, rc);
1129  }
1130  }
1131 
1132  if (mbp.pMP != 0) {
1133  SAFEDELETE(mbp.pMP);
1134  mbp.pMP = 0;
1135  }
1136 
1137  if (mbp.pT != 0) {
1138  SAFEDELETE(mbp.pT);
1139  mbp.pT = 0;
1140  }
1141 
1142 #ifdef USE_RTAI
1143  if (::rtmbdyn_rtai_task) {
1144  (void)rtmbdyn_rt_task_delete(&::rtmbdyn_rtai_task);
1145  ::rtmbdyn_rtai_task = NULL;
1146  }
1147 #endif /* USE_RTAI */
1148 
1149  mbdyn_cleanup();
1150 
1151  MB_EXIT(return, rc);
1152 } // main() end
1153 
1154 
1155 static Solver*
1157  const std::string& sInputFileName,
1158  const std::string& sOutputFileName,
1159  unsigned int nThreads,
1160  bool using_mpi,
1161  bool bException)
1162 {
1163  DEBUGCOUTFNAME("RunMBDyn");
1164 
1165  Solver* pSolv(0);
1166 
1167  /* NOTE: the flag "bParallel" states whether the analysis
1168  * must be run in parallel or not; the flag "using_mpi"
1169  * can be true because the "-p" switch was detected;
1170  * it can be switched on by the "parallel" keyword in the
1171  * "data" block, but the analysis can still be scalar if
1172  * only one machine is available */
1173  bool bParallel(false);
1174 
1175  /* parole chiave */
1176  const char* sKeyWords[] = {
1177  "begin",
1178  "end",
1179  "data",
1180 
1181  /* problem */
1182  "problem",
1183  "integrator", /* deprecated */
1184 
1185  /* problem types */
1186  "initial" "value",
1187  "multistep", /* deprecated */
1188  "parallel" "initial" "value",
1189  "inverse" "dynamics",
1190 
1191  "parallel", /* deprecated */
1192 
1193  NULL
1194  };
1195 
1196  /* enum delle parole chiave */
1197  enum KeyWords {
1198  UNKNOWN = -1,
1199 
1200  BEGIN = 0,
1201  END,
1202  DATA,
1203 
1204  PROBLEM,
1205  INTEGRATOR, /* deprecated */
1206 
1207  /* problem types */
1208  INITIAL_VALUE,
1209  MULTISTEP, /* deprecated */
1210  PARALLEL_INITIAL_VALUE,
1211  INVERSE_DYNAMICS,
1212 
1213  PARALLEL, /* deprecated */
1214 
1215  LASTKEYWORD
1216  };
1217 
1218  /* tabella delle parole chiave */
1219  KeyTable K(HP, sKeyWords);
1220 
1221  /* legge i dati della simulazione */
1222  /* NOTE: if the first GetDescription() fails because
1223  * of an end-of-file, don't treat it as an error */
1224  KeyWords cd;
1225  try {
1226  cd = KeyWords(HP.GetDescription());
1227  } catch (EndOfFile) {
1228  throw NoErr(MBDYN_EXCEPT_ARGS);
1229  }
1230  /* looking for "begin"... */
1231  if (cd != BEGIN) {
1232  silent_cerr(std::endl
1233  << "Error: <begin> expected at line "
1234  << HP.GetLineData() << "; aborting..." << std::endl);
1236  }
1237 
1238  /* looking for "data"... */
1239  if (KeyWords(HP.GetWord()) != DATA) {
1240  silent_cerr(std::endl
1241  << "Error: <begin: data;> expected at line "
1242  << HP.GetLineData() << "; aborting..." << std::endl);
1244  }
1245 
1246  KeyWords CurrInt = INITIAL_VALUE;
1247 
1248  /* Ciclo infinito */
1249  while (true) {
1250  switch (KeyWords(HP.GetDescription())) {
1251  case INTEGRATOR:
1252  pedantic_cout("statement \"integrator\" is deprecated; "
1253  "use \"problem\" instead." << std::endl);
1254  case PROBLEM:
1255  switch (KeyWords(HP.GetWord())) {
1256  case MULTISTEP:
1257  pedantic_cout("deprecated \"multistep\" problem; "
1258  "use \"initial value\" instead" << std::endl);
1259  case INITIAL_VALUE:
1260  CurrInt = INITIAL_VALUE;
1261  break;
1262 
1263  case PARALLEL_INITIAL_VALUE:
1264  CurrInt = PARALLEL_INITIAL_VALUE;
1265 #ifdef USE_MPI
1266  /* NOTE: use "parallel" in "data" block
1267  * for models that should always be solved
1268  * in parallel; otherwise this directive
1269  * is superseded by the "-p" command-line
1270  * switch */
1271  using_mpi = true;
1272  break;
1273 #else /* !USE_MPI */
1274  silent_cerr("compile with -DUSE_MPI to enable "
1275  "parallel solution" << std::endl);
1277 #endif /* !USE_MPI */
1278 
1279  case INVERSE_DYNAMICS:
1280  CurrInt = INVERSE_DYNAMICS;
1281  break;
1282 
1283  default:
1284  silent_cerr(std::endl
1285  << "Unknown problem at line "
1286  << HP.GetLineData()
1287  << "; aborting..." << std::endl);
1289  }
1290  break;
1291 
1292  case END:
1293  if (KeyWords(HP.GetWord()) != DATA) {
1294  silent_cerr(std::endl
1295  << "Error: <end: data;> expected"
1296  " at line " << HP.GetLineData()
1297  << "; aborting..." << std::endl);
1299  }
1300  goto endofcycle;
1301 
1302  default:
1303  silent_cerr(std::endl
1304  << "Unknown description at line "
1305  << HP.GetLineData()
1306  << "; aborting..." << std::endl);
1308  }
1309  }
1310 
1311  /* Uscita dal ciclo infinito */
1312 endofcycle:
1313 
1314 #ifdef USE_MPI
1315  /* using_mpi is detected from command line switch "-p"
1316  * or set after "parallel" config statement */
1317  if (using_mpi) {
1318  unsigned int size = MPI::COMM_WORLD.Get_size();
1319  unsigned int Bcount = 0;
1320 
1321 #ifdef USE_EXTERNAL
1322  int* pBuff = NULL;
1323  SAFENEWARR(pBuff, int, size+1);
1324  pBuff[0] = 0;
1325  MPI::COMM_WORLD.Allgather(pBuff, 1, MPI::INT,
1326  pBuff+1, 1, MPI::INT);
1327  std::vector<unsigned int> iInterfaceProc(5);
1328  unsigned int Icount = 0;
1329  for (unsigned int i = 1; i <= size; i++) {
1330  if (pBuff[i] == pBuff[0]) {
1331  Bcount++;
1332  }
1333  if (pBuff[i] > 9) {
1334  if (Icount <= 5) {
1335  iInterfaceProc[Icount++] = i-1;
1336 
1337  } else {
1338  iInterfaceProc.push_back(i-1);
1339  }
1340  }
1341  }
1342  if (Bcount == size) {
1343  /* l'unica cosa che c'e' e' MBDyn */
1344  MBDynComm = MPI::COMM_WORLD.Dup();
1345  } else {
1346  MBDynComm = MPI::COMM_WORLD.Split(pBuff[0], 1);
1347  }
1348  if (Icount != 0) {
1349  for (unsigned int ii = 0; ii < Icount; ii++) {
1350  InterfaceComms.push_back(MBDynComm.Create_intercomm(0, MPI::COMM_WORLD, iInterfaceProc[ii], INTERF_COMM_LABEL));
1351  }
1352  }
1353  SAFEDELETEARR(pBuff);
1354 #else /* ! USE_EXTERNAL */
1355  MBDynComm = MPI::COMM_WORLD.Dup();
1356  Bcount = size;
1357 #endif /* ! USE_EXTERNAL */
1358  if (MBDynComm.Get_rank()) {
1359  silent_cout("MBDyn will run on " << Bcount
1360  << " processors starting from "
1361  "processor " /* ??? */
1362  << std::endl);
1363  }
1364  bParallel = (MBDynComm.Get_size() != 1);
1365 
1366  if (bParallel) {
1367  /*
1368  * E' necessario poter determinare in questa routine
1369  * quale e' il master in modo da far calcolare la soluzione
1370  * solo su di esso
1371  */
1372  MyRank = MBDynComm.Get_rank();
1373  /* chiama il gestore dei dati generali della simulazione */
1374 
1375  /*
1376  * I file di output vengono stampati localmente
1377  * da ogni processo aggiungendo al termine
1378  * dell'OutputFileName il rank del processo
1379  */
1380  ASSERT(MPI::COMM_WORLD.Get_size() > 1);
1381  int iRankLength = 1 + (int)log10(MPI::COMM_WORLD.Get_size() - 1);
1382 
1383  char buf[STRLENOF(".") + iRankLength + 1];
1384  snprintf(buf, sizeof(buf), ".%.*d", iRankLength, MyRank);
1385  sOutputFileName += buf;
1386  }
1387  }
1388 #endif /* USE_MPI */
1389 
1390  switch (CurrInt) {
1391  case INITIAL_VALUE:
1392  case PARALLEL_INITIAL_VALUE:
1393  SAFENEWWITHCONSTRUCTOR(pSolv,
1394  Solver,
1395  Solver(HP, sInputFileName,
1396  sOutputFileName, nThreads, bParallel));
1397  break;
1398 
1399  case INVERSE_DYNAMICS:
1400  SAFENEWWITHCONSTRUCTOR(pSolv,
1401  InverseSolver,
1402  InverseSolver(HP, sInputFileName,
1403  sOutputFileName, nThreads, bParallel));
1404  break;
1405 
1406  default:
1407  silent_cerr("Unknown integrator; aborting..." << std::endl);
1409  }
1410 
1411  /* Runs the simulation */
1412  if (bException) {
1413  pSolv->Run();
1414 
1415  } else {
1416  try {
1417  /* Runs the simulation */
1418  pSolv->Run();
1419  } catch (...) {
1420  if (pSolv) {
1421  SAFEDELETE(pSolv);
1422  pSolv = 0;
1423  }
1424  throw;
1425  }
1426  }
1427 
1428  return pSolv;
1429 } // RunMBDyn
Definition: mbdyn.cc:131
bool bTable
Definition: mbdyn.cc:151
std::ifstream FileStreamIn
Definition: mbdyn.cc:145
int iSleepTime
Definition: mbdyn.cc:143
const char sDefaultOutputFileName[]
Definition: mbdyn.cc:117
int optopt
Definition: getopt.c:73
int optind
Definition: getopt.c:72
bool bRedefine
Definition: mbdyn.cc:150
InputFormat
Definition: mbdyn.cc:130
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
#define DEBUGCOUTFNAME(fname)
Definition: myassert.h:256
int opterr
Definition: getopt.c:71
unsigned int nThreads
Definition: mbdyn.cc:156
#define MB_EXIT(what, err)
Definition: mbdyn.cc:97
InputFormat CurrInputFormat
Definition: mbdyn.cc:154
Table * pT
Definition: mbdyn.cc:152
int fSilent
Definition: myassert.cc:58
#define SAFEDELETEARR(pnt)
Definition: mynewmem.h:713
void mbdyn_warranty(void)
Definition: legalese.cc:44
int is_abs_path(const char *const p)
Definition: fn_UNIX.cc:206
std::string sOutputFileName
Definition: mbdyn.cc:148
std::istream * pIn
Definition: mbdyn.cc:146
InputSource CurrInputSource
Definition: mbdyn.cc:155
static void mbdyn_version(void)
Definition: mbdyn.cc:197
Definition: dataman4.cc:96
bool using_mpi
Definition: mbdyn.cc:157
#define PATH_MAX
Definition: mbdyn.cc:109
int main(int argc, char *argv[])
Definition: mbdyn.cc:1012
virtual clock_t GetCPUTime(void) const
Definition: solver.cc:5188
bool bShowSymbolTable
Definition: mbdyn.cc:144
void Run(void)
Definition: solver.cc:1633
std::string sInputFileName
Definition: mbdyn.cc:147
int mbdyn_cleanup(void)
Definition: cleanup.cc:77
static int mbdyn_prepare_files(const std::string &sInputFileName, std::string &sOutputFileName)
Definition: mbdyn.cc:667
int GetDescription(void)
Definition: parser.cc:730
int fPedantic
Definition: myassert.cc:59
const char DIR_SEP
Definition: filename.h:88
MathParser * pMP
Definition: mbdyn.cc:153
#define ASSERT(expression)
Definition: colamd.c:977
KeyWords
Definition: dataman4.cc:94
#define SAFENEWWITHCONSTRUCTOR(pnt, item, constructor)
Definition: mynewmem.h:698
static Solver * RunMBDyn(MBDynParser &, const std::string &, const std::string &, unsigned int, bool, bool)
Definition: mbdyn.cc:1156
Definition: except.h:79
Definition: solver.h:78
InputSource
Definition: mbdyn.cc:135
const std::string sDefaultInputFileName("MBDyn")
int getopt(int argc, char *const argv[], const char *opts)
Definition: getopt.c:93
#define STRLENOF(s)
Definition: mbdyn.h:166
virtual int GetWord(void)
Definition: parser.cc:1083
#define SAFENEWARR(pnt, item, sz)
Definition: mynewmem.h:701
void mbdyn_license(void)
Definition: legalese.cc:37
Definition: table.h:43
char * optarg
Definition: getopt.c:74
void GetEnviron(MathParser &)
Definition: env.cc:53
void mbdyn_parse_arguments(mbdyn_proc_t &mbp, int argc, char *argv[], int &currarg)
Definition: mbdyn.cc:360
static doublereal buf[BUFSIZE]
Definition: discctrl.cc:333
void mbdyn_cleanup_destroy(void)
Definition: cleanup.cc:93
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697
Table & GetSymbolTable(void) const
Definition: mathp.cc:1931
bool bException
Definition: mbdyn.cc:149
static int mbdyn_program(mbdyn_proc_t &mbp, int argc, char *argv[], int &currarg)
Definition: mbdyn.cc:776
const char * path
Definition: autopilot.c:141
#define SAFEDELETE(pnt)
Definition: mynewmem.h:710