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, 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)
105 #ifdef GMX_THREAD_MPI
106 tMPI_Thread_mutex_lock(&init_mutex);
109 #ifdef GMX_THREAD_MPI
110 tMPI_Thread_mutex_unlock(&init_mutex);
112 if ((pr=strrchr(ret,DIR_SEPARATOR)) != NULL)
117 const char *Program(void)
120 #ifdef GMX_THREAD_MPI
121 tMPI_Thread_mutex_lock(&init_mutex);
124 #ifdef GMX_THREAD_MPI
125 tMPI_Thread_mutex_unlock(&init_mutex);
130 const char *command_line(void)
133 #ifdef GMX_THREAD_MPI
134 tMPI_Thread_mutex_lock(&init_mutex);
137 #ifdef GMX_THREAD_MPI
138 tMPI_Thread_mutex_unlock(&init_mutex);
143 void set_program_name(const char *argvzero)
145 #ifdef GMX_THREAD_MPI
146 tMPI_Thread_mutex_lock(&init_mutex);
148 if (program_name == NULL)
150 /* if filename has file ending (e.g. .exe) then strip away */
151 char* extpos=strrchr(argvzero,'.');
152 if(extpos > strrchr(argvzero,DIR_SEPARATOR))
154 program_name=gmx_strndup(argvzero,extpos-argvzero);
158 program_name=gmx_strdup(argvzero);
161 if (program_name == NULL)
162 program_name="GROMACS";
163 #ifdef GMX_THREAD_MPI
164 tMPI_Thread_mutex_unlock(&init_mutex);
169 void set_command_line(int argc, char *argv[])
174 #ifdef GMX_THREAD_MPI
175 tMPI_Thread_mutex_lock(&init_mutex);
179 cmdlength = strlen(argv[0]);
180 for (i=1; i<argc; i++)
182 cmdlength += strlen(argv[i]);
185 /* Fill the cmdline string */
186 snew(cmd_line,cmdlength+argc+1);
187 for (i=0; i<argc; i++)
189 strcat(cmd_line,argv[i]);
190 strcat(cmd_line," ");
193 #ifdef GMX_THREAD_MPI
194 tMPI_Thread_mutex_unlock(&init_mutex);
199 /* utility functions */
201 gmx_bool bRmod_fd(double a, double b, double c, gmx_bool bDouble)
206 tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
208 iq = (a - b + tol*a)/c;
210 if (fabs(a - b - c*iq) <= tol*fabs(a))
216 int check_times2(real t,real t0,real tp, real tpp, gmx_bool bDouble)
222 /* since t is float, we can not use double precision for bRmod */
226 if (t-tp>0 && tp-tpp>0)
227 margin = 0.1*min(t-tp,tp-tpp);
232 if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN))) &&
233 (!bTimeSet(TEND) || (t <= rTimeValue(TEND)))) {
234 if (bTimeSet(TDELTA) && !bRmod_fd(t,t0,rTimeValue(TDELTA),bDouble))
239 else if (bTimeSet(TEND) && (t >= rTimeValue(TEND)))
242 fprintf(debug,"t=%g, t0=%g, b=%g, e=%g, dt=%g: r=%d\n",
243 t,t0,rTimeValue(TBEGIN),rTimeValue(TEND),rTimeValue(TDELTA),r);
247 int check_times(real t)
249 return check_times2(t,t,t,t,FALSE);
255 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
258 const char *select = NULL;
262 select = getenv("GMXTIMEUNIT");
266 while(time_list[i] && strcmp(time_list[i], select) != 0)
272 if (!bCanTime || select == NULL ||
273 time_list[i]==NULL || strcmp(time_list[i], select) != 0)
275 /* Set it to the default: ps */
277 while(time_list[i] && strcmp(time_list[i], "ps") != 0)
283 time_list[0] = time_list[i];
287 static void set_default_xvg_format(const char *xvg_list[])
290 const char *select,*tmp;
292 select = getenv("GMX_VIEW_XVG");
295 /* The default is the first option */
296 xvg_list[0] = xvg_list[1];
301 while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
305 if (xvg_list[i] != NULL)
307 xvg_list[0] = xvg_list[i];
311 xvg_list[0] = xvg_list[exvgNONE];
317 /***** T O P O L O G Y S T U F F ******/
319 t_topology *read_top(const char *fn,int *ePBC)
325 epbc = read_tpx_top(fn,NULL,NULL,&natoms,NULL,NULL,NULL,top);
332 /*************************************************************
334 * P A R S I N G S T U F F
336 *************************************************************/
338 static void usage(const char *type,const char *arg)
341 gmx_fatal(FARGS,"Expected %s argument for option %s\n",type,arg);
344 int iscan(int argc,char *argv[],int *i)
349 if (!sscanf(argv[++(*i)],"%d",&var))
350 usage("an integer",argv[(*i)-1]);
352 usage("an integer",argv[*i]);
357 gmx_large_int_t istepscan(int argc,char *argv[],int *i)
359 gmx_large_int_t var=0;
362 if (!sscanf(argv[++(*i)],gmx_large_int_pfmt,&var))
363 usage("an integer",argv[(*i)-1]);
365 usage("an integer",argv[*i]);
370 double dscan(int argc,char *argv[],int *i)
375 if (!sscanf(argv[++(*i)],"%lf",&var))
376 usage("a real",argv[(*i)-1]);
378 usage("a real",argv[*i]);
383 char *sscan(int argc,char *argv[],int *i)
387 if ( (argv[(*i)+1][0]=='-') && (argc > (*i)+2) &&
388 (argv[(*i)+2][0]!='-') )
390 fprintf(stderr,"Possible missing string argument for option %s\n\n",
395 usage("a string",argv[*i]);
400 int nenum(const char *const enumc[])
405 /* we *can* compare pointers directly here! */
406 while(enumc[i] && enumc[0]!=enumc[i])
412 static void pdesc(char *desc)
417 if ((int)strlen(ptr) < 70)
418 fprintf(stderr,"\t%s\n",ptr);
420 for(nptr=ptr+70; (nptr != ptr) && (!isspace(*nptr)); nptr--)
423 fprintf(stderr,"\t%s\n",ptr);
427 fprintf(stderr,"\t%s\n",ptr);
433 static FILE *man_file(const output_env_t oenv,const char *mantp)
437 const char *pr = output_env_get_short_program_name(oenv);
439 if (strcmp(mantp,"ascii") != 0)
440 sprintf(buf,"%s.%s",pr,mantp);
442 sprintf(buf,"%s.txt",pr);
443 fp = gmx_fio_fopen(buf,"w");
448 static int add_parg(int npargs,t_pargs *pa,t_pargs *pa_add)
450 memcpy(&(pa[npargs]),pa_add,sizeof(*pa_add));
455 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
457 char *newdesc=NULL,*ndesc=NULL,*nptr=NULL;
461 /* First compute length for description */
462 len = strlen(pa->desc)+1;
463 if ((ptr = strstr(pa->desc,"HIDDEN")) != NULL)
465 if (pa->type == etENUM) {
467 for(k=1; (pa->u.c[k] != NULL); k++) {
468 len += strlen(pa->u.c[k])+12;
473 /* add label for hidden options */
475 sprintf(newdesc,"[hidden] %s",ptr+6);
477 strcpy(newdesc,pa->desc);
479 /* change '%t' into time_unit */
480 #define TUNITLABEL "%t"
481 #define NTUNIT strlen(TUNITLABEL)
482 if (pa->type == etTIME)
483 while( (nptr=strstr(newdesc,TUNITLABEL)) != NULL ) {
486 len+=strlen(time_unit_str)-NTUNIT;
488 strcpy(ndesc,newdesc);
489 strcat(ndesc,time_unit_str);
498 /* Add extra comment for enumerateds */
499 if (pa->type == etENUM) {
500 strcat(newdesc,": ");
501 for(k=1; (pa->u.c[k] != NULL); k++) {
502 strcat(newdesc,"[TT]");
503 strcat(newdesc,pa->u.c[k]);
504 strcat(newdesc,"[tt]");
505 /* Print a comma everywhere but at the last one */
506 if (pa->u.c[k+1] != NULL) {
507 if (pa->u.c[k+2] == NULL)
508 strcat(newdesc," or ");
510 strcat(newdesc,", ");
518 void parse_common_args(int *argc,char *argv[],unsigned long Flags,
519 int nfile,t_filenm fnm[],int npargs,t_pargs *pa,
520 int ndesc,const char **desc,
521 int nbugs,const char **bugs,
524 gmx_bool bHelp=FALSE,bHidden=FALSE,bQuiet=FALSE,bVersion=FALSE;
525 const char *manstr[] = { NULL, "no", "html", "tex", "nroff", "ascii",
526 "completion", "py", "xml", "wiki", NULL };
527 /* This array should match the order of the enum in oenv.h */
528 const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
529 /* This array should match the order of the enum in oenv.h */
530 const char *time_units[] = { NULL, "fs", "ps", "ns", "us", "ms", "s",
532 int nicelevel=0,mantp=0,npri=0,debug_level=0,verbose_level=0;
534 real tbegin=0,tend=0,tdelta=0;
535 gmx_bool bView=FALSE;
537 t_pargs *all_pa=NULL;
539 t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri},
540 "HIDDEN Set non blocking priority (try 128)" };
541 t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel},
542 "Set the nicelevel" };
543 t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm},
544 "Set the default filename for all file options" };
545 t_pargs begin_pa = { "-b", FALSE, etTIME, {&tbegin},
546 "First frame (%t) to read from trajectory" };
547 t_pargs end_pa = { "-e", FALSE, etTIME, {&tend},
548 "Last frame (%t) to read from trajectory" };
549 t_pargs dt_pa = { "-dt", FALSE, etTIME, {&tdelta},
550 "Only use frame when t MOD dt = first time (%t)" };
551 t_pargs view_pa = { "-w", FALSE, etBOOL, {&bView},
552 "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files" };
553 t_pargs xvg_pa = { "-xvg", FALSE, etENUM, {xvg_format},
554 "xvg plot formatting" };
555 t_pargs time_pa = { "-tu", FALSE, etENUM, {time_units},
557 /* Maximum number of extra arguments */
561 { "-h", FALSE, etBOOL, {&bHelp},
562 "Print help info and quit" },
563 { "-version", FALSE, etBOOL, {&bVersion},
564 "Print version info and quit" },
565 { "-verb", FALSE, etINT, {&verbose_level},
566 "HIDDENLevel of verbosity for this program" },
567 { "-hidden", FALSE, etBOOL, {&bHidden},
568 "HIDDENPrint hidden options" },
569 { "-quiet",FALSE, etBOOL, {&bQuiet},
570 "HIDDENDo not print help info" },
571 { "-man", FALSE, etENUM, {manstr},
572 "HIDDENWrite manual and quit" },
573 { "-debug",FALSE, etINT, {&debug_level},
574 "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
576 #define NPCA_PA asize(pca_pa)
578 gmx_bool bPrint,bExit,bXvgr;
579 int i,j,k,npall,max_pa,cmdlength;
583 #define FF(arg) ((Flags & arg)==arg)
587 cmdlength = strlen(argv[0]);
588 /* Check for double arguments */
589 for (i=1; (i<*argc); i++)
591 cmdlength += strlen(argv[i]);
592 if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1])))
594 for (j=i+1; (j<*argc); j++)
596 if ( (argv[i][0]=='-') && (argv[j][0]=='-') &&
597 (strcmp(argv[i],argv[j])==0) )
599 if (FF(PCA_NOEXIT_ON_ARGS))
600 fprintf(stderr,"Double command line argument %s\n",
603 gmx_fatal(FARGS,"Double command line argument %s\n",
610 set_program_name(argv[0]);
611 set_command_line(*argc, argv);
613 /* Handle the flags argument, which is a bit field
614 * The FF macro returns whether or not the bit is set
616 bPrint = !FF(PCA_SILENT);
618 /* Check ALL the flags ... */
619 max_pa = NPCA_PA + EXTRA_PA + npargs+1;
622 for(i=npall=0; (i<NPCA_PA); i++)
623 npall = add_parg(npall,all_pa,&(pca_pa[i]));
626 envstr = getenv("GMXNPRIALL");
628 npri=strtol(envstr,NULL,10);
629 if (FF(PCA_BE_NICE)) {
630 envstr = getenv("GMXNPRI");
632 npri=strtol(envstr,NULL,10);
634 npall = add_parg(npall,all_pa,&npri_pa);
639 npall = add_parg(npall,all_pa,&nice_pa);
641 if (FF(PCA_CAN_SET_DEFFNM))
642 npall = add_parg(npall,all_pa,&deffnm_pa);
643 if (FF(PCA_CAN_BEGIN))
644 npall = add_parg(npall,all_pa,&begin_pa);
646 npall = add_parg(npall,all_pa,&end_pa);
649 npall = add_parg(npall,all_pa,&dt_pa);
651 if (FF(PCA_TIME_UNIT)) {
652 npall = add_parg(npall,all_pa,&time_pa);
654 if (FF(PCA_CAN_VIEW))
655 npall = add_parg(npall,all_pa,&view_pa);
658 for(i=0; (i<nfile); i++)
660 bXvgr = bXvgr || (fnm[i].ftp == efXVG);
664 npall = add_parg(npall,all_pa,&xvg_pa);
667 /* Now append the program specific arguments */
668 for(i=0; (i<npargs); i++)
669 npall = add_parg(npall,all_pa,&(pa[i]));
671 /* set etENUM options to default */
672 for(i=0; (i<npall); i++)
674 if (all_pa[i].type==etENUM)
676 all_pa[i].u.c[0]=all_pa[i].u.c[1];
679 set_default_time_unit(time_units,FF(PCA_TIME_UNIT));
680 set_default_xvg_format(xvg_format);
682 /* Now parse all the command-line options */
683 get_pargs(argc,argv,npall,all_pa,FF(PCA_KEEP_ARGS));
685 /* set program name, command line, and default values for output options */
686 output_env_init(*oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
687 (xvg_format_t)nenum(xvg_format), verbose_level, debug_level);
690 printf("Program: %s\n",output_env_get_program_name(*oenv));
691 gmx_print_version_info(stdout);
695 if (FF(PCA_CAN_SET_DEFFNM) && (deffnm!=NULL))
696 set_default_file_name(deffnm);
698 /* Parse the file args */
699 parse_file_args(argc,argv,nfile,fnm,FF(PCA_KEEP_ARGS),!FF(PCA_NOT_READ_NODE));
701 /* Open the debug file */
702 if (debug_level > 0) {
705 if (gmx_mpi_initialized())
706 sprintf(buf,"%s%d.debug",output_env_get_short_program_name(*oenv),
709 sprintf(buf,"%s.debug",output_env_get_short_program_name(*oenv));
711 init_debug(debug_level,buf);
712 fprintf(stderr,"Opening debug file %s (src code file %s, line %d)\n",
713 buf,__FILE__,__LINE__);
716 /* Now copy the results back... */
717 for(i=0,k=npall-npargs; (i<npargs); i++,k++)
718 memcpy(&(pa[i]),&(all_pa[k]),(size_t)sizeof(pa[i]));
721 for(i=0; (i<npall); i++)
722 all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
724 bExit = bHelp || (strcmp(manstr[0],"no") != 0);
726 #if (defined __sgi && USE_SGI_FPE)
730 /* Set the nice level */
732 if (npri != 0 && !bExit) {
733 schedctl(MPTS_RTPRI,0,npri);
740 /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
741 if (nicelevel != 0 && !bExit)
743 #ifdef GMX_THREAD_MPI
744 static gmx_bool nice_set=FALSE; /* only set it once */
745 tMPI_Thread_mutex_lock(&init_mutex);
749 i=nice(nicelevel); /* assign ret value to avoid warnings */
750 #ifdef GMX_THREAD_MPI
753 tMPI_Thread_mutex_unlock(&init_mutex);
759 /* Update oenv for parsed command line options settings. */
760 (*oenv)->xvg_format = (xvg_format_t)nenum(xvg_format);
761 (*oenv)->time_unit = (time_unit_t)nenum(time_units);
763 if (!(FF(PCA_QUIET) || bQuiet )) {
765 write_man(stderr,"help",output_env_get_program_name(*oenv),
766 ndesc,desc,nfile, fnm,npall,all_pa, nbugs,bugs,bHidden);
768 pr_fns(stderr,nfile,fnm);
769 print_pargs(stderr,npall,all_pa,FALSE);
773 if (strcmp(manstr[0],"no") != 0) {
774 if(!strcmp(manstr[0],"completion")) {
775 /* one file each for csh, bash and zsh if we do completions */
776 fp=man_file(*oenv,"completion-zsh");
778 write_man(fp,"completion-zsh",output_env_get_program_name(*oenv),
779 ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden);
781 fp=man_file(*oenv,"completion-bash");
782 write_man(fp,"completion-bash",output_env_get_program_name(*oenv),
783 ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden);
785 fp=man_file(*oenv,"completion-csh");
786 write_man(fp,"completion-csh",output_env_get_program_name(*oenv),
787 ndesc,desc,nfile, fnm, npall,all_pa,nbugs,bugs,bHidden);
790 fp=man_file(*oenv,manstr[0]);
791 write_man(fp,manstr[0],output_env_get_program_name(*oenv),
792 ndesc,desc,nfile,fnm, npall, all_pa,nbugs,bugs,bHidden);
797 /* convert time options, must be done after printing! */
799 for(i=0; i<npall; i++) {
800 if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0)) {
801 *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
805 /* Extract Time info from arguments */
806 if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b",npall,all_pa))
807 setTimeValue(TBEGIN,opt2parg_real("-b",npall,all_pa));
809 if (FF(PCA_CAN_END) && opt2parg_bSet("-e",npall,all_pa))
810 setTimeValue(TEND,opt2parg_real("-e",npall,all_pa));
812 if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt",npall,all_pa))
813 setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa));
816 for (i = 0; i < npall; ++i)
817 sfree((void *)all_pa[i].desc);
820 if (!FF(PCA_NOEXIT_ON_ARGS)) {