2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
57 #include "gmx_fatal.h"
60 #include "mtop_util.h"
64 #include "thread_mpi.h"
69 #include <sys/schedctl.h>
70 #include <sys/sysmp.h>
73 /* The source code in this file should be thread-safe.
74 Please keep it that way. */
76 /******************************************************************
78 * T R A J E C T O R Y S T U F F
80 ******************************************************************/
82 /* inherently globally shared names: */
83 static const char *program_name = NULL;
84 static char *cmd_line = NULL;
87 /* For now, some things here are simply not re-entrant, so
88 we have to actively lock them. */
89 static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
93 /****************************************************************
95 * E X P O R T E D F U N C T I O N S
97 ****************************************************************/
100 /* progam names, etc. */
102 const char *ShortProgram(void)
104 const char *pr, *ret;
105 #ifdef GMX_THREAD_MPI
106 tMPI_Thread_mutex_lock(&init_mutex);
108 pr = ret = program_name;
109 #ifdef GMX_THREAD_MPI
110 tMPI_Thread_mutex_unlock(&init_mutex);
112 if ((pr = strrchr(ret, DIR_SEPARATOR)) != NULL)
119 const char *Program(void)
122 #ifdef GMX_THREAD_MPI
123 tMPI_Thread_mutex_lock(&init_mutex);
126 #ifdef GMX_THREAD_MPI
127 tMPI_Thread_mutex_unlock(&init_mutex);
132 const char *command_line(void)
135 #ifdef GMX_THREAD_MPI
136 tMPI_Thread_mutex_lock(&init_mutex);
139 #ifdef GMX_THREAD_MPI
140 tMPI_Thread_mutex_unlock(&init_mutex);
145 void set_program_name(const char *argvzero)
147 #ifdef GMX_THREAD_MPI
148 tMPI_Thread_mutex_lock(&init_mutex);
150 if (program_name == NULL)
152 /* if filename has file ending (e.g. .exe) then strip away */
153 char* extpos = strrchr(argvzero, '.');
154 if (extpos > strrchr(argvzero, DIR_SEPARATOR))
156 program_name = gmx_strndup(argvzero, extpos-argvzero);
160 program_name = gmx_strdup(argvzero);
163 if (program_name == NULL)
165 program_name = "GROMACS";
167 #ifdef GMX_THREAD_MPI
168 tMPI_Thread_mutex_unlock(&init_mutex);
173 void set_command_line(int argc, char *argv[])
178 #ifdef GMX_THREAD_MPI
179 tMPI_Thread_mutex_lock(&init_mutex);
181 if (cmd_line == NULL)
183 cmdlength = strlen(argv[0]);
184 for (i = 1; i < argc; i++)
186 cmdlength += strlen(argv[i]);
189 /* Fill the cmdline string */
190 snew(cmd_line, cmdlength+argc+1);
191 for (i = 0; i < argc; i++)
193 strcat(cmd_line, argv[i]);
194 strcat(cmd_line, " ");
197 #ifdef GMX_THREAD_MPI
198 tMPI_Thread_mutex_unlock(&init_mutex);
203 /* utility functions */
205 gmx_bool bRmod_fd(double a, double b, double c, gmx_bool bDouble)
210 tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
212 iq = (a - b + tol*a)/c;
214 if (fabs(a - b - c*iq) <= tol*fabs(a))
224 int check_times2(real t, real t0, real tp, real tpp, gmx_bool bDouble)
230 /* since t is float, we can not use double precision for bRmod */
234 if (t-tp > 0 && tp-tpp > 0)
236 margin = 0.1*min(t-tp, tp-tpp);
244 if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN))) &&
245 (!bTimeSet(TEND) || (t <= rTimeValue(TEND))))
247 if (bTimeSet(TDELTA) && !bRmod_fd(t, t0, rTimeValue(TDELTA), bDouble))
256 else if (bTimeSet(TEND) && (t >= rTimeValue(TEND)))
262 fprintf(debug, "t=%g, t0=%g, b=%g, e=%g, dt=%g: r=%d\n",
263 t, t0, rTimeValue(TBEGIN), rTimeValue(TEND), rTimeValue(TDELTA), r);
268 int check_times(real t)
270 return check_times2(t, t, t, t, FALSE);
276 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
279 const char *select = NULL;
283 select = getenv("GMXTIMEUNIT");
287 while (time_list[i] && strcmp(time_list[i], select) != 0)
293 if (!bCanTime || select == NULL ||
294 time_list[i] == NULL || strcmp(time_list[i], select) != 0)
296 /* Set it to the default: ps */
298 while (time_list[i] && strcmp(time_list[i], "ps") != 0)
304 time_list[0] = time_list[i];
308 static void set_default_xvg_format(const char *xvg_list[])
311 const char *select, *tmp;
313 select = getenv("GMX_VIEW_XVG");
316 /* The default is the first option */
317 xvg_list[0] = xvg_list[1];
322 while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
326 if (xvg_list[i] != NULL)
328 xvg_list[0] = xvg_list[i];
332 xvg_list[0] = xvg_list[exvgNONE];
338 /***** T O P O L O G Y S T U F F ******/
340 t_topology *read_top(const char *fn, int *ePBC)
346 epbc = read_tpx_top(fn, NULL, NULL, &natoms, NULL, NULL, NULL, top);
355 /*************************************************************
357 * P A R S I N G S T U F F
359 *************************************************************/
361 static void usage(const char *type, const char *arg)
364 gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
367 int iscan(int argc, char *argv[], int *i)
373 if (!sscanf(argv[++(*i)], "%d", &var))
375 usage("an integer", argv[(*i)-1]);
380 usage("an integer", argv[*i]);
386 gmx_large_int_t istepscan(int argc, char *argv[], int *i)
388 gmx_large_int_t var = 0;
392 if (!sscanf(argv[++(*i)], gmx_large_int_pfmt, &var))
394 usage("an integer", argv[(*i)-1]);
399 usage("an integer", argv[*i]);
405 double dscan(int argc, char *argv[], int *i)
411 if (!sscanf(argv[++(*i)], "%lf", &var))
413 usage("a real", argv[(*i)-1]);
418 usage("a real", argv[*i]);
424 char *sscan(int argc, char *argv[], int *i)
428 if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
429 (argv[(*i)+2][0] != '-') )
431 fprintf(stderr, "Possible missing string argument for option %s\n\n",
437 usage("a string", argv[*i]);
443 int nenum(const char *const enumc[])
448 /* we *can* compare pointers directly here! */
449 while (enumc[i] && enumc[0] != enumc[i])
457 static void pdesc(char *desc)
462 if ((int)strlen(ptr) < 70)
464 fprintf(stderr, "\t%s\n", ptr);
468 for (nptr = ptr+70; (nptr != ptr) && (!isspace(*nptr)); nptr--)
474 fprintf(stderr, "\t%s\n", ptr);
480 fprintf(stderr, "\t%s\n", ptr);
486 static FILE *man_file(const output_env_t oenv, const char *mantp)
490 const char *pr = output_env_get_short_program_name(oenv);
492 if (strcmp(mantp, "ascii") != 0)
494 sprintf(buf, "%s.%s", pr, mantp);
498 sprintf(buf, "%s.txt", pr);
500 fp = gmx_fio_fopen(buf, "w");
505 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
507 memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
512 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
514 char *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
515 const char*ptr = NULL;
518 /* First compute length for description */
519 len = strlen(pa->desc)+1;
520 if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
524 if (pa->type == etENUM)
527 for (k = 1; (pa->u.c[k] != NULL); k++)
529 len += strlen(pa->u.c[k])+12;
534 /* add label for hidden options */
537 sprintf(newdesc, "[hidden] %s", ptr+6);
541 strcpy(newdesc, pa->desc);
544 /* change '%t' into time_unit */
545 #define TUNITLABEL "%t"
546 #define NTUNIT strlen(TUNITLABEL)
547 if (pa->type == etTIME)
549 while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
553 len += strlen(time_unit_str)-NTUNIT;
555 strcpy(ndesc, newdesc);
556 strcat(ndesc, time_unit_str);
566 /* Add extra comment for enumerateds */
567 if (pa->type == etENUM)
569 strcat(newdesc, ": ");
570 for (k = 1; (pa->u.c[k] != NULL); k++)
572 strcat(newdesc, "[TT]");
573 strcat(newdesc, pa->u.c[k]);
574 strcat(newdesc, "[tt]");
575 /* Print a comma everywhere but at the last one */
576 if (pa->u.c[k+1] != NULL)
578 if (pa->u.c[k+2] == NULL)
580 strcat(newdesc, " or ");
584 strcat(newdesc, ", ");
593 void parse_common_args(int *argc, char *argv[], unsigned long Flags,
594 int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
595 int ndesc, const char **desc,
596 int nbugs, const char **bugs,
599 gmx_bool bHelp = FALSE, bHidden = FALSE, bQuiet = FALSE, bVersion = FALSE;
600 const char *manstr[] = {
601 NULL, "no", "html", "tex", "nroff", "ascii",
602 "completion", "py", "xml", "wiki", NULL
604 /* This array should match the order of the enum in oenv.h */
605 const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
606 /* This array should match the order of the enum in oenv.h */
607 const char *time_units[] = {
608 NULL, "fs", "ps", "ns", "us", "ms", "s",
611 int nicelevel = 0, mantp = 0, npri = 0, debug_level = 0, verbose_level = 0;
613 real tbegin = 0, tend = 0, tdelta = 0;
614 gmx_bool bView = FALSE;
616 t_pargs *all_pa = NULL;
619 "-npri", FALSE, etINT, {&npri},
620 "HIDDEN Set non blocking priority (try 128)"
623 "-nice", FALSE, etINT, {&nicelevel},
626 t_pargs deffnm_pa = {
627 "-deffnm", FALSE, etSTR, {&deffnm},
628 "Set the default filename for all file options"
631 "-b", FALSE, etTIME, {&tbegin},
632 "First frame (%t) to read from trajectory"
635 "-e", FALSE, etTIME, {&tend},
636 "Last frame (%t) to read from trajectory"
639 "-dt", FALSE, etTIME, {&tdelta},
640 "Only use frame when t MOD dt = first time (%t)"
643 "-w", FALSE, etBOOL, {&bView},
644 "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
647 "-xvg", FALSE, etENUM, {xvg_format},
648 "xvg plot formatting"
651 "-tu", FALSE, etENUM, {time_units},
654 /* Maximum number of extra arguments */
658 { "-h", FALSE, etBOOL, {&bHelp},
659 "Print help info and quit" },
660 { "-version", FALSE, etBOOL, {&bVersion},
661 "Print version info and quit" },
662 { "-verb", FALSE, etINT, {&verbose_level},
663 "HIDDENLevel of verbosity for this program" },
664 { "-hidden", FALSE, etBOOL, {&bHidden},
665 "HIDDENPrint hidden options" },
666 { "-quiet", FALSE, etBOOL, {&bQuiet},
667 "HIDDENDo not print help info" },
668 { "-man", FALSE, etENUM, {manstr},
669 "HIDDENWrite manual and quit" },
670 { "-debug", FALSE, etINT, {&debug_level},
671 "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
673 #define NPCA_PA asize(pca_pa)
675 gmx_bool bPrint, bExit, bXvgr;
676 int i, j, k, npall, max_pa, cmdlength;
680 #define FF(arg) ((Flags & arg) == arg)
684 cmdlength = strlen(argv[0]);
685 /* Check for double arguments */
686 for (i = 1; (i < *argc); i++)
688 cmdlength += strlen(argv[i]);
689 if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1])))
691 for (j = i+1; (j < *argc); j++)
693 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
694 (strcmp(argv[i], argv[j]) == 0) )
696 if (FF(PCA_NOEXIT_ON_ARGS))
698 fprintf(stderr, "Double command line argument %s\n",
703 gmx_fatal(FARGS, "Double command line argument %s\n",
711 set_program_name(argv[0]);
712 set_command_line(*argc, argv);
714 /* Handle the flags argument, which is a bit field
715 * The FF macro returns whether or not the bit is set
717 bPrint = !FF(PCA_SILENT);
719 /* Check ALL the flags ... */
720 max_pa = NPCA_PA + EXTRA_PA + npargs+1;
721 snew(all_pa, max_pa);
723 for (i = npall = 0; (i < NPCA_PA); i++)
725 npall = add_parg(npall, all_pa, &(pca_pa[i]));
729 envstr = getenv("GMXNPRIALL");
732 npri = strtol(envstr, NULL, 10);
736 envstr = getenv("GMXNPRI");
739 npri = strtol(envstr, NULL, 10);
742 npall = add_parg(npall, all_pa, &npri_pa);
749 npall = add_parg(npall, all_pa, &nice_pa);
751 if (FF(PCA_CAN_SET_DEFFNM))
753 npall = add_parg(npall, all_pa, &deffnm_pa);
755 if (FF(PCA_CAN_BEGIN))
757 npall = add_parg(npall, all_pa, &begin_pa);
761 npall = add_parg(npall, all_pa, &end_pa);
765 npall = add_parg(npall, all_pa, &dt_pa);
767 if (FF(PCA_TIME_UNIT))
769 npall = add_parg(npall, all_pa, &time_pa);
771 if (FF(PCA_CAN_VIEW))
773 npall = add_parg(npall, all_pa, &view_pa);
777 for (i = 0; (i < nfile); i++)
779 bXvgr = bXvgr || (fnm[i].ftp == efXVG);
783 npall = add_parg(npall, all_pa, &xvg_pa);
786 /* Now append the program specific arguments */
787 for (i = 0; (i < npargs); i++)
789 npall = add_parg(npall, all_pa, &(pa[i]));
792 /* set etENUM options to default */
793 for (i = 0; (i < npall); i++)
795 if (all_pa[i].type == etENUM)
797 all_pa[i].u.c[0] = all_pa[i].u.c[1];
800 set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
801 set_default_xvg_format(xvg_format);
803 /* Now parse all the command-line options */
804 get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
806 /* set program name, command line, and default values for output options */
807 output_env_init(*oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
808 (xvg_format_t)nenum(xvg_format), verbose_level, debug_level);
812 printf("Program: %s\n", output_env_get_program_name(*oenv));
813 gmx_print_version_info(stdout);
818 if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
820 set_default_file_name(deffnm);
823 /* Parse the file args */
824 parse_file_args(argc, argv, nfile, fnm, FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
826 /* Open the debug file */
831 if (gmx_mpi_initialized())
833 sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
838 sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
841 init_debug(debug_level, buf);
842 fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
843 buf, __FILE__, __LINE__);
846 /* Now copy the results back... */
847 for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
849 memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
853 for (i = 0; (i < npall); i++)
855 all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
858 bExit = bHelp || (strcmp(manstr[0], "no") != 0);
860 #if (defined __sgi && USE_SGI_FPE)
864 /* Set the nice level */
866 if (npri != 0 && !bExit)
868 schedctl(MPTS_RTPRI, 0, npri);
875 /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
876 if (nicelevel != 0 && !bExit)
878 #ifdef GMX_THREAD_MPI
879 static gmx_bool nice_set = FALSE; /* only set it once */
880 tMPI_Thread_mutex_lock(&init_mutex);
884 i = nice(nicelevel); /* assign ret value to avoid warnings */
885 #ifdef GMX_THREAD_MPI
888 tMPI_Thread_mutex_unlock(&init_mutex);
894 /* Update oenv for parsed command line options settings. */
895 (*oenv)->xvg_format = (xvg_format_t)nenum(xvg_format);
896 (*oenv)->time_unit = (time_unit_t)nenum(time_units);
898 if (!(FF(PCA_QUIET) || bQuiet ))
902 write_man(stderr, "help", output_env_get_program_name(*oenv),
903 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
907 pr_fns(stderr, nfile, fnm);
908 print_pargs(stderr, npall, all_pa, FALSE);
912 if (strcmp(manstr[0], "no") != 0)
914 if (!strcmp(manstr[0], "completion"))
916 /* one file each for csh, bash and zsh if we do completions */
917 fp = man_file(*oenv, "completion-zsh");
919 write_man(fp, "completion-zsh", output_env_get_program_name(*oenv),
920 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
922 fp = man_file(*oenv, "completion-bash");
923 write_man(fp, "completion-bash", output_env_get_program_name(*oenv),
924 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
926 fp = man_file(*oenv, "completion-csh");
927 write_man(fp, "completion-csh", output_env_get_program_name(*oenv),
928 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
933 fp = man_file(*oenv, manstr[0]);
934 write_man(fp, manstr[0], output_env_get_program_name(*oenv),
935 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
940 /* convert time options, must be done after printing! */
942 for (i = 0; i < npall; i++)
944 if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
946 *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
950 /* Extract Time info from arguments */
951 if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
953 setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
956 if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
958 setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
961 if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
963 setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
967 for (i = 0; i < npall; ++i)
969 sfree((void *)all_pa[i].desc);
973 if (!FF(PCA_NOEXIT_ON_ARGS))