Remove unnecessary config.h includes
[alexxy/gromacs.git] / src / gromacs / gmxpreprocess / topio.c
index 37602df41fa5a65cc7117db51800f39c2b7321b6..f7efad094cf21ac20e3ccba791e7af356f8f2f81 100644 (file)
@@ -1,67 +1,69 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+/*
+ * This file is part of the GROMACS molecular simulation package.
  *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
+ * Copyright (c) 2001-2004, The GROMACS development team.
+ * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
  * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
  * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
 
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
 #include <math.h>
-#include <sys/types.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
 
-#include "futil.h"
-#include "sysstuff.h"
-#include "typedefs.h"
-#include "smalloc.h"
-#include "macros.h"
-#include "gmxfio.h"
-#include "txtdump.h"
-#include "physics.h"
-#include "macros.h"
-#include "names.h"
-#include "string2.h"
-#include "symtab.h"
-#include "gmx_fatal.h"
-#include "warninp.h"
+#include <sys/types.h>
+
+#include "gromacs/utility/futil.h"
+#include "gromacs/legacyheaders/typedefs.h"
+#include "gromacs/utility/smalloc.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/fileio/gmxfio.h"
+#include "gromacs/legacyheaders/txtdump.h"
+#include "gromacs/math/units.h"
+#include "gromacs/legacyheaders/macros.h"
+#include "gromacs/legacyheaders/names.h"
+#include "gromacs/utility/cstringutil.h"
+#include "gromacs/topology/block.h"
+#include "gromacs/topology/symtab.h"
+#include "gromacs/topology/topology.h"
+#include "gromacs/utility/fatalerror.h"
+#include "gromacs/legacyheaders/warninp.h"
 #include "vsite_parm.h"
 
-#include "grompp.h"
+#include "grompp-impl.h"
 #include "toputil.h"
 #include "toppush.h"
 #include "topdirs.h"
 #include "topshake.h"
 #include "gmxcpp.h"
 #include "gpp_bond_atomtype.h"
-#include "genborn.h"
-#include "maths.h"
+#include "gromacs/legacyheaders/genborn.h"
+#include "gromacs/math/utilities.h"
 
-#define CPPMARK        '#'     /* mark from cpp                        */
-#define OPENDIR        '['     /* starting sign for directive          */
-#define CLOSEDIR       ']'     /* ending sign for directive            */
+#define OPENDIR     '[' /* starting sign for directive */
+#define CLOSEDIR    ']' /* ending sign for directive   */
 
-#define PM()  \
-  printf("line: %d, maxavail: %d\n",__LINE__,maxavail()); \
-  fflush(stdout)
-
-static void free_nbparam(t_nbparam **param,int nr)
+static void free_nbparam(t_nbparam **param, int nr)
 {
-  int i;
+    int i;
 
-  for(i=0; i<nr; i++)
-    sfree(param[i]);
-  sfree(param);
+    for (i = 0; i < nr; i++)
+    {
+        sfree(param[i]);
+    }
+    sfree(param);
 }
 
-static int copy_nbparams(t_nbparam **param,int ftype,t_params *plist,int nr)
+static int copy_nbparams(t_nbparam **param, int ftype, t_params *plist, int nr)
 {
-  int i,j,f;
-  int nrfp,ncopy;
-
-  nrfp = NRFP(ftype);
-  
-  ncopy = 0;
-  for(i=0; i<nr; i++)
-    for(j=0; j<=i; j++)
-      if (param[i][j].bSet) {
-       for(f=0; f<nrfp; f++) {
-         plist->param[nr*i+j].c[f] = param[i][j].c[f];
-         plist->param[nr*j+i].c[f] = param[i][j].c[f];
-       }
-       ncopy++;
-      }
-  
-  return ncopy;
+    int i, j, f;
+    int nrfp, ncopy;
+
+    nrfp = NRFP(ftype);
+
+    ncopy = 0;
+    for (i = 0; i < nr; i++)
+    {
+        for (j = 0; j <= i; j++)
+        {
+            if (param[i][j].bSet)
+            {
+                for (f = 0; f < nrfp; f++)
+                {
+                    plist->param[nr*i+j].c[f] = param[i][j].c[f];
+                    plist->param[nr*j+i].c[f] = param[i][j].c[f];
+                }
+                ncopy++;
+            }
+        }
+    }
+
+    return ncopy;
 }
 
