4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Copyright (c) 1991-2001, University of Groningen, The Netherlands
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * If you want to redistribute modifications, please consider that
18 * scientific software is very special. Version control is crucial -
19 * bugs must be traceable. We will be happy to consider code for
20 * inclusion in the official distribution, but derived work must not
21 * be called official GROMACS. Details are found in the README & COPYING
22 * files - if they are missing, get the official version at www.gromacs.org.
24 * To help us fund GROMACS development, we humbly ask that you cite
25 * the papers on the package - you can find them in the top README file.
27 * For more info, check our website at http://www.gromacs.org
30 * Gnomes, ROck Monsters And Chili Sauce
56 #include <sys/schedctl.h>
57 #include <sys/sysmp.h>
60 /******************************************************************
62 * T R A J E C T O R Y S T U F F
64 ******************************************************************/
66 /* Globals for trajectory input */
70 real timefactor
= NOTSET
;
71 char *timelabel
= NULL
;
72 static char *timestr
[] = { NULL
, "fs", "ps", "ns", "us", "ms", "s",
74 real timefactors
[] = { 0, 1e3
, 1, 1e-3, 1e-6, 1e-9, 1e-12,
75 (1.0/60.0)*1e-12, (1.0/3600.0)*1e-12, 0 };
76 static char *xvgrtimestr
[] = { NULL
, "fs", "ps", "ns", "\\8m\\4s", "ms", "s",
78 static bool bView
=FALSE
;
79 static unsigned long uFlags
=0;
80 static char *program
=NULL
;
82 #define FF(arg) ((uFlags & arg)==arg)
84 char *ShortProgram(void)
89 if ((pr
=strrchr(program
,'/')) != NULL
)
106 void set_program_name(char *argvzero
)
108 /* When you run a dynamically linked program before installing
109 * it, libtool uses wrapper scripts and prefixes the name with "lt-".
110 * Until libtool is fixed to set argv[0] right, rip away the prefix:
113 if(strlen(argvzero
)>3 && !strncmp(argvzero
,"lt-",3))
114 program
= strdup(argvzero
+3);
116 program
= strdup(argvzero
);
120 /****************************************************************
122 * E X P O R T E D F U N C T I O N S
124 ****************************************************************/
126 bool bRmod(double a
,double b
)
131 tol
= 5*GMX_REAL_EPS
;
133 iq
= ((1.0+tol
)*a
)/b
;
135 if (fabs(a
-b
*iq
) <= tol
*fabs(a
))
141 int check_times2(real t
,real t0
,real tp
, real tpp
)
146 if (t
-tp
>0 && tp
-tpp
>0)
147 margin
= 0.1*min(t
-tp
,tp
-tpp
);
152 if ((((tbegin
>= 0.0) && (t
>= tbegin
)) || (tbegin
== -1.0)) &&
153 (((tend
>= 0.0) && (t
<= tend
+margin
)) || (tend
== -1.0))) {
154 if (tdelta
> 0 && !bRmod(t
-t0
,tdelta
))
159 else if ((tend
!= -1.0) && (t
>=tend
))
161 if (debug
) fprintf(debug
,"t=%g, t0=%g, b=%g, e=%g, dt=%g: r=%d\n",
162 t
,t0
,tbegin
,tend
,tdelta
,r
);
166 int check_times(real t
)
168 return check_times2(t
,t
,t
,t
);
171 char *time_unit(void)
176 char *time_label(void)
178 static char label
[20];
180 sprintf(label
,"Time (%s)",timestr
[0] ? timestr
[0] : "ps");
185 char *xvgr_tlabel(void)
187 static char label
[20];
189 sprintf(label
,"Time (%s)",
190 nenum(timestr
) ? xvgrtimestr
[nenum(timestr
)] : "ps");
195 static void init_time_factor()
197 if (timefactor
== NOTSET
)
198 timefactor
= timefactors
[nenum(timestr
)];
201 real
time_factor(void)
208 real
convert_time(real time
)
212 return (time
*timefactor
);
216 void convert_times(int n
, real
*time
)
224 time
[i
] *= timefactor
;
227 void default_time(void)
229 timestr
[0] = timestr
[1];
230 timefactor
= timefactors
[1];
231 xvgrtimestr
[0] = xvgrtimestr
[1];
234 static void set_default_time_unit(char *select
)
239 while(timestr
[i
] && strcmp(timestr
[i
], select
)!=0)
241 if (strcmp(timestr
[i
], select
)==0) {
242 timestr
[0] = timestr
[i
];
243 timefactors
[0] = timefactors
[i
];
244 xvgrtimestr
[0] = xvgrtimestr
[i
];
246 timestr
[j
]=timestr
[j
-1];
247 timefactors
[j
]=timefactors
[j
-1];
248 xvgrtimestr
[j
]=xvgrtimestr
[j
-1];
250 timestr
[1]=timestr
[0];
251 timefactors
[1]=timefactors
[0];
252 xvgrtimestr
[1]=xvgrtimestr
[0];
256 /***** T O P O L O G Y S T U F F ******/
258 t_topology
*read_top(char *fn
)
265 read_tpx(fn
,&step
,&t
,&lambda
,NULL
,NULL
,
266 &natoms
,NULL
,NULL
,NULL
,top
);
271 void mk_single_top(t_topology
*top
)
275 for(i
=0; (i
<ebNR
); i
++)
276 top
->blocks
[i
].multinr
[0]=top
->blocks
[i
].multinr
[MAXNODES
-1];
277 for(i
=0; (i
<F_NRE
); i
++)
278 top
->idef
.il
[i
].multinr
[0]=top
->idef
.il
[i
].multinr
[MAXNODES
-1];
281 /*************************************************************
283 * P A R S I N G S T U F F
285 *************************************************************/
287 static void usage(char *type
,char *arg
)
290 fatal_error(0,"Expected %s argument for option %s\n",type
,arg
);
293 int iscan(int argc
,char *argv
[],int *i
)
298 if (!sscanf(argv
[++(*i
)],"%d",&var
))
299 usage("an integer",argv
[(*i
)-1]);
301 usage("an integer",argv
[*i
]);
306 double dscan(int argc
,char *argv
[],int *i
)
311 if (!sscanf(argv
[++(*i
)],"%lf",&var
))
312 usage("a real",argv
[(*i
)-1]);
314 usage("a real",argv
[*i
]);
319 char *sscan(int argc
,char *argv
[],int *i
)
322 if ( (argv
[(*i
)+1][0]=='-') && (argc
> (*i
)+2) && (argv
[(*i
)+2][0]!='-') )
323 fprintf(stderr
,"Possible missing string argument for option %s\n\n",
326 usage("a string",argv
[*i
]);
331 int nenum(char *enumc
[])
336 /* we *can* compare pointers directly here! */
337 while(enumc
[i
] && enumc
[0]!=enumc
[i
])
343 static void pdesc(char *desc
)
348 if ((int)strlen(ptr
) < 70)
349 fprintf(stderr
,"\t%s\n",ptr
);
351 for(nptr
=ptr
+70; (nptr
!= ptr
) && (!isspace(*nptr
)); nptr
--)
354 fprintf(stderr
,"\t%s\n",ptr
);
358 fprintf(stderr
,"\t%s\n",ptr
);
369 static FILE *man_file(char *program
,char *mantp
)
374 if ((pr
=strrchr(program
,'/')) == NULL
)
379 if (strcmp(mantp
,"ascii") != 0)
380 sprintf(buf
,"%s.%s",pr
,mantp
);
382 sprintf(buf
,"%s.txt",pr
);
383 fp
= ffopen(buf
,"w");
388 static int add_parg(int npargs
,t_pargs
**pa
,t_pargs
*pa_add
)
390 srenew((*pa
),npargs
+1);
391 memcpy(&((*pa
)[npargs
]),pa_add
,sizeof(*pa_add
));
396 static char *mk_desc(t_pargs
*pa
, char *time_unit_str
)
398 char *newdesc
=NULL
,*ndesc
=NULL
,*ptr
=NULL
;
401 /* First compute length for description */
402 len
= strlen(pa
->desc
)+1;
403 if ((ptr
= strstr(pa
->desc
,"HIDDEN")) != NULL
)
405 if (pa
->type
== etENUM
) {
407 for(k
=1; (pa
->u
.c
[k
] != NULL
); k
++) {
408 len
+= strlen(pa
->u
.c
[k
])+12;
413 /* add label for hidden options */
415 sprintf(newdesc
,"[hidden] %s",ptr
+6);
417 strcpy(newdesc
,pa
->desc
);
419 /* change '%t' into time_unit */
420 #define TUNITLABEL "%t"
421 #define NTUNIT strlen(TUNITLABEL)
422 if (pa
->type
== etTIME
)
423 while( (ptr
=strstr(newdesc
,TUNITLABEL
)) != NULL
) {
426 len
+=strlen(time_unit_str
)-NTUNIT
;
428 strcpy(ndesc
,newdesc
);
429 strcat(ndesc
,time_unit_str
);
438 /* Add extra comment for enumerateds */
439 if (pa
->type
== etENUM
) {
440 strcat(newdesc
,": ");
441 for(k
=1; (pa
->u
.c
[k
] != NULL
); k
++) {
442 strcat(newdesc
,"[TT]");
443 strcat(newdesc
,pa
->u
.c
[k
]);
444 strcat(newdesc
,"[tt]");
445 /* Print a comma everywhere but at the last one */
446 if (pa
->u
.c
[k
+1] != NULL
) {
447 if (pa
->u
.c
[k
+2] == NULL
)
448 strcat(newdesc
," or ");
450 strcat(newdesc
,", ");
457 void parse_common_args(int *argc
,char *argv
[],unsigned long Flags
,
458 int nfile
,t_filenm fnm
[],int npargs
,t_pargs
*pa
,
459 int ndesc
,char **desc
,int nbugs
,char **bugs
)
461 static bool bHelp
=FALSE
,bHidden
=FALSE
,bQuiet
=FALSE
;
462 static char *manstr
[] = { NULL
, "no", "html", "tex", "nroff", "ascii", "completion", NULL
};
463 static char *not_nicestr
[] = { NULL
, "0", "4", "10", "19", NULL
};
464 static char *nicestr
[] = { NULL
, "19", "10", "4", "0", NULL
};
465 static char *not_npristr
[] = { NULL
, "0", "128", "100", "200", "250", NULL
};
466 static char *npristr
[] = { NULL
, "128", "250", "200", "100", "0", NULL
};
467 static int nicelevel
=0,mantp
=0,npri
=0;
468 static bool bGUI
=FALSE
,bDebug
=FALSE
;
469 static char *deffnm
=NULL
;
477 t_pargs
*all_pa
=NULL
;
479 t_pargs motif_pa
= { "-X", FALSE
, etBOOL
, {&bGUI
},
480 "Use dialog box GUI to edit command line options" };
481 t_pargs npri_paX
= { "-npri", FALSE
, etENUM
, {not_npristr
},
482 "Set non blocking priority" };
483 t_pargs npri_pa
= { "-npri", FALSE
, etINT
, {&npri
},
484 "HIDDEN Set non blocking priority (try 128)" };
485 t_pargs nice_paX
= { "-nice", FALSE
, etENUM
, {not_nicestr
},
486 "Set the nicelevel" };
487 t_pargs nice_pa
= { "-nice", FALSE
, etINT
, {&nicelevel
},
488 "Set the nicelevel" };
489 t_pargs deffnm_pa
= { "-deffnm", FALSE
, etSTR
, {&deffnm
},
490 "Set the default filename for all file options" };
491 t_pargs begin_pa
= { "-b", FALSE
, etTIME
, {&tbegin
},
492 "First frame (%t) to read from trajectory" };
493 t_pargs end_pa
= { "-e", FALSE
, etTIME
, {&tend
},
494 "Last frame (%t) to read from trajectory" };
495 t_pargs dt_pa
= { "-dt", FALSE
, etTIME
, {&tdelta
},
496 "Only use frame when t MOD dt = first time (%t)" };
497 t_pargs view_pa
= { "-w", FALSE
, etBOOL
, {&bView
},
498 "View output xvg, xpm, eps and pdb files" };
499 t_pargs time_pa
= { "-tu", FALSE
, etENUM
, {timestr
},
503 { "-h", FALSE
, etBOOL
, {&bHelp
},
504 "Print help info and quit" },
505 { "-hidden", FALSE
, etBOOL
, {&bHidden
},
506 "HIDDENPrint hidden options" },
507 { "-quiet",FALSE
, etBOOL
, {&bQuiet
},
508 "HIDDENDo not print help info" },
509 { "-man", FALSE
, etENUM
, {manstr
},
510 "HIDDENWrite manual and quit" },
511 { "-debug",FALSE
, etBOOL
, {&bDebug
},
512 "HIDDENWrite file with debug information" },
514 #define NPCA_PA asize(pca_pa)
518 fprintf(debug
,"PID=%d, argc = %d\n",gmx_node_id(),*argc
);
519 for(i
=0; (i
<*argc
); i
++)
520 fprintf(debug
,"PID=%d, argv[%d] = %s\n",gmx_node_id(),i
,argv
[i
]);
523 /* Check for double arguments */
524 for (i
=1; (i
<*argc
); i
++) {
525 if (argv
[i
] && (strlen(argv
[i
]) > 1) && (!isdigit(argv
[i
][1]))) {
526 for (j
=i
+1; (j
<*argc
); j
++) {
527 if ( (argv
[i
][0]=='-') && (argv
[j
][0]=='-') &&
528 (strcmp(argv
[i
],argv
[j
])==0) ) {
529 if (FF(PCA_NOEXIT_ON_ARGS
))
530 fprintf(stderr
,"Double command line argument %s\n",argv
[i
]);
532 fatal_error(0,"Double command line argument %s\n",argv
[i
]);
539 /* Handle the flags argument, which is a bit field
540 * The FF macro returns whether or not the bit is set
543 bPrint
= !FF(PCA_SILENT
);
545 /* Check whether we should have GUI or not */
547 bGUI
= (getenv("GMXMOTIF") != NULL
);
548 for(i
=1; (i
<*argc
); i
++) {
549 if (strcmp(argv
[i
],"-X") == 0)
551 else if (strcmp(argv
[i
],"-noX") == 0)
560 set_program_name(argv
[0]);
562 /* Check ALL the flags ... */
563 snew(all_pa
,NPCA_PA
+npargs
);
564 for(i
=npall
=0; (i
<NPCA_PA
); i
++)
565 npall
= add_parg(npall
,&(all_pa
),&(pca_pa
[i
]));
568 npall
= add_parg(npall
,&(all_pa
),&motif_pa
);
571 envstr
= getenv("GMXNPRIALL");
574 if (FF(PCA_BE_NICE
)) {
575 envstr
= getenv("GMXNPRI");
581 npri_paX
.u
.c
= npristr
;
582 npall
= add_parg(npall
,&(all_pa
),&npri_paX
);
585 npall
= add_parg(npall
,&(all_pa
),&npri_pa
);
589 /* Automatic nice or scheduling options */
591 nice_paX
.u
.c
= nicestr
;
592 npall
= add_parg(npall
,&(all_pa
),&nice_paX
);
597 npall
= add_parg(npall
,&(all_pa
),&nice_pa
);
600 if (FF(PCA_CAN_SET_DEFFNM
))
601 npall
= add_parg(npall
,&(all_pa
),&deffnm_pa
);
602 if (FF(PCA_CAN_BEGIN
))
603 npall
= add_parg(npall
,&(all_pa
),&begin_pa
);
605 npall
= add_parg(npall
,&(all_pa
),&end_pa
);
607 npall
= add_parg(npall
,&(all_pa
),&dt_pa
);
608 if (FF(PCA_TIME_UNIT
)) {
609 envstr
= getenv("GMXTIMEUNIT");
610 if ( envstr
== NULL
)
612 set_default_time_unit(envstr
);
613 npall
= add_parg(npall
,&(all_pa
),&time_pa
);
615 set_default_time_unit("ps");
616 if (FF(PCA_CAN_VIEW
))
617 npall
= add_parg(npall
,&(all_pa
),&view_pa
);
619 /* Now append the program specific arguments */
620 for(i
=0; (i
<npargs
); i
++)
621 npall
= add_parg(npall
,&(all_pa
),&(pa
[i
]));
623 /* set etENUM options to default */
624 for(i
=0; (i
<npall
); i
++)
625 if (all_pa
[i
].type
==etENUM
)
626 all_pa
[i
].u
.c
[0]=all_pa
[i
].u
.c
[1];
628 /* Now parse all the command-line options */
629 get_pargs(argc
,argv
,npall
,all_pa
,FF(PCA_KEEP_ARGS
));
631 if (FF(PCA_CAN_SET_DEFFNM
) && (deffnm
!=NULL
))
632 set_default_file_name(deffnm
);
634 /* Parse the file args */
635 parse_file_args(argc
,argv
,nfile
,fnm
,FF(PCA_KEEP_ARGS
));
637 /* Open the debug file */
641 if (gmx_node_num() > 1)
642 sprintf(buf
,"%s%d.log",ShortProgram(),gmx_node_id());
644 sprintf(buf
,"%s.log",ShortProgram());
647 fprintf(debug
,"%s (this file) opened in file %s, line %d\n",
648 buf
,__FILE__
,__LINE__
);
651 /* Now we have parsed the command line arguments. If the user wants it
652 * we can now plop up a GUI dialog box to edit options.
656 gmx_gui(argc
,argv
,nfile
,fnm
,npall
,all_pa
,ndesc
,desc
,nbugs
,bugs
);
658 fatal_error(0,"GROMACS compiled without MOTIF support - can't use X interface");
662 /* Now copy the results back... */
663 for(i
=0,k
=npall
-npargs
; (i
<npargs
); i
++,k
++)
664 memcpy(&(pa
[i
]),&(all_pa
[k
]),(size_t)sizeof(pa
[i
]));
666 for(i
=0; (i
<npall
); i
++)
667 all_pa
[i
].desc
= mk_desc(&(all_pa
[i
]), time_unit() );
669 bExit
= bHelp
|| (strcmp(manstr
[0],"no") != 0);
671 #if (defined __sgi && USE_SGI_FPE)
675 /* Set the nice level */
679 sscanf(npristr
[0],"%d",&npri
);
681 sscanf(not_npristr
[0],"%d",&npri
);
682 if (npri
!= 0 && !bExit
) {
683 (void) schedctl(MPTS_RTPRI
,0,npri
);
691 sscanf(nicestr
[0],"%d",&nicelevel
);
693 sscanf(not_nicestr
[0],"%d",&nicelevel
);
695 if (nicelevel
!= 0 && !bExit
)
699 if (!(FF(PCA_QUIET
) || bQuiet
)) {
701 write_man(stderr
,"help",program
,ndesc
,desc
,nfile
,fnm
,npall
,all_pa
,
704 pr_fns(stderr
,nfile
,fnm
);
705 print_pargs(stderr
,npall
,all_pa
);
709 if (strcmp(manstr
[0],"no") != 0) {
710 if(!strcmp(manstr
[0],"completion")) {
711 /* one file each for csh, bash and zsh if we do completions */
712 fp
=man_file(program
,"completion-zsh");
713 write_man(fp
,"completion-zsh",program
,ndesc
,desc
,nfile
,fnm
,npall
,all_pa
,nbugs
,bugs
,bHidden
);
715 fp
=man_file(program
,"completion-bash");
716 write_man(fp
,"completion-bash",program
,ndesc
,desc
,nfile
,fnm
,npall
,all_pa
,nbugs
,bugs
,bHidden
);
718 fp
=man_file(program
,"completion-csh");
719 write_man(fp
,"completion-csh",program
,ndesc
,desc
,nfile
,fnm
,npall
,all_pa
,nbugs
,bugs
,bHidden
);
722 fp
=man_file(program
,manstr
[0]);
723 write_man(fp
,manstr
[0],program
,ndesc
,desc
,nfile
,fnm
,npall
,all_pa
,nbugs
,bugs
,bHidden
);
728 /* convert time options, must be done after printing! */
730 for(i
=0; i
<npall
; i
++) {
731 if ((all_pa
[i
].type
== etTIME
) && (*all_pa
[i
].u
.r
>= 0)) {
732 *all_pa
[i
].u
.r
/= timefactor
;
737 for(i
=0; i
<npall
; i
++)
738 sfree(all_pa
[i
].desc
);
741 if (!FF(PCA_NOEXIT_ON_ARGS
)) {
743 for(i
=1; (i
<*argc
); i
++)
744 fprintf(stderr
,"Unknown argument: %s\n",argv
[i
]);
745 fatal_error(0,"Program %s halted",Program());
751 gmx_abort(gmx_node_id(),gmx_node_num(),0);