Refactored 'solvate' and 'insert-molecules'
authorMark Abraham <mark.j.abraham@gmail.com>
Mon, 3 Feb 2014 00:13:27 +0000 (01:13 +0100)
committerRoland Schulz <roland@rschulz.eu>
Wed, 12 Feb 2014 02:42:21 +0000 (03:42 +0100)
The use of "VDW radii" in these tools was misleading in both
documentation and code. VDW radii are used if they are found, but they
used to be scaled down via a hidden option, and the user had to
magically know what kind of number to give to -vdwd. Documented what
is going on here.

Made that hidden option public, and renamed -vdwd to -radius. Renamed
variables named r to be more reflective of their use as additive
inter-atomic exclusion half-distances. This clarified what "mk_vdw"
was really doing, and that a call to it should not be living at the
end of a function that reads in a conformation from a file. Renamed
lots of things and documented more behaviour. Freed some memory
that should have been freed all along.

This exposed some horrible use of t_atoms. Fixed the code to always
allocate on the heap, call the initializer and call the destructor.

Change-Id: I3f8bbbed07442ccc6cd8e563168f5a68736c6b40

src/gromacs/gmxpreprocess/insert-molecules.cpp
src/gromacs/gmxpreprocess/read-conformation.cpp
src/gromacs/gmxpreprocess/read-conformation.h
src/gromacs/gmxpreprocess/solvate.cpp

index 1078119aae581058581017d0c9c025bfc615ddd5..817b6d3fb52760fe1ff5a02ead0150624755676b 100644 (file)
@@ -81,9 +81,9 @@ static gmx_bool in_box(t_pbc *pbc, rvec x)
  * allPairsDistOk is probably even faster than the other code.
  */
 static gmx_bool
