c5ebbb0e6c0881cfb9234a3e91c03e54e985519f
[alexxy/gromacs.git] / src / programs / gmx / grompp.c
1 /*  -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  *
4  *                This source code is part of
5  *
6  *                 G   R   O   M   A   C   S
7  *
8  *          GROningen MAchine for Chemical Simulations
9  *
10  *                        VERSION 3.2.03
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.
15
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.
20  *
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.
27  *
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.
30  *
31  * For more info, check our website at http://www.gromacs.org
32  *
33  * And Hey:
34  * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <sys/types.h>
41 #include <math.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <limits.h>
45
46 #include "sysstuff.h"
47 #include "smalloc.h"
48 #include "macros.h"
49 #include "string2.h"
50 #include "readir.h"
51 #include "toputil.h"
52 #include "topio.h"
53 #include "gromacs/fileio/confio.h"
54 #include "readir.h"
55 #include "symtab.h"
56 #include "names.h"
57 #include "grompp.h"
58 #include "random.h"
59 #include "vec.h"
60 #include "gromacs/fileio/futil.h"
61 #include "statutil.h"
62 #include "splitter.h"
63 #include "sortwater.h"
64 #include "convparm.h"
65 #include "gmx_fatal.h"
66 #include "warninp.h"
67 #include "index.h"
68 #include "gromacs/fileio/gmxfio.h"
69 #include "gromacs/fileio/trnio.h"
70 #include "gromacs/fileio/tpxio.h"
71 #include "gromacs/fileio/trxio.h"
72 #include "vsite_parm.h"
73 #include "txtdump.h"
74 #include "calcgrid.h"
75 #include "add_par.h"
76 #include "gromacs/fileio/enxio.h"
77 #include "perf_est.h"
78 #include "compute_io.h"
79 #include "gpp_atomtype.h"
80 #include "mtop_util.h"
81 #include "genborn.h"
82 #include "calc_verletbuf.h"
83
84 #include "tomorse.h"
85
86 static int rm_interactions(int ifunc, int nrmols, t_molinfo mols[])
87 {
88     int  i, n;
89
90     n = 0;
91     /* For all the molecule types */
92     for (i = 0; i < nrmols; i++)
93     {
94         n += mols[i].plist[ifunc].nr;
95         mols[i].plist[ifunc].nr = 0;
96     }
97     return n;
98 }
99
100 static int check_atom_names(const char *fn1, const char *fn2,
101                             gmx_mtop_t *mtop, t_atoms *at)
102 {
103     int      mb, m, i, j, nmismatch;
104     t_atoms *tat;
105 #define MAXMISMATCH 20
106
107     if (mtop->natoms != at->nr)
108     {
109         gmx_incons("comparing atom names");
110     }
111
112     nmismatch = 0;
113     i         = 0;
114     for (mb = 0; mb < mtop->nmolblock; mb++)
115     {
116         tat = &mtop->moltype[mtop->molblock[mb].type].atoms;
117         for (m = 0; m < mtop->molblock[mb].nmol; m++)
118         {
119             for (j = 0; j < tat->nr; j++)
120             {
121                 if (strcmp( *(tat->atomname[j]), *(at->atomname[i]) ) != 0)
122                 {
123                     if (nmismatch < MAXMISMATCH)
124                     {
125                         fprintf(stderr,
126                                 "Warning: atom name %d in %s and %s does not match (%s - %s)\n",
127                                 i+1, fn1, fn2, *(tat->atomname[j]), *(at->atomname[i]));
128                     }
129                     else if (nmismatch == MAXMISMATCH)
130                     {
131                         fprintf(stderr, "(more than %d non-matching atom names)\n", MAXMISMATCH);
132                     }
133                     nmismatch++;
134                 }
135                 i++;
136             }
137         }
138     }
139
140     return nmismatch;
141 }
142
143 static void check_eg_vs_cg(gmx_mtop_t *mtop)
144 {
145     int            astart, mb, m, cg, j, firstj;
146     unsigned char  firsteg, eg;
147     gmx_moltype_t *molt;
148
149     /* Go through all the charge groups and make sure all their
150      * atoms are in the same energy group.
151      */
152
153     astart = 0;
154     for (mb = 0; mb < mtop->nmolblock; mb++)
155     {
156         molt = &mtop->moltype[mtop->molblock[mb].type];
157         for (m = 0; m < mtop->molblock[mb].nmol; m++)
158         {
159             for (cg = 0; cg < molt->cgs.nr; cg++)
160             {
161                 /* Get the energy group of the first atom in this charge group */
162                 firstj  = astart + molt->cgs.index[cg];
163                 firsteg = ggrpnr(&mtop->groups, egcENER, firstj);
164                 for (j = molt->cgs.index[cg]+1; j < molt->cgs.index[cg+1]; j++)
165                 {
166                     eg = ggrpnr(&mtop->groups, egcENER, astart+j);
167                     if (eg != firsteg)
168                     {
169                         gmx_fatal(FARGS, "atoms %d and %d in charge group %d of molecule type '%s' are in different energy groups",
170                                   firstj+1, astart+j+1, cg+1, *molt->name);
171                     }
172                 }
173             }
174             astart += molt->atoms.nr;
175         }
176     }
177 }
178
179 static void check_cg_sizes(const char *topfn, t_block *cgs, warninp_t wi)
180 {
181     int  maxsize, cg;
182     char warn_buf[STRLEN];
183
184     maxsize = 0;
185     for (cg = 0; cg < cgs->nr; cg++)
186     {
187         maxsize = max(maxsize, cgs->index[cg+1]-cgs->index[cg]);
188     }
189
190     if (maxsize > MAX_CHARGEGROUP_SIZE)
191     {
192         gmx_fatal(FARGS, "The largest charge group contains %d atoms. The maximum is %d.", maxsize, MAX_CHARGEGROUP_SIZE);
193     }
194     else if (maxsize > 10)
195     {
196         set_warning_line(wi, topfn, -1);
197         sprintf(warn_buf,
198                 "The largest charge group contains %d atoms.\n"
199                 "Since atoms only see each other when the centers of geometry of the charge groups they belong to are within the cut-off distance, too large charge groups can lead to serious cut-off artifacts.\n"
200                 "For efficiency and accuracy, charge group should consist of a few atoms.\n"
201                 "For all-atom force fields use: CH3, CH2, CH, NH2, NH, OH, CO2, CO, etc.",
202                 maxsize);
203         warning_note(wi, warn_buf);
204     }
205 }
206
207 static void check_bonds_timestep(gmx_mtop_t *mtop, double dt, warninp_t wi)
208 {
209     /* This check is not intended to ensure accurate integration,
210      * rather it is to signal mistakes in the mdp settings.
211      * A common mistake is to forget to turn on constraints
212      * for MD after energy minimization with flexible bonds.
213      * This check can also detect too large time steps for flexible water
214      * models, but such errors will often be masked by the constraints
215      * mdp options, which turns flexible water into water with bond constraints,
216      * but without an angle constraint. Unfortunately such incorrect use
217      * of water models can not easily be detected without checking
218      * for specific model names.
219      *
220      * The stability limit of leap-frog or velocity verlet is 4.44 steps
221      * per oscillational period.
222      * But accurate bonds distributions are lost far before that limit.
223      * To allow relatively common schemes (although not common with Gromacs)
224      * of dt=1 fs without constraints and dt=2 fs with only H-bond constraints
225      * we set the note limit to 10.
226      */
227     int            min_steps_warn = 5;
228     int            min_steps_note = 10;
229     t_iparams     *ip;
230     int            molt;
231     gmx_moltype_t *moltype, *w_moltype;
232     t_atom        *atom;
233     t_ilist       *ilist, *ilb, *ilc, *ils;
234     int            ftype;
235     int            i, a1, a2, w_a1, w_a2, j;
236     real           twopi2, limit2, fc, re, m1, m2, period2, w_period2;
237     gmx_bool       bFound, bWater, bWarn;
238     char           warn_buf[STRLEN];
239
240     ip = mtop->ffparams.iparams;
241
242     twopi2 = sqr(2*M_PI);
243
244     limit2 = sqr(min_steps_note*dt);
245
246     w_a1      = w_a2 = -1;
247     w_period2 = -1.0;
248
249     w_moltype = NULL;
250     for (molt = 0; molt < mtop->nmoltype; molt++)
251     {
252         moltype = &mtop->moltype[molt];
253         atom    = moltype->atoms.atom;
254         ilist   = moltype->ilist;
255         ilc     = &ilist[F_CONSTR];
256         ils     = &ilist[F_SETTLE];
257         for (ftype = 0; ftype < F_NRE; ftype++)
258         {
259             if (!(ftype == F_BONDS || ftype == F_G96BONDS || ftype == F_HARMONIC))
260             {
261                 continue;
262             }
263
264             ilb = &ilist[ftype];
265             for (i = 0; i < ilb->nr; i += 3)
266             {
267                 fc = ip[ilb->iatoms[i]].harmonic.krA;
268                 re = ip[ilb->iatoms[i]].harmonic.rA;
269                 if (ftype == F_G96BONDS)
270                 {
271                     /* Convert squared sqaure fc to harmonic fc */
272                     fc = 2*fc*re;
273                 }
274                 a1 = ilb->iatoms[i+1];
275                 a2 = ilb->iatoms[i+2];
276                 m1 = atom[a1].m;
277                 m2 = atom[a2].m;
278                 if (fc > 0 && m1 > 0 && m2 > 0)
279                 {
280                     period2 = twopi2*m1*m2/((m1 + m2)*fc);
281                 }
282                 else
283                 {
284                     period2 = GMX_FLOAT_MAX;
285                 }
286                 if (debug)
287                 {
288                     fprintf(debug, "fc %g m1 %g m2 %g period %g\n",
289                             fc, m1, m2, sqrt(period2));
290                 }
291                 if (period2 < limit2)
292                 {
293                     bFound = FALSE;
294                     for (j = 0; j < ilc->nr; j += 3)
295                     {
296                         if ((ilc->iatoms[j+1] == a1 && ilc->iatoms[j+2] == a2) ||
297                             (ilc->iatoms[j+1] == a2 && ilc->iatoms[j+2] == a1))
298                         {
299                             bFound = TRUE;
300                         }
301                     }
302                     for (j = 0; j < ils->nr; j += 4)
303                     {
304                         if ((a1 == ils->iatoms[j+1] || a1 == ils->iatoms[j+2] || a1 == ils->iatoms[j+3]) &&
305                             (a2 == ils->iatoms[j+1] || a2 == ils->iatoms[j+2] || a2 == ils->iatoms[j+3]))
306                         {
307                             bFound = TRUE;
308                         }
309                     }
310                     if (!bFound &&
311                         (w_moltype == NULL || period2 < w_period2))
312                     {
313                         w_moltype = moltype;
314                         w_a1      = a1;
315                         w_a2      = a2;
316                         w_period2 = period2;
317                     }
318                 }
319             }
320         }
321     }
322
323     if (w_moltype != NULL)
324     {
325         bWarn = (w_period2 < sqr(min_steps_warn*dt));
326         /* A check that would recognize most water models */
327         bWater = ((*w_moltype->atoms.atomname[0])[0] == 'O' &&
328                   w_moltype->atoms.nr <= 5);
329         sprintf(warn_buf, "The bond in molecule-type %s between atoms %d %s and %d %s has an estimated oscillational period of %.1e ps, which is less than %d times the time step of %.1e ps.\n"
330                 "%s",
331                 *w_moltype->name,
332                 w_a1+1, *w_moltype->atoms.atomname[w_a1],
333                 w_a2+1, *w_moltype->atoms.atomname[w_a2],
334                 sqrt(w_period2), bWarn ? min_steps_warn : min_steps_note, dt,
335                 bWater ?
336                 "Maybe you asked for fexible water." :
337                 "Maybe you forgot to change the constraints mdp option.");
338         if (bWarn)
339         {
340             warning(wi, warn_buf);
341         }
342         else
343         {
344             warning_note(wi, warn_buf);
345         }
346     }
347 }
348
349 static void check_vel(gmx_mtop_t *mtop, rvec v[])
350 {
351     gmx_mtop_atomloop_all_t aloop;
352     t_atom                 *atom;
353     int                     a;
354
355     aloop = gmx_mtop_atomloop_all_init(mtop);
356     while (gmx_mtop_atomloop_all_next(aloop, &a, &atom))
357     {
358         if (atom->ptype == eptShell ||
359             atom->ptype == eptBond  ||
360             atom->ptype == eptVSite)
361         {
362             clear_rvec(v[a]);
363         }
364     }
365 }
366
367 static gmx_bool nint_ftype(gmx_mtop_t *mtop, t_molinfo *mi, int ftype)
368 {
369     int nint, mb;
370
371     nint = 0;
372     for (mb = 0; mb < mtop->nmolblock; mb++)
373     {
374         nint += mtop->molblock[mb].nmol*mi[mtop->molblock[mb].type].plist[ftype].nr;
375     }
376
377     return nint;
378 }
379
380 /* This routine reorders the molecule type array
381  * in the order of use in the molblocks,
382  * unused molecule types are deleted.
383  */
384 static void renumber_moltypes(gmx_mtop_t *sys,
385                               int *nmolinfo, t_molinfo **molinfo)
386 {
387     int       *order, norder, i;
388     int        mb, mi;
389     t_molinfo *minew;
390
391     snew(order, *nmolinfo);
392     norder = 0;
393     for (mb = 0; mb < sys->nmolblock; mb++)
394     {
395         for (i = 0; i < norder; i++)
396         {
397             if (order[i] == sys->molblock[mb].type)
398             {
399                 break;
400             }
401         }
402         if (i == norder)
403         {
404             /* This type did not occur yet, add it */
405             order[norder] = sys->molblock[mb].type;
406             /* Renumber the moltype in the topology */
407             norder++;
408         }
409         sys->molblock[mb].type = i;
410     }
411
412     /* We still need to reorder the molinfo structs */
413     snew(minew, norder);
414     for (mi = 0; mi < *nmolinfo; mi++)
415     {
416         for (i = 0; i < norder; i++)
417         {
418             if (order[i] == mi)
419             {
420                 break;
421             }
422         }
423         if (i == norder)
424         {
425             done_mi(&(*molinfo)[mi]);
426         }
427         else
428         {
429             minew[i] = (*molinfo)[mi];
430         }
431     }
432     sfree(*molinfo);
433
434     *nmolinfo = norder;
435     *molinfo  = minew;
436 }
437
438 static void molinfo2mtop(int nmi, t_molinfo *mi, gmx_mtop_t *mtop)
439 {
440     int            m;
441     gmx_moltype_t *molt;
442
443     mtop->nmoltype = nmi;
444     snew(mtop->moltype, nmi);
445     for (m = 0; m < nmi; m++)
446     {
447         molt        = &mtop->moltype[m];
448         molt->name  = mi[m].name;
449         molt->atoms = mi[m].atoms;
450         /* ilists are copied later */
451         molt->cgs   = mi[m].cgs;
452         molt->excls = mi[m].excls;
453     }
454 }
455
456 static void
457 new_status(const char *topfile, const char *topppfile, const char *confin,
458            t_gromppopts *opts, t_inputrec *ir, gmx_bool bZero,
459            gmx_bool bGenVel, gmx_bool bVerbose, t_state *state,
460            gpp_atomtype_t atype, gmx_mtop_t *sys,
461            int *nmi, t_molinfo **mi, t_params plist[],
462            int *comb, double *reppow, real *fudgeQQ,
463            gmx_bool bMorse,
464            warninp_t wi)
465 {
466     t_molinfo      *molinfo = NULL;
467     int             nmolblock;
468     gmx_molblock_t *molblock, *molbs;
469     t_atoms        *confat;
470     int             mb, i, nrmols, nmismatch;
471     char            buf[STRLEN];
472     gmx_bool        bGB = FALSE;
473     char            warn_buf[STRLEN];
474
475     init_mtop(sys);
476
477     /* Set gmx_boolean for GB */
478     if (ir->implicit_solvent)
479     {
480         bGB = TRUE;
481     }
482
483     /* TOPOLOGY processing */
484     sys->name = do_top(bVerbose, topfile, topppfile, opts, bZero, &(sys->symtab),
485                        plist, comb, reppow, fudgeQQ,
486                        atype, &nrmols, &molinfo, ir,
487                        &nmolblock, &molblock, bGB,
488                        wi);
489
490     sys->nmolblock = 0;
491     snew(sys->molblock, nmolblock);
492
493     sys->natoms = 0;
494     for (mb = 0; mb < nmolblock; mb++)
495     {
496         if (sys->nmolblock > 0 &&
497             molblock[mb].type == sys->molblock[sys->nmolblock-1].type)
498         {
499             /* Merge consecutive blocks with the same molecule type */
500             sys->molblock[sys->nmolblock-1].nmol += molblock[mb].nmol;
501             sys->natoms += molblock[mb].nmol*sys->molblock[sys->nmolblock-1].natoms_mol;
502         }
503         else if (molblock[mb].nmol > 0)
504         {
505             /* Add a new molblock to the topology */
506             molbs             = &sys->molblock[sys->nmolblock];
507             *molbs            = molblock[mb];
508             molbs->natoms_mol = molinfo[molbs->type].atoms.nr;
509             molbs->nposres_xA = 0;
510             molbs->nposres_xB = 0;
511             sys->natoms      += molbs->nmol*molbs->natoms_mol;
512             sys->nmolblock++;
513         }
514     }
515     if (sys->nmolblock == 0)
516     {
517         gmx_fatal(FARGS, "No molecules were defined in the system");
518     }
519
520     renumber_moltypes(sys, &nrmols, &molinfo);
521
522     if (bMorse)
523     {
524         convert_harmonics(nrmols, molinfo, atype);
525     }
526
527     if (ir->eDisre == edrNone)
528     {
529         i = rm_interactions(F_DISRES, nrmols, molinfo);
530         if (i > 0)
531         {
532             set_warning_line(wi, "unknown", -1);
533             sprintf(warn_buf, "disre = no, removed %d distance restraints", i);
534             warning_note(wi, warn_buf);
535         }
536     }
537     if (opts->bOrire == FALSE)
538     {
539         i = rm_interactions(F_ORIRES, nrmols, molinfo);
540         if (i > 0)
541         {
542             set_warning_line(wi, "unknown", -1);
543             sprintf(warn_buf, "orire = no, removed %d orientation restraints", i);
544             warning_note(wi, warn_buf);
545         }
546     }
547
548     /* Copy structures from msys to sys */
549     molinfo2mtop(nrmols, molinfo, sys);
550
551     gmx_mtop_finalize(sys);
552
553     /* COORDINATE file processing */
554     if (bVerbose)
555     {
556         fprintf(stderr, "processing coordinates...\n");
557     }
558
559     get_stx_coordnum(confin, &state->natoms);
560     if (state->natoms != sys->natoms)
561     {
562         gmx_fatal(FARGS, "number of coordinates in coordinate file (%s, %d)\n"
563                   "             does not match topology (%s, %d)",
564                   confin, state->natoms, topfile, sys->natoms);
565     }
566     else
567     {
568         /* make space for coordinates and velocities */
569         char title[STRLEN];
570         snew(confat, 1);
571         init_t_atoms(confat, state->natoms, FALSE);
572         init_state(state, state->natoms, 0, 0, 0, 0);
573         read_stx_conf(confin, title, confat, state->x, state->v, NULL, state->box);
574         /* This call fixes the box shape for runs with pressure scaling */
575         set_box_rel(ir, state);
576
577         nmismatch = check_atom_names(topfile, confin, sys, confat);
578         free_t_atoms(confat, TRUE);
579         sfree(confat);
580
581         if (nmismatch)
582         {
583             sprintf(buf, "%d non-matching atom name%s\n"
584                     "atom names from %s will be used\n"
585                     "atom names from %s will be ignored\n",
586                     nmismatch, (nmismatch == 1) ? "" : "s", topfile, confin);
587             warning(wi, buf);
588         }
589         if (bVerbose)
590         {
591             fprintf(stderr, "double-checking input for internal consistency...\n");
592         }
593         double_check(ir, state->box, nint_ftype(sys, molinfo, F_CONSTR), wi);
594     }
595
596     if (bGenVel)
597     {
598         real                   *mass;
599         gmx_mtop_atomloop_all_t aloop;
600         t_atom                 *atom;
601
602         snew(mass, state->natoms);
603         aloop = gmx_mtop_atomloop_all_init(sys);
604         while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
605         {
606             mass[i] = atom->m;
607         }
608
609         if (opts->seed == -1)
610         {
611             opts->seed = make_seed();
612             fprintf(stderr, "Setting gen_seed to %d\n", opts->seed);
613         }
614         maxwell_speed(opts->tempi, opts->seed, sys, state->v);
615
616         stop_cm(stdout, state->natoms, mass, state->x, state->v);
617         sfree(mass);
618     }
619
620     *nmi = nrmols;
621     *mi  = molinfo;
622 }
623
624 static void copy_state(const char *slog, t_trxframe *fr,
625                        gmx_bool bReadVel, t_state *state,
626                        double *use_time)
627 {
628     int i;
629
630     if (fr->not_ok & FRAME_NOT_OK)
631     {
632         gmx_fatal(FARGS, "Can not start from an incomplete frame");
633     }
634     if (!fr->bX)
635     {
636         gmx_fatal(FARGS, "Did not find a frame with coordinates in file %s",
637                   slog);
638     }
639
640     for (i = 0; i < state->natoms; i++)
641     {
642         copy_rvec(fr->x[i], state->x[i]);
643     }
644     if (bReadVel)
645     {
646         if (!fr->bV)
647         {
648             gmx_incons("Trajecory frame unexpectedly does not contain velocities");
649         }
650         for (i = 0; i < state->natoms; i++)
651         {
652             copy_rvec(fr->v[i], state->v[i]);
653         }
654     }
655     if (fr->bBox)
656     {
657         copy_mat(fr->box, state->box);
658     }
659
660     *use_time = fr->time;
661 }
662
663 static void cont_status(const char *slog, const char *ener,
664                         gmx_bool bNeedVel, gmx_bool bGenVel, real fr_time,
665                         t_inputrec *ir, t_state *state,
666                         gmx_mtop_t *sys,
667                         const output_env_t oenv)
668 /* If fr_time == -1 read the last frame available which is complete */
669 {
670     gmx_bool     bReadVel;
671     t_trxframe   fr;
672     t_trxstatus *fp;
673     int          i;
674     double       use_time;
675
676     bReadVel = (bNeedVel && !bGenVel);
677
678     fprintf(stderr,
679             "Reading Coordinates%s and Box size from old trajectory\n",
680             bReadVel ? ", Velocities" : "");
681     if (fr_time == -1)
682     {
683         fprintf(stderr, "Will read whole trajectory\n");
684     }
685     else
686     {
687         fprintf(stderr, "Will read till time %g\n", fr_time);
688     }
689     if (!bReadVel)
690     {
691         if (bGenVel)
692         {
693             fprintf(stderr, "Velocities generated: "
694                     "ignoring velocities in input trajectory\n");
695         }
696         read_first_frame(oenv, &fp, slog, &fr, TRX_NEED_X);
697     }
698     else
699     {
700         read_first_frame(oenv, &fp, slog, &fr, TRX_NEED_X | TRX_NEED_V);
701
702         if (!fr.bV)
703         {
704             fprintf(stderr,
705                     "\n"
706                     "WARNING: Did not find a frame with velocities in file %s,\n"
707                     "         all velocities will be set to zero!\n\n", slog);
708             for (i = 0; i < sys->natoms; i++)
709             {
710                 clear_rvec(state->v[i]);
711             }
712             close_trj(fp);
713             /* Search for a frame without velocities */
714             bReadVel = FALSE;
715             read_first_frame(oenv, &fp, slog, &fr, TRX_NEED_X);
716         }
717     }
718
719     state->natoms = fr.natoms;
720
721     if (sys->natoms != state->natoms)
722     {
723         gmx_fatal(FARGS, "Number of atoms in Topology "
724                   "is not the same as in Trajectory");
725     }
726     copy_state(slog, &fr, bReadVel, state, &use_time);
727
728     /* Find the appropriate frame */
729     while ((fr_time == -1 || fr.time < fr_time) &&
730            read_next_frame(oenv, fp, &fr))
731     {
732         copy_state(slog, &fr, bReadVel, state, &use_time);
733     }
734
735     close_trj(fp);
736
737     /* Set the relative box lengths for preserving the box shape.
738      * Note that this call can lead to differences in the last bit
739      * with respect to using tpbconv to create a [TT].tpx[tt] file.
740      */
741     set_box_rel(ir, state);
742
743     fprintf(stderr, "Using frame at t = %g ps\n", use_time);
744     fprintf(stderr, "Starting time for run is %g ps\n", ir->init_t);
745
746     if ((ir->epc != epcNO  || ir->etc == etcNOSEHOOVER) && ener)
747     {
748         get_enx_state(ener, use_time, &sys->groups, ir, state);
749         preserve_box_shape(ir, state->box_rel, state->boxv);
750     }
751 }
752
753 static void read_posres(gmx_mtop_t *mtop, t_molinfo *molinfo, gmx_bool bTopB,
754                         char *fn,
755                         int rc_scaling, int ePBC,
756                         rvec com,
757                         warninp_t wi)
758 {
759     gmx_bool        bFirst = TRUE, *hadAtom;
760     rvec           *x, *v, *xp;
761     dvec            sum;
762     double          totmass;
763     t_atoms         dumat;
764     matrix          box, invbox;
765     int             natoms, npbcdim = 0;
766     char            warn_buf[STRLEN], title[STRLEN];
767     int             a, i, ai, j, k, mb, nat_molb;
768     gmx_molblock_t *molb;
769     t_params       *pr, *prfb;
770     t_atom         *atom;
771
772     get_stx_coordnum(fn, &natoms);
773     if (natoms != mtop->natoms)
774     {
775         sprintf(warn_buf, "The number of atoms in %s (%d) does not match the number of atoms in the topology (%d). Will assume that the first %d atoms in the topology and %s match.", fn, natoms, mtop->natoms, min(mtop->natoms, natoms), fn);
776         warning(wi, warn_buf);
777     }
778     snew(x, natoms);
779     snew(v, natoms);
780     init_t_atoms(&dumat, natoms, FALSE);
781     read_stx_conf(fn, title, &dumat, x, v, NULL, box);
782
783     npbcdim = ePBC2npbcdim(ePBC);
784     clear_rvec(com);
785     if (rc_scaling != erscNO)
786     {
787         copy_mat(box, invbox);
788         for (j = npbcdim; j < DIM; j++)
789         {
790             clear_rvec(invbox[j]);
791             invbox[j][j] = 1;
792         }
793         m_inv_ur0(invbox, invbox);
794     }
795
796     /* Copy the reference coordinates to mtop */
797     clear_dvec(sum);
798     totmass = 0;
799     a       = 0;
800     snew(hadAtom, natoms);
801     for (mb = 0; mb < mtop->nmolblock; mb++)
802     {
803         molb     = &mtop->molblock[mb];
804         nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
805         pr       = &(molinfo[molb->type].plist[F_POSRES]);
806         prfb     = &(molinfo[molb->type].plist[F_FBPOSRES]);
807         if (pr->nr > 0 || prfb->nr > 0)
808         {
809             atom = mtop->moltype[molb->type].atoms.atom;
810             for (i = 0; (i < pr->nr); i++)
811             {
812                 ai = pr->param[i].AI;
813                 if (ai >= natoms)
814                 {
815                     gmx_fatal(FARGS, "Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n",
816                               ai+1, *molinfo[molb->type].name, fn, natoms);
817                 }
818                 hadAtom[ai] = TRUE;
819                 if (rc_scaling == erscCOM)
820                 {
821                     /* Determine the center of mass of the posres reference coordinates */
822                     for (j = 0; j < npbcdim; j++)
823                     {
824                         sum[j] += atom[ai].m*x[a+ai][j];
825                     }
826                     totmass  += atom[ai].m;
827                 }
828             }
829             /* Same for flat-bottomed posres, but do not count an atom twice for COM */
830             for (i = 0; (i < prfb->nr); i++)
831             {
832                 ai = prfb->param[i].AI;
833                 if (ai >= natoms)
834                 {
835                     gmx_fatal(FARGS, "Position restraint atom index (%d) in moltype '%s' is larger than number of atoms in %s (%d).\n",
836                               ai+1, *molinfo[molb->type].name, fn, natoms);
837                 }
838                 if (rc_scaling == erscCOM && hadAtom[ai] == FALSE)
839                 {
840                     /* Determine the center of mass of the posres reference coordinates */
841                     for (j = 0; j < npbcdim; j++)
842                     {
843                         sum[j] += atom[ai].m*x[a+ai][j];
844                     }
845                     totmass  += atom[ai].m;
846                 }
847             }
848             if (!bTopB)
849             {
850                 molb->nposres_xA = nat_molb;
851                 snew(molb->posres_xA, molb->nposres_xA);
852                 for (i = 0; i < nat_molb; i++)
853                 {
854                     copy_rvec(x[a+i], molb->posres_xA[i]);
855                 }
856             }
857             else
858             {
859                 molb->nposres_xB = nat_molb;
860                 snew(molb->posres_xB, molb->nposres_xB);
861                 for (i = 0; i < nat_molb; i++)
862                 {
863                     copy_rvec(x[a+i], molb->posres_xB[i]);
864                 }
865             }
866         }
867         a += nat_molb;
868     }
869     if (rc_scaling == erscCOM)
870     {
871         if (totmass == 0)
872         {
873             gmx_fatal(FARGS, "The total mass of the position restraint atoms is 0");
874         }
875         for (j = 0; j < npbcdim; j++)
876         {
877             com[j] = sum[j]/totmass;
878         }
879         fprintf(stderr, "The center of mass of the position restraint coord's is %6.3f %6.3f %6.3f\n", com[XX], com[YY], com[ZZ]);
880     }
881
882     if (rc_scaling != erscNO)
883     {
884         for (mb = 0; mb < mtop->nmolblock; mb++)
885         {
886             molb     = &mtop->molblock[mb];
887             nat_molb = molb->nmol*mtop->moltype[molb->type].atoms.nr;
888             if (molb->nposres_xA > 0 || molb->nposres_xB > 0)
889             {
890                 xp = (!bTopB ? molb->posres_xA : molb->posres_xB);
891                 for (i = 0; i < nat_molb; i++)
892                 {
893                     for (j = 0; j < npbcdim; j++)
894                     {
895                         if (rc_scaling == erscALL)
896                         {
897                             /* Convert from Cartesian to crystal coordinates */
898                             xp[i][j] *= invbox[j][j];
899                             for (k = j+1; k < npbcdim; k++)
900                             {
901                                 xp[i][j] += invbox[k][j]*xp[i][k];
902                             }
903                         }
904                         else if (rc_scaling == erscCOM)
905                         {
906                             /* Subtract the center of mass */
907                             xp[i][j] -= com[j];
908                         }
909                     }
910                 }
911             }
912         }
913
914         if (rc_scaling == erscCOM)
915         {
916             /* Convert the COM from Cartesian to crystal coordinates */
917             for (j = 0; j < npbcdim; j++)
918             {
919                 com[j] *= invbox[j][j];
920                 for (k = j+1; k < npbcdim; k++)
921                 {
922                     com[j] += invbox[k][j]*com[k];
923                 }
924             }
925         }
926     }
927
928     free_t_atoms(&dumat, TRUE);
929     sfree(x);
930     sfree(v);
931     sfree(hadAtom);
932 }
933
934 static void gen_posres(gmx_mtop_t *mtop, t_molinfo *mi,
935                        char *fnA, char *fnB,
936                        int rc_scaling, int ePBC,
937                        rvec com, rvec comB,
938                        warninp_t wi)
939 {
940     int i, j;
941
942     read_posres  (mtop, mi, FALSE, fnA, rc_scaling, ePBC, com, wi);
943     if (strcmp(fnA, fnB) != 0)
944     {
945         read_posres(mtop, mi, TRUE, fnB, rc_scaling, ePBC, comB, wi);
946     }
947 }
948
949 static void set_wall_atomtype(gpp_atomtype_t at, t_gromppopts *opts,
950                               t_inputrec *ir, warninp_t wi)
951 {
952     int  i;
953     char warn_buf[STRLEN];
954
955     if (ir->nwall > 0)
956     {
957         fprintf(stderr, "Searching the wall atom type(s)\n");
958     }
959     for (i = 0; i < ir->nwall; i++)
960     {
961         ir->wall_atomtype[i] = get_atomtype_type(opts->wall_atomtype[i], at);
962         if (ir->wall_atomtype[i] == NOTSET)
963         {
964             sprintf(warn_buf, "Specified wall atom type %s is not defined", opts->wall_atomtype[i]);
965             warning_error(wi, warn_buf);
966         }
967     }
968 }
969
970 static int nrdf_internal(t_atoms *atoms)
971 {
972     int i, nmass, nrdf;
973
974     nmass = 0;
975     for (i = 0; i < atoms->nr; i++)
976     {
977         /* Vsite ptype might not be set here yet, so also check the mass */
978         if ((atoms->atom[i].ptype == eptAtom ||
979              atoms->atom[i].ptype == eptNucleus)
980             && atoms->atom[i].m > 0)
981         {
982             nmass++;
983         }
984     }
985     switch (nmass)
986     {
987         case 0:  nrdf = 0; break;
988         case 1:  nrdf = 0; break;
989         case 2:  nrdf = 1; break;
990         default: nrdf = nmass*3 - 6; break;
991     }
992
993     return nrdf;
994 }
995
996 void
997 spline1d( double        dx,
998           double *      y,
999           int           n,
1000           double *      u,
1001           double *      y2 )
1002 {
1003     int    i;
1004     double p, q;
1005
1006     y2[0] = 0.0;
1007     u[0]  = 0.0;
1008
1009     for (i = 1; i < n-1; i++)
1010     {
1011         p     = 0.5*y2[i-1]+2.0;
1012         y2[i] = -0.5/p;
1013         q     = (y[i+1]-2.0*y[i]+y[i-1])/dx;
1014         u[i]  = (3.0*q/dx-0.5*u[i-1])/p;
1015     }
1016
1017     y2[n-1] = 0.0;
1018
1019     for (i = n-2; i >= 0; i--)
1020     {
1021         y2[i] = y2[i]*y2[i+1]+u[i];
1022     }
1023 }
1024
1025
1026 void
1027 interpolate1d( double     xmin,
1028                double     dx,
1029                double *   ya,
1030                double *   y2a,
1031                double     x,
1032                double *   y,
1033                double *   y1)
1034 {
1035     int    ix;
1036     double a, b;
1037
1038     ix = (x-xmin)/dx;
1039
1040     a = (xmin+(ix+1)*dx-x)/dx;
1041     b = (x-xmin-ix*dx)/dx;
1042
1043     *y  = a*ya[ix]+b*ya[ix+1]+((a*a*a-a)*y2a[ix]+(b*b*b-b)*y2a[ix+1])*(dx*dx)/6.0;
1044     *y1 = (ya[ix+1]-ya[ix])/dx-(3.0*a*a-1.0)/6.0*dx*y2a[ix]+(3.0*b*b-1.0)/6.0*dx*y2a[ix+1];
1045 }
1046
1047
1048 void
1049 setup_cmap (int              grid_spacing,
1050             int              nc,
1051             real *           grid,
1052             gmx_cmap_t *     cmap_grid)
1053 {
1054     double *tmp_u, *tmp_u2, *tmp_yy, *tmp_y1, *tmp_t2, *tmp_grid;
1055
1056     int     i, j, k, ii, jj, kk, idx;
1057     int     offset;
1058     double  dx, xmin, v, v1, v2, v12;
1059     double  phi, psi;
1060
1061     snew(tmp_u, 2*grid_spacing);
1062     snew(tmp_u2, 2*grid_spacing);
1063     snew(tmp_yy, 2*grid_spacing);
1064     snew(tmp_y1, 2*grid_spacing);
1065     snew(tmp_t2, 2*grid_spacing*2*grid_spacing);
1066     snew(tmp_grid, 2*grid_spacing*2*grid_spacing);
1067
1068     dx   = 360.0/grid_spacing;
1069     xmin = -180.0-dx*grid_spacing/2;
1070
1071     for (kk = 0; kk < nc; kk++)
1072     {
1073         /* Compute an offset depending on which cmap we are using
1074          * Offset will be the map number multiplied with the
1075          * grid_spacing * grid_spacing * 2
1076          */
1077         offset = kk * grid_spacing * grid_spacing * 2;
1078
1079         for (i = 0; i < 2*grid_spacing; i++)
1080         {
1081             ii = (i+grid_spacing-grid_spacing/2)%grid_spacing;
1082
1083             for (j = 0; j < 2*grid_spacing; j++)
1084             {
1085                 jj = (j+grid_spacing-grid_spacing/2)%grid_spacing;
1086                 tmp_grid[i*grid_spacing*2+j] = grid[offset+ii*grid_spacing+jj];
1087             }
1088         }
1089
1090         for (i = 0; i < 2*grid_spacing; i++)
1091         {
1092             spline1d(dx, &(tmp_grid[2*grid_spacing*i]), 2*grid_spacing, tmp_u, &(tmp_t2[2*grid_spacing*i]));
1093         }
1094
1095         for (i = grid_spacing/2; i < grid_spacing+grid_spacing/2; i++)
1096         {
1097             ii  = i-grid_spacing/2;
1098             phi = ii*dx-180.0;
1099
1100             for (j = grid_spacing/2; j < grid_spacing+grid_spacing/2; j++)
1101             {
1102                 jj  = j-grid_spacing/2;
1103                 psi = jj*dx-180.0;
1104
1105                 for (k = 0; k < 2*grid_spacing; k++)
1106                 {
1107                     interpolate1d(xmin, dx, &(tmp_grid[2*grid_spacing*k]),
1108                                   &(tmp_t2[2*grid_spacing*k]), psi, &tmp_yy[k], &tmp_y1[k]);
1109                 }
1110
1111                 spline1d(dx, tmp_yy, 2*grid_spacing, tmp_u, tmp_u2);
1112                 interpolate1d(xmin, dx, tmp_yy, tmp_u2, phi, &v, &v1);
1113                 spline1d(dx, tmp_y1, 2*grid_spacing, tmp_u, tmp_u2);
1114                 interpolate1d(xmin, dx, tmp_y1, tmp_u2, phi, &v2, &v12);
1115
1116                 idx = ii*grid_spacing+jj;
1117                 cmap_grid->cmapdata[kk].cmap[idx*4]   = grid[offset+ii*grid_spacing+jj];
1118                 cmap_grid->cmapdata[kk].cmap[idx*4+1] = v1;
1119                 cmap_grid->cmapdata[kk].cmap[idx*4+2] = v2;
1120                 cmap_grid->cmapdata[kk].cmap[idx*4+3] = v12;
1121             }
1122         }
1123     }
1124 }
1125
1126 void init_cmap_grid(gmx_cmap_t *cmap_grid, int ngrid, int grid_spacing)
1127 {
1128     int i, k, nelem;
1129
1130     cmap_grid->ngrid        = ngrid;
1131     cmap_grid->grid_spacing = grid_spacing;
1132     nelem                   = cmap_grid->grid_spacing*cmap_grid->grid_spacing;
1133
1134     snew(cmap_grid->cmapdata, ngrid);
1135
1136     for (i = 0; i < cmap_grid->ngrid; i++)
1137     {
1138         snew(cmap_grid->cmapdata[i].cmap, 4*nelem);
1139     }
1140 }
1141
1142
1143 static int count_constraints(gmx_mtop_t *mtop, t_molinfo *mi, warninp_t wi)
1144 {
1145     int             count, count_mol, i, mb;
1146     gmx_molblock_t *molb;
1147     t_params       *plist;
1148     char            buf[STRLEN];
1149
1150     count = 0;
1151     for (mb = 0; mb < mtop->nmolblock; mb++)
1152     {
1153         count_mol = 0;
1154         molb      = &mtop->molblock[mb];
1155         plist     = mi[molb->type].plist;
1156
1157         for (i = 0; i < F_NRE; i++)
1158         {
1159             if (i == F_SETTLE)
1160             {
1161                 count_mol += 3*plist[i].nr;
1162             }
1163             else if (interaction_function[i].flags & IF_CONSTRAINT)
1164             {
1165                 count_mol += plist[i].nr;
1166             }
1167         }
1168
1169         if (count_mol > nrdf_internal(&mi[molb->type].atoms))
1170         {
1171             sprintf(buf,
1172                     "Molecule type '%s' has %d constraints.\n"
1173                     "For stability and efficiency there should not be more constraints than internal number of degrees of freedom: %d.\n",
1174                     *mi[molb->type].name, count_mol,
1175                     nrdf_internal(&mi[molb->type].atoms));
1176             warning(wi, buf);
1177         }
1178         count += molb->nmol*count_mol;
1179     }
1180
1181     return count;
1182 }
1183
1184 static void check_gbsa_params_charged(gmx_mtop_t *sys, gpp_atomtype_t atype)
1185 {
1186     int            i, nmiss, natoms, mt;
1187     real           q;
1188     const t_atoms *atoms;
1189
1190     nmiss = 0;
1191     for (mt = 0; mt < sys->nmoltype; mt++)
1192     {
1193         atoms  = &sys->moltype[mt].atoms;
1194         natoms = atoms->nr;
1195
1196         for (i = 0; i < natoms; i++)
1197         {
1198             q = atoms->atom[i].q;
1199             if ((get_atomtype_radius(atoms->atom[i].type, atype)    == 0  ||
1200                  get_atomtype_vol(atoms->atom[i].type, atype)       == 0  ||
1201                  get_atomtype_surftens(atoms->atom[i].type, atype)  == 0  ||
1202                  get_atomtype_gb_radius(atoms->atom[i].type, atype) == 0  ||
1203                  get_atomtype_S_hct(atoms->atom[i].type, atype)     == 0) &&
1204                 q != 0)
1205             {
1206                 fprintf(stderr, "\nGB parameter(s) zero for atom type '%s' while charge is %g\n",
1207                         get_atomtype_name(atoms->atom[i].type, atype), q);
1208                 nmiss++;
1209             }
1210         }
1211     }
1212
1213     if (nmiss > 0)
1214     {
1215         gmx_fatal(FARGS, "Can't do GB electrostatics; the implicit_genborn_params section of the forcefield has parameters with value zero for %d atomtypes that occur as charged atoms.", nmiss);
1216     }
1217 }
1218
1219
1220 static void check_gbsa_params(gpp_atomtype_t atype)
1221 {
1222     int  nmiss, i;
1223
1224     /* If we are doing GBSA, check that we got the parameters we need
1225      * This checking is to see if there are GBSA paratmeters for all
1226      * atoms in the force field. To go around this for testing purposes
1227      * comment out the nerror++ counter temporarily
1228      */
1229     nmiss = 0;
1230     for (i = 0; i < get_atomtype_ntypes(atype); i++)
1231     {
1232         if (get_atomtype_radius(i, atype)    < 0 ||
1233             get_atomtype_vol(i, atype)       < 0 ||
1234             get_atomtype_surftens(i, atype)  < 0 ||
1235             get_atomtype_gb_radius(i, atype) < 0 ||
1236             get_atomtype_S_hct(i, atype)     < 0)
1237         {
1238             fprintf(stderr, "\nGB parameter(s) missing or negative for atom type '%s'\n",
1239                     get_atomtype_name(i, atype));
1240             nmiss++;
1241         }
1242     }
1243
1244     if (nmiss > 0)
1245     {
1246         gmx_fatal(FARGS, "Can't do GB electrostatics; the implicit_genborn_params section of the forcefield is missing parameters for %d atomtypes or they might be negative.", nmiss);
1247     }
1248
1249 }
1250
1251 static void set_verlet_buffer(const gmx_mtop_t *mtop,
1252                               t_inputrec       *ir,
1253                               matrix            box,
1254                               real              verletbuf_drift,
1255                               warninp_t         wi)
1256 {
1257     real                   ref_T;
1258     int                    i;
1259     verletbuf_list_setup_t ls;
1260     real                   rlist_1x1;
1261     int                    n_nonlin_vsite;
1262     char                   warn_buf[STRLEN];
1263
1264     ref_T = 0;
1265     for (i = 0; i < ir->opts.ngtc; i++)
1266     {
1267         if (ir->opts.ref_t[i] < 0)
1268         {
1269             warning(wi, "Some atom groups do not use temperature coupling. This cannot be accounted for in the energy drift estimation for the Verlet buffer size. The energy drift and the Verlet buffer might be underestimated.");
1270         }
1271         else
1272         {
1273             ref_T = max(ref_T, ir->opts.ref_t[i]);
1274         }
1275     }
1276
1277     printf("Determining Verlet buffer for an energy drift of %g kJ/mol/ps at %g K\n", verletbuf_drift, ref_T);
1278
1279     for (i = 0; i < ir->opts.ngtc; i++)
1280     {
1281         if (ir->opts.ref_t[i] >= 0 && ir->opts.ref_t[i] != ref_T)
1282         {
1283             sprintf(warn_buf, "ref_T for group of %.1f DOFs is %g K, which is smaller than the maximum of %g K used for the buffer size calculation. The buffer size might be on the conservative (large) side.",
1284                     ir->opts.nrdf[i], ir->opts.ref_t[i], ref_T);
1285             warning_note(wi, warn_buf);
1286         }
1287     }
1288
1289     /* Calculate the buffer size for simple atom vs atoms list */
1290     ls.cluster_size_i = 1;
1291     ls.cluster_size_j = 1;
1292     calc_verlet_buffer_size(mtop, det(box), ir, verletbuf_drift,
1293                             &ls, &n_nonlin_vsite, &rlist_1x1);
1294
1295     /* Set the pair-list buffer size in ir */
1296     verletbuf_get_list_setup(FALSE, &ls);
1297     calc_verlet_buffer_size(mtop, det(box), ir, verletbuf_drift,
1298                             &ls, &n_nonlin_vsite, &ir->rlist);
1299
1300     if (n_nonlin_vsite > 0)
1301     {
1302         sprintf(warn_buf, "There are %d non-linear virtual site constructions. Their contribution to the energy drift is approximated. In most cases this does not affect the energy drift significantly.", n_nonlin_vsite);
1303         warning_note(wi, warn_buf);
1304     }
1305
1306     printf("Calculated rlist for %dx%d atom pair-list as %.3f nm, buffer size %.3f nm\n",
1307            1, 1, rlist_1x1, rlist_1x1-max(ir->rvdw, ir->rcoulomb));
1308
1309     ir->rlistlong = ir->rlist;
1310     printf("Set rlist, assuming %dx%d atom pair-list, to %.3f nm, buffer size %.3f nm\n",
1311            ls.cluster_size_i, ls.cluster_size_j,
1312            ir->rlist, ir->rlist-max(ir->rvdw, ir->rcoulomb));
1313
1314     if (sqr(ir->rlistlong) >= max_cutoff2(ir->ePBC, box))
1315     {
1316         gmx_fatal(FARGS, "The pair-list cut-off (%g nm) is longer than half the shortest box vector or longer than the smallest box diagonal element (%g nm). Increase the box size or decrease nstlist or increase verlet-buffer-drift.", ir->rlistlong, sqrt(max_cutoff2(ir->ePBC, box)));
1317     }
1318 }
1319
1320 int gmx_grompp(int argc, char *argv[])
1321 {
1322     static const char *desc[] = {
1323         "[THISMODULE] (the gromacs preprocessor)",
1324         "reads a molecular topology file, checks the validity of the",
1325         "file, expands the topology from a molecular description to an atomic",
1326         "description. The topology file contains information about",
1327         "molecule types and the number of molecules, the preprocessor",
1328         "copies each molecule as needed. ",
1329         "There is no limitation on the number of molecule types. ",
1330         "Bonds and bond-angles can be converted into constraints, separately",
1331         "for hydrogens and heavy atoms.",
1332         "Then a coordinate file is read and velocities can be generated",
1333         "from a Maxwellian distribution if requested.",
1334         "[THISMODULE] also reads parameters for [gmx-mdrun] ",
1335         "(eg. number of MD steps, time step, cut-off), and others such as",
1336         "NEMD parameters, which are corrected so that the net acceleration",
1337         "is zero.",
1338         "Eventually a binary file is produced that can serve as the sole input",
1339         "file for the MD program.[PAR]",
1340
1341         "[THISMODULE] uses the atom names from the topology file. The atom names",
1342         "in the coordinate file (option [TT]-c[tt]) are only read to generate",
1343         "warnings when they do not match the atom names in the topology.",
1344         "Note that the atom names are irrelevant for the simulation as",
1345         "only the atom types are used for generating interaction parameters.[PAR]",
1346
1347         "[THISMODULE] uses a built-in preprocessor to resolve includes, macros, ",
1348         "etc. The preprocessor supports the following keywords:[PAR]",
1349         "#ifdef VARIABLE[BR]",
1350         "#ifndef VARIABLE[BR]",
1351         "#else[BR]",
1352         "#endif[BR]",
1353         "#define VARIABLE[BR]",
1354         "#undef VARIABLE[BR]"
1355         "#include \"filename\"[BR]",
1356         "#include <filename>[PAR]",
1357         "The functioning of these statements in your topology may be modulated by",
1358         "using the following two flags in your [TT].mdp[tt] file:[PAR]",
1359         "[TT]define = -DVARIABLE1 -DVARIABLE2[BR]",
1360         "include = -I/home/john/doe[tt][BR]",
1361         "For further information a C-programming textbook may help you out.",
1362         "Specifying the [TT]-pp[tt] flag will get the pre-processed",
1363         "topology file written out so that you can verify its contents.[PAR]",
1364
1365         /* cpp has been unnecessary for some time, hasn't it?
1366             "If your system does not have a C-preprocessor, you can still",
1367             "use [TT]grompp[tt], but you do not have access to the features ",
1368             "from the cpp. Command line options to the C-preprocessor can be given",
1369             "in the [TT].mdp[tt] file. See your local manual (man cpp).[PAR]",
1370          */
1371
1372         "When using position restraints a file with restraint coordinates",
1373         "can be supplied with [TT]-r[tt], otherwise restraining will be done",
1374         "with respect to the conformation from the [TT]-c[tt] option.",
1375         "For free energy calculation the the coordinates for the B topology",
1376         "can be supplied with [TT]-rb[tt], otherwise they will be equal to",
1377         "those of the A topology.[PAR]",
1378
1379         "Starting coordinates can be read from trajectory with [TT]-t[tt].",
1380         "The last frame with coordinates and velocities will be read,",
1381         "unless the [TT]-time[tt] option is used. Only if this information",
1382         "is absent will the coordinates in the [TT]-c[tt] file be used.",
1383         "Note that these velocities will not be used when [TT]gen_vel = yes[tt]",
1384         "in your [TT].mdp[tt] file. An energy file can be supplied with",
1385         "[TT]-e[tt] to read Nose-Hoover and/or Parrinello-Rahman coupling",
1386         "variables.[PAR]",
1387
1388         "[THISMODULE] can be used to restart simulations (preserving",
1389         "continuity) by supplying just a checkpoint file with [TT]-t[tt].",
1390         "However, for simply changing the number of run steps to extend",
1391         "a run, using [gmx-tpbconv] is more convenient than [THISMODULE].",
1392         "You then supply the old checkpoint file directly to [gmx-mdrun]",
1393         "with [TT]-cpi[tt]. If you wish to change the ensemble or things",
1394         "like output frequency, then supplying the checkpoint file to",
1395         "[THISMODULE] with [TT]-t[tt] along with a new [TT].mdp[tt] file",
1396         "with [TT]-f[tt] is the recommended procedure.[PAR]",
1397
1398         "By default, all bonded interactions which have constant energy due to",
1399         "virtual site constructions will be removed. If this constant energy is",
1400         "not zero, this will result in a shift in the total energy. All bonded",
1401         "interactions can be kept by turning off [TT]-rmvsbds[tt]. Additionally,",
1402         "all constraints for distances which will be constant anyway because",
1403         "of virtual site constructions will be removed. If any constraints remain",
1404         "which involve virtual sites, a fatal error will result.[PAR]"
1405
1406         "To verify your run input file, please take note of all warnings",
1407         "on the screen, and correct where necessary. Do also look at the contents",
1408         "of the [TT]mdout.mdp[tt] file; this contains comment lines, as well as",
1409         "the input that [THISMODULE] has read. If in doubt, you can start [THISMODULE]",
1410         "with the [TT]-debug[tt] option which will give you more information",
1411         "in a file called [TT]grompp.log[tt] (along with real debug info). You",
1412         "can see the contents of the run input file with the [gmx-dump]",
1413         "program. [gmx-check] can be used to compare the contents of two",
1414         "run input files.[PAR]"
1415
1416         "The [TT]-maxwarn[tt] option can be used to override warnings printed",
1417         "by [THISMODULE] that otherwise halt output. In some cases, warnings are",
1418         "harmless, but usually they are not. The user is advised to carefully",
1419         "interpret the output messages before attempting to bypass them with",
1420         "this option."
1421     };
1422     t_gromppopts      *opts;
1423     gmx_mtop_t        *sys;
1424     int                nmi;
1425     t_molinfo         *mi;
1426     gpp_atomtype_t     atype;
1427     t_inputrec        *ir;
1428     int                natoms, nvsite, comb, mt;
1429     t_params          *plist;
1430     t_state            state;
1431     matrix             box;
1432     real               max_spacing, fudgeQQ;
1433     double             reppow;
1434     char               fn[STRLEN], fnB[STRLEN];
1435     const char        *mdparin;
1436     int                ntype;
1437     gmx_bool           bNeedVel, bGenVel;
1438     gmx_bool           have_atomnumber;
1439     int                n12, n13, n14;
1440     t_params          *gb_plist = NULL;
1441     gmx_genborn_t     *born     = NULL;
1442     output_env_t       oenv;
1443     gmx_bool           bVerbose = FALSE;
1444     warninp_t          wi;
1445     char               warn_buf[STRLEN];
1446
1447     t_filenm           fnm[] = {
1448         { efMDP, NULL,  NULL,        ffREAD  },
1449         { efMDP, "-po", "mdout",     ffWRITE },
1450         { efSTX, "-c",  NULL,        ffREAD  },
1451         { efSTX, "-r",  NULL,        ffOPTRD },
1452         { efSTX, "-rb", NULL,        ffOPTRD },
1453         { efNDX, NULL,  NULL,        ffOPTRD },
1454         { efTOP, NULL,  NULL,        ffREAD  },
1455         { efTOP, "-pp", "processed", ffOPTWR },
1456         { efTPX, "-o",  NULL,        ffWRITE },
1457         { efTRN, "-t",  NULL,        ffOPTRD },
1458         { efEDR, "-e",  NULL,        ffOPTRD },
1459         { efTRN, "-ref", "rotref",    ffOPTRW }
1460     };
1461 #define NFILE asize(fnm)
1462
1463     /* Command line options */
1464     static gmx_bool bRenum   = TRUE;
1465     static gmx_bool bRmVSBds = TRUE, bZero = FALSE;
1466     static int      i, maxwarn = 0;
1467     static real     fr_time = -1;
1468     t_pargs         pa[]    = {
1469         { "-v",       FALSE, etBOOL, {&bVerbose},
1470           "Be loud and noisy" },
1471         { "-time",    FALSE, etREAL, {&fr_time},
1472           "Take frame at or first after this time." },
1473         { "-rmvsbds", FALSE, etBOOL, {&bRmVSBds},
1474           "Remove constant bonded interactions with virtual sites" },
1475         { "-maxwarn", FALSE, etINT,  {&maxwarn},
1476           "Number of allowed warnings during input processing. Not for normal use and may generate unstable systems" },
1477         { "-zero",    FALSE, etBOOL, {&bZero},
1478           "Set parameters for bonded interactions without defaults to zero instead of generating an error" },
1479         { "-renum",   FALSE, etBOOL, {&bRenum},
1480           "Renumber atomtypes and minimize number of atomtypes" }
1481     };
1482
1483     /* Initiate some variables */
1484     snew(ir, 1);
1485     snew(opts, 1);
1486     init_ir(ir, opts);
1487
1488     /* Parse the command line */
1489     if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa,
1490                            asize(desc), desc, 0, NULL, &oenv))
1491     {
1492         return 0;
1493     }
1494
1495     wi = init_warning(TRUE, maxwarn);
1496
1497     /* PARAMETER file processing */
1498     mdparin = opt2fn("-f", NFILE, fnm);
1499     set_warning_line(wi, mdparin, -1);
1500     get_ir(mdparin, opt2fn("-po", NFILE, fnm), ir, opts, wi);
1501
1502     if (bVerbose)
1503     {
1504         fprintf(stderr, "checking input for internal consistency...\n");
1505     }
1506     check_ir(mdparin, ir, opts, wi);
1507
1508     if (ir->ld_seed == -1)
1509     {
1510         ir->ld_seed = make_seed();
1511         fprintf(stderr, "Setting the LD random seed to %d\n", ir->ld_seed);
1512     }
1513
1514     if (ir->expandedvals->lmc_seed == -1)
1515     {
1516         ir->expandedvals->lmc_seed = make_seed();
1517         fprintf(stderr, "Setting the lambda MC random seed to %d\n", ir->expandedvals->lmc_seed);
1518     }
1519
1520     bNeedVel = EI_STATE_VELOCITY(ir->eI);
1521     bGenVel  = (bNeedVel && opts->bGenVel);
1522     if (bGenVel && ir->bContinuation)
1523     {
1524         sprintf(warn_buf,
1525                 "Generating velocities is inconsistent with attempting "
1526                 "to continue a previous run. Choose only one of "
1527                 "gen-vel = yes and continuation = yes.");
1528         warning_error(wi, warn_buf);
1529     }
1530
1531     snew(plist, F_NRE);
1532     init_plist(plist);
1533     snew(sys, 1);
1534     atype = init_atomtype();
1535     if (debug)
1536     {
1537         pr_symtab(debug, 0, "Just opened", &sys->symtab);
1538     }
1539
1540     strcpy(fn, ftp2fn(efTOP, NFILE, fnm));
1541     if (!gmx_fexist(fn))
1542     {
1543         gmx_fatal(FARGS, "%s does not exist", fn);
1544     }
1545     new_status(fn, opt2fn_null("-pp", NFILE, fnm), opt2fn("-c", NFILE, fnm),
1546                opts, ir, bZero, bGenVel, bVerbose, &state,
1547                atype, sys, &nmi, &mi, plist, &comb, &reppow, &fudgeQQ,
1548                opts->bMorse,
1549                wi);
1550
1551     if (debug)
1552     {
1553         pr_symtab(debug, 0, "After new_status", &sys->symtab);
1554     }
1555
1556     nvsite = 0;
1557     /* set parameters for virtual site construction (not for vsiten) */
1558     for (mt = 0; mt < sys->nmoltype; mt++)
1559     {
1560         nvsite +=
1561             set_vsites(bVerbose, &sys->moltype[mt].atoms, atype, mi[mt].plist);
1562     }
1563     /* now throw away all obsolete bonds, angles and dihedrals: */
1564     /* note: constraints are ALWAYS removed */
1565     if (nvsite)
1566     {
1567         for (mt = 0; mt < sys->nmoltype; mt++)
1568         {
1569             clean_vsite_bondeds(mi[mt].plist, sys->moltype[mt].atoms.nr, bRmVSBds);
1570         }
1571     }
1572
1573     if (ir->cutoff_scheme == ecutsVERLET)
1574     {
1575         fprintf(stderr, "Removing all charge groups because cutoff-scheme=%s\n",
1576                 ecutscheme_names[ir->cutoff_scheme]);
1577
1578         /* Remove all charge groups */
1579         gmx_mtop_remove_chargegroups(sys);
1580     }
1581
1582     if (count_constraints(sys, mi, wi) && (ir->eConstrAlg == econtSHAKE))
1583     {
1584         if (ir->eI == eiCG || ir->eI == eiLBFGS)
1585         {
1586             sprintf(warn_buf, "Can not do %s with %s, use %s",
1587                     EI(ir->eI), econstr_names[econtSHAKE], econstr_names[econtLINCS]);
1588             warning_error(wi, warn_buf);
1589         }
1590         if (ir->bPeriodicMols)
1591         {
1592             sprintf(warn_buf, "Can not do periodic molecules with %s, use %s",
1593                     econstr_names[econtSHAKE], econstr_names[econtLINCS]);
1594             warning_error(wi, warn_buf);
1595         }
1596     }
1597
1598     if (EI_SD (ir->eI) &&  ir->etc != etcNO)
1599     {
1600         warning_note(wi, "Temperature coupling is ignored with SD integrators.");
1601     }
1602
1603     /* If we are doing QM/MM, check that we got the atom numbers */
1604     have_atomnumber = TRUE;
1605     for (i = 0; i < get_atomtype_ntypes(atype); i++)
1606     {
1607         have_atomnumber = have_atomnumber && (get_atomtype_atomnumber(i, atype) >= 0);
1608     }
1609     if (!have_atomnumber && ir->bQMMM)
1610     {
1611         warning_error(wi,
1612                       "\n"
1613                       "It appears as if you are trying to run a QM/MM calculation, but the force\n"
1614                       "field you are using does not contain atom numbers fields. This is an\n"
1615                       "optional field (introduced in Gromacs 3.3) for general runs, but mandatory\n"
1616                       "for QM/MM. The good news is that it is easy to add - put the atom number as\n"
1617                       "an integer just before the mass column in ffXXXnb.itp.\n"
1618                       "NB: United atoms have the same atom numbers as normal ones.\n\n");
1619     }
1620
1621     if (ir->bAdress)
1622     {
1623         if ((ir->adress->const_wf > 1) || (ir->adress->const_wf < 0))
1624         {
1625             warning_error(wi, "AdResS contant weighting function should be between 0 and 1\n\n");
1626         }
1627         /** \TODO check size of ex+hy width against box size */
1628     }
1629
1630     /* Check for errors in the input now, since they might cause problems
1631      * during processing further down.
1632      */
1633     check_warning_error(wi, FARGS);
1634
1635     if (opt2bSet("-r", NFILE, fnm))
1636     {
1637         sprintf(fn, "%s", opt2fn("-r", NFILE, fnm));
1638     }
1639     else
1640     {
1641         sprintf(fn, "%s", opt2fn("-c", NFILE, fnm));
1642     }
1643     if (opt2bSet("-rb", NFILE, fnm))
1644     {
1645         sprintf(fnB, "%s", opt2fn("-rb", NFILE, fnm));
1646     }
1647     else
1648     {
1649         strcpy(fnB, fn);
1650     }
1651
1652     if (nint_ftype(sys, mi, F_POSRES) > 0 || nint_ftype(sys, mi, F_FBPOSRES) > 0)
1653     {
1654         if (bVerbose)
1655         {
1656             fprintf(stderr, "Reading position restraint coords from %s", fn);
1657             if (strcmp(fn, fnB) == 0)
1658             {
1659                 fprintf(stderr, "\n");
1660             }
1661             else
1662             {
1663                 fprintf(stderr, " and %s\n", fnB);
1664             }
1665         }
1666         gen_posres(sys, mi, fn, fnB,
1667                    ir->refcoord_scaling, ir->ePBC,
1668                    ir->posres_com, ir->posres_comB,
1669                    wi);
1670     }
1671
1672     /* If we are using CMAP, setup the pre-interpolation grid */
1673     if (plist->ncmap > 0)
1674     {
1675         init_cmap_grid(&sys->ffparams.cmap_grid, plist->nc, plist->grid_spacing);
1676         setup_cmap(plist->grid_spacing, plist->nc, plist->cmap, &sys->ffparams.cmap_grid);
1677     }
1678
1679     set_wall_atomtype(atype, opts, ir, wi);
1680     if (bRenum)
1681     {
1682         renum_atype(plist, sys, ir->wall_atomtype, atype, bVerbose);
1683         ntype = get_atomtype_ntypes(atype);
1684     }
1685
1686     if (ir->implicit_solvent != eisNO)
1687     {
1688         /* Now we have renumbered the atom types, we can check the GBSA params */
1689         check_gbsa_params(atype);
1690
1691         /* Check that all atoms that have charge and/or LJ-parameters also have
1692          * sensible GB-parameters
1693          */
1694         check_gbsa_params_charged(sys, atype);
1695     }
1696
1697     /* PELA: Copy the atomtype data to the topology atomtype list */
1698     copy_atomtype_atomtypes(atype, &(sys->atomtypes));
1699
1700     if (debug)
1701     {
1702         pr_symtab(debug, 0, "After renum_atype", &sys->symtab);
1703     }
1704
1705     if (bVerbose)
1706     {
1707         fprintf(stderr, "converting bonded parameters...\n");
1708     }
1709
1710     ntype = get_atomtype_ntypes(atype);
1711     convert_params(ntype, plist, mi, comb, reppow, fudgeQQ, sys);
1712
1713     if (debug)
1714     {
1715         pr_symtab(debug, 0, "After convert_params", &sys->symtab);
1716     }
1717
1718     /* set ptype to VSite for virtual sites */
1719     for (mt = 0; mt < sys->nmoltype; mt++)
1720     {
1721         set_vsites_ptype(FALSE, &sys->moltype[mt]);
1722     }
1723     if (debug)
1724     {
1725         pr_symtab(debug, 0, "After virtual sites", &sys->symtab);
1726     }
1727     /* Check velocity for virtual sites and shells */
1728     if (bGenVel)
1729     {
1730         check_vel(sys, state.v);
1731     }
1732
1733     /* check masses */
1734     check_mol(sys, wi);
1735
1736     for (i = 0; i < sys->nmoltype; i++)
1737     {
1738         check_cg_sizes(ftp2fn(efTOP, NFILE, fnm), &sys->moltype[i].cgs, wi);
1739     }
1740
1741     if (EI_DYNAMICS(ir->eI) && ir->eI != eiBD)
1742     {
1743         check_bonds_timestep(sys, ir->delta_t, wi);
1744     }
1745
1746     if (EI_ENERGY_MINIMIZATION(ir->eI) && 0 == ir->nsteps)
1747     {
1748         warning_note(wi, "Zero-step energy minimization will alter the coordinates before calculating the energy. If you just want the energy of a single point, try zero-step MD (with unconstrained_start = yes). To do multiple single-point energy evaluations of different configurations of the same topology, use mdrun -rerun.");
1749     }
1750
1751     check_warning_error(wi, FARGS);
1752
1753     if (bVerbose)
1754     {
1755         fprintf(stderr, "initialising group options...\n");
1756     }
1757     do_index(mdparin, ftp2fn_null(efNDX, NFILE, fnm),
1758              sys, bVerbose, ir,
1759              bGenVel ? state.v : NULL,
1760              wi);
1761
1762     if (ir->cutoff_scheme == ecutsVERLET && ir->verletbuf_drift > 0 &&
1763         ir->nstlist > 1)
1764     {
1765         if (EI_DYNAMICS(ir->eI) &&
1766             !(EI_MD(ir->eI) && ir->etc == etcNO) &&
1767             inputrec2nboundeddim(ir) == 3)
1768         {
1769             set_verlet_buffer(sys, ir, state.box, ir->verletbuf_drift, wi);
1770         }
1771     }
1772
1773     /* Init the temperature coupling state */
1774     init_gtc_state(&state, ir->opts.ngtc, 0, ir->opts.nhchainlength); /* need to add nnhpres here? */
1775
1776     if (bVerbose)
1777     {
1778         fprintf(stderr, "Checking consistency between energy and charge groups...\n");
1779     }
1780     check_eg_vs_cg(sys);
1781
1782     if (debug)
1783     {
1784         pr_symtab(debug, 0, "After index", &sys->symtab);
1785     }
1786     triple_check(mdparin, ir, sys, wi);
1787     close_symtab(&sys->symtab);
1788     if (debug)
1789     {
1790         pr_symtab(debug, 0, "After close", &sys->symtab);
1791     }
1792
1793     /* make exclusions between QM atoms */
1794     if (ir->bQMMM)
1795     {
1796         if (ir->QMMMscheme == eQMMMschemenormal && ir->ns_type == ensSIMPLE)
1797         {
1798             gmx_fatal(FARGS, "electrostatic embedding only works with grid neighboursearching, use ns-type=grid instead\n");
1799         }
1800         else
1801         {
1802             generate_qmexcl(sys, ir, wi);
1803         }
1804     }
1805
1806     if (ftp2bSet(efTRN, NFILE, fnm))
1807     {
1808         if (bVerbose)
1809         {
1810             fprintf(stderr, "getting data from old trajectory ...\n");
1811         }
1812         cont_status(ftp2fn(efTRN, NFILE, fnm), ftp2fn_null(efEDR, NFILE, fnm),
1813                     bNeedVel, bGenVel, fr_time, ir, &state, sys, oenv);
1814     }
1815
1816     if (ir->ePBC == epbcXY && ir->nwall != 2)
1817     {
1818         clear_rvec(state.box[ZZ]);
1819     }
1820
1821     if (ir->cutoff_scheme != ecutsVERLET && ir->rlist > 0)
1822     {
1823         set_warning_line(wi, mdparin, -1);
1824         check_chargegroup_radii(sys, ir, state.x, wi);
1825     }
1826
1827     if (EEL_FULL(ir->coulombtype))
1828     {
1829         /* Calculate the optimal grid dimensions */
1830         copy_mat(state.box, box);
1831         if (ir->ePBC == epbcXY && ir->nwall == 2)
1832         {
1833             svmul(ir->wall_ewald_zfac, box[ZZ], box[ZZ]);
1834         }
1835         if (ir->nkx > 0 && ir->nky > 0 && ir->nkz > 0)
1836         {
1837             /* Mark fourier_spacing as not used */
1838             ir->fourier_spacing = 0;
1839         }
1840         else if (ir->nkx != 0 && ir->nky != 0 && ir->nkz != 0)
1841         {
1842             set_warning_line(wi, mdparin, -1);
1843             warning_error(wi, "Some of the Fourier grid sizes are set, but all of them need to be set.");
1844         }
1845         max_spacing = calc_grid(stdout, box, ir->fourier_spacing,
1846                                 &(ir->nkx), &(ir->nky), &(ir->nkz));
1847     }
1848
1849     /* MRS: eventually figure out better logic for initializing the fep
1850        values that makes declaring the lambda and declaring the state not
1851        potentially conflict if not handled correctly. */
1852     if (ir->efep != efepNO)
1853     {
1854         state.fep_state = ir->fepvals->init_fep_state;
1855         for (i = 0; i < efptNR; i++)
1856         {
1857             /* init_lambda trumps state definitions*/
1858             if (ir->fepvals->init_lambda >= 0)
1859             {
1860                 state.lambda[i] = ir->fepvals->init_lambda;
1861             }
1862             else
1863             {
1864                 if (ir->fepvals->all_lambda[i] == NULL)
1865                 {
1866                     gmx_fatal(FARGS, "Values of lambda not set for a free energy calculation!");
1867                 }
1868                 else
1869                 {
1870                     state.lambda[i] = ir->fepvals->all_lambda[i][state.fep_state];
1871                 }
1872             }
1873         }
1874     }
1875
1876     if (ir->ePull != epullNO)
1877     {
1878         set_pull_init(ir, sys, state.x, state.box, state.lambda[efptMASS], oenv, opts->pull_start);
1879     }
1880
1881     if (ir->bRot)
1882     {
1883         set_reference_positions(ir->rot, state.x, state.box,
1884                                 opt2fn("-ref", NFILE, fnm), opt2bSet("-ref", NFILE, fnm),
1885                                 wi);
1886     }
1887
1888     /*  reset_multinr(sys); */
1889
1890     if (EEL_PME(ir->coulombtype))
1891     {
1892         float ratio = pme_load_estimate(sys, ir, state.box);
1893         fprintf(stderr, "Estimate for the relative computational load of the PME mesh part: %.2f\n", ratio);
1894         /* With free energy we might need to do PME both for the A and B state
1895          * charges. This will double the cost, but the optimal performance will
1896          * then probably be at a slightly larger cut-off and grid spacing.
1897          */
1898         if ((ir->efep == efepNO && ratio > 1.0/2.0) ||
1899             (ir->efep != efepNO && ratio > 2.0/3.0))
1900         {
1901             warning_note(wi,
1902                          "The optimal PME mesh load for parallel simulations is below 0.5\n"
1903                          "and for highly parallel simulations between 0.25 and 0.33,\n"
1904                          "for higher performance, increase the cut-off and the PME grid spacing.\n");
1905             if (ir->efep != efepNO)
1906             {
1907                 warning_note(wi,
1908                              "For free energy simulations, the optimal load limit increases from 0.5 to 0.667\n");
1909             }
1910         }
1911     }
1912
1913     {
1914         char   warn_buf[STRLEN];
1915         double cio = compute_io(ir, sys->natoms, &sys->groups, F_NRE, 1);
1916         sprintf(warn_buf, "This run will generate roughly %.0f Mb of data", cio);
1917         if (cio > 2000)
1918         {
1919             set_warning_line(wi, mdparin, -1);
1920             warning_note(wi, warn_buf);
1921         }
1922         else
1923         {
1924             printf("%s\n", warn_buf);
1925         }
1926     }
1927
1928     if (bVerbose)
1929     {
1930         fprintf(stderr, "writing run input file...\n");
1931     }
1932
1933     done_warning(wi, FARGS);
1934
1935     write_tpx_state(ftp2fn(efTPX, NFILE, fnm), ir, &state, sys);
1936
1937     return 0;
1938 }