Properly finalize MPI on mdrun -version. Fixes #1313
[alexxy/gromacs.git] / src / gmxlib / statutil.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
11  *
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.
16  *
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.
21  *
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.
26  *
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.
34  *
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.
37  */
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42
43 #include <ctype.h>
44 #include <assert.h>
45 #include "copyrite.h"
46 #include "sysstuff.h"
47 #include "macros.h"
48 #include "string2.h"
49 #include "smalloc.h"
50 #include "pbc.h"
51 #include "statutil.h"
52 #include "names.h"
53 #include "vec.h"
54 #include "futil.h"
55 #include "wman.h"
56 #include "tpxio.h"
57 #include "gmx_fatal.h"
58 #include "network.h"
59 #include "vec.h"
60 #include "mtop_util.h"
61 #include "gmxfio.h"
62
63 #ifdef GMX_THREAD_MPI
64 #include "thread_mpi.h"
65 #endif
66
67 /* used for npri */
68 #ifdef __sgi
69 #include <sys/schedctl.h>
70 #include <sys/sysmp.h>
71 #endif
72
73 /* The source code in this file should be thread-safe.
74       Please keep it that way. */
75
76 /******************************************************************
77  *
78  *             T R A J E C T O R Y   S T U F F
79  *
80  ******************************************************************/
81
82 /* inherently globally shared names: */
83 static const char *program_name = NULL;
84 static char       *cmd_line     = NULL;
85
86 #ifdef GMX_THREAD_MPI
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;
90 #endif
91
92
93 /****************************************************************
94  *
95  *            E X P O R T E D   F U N C T I O N S
96  *
97  ****************************************************************/
98
99
100 /* progam names, etc. */
101
102 const char *ShortProgram(void)
103 {
104     const char *pr, *ret;
105 #ifdef GMX_THREAD_MPI
106     tMPI_Thread_mutex_lock(&init_mutex);
107 #endif
108     pr = ret = program_name;
109 #ifdef GMX_THREAD_MPI
110     tMPI_Thread_mutex_unlock(&init_mutex);
111 #endif
112     if ((pr = strrchr(ret, DIR_SEPARATOR)) != NULL)
113     {
114         ret = pr+1;
115     }
116     return ret;
117 }
118
119 const char *Program(void)
120 {
121     const char *ret;
122 #ifdef GMX_THREAD_MPI
123     tMPI_Thread_mutex_lock(&init_mutex);
124 #endif
125     ret = program_name;
126 #ifdef GMX_THREAD_MPI
127     tMPI_Thread_mutex_unlock(&init_mutex);
128 #endif
129     return ret;
130 }
131
132 const char *command_line(void)
133 {
134     const char *ret;
135 #ifdef GMX_THREAD_MPI
136     tMPI_Thread_mutex_lock(&init_mutex);
137 #endif
138     ret = cmd_line;
139 #ifdef GMX_THREAD_MPI
140     tMPI_Thread_mutex_unlock(&init_mutex);
141 #endif
142     return ret;
143 }
144
145 void set_program_name(const char *argvzero)
146 {
147 #ifdef GMX_THREAD_MPI
148     tMPI_Thread_mutex_lock(&init_mutex);
149 #endif
150     if (program_name == NULL)
151     {
152         /* if filename has file ending (e.g. .exe) then strip away */
153         char* extpos = strrchr(argvzero, '.');
154         if (extpos > strrchr(argvzero, DIR_SEPARATOR))
155         {
156             program_name = gmx_strndup(argvzero, extpos-argvzero);
157         }
158         else
159         {
160             program_name = gmx_strdup(argvzero);
161         }
162     }
163     if (program_name == NULL)
164     {
165         program_name = "GROMACS";
166     }
167 #ifdef GMX_THREAD_MPI
168     tMPI_Thread_mutex_unlock(&init_mutex);
169 #endif
170 }
171
172
173 void set_command_line(int argc, char *argv[])
174 {
175     int    i;
176     size_t cmdlength;
177
178 #ifdef GMX_THREAD_MPI
179     tMPI_Thread_mutex_lock(&init_mutex);
180 #endif
181     if (cmd_line == NULL)
182     {
183         cmdlength = strlen(argv[0]);
184         for (i = 1; i < argc; i++)
185         {
186             cmdlength += strlen(argv[i]);
187         }
188
189         /* Fill the cmdline string */
190         snew(cmd_line, cmdlength+argc+1);
191         for (i = 0; i < argc; i++)
192         {
193             strcat(cmd_line, argv[i]);
194             strcat(cmd_line, " ");
195         }
196     }
197 #ifdef GMX_THREAD_MPI
198     tMPI_Thread_mutex_unlock(&init_mutex);
199 #endif
200
201 }
202
203 /* utility functions */
204
205 gmx_bool bRmod_fd(double a, double b, double c, gmx_bool bDouble)
206 {
207     int    iq;
208     double tol;
209
210     tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
211
212     iq = (a - b + tol*a)/c;
213
214     if (fabs(a - b - c*iq) <= tol*fabs(a))
215     {
216         return TRUE;
217     }
218     else
219     {
220         return FALSE;
221     }
222 }
223
224 int check_times2(real t, real t0, real tp, real tpp, gmx_bool bDouble)
225 {
226     int  r;
227     real margin;
228
229 #ifndef GMX_DOUBLE
230     /* since t is float, we can not use double precision for bRmod */
231     bDouble = FALSE;
232 #endif
233
234     if (t-tp > 0 && tp-tpp > 0)
235     {
236         margin = 0.1*min(t-tp, tp-tpp);
237     }
238     else
239     {
240         margin = 0;
241     }
242
243     r = -1;
244     if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN)))  &&
245         (!bTimeSet(TEND)   || (t <= rTimeValue(TEND))))
246     {
247         if (bTimeSet(TDELTA) && !bRmod_fd(t, t0, rTimeValue(TDELTA), bDouble))
248         {
249             r = -1;
250         }
251         else
252         {
253             r = 0;
254         }
255     }
256     else if (bTimeSet(TEND) && (t >= rTimeValue(TEND)))
257     {
258         r = 1;
259     }
260     if (debug)
261     {
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);
264     }
265     return r;
266 }
267
268 int check_times(real t)
269 {
270     return check_times2(t, t, t, t, FALSE);
271 }
272
273
274
275
276 static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
277 {
278     int         i      = 0, j;
279     const char *select = NULL;
280
281     if (bCanTime)
282     {
283         select = getenv("GMXTIMEUNIT");
284         if (select != NULL)
285         {
286             i = 1;
287             while (time_list[i] && strcmp(time_list[i], select) != 0)
288             {
289                 i++;
290             }
291         }
292     }
293     if (!bCanTime || select == NULL ||
294         time_list[i] == NULL || strcmp(time_list[i], select) != 0)
295     {
296         /* Set it to the default: ps */
297         i = 1;
298         while (time_list[i] && strcmp(time_list[i], "ps") != 0)
299         {
300             i++;
301         }
302
303     }
304     time_list[0] = time_list[i];
305 }
306
307
308 static void set_default_xvg_format(const char *xvg_list[])
309 {
310     int         i, j;
311     const char *select, *tmp;
312
313     select = getenv("GMX_VIEW_XVG");
314     if (select == NULL)
315     {
316         /* The default is the first option */
317         xvg_list[0] = xvg_list[1];
318     }
319     else
320     {
321         i = 1;
322         while (xvg_list[i] && strcmp(xvg_list[i], select) != 0)
323         {
324             i++;
325         }
326         if (xvg_list[i] != NULL)
327         {
328             xvg_list[0] = xvg_list[i];
329         }
330         else
331         {
332             xvg_list[0] = xvg_list[exvgNONE];
333         }
334     }
335 }
336
337
338 /***** T O P O L O G Y   S T U F F ******/
339
340 t_topology *read_top(const char *fn, int *ePBC)
341 {
342     int         epbc, natoms;
343     t_topology *top;
344
345     snew(top, 1);
346     epbc = read_tpx_top(fn, NULL, NULL, &natoms, NULL, NULL, NULL, top);
347     if (ePBC)
348     {
349         *ePBC = epbc;
350     }
351
352     return top;
353 }
354
355 /*************************************************************
356  *
357  *           P A R S I N G   S T U F F
358  *
359  *************************************************************/
360
361 static void usage(const char *type, const char *arg)
362 {
363     assert(arg);
364     gmx_fatal(FARGS, "Expected %s argument for option %s\n", type, arg);
365 }
366
367 int iscan(int argc, char *argv[], int *i)
368 {
369     int var = 0;
370
371     if (argc > (*i)+1)
372     {
373         if (!sscanf(argv[++(*i)], "%d", &var))
374         {
375             usage("an integer", argv[(*i)-1]);
376         }
377     }
378     else
379     {
380         usage("an integer", argv[*i]);
381     }
382
383     return var;
384 }
385
386 gmx_large_int_t istepscan(int argc, char *argv[], int *i)
387 {
388     gmx_large_int_t var = 0;
389
390     if (argc > (*i)+1)
391     {
392         if (!sscanf(argv[++(*i)], gmx_large_int_pfmt, &var))
393         {
394             usage("an integer", argv[(*i)-1]);
395         }
396     }
397     else
398     {
399         usage("an integer", argv[*i]);
400     }
401
402     return var;
403 }
404
405 double dscan(int argc, char *argv[], int *i)
406 {
407     double var = 0;
408
409     if (argc > (*i)+1)
410     {
411         if (!sscanf(argv[++(*i)], "%lf", &var))
412         {
413             usage("a real", argv[(*i)-1]);
414         }
415     }
416     else
417     {
418         usage("a real", argv[*i]);
419     }
420
421     return var;
422 }
423
424 char *sscan(int argc, char *argv[], int *i)
425 {
426     if (argc > (*i)+1)
427     {
428         if ( (argv[(*i)+1][0] == '-') && (argc > (*i)+2) &&
429              (argv[(*i)+2][0] != '-') )
430         {
431             fprintf(stderr, "Possible missing string argument for option %s\n\n",
432                     argv[*i]);
433         }
434     }
435     else
436     {
437         usage("a string", argv[*i]);
438     }
439
440     return argv[++(*i)];
441 }
442
443 int nenum(const char *const enumc[])
444 {
445     int i;
446
447     i = 1;
448     /* we *can* compare pointers directly here! */
449     while (enumc[i] && enumc[0] != enumc[i])
450     {
451         i++;
452     }
453
454     return i;
455 }
456
457 static void pdesc(char *desc)
458 {
459     char *ptr, *nptr;
460
461     ptr = desc;
462     if ((int)strlen(ptr) < 70)
463     {
464         fprintf(stderr, "\t%s\n", ptr);
465     }
466     else
467     {
468         for (nptr = ptr+70; (nptr != ptr) && (!isspace(*nptr)); nptr--)
469         {
470             ;
471         }
472         if (nptr == ptr)
473         {
474             fprintf(stderr, "\t%s\n", ptr);
475         }
476         else
477         {
478             *nptr = '\0';
479             nptr++;
480             fprintf(stderr, "\t%s\n", ptr);
481             pdesc(nptr);
482         }
483     }
484 }
485
486 static FILE *man_file(const output_env_t oenv, const char *mantp)
487 {
488     FILE       *fp;
489     char        buf[256];
490     const char *pr = output_env_get_short_program_name(oenv);
491
492     if (strcmp(mantp, "ascii") != 0)
493     {
494         sprintf(buf, "%s.%s", pr, mantp);
495     }
496     else
497     {
498         sprintf(buf, "%s.txt", pr);
499     }
500     fp = gmx_fio_fopen(buf, "w");
501
502     return fp;
503 }
504
505 static int add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
506 {
507     memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
508
509     return npargs+1;
510 }
511
512 static char *mk_desc(t_pargs *pa, const char *time_unit_str)
513 {
514     char      *newdesc = NULL, *ndesc = NULL, *nptr = NULL;
515     const char*ptr     = NULL;
516     int        len, k;
517
518     /* First compute length for description */
519     len = strlen(pa->desc)+1;
520     if ((ptr = strstr(pa->desc, "HIDDEN")) != NULL)
521     {
522         len += 4;
523     }
524     if (pa->type == etENUM)
525     {
526         len += 10;
527         for (k = 1; (pa->u.c[k] != NULL); k++)
528         {
529             len += strlen(pa->u.c[k])+12;
530         }
531     }
532     snew(newdesc, len);
533
534     /* add label for hidden options */
535     if (is_hidden(pa))
536     {
537         sprintf(newdesc, "[hidden] %s", ptr+6);
538     }
539     else
540     {
541         strcpy(newdesc, pa->desc);
542     }
543
544     /* change '%t' into time_unit */
545 #define TUNITLABEL "%t"
546 #define NTUNIT strlen(TUNITLABEL)
547     if (pa->type == etTIME)
548     {
549         while ( (nptr = strstr(newdesc, TUNITLABEL)) != NULL)
550         {
551             nptr[0] = '\0';
552             nptr   += NTUNIT;
553             len    += strlen(time_unit_str)-NTUNIT;
554             snew(ndesc, len);
555             strcpy(ndesc, newdesc);
556             strcat(ndesc, time_unit_str);
557             strcat(ndesc, nptr);
558             sfree(newdesc);
559             newdesc = ndesc;
560             ndesc   = NULL;
561         }
562     }
563 #undef TUNITLABEL
564 #undef NTUNIT
565
566     /* Add extra comment for enumerateds */
567     if (pa->type == etENUM)
568     {
569         strcat(newdesc, ": ");
570         for (k = 1; (pa->u.c[k] != NULL); k++)
571         {
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)
577             {
578                 if (pa->u.c[k+2] == NULL)
579                 {
580                     strcat(newdesc, " or ");
581                 }
582                 else
583                 {
584                     strcat(newdesc, ", ");
585                 }
586             }
587         }
588     }
589     return newdesc;
590 }
591
592
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,
597                        output_env_t *oenv)
598 {
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
603     };
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",
609         NULL
610     };
611     int         nicelevel = 0, mantp = 0, npri = 0, debug_level = 0, verbose_level = 0;
612     char       *deffnm    = NULL;
613     real        tbegin    = 0, tend = 0, tdelta = 0;
614     gmx_bool    bView     = FALSE;
615
616     t_pargs    *all_pa = NULL;
617
618     t_pargs     npri_pa   = {
619         "-npri", FALSE, etINT,   {&npri},
620         "HIDDEN Set non blocking priority (try 128)"
621     };
622     t_pargs     nice_pa   = {
623         "-nice", FALSE, etINT,   {&nicelevel},
624         "Set the nicelevel"
625     };
626     t_pargs     deffnm_pa = {
627         "-deffnm", FALSE, etSTR, {&deffnm},
628         "Set the default filename for all file options"
629     };
630     t_pargs     begin_pa  = {
631         "-b",    FALSE, etTIME,  {&tbegin},
632         "First frame (%t) to read from trajectory"
633     };
634     t_pargs     end_pa    = {
635         "-e",    FALSE, etTIME,  {&tend},
636         "Last frame (%t) to read from trajectory"
637     };
638     t_pargs     dt_pa     = {
639         "-dt",   FALSE, etTIME,  {&tdelta},
640         "Only use frame when t MOD dt = first time (%t)"
641     };
642     t_pargs     view_pa   = {
643         "-w",    FALSE, etBOOL,  {&bView},
644         "View output [TT].xvg[tt], [TT].xpm[tt], [TT].eps[tt] and [TT].pdb[tt] files"
645     };
646     t_pargs     xvg_pa    = {
647         "-xvg",  FALSE, etENUM,  {xvg_format},
648         "xvg plot formatting"
649     };
650     t_pargs     time_pa   = {
651         "-tu",   FALSE, etENUM,  {time_units},
652         "Time unit"
653     };
654     /* Maximum number of extra arguments */
655 #define EXTRA_PA 16
656
657     t_pargs     pca_pa[] = {
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" },
672     };
673 #define NPCA_PA asize(pca_pa)
674     FILE       *fp;
675     gmx_bool    bPrint, bExit, bXvgr;
676     int         i, j, k, npall, max_pa, cmdlength;
677     char       *ptr, *newdesc;
678     const char *envstr;
679
680 #define FF(arg) ((Flags & arg) == arg)
681
682     snew(*oenv, 1);
683
684     cmdlength = strlen(argv[0]);
685     /* Check for double arguments */
686     for (i = 1; (i < *argc); i++)
687     {
688         cmdlength += strlen(argv[i]);
689         if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1])))
690         {
691             for (j = i+1; (j < *argc); j++)
692             {
693                 if ( (argv[i][0] == '-') && (argv[j][0] == '-') &&
694                      (strcmp(argv[i], argv[j]) == 0) )
695                 {
696                     if (FF(PCA_NOEXIT_ON_ARGS))
697                     {
698                         fprintf(stderr, "Double command line argument %s\n",
699                                 argv[i]);
700                     }
701                     else
702                     {
703                         gmx_fatal(FARGS, "Double command line argument %s\n",
704                                   argv[i]);
705                     }
706                 }
707             }
708         }
709     }
710     debug_gmx();
711     set_program_name(argv[0]);
712     set_command_line(*argc, argv);
713
714     /* Handle the flags argument, which is a bit field
715      * The FF macro returns whether or not the bit is set
716      */
717     bPrint        = !FF(PCA_SILENT);
718
719     /* Check ALL the flags ... */
720     max_pa = NPCA_PA + EXTRA_PA + npargs+1;
721     snew(all_pa, max_pa);
722
723     for (i = npall = 0; (i < NPCA_PA); i++)
724     {
725         npall = add_parg(npall, all_pa, &(pca_pa[i]));
726     }
727
728 #ifdef __sgi
729     envstr = getenv("GMXNPRIALL");
730     if (envstr)
731     {
732         npri = strtol(envstr, NULL, 10);
733     }
734     if (FF(PCA_BE_NICE))
735     {
736         envstr = getenv("GMXNPRI");
737         if (envstr)
738         {
739             npri = strtol(envstr, NULL, 10);
740         }
741     }
742     npall = add_parg(npall, all_pa, &npri_pa);
743 #endif
744
745     if (FF(PCA_BE_NICE))
746     {
747         nicelevel = 19;
748     }
749     npall = add_parg(npall, all_pa, &nice_pa);
750
751     if (FF(PCA_CAN_SET_DEFFNM))
752     {
753         npall = add_parg(npall, all_pa, &deffnm_pa);
754     }
755     if (FF(PCA_CAN_BEGIN))
756     {
757         npall = add_parg(npall, all_pa, &begin_pa);
758     }
759     if (FF(PCA_CAN_END))
760     {
761         npall = add_parg(npall, all_pa, &end_pa);
762     }
763     if (FF(PCA_CAN_DT))
764     {
765         npall = add_parg(npall, all_pa, &dt_pa);
766     }
767     if (FF(PCA_TIME_UNIT))
768     {
769         npall = add_parg(npall, all_pa, &time_pa);
770     }
771     if (FF(PCA_CAN_VIEW))
772     {
773         npall = add_parg(npall, all_pa, &view_pa);
774     }
775
776     bXvgr = FALSE;
777     for (i = 0; (i < nfile); i++)
778     {
779         bXvgr = bXvgr ||  (fnm[i].ftp == efXVG);
780     }
781     if (bXvgr)
782     {
783         npall = add_parg(npall, all_pa, &xvg_pa);
784     }
785
786     /* Now append the program specific arguments */
787     for (i = 0; (i < npargs); i++)
788     {
789         npall = add_parg(npall, all_pa, &(pa[i]));
790     }
791
792     /* set etENUM options to default */
793     for (i = 0; (i < npall); i++)
794     {
795         if (all_pa[i].type == etENUM)
796         {
797             all_pa[i].u.c[0] = all_pa[i].u.c[1];
798         }
799     }
800     set_default_time_unit(time_units, FF(PCA_TIME_UNIT));
801     set_default_xvg_format(xvg_format);
802
803     /* Now parse all the command-line options */
804     get_pargs(argc, argv, npall, all_pa, FF(PCA_KEEP_ARGS));
805
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);
809
810     if (bVersion)
811     {
812         printf("Program: %s\n", output_env_get_program_name(*oenv));
813         gmx_print_version_info(stdout);
814         gmx_finalize_par();
815         exit(0);
816     }
817
818     if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
819     {
820         set_default_file_name(deffnm);
821     }
822
823     /* Parse the file args */
824     parse_file_args(argc, argv, nfile, fnm, FF(PCA_KEEP_ARGS), !FF(PCA_NOT_READ_NODE));
825
826     /* Open the debug file */
827     if (debug_level > 0)
828     {
829         char buf[256];
830
831         if (gmx_mpi_initialized())
832         {
833             sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
834                     gmx_node_rank());
835         }
836         else
837         {
838             sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
839         }
840
841         init_debug(debug_level, buf);
842         fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
843                 buf, __FILE__, __LINE__);
844     }
845
846     /* Now copy the results back... */
847     for (i = 0, k = npall-npargs; (i < npargs); i++, k++)
848     {
849         memcpy(&(pa[i]), &(all_pa[k]), (size_t)sizeof(pa[i]));
850     }
851
852
853     for (i = 0; (i < npall); i++)
854     {
855         all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
856     }
857
858     bExit = bHelp || (strcmp(manstr[0], "no") != 0);
859
860 #if (defined __sgi && USE_SGI_FPE)
861     doexceptions();
862 #endif
863
864     /* Set the nice level */
865 #ifdef __sgi
866     if (npri != 0 && !bExit)
867     {
868         schedctl(MPTS_RTPRI, 0, npri);
869     }
870 #endif
871
872 #ifdef HAVE_UNISTD_H
873
874 #ifndef GMX_NO_NICE
875     /* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
876     if (nicelevel != 0 && !bExit)
877     {
878 #ifdef GMX_THREAD_MPI
879         static gmx_bool nice_set = FALSE; /* only set it once */
880         tMPI_Thread_mutex_lock(&init_mutex);
881         if (!nice_set)
882         {
883 #endif
884         i = nice(nicelevel);   /* assign ret value to avoid warnings */
885 #ifdef GMX_THREAD_MPI
886         nice_set = TRUE;
887     }
888     tMPI_Thread_mutex_unlock(&init_mutex);
889 #endif
890     }
891 #endif
892 #endif
893
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);
897
898     if (!(FF(PCA_QUIET) || bQuiet ))
899     {
900         if (bHelp)
901         {
902             write_man(stderr, "help", output_env_get_program_name(*oenv),
903                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
904         }
905         else if (bPrint)
906         {
907             pr_fns(stderr, nfile, fnm);
908             print_pargs(stderr, npall, all_pa, FALSE);
909         }
910     }
911
912     if (strcmp(manstr[0], "no") != 0)
913     {
914         if (!strcmp(manstr[0], "completion"))
915         {
916             /* one file each for csh, bash and zsh if we do completions */
917             fp = man_file(*oenv, "completion-zsh");
918
919             write_man(fp, "completion-zsh", output_env_get_program_name(*oenv),
920                       ndesc, desc, nfile, fnm, npall, all_pa, nbugs, bugs, bHidden);
921             gmx_fio_fclose(fp);
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);
925             gmx_fio_fclose(fp);
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);
929             gmx_fio_fclose(fp);
930         }
931         else
932         {
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);
936             gmx_fio_fclose(fp);
937         }
938     }
939
940     /* convert time options, must be done after printing! */
941
942     for (i = 0; i < npall; i++)
943     {
944         if ((all_pa[i].type == etTIME) && (*all_pa[i].u.r >= 0))
945         {
946             *all_pa[i].u.r *= output_env_get_time_invfactor(*oenv);
947         }
948     }
949
950     /* Extract Time info from arguments */
951     if (FF(PCA_CAN_BEGIN) && opt2parg_bSet("-b", npall, all_pa))
952     {
953         setTimeValue(TBEGIN, opt2parg_real("-b", npall, all_pa));
954     }
955
956     if (FF(PCA_CAN_END) && opt2parg_bSet("-e", npall, all_pa))
957     {
958         setTimeValue(TEND, opt2parg_real("-e", npall, all_pa));
959     }
960
961     if (FF(PCA_CAN_DT) && opt2parg_bSet("-dt", npall, all_pa))
962     {
963         setTimeValue(TDELTA, opt2parg_real("-dt", npall, all_pa));
964     }
965
966     /* clear memory */
967     for (i = 0; i < npall; ++i)
968     {
969         sfree((void *)all_pa[i].desc);
970     }
971     sfree(all_pa);
972
973     if (!FF(PCA_NOEXIT_ON_ARGS))
974     {
975         if (*argc > 1)
976         {
977             gmx_cmd(argv[1]);
978         }
979     }
980     if (bExit)
981     {
982         gmx_finalize_par();
983
984         exit(0);
985     }
986 #undef FF
987 }