-allPairsDistOk(t_atoms *atoms, rvec *x, real *r,
+allPairsDistOk(t_atoms *atoms, rvec *x, real *exclusionDistances,
                int ePBC, matrix box,
-               t_atoms *atoms_insrt, rvec *x_n, real *r_insrt)
+               t_atoms *atoms_insrt, rvec *x_n, real *exclusionDistances_insrt)
 {
     int   i, j;
     rvec  dx;
@@ -97,7 +97,7 @@ allPairsDistOk(t_atoms *atoms, rvec *x, real *r,
         {
             pbc_dx(&pbc, x[i], x_n[j], dx);
             n2 = norm2(dx);
-            r2 = sqr(r[i]+r_insrt[j]);
+            r2 = sqr(exclusionDistances[i]+exclusionDistances_insrt[j]);
             if (n2 < r2)
             {
                 return FALSE;
@@ -113,9 +113,9 @@ enum {
 };
 
 static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int seed,
-                         t_atoms *atoms, rvec **x, real **r, int ePBC, matrix box,
+                         t_atoms *atoms, rvec **x, real **exclusionDistances, int ePBC, matrix box,
                          gmx_atomprop_t aps,
-                         real r_distance, real r_scale, real rshell,
+                         real defaultDistance, real scaleFactor, real rshell,
                          const output_env_t oenv,
                          const char* posfn, const rvec deltaR, int enum_rot,
                          gmx_bool bCheckAllPairDist)
@@ -124,7 +124,7 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
     static  char    *title_insrt;
     t_atoms          atoms_insrt;
     rvec            *x_insrt, *x_n;
-    real            *r_insrt;
+    real            *exclusionDistances_insrt;
     int              ePBC_insrt;
     matrix           box_insrt;
     int              i, mol, onr, ncol;
@@ -138,14 +138,17 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
     set_pbc(&pbc, ePBC, box);
 
     /* read number of atoms of insert molecules */
-    get_stx_coordnum(mol_insrt, &atoms_insrt.nr);
-    if (atoms_insrt.nr == 0)
     {
-        gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
+        int natoms;
+        get_stx_coordnum(mol_insrt, &natoms);
+        if (natoms == 0)
+        {
+            gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
+        }
+        init_t_atoms(&atoms_insrt, natoms, FALSE);
     }
     /* allocate memory for atom coordinates of insert molecules */
     snew(x_insrt, atoms_insrt.nr);
-    snew(r_insrt, atoms_insrt.nr);
     snew(atoms_insrt.resinfo, atoms_insrt.nr);
     snew(atoms_insrt.atomname, atoms_insrt.nr);
     snew(atoms_insrt.atom, atoms_insrt.nr);
@@ -161,8 +164,8 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
             title_insrt, atoms_insrt.nr, atoms_insrt.nres);
     srenew(atoms_insrt.resinfo, atoms_insrt.nres);
 
-    /* initialise van der waals arrays for inserted molecules */
-    mk_vdw(&atoms_insrt, r_insrt, aps, r_distance, r_scale);
+    /* initialise distance arrays for inserted molecules */
+    exclusionDistances_insrt = makeExclusionDistances(&atoms_insrt, aps, defaultDistance, scaleFactor);
 
     /* With -ip, take nmol_insrt from file posfn */
     if (posfn != NULL)
@@ -179,7 +182,7 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
     srenew(atoms->atomname, (atoms->nr+atoms_insrt.nr*nmol_insrt));
     srenew(atoms->atom, (atoms->nr+atoms_insrt.nr*nmol_insrt));
     srenew(*x, (atoms->nr+atoms_insrt.nr*nmol_insrt));
-    srenew(*r, (atoms->nr+atoms_insrt.nr*nmol_insrt));
+    srenew(*exclusionDistances, (atoms->nr+atoms_insrt.nr*nmol_insrt));
 
     trial = mol = 0;
     while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
@@ -240,13 +243,13 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
          * even faster than add_conf() when inserting a small molecule into a moderately
          * small system.
          */
-        if (bCheckAllPairDist && !allPairsDistOk(atoms, *x, *r, ePBC, box, &atoms_insrt, x_n, r_insrt))
+        if (bCheckAllPairDist && !allPairsDistOk(atoms, *x, *exclusionDistances, ePBC, box, &atoms_insrt, x_n, exclusionDistances_insrt))
         {
             continue;
         }
 
-        add_conf(atoms, x, NULL, r, FALSE, ePBC, box, TRUE,
-                 &atoms_insrt, x_n, NULL, r_insrt, FALSE, rshell, 0, oenv);
+        add_conf(atoms, x, NULL, exclusionDistances, FALSE, ePBC, box, TRUE,
+                 &atoms_insrt, x_n, NULL, exclusionDistances_insrt, FALSE, rshell, 0, oenv);
 
         if (atoms->nr == (atoms_insrt.nr+onr))
         {
@@ -259,13 +262,17 @@ static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int se
     srenew(atoms->atomname, atoms->nr);
     srenew(atoms->atom,     atoms->nr);
     srenew(*x,              atoms->nr);
-    srenew(*r,              atoms->nr);
+    srenew(*exclusionDistances, atoms->nr);
 
     fprintf(stderr, "\n");
     /* print number of molecules added */
     fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n",
             mol, nmol_insrt, *atoms_insrt.resinfo[0].name);
 
+    sfree(x_n);
+    sfree(exclusionDistances_insrt);
+    done_atom(&atoms_insrt);
+
     return title_insrt;
 }
 
@@ -283,11 +290,12 @@ int gmx_insert_molecules(int argc, char *argv[])
         "By default, the insertion positions are random (with initial seed",
         "specified by [TT]-seed[tt]). The program iterates until [TT]-nmol[tt]",
         "molecules have been inserted in the box. Molecules are not inserted",
-        "where the distance between any existing atom and any atom of ",
-        "the inserted molecule is less than the sum of the van der Waals radii of ",
-        "both atoms. A database ([TT]vdwradii.dat[tt]) of van der Waals radii is ",
-        "read by the program, and atoms not in the database are ",
-        "assigned a default distance [TT]-vdwd[tt].[PAR]",
+        "where the distance between any existing atom and any atom of the",
+        "inserted molecule is less than the sum based on the van der Waals",
+        "radii of both atoms. A database ([TT]vdwradii.dat[tt]) of van der",
+        "Waals radii is read by the program, and the resulting radii scaled",
+        "by [TT]-scale[tt]. If radii are not found in the database, those"
+        "atoms are assigned the (pre-scaled) distance [TT]-radius[tt].[PAR]",
 
         "A total of [TT]-nmol[tt] * [TT]-try[tt] insertion attempts are made",
         "before giving up. Increase [TT]-try[tt] if you have several small",
@@ -315,13 +323,13 @@ int gmx_insert_molecules(int argc, char *argv[])
     /* parameter data */
     gmx_bool       bProt, bBox;
     const char    *conf_prot, *confout;
-    real          *r;
-    char          *title_ins = NULL;
+    real          *exclusionDistances = NULL;
+    char          *title_ins          = NULL;
     gmx_atomprop_t aps;
 
     /* protein configuration data */
     char          *title = NULL;
-    t_atoms        atoms;
+    t_atoms       *atoms;
     rvec          *x    = NULL;
     int            ePBC = -1;
     matrix         box;
@@ -334,10 +342,10 @@ int gmx_insert_molecules(int argc, char *argv[])
     };
 #define NFILE asize(fnm)
 
