1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
52 #include "gmx_fatal.h"
56 #include "gromacs/utility/exceptions.h"
57 #include "gromacs/utility/gmxassert.h"
58 #include "gromacs/utility/programinfo.h"
60 #include "thread_mpi/threads.h"
68 #include <sys/schedctl.h>
69 #include <sys/sysmp.h>
72 /* The source code in this file should be thread-safe.
73 Please keep it that way. */
75 /******************************************************************
77 * T R A J E C T O R Y S T U F F
79 ******************************************************************/
81 /****************************************************************
83 * E X P O R T E D F U N C T I O N S
85 ****************************************************************/
88 /* progam names, etc. */
90 const char *ShortProgram(void)
94 return gmx::ProgramInfo::getInstance().programName().c_str();
96 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
99 const char *Program(void)
103 return gmx::ProgramInfo::getInstance().programNameWithPath().c_str();
105 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
108 const char *command_line(void)
112 return gmx::ProgramInfo::getInstance().commandLine().c_str();
114 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
117 void set_program_name(const char *argvzero)
119 // The negative argc is a hack to make the ProgramInfo overridable in
120 // parse_common_args(), where the full command-line is known.
121 gmx::ProgramInfo::init(-1, &argvzero);
124 /* utility functions */
126 gmx_bool bRmod_fd(double a, double b, double c, gmx_bool bDouble)
131 tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
133 iq = static_cast<int>((a - b + tol*a)/c);
135 if (std::fabs(a - b - c*iq) <= tol*std::fabs(a))
145 int check_times2(real t, real t0, real tp, real tpp, gmx_bool bDouble)
150 /* since t is float, we can not use double precision for bRmod */
155 if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN))) &&
156 (!bTimeSet(TEND) || (t <= rTimeValue(TEND))))
158 if (bTimeSet(TDELTA) && !bRmod_fd(t, t0, rTimeValue(TDELTA), bDouble))
167 else if (bTimeSet(TEND) && (t >= rTimeValue(TEND)))
173 fprintf(debug, "t=%g, t0=%g, b=%g, e=%g, dt=%g: r=%d\n",
174 t, t0, rTimeValue(TBEGIN), rTimeValue(TEND), rTimeValue(TDELTA), r);
179 int check_times(real t)
181 return check_times2(t, t, t, t, FALSE);
187 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
190 const char *select = NULL;
194 select = getenv("GMXTIMEUNIT");
198 while (time_list[i] && strcmp(time_list[i], select) != 0)
204 if (!bCanTime || select == NULL ||
205 time_list[i] == NULL || strcmp(time_list[i], select) != 0)
207 /* Set it to the default: ps */
209 while (time_list[i] && strcmp(time_list[i], "ps") != 0)
215 time_list[0] = time_list[i];
219 static void set_default_xvg_format(const char *xvg_list[])
224 select = getenv("GMX_VIEW_XVG");
227 /* The default is the first option */
228 xvg_list[0] = xvg_list[1];
233 while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
237 if (xvg_list[i] != NULL)
239 xvg_list[0] = xvg_list[i];
243 xvg_list[0] = xvg_list[exvgNONE];
249 /***** T O P O L O G Y S T U F F ******/
251 t_topology *read_top(const char *fn, int *ePBC)
257 epbc = read_tpx_top(fn, NULL, NULL, &natoms, NULL, NULL, NULL, top);
266 /*************************************************************
268 * P A R S I N G S T U F F
270 *************************************************************/
272 static void usage(const char *type, const char *arg)
274 GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
275 gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
278 int iscan(int argc, char *argv[], int *i)
280 const char *const arg = argv[*i];
283 usage("an integer", arg);
285 const char *const value = argv[++(*i)];
287 int var = std::strtol(value, &endptr, 10);
288 if (*value == '\0' || *endptr != '\0')
290 usage("an integer", arg);
295 gmx_large_int_t istepscan(int argc, char *argv[], int *i)
297 const char *const arg = argv[*i];
300 usage("an integer", arg);
302 const char *const value = argv[++(*i)];
304 gmx_large_int_t var = str_to_large_int_t(value, &endptr);
305 if (*value == '\0' || *endptr != '\0')
307 usage("an integer", arg);
312 double dscan(int argc, char *argv[], int *i)
314 const char *const arg = argv[*i];
317 usage("a real", arg);
319 const char *const value = argv[++(*i)];
321 double var = std::strtod(value, &endptr);
322 if (*value == '\0' || *endptr != '\0')
324 usage("a real", arg);
329 char *sscan(int argc, char *argv[], int *i)
333 if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
334 (argv[(*i)+2][0] != '-') )
336 fprintf(stderr, "Possible missing string argument for option %s\n\n",
342 usage("a string", argv[*i]);
348 int nenum(const char *const enumc[])
353 /* we *can* compare pointers directly here! */
354 while (enumc[i] && enumc[0] != enumc[i])
362 static void pdesc(char *desc)
367 if ((int)strlen(ptr) < 70)
369 fprintf(stderr, "\t%s\n", ptr);
373 for (nptr = ptr+70; (nptr != ptr) && (!std::isspace(*nptr)); nptr--)
379 fprintf(stderr, "\t%s\n", ptr);
385 fprintf(stderr, "\t%s\n", ptr);
391 static FILE *man_file(const output_env_t oenv, const char *mantp)
395 const char *pr = output_env_get_short_program_name(oenv);
397 if (strcmp(mantp, "ascii") != 0)
399 sprintf(buf, "%s.%s", pr, mantp);
403 sprintf(buf, "%s.txt", pr);
405 fp = gmx_fio_fopen(buf, "w");
410 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
412 memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
417 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
419 char *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
420 const char*ptr = NULL;
423 /* First compute length for description */
424 len = strlen(pa->desc)+1;
425 if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
429 if (pa->type == etENUM)
432 for (k = 1; (pa->u.c[k] != NULL); k++)
434 len += strlen(pa->u.c[k])+12;
439 /* add label for hidden options */
442 sprintf(newdesc, "[hidden] %s", ptr+6);
446 strcpy(newdesc, pa->desc);
449 /* change '%t' into time_unit */
450 #define TUNITLABEL "%t"
451 #define NTUNIT strlen(TUNITLABEL)
452 if (pa->type == etTIME)
454 while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
458 len += strlen(time_unit_str)-NTUNIT;
460 strcpy(ndesc, newdesc);
461 strcat(ndesc, time_unit_str);
471 /* Add extra comment for enumerateds */
472 if (pa->type == etENUM)
474 strcat(newdesc, ": ");
475 for (k = 1; (pa->u.c[k] != NULL); k++)
477 strcat(newdesc, "[TT]");
478 strcat(newdesc, pa->u.c[k]);
479 strcat(newdesc, "[tt]");
480 /* Print a comma everywhere but at the last one */
481 if (pa->u.c[k+1] != NULL)
483 if (pa->u.c[k+2] == NULL)
485 strcat(newdesc, " or ");
489 strcat(newdesc, ", ");
498 void parse_common_args(int *argc, char *argv[], unsigned long Flags,
499 int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
500 int ndesc, const char **desc,
501 int nbugs, const char **bugs,
504 gmx_bool bHelp = FALSE, bHidden = FALSE, bQuiet = FALSE, bVersion = FALSE;
505 const char *manstr[] = {
506 NULL, "no", "html", "tex", "nroff", "ascii",
507 "completion", "py", "xml", "wiki", NULL
509 /* This array should match the order of the enum in oenv.h */
510 const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
511 /* This array should match the order of the enum in oenv.h */
512 const char *time_units[] = {
513 NULL, "fs", "ps", "ns", "us", "ms", "s",
516 int nicelevel = 0, debug_level = 0, verbose_level = 0;
518 real tbegin = 0, tend = 0, tdelta = 0;
519 gmx_bool bView = FALSE;
521 t_pargs *all_pa = NULL;
526 "-npri", FALSE, etINT, {&npri},
527 "HIDDEN Set non blocking priority (try 128)"
531 "-nice", FALSE, etINT, {&nicelevel},
534 t_pargs deffnm_pa = {
535 "-deffnm", FALSE, etSTR, {&deffnm},
536 "Set the default filename for all file options"
539 "-b", FALSE, etTIME, {&tbegin},
540 "First frame (%t) to read from trajectory"
543 "-e", FALSE, etTIME, {&tend},
544 "Last frame (%t) to read from trajectory"
547 "-dt", FALSE, etTIME, {&tdelta},
548 "Only use frame when t MOD dt = first time (%t)"
551 "-w", FALSE, etBOOL, {&bView},
552 "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
555 "-xvg", FALSE, etENUM, {xvg_format},
556 "xvg plot formatting"
559 "-tu", FALSE, etENUM, {time_units},
562 /* Maximum number of extra arguments */
566 { "-h", FALSE, etBOOL, {&bHelp},
567 "Print help info and quit" },
568 { "-version", FALSE, etBOOL, {&bVersion},
569 "Print version info and quit" },
570 { "-verb", FALSE, etINT, {&verbose_level},
571 "HIDDENLevel of verbosity for this program" },
572 { "-hidden", FALSE, etBOOL, {&bHidden},
573 "HIDDENPrint hidden options" },
574 { "-quiet", FALSE, etBOOL, {&bQuiet},
575 "HIDDENDo not print help info" },
576 { "-man", FALSE, etENUM, {manstr},
577 "HIDDENWrite manual and quit" },
578 { "-debug", FALSE, etINT, {&debug_level},
579 "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
581 #define NPCA_PA asize(pca_pa)
583 gmx_bool bPrint, bExit, bXvgr;
584 int i, j, k, npall, max_pa;
586 #define FF(arg) ((Flags & arg) == arg)
588 /* Check for double arguments */
589 for (i = 1; (i < *argc); i++)
591 if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1])))
593 for (j = i+1; (j < *argc); j++)
595 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
596 (strcmp(argv[i], argv[j]) == 0) )
598 if (FF(PCA_NOEXIT_ON_ARGS))
600 fprintf(stderr, "Double command line argument %s\n",
605 gmx_fatal(FARGS, "Double command line argument %s\n",
613 gmx::ProgramInfo::init(*argc, argv);
615 /* Handle the flags argument, which is a bit field
616 * The FF macro returns whether or not the bit is set
618 bPrint = !FF(PCA_SILENT);
620 /* Check ALL the flags ... */
621 max_pa = NPCA_PA + EXTRA_PA + npargs+1;
622 snew(all_pa, max_pa);
624 for (i = npall = 0; (i < static_cast<int>(NPCA_PA)); i++)
626 npall = add_parg(npall, all_pa, &(pca_pa[i]));
630 const char *envstr = getenv("GMXNPRIALL");
633 npri = strtol(envstr, NULL, 10);
637 envstr = getenv("GMXNPRI");
640 npri = strtol(envstr, NULL, 10);
643 npall = add_parg(npall, all_pa, &npri_pa);
650 npall = add_parg(npall, all_pa, &nice_pa);
652 if (FF(PCA_CAN_SET_DEFFNM))
654 npall = add_parg(npall, all_pa, &deffnm_pa);
656 if (FF(PCA_CAN_BEGIN))
658 npall = add_parg(npall, all_pa, &begin_pa);
662 npall = add_parg(npall, all_pa, &end_pa);
666 npall = add_parg(npall, all_pa, &dt_pa);
668 if (FF(PCA_TIME_UNIT))
670 npall = add_parg(npall, all_pa, &time_pa);
672 if (FF(PCA_CAN_VIEW))
674 npall = add_parg(npall, all_pa, &view_pa);
678 for (i = 0; (i < nfile); i++)
680 bXvgr = bXvgr || (fnm[i].ftp == efXVG);
684 npall = add_parg(npall, all_pa, &xvg_pa);
687 /* Now append the program specific arguments */
688 for (i = 0; (i < npargs); i++)
690 npall = add_parg(npall, all_pa, &(pa[i]));
693 /* set etENUM options to default */
694 for (i = 0; (i < npall); i++)
696 if (all_pa[i].type == etENUM)
698 all_pa[i].u.c[0] = all_pa[i].u.c[1];
701 set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
702 set_default_xvg_format(xvg_format);
704 /* Now parse all the command-line options */
705 get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
707 /* set program name, command line, and default values for output options */
708 output_env_init(oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
709 (xvg_format_t)nenum(xvg_format), verbose_level, debug_level);
713 printf("Program: %s\n", output_env_get_program_name(*oenv));
714 gmx_print_version_info(stdout);
718 if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
720 set_default_file_name(deffnm);
723 /* Parse the file args */
724 parse_file_args(argc, argv, nfile, fnm, FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
726 /* Open the debug file */
731 if (gmx_mpi_initialized())
733 sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
738 sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
741 init_debug(debug_level, buf);
742 fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
743 buf, __FILE__, __LINE__);
746 /* Now copy the results back... */
747 for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
749 memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
753 for (i = 0; (i < npall); i++)
755 all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
758 bExit = bHelp || (strcmp(manstr[0], "no") != 0);
760 #if (defined __sgi && USE_SGI_FPE)
764 /* Set the nice level */
766 if (npri != 0 && !bExit)
768 schedctl(MPTS_RTPRI, 0, npri);
774 /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
775 if (nicelevel != 0 && !bExit)
777 static gmx_bool nice_set = FALSE; /* only set it once */
778 static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
779 tMPI_Thread_mutex_lock(&init_mutex);
782 if (nice(nicelevel) == -1)
784 /* Do nothing, but use the return value to avoid warnings. */
788 tMPI_Thread_mutex_unlock(&init_mutex);
793 if (!(FF(PCA_QUIET) || bQuiet ))
797 write_man(stderr, "help", output_env_get_program_name(*oenv),
798 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
802 pr_fns(stderr, nfile, fnm);
803 print_pargs(stderr, npall, all_pa, FALSE);
807 if (strcmp(manstr[0], "no") != 0)
809 if (!strcmp(manstr[0], "completion"))
811 /* one file each for csh, bash and zsh if we do completions */
812 fp = man_file(*oenv, "completion-zsh");
814 write_man(fp, "completion-zsh", output_env_get_program_name(*oenv),
815 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
817 fp = man_file(*oenv, "completion-bash");
818 write_man(fp, "completion-bash", output_env_get_program_name(*oenv),
819 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
821 fp = man_file(*oenv, "completion-csh");
822 write_man(fp, "completion-csh", output_env_get_program_name(*oenv),
823 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
828 fp = man_file(*oenv, manstr[0]);
829 write_man(fp, manstr[0], output_env_get_program_name(*oenv),
830 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
835 /* convert time options, must be done after printing! */
837 for (i = 0; i < npall; i++)
839 if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
841 *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
845 /* Extract Time info from arguments */
846 if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
848 setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
851 if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
853 setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
856 if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
858 setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
862 for (i = 0; i < npall; ++i)
864 sfree((void *)all_pa[i].desc);
868 if (!FF(PCA_NOEXIT_ON_ARGS))