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
50 #include "gmx_fatal.h"
54 #include "gromacs/onlinehelp/wman.h"
55 #include "gromacs/utility/exceptions.h"
56 #include "gromacs/utility/gmxassert.h"
57 #include "gromacs/utility/programinfo.h"
59 #include "thread_mpi/threads.h"
67 #include <sys/schedctl.h>
68 #include <sys/sysmp.h>
71 /* The source code in this file should be thread-safe.
72 Please keep it that way. */
74 /******************************************************************
76 * T R A J E C T O R Y S T U F F
78 ******************************************************************/
80 /****************************************************************
82 * E X P O R T E D F U N C T I O N S
84 ****************************************************************/
87 /* progam names, etc. */
89 const char *ShortProgram(void)
93 // TODO: Use the display name once it doesn't break anything.
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 /* utility functions */
110 gmx_bool bRmod_fd(double a, double b, double c, gmx_bool bDouble)
115 tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
117 iq = static_cast<int>((a - b + tol*a)/c);
119 if (std::fabs(a - b - c*iq) <= tol*std::fabs(a))
129 int check_times2(real t, real t0, gmx_bool bDouble)
134 /* since t is float, we can not use double precision for bRmod */
139 if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN))) &&
140 (!bTimeSet(TEND) || (t <= rTimeValue(TEND))))
142 if (bTimeSet(TDELTA) && !bRmod_fd(t, t0, rTimeValue(TDELTA), bDouble))
151 else if (bTimeSet(TEND) && (t >= rTimeValue(TEND)))
157 fprintf(debug, "t=%g, t0=%g, b=%g, e=%g, dt=%g: r=%d\n",
158 t, t0, rTimeValue(TBEGIN), rTimeValue(TEND), rTimeValue(TDELTA), r);
163 int check_times(real t)
165 return check_times2(t, t, FALSE);
171 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
174 const char *select = NULL;
178 select = getenv("GMXTIMEUNIT");
182 while (time_list[i] && strcmp(time_list[i], select) != 0)
188 if (!bCanTime || select == NULL ||
189 time_list[i] == NULL || strcmp(time_list[i], select) != 0)
191 /* Set it to the default: ps */
193 while (time_list[i] && strcmp(time_list[i], "ps") != 0)
199 time_list[0] = time_list[i];
203 static void set_default_xvg_format(const char *xvg_list[])
208 select = getenv("GMX_VIEW_XVG");
211 /* The default is the first option */
212 xvg_list[0] = xvg_list[1];
217 while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
221 if (xvg_list[i] != NULL)
223 xvg_list[0] = xvg_list[i];
227 xvg_list[0] = xvg_list[exvgNONE];
233 /***** T O P O L O G Y S T U F F ******/
235 t_topology *read_top(const char *fn, int *ePBC)
241 epbc = read_tpx_top(fn, NULL, NULL, &natoms, NULL, NULL, NULL, top);
250 /*************************************************************
252 * P A R S I N G S T U F F
254 *************************************************************/
256 static void usage(const char *type, const char *arg)
258 GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
259 gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
262 int iscan(int argc, char *argv[], int *i)
264 const char *const arg = argv[*i];
267 usage("an integer", arg);
269 const char *const value = argv[++(*i)];
271 int var = std::strtol(value, &endptr, 10);
272 if (*value == '\0' || *endptr != '\0')
274 usage("an integer", arg);
279 gmx_large_int_t istepscan(int argc, char *argv[], int *i)
281 const char *const arg = argv[*i];
284 usage("an integer", arg);
286 const char *const value = argv[++(*i)];
288 gmx_large_int_t var = str_to_large_int_t(value, &endptr);
289 if (*value == '\0' || *endptr != '\0')
291 usage("an integer", arg);
296 double dscan(int argc, char *argv[], int *i)
298 const char *const arg = argv[*i];
301 usage("a real", arg);
303 const char *const value = argv[++(*i)];
305 double var = std::strtod(value, &endptr);
306 if (*value == '\0' || *endptr != '\0')
308 usage("a real", arg);
313 char *sscan(int argc, char *argv[], int *i)
317 if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
318 (argv[(*i)+2][0] != '-') )
320 fprintf(stderr, "Possible missing string argument for option %s\n\n",
326 usage("a string", argv[*i]);
332 int nenum(const char *const enumc[])
337 /* we *can* compare pointers directly here! */
338 while (enumc[i] && enumc[0] != enumc[i])
346 static void pdesc(char *desc)
351 if ((int)strlen(ptr) < 70)
353 fprintf(stderr, "\t%s\n", ptr);
357 for (nptr = ptr+70; (nptr != ptr) && (!std::isspace(*nptr)); nptr--)
363 fprintf(stderr, "\t%s\n", ptr);
369 fprintf(stderr, "\t%s\n", ptr);
375 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
377 memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
382 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
384 char *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
385 const char*ptr = NULL;
388 /* First compute length for description */
389 len = strlen(pa->desc)+1;
390 if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
394 if (pa->type == etENUM)
397 for (k = 1; (pa->u.c[k] != NULL); k++)
399 len += strlen(pa->u.c[k])+12;
404 /* add label for hidden options */
407 sprintf(newdesc, "[hidden] %s", ptr+6);
411 strcpy(newdesc, pa->desc);
414 /* change '%t' into time_unit */
415 #define TUNITLABEL "%t"
416 #define NTUNIT strlen(TUNITLABEL)
417 if (pa->type == etTIME)
419 while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
423 len += strlen(time_unit_str)-NTUNIT;
425 strcpy(ndesc, newdesc);
426 strcat(ndesc, time_unit_str);
436 /* Add extra comment for enumerateds */
437 if (pa->type == etENUM)
439 strcat(newdesc, ": ");
440 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)
448 if (pa->u.c[k+2] == NULL)
450 strcat(newdesc, " or ");
454 strcat(newdesc, ", ");
463 gmx_bool parse_common_args(int *argc, char *argv[], unsigned long Flags,
464 int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
465 int ndesc, const char **desc,
466 int nbugs, const char **bugs,
469 const char *manstr[] = {
470 NULL, "no", "help", "html", "nroff", "completion", NULL
472 /* This array should match the order of the enum in oenv.h */
473 const char *xvg_format[] = { NULL, "xmgrace", "xmgr", "none", NULL };
474 /* This array should match the order of the enum in oenv.h */
475 const char *time_units[] = {
476 NULL, "fs", "ps", "ns", "us", "ms", "s",
479 int nicelevel = 0, debug_level = 0;
481 real tbegin = 0, tend = 0, tdelta = 0;
482 gmx_bool bView = FALSE;
484 t_pargs *all_pa = NULL;
489 "-npri", FALSE, etINT, {&npri},
490 "HIDDEN Set non blocking priority (try 128)"
494 "-nice", FALSE, etINT, {&nicelevel},
497 t_pargs deffnm_pa = {
498 "-deffnm", FALSE, etSTR, {&deffnm},
499 "Set the default filename for all file options"
502 "-b", FALSE, etTIME, {&tbegin},
503 "First frame (%t) to read from trajectory"
506 "-e", FALSE, etTIME, {&tend},
507 "Last frame (%t) to read from trajectory"
510 "-dt", FALSE, etTIME, {&tdelta},
511 "Only use frame when t MOD dt = first time (%t)"
514 "-w", FALSE, etBOOL, {&bView},
515 "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
518 "-xvg", FALSE, etENUM, {xvg_format},
519 "xvg plot formatting"
522 "-tu", FALSE, etENUM, {time_units},
525 /* Maximum number of extra arguments */
529 { "-man", FALSE, etENUM, {manstr},
530 "HIDDENWrite manual and quit" },
531 { "-debug", FALSE, etINT, {&debug_level},
532 "HIDDENWrite file with debug information, 1: short, 2: also x and f" },
534 #define NPCA_PA asize(pca_pa)
535 gmx_bool bExit, bXvgr;
536 int i, j, k, npall, max_pa;
538 // Handle the flags argument, which is a bit field
539 // The FF macro returns whether or not the bit is set
540 #define FF(arg) ((Flags & arg) == arg)
542 /* Check for double arguments */
543 for (i = 1; (i < *argc); i++)
545 if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1])))
547 for (j = i+1; (j < *argc); j++)
549 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
550 (strcmp(argv[i], argv[j]) == 0) )
552 if (FF(PCA_NOEXIT_ON_ARGS))
554 fprintf(stderr, "Double command line argument %s\n",
559 gmx_fatal(FARGS, "Double command line argument %s\n",
568 /* Check ALL the flags ... */
569 max_pa = NPCA_PA + EXTRA_PA + npargs+1;
570 snew(all_pa, max_pa);
572 for (i = npall = 0; (i < static_cast<int>(NPCA_PA)); i++)
574 npall = add_parg(npall, all_pa, &(pca_pa[i]));
578 const char *envstr = getenv("GMXNPRIALL");
581 npri = strtol(envstr, NULL, 10);
585 envstr = getenv("GMXNPRI");
588 npri = strtol(envstr, NULL, 10);
591 npall = add_parg(npall, all_pa, &npri_pa);
598 npall = add_parg(npall, all_pa, &nice_pa);
600 if (FF(PCA_CAN_SET_DEFFNM))
602 npall = add_parg(npall, all_pa, &deffnm_pa);
604 if (FF(PCA_CAN_BEGIN))
606 npall = add_parg(npall, all_pa, &begin_pa);
610 npall = add_parg(npall, all_pa, &end_pa);
614 npall = add_parg(npall, all_pa, &dt_pa);
616 if (FF(PCA_TIME_UNIT))
618 npall = add_parg(npall, all_pa, &time_pa);
620 if (FF(PCA_CAN_VIEW))
622 npall = add_parg(npall, all_pa, &view_pa);
626 for (i = 0; (i < nfile); i++)
628 bXvgr = bXvgr || (fnm[i].ftp == efXVG);
632 npall = add_parg(npall, all_pa, &xvg_pa);
635 /* Now append the program specific arguments */
636 for (i = 0; (i < npargs); i++)
638 npall = add_parg(npall, all_pa, &(pa[i]));
641 /* set etENUM options to default */
642 for (i = 0; (i < npall); i++)
644 if (all_pa[i].type == etENUM)
646 all_pa[i].u.c[0] = all_pa[i].u.c[1];
649 set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
650 set_default_xvg_format(xvg_format);
652 /* Now parse all the command-line options */
653 get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
655 /* set program name, command line, and default values for output options */
656 output_env_init(oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
657 (xvg_format_t)nenum(xvg_format), 0, debug_level);
659 if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
661 set_default_file_name(deffnm);
664 /* Parse the file args */
665 parse_file_args(argc, argv, nfile, fnm, FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
667 /* Open the debug file */
672 if (gmx_mpi_initialized())
674 sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
679 sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
682 init_debug(debug_level, buf);
683 fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
684 buf, __FILE__, __LINE__);
687 /* Now copy the results back... */
688 for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
690 memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
694 for (i = 0; (i < npall); i++)
696 all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
700 GMX_ASSERT(manstr[0] != NULL,
701 "Enum option default assignment should have changed this");
702 bExit = (strcmp(manstr[0], "no") != 0);
704 #if (defined __sgi && USE_SGI_FPE)
708 /* Set the nice level */
710 if (npri != 0 && !bExit)
712 schedctl(MPTS_RTPRI, 0, npri);
718 /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
719 if (nicelevel != 0 && !bExit)
721 static gmx_bool nice_set = FALSE; /* only set it once */
722 static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
723 tMPI_Thread_mutex_lock(&init_mutex);
726 if (nice(nicelevel) == -1)
728 /* Do nothing, but use the return value to avoid warnings. */
732 tMPI_Thread_mutex_unlock(&init_mutex);
737 if (strcmp(manstr[0], "no") != 0 && !(FF(PCA_QUIET)))
739 if (!strcmp(manstr[0], "completion"))
741 /* one file each for csh, bash and zsh if we do completions */
742 write_man("completion-zsh", output_env_get_short_program_name(*oenv),
743 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
744 write_man("completion-bash", output_env_get_short_program_name(*oenv),
745 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
746 write_man("completion-csh", output_env_get_short_program_name(*oenv),
747 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
751 write_man(manstr[0], output_env_get_short_program_name(*oenv),
752 ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs);
756 /* convert time options, must be done after printing! */
758 for (i = 0; i < npall; i++)
760 if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
762 *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
766 /* Extract Time info from arguments */
767 if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
769 setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
772 if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
774 setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
777 if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
779 setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
783 for (i = 0; i < npall; ++i)
785 sfree((void *)all_pa[i].desc);
789 if (!FF(PCA_NOEXIT_ON_ARGS))