-    static int      nmol_ins          = 0, nmol_try = 10, seed = 1997, enum_rot;
-    static real     r_distance        = 0.105, r_scale = 0.57;
-    static rvec     new_box           = {0.0, 0.0, 0.0}, deltaR = {0.0, 0.0, 0.0};
-    static gmx_bool bCheckAllPairDist = FALSE;
+    static int      nmol_ins               = 0, nmol_try = 10, seed = 1997, enum_rot;
+    static real     defaultDistance        = 0.105, scaleFactor = 0.57;
+    static rvec     new_box                = {0.0, 0.0, 0.0}, deltaR = {0.0, 0.0, 0.0};
+    static gmx_bool bCheckAllPairDist      = FALSE;
     output_env_t    oenv;
     const char     *enum_rot_string[] = {NULL, "xyz", "z", "none", NULL};
     t_pargs         pa[]              = {
@@ -349,10 +357,10 @@ int gmx_insert_molecules(int argc, char *argv[])
           "Try inserting [TT]-nmol[tt] times [TT]-try[tt] times" },
         { "-seed",   FALSE, etINT, {&seed},
           "Random generator seed"},
-        { "-vdwd",   FALSE, etREAL, {&r_distance},
+        { "-radius",   FALSE, etREAL, {&defaultDistance},
           "Default van der Waals distance"},
-        { "-vdwscale", FALSE, etREAL, {&r_scale},
-          "HIDDENScale factor to multiply Van der Waals radii from the database in share/gromacs/top/vdwradii.dat. The default value of 0.57 yields density close to 1000 g/l for proteins in water." },
+        { "-scale", FALSE, etREAL, {&scaleFactor},
+          "Scale factor to multiply Van der Waals radii from the database in share/gromacs/top/vdwradii.dat. The default value of 0.57 yields density close to 1000 g/l for proteins in water." },
         { "-dr",    FALSE, etRVEC, {deltaR},
           "Allowed displacement in x/y/z from positions in [TT]-ip[tt] file" },
         { "-rot", FALSE,  etENUM, {enum_rot_string},
@@ -392,29 +400,21 @@ int gmx_insert_molecules(int argc, char *argv[])
 
     aps = gmx_atomprop_init();
 
+    snew(atoms, 1);
+    init_t_atoms(atoms, 0, FALSE);
     if (bProt)
     {
-        /*generate a solute configuration */
+        /* Generate a solute configuration */
         conf_prot = opt2fn("-f", NFILE, fnm);
-        title     = read_conformation(conf_prot, &atoms, &x, NULL, &r, &ePBC, box,
-                                      aps, r_distance, r_scale);
-        if (atoms.nr == 0)
+        title     = readConformation(conf_prot, atoms, &x, NULL,
+                                     &ePBC, box);
+        exclusionDistances = makeExclusionDistances(atoms, aps, defaultDistance, scaleFactor);
+        if (atoms->nr == 0)
         {
             fprintf(stderr, "Note: no atoms in %s\n", conf_prot);
             bProt = FALSE;
         }
     }
-    else
-    {
-        atoms.nr       = 0;
-        atoms.nres     = 0;
-        atoms.resinfo  = NULL;
-        atoms.atomname = NULL;
-        atoms.atom     = NULL;
-        atoms.pdbinfo  = NULL;
-        x              = NULL;
-        r              = NULL;
-    }
     if (bBox)
     {
         ePBC = epbcXYZ;
@@ -432,8 +432,8 @@ int gmx_insert_molecules(int argc, char *argv[])
     /* add nmol_ins molecules of atoms_ins
        in random orientation at random place */
     title_ins = insert_mols(insertionMoleculeFileName, nmol_ins, nmol_try, seed,
-                            &atoms, &x, &r, ePBC, box, aps,
-                            r_distance, r_scale, 0,
+                            atoms, &x, &exclusionDistances, ePBC, box, aps,
+                            defaultDistance, scaleFactor, 0,
                             oenv, opt2fn_null("-ip", NFILE, fnm), deltaR, enum_rot,
                             bCheckAllPairDist);
 
@@ -442,20 +442,24 @@ int gmx_insert_molecules(int argc, char *argv[])
     fprintf(stderr, "Writing generated configuration to %s\n", confout);
     if (bProt)
     {
-        write_sto_conf(confout, title, &atoms, x, NULL, ePBC, box);
+        write_sto_conf(confout, title, atoms, x, NULL, ePBC, box);
         /* print box sizes and box type to stderr */
         fprintf(stderr, "%s\n", title);
     }
     else
     {
-        write_sto_conf(confout, title_ins, &atoms, x, NULL, ePBC, box);
+        write_sto_conf(confout, title_ins, atoms, x, NULL, ePBC, box);
     }
 
     /* print size of generated configuration */
     fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
-            atoms.nr, atoms.nres);
+            atoms->nr, atoms->nres);
 
     gmx_atomprop_destroy(aps);
+    sfree(exclusionDistances);
+    sfree(x);
+    done_atom(atoms);
+    sfree(atoms);
 
     return 0;
 }