-static void gen_pairs(t_params *nbs,t_params *pairs,real fudge, int comb, gmx_bool bVerbose)
+static void gen_pairs(t_params *nbs, t_params *pairs, real fudge, int comb)
 {
-    int     i,j,ntp,nrfp,nrfpA,nrfpB,nnn;
+    int     i, j, ntp, nrfp, nrfpA, nrfpB, nnn;
     real    scaling;
     ntp       = nbs->nr;
     nnn       = sqrt(ntp);
@@ -121,96 +126,111 @@ static void gen_pairs(t_params *nbs,t_params *pairs,real fudge, int comb, gmx_bo
     nrfpA     = interaction_function[F_LJ14].nrfpA;
     nrfpB     = interaction_function[F_LJ14].nrfpB;
     pairs->nr = ntp;
-  
-  if ((nrfp  != nrfpA) || (nrfpA != nrfpB))
-    gmx_incons("Number of force parameters in gen_pairs wrong");
-
-  fprintf(stderr,"Generating 1-4 interactions: fudge = %g\n",fudge);
-  if (debug) {
-    fprintf(debug,"Fudge factor for 1-4 interactions: %g\n",fudge);
-    fprintf(debug,"Holy Cow! there are %d types\n",ntp);
-  }
-  snew(pairs->param,pairs->nr);
-  for(i=0; (i<ntp); i++) {
-    /* Copy param.a */
-    pairs->param[i].a[0] = i / nnn;
-    pairs->param[i].a[1] = i % nnn;
-    /* Copy normal and FEP parameters and multiply by fudge factor */
-
-    
-    
-    for(j=0; (j<nrfp); j++) {
-        /* If we are using sigma/epsilon values, only the epsilon values 
-         * should be scaled, but not sigma. 
-         * The sigma values have even indices 0,2, etc.
-         */
-        if ((comb == eCOMB_ARITHMETIC || comb == eCOMB_GEOM_SIG_EPS) && (j%2==0))
-            scaling = 1.0;
-        else
-            scaling = fudge;
-        
-        pairs->param[i].c[j]=scaling*nbs->param[i].c[j];
-        pairs->param[i].c[nrfp+j]=scaling*nbs->param[i].c[j];
+
+    if ((nrfp  != nrfpA) || (nrfpA != nrfpB))
+    {
+        gmx_incons("Number of force parameters in gen_pairs wrong");
+    }
+
+    fprintf(stderr, "Generating 1-4 interactions: fudge = %g\n", fudge);
+    if (debug)
+    {
+        fprintf(debug, "Fudge factor for 1-4 interactions: %g\n", fudge);
+        fprintf(debug, "Holy Cow! there are %d types\n", ntp);
+    }
+    snew(pairs->param, pairs->nr);
+    for (i = 0; (i < ntp); i++)
+    {
+        /* Copy param.a */
+        pairs->param[i].a[0] = i / nnn;
+        pairs->param[i].a[1] = i % nnn;
+        /* Copy normal and FEP parameters and multiply by fudge factor */
+
+
+
+        for (j = 0; (j < nrfp); j++)
+        {
+            /* If we are using sigma/epsilon values, only the epsilon values
+             * should be scaled, but not sigma.
+             * The sigma values have even indices 0,2, etc.
+             */
+            if ((comb == eCOMB_ARITHMETIC || comb == eCOMB_GEOM_SIG_EPS) && (j%2 == 0))
+            {
+                scaling = 1.0;
+            }
+            else
+            {
+                scaling = fudge;
+            }
+
+            pairs->param[i].c[j]      = scaling*nbs->param[i].c[j];
+            pairs->param[i].c[nrfp+j] = scaling*nbs->param[i].c[j];
+        }
     }
-  }
 }
 
-double check_mol(gmx_mtop_t *mtop,warninp_t wi)
+double check_mol(gmx_mtop_t *mtop, warninp_t wi)
 {
-  char    buf[256];
-  int     i,mb,nmol,ri,pt;
-  double  q;
-  real    m;
-  t_atoms *atoms;
-
-  /* Check mass and charge */
-  q=0.0;
-
-  for(mb=0; mb<mtop->nmoltype; mb++) {
-    atoms = &mtop->moltype[mtop->molblock[mb].type].atoms;
-    nmol  = mtop->molblock[mb].nmol;
-    for (i=0; (i<atoms->nr); i++) {
-      q += nmol*atoms->atom[i].q;
-      m  = atoms->atom[i].m;
-      pt = atoms->atom[i].ptype;
-      /* If the particle is an atom or a nucleus it must have a mass,
-       * else, if it is a shell, a vsite or a bondshell it can have mass zero
-       */
-      if ((m <= 0.0) && ((pt == eptAtom) || (pt == eptNucleus))) {
-       ri = atoms->atom[i].resind;
-       sprintf(buf,"atom %s (Res %s-%d) has mass %g\n",
-               *(atoms->atomname[i]),
-               *(atoms->resinfo[ri].name),
-               atoms->resinfo[ri].nr,
-               m);
-       warning_error(wi,buf);
-      } else 
-       if ((m!=0) && (pt == eptVSite)) {
-         ri = atoms->atom[i].resind;
-         sprintf(buf,"virtual site %s (Res %s-%d) has non-zero mass %g\n"
-                 "     Check your topology.\n",
-                 *(atoms->atomname[i]),
-                 *(atoms->resinfo[ri].name),
-                 atoms->resinfo[ri].nr,
-                 m);
-         warning_error(wi,buf);
-         /* The following statements make LINCS break! */
-         /* atoms->atom[i].m=0; */
-       }
+    char     buf[256];
+    int      i, mb, nmol, ri, pt;
+    double   q;
+    real     m, mB;
+    t_atoms *atoms;
+
+    /* Check mass and charge */
+    q = 0.0;
+
+    for (mb = 0; mb < mtop->nmoltype; mb++)
+    {
+        atoms = &mtop->moltype[mtop->molblock[mb].type].atoms;
+        nmol  = mtop->molblock[mb].nmol;
+        for (i = 0; (i < atoms->nr); i++)
+        {
+            q += nmol*atoms->atom[i].q;
+            m  = atoms->atom[i].m;
+            mB = atoms->atom[i].mB;
+            pt = atoms->atom[i].ptype;
+            /* If the particle is an atom or a nucleus it must have a mass,
+             * else, if it is a shell, a vsite or a bondshell it can have mass zero
+             */
+            if (((m <= 0.0) || (mB <= 0.0)) && ((pt == eptAtom) || (pt == eptNucleus)))
+            {
+                ri = atoms->atom[i].resind;
+                sprintf(buf, "atom %s (Res %s-%d) has mass %g (state A) / %g (state B)\n",
+                        *(atoms->atomname[i]),
+                        *(atoms->resinfo[ri].name),
+                        atoms->resinfo[ri].nr,
+                        m, mB);
+                warning_error(wi, buf);
+            }
+            else
+            if (((m != 0) || (mB != 0)) && (pt == eptVSite))
+            {
+                ri = atoms->atom[i].resind;
+                sprintf(buf, "virtual site %s (Res %s-%d) has non-zero mass %g (state A) / %g (state B)\n"
+                        "     Check your topology.\n",
+                        *(atoms->atomname[i]),
+                        *(atoms->resinfo[ri].name),
+                        atoms->resinfo[ri].nr,
+                        m, mB);
+                warning_error(wi, buf);
+                /* The following statements make LINCS break! */
+                /* atoms->atom[i].m=0; */
+            }
+        }
     }
-  }
-  return q;
+    return q;
 }
 
-static void sum_q(t_atoms *atoms,int n,double *qt,double *qBt)
+static void sum_q(t_atoms *atoms, int n, double *qt, double *qBt)
 {
-    double qmolA,qmolB;
+    double  qmolA, qmolB;
     int     i;
 
     /* sum charge */
     qmolA = 0;
     qmolB = 0;
-    for (i=0; i<atoms->nr; i++)
+    for (i = 0; i < atoms->nr; i++)
     {
         qmolA += atoms->atom[i].q;
         qmolB += atoms->atom[i].qB;
@@ -225,243 +245,266 @@ static void sum_q(t_atoms *atoms,int n,double *qt,double *qBt)
     }
 }
 
-static void get_nbparm(char *nb_str,char *comb_str,int *nb,int *comb,
+static void get_nbparm(char *nb_str, char *comb_str, int *nb, int *comb,
                        warninp_t wi)
 {
-  int  i;
-  char warn_buf[STRLEN];
-  
-  *nb   = -1;
-  for(i=1; (i<eNBF_NR); i++)
-    if (gmx_strcasecmp(nb_str,enbf_names[i]) == 0)
-      *nb = i;
-  if (*nb == -1)
-    *nb = strtol(nb_str,NULL,10);
-  if ((*nb < 1) || (*nb >= eNBF_NR)) {
-    sprintf(warn_buf,"Invalid nonbond function selector '%s' using %s",
-           nb_str,enbf_names[1]);
-    warning_error(wi,warn_buf);
-    *nb = 1;
-  }
-  *comb = -1;
-  for(i=1; (i<eCOMB_NR); i++)
-    if (gmx_strcasecmp(comb_str,ecomb_names[i]) == 0)
-      *comb = i;
-  if (*comb == -1)
-    *comb = strtol(comb_str,NULL,10);
-  if ((*comb < 1) || (*comb >= eCOMB_NR)) {
-    sprintf(warn_buf,"Invalid combination rule selector '%s' using %s",
-           comb_str,ecomb_names[1]);
-    warning_error(wi,warn_buf);
-    *comb = 1;
-  }
+    int  i;
+    char warn_buf[STRLEN];
+
+    *nb   = -1;
+    for (i = 1; (i < eNBF_NR); i++)
+    {
+        if (gmx_strcasecmp(nb_str, enbf_names[i]) == 0)
+        {
+            *nb = i;
+        }
+    }
+    if (*nb == -1)
+    {
+        *nb = strtol(nb_str, NULL, 10);
+    }
+    if ((*nb < 1) || (*nb >= eNBF_NR))
+    {
+        sprintf(warn_buf, "Invalid nonbond function selector '%s' using %s",
+                nb_str, enbf_names[1]);
+        warning_error(wi, warn_buf);
+        *nb = 1;
+    }
+    *comb = -1;
+    for (i = 1; (i < eCOMB_NR); i++)
+    {
+        if (gmx_strcasecmp(comb_str, ecomb_names[i]) == 0)
+        {
+            *comb = i;
+        }
+    }
+    if (*comb == -1)
+    {
+        *comb = strtol(comb_str, NULL, 10);
+    }
+    if ((*comb < 1) || (*comb >= eCOMB_NR))
+    {
+        sprintf(warn_buf, "Invalid combination rule selector '%s' using %s",
+                comb_str, ecomb_names[1]);
+        warning_error(wi, warn_buf);
+        *comb = 1;
+    }
 }
 
-static char ** cpp_opts(const char *define,const char *include,
-                        const char *infile,
+static char ** cpp_opts(const char *define, const char *include,
                         warninp_t wi)
 {
-  int  n,len;
-  int  ncppopts=0;
-  const char *cppadds[2];
-  char **cppopts  = NULL;
-  const char *option[2] = { "-D","-I" };
-  const char *nopt[2]   = { "define", "include" };
-  const char *ptr;
-  const char *rptr;
-  char *buf;
-  char warn_buf[STRLEN];
-  
-  cppadds[0] = define;
-  cppadds[1] = include;
-  for(n=0; (n<2); n++) {
-    if (cppadds[n]) {
-      ptr = cppadds[n];
-      while(*ptr != '\0') {
-       while((*ptr != '\0') && isspace(*ptr))
-         ptr++;
-       rptr = ptr;
-       while((*rptr != '\0') && !isspace(*rptr))
-         rptr++;
-       len = (rptr - ptr);
-       if (len > 2) {
-         snew(buf,(len+1));
-         strncpy(buf,ptr,len);
-         if (strstr(ptr,option[n]) != ptr) {
-          set_warning_line(wi,"mdp file",-1);
-          sprintf(warn_buf,"Malformed %s option %s",nopt[n],buf);
-          warning(wi,warn_buf);
-         }
-         else {
-           srenew(cppopts,++ncppopts);
-           cppopts[ncppopts-1] = strdup(buf);
-         }
-         sfree(buf);
-         ptr = rptr;
-       }
-      }
+    int         n, len;
+    int         ncppopts = 0;
+    const char *cppadds[2];
+    char      **cppopts   = NULL;
+    const char *option[2] = { "-D", "-I" };
+    const char *nopt[2]   = { "define", "include" };
+    const char *ptr;
+    const char *rptr;
+    char       *buf;
+    char        warn_buf[STRLEN];
+
+    cppadds[0] = define;
+    cppadds[1] = include;
+    for (n = 0; (n < 2); n++)
+    {
+        if (cppadds[n])
+        {
+            ptr = cppadds[n];
+            while (*ptr != '\0')
+            {
+                while ((*ptr != '\0') && isspace(*ptr))
+                {
+                    ptr++;
+                }
+                rptr = ptr;
+                while ((*rptr != '\0') && !isspace(*rptr))
+                {
+                    rptr++;
+                }
+                len = (rptr - ptr);
+                if (len > 2)
+                {
+                    snew(buf, (len+1));
+                    strncpy(buf, ptr, len);
+                    if (strstr(ptr, option[n]) != ptr)
+                    {
+                        set_warning_line(wi, "mdp file", -1);
+                        sprintf(warn_buf, "Malformed %s option %s", nopt[n], buf);
+                        warning(wi, warn_buf);
+                    }
+                    else
+                    {
+                        srenew(cppopts, ++ncppopts);
+                        cppopts[ncppopts-1] = gmx_strdup(buf);
+                    }
+                    sfree(buf);
+                    ptr = rptr;
+                }
+            }
+        }
     }
-  }
-  srenew(cppopts,++ncppopts);
-  cppopts[ncppopts-1] = NULL;
+    srenew(cppopts, ++ncppopts);
+    cppopts[ncppopts-1] = NULL;
 
-  return cppopts;  
+    return cppopts;
 }
 
 
 int
-find_gb_bondlength(t_params *plist,int ai,int aj, real *length)
+find_gb_bondlength(t_params *plist, int ai, int aj, real *length)
 {
-    int i,j,a1,a2;
-    
-    int found=0;
+    int i, j, a1, a2;
+
+    int found = 0;
     int status;
-    
-    for(i=0;i<F_NRE && !found;i++)
+
+    for (i = 0; i < F_NRE && !found; i++)
     {
-        if(IS_CHEMBOND(i))
+        if (IS_CHEMBOND(i))
         {
-            for(j=0;j<plist[i].nr; j++)
+            for (j = 0; j < plist[i].nr; j++)
             {
-                a1=plist[i].param[j].a[0];
-                a2=plist[i].param[j].a[1];
-                
-                if( (a1==ai && a2==aj) || (a1==aj && a2==ai))
+                a1 = plist[i].param[j].a[0];
+                a2 = plist[i].param[j].a[1];
+
+                if ( (a1 == ai && a2 == aj) || (a1 == aj && a2 == ai))
                 {
                     /* Equilibrium bond distance */
-                    *length=plist[i].param[j].c[0];
-                    found=1;
+                    *length = plist[i].param[j].c[0];
+                    found   = 1;
                 }
             }
         }
     }
     status = !found;
-    
+
     return status;
 }
 
 
 int
-find_gb_anglelength(t_params *plist,int ai,int ak, real *length)
+find_gb_anglelength(t_params *plist, int ai, int ak, real *length)
 {
-    int i,j,a1,a2,a3;
-    real r12,r23,a123;
-    int found=0;
-    int status,status1,status2;
-    
+    int  i, j, a1, a2, a3;
+    real r12, r23, a123;
+    int  found = 0;
+    int  status, status1, status2;
+
     r12 = r23 = 0;
-    
-    for(i=0;i<F_NRE && !found;i++)
+
+    for (i = 0; i < F_NRE && !found; i++)
     {
-        if(IS_ANGLE(i))
+        if (IS_ANGLE(i))
         {
-            for(j=0;j<plist[i].nr; j++)
+            for (j = 0; j < plist[i].nr; j++)
             {
-                a1=plist[i].param[j].a[0];
-                a2=plist[i].param[j].a[1];
-                a3=plist[i].param[j].a[2];
+                a1 = plist[i].param[j].a[0];
+                a2 = plist[i].param[j].a[1];
+                a3 = plist[i].param[j].a[2];
 
                 /* We dont care what the middle atom is, but use it below */
-                if( (a1==ai && a3==ak) || (a1==ak && a3==ai) )
-                {                    
+                if ( (a1 == ai && a3 == ak) || (a1 == ak && a3 == ai) )
+                {
                     /* Equilibrium bond distance */
                     a123 = plist[i].param[j].c[0];
                     /* Use middle atom to find reference distances r12 and r23 */
-                    status1 = find_gb_bondlength(plist,a1,a2,&r12);
-                    status2 = find_gb_bondlength(plist,a2,a3,&r23);
-                    
-                    if(status1==0 && status2==0)
+                    status1 = find_gb_bondlength(plist, a1, a2, &r12);
+                    status2 = find_gb_bondlength(plist, a2, a3, &r23);
+
+                    if (status1 == 0 && status2 == 0)
                     {
                         /* cosine theorem to get r13 */
-                        *length=sqrt(r12*r12+r23*r23-(2*r12*r23*cos(a123/RAD2DEG)));
-                        found=1;
+                        *length = sqrt(r12*r12+r23*r23-(2*r12*r23*cos(a123/RAD2DEG)));
+                        found   = 1;
                     }
                 }
             }
         }
     }
     status = !found;
-    
+
     return status;
 }
 
-int 
-generate_gb_exclusion_interactions(t_molinfo *mi,gpp_atomtype_t atype,t_nextnb *nnb)
+int
+generate_gb_exclusion_interactions(t_molinfo *mi, gpp_atomtype_t atype, t_nextnb *nnb)
 {
-       int          i,j,k,n,ai,aj,ti,tj;
-    int          n12,n13,n14;
+    int          i, j, k, n, ai, aj, ti, tj;
+    int          n12, n13, n14;
     int          ftype;
     t_param      param;
     t_params *   plist;
     t_atoms *    at;
-    real         radiusi,radiusj;
-    real         gb_radiusi,gb_radiusj;
-    real         param_c2,param_c4;
+    real         radiusi, radiusj;
+    real         gb_radiusi, gb_radiusj;
+    real         param_c2, param_c4;
     real         distance;
-    
+
     plist = mi->plist;
     at    = &mi->atoms;
-    
-    for(n=1;n<=nnb->nrex;n++)
+
+    for (n = 1; n <= nnb->nrex; n++)
     {
-        switch(n)
+        switch (n)
         {
-            case 1: 
-                ftype=F_GB12;
+            case 1:
+                ftype    = F_GB12;
                 param_c2 = STILL_P2;
                 param_c4 = 0.8875;
                 break;
             case 2:
-                ftype=F_GB13;
+                ftype    = F_GB13;
                 param_c2 = STILL_P3;
                 param_c4 = 0.3516;
                 break;
             default:
                 /* Put all higher-order exclusions into 1,4 list so we dont miss them */
-                ftype=F_GB14;
+                ftype    = F_GB14;
                 param_c2 = STILL_P3;
                 param_c4 = 0.3516;
                 break;
         }
-        
-        for(ai=0;ai<nnb->nr;ai++)
+
+        for (ai = 0; ai < nnb->nr; ai++)
         {
             ti         = at->atom[ai].type;
-            radiusi    = get_atomtype_radius(ti,atype);
-            gb_radiusi = get_atomtype_gb_radius(ti,atype);
-            
-            for(j=0;j<nnb->nrexcl[ai][n];j++)
+            radiusi    = get_atomtype_radius(ti, atype);
+            gb_radiusi = get_atomtype_gb_radius(ti, atype);
+
+            for (j = 0; j < nnb->nrexcl[ai][n]; j++)
             {
                 aj = nnb->a[ai][n][j];
-                
+
                 /* Only add the interactions once */
-                if(aj>ai)
+                if (aj > ai)
                 {
-                    tj = at->atom[aj].type;
-                    radiusj    = get_atomtype_radius(tj,atype);
-                    gb_radiusj = get_atomtype_gb_radius(tj,atype);
-                    
-                   /* There is an exclusion of type "ftype" between atoms ai and aj */
+                    tj         = at->atom[aj].type;
+                    radiusj    = get_atomtype_radius(tj, atype);
+                    gb_radiusj = get_atomtype_gb_radius(tj, atype);
+
+                    /* There is an exclusion of type "ftype" between atoms ai and aj */
                     param.a[0] = ai;
                     param.a[1] = aj;
 
                     /* Reference distance, not used for 1-4 interactions */
-                    switch(ftype)
+                    switch (ftype)
                     {
                         case F_GB12:
-                            if(find_gb_bondlength(plist,ai,aj,&distance)!=0)
+                            if (find_gb_bondlength(plist, ai, aj, &distance) != 0)
                             {
-                                gmx_fatal(FARGS,"Cannot find bond length for atoms %d-%d",ai,aj);
+                                gmx_fatal(FARGS, "Cannot find bond length for atoms %d-%d", ai, aj);
                             }
                             break;
                         case F_GB13:
-                            if(find_gb_anglelength(plist,ai,aj,&distance)!=0)
+                            if (find_gb_anglelength(plist, ai, aj, &distance) != 0)
                             {
-                                gmx_fatal(FARGS,"Cannot find length for atoms %d-%d involved in angle",ai,aj);
-                            }                            
+                                gmx_fatal(FARGS, "Cannot find length for atoms %d-%d involved in angle", ai, aj);
+                            }
                             break;
                         default:
-                            distance=-1;
+                            distance = -1;
                             break;
                     }
                     /* Assign GB parameters */
@@ -475,21 +518,21 @@ generate_gb_exclusion_interactions(t_molinfo *mi,gpp_atomtype_t atype,t_nextnb *
                     param.c[3] = gb_radiusi+gb_radiusj;
                     /* Parameter */
                     param.c[4] = param_c4;
-                    
+
                     /* Add it to the parameter list */
-                    add_param_to_list(&plist[ftype],&param);
+                    add_param_to_list(&plist[ftype], &param);
                 }
             }
         }
-       }
-       return 0;
+    }
+    return 0;
 }
 
 
 
 
-static char **read_topol(const char *infile,const char *outfile,
-                         const char *define,const char *include,
+static char **read_topol(const char *infile, const char *outfile,
+                         const char *define, const char *include,
                          t_symtab    *symtab,
                          gpp_atomtype_t atype,
                          int         *nrmols,
@@ -504,475 +547,542 @@ static char **read_topol(const char *infile,const char *outfile,
                          gmx_bool        bFEP,
                          gmx_bool        bGenborn,
                          gmx_bool        bZero,
-                         gmx_bool        bVerbose,
                          warninp_t   wi)
 {
-  FILE       *out;
-  int        i,sl,nb_funct,comb;
-  char       *pline=NULL,**title=NULL;
-  char       line[STRLEN],errbuf[256],comb_str[256],nb_str[256];
-  char       genpairs[32];
-  char       *dirstr,*dummy2;
-  int        nrcopies,nmol,nmolb=0,nscan,ncombs,ncopy;
-  double     fLJ,fQQ,fPOW;
-  gmx_molblock_t *molb=NULL;
-  t_topology *block=NULL;
-  t_molinfo  *mi0=NULL;
-  DirStack   *DS;
-  directive  d,newd;
-  t_nbparam  **nbparam,**pair;
-  t_block2   *block2;
-  real       fudgeLJ=-1;    /* Multiplication factor to generate 1-4 from LJ */
-  gmx_bool       bReadDefaults,bReadMolType,bGenPairs,bWarn_copy_A_B;
-  double     qt=0,qBt=0; /* total charge */
-  t_bond_atomtype batype;
-  int        lastcg=-1;
-  int        dcatt=-1,nmol_couple;
-  /* File handling variables */
-  int        status,done;
-  gmx_cpp_t  handle;
-  char     *tmp_line=NULL;
-  char       warn_buf[STRLEN];
-  const char *floating_point_arithmetic_tip =
-      "Total charge should normally be an integer. See\n"
-      "http://www.gromacs.org/Documentation/Floating_Point_Arithmetic\n"
-      "for discussion on how close it should be to an integer.\n";
-  /* We need to open the output file before opening the input file,
-   * because cpp_open_file can change the current working directory.
-   */
-  if (outfile) {
-    out = gmx_fio_fopen(outfile,"w");
-  } else {
-    out = NULL;
-  }
-
-  /* open input file */
-  status = cpp_open_file(infile,&handle,cpp_opts(define,include,infile,wi));
-  if (status != 0) 
-    gmx_fatal(FARGS,cpp_error(&handle,status));
-
-  /* some local variables */
-  DS_Init(&DS);                        /* directive stack                       */
-  nmol     = 0;                        /* no molecules yet...                   */
-  d        = d_invalid;         /* first thing should be a directive    */
-  nbparam  = NULL;              /* The temporary non-bonded matrix       */
-  pair     = NULL;              /* The temporary pair interaction matrix */
-  block2   = NULL;             /* the extra exclusions                  */
-  nb_funct = F_LJ;
-  *reppow  = 12.0;              /* Default value for repulsion power     */
-  
-  comb     = 0;
-  
-  /* Init the number of CMAP torsion angles  and grid spacing */
-  plist->grid_spacing = 0;
-  plist->nc           = 0;
-       
-  bWarn_copy_A_B = bFEP;
-
-  batype = init_bond_atomtype();
-  /* parse the actual file */
-  bReadDefaults = FALSE;
-  bGenPairs     = FALSE;
-  bReadMolType  = FALSE;
-  nmol_couple = 0;
-  
-  do {
-    status = cpp_read_line(&handle,STRLEN,line);
-    done = (status == eCPP_EOF);
-    if (!done) {
-      if (status != eCPP_OK)
-       gmx_fatal(FARGS,cpp_error(&handle,status));
-      else if (out)
-       fprintf(out,"%s\n",line);
-
-      set_warning_line(wi,cpp_cur_file(&handle),cpp_cur_linenr(&handle));
-    
-      pline = strdup(line);
-    
-       /* Strip trailing '\' from pline, if it exists */
-       sl = strlen(pline);
-       if ((sl > 0) && (pline[sl-1] == CONTINUE)) {
-               pline[sl-1] = ' ';
-       }
-               
-               /* build one long line from several fragments - necessary for CMAP */
-               while (continuing(line))
-               {
-                       status = cpp_read_line(&handle,STRLEN,line);
-            set_warning_line(wi,cpp_cur_file(&handle),cpp_cur_linenr(&handle));
-                       
-                       /* Since we depend on the '\' being present to continue to read, we copy line                                           
-                        * to a tmp string, strip the '\' from that string, and cat it to pline                                                 
-                        */
-                       tmp_line=strdup(line);
-                       
-                       sl = strlen(tmp_line);
-                       if ((sl > 0) && (tmp_line[sl-1] == CONTINUE)) {
-                               tmp_line[sl-1] = ' ';
-                       }
-                       
-                       done = (status == eCPP_EOF);
-                       if (!done) {
-                               if (status != eCPP_OK)
-                                       gmx_fatal(FARGS,cpp_error(&handle,status));
-                               else if (out)
-                                       fprintf(out,"%s\n",line);
-                       }
-                       
-                       srenew(pline,strlen(pline)+strlen(tmp_line)+1);
-                       strcat(pline,tmp_line);
-            sfree(tmp_line);
-               }
-                               
-      /* skip trailing and leading spaces and comment text */
-      strip_comment (pline);
-      trim (pline);
-    
-      /* if there is something left... */
-      if ((int)strlen(pline) > 0) {
-       if (pline[0] == OPENDIR) {
-         /* A directive on this line: copy the directive 
-          * without the brackets into dirstr, then
-          * skip spaces and tabs on either side of directive
-          */
-         dirstr = strdup((pline+1));
-         if ((dummy2 = strchr (dirstr,CLOSEDIR)) != NULL)
-           (*dummy2) = 0;
-         trim (dirstr);
-         
-         if ((newd = str2dir(dirstr)) == d_invalid) {
-           sprintf(errbuf,"Invalid directive %s",dirstr);
-           warning_error(wi,errbuf);
-         }
-         else {
-           /* Directive found */
-           if (debug) 
-             fprintf(debug,"found directive '%s'\n",dir2str(newd));
-           if (DS_Check_Order (DS,newd)) {
-             DS_Push (&DS,newd);
-               d = newd;
-           }
-           else {
-             /* we should print here which directives should have
-                been present, and which actually are */
-             gmx_fatal(FARGS,"%s\nInvalid order for directive %s",
-                       cpp_error(&handle,eCPP_SYNTAX),dir2str(newd));
-             /* d = d_invalid; */
-           }
-         }
-         sfree(dirstr);
-       }
-       else if (d != d_invalid) {
-         /* Not a directive, just a plain string 
-          * use a gigantic switch to decode,
-          * if there is a valid directive!
-          */
-         switch (d) {
-         case d_defaults:
-           if (bReadDefaults)
-             gmx_fatal(FARGS,"%s\nFound a second defaults directive.\n",
-                       cpp_error(&handle,eCPP_SYNTAX));
-           bReadDefaults = TRUE;
-           nscan = sscanf(pline,"%s%s%s%lf%lf%lf",
-                          nb_str,comb_str,genpairs,&fLJ,&fQQ,&fPOW);
-           if (nscan < 2)
-            too_few(wi);
-           else {
-             bGenPairs = FALSE;
-             fudgeLJ   = 1.0;
-             *fudgeQQ  = 1.0;
-             
-             get_nbparm(nb_str,comb_str,&nb_funct,&comb,wi);
-             *combination_rule = comb;
-             if (nscan >= 3) {
-               bGenPairs = (gmx_strncasecmp(genpairs,"Y",1) == 0);
-               if (nb_funct != eNBF_LJ && bGenPairs) {
-                 gmx_fatal(FARGS,"Generating pair parameters is only supported with LJ non-bonded interactions");
-               }
-             }
-             if (nscan >= 4)
-               fudgeLJ   = fLJ;
-             if (nscan >= 5)
-               *fudgeQQ  = fQQ;
-             if (nscan >= 6)
-               *reppow   = fPOW;
-           }
-           nb_funct = ifunc_index(d_nonbond_params,nb_funct);
-           
-           break;
-         case d_atomtypes:
-           push_at(symtab,atype,batype,pline,nb_funct,
-                &nbparam,bGenPairs ? &pair : NULL,wi);
-           break;
-           
-         case d_bondtypes:
-          push_bt(d,plist,2,NULL,batype,pline,wi);
-           break;
-         case d_constrainttypes:
-          push_bt(d,plist,2,NULL,batype,pline,wi);
-           break;
-         case d_pairtypes:
-           if (bGenPairs)
-            push_nbt(d,pair,atype,pline,F_LJ14,wi);
-           else
-            push_bt(d,plist,2,atype,NULL,pline,wi);
-             break;
-         case d_angletypes:
-          push_bt(d,plist,3,NULL,batype,pline,wi);
-           break;
-         case d_dihedraltypes:
-           /* Special routine that can read both 2 and 4 atom dihedral definitions. */
-          push_dihedraltype(d,plist,batype,pline,wi);
-           break;
-
-         case d_nonbond_params:
-          push_nbt(d,nbparam,atype,pline,nb_funct,wi);
-           break;
-           /*
-             case d_blocktype:
-             nblock++;
-             srenew(block,nblock);
-             srenew(blockinfo,nblock);
-             blk0=&(block[nblock-1]);
-             bi0=&(blockinfo[nblock-1]);
-             init_top(blk0);
-             init_molinfo(bi0);
-             push_molt(symtab,bi0,pline);
-             break;
-           */
-
-         case d_implicit_genborn_params:
-          push_gb_params(atype,pline,wi);
-           break;
-
-         case d_implicit_surface_params:
-           gmx_fatal(FARGS,"Implicit surface directive not supported yet.");
-           break;
-
-         case d_cmaptypes:
-          push_cmaptype(d, plist, 5, atype, batype,pline,wi);
-               break;
-                         
-         case d_moleculetype: {
-           if (!bReadMolType) {
-             int ntype;
-          if (opts->couple_moltype != NULL &&
-              (opts->couple_lam0 == ecouplamNONE ||
-               opts->couple_lam0 == ecouplamQ ||
-               opts->couple_lam1 == ecouplamNONE ||
-               opts->couple_lam1 == ecouplamQ))
-          {
-              dcatt = add_atomtype_decoupled(symtab,atype,
-                                             &nbparam,bGenPairs?&pair:NULL);
-          }
-             ntype = get_atomtype_ntypes(atype);
-             ncombs = (ntype*(ntype+1))/2;
-             generate_nbparams(comb,nb_funct,&(plist[nb_funct]),atype,wi);
-             ncopy = copy_nbparams(nbparam,nb_funct,&(plist[nb_funct]),
-                                   ntype);
-             fprintf(stderr,"Generated %d of the %d non-bonded parameter combinations\n",ncombs-ncopy,ncombs);
-             free_nbparam(nbparam,ntype);
-             if (bGenPairs) {
-               gen_pairs(&(plist[nb_funct]),&(plist[F_LJ14]),fudgeLJ,comb,bVerbose);
-               ncopy = copy_nbparams(pair,nb_funct,&(plist[F_LJ14]),
-                                     ntype);
-               fprintf(stderr,"Generated %d of the %d 1-4 parameter combinations\n",ncombs-ncopy,ncombs);
-               free_nbparam(pair,ntype);
-             }
-             /* Copy GBSA parameters to atomtype array? */
-             
-             bReadMolType = TRUE;
-           }
-           
-           push_molt(symtab,&nmol,molinfo,pline,wi);
-           srenew(block2,nmol);
-           block2[nmol-1].nr=0;
-           mi0=&((*molinfo)[nmol-1]);
-           break;
-         }
-         case d_atoms: 
-          push_atom(symtab,&(mi0->cgs),&(mi0->atoms),atype,pline,&lastcg,wi);
-           break;
-           
-         case d_pairs: 
-          push_bond(d,plist,mi0->plist,&(mi0->atoms),atype,pline,FALSE,
-                    bGenPairs,*fudgeQQ,bZero,&bWarn_copy_A_B,wi);
-           break;
-           
-         case d_vsites2:
-         case d_vsites3:
-         case d_vsites4:
-         case d_bonds:
-         case d_angles:
-         case d_constraints:
-         case d_settles:
-         case d_position_restraints:
-         case d_angle_restraints:
-         case d_angle_restraints_z:
-         case d_distance_restraints: 
-         case d_orientation_restraints:
-         case d_dihedral_restraints:
-         case d_dihedrals:
-         case d_polarization:
-         case d_water_polarization:
-         case d_thole_polarization:
-           push_bond(d,plist,mi0->plist,&(mi0->atoms),atype,pline,TRUE,
-                  bGenPairs,*fudgeQQ,bZero,&bWarn_copy_A_B,wi);
-           break;
-         case d_cmap:
-          push_cmap(d,plist,mi0->plist,&(mi0->atoms),atype,pline,
-                    &bWarn_copy_A_B,wi);
-               break;
-                         
-         case d_vsitesn:
-          push_vsitesn(d,plist,mi0->plist,&(mi0->atoms),atype,pline,wi);
-           break;
-         case d_exclusions:
-           assert(block2);
-           if (!block2[nmol-1].nr)
-             init_block2(&(block2[nmol-1]),mi0->atoms.nr);
-           push_excl(pline,&(block2[nmol-1]));
-           break;
-         case d_system: 
-           trim(pline);
-           title=put_symtab(symtab,pline);
-           break;
-         case d_molecules: {
-           int  whichmol;
-           gmx_bool bCouple;
-           
-           push_mol(nmol,*molinfo,pline,&whichmol,&nrcopies,wi);
-           mi0=&((*molinfo)[whichmol]);
-           srenew(molb,nmolb+1);
-           molb[nmolb].type = whichmol;
-           molb[nmolb].nmol = nrcopies;
-           nmolb++;
-           
-        bCouple = (opts->couple_moltype != NULL &&
-                   (gmx_strcasecmp("system"    ,opts->couple_moltype) == 0 ||
-                    gmx_strcasecmp(*(mi0->name),opts->couple_moltype) == 0));
-        if (bCouple) {
-            nmol_couple += nrcopies;
-        }
+    FILE           *out;
+    int             i, sl, nb_funct, comb;
+    char           *pline = NULL, **title = NULL;
+    char            line[STRLEN], errbuf[256], comb_str[256], nb_str[256];
+    char            genpairs[32];
+    char           *dirstr, *dummy2;
+    int             nrcopies, nmol, nmolb = 0, nscan, ncombs, ncopy;
+    double          fLJ, fQQ, fPOW;
+    gmx_molblock_t *molb  = NULL;
+    t_topology     *block = NULL;
+    t_molinfo      *mi0   = NULL;
+    DirStack       *DS;
+    directive       d, newd;
+    t_nbparam     **nbparam, **pair;
+    t_block2       *block2;
+    real            fudgeLJ = -1;    /* Multiplication factor to generate 1-4 from LJ */
+    gmx_bool        bReadDefaults, bReadMolType, bGenPairs, bWarn_copy_A_B;
+    double          qt = 0, qBt = 0; /* total charge */
+    t_bond_atomtype batype;
+    int             lastcg = -1;
+    int             dcatt  = -1, nmol_couple;
+    /* File handling variables */
+    int             status, done;
+    gmx_cpp_t       handle;
+    char           *tmp_line = NULL;
+    char            warn_buf[STRLEN];
+    const char     *floating_point_arithmetic_tip =
+        "Total charge should normally be an integer. See\n"
+        "http://www.gromacs.org/Documentation/Floating_Point_Arithmetic\n"
+        "for discussion on how close it should be to an integer.\n";
+    /* We need to open the output file before opening the input file,
+     * because cpp_open_file can change the current working directory.
+     */
+    if (outfile)
+    {
+        out = gmx_fio_fopen(outfile, "w");
+    }
+    else
+    {
+        out = NULL;
+    }
 
-           if (mi0->atoms.nr == 0) {
-             gmx_fatal(FARGS,"Molecule type '%s' contains no atoms",
-                       *mi0->name);
-           }
-           fprintf(stderr,
-                   "Excluding %d bonded neighbours molecule type '%s'\n",
-                   mi0->nrexcl,*mi0->name);
-           sum_q(&mi0->atoms,nrcopies,&qt,&qBt);
-           if (!mi0->bProcessed) 
-             {
-            t_nextnb nnb;
-            generate_excl(mi0->nrexcl,
-                          mi0->atoms.nr,
-                          mi0->plist,
-                          &nnb,
-                          &(mi0->excls));
-            merge_excl(&(mi0->excls),&(block2[whichmol]));
-            done_block2(&(block2[whichmol]));
-            make_shake(mi0->plist,&mi0->atoms,atype,opts->nshake);
-         
-            
-            
-            /* nnb contains information about first,2nd,3rd bonded neighbors.
-             * Use this to generate GB 1-2,1-3,1-4 interactions when necessary.
-             */
-            if (bGenborn==TRUE)
+    /* open input file */
+    status = cpp_open_file(infile, &handle, cpp_opts(define, include, wi));
+    if (status != 0)
+    {
+        gmx_fatal(FARGS, cpp_error(&handle, status));
+    }
+
+    /* some local variables */
+    DS_Init(&DS);         /* directive stack                    */
+    nmol     = 0;         /* no molecules yet...                        */
+    d        = d_invalid; /* first thing should be a directive   */
+    nbparam  = NULL;      /* The temporary non-bonded matrix       */
+    pair     = NULL;      /* The temporary pair interaction matrix */
+    block2   = NULL;      /* the extra exclusions                       */
+    nb_funct = F_LJ;
+    *reppow  = 12.0;      /* Default value for repulsion power     */
+
+    comb     = 0;
+
+    /* Init the number of CMAP torsion angles  and grid spacing */
+    plist[F_CMAP].grid_spacing = 0;
+    plist[F_CMAP].nc           = 0;
+
+    bWarn_copy_A_B = bFEP;
+
+    batype = init_bond_atomtype();
+    /* parse the actual file */
+    bReadDefaults = FALSE;
+    bGenPairs     = FALSE;
+    bReadMolType  = FALSE;
+    nmol_couple   = 0;
+
+    do
+    {
+        status = cpp_read_line(&handle, STRLEN, line);
+        done   = (status == eCPP_EOF);
+        if (!done)
+        {
+            if (status != eCPP_OK)
+            {
+                gmx_fatal(FARGS, cpp_error(&handle, status));
+            }
+            else if (out)
+            {
+                fprintf(out, "%s\n", line);
+            }
+
+            set_warning_line(wi, cpp_cur_file(&handle), cpp_cur_linenr(&handle));
+
+            pline = gmx_strdup(line);
+
+            /* Strip trailing '\' from pline, if it exists */
+            sl = strlen(pline);
+            if ((sl > 0) && (pline[sl-1] == CONTINUE))
             {
-                generate_gb_exclusion_interactions(mi0,atype,&nnb);
+                pline[sl-1] = ' ';
             }
-            
-            done_nnb(&nnb);
-            
-            if (bCouple)
+
+            /* build one long line from several fragments - necessary for CMAP */
+            while (continuing(line))
             {
-                convert_moltype_couple(mi0,dcatt,*fudgeQQ,
-                                       opts->couple_lam0,opts->couple_lam1,
-                                       opts->bCoupleIntra,
-                                       nb_funct,&(plist[nb_funct]));
+                status = cpp_read_line(&handle, STRLEN, line);
+                set_warning_line(wi, cpp_cur_file(&handle), cpp_cur_linenr(&handle));
+
+                /* Since we depend on the '\' being present to continue to read, we copy line
+                 * to a tmp string, strip the '\' from that string, and cat it to pline
+                 */
+                tmp_line = gmx_strdup(line);
+
+                sl = strlen(tmp_line);
+                if ((sl > 0) && (tmp_line[sl-1] == CONTINUE))
+                {
+                    tmp_line[sl-1] = ' ';
+                }
+
+                done = (status == eCPP_EOF);
+                if (!done)
+                {
+                    if (status != eCPP_OK)
+                    {
+                        gmx_fatal(FARGS, cpp_error(&handle, status));
+                    }
+                    else if (out)
+                    {
+                        fprintf(out, "%s\n", line);
+                    }
+                }
+
+                srenew(pline, strlen(pline)+strlen(tmp_line)+1);
+                strcat(pline, tmp_line);
+                sfree(tmp_line);
             }
-            stupid_fill_block(&mi0->mols,mi0->atoms.nr,TRUE);
-            mi0->bProcessed=TRUE;
-           }
-           break;
-         }
-         default:
-           fprintf (stderr,"case: %d\n",d);
-           invalid_case();
-         }
-       }
-      }
-      sfree(pline);
-      pline=NULL;
+
+            /* skip trailing and leading spaces and comment text */
+            strip_comment (pline);
+            trim (pline);
+
+            /* if there is something left... */
+            if ((int)strlen(pline) > 0)
+            {
+                if (pline[0] == OPENDIR)
+                {
+                    /* A directive on this line: copy the directive
+                     * without the brackets into dirstr, then
+                     * skip spaces and tabs on either side of directive
+                     */
+                    dirstr = gmx_strdup((pline+1));
+                    if ((dummy2 = strchr (dirstr, CLOSEDIR)) != NULL)
+                    {
+                        (*dummy2) = 0;
+                    }
+                    trim (dirstr);
+
+                    if ((newd = str2dir(dirstr)) == d_invalid)
+                    {
+                        sprintf(errbuf, "Invalid directive %s", dirstr);
+                        warning_error(wi, errbuf);
+                    }
+                    else
+                    {
+                        /* Directive found */
+                        if (debug)
+                        {
+                            fprintf(debug, "found directive '%s'\n", dir2str(newd));
+                        }
+                        if (DS_Check_Order (DS, newd))
+                        {
+                            DS_Push (&DS, newd);
+                            d = newd;
+                        }
+                        else
+                        {
+                            /* we should print here which directives should have
+                               been present, and which actually are */
+                            gmx_fatal(FARGS, "%s\nInvalid order for directive %s",
+                                      cpp_error(&handle, eCPP_SYNTAX), dir2str(newd));
+                            /* d = d_invalid; */
+                        }
+                    }
+                    sfree(dirstr);
+                }
+                else if (d != d_invalid)
+                {
+                    /* Not a directive, just a plain string
+                     * use a gigantic switch to decode,
+                     * if there is a valid directive!
+                     */
+                    switch (d)
+                    {
+                        case d_defaults:
+                            if (bReadDefaults)
+                            {
+                                gmx_fatal(FARGS, "%s\nFound a second defaults directive.\n",
+                                          cpp_error(&handle, eCPP_SYNTAX));
+                            }
+                            bReadDefaults = TRUE;
+                            nscan         = sscanf(pline, "%s%s%s%lf%lf%lf",
+                                                   nb_str, comb_str, genpairs, &fLJ, &fQQ, &fPOW);
+                            if (nscan < 2)
+                            {
+                                too_few(wi);
+                            }
+                            else
+                            {
+                                bGenPairs = FALSE;
+                                fudgeLJ   = 1.0;
+                                *fudgeQQ  = 1.0;
+
+                                get_nbparm(nb_str, comb_str, &nb_funct, &comb, wi);
+                                *combination_rule = comb;
+                                if (nscan >= 3)
+                                {
+                                    bGenPairs = (gmx_strncasecmp(genpairs, "Y", 1) == 0);
+                                    if (nb_funct != eNBF_LJ && bGenPairs)
+                                    {
+                                        gmx_fatal(FARGS, "Generating pair parameters is only supported with LJ non-bonded interactions");
+                                    }
+                                }
+                                if (nscan >= 4)
+                                {
+                                    fudgeLJ   = fLJ;
+                                }
+                                if (nscan >= 5)
+                                {
+                                    *fudgeQQ  = fQQ;
+                                }
+                                if (nscan >= 6)
+                                {
+                                    *reppow   = fPOW;
+                                }
+                            }
+                            nb_funct = ifunc_index(d_nonbond_params, nb_funct);
+
+                            break;
+                        case d_atomtypes:
+                            push_at(symtab, atype, batype, pline, nb_funct,
+                                    &nbparam, bGenPairs ? &pair : NULL, wi);
+                            break;
+
+                        case d_bondtypes:
+                            push_bt(d, plist, 2, NULL, batype, pline, wi);
+                            break;
+                        case d_constrainttypes:
+                            push_bt(d, plist, 2, NULL, batype, pline, wi);
+                            break;
+                        case d_pairtypes:
+                            if (bGenPairs)
+                            {
+                                push_nbt(d, pair, atype, pline, F_LJ14, wi);
+                            }
+                            else
+                            {
+                                push_bt(d, plist, 2, atype, NULL, pline, wi);
+                            }
+                            break;
+                        case d_angletypes:
+                            push_bt(d, plist, 3, NULL, batype, pline, wi);
+                            break;
+                        case d_dihedraltypes:
+                            /* Special routine that can read both 2 and 4 atom dihedral definitions. */
+                            push_dihedraltype(d, plist, batype, pline, wi);
+                            break;
+
+                        case d_nonbond_params:
+                            push_nbt(d, nbparam, atype, pline, nb_funct, wi);
+                            break;
+                        /*
+                           case d_blocktype:
+                           nblock++;
+                           srenew(block,nblock);
+                           srenew(blockinfo,nblock);
+                           blk0=&(block[nblock-1]);
+                           bi0=&(blockinfo[nblock-1]);
+                           init_top(blk0);
+                           init_molinfo(bi0);
+                           push_molt(symtab,bi0,pline);
+                           break;
+                         */
+
+                        case d_implicit_genborn_params:
+                            push_gb_params(atype, pline, wi);
+                            break;
+
+                        case d_implicit_surface_params:
+                            gmx_fatal(FARGS, "Implicit surface directive not supported yet.");
+                            break;
+
+                        case d_cmaptypes:
+                            push_cmaptype(d, plist, 5, atype, batype, pline, wi);
+                            break;
+
+                        case d_moleculetype:
+                        {
+                            if (!bReadMolType)
+                            {
+                                int ntype;
+                                if (opts->couple_moltype != NULL &&
+                                    (opts->couple_lam0 == ecouplamNONE ||
+                                     opts->couple_lam0 == ecouplamQ ||
+                                     opts->couple_lam1 == ecouplamNONE ||
+                                     opts->couple_lam1 == ecouplamQ))
+                                {
+                                    dcatt = add_atomtype_decoupled(symtab, atype,
+                                                                   &nbparam, bGenPairs ? &pair : NULL);
+                                }
+                                ntype  = get_atomtype_ntypes(atype);
+                                ncombs = (ntype*(ntype+1))/2;
+                                generate_nbparams(comb, nb_funct, &(plist[nb_funct]), atype, wi);
+                                ncopy = copy_nbparams(nbparam, nb_funct, &(plist[nb_funct]),
+                                                      ntype);
+                                fprintf(stderr, "Generated %d of the %d non-bonded parameter combinations\n", ncombs-ncopy, ncombs);
+                                free_nbparam(nbparam, ntype);
+                                if (bGenPairs)
+                                {
+                                    gen_pairs(&(plist[nb_funct]), &(plist[F_LJ14]), fudgeLJ, comb);
+                                    ncopy = copy_nbparams(pair, nb_funct, &(plist[F_LJ14]),
+                                                          ntype);
+                                    fprintf(stderr, "Generated %d of the %d 1-4 parameter combinations\n", ncombs-ncopy, ncombs);
+                                    free_nbparam(pair, ntype);
+                                }
+                                /* Copy GBSA parameters to atomtype array? */
+
+                                bReadMolType = TRUE;
+                            }
+
+                            push_molt(symtab, &nmol, molinfo, pline, wi);
+                            srenew(block2, nmol);
+                            block2[nmol-1].nr = 0;
+                            mi0               = &((*molinfo)[nmol-1]);
+                            break;
+                        }
+                        case d_atoms:
+                            push_atom(symtab, &(mi0->cgs), &(mi0->atoms), atype, pline, &lastcg, wi);
+                            break;
+
+                        case d_pairs:
+                            push_bond(d, plist, mi0->plist, &(mi0->atoms), atype, pline, FALSE,
+                                      bGenPairs, *fudgeQQ, bZero, &bWarn_copy_A_B, wi);
+                            break;
+
+                        case d_vsites2:
+                        case d_vsites3:
+                        case d_vsites4:
+                        case d_bonds:
+                        case d_angles:
+                        case d_constraints:
+                        case d_settles:
+                        case d_position_restraints:
+                        case d_angle_restraints:
+                        case d_angle_restraints_z:
+                        case d_distance_restraints:
+                        case d_orientation_restraints:
+                        case d_dihedral_restraints:
+                        case d_dihedrals:
+                        case d_polarization:
+                        case d_water_polarization:
+                        case d_thole_polarization:
+                            push_bond(d, plist, mi0->plist, &(mi0->atoms), atype, pline, TRUE,
+                                      bGenPairs, *fudgeQQ, bZero, &bWarn_copy_A_B, wi);
+                            break;
+                        case d_cmap:
+                            push_cmap(d, plist, mi0->plist, &(mi0->atoms), atype, pline, wi);
+                            break;
+
+                        case d_vsitesn:
+                            push_vsitesn(d, mi0->plist, &(mi0->atoms), pline, wi);
+                            break;
+                        case d_exclusions:
+                            assert(block2);
+                            if (!block2[nmol-1].nr)
+                            {
+                                init_block2(&(block2[nmol-1]), mi0->atoms.nr);
+                            }
+                            push_excl(pline, &(block2[nmol-1]));
+                            break;
+                        case d_system:
+                            trim(pline);
+                            title = put_symtab(symtab, pline);
+                            break;
+                        case d_molecules:
+                        {
+                            int      whichmol;
+                            gmx_bool bCouple;
+
+                            push_mol(nmol, *molinfo, pline, &whichmol, &nrcopies, wi);
+                            mi0 = &((*molinfo)[whichmol]);
+                            srenew(molb, nmolb+1);
+                            molb[nmolb].type = whichmol;
+                            molb[nmolb].nmol = nrcopies;
+                            nmolb++;
+
+                            bCouple = (opts->couple_moltype != NULL &&
+                                       (gmx_strcasecmp("system", opts->couple_moltype) == 0 ||
+                                        gmx_strcasecmp(*(mi0->name), opts->couple_moltype) == 0));
+                            if (bCouple)
+                            {
+                                nmol_couple += nrcopies;
+                            }
+
+                            if (mi0->atoms.nr == 0)
+                            {
+                                gmx_fatal(FARGS, "Molecule type '%s' contains no atoms",
+                                          *mi0->name);
+                            }
+                            fprintf(stderr,
+                                    "Excluding %d bonded neighbours molecule type '%s'\n",
+                                    mi0->nrexcl, *mi0->name);
+                            sum_q(&mi0->atoms, nrcopies, &qt, &qBt);
+                            if (!mi0->bProcessed)
+                            {
+                                t_nextnb nnb;
+                                generate_excl(mi0->nrexcl,
+                                              mi0->atoms.nr,
+                                              mi0->plist,
+                                              &nnb,
+                                              &(mi0->excls));
+                                merge_excl(&(mi0->excls), &(block2[whichmol]));
+                                done_block2(&(block2[whichmol]));
+                                make_shake(mi0->plist, &mi0->atoms, opts->nshake);
+
+
+
+                                /* nnb contains information about first,2nd,3rd bonded neighbors.
+                                 * Use this to generate GB 1-2,1-3,1-4 interactions when necessary.
+                                 */
+                                if (bGenborn == TRUE)
+                                {
+                                    generate_gb_exclusion_interactions(mi0, atype, &nnb);
+                                }
+
+                                done_nnb(&nnb);
+
+                                if (bCouple)
+                                {
+                                    convert_moltype_couple(mi0, dcatt, *fudgeQQ,
+                                                           opts->couple_lam0, opts->couple_lam1,
+                                                           opts->bCoupleIntra,
+                                                           nb_funct, &(plist[nb_funct]));
+                                }
+                                stupid_fill_block(&mi0->mols, mi0->atoms.nr, TRUE);
+                                mi0->bProcessed = TRUE;
+                            }
+                            break;
+                        }
+                        default:
+                            fprintf (stderr, "case: %d\n", d);
+                            gmx_incons("unknown directive");
+                    }
+                }
+            }
+            sfree(pline);
+            pline = NULL;
+        }
+    }
+    while (!done);
+    status = cpp_close_file(&handle);
+    if (status != eCPP_OK)
+    {
+        gmx_fatal(FARGS, cpp_error(&handle, status));
+    }
+    cpp_done();
+    if (out)
+    {
+        gmx_fio_fclose(out);
     }
-  } while (!done);
-  status = cpp_close_file(&handle);
-  if (status != eCPP_OK) 
-    gmx_fatal(FARGS,cpp_error(&handle,status));
-  if (out)
-    gmx_fio_fclose(out);
-
-  if (opts->couple_moltype) {
-    if (nmol_couple == 0) {
-      gmx_fatal(FARGS,"Did not find any molecules of type '%s' for coupling",
-               opts->couple_moltype);
+
+    if (opts->couple_moltype)
+    {
+        if (nmol_couple == 0)
+        {
+            gmx_fatal(FARGS, "Did not find any molecules of type '%s' for coupling",
+                      opts->couple_moltype);
+        }
+        fprintf(stderr, "Coupling %d copies of molecule type '%s'\n",
+                nmol_couple, opts->couple_moltype);
     }
-    fprintf(stderr,"Coupling %d copies of molecule type '%s'\n",
-            nmol_couple,opts->couple_moltype);
-  }
-  
-  /* this is not very clean, but fixes core dump on empty system name */
-  if(!title)
-    title=put_symtab(symtab,"");
-  if (fabs(qt) > 1e-4) {
-    sprintf(warn_buf,"System has non-zero total charge: %.6f\n%s\n",qt,floating_point_arithmetic_tip);
-    warning_note(wi,warn_buf);
-  }
-  if (fabs(qBt) > 1e-4 && !gmx_within_tol(qBt,qt,1e-6)) {
-    sprintf(warn_buf,"State B has non-zero total charge: %.6f\n%s\n",qBt,floating_point_arithmetic_tip);
-    warning_note(wi,warn_buf);
-  }
-  DS_Done (&DS);
-  for(i=0; i<nmol; i++)
-    done_block2(&(block2[i]));
-  free(block2);
-  
-  done_bond_atomtype(&batype);
-  
-  *nrmols=nmol;
-  
-  *nmolblock = nmolb;
-  *molblock  = molb;
-  
-  return title;
+
+    /* this is not very clean, but fixes core dump on empty system name */
+    if (!title)
+    {
+        title = put_symtab(symtab, "");
+    }
+    if (fabs(qt) > 1e-4)
+    {
+        sprintf(warn_buf, "System has non-zero total charge: %.6f\n%s\n", qt, floating_point_arithmetic_tip);
+        warning_note(wi, warn_buf);
+    }
+    if (fabs(qBt) > 1e-4 && !gmx_within_tol(qBt, qt, 1e-6))
+    {
+        sprintf(warn_buf, "State B has non-zero total charge: %.6f\n%s\n", qBt, floating_point_arithmetic_tip);
+        warning_note(wi, warn_buf);
+    }
+    DS_Done (&DS);
+    for (i = 0; i < nmol; i++)
+    {
+        done_block2(&(block2[i]));
+    }
+    free(block2);
+
+    done_bond_atomtype(&batype);
+
+    *nrmols = nmol;
+
+    *nmolblock = nmolb;
+    *molblock  = molb;
+
+    return title;
 }
 
-char **do_top(gmx_bool         bVerbose,
-              const char   *topfile,
-              const char   *topppfile,
-              t_gromppopts *opts,
-              gmx_bool         bZero,
-              t_symtab     *symtab,
-              t_params     plist[],
-              int          *combination_rule,
-              double       *repulsion_power,
-              real         *fudgeQQ,
-              gpp_atomtype_t atype,
-              int          *nrmols,
-              t_molinfo    **molinfo,
-              t_inputrec   *ir,
-              int          *nmolblock,
-              gmx_molblock_t **molblock,
+char **do_top(gmx_bool          bVerbose,
+              const char       *topfile,
+              const char       *topppfile,
+              t_gromppopts     *opts,
+              gmx_bool          bZero,
+              t_symtab         *symtab,
+              t_params          plist[],
+              int              *combination_rule,
+              double           *repulsion_power,
+              real             *fudgeQQ,
+              gpp_atomtype_t    atype,
+              int              *nrmols,
+              t_molinfo       **molinfo,
+              t_inputrec       *ir,
+              int              *nmolblock,
+              gmx_molblock_t  **molblock,
               gmx_bool          bGenborn,
-              warninp_t     wi)
+              warninp_t         wi)
 {
     /* Tmpfile might contain a long path */
     const char *tmpfile;
-    char **title;
-    
+    char      **title;
+
     if (topppfile)
     {
         tmpfile = topppfile;
@@ -981,349 +1091,404 @@ char **do_top(gmx_bool         bVerbose,
     {
         tmpfile = NULL;
     }
-    
+
     if (bVerbose)
     {
         printf("processing topology...\n");
     }
-    title = read_topol(topfile,tmpfile,opts->define,opts->include,
-                       symtab,atype,nrmols,molinfo,
-                       plist,combination_rule,repulsion_power,
-                       opts,fudgeQQ,nmolblock,molblock,
-                       ir->efep!=efepNO,bGenborn,bZero,bVerbose,
-                       wi);
-    if ((*combination_rule != eCOMB_GEOMETRIC) && 
+    title = read_topol(topfile, tmpfile, opts->define, opts->include,
+                       symtab, atype, nrmols, molinfo,
+                       plist, combination_rule, repulsion_power,
+                       opts, fudgeQQ, nmolblock, molblock,
+                       ir->efep != efepNO, bGenborn, bZero, wi);
+    if ((*combination_rule != eCOMB_GEOMETRIC) &&
         (ir->vdwtype == evdwUSER))
     {
-        warning(wi,"Using sigma/epsilon based combination rules with"
+        warning(wi, "Using sigma/epsilon based combination rules with"
                 " user supplied potential function may produce unwanted"
                 " results");
     }
-    
+
     return title;
 }
 
 
-static void generate_qmexcl_moltype(gmx_moltype_t *molt,unsigned char *grpnr,
-                                   t_inputrec *ir)
+static void generate_qmexcl_moltype(gmx_moltype_t *molt, unsigned char *grpnr,
+                                    t_inputrec *ir)
 {
-  /* This routine expects molt->ilist to be of size F_NRE and ordered. */
-
-  /* generates the exclusions between the individual QM atoms, as
-   * these interactions should be handled by the QM subroutines and
-   * not by the gromacs routines 
-   */
-  int
-    i,j,l,k=0,jmax,qm_max=0,qm_nr=0,nratoms=0,link_nr=0,link_max=0;
-  atom_id 
-    *qm_arr=NULL,*link_arr=NULL,a1,a2,a3,a4,ftype=0;
-  t_blocka
-    qmexcl;
-  t_block2
-    qmexcl2;
-  gmx_bool 
-    *bQMMM,*blink,bexcl;
-
-  /* First we search and select the QM atoms in an qm_arr array that
-   * we use to create the exclusions.
-   *
-   * we take the possibility into account that a user has defined more
-   * than one QM group:
-   *
-   * for that we also need to do this an ugly work-about just in case
-   * the QM group contains the entire system...  
-   */
-  jmax = ir->opts.ngQM;
-
-  /* we first search for all the QM atoms and put them in an array 
-   */
-  for(j=0;j<jmax;j++){
-    for(i=0;i<molt->atoms.nr;i++){
-      if(qm_nr>=qm_max){
-       qm_max += 100;
-       srenew(qm_arr,qm_max);
-      }
-      if ((grpnr ? grpnr[i] : 0) == j){
-       qm_arr[qm_nr++] = i;
-      }
+    /* This routine expects molt->ilist to be of size F_NRE and ordered. */
+
+    /* generates the exclusions between the individual QM atoms, as
+     * these interactions should be handled by the QM subroutines and
+     * not by the gromacs routines
+     */
+    int
+        i, j, l, k = 0, jmax, qm_max = 0, qm_nr = 0, nratoms = 0, link_nr = 0, link_max = 0;
+    atom_id
+       *qm_arr = NULL, *link_arr = NULL, a1, a2, a3, a4, ftype = 0;
+    t_blocka
+        qmexcl;
+    t_block2
+        qmexcl2;
+    gmx_bool
+       *bQMMM, *blink, bexcl;
+
+    /* First we search and select the QM atoms in an qm_arr array that
+     * we use to create the exclusions.
+     *
+     * we take the possibility into account that a user has defined more
+     * than one QM group:
+     *
+     * for that we also need to do this an ugly work-about just in case
+     * the QM group contains the entire system...
+     */
+    jmax = ir->opts.ngQM;
+
+    /* we first search for all the QM atoms and put them in an array
+     */
+    for (j = 0; j < jmax; j++)
+    {
+        for (i = 0; i < molt->atoms.nr; i++)
+        {
+            if (qm_nr >= qm_max)
+            {
+                qm_max += 100;
+                srenew(qm_arr, qm_max);
+            }
+            if ((grpnr ? grpnr[i] : 0) == j)
+            {
+                qm_arr[qm_nr++] = i;
+            }
+        }
     }
-  }  
-  /* bQMMM[..] is an array containin TRUE/FALSE for atoms that are
-   * QM/not QM. We first set all elements to false. Afterwards we use
-   * the qm_arr to change the elements corresponding to the QM atoms
-   * to TRUE.  
-   */
-  snew(bQMMM,molt->atoms.nr);
-  for (i=0;i<molt->atoms.nr;i++)
-    bQMMM[i]=FALSE;
-  for (i=0;i<qm_nr;i++)
-    bQMMM[qm_arr[i]]=TRUE;
-  
-  /* We remove all bonded interactions (i.e. bonds,
-   * angles, dihedrals, 1-4's), involving the QM atoms. The way they
-   * are removed is as follows: if the interaction invloves 2 atoms,
-   * it is removed if both atoms are QMatoms. If it involves 3 atoms,
-   * it is removed if at least two of the atoms are QM atoms, if the
-   * interaction involves 4 atoms, it is removed if there are at least
-   * 2 QM atoms.  Since this routine is called once before any forces
-   * are computed, the top->idef.il[N].iatom[] array (see idef.h) can
-   * be rewritten at this poitn without any problem. 25-9-2002 */
-  
-  /* first check weter we already have CONNBONDS: */
-  if (molt->ilist[F_CONNBONDS].nr != 0){
-    fprintf(stderr,"nr. of CONNBONDS present already: %d\n",
-           molt->ilist[F_CONNBONDS].nr/3);
-    ftype = molt->ilist[F_CONNBONDS].iatoms[0];
-    k = molt->ilist[F_CONNBONDS].nr;
-  }
-  /* now we delete all bonded interactions, except the ones describing
-   * a chemical bond. These are converted to CONNBONDS
-   */
-  for (i=0;i<F_LJ;i++){
-    if(i==F_CONNBONDS)
-      continue;
-    nratoms = interaction_function[i].nratoms;
-    j = 0;
-    while (j<molt->ilist[i].nr){
-      bexcl = FALSE;
-      switch (nratoms){
-      case 2:
-       a1 = molt->ilist[i].iatoms[j+1];
-       a2 = molt->ilist[i].iatoms[j+2];
-       bexcl = (bQMMM[a1] && bQMMM[a2]);
-       /* a bonded beteen two QM atoms will be copied to the
-        * CONNBONDS list, for reasons mentioned above 
-        */
-       if(bexcl && i<F_ANGLES){
-         srenew(molt->ilist[F_CONNBONDS].iatoms,k+3);
-         molt->ilist[F_CONNBONDS].nr         += 3; 
-         molt->ilist[F_CONNBONDS].iatoms[k++] = ftype;
-         molt->ilist[F_CONNBONDS].iatoms[k++] = a1;
-         molt->ilist[F_CONNBONDS].iatoms[k++] = a2;
-       }
-       break;
-      case 3:
-       a1 = molt->ilist[i].iatoms[j+1];
-       a2 = molt->ilist[i].iatoms[j+2];
-       a3 = molt->ilist[i].iatoms[j+3];
-       bexcl = ((bQMMM[a1] && bQMMM[a2]) ||
-                (bQMMM[a1] && bQMMM[a3]) ||
-                (bQMMM[a2] && bQMMM[a3]));
-       break;
-      case 4:
-       a1 = molt->ilist[i].iatoms[j+1];
-       a2 = molt->ilist[i].iatoms[j+2];
-       a3 = molt->ilist[i].iatoms[j+3];
-       a4 = molt->ilist[i].iatoms[j+4];
-       bexcl = ((bQMMM[a1] && bQMMM[a2] && bQMMM[a3]) ||
-                (bQMMM[a1] && bQMMM[a2] && bQMMM[a4]) ||
-                (bQMMM[a1] && bQMMM[a3] && bQMMM[a4]) ||
-                (bQMMM[a2] && bQMMM[a3] && bQMMM[a4]));
-       break;
-      default:
-       gmx_fatal(FARGS,"no such bonded interactions with %d atoms\n",nratoms);
-      }
-      if (bexcl){
-       /* since the interaction involves QM atoms, these should be
-         * removed from the MM ilist 
-        */
-       molt->ilist[i].nr -= (nratoms+1);
-       for (l=j;l<molt->ilist[i].nr;l++)
-         molt->ilist[i].iatoms[l] = molt->ilist[i].iatoms[l+(nratoms+1)];  
-      } else {
-       j += nratoms+1; /* the +1 is for the functype */
-      }
+    /* bQMMM[..] is an array containin TRUE/FALSE for atoms that are
+     * QM/not QM. We first set all elements to false. Afterwards we use
+     * the qm_arr to change the elements corresponding to the QM atoms
+     * to TRUE.
+     */
+    snew(bQMMM, molt->atoms.nr);
+    for (i = 0; i < molt->atoms.nr; i++)
+    {
+        bQMMM[i] = FALSE;
     }
-  }
-  /* Now, we search for atoms bonded to a QM atom because we also want
-   * to exclude their nonbonded interactions with the QM atoms. The
-   * reason for this is that this interaction is accounted for in the
-   * linkatoms interaction with the QMatoms and would be counted
-   * twice.  */
-  for(i=0;i<F_NRE;i++){
-    if(IS_CHEMBOND(i)){
-      j=0;
-      while(j<molt->ilist[i].nr){
-       a1 = molt->ilist[i].iatoms[j+1];
-       a2 = molt->ilist[i].iatoms[j+2];
-       if((bQMMM[a1] && !bQMMM[a2])||(!bQMMM[a1] && bQMMM[a2])){
-         if(link_nr>=link_max){
-           link_max += 10;
-           srenew(link_arr,link_max);
-         }
-         if(bQMMM[a1]){
-           link_arr[link_nr++] = a2;
-         } else {
-           link_arr[link_nr++] = a1;
-         }
-       }
-       j+=3;
-      }
+    for (i = 0; i < qm_nr; i++)
+    {
+        bQMMM[qm_arr[i]] = TRUE;
     }
-  }   
-  snew(blink,molt->atoms.nr);   
-  for (i=0;i<molt->atoms.nr;i++)
-    blink[i]=FALSE;
-  for (i=0;i<link_nr;i++)
-    blink[link_arr[i]]=TRUE;
-  /* creating the exclusion block for the QM atoms. Each QM atom has
-   * as excluded elements all the other QMatoms (and itself).
-   */
-  qmexcl.nr = molt->atoms.nr;
-  qmexcl.nra = qm_nr*(qm_nr+link_nr)+link_nr*qm_nr; 
-  snew(qmexcl.index,qmexcl.nr+1);
-  snew(qmexcl.a,qmexcl.nra);
-  j=0;
-  for(i=0;i<qmexcl.nr;i++){
-    qmexcl.index[i]=j;
-    if(bQMMM[i]){
-      for(k=0;k<qm_nr;k++){
-       qmexcl.a[k+j] = qm_arr[k];
-      }
-      for(k=0;k<link_nr;k++){
-       qmexcl.a[qm_nr+k+j] = link_arr[k];
-      }
-      j+=(qm_nr+link_nr);
+
+    /* We remove all bonded interactions (i.e. bonds,
+     * angles, dihedrals, 1-4's), involving the QM atoms. The way they
+     * are removed is as follows: if the interaction invloves 2 atoms,
+     * it is removed if both atoms are QMatoms. If it involves 3 atoms,
+     * it is removed if at least two of the atoms are QM atoms, if the
+     * interaction involves 4 atoms, it is removed if there are at least
+     * 2 QM atoms.  Since this routine is called once before any forces
+     * are computed, the top->idef.il[N].iatom[] array (see idef.h) can
+     * be rewritten at this poitn without any problem. 25-9-2002 */
+
+    /* first check weter we already have CONNBONDS: */
+    if (molt->ilist[F_CONNBONDS].nr != 0)
+    {
+        fprintf(stderr, "nr. of CONNBONDS present already: %d\n",
+                molt->ilist[F_CONNBONDS].nr/3);
+        ftype = molt->ilist[F_CONNBONDS].iatoms[0];
+        k     = molt->ilist[F_CONNBONDS].nr;
     }
-    if(blink[i]){
-      for(k=0;k<qm_nr;k++){
-       qmexcl.a[k+j] = qm_arr[k];
-      }
-      j+=qm_nr;
+    /* now we delete all bonded interactions, except the ones describing
+     * a chemical bond. These are converted to CONNBONDS
+     */
+    for (i = 0; i < F_LJ; i++)
+    {
+        if (i == F_CONNBONDS)
+        {
+            continue;
+        }
+        nratoms = interaction_function[i].nratoms;
+        j       = 0;
+        while (j < molt->ilist[i].nr)
+        {
+            bexcl = FALSE;
+            switch (nratoms)
+            {
+                case 2:
+                    a1    = molt->ilist[i].iatoms[j+1];
+                    a2    = molt->ilist[i].iatoms[j+2];
+                    bexcl = (bQMMM[a1] && bQMMM[a2]);
+                    /* a bonded beteen two QM atoms will be copied to the
+                     * CONNBONDS list, for reasons mentioned above
+                     */
+                    if (bexcl && i < F_ANGLES)
+                    {
+                        srenew(molt->ilist[F_CONNBONDS].iatoms, k+3);
+                        molt->ilist[F_CONNBONDS].nr         += 3;
+                        molt->ilist[F_CONNBONDS].iatoms[k++] = ftype;
+                        molt->ilist[F_CONNBONDS].iatoms[k++] = a1;
+                        molt->ilist[F_CONNBONDS].iatoms[k++] = a2;
+                    }
+                    break;
+                case 3:
+                    a1    = molt->ilist[i].iatoms[j+1];
+                    a2    = molt->ilist[i].iatoms[j+2];
+                    a3    = molt->ilist[i].iatoms[j+3];
+                    bexcl = ((bQMMM[a1] && bQMMM[a2]) ||
+                             (bQMMM[a1] && bQMMM[a3]) ||
+                             (bQMMM[a2] && bQMMM[a3]));
+                    break;
+                case 4:
+                    a1    = molt->ilist[i].iatoms[j+1];
+                    a2    = molt->ilist[i].iatoms[j+2];
+                    a3    = molt->ilist[i].iatoms[j+3];
+                    a4    = molt->ilist[i].iatoms[j+4];
+                    bexcl = ((bQMMM[a1] && bQMMM[a2] && bQMMM[a3]) ||
+                             (bQMMM[a1] && bQMMM[a2] && bQMMM[a4]) ||
+                             (bQMMM[a1] && bQMMM[a3] && bQMMM[a4]) ||
+                             (bQMMM[a2] && bQMMM[a3] && bQMMM[a4]));
+                    break;
+                default:
+                    gmx_fatal(FARGS, "no such bonded interactions with %d atoms\n", nratoms);
+            }
+            if (bexcl)
+            {
+                /* since the interaction involves QM atoms, these should be
+                 * removed from the MM ilist
+                 */
+                molt->ilist[i].nr -= (nratoms+1);
+                for (l = j; l < molt->ilist[i].nr; l++)
+                {
+                    molt->ilist[i].iatoms[l] = molt->ilist[i].iatoms[l+(nratoms+1)];
+                }
+            }
+            else
+            {
+                j += nratoms+1; /* the +1 is for the functype */
+            }
+        }
     }
-  }
-  qmexcl.index[qmexcl.nr]=j;
-  
-  /* and merging with the exclusions already present in sys.
-   */
-
-  init_block2(&qmexcl2,molt->atoms.nr);
-  b_to_b2(&qmexcl, &qmexcl2);
-  merge_excl(&(molt->excls),&qmexcl2);
-  done_block2(&qmexcl2);
-
-  /* Finally, we also need to get rid of the pair interactions of the
-   * classical atom bonded to the boundary QM atoms with the QMatoms,
-   * as this interaction is already accounted for by the QM, so also
-   * here we run the risk of double counting! We proceed in a similar
-   * way as we did above for the other bonded interactions: */
-  for (i=F_LJ14;i<F_COUL14;i++){
-    nratoms = interaction_function[i].nratoms;
+    /* Now, we search for atoms bonded to a QM atom because we also want
+     * to exclude their nonbonded interactions with the QM atoms. The
+     * reason for this is that this interaction is accounted for in the
+     * linkatoms interaction with the QMatoms and would be counted
+     * twice.  */
+
+    for (i = 0; i < F_NRE; i++)
+    {
+        if (IS_CHEMBOND(i))
+        {
+            j = 0;
+            while (j < molt->ilist[i].nr)
+            {
+                a1 = molt->ilist[i].iatoms[j+1];
+                a2 = molt->ilist[i].iatoms[j+2];
+                if ((bQMMM[a1] && !bQMMM[a2]) || (!bQMMM[a1] && bQMMM[a2]))
+                {
+                    if (link_nr >= link_max)
+                    {
+                        link_max += 10;
+                        srenew(link_arr, link_max);
+                    }
+                    if (bQMMM[a1])
+                    {
+                        link_arr[link_nr++] = a2;
+                    }
+                    else
+                    {
+                        link_arr[link_nr++] = a1;
+                    }
+                }
+                j += 3;
+            }
+        }
+    }
+    snew(blink, molt->atoms.nr);
+    for (i = 0; i < molt->atoms.nr; i++)
+    {
+        blink[i] = FALSE;
+    }
+    for (i = 0; i < link_nr; i++)
+    {
+        blink[link_arr[i]] = TRUE;
+    }
+    /* creating the exclusion block for the QM atoms. Each QM atom has
+     * as excluded elements all the other QMatoms (and itself).
+     */
+    qmexcl.nr  = molt->atoms.nr;
+    qmexcl.nra = qm_nr*(qm_nr+link_nr)+link_nr*qm_nr;
+    snew(qmexcl.index, qmexcl.nr+1);
+    snew(qmexcl.a, qmexcl.nra);
     j = 0;
-    while (j<molt->ilist[i].nr){
-      bexcl = FALSE;
-      a1 = molt->ilist[i].iatoms[j+1];
-      a2 = molt->ilist[i].iatoms[j+2];
-      bexcl = ((bQMMM[a1] && bQMMM[a2])||
-              (blink[a1] && bQMMM[a2])||
-              (bQMMM[a1] && blink[a2]));
-      if (bexcl){
-       /* since the interaction involves QM atoms, these should be
-         * removed from the MM ilist 
-        */
-       molt->ilist[i].nr -= (nratoms+1);
-       for (k=j;k<molt->ilist[i].nr;k++)
-         molt->ilist[i].iatoms[k] = molt->ilist[i].iatoms[k+(nratoms+1)];  
-      } else {
-       j += nratoms+1; /* the +1 is for the functype */
-      }
+    for (i = 0; i < qmexcl.nr; i++)
+    {
+        qmexcl.index[i] = j;
+        if (bQMMM[i])
+        {
+            for (k = 0; k < qm_nr; k++)
+            {
+                qmexcl.a[k+j] = qm_arr[k];
+            }
+            for (k = 0; k < link_nr; k++)
+            {
+                qmexcl.a[qm_nr+k+j] = link_arr[k];
+            }
+            j += (qm_nr+link_nr);
+        }
+        if (blink[i])
+        {
+            for (k = 0; k < qm_nr; k++)
+            {
+                qmexcl.a[k+j] = qm_arr[k];
+            }
+            j += qm_nr;
+        }
     }
-  }  
-  
-  free(qm_arr);  
-  free(bQMMM);
-  free(link_arr);
-  free(blink);
-} /* generate_qmexcl */ 
-
-void generate_qmexcl(gmx_mtop_t *sys,t_inputrec *ir,warninp_t    wi)
-{
-  /* This routine expects molt->molt[m].ilist to be of size F_NRE and ordered.
-   */
-
-  unsigned char *grpnr;
-  int mb,mol,nat_mol,i,nr_mol_with_qm_atoms=0;
-  gmx_molblock_t *molb;
-  gmx_bool bQMMM;
-
-  grpnr = sys->groups.grpnr[egcQMMM];
-
-  for(mb=0; mb<sys->nmolblock; mb++) {
-    molb = &sys->molblock[mb];
-    nat_mol = sys->moltype[molb->type].atoms.nr;
-    for(mol=0; mol<molb->nmol; mol++) {
-      bQMMM = FALSE;
-      for(i=0; i<nat_mol; i++) {
-        if ((grpnr ? grpnr[i] : 0) < ir->opts.ngQM) {
-          bQMMM = TRUE;
+    qmexcl.index[qmexcl.nr] = j;
+
+    /* and merging with the exclusions already present in sys.
+     */
+
+    init_block2(&qmexcl2, molt->atoms.nr);
+    b_to_b2(&qmexcl, &qmexcl2);
+    merge_excl(&(molt->excls), &qmexcl2);
+    done_block2(&qmexcl2);
+
+    /* Finally, we also need to get rid of the pair interactions of the
+     * classical atom bonded to the boundary QM atoms with the QMatoms,
+     * as this interaction is already accounted for by the QM, so also
+     * here we run the risk of double counting! We proceed in a similar
+     * way as we did above for the other bonded interactions: */
+    for (i = F_LJ14; i < F_COUL14; i++)
+    {
+        nratoms = interaction_function[i].nratoms;
+        j       = 0;
+        while (j < molt->ilist[i].nr)
+        {
+            a1    = molt->ilist[i].iatoms[j+1];
+            a2    = molt->ilist[i].iatoms[j+2];
+            bexcl = ((bQMMM[a1] && bQMMM[a2]) ||
+                     (blink[a1] && bQMMM[a2]) ||
+                     (bQMMM[a1] && blink[a2]));
+            if (bexcl)
+            {
+                /* since the interaction involves QM atoms, these should be
+                 * removed from the MM ilist
+                 */
+                molt->ilist[i].nr -= (nratoms+1);
+                for (k = j; k < molt->ilist[i].nr; k++)
+                {
+                    molt->ilist[i].iatoms[k] = molt->ilist[i].iatoms[k+(nratoms+1)];
+                }
+            }
+            else
+            {
+                j += nratoms+1; /* the +1 is for the functype */
+            }
         }
-      }
-      if (bQMMM) {
-        nr_mol_with_qm_atoms++;
-        if (molb->nmol > 1) {
-           /* We need to split this molblock */
-             if (mol > 0) {
-             /* Split the molblock at this molecule */
-               sys->nmolblock++;
-            srenew(sys->molblock,sys->nmolblock);
-            for(i=sys->nmolblock-2; i >= mb;i--) {
-              sys->molblock[i+1] = sys->molblock[i];
+    }
+
+    free(qm_arr);
+    free(bQMMM);
+    free(link_arr);
+    free(blink);
+} /* generate_qmexcl */
+
+void generate_qmexcl(gmx_mtop_t *sys, t_inputrec *ir, warninp_t    wi)
+{
+    /* This routine expects molt->molt[m].ilist to be of size F_NRE and ordered.
+     */
+
+    unsigned char  *grpnr;
+    int             mb, mol, nat_mol, i, nr_mol_with_qm_atoms = 0;
+    gmx_molblock_t *molb;
+    gmx_bool        bQMMM;
+
+    grpnr = sys->groups.grpnr[egcQMMM];
+
+    for (mb = 0; mb < sys->nmolblock; mb++)
+    {
+        molb    = &sys->molblock[mb];
+        nat_mol = sys->moltype[molb->type].atoms.nr;
+        for (mol = 0; mol < molb->nmol; mol++)
+        {
+            bQMMM = FALSE;
+            for (i = 0; i < nat_mol; i++)
+            {
+                if ((grpnr ? grpnr[i] : 0) < ir->opts.ngQM)
+                {
+                    bQMMM = TRUE;
+                }
+            }
+            if (bQMMM)
+            {
+                nr_mol_with_qm_atoms++;
+                if (molb->nmol > 1)
+                {
+                    /* We need to split this molblock */
+                    if (mol > 0)
+                    {
+                        /* Split the molblock at this molecule */
+                        sys->nmolblock++;
+                        srenew(sys->molblock, sys->nmolblock);
+                        for (i = sys->nmolblock-2; i >= mb; i--)
+                        {
+                            sys->molblock[i+1] = sys->molblock[i];
+                        }
+                        sys->molblock[mb  ].nmol  = mol;
+                        sys->molblock[mb+1].nmol -= mol;
+                        mb++;
+                        molb = &sys->molblock[mb];
+                    }
+                    if (molb->nmol > 1)
+                    {
+                        /* Split the molblock after this molecule */
+                        sys->nmolblock++;
+                        srenew(sys->molblock, sys->nmolblock);
+                        molb = &sys->molblock[mb];
+                        for (i = sys->nmolblock-2; i >= mb; i--)
+                        {
+                            sys->molblock[i+1] = sys->molblock[i];
+                        }
+                        sys->molblock[mb  ].nmol  = 1;
+                        sys->molblock[mb+1].nmol -= 1;
+                    }
+
+                    /* Add a moltype for the QMMM molecule */
+                    sys->nmoltype++;
+                    srenew(sys->moltype, sys->nmoltype);
+                    /* Copy the moltype struct */
+                    sys->moltype[sys->nmoltype-1] = sys->moltype[molb->type];
+                    /* Copy the exclusions to a new array, since this is the only
+                     * thing that needs to be modified for QMMM.
+                     */
+                    copy_blocka(&sys->moltype[molb->type     ].excls,
+                                &sys->moltype[sys->nmoltype-1].excls);
+                    /* Set the molecule type for the QMMM molblock */
+                    molb->type = sys->nmoltype - 1;
+                }
+                generate_qmexcl_moltype(&sys->moltype[molb->type], grpnr, ir);
             }
-            sys->molblock[mb  ].nmol  = mol;
-            sys->molblock[mb+1].nmol -= mol;
-            mb++;
-            molb = &sys->molblock[mb];
-          }
-          if (molb->nmol > 1) {
-          /* Split the molblock after this molecule */
-            sys->nmolblock++;
-            srenew(sys->molblock,sys->nmolblock);
-            molb = &sys->molblock[mb];
-            for(i=sys->nmolblock-2; i >= mb;i--) {
-              sys->molblock[i+1] = sys->molblock[i];
+            if (grpnr)
+            {
+                grpnr += nat_mol;
             }
-            sys->molblock[mb  ].nmol  = 1;
-            sys->molblock[mb+1].nmol -= 1;
-          }
-          
-          /* Add a moltype for the QMMM molecule */
-          sys->nmoltype++;
-          srenew(sys->moltype,sys->nmoltype);
-          /* Copy the moltype struct */
-          sys->moltype[sys->nmoltype-1] = sys->moltype[molb->type];
-          /* Copy the exclusions to a new array, since this is the only
-           * thing that needs to be modified for QMMM.
-           */
-          copy_blocka(&sys->moltype[molb->type     ].excls,
-                      &sys->moltype[sys->nmoltype-1].excls);
-          /* Set the molecule type for the QMMM molblock */
-          molb->type = sys->nmoltype - 1;
         }
-         generate_qmexcl_moltype(&sys->moltype[molb->type],grpnr,ir);
-      }
-      if (grpnr) {        
-        grpnr += nat_mol;
-      }
     }
-  }
-  if(nr_mol_with_qm_atoms>1){
-      /* generate a warning is there are QM atoms in different
-       * topologies. In this case it is not possible at this stage to
-       * mutualy exclude the non-bonded interactions via the
-       * exclusions (AFAIK). Instead, the user is advised to use the
-       * energy group exclusions in the mdp file
-       */
-      warning_note(wi,
-                   "\nThe QM subsystem is divided over multiple topologies. "
-                   "The mutual non-bonded interactions cannot be excluded. "
-                   "There are two ways to achieve this:\n\n"
-                   "1) merge the topologies, such that the atoms of the QM "
-                   "subsystem are all present in one single topology file. "
-                   "In this case this warning will dissappear\n\n"
-                   "2) exclude the non-bonded interactions explicitly via the "
-                   "energygrp-excl option in the mdp file. if this is the case "
-                   "this warning may be ignored"
-                   "\n\n");
-  }   
+    if (nr_mol_with_qm_atoms > 1)
+    {
+        /* generate a warning is there are QM atoms in different
+         * topologies. In this case it is not possible at this stage to
+         * mutualy exclude the non-bonded interactions via the
+         * exclusions (AFAIK). Instead, the user is advised to use the
+         * energy group exclusions in the mdp file
+         */
+        warning_note(wi,
+                     "\nThe QM subsystem is divided over multiple topologies. "
+                     "The mutual non-bonded interactions cannot be excluded. "
+                     "There are two ways to achieve this:\n\n"
+                     "1) merge the topologies, such that the atoms of the QM "
+                     "subsystem are all present in one single topology file. "
+                     "In this case this warning will dissappear\n\n"
+                     "2) exclude the non-bonded interactions explicitly via the "
+                     "energygrp-excl option in the mdp file. if this is the case "
+                     "this warning may be ignored"
+                     "\n\n");
+    }
 }