index 1a9a9f1d1e136b792e3bde49c9dd9493ba15af20..cfb4718c79033ceafe97863ba2a4013735727c74 100644 (file)
 #include "types/atoms.h"
 #include "smalloc.h"
 
-void mk_vdw(t_atoms *a, real rvdw[], gmx_atomprop_t aps,
-            real r_distance, real r_scale)
+real *makeExclusionDistances(const t_atoms *a, gmx_atomprop_t aps,
+                             real defaultDistance, real scaleFactor)
 {
-    int i;
+    int   i;
+    real *exclusionDistances;
 
-    /* initialise van der waals arrays of configuration */
-    fprintf(stderr, "Initialising van der waals distances...\n");
+    snew(exclusionDistances, a->nr);
+    /* initialise arrays with distances usually based on van der Waals
+       radii */
+    fprintf(stderr, "Initialising inter-atomic distances...\n");
     for (i = 0; (i < a->nr); i++)
     {
         if (!gmx_atomprop_query(aps, epropVDW,
                                 *(a->resinfo[a->atom[i].resind].name),
-                                *(a->atomname[i]), &(rvdw[i])))
+                                *(a->atomname[i]), &(exclusionDistances[i])))
         {
-            rvdw[i] = r_distance;
+            exclusionDistances[i] = defaultDistance;
         }
         else
         {
-            rvdw[i] *= r_scale;
+            exclusionDistances[i] *= scaleFactor;
         }
     }
+    return exclusionDistances;
 }
 
-char *read_conformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
-                        real **r, int *ePBC, matrix box, gmx_atomprop_t aps,
-                        real r_distance, real r_scale)
+char *readConformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
+                       int *ePBC, matrix box)
 {
     char *title;
     int   natoms;
@@ -78,7 +81,6 @@ char *read_conformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
     {
         snew(*v, natoms);
     }
-    snew(*r, natoms);
     init_t_atoms(atoms, natoms, FALSE);
 
     /* read residue number, residue names, atomnames, coordinates etc. */
@@ -87,7 +89,5 @@ char *read_conformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
     fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
             title, atoms->nr, atoms->nres);
 
-    mk_vdw(atoms, *r, aps, r_distance, r_scale);
-
     return title;
 }
index 95e5badd21d892ef029ddb773fe3c80cfe2bc081..13386af2ee369db78be967f3f18bc95000b44a34 100644 (file)
 extern "C" {
 #endif
 
-/*! Helper function reading VDW radii
+/*! \brief Allocate and fill an array of inter-atomic half distances
  *
- * Used directly and indirectly by generate-velocities and
- * insert-molecules. */
-void mk_vdw(t_atoms *a, real rvdw[], gmx_atomprop_t aps,
-            real r_distance, real r_scale);
+ * These are either scaled VDW radii taken from vdwradii.dat, or the
+ * default value. Used directly and indirectly by solvate and
+ * insert-molecules for deciding whether molecules clash. The return
+ * pointer should be freed by the caller. */
+real *makeExclusionDistances(const t_atoms *a, gmx_atomprop_t aps,
+                             real defaultDistance, real scaleFactor);
 
-/*! Helper function to read a conformation from a file.
+/*! \brief Read a conformation from a file, allocate and fill data structures.
  *
- * Used by generate-velocities and insert-molecules. */
-char *read_conformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
-                        real **r, int *ePBC, matrix box, gmx_atomprop_t aps,
-                        real r_distance, real r_scale);
+ * Used by solvate and insert-molecules. The returned pointers *x and
+ * *v should be freed by the caller. atoms should have its destructor
+ * called. */
+char *readConformation(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
+                       int *ePBC, matrix box);
 
 #ifdef __cplusplus
 }
index 3f2dd781350bbf76f64bec89e8cc383860978530..41cc0db1d40d5cb370de1d8ff956f1534cbb80c3 100644 (file)
@@ -369,10 +369,10 @@ static void make_new_conformation(t_atoms *atoms, rvec *x, rvec *v, real *r, mat
     }
 }
 
-static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **r,
+static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **exclusionDistances,
                      int ePBC, matrix box,
                      gmx_atomprop_t aps,
-                     real r_distance, real r_scale, int *atoms_added,
+                     real defaultDistance, real scaleFactor, int *atoms_added,
                      int *residues_added, real rshell, int max_sol,
                      const output_env_t oenv)
 {
@@ -382,7 +382,7 @@ static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **
     char     title_solvt[STRLEN];
     t_atoms *atoms_solvt;
     rvec    *x_solvt, *v_solvt = NULL;
-    real    *r_solvt;
+    real    *exclusionDistances_solvt;
     int      ePBC_solvt;
     matrix   box_solvt;
     int      onr, onres;
@@ -391,18 +391,22 @@ static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **
     lfn = gmxlibfn(fn);
     strncpy(filename, lfn, STRLEN);
     sfree(lfn);
-    snew(atoms_solvt, 1);
-    get_stx_coordnum(filename, &(atoms_solvt->nr));
-    if (atoms_solvt->nr == 0)
     {
-        gmx_fatal(FARGS, "No solvent in %s, please check your input\n", filename);
+        int natoms;
+        get_stx_coordnum(filename, &natoms);
+        if (0 == natoms)
+        {
+            gmx_fatal(FARGS, "No solvent in %s, please check your input\n", filename);
+        }
+        snew(atoms_solvt, 1);
+        init_t_atoms(atoms_solvt, natoms, FALSE);
     }
     snew(x_solvt, atoms_solvt->nr);
     if (v)
     {
         snew(v_solvt, atoms_solvt->nr);
     }
-    snew(r_solvt, atoms_solvt->nr);
+    snew(exclusionDistances_solvt, atoms_solvt->nr);
     snew(atoms_solvt->resinfo, atoms_solvt->nr);
     snew(atoms_solvt->atomname, atoms_solvt->nr);
     snew(atoms_solvt->atom, atoms_solvt->nr);
@@ -419,8 +423,8 @@ static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **
     /* apply pbc for solvent configuration for whole molecules */
     rm_res_pbc(atoms_solvt, x_solvt, box_solvt);
 
-    /* initialise van der waals arrays for solvent configuration */
-    mk_vdw(atoms_solvt, r_solvt, aps, r_distance, r_scale);
+    /* initialise distance arrays for solvent configuration */
+    exclusionDistances_solvt = makeExclusionDistances(atoms_solvt, aps, defaultDistance, scaleFactor);
 
     /* calculate the box multiplication factors n_box[0...DIM] */
     nmol = 1;
@@ -445,10 +449,10 @@ static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **
     {
         srenew(v_solvt, atoms_solvt->nr*nmol);
     }
-    srenew(r_solvt, atoms_solvt->nr*nmol);
+    srenew(exclusionDistances_solvt, atoms_solvt->nr*nmol);
 
     /* generate a new solvent configuration */
-    make_new_conformation(atoms_solvt, x_solvt, v_solvt, r_solvt, box_solvt, n_box);
+    make_new_conformation(atoms_solvt, x_solvt, v_solvt, exclusionDistances_solvt, box_solvt, n_box);
 
 #ifdef DEBUG
     print_stat(x_solvt, atoms_solvt->nr, box_solvt);
@@ -458,18 +462,20 @@ static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **
     print_stat(x_solvt, atoms_solvt->nr, box_solvt);
 #endif
     /* Sort the solvent mixture, not the protein... */
-    sort_molecule(&atoms_solvt, x_solvt, v_solvt, r_solvt);
+    sort_molecule(&atoms_solvt, x_solvt, v_solvt, exclusionDistances_solvt);
 
     /* add the two configurations */
     onr   = atoms->nr;
     onres = atoms->nres;
-    add_conf(atoms, x, v, r, TRUE, ePBC, box, FALSE,
-             atoms_solvt, x_solvt, v_solvt, r_solvt, TRUE, rshell, max_sol, oenv);
+    add_conf(atoms, x, v, exclusionDistances, TRUE, ePBC, box, FALSE,
+             atoms_solvt, x_solvt, v_solvt, exclusionDistances_solvt, TRUE, rshell, max_sol, oenv);
     *atoms_added    = atoms->nr-onr;
     *residues_added = atoms->nres-onres;
 
     sfree(x_solvt);
-    sfree(r_solvt);
+    sfree(exclusionDistances_solvt);
+    done_atom(atoms_solvt);
+    sfree(atoms_solvt);
 
     fprintf(stderr, "Generated solvent containing %d atoms in %d residues\n",
             *atoms_added, *residues_added);
@@ -623,13 +629,11 @@ int gmx_solvate(int argc, char *argv[])
         "to change the box dimensions and center the solute.",
         "Solvent molecules are removed from the box where the ",
         "distance between any atom of the solute molecule(s) and any atom of ",
-        "the solvent molecule is less than the sum of the van der Waals radii of ",
-        "both atoms. A database ([TT]vdwradii.dat[tt]) of van der Waals radii is ",
-        "read by the program, and atoms not in the database are ",
-        "assigned a default distance [TT]-vdwd[tt].",
-        "Note that this option will also influence the distances between",
-        "solvent molecules if they contain atoms that are not in the database.",
-        "[PAR]",
+        "the solvent molecule is less than the sum of the scaled van der Waals",
+        "radii of both atoms. A database ([TT]vdwradii.dat[tt]) of van der",
+        "Waals radii is read by the program, and the resulting radii scaled",
+        "by [TT]-scale[tt]. If radii are not found in the database, those"
+        "atoms are assigned the (pre-scaled) distance [TT]-radius[tt].[PAR]",
 
         "The default solvent is Simple Point Charge water (SPC), with coordinates ",
         "from [TT]$GMXLIB/spc216.gro[tt]. These coordinates can also be used",
@@ -675,13 +679,13 @@ int gmx_solvate(int argc, char *argv[])
     /* parameter data */
     gmx_bool       bProt, bBox;
     const char    *conf_prot, *confout;
-    real          *r;
+    real          *exclusionDistances = NULL;
     gmx_atomprop_t aps;
 
     /* protein configuration data */
     char    *title = NULL;
-    t_atoms  atoms;
-    rvec    *x, *v = NULL;
+    t_atoms *atoms;
+    rvec    *x    = NULL, *v = NULL;
     int      ePBC = -1;
     matrix   box;
 
@@ -696,18 +700,18 @@ int gmx_solvate(int argc, char *argv[])
     };
 #define NFILE asize(fnm)
 
-    static real     r_distance = 0.105, r_shell = 0, r_scale = 0.57;
-    static rvec     new_box    = {0.0, 0.0, 0.0};
-    static gmx_bool bReadV     = FALSE;
-    static int      max_sol    = 0;
+    static real     defaultDistance = 0.105, r_shell = 0, scaleFactor = 0.57;
+    static rvec     new_box         = {0.0, 0.0, 0.0};
+    static gmx_bool bReadV          = FALSE;
+    static int      max_sol         = 0;
     output_env_t    oenv;
     t_pargs         pa[]              = {
         { "-box",    FALSE, etRVEC, {new_box},
           "Box size (in nm)" },
-        { "-vdwd",   FALSE, etREAL, {&r_distance},
+        { "-radius",   FALSE, etREAL, {&defaultDistance},
           "Default van der Waals distance"},
-        { "-vdwscale", FALSE, etREAL, {&r_scale},
-          "HIDDENScale factor to multiply Van der Waals radii from the database in share/gromacs/top/vdwradii.dat. The default value of 0.57 yields density close to 1000 g/l for proteins in water." },
+        { "-scale", FALSE, etREAL, {&scaleFactor},
+          "Scale factor to multiply Van der Waals radii from the database in share/gromacs/top/vdwradii.dat. The default value of 0.57 yields density close to 1000 g/l for proteins in water." },
         { "-shell",  FALSE, etREAL, {&r_shell},
           "Thickness of optional water layer around solute" },
         { "-maxsol", FALSE, etINT,  {&max_sol},
@@ -735,33 +739,26 @@ int gmx_solvate(int argc, char *argv[])
 
     aps = gmx_atomprop_init();
 
+    snew(atoms, 1);
+    init_t_atoms(atoms, 0, FALSE);
     if (bProt)
     {
         /* Generate a solute configuration */
         conf_prot = opt2fn("-cp", NFILE, fnm);
-        title     = read_conformation(conf_prot, &atoms, &x, bReadV ? &v : NULL, &r, &ePBC, box,
-                                      aps, r_distance, r_scale);
+        title     = readConformation(conf_prot, atoms, &x,
+                                     bReadV ? &v : NULL, &ePBC, box);
+        exclusionDistances = makeExclusionDistances(atoms, aps, defaultDistance, scaleFactor);
+
         if (bReadV && !v)
         {
             fprintf(stderr, "Note: no velocities found\n");
         }
-        if (atoms.nr == 0)
+        if (atoms->nr == 0)
         {
             fprintf(stderr, "Note: no atoms in %s\n", conf_prot);
             bProt = FALSE;
         }
     }
-    else
-    {
-        atoms.nr       = 0;
-        atoms.nres     = 0;
-        atoms.resinfo  = NULL;
-        atoms.atomname = NULL;
-        atoms.atom     = NULL;
-        atoms.pdbinfo  = NULL;
-        x              = NULL;
-        r              = NULL;
-    }
     if (bBox)
     {
         ePBC = epbcXYZ;
@@ -776,8 +773,8 @@ int gmx_solvate(int argc, char *argv[])
                   "or give explicit -box command line option");
     }
 
-    add_solv(solventFileName, &atoms, &x, v ? &v : NULL, &r, ePBC, box,
-             aps, r_distance, r_scale, &atoms_added, &residues_added, r_shell, max_sol,
+    add_solv(solventFileName, atoms, &x, v ? &v : NULL, &exclusionDistances, ePBC, box,
+             aps, defaultDistance, scaleFactor, &atoms_added, &residues_added, r_shell, max_sol,
              oenv);
 
     /* write new configuration 1 to file confout */
@@ -785,21 +782,26 @@ int gmx_solvate(int argc, char *argv[])
     fprintf(stderr, "Writing generated configuration to %s\n", confout);
     if (bProt)
     {
-        write_sto_conf(confout, title, &atoms, x, v, ePBC, box);
+        write_sto_conf(confout, title, atoms, x, v, ePBC, box);
         /* print box sizes and box type to stderr */
         fprintf(stderr, "%s\n", title);
     }
     else
     {
-        write_sto_conf(confout, "Generated by gmx solvate", &atoms, x, v, ePBC, box);
+        write_sto_conf(confout, "Generated by gmx solvate", atoms, x, v, ePBC, box);
     }
 
     /* print size of generated configuration */
     fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
-            atoms.nr, atoms.nres);
-    update_top(&atoms, box, NFILE, fnm, aps);
+            atoms->nr, atoms->nres);
+    update_top(atoms, box, NFILE, fnm, aps);
 
     gmx_atomprop_destroy(aps);
+    sfree(exclusionDistances);
+    sfree(x);
+    sfree(v);
+    done_atom(atoms);
+    sfree(atoms);
 
     return 0;
 }