1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*- */
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
46 #include "gromacs/fileio/confio.h"
51 #include "gromacs/fileio/futil.h"
55 #include "gmx_fatal.h"
60 #include "gromacs/fileio/pdbio.h"
66 void print_stat(rvec *x, int natoms, matrix box)
70 for (m = 0; (m < DIM); m++)
75 for (i = 0; (i < natoms); i++)
77 for (m = 0; m < DIM; m++)
79 xmin[m] = min(xmin[m], x[i][m]);
80 xmax[m] = max(xmax[m], x[i][m]);
83 for (m = 0; (m < DIM); m++)
85 fprintf(stderr, "DIM %d XMIN %8.3f XMAX %8.3f BOX %8.3f\n",
86 m, xmin[m], xmax[m], box[m][m]);
91 static gmx_bool in_box(t_pbc *pbc, rvec x)
96 /* pbc_dx_aiuc only works correctly with the rectangular box center */
97 calc_box_center(ecenterRECT, pbc->box, box_center);
99 shift = pbc_dx_aiuc(pbc, x, box_center, dx);
101 return (shift == CENTRAL);
104 static void mk_vdw(t_atoms *a, real rvdw[], gmx_atomprop_t aps,
105 real r_distance, real r_scale)
109 /* initialise van der waals arrays of configuration */
110 fprintf(stderr, "Initialising van der waals distances...\n");
111 for (i = 0; (i < a->nr); i++)
113 if (!gmx_atomprop_query(aps, epropVDW,
114 *(a->resinfo[a->atom[i].resind].name),
115 *(a->atomname[i]), &(rvdw[i])))
117 rvdw[i] = r_distance;
134 void sort_molecule(t_atoms **atoms_solvt, rvec *x, rvec *v, real *r)
136 int atnr, i, j, moltp = 0, nrmoltypes, resi_o, resi_n, resnr;
137 t_moltypes *moltypes;
138 t_atoms *atoms, *newatoms;
139 rvec *newx, *newv = NULL;
142 fprintf(stderr, "Sorting configuration\n");
144 atoms = *atoms_solvt;
146 /* copy each residue from *atoms to a molecule in *molecule */
149 for (i = 0; i < atoms->nr; i++)
151 if ( (i == 0) || (atoms->atom[i].resind != atoms->atom[i-1].resind) )
153 /* see if this was a molecule type we haven't had yet: */
155 for (j = 0; (j < nrmoltypes) && (moltp == NOTSET); j++)
157 if (strcmp(*(atoms->resinfo[atoms->atom[i].resind].name),
158 moltypes[j].name) == 0)
167 srenew(moltypes, nrmoltypes);
168 moltypes[moltp].name = *(atoms->resinfo[atoms->atom[i].resind].name);
170 while ((i+atnr < atoms->nr) &&
171 (atoms->atom[i].resind == atoms->atom[i+atnr].resind))
175 moltypes[moltp].natoms = atnr;
176 moltypes[moltp].nmol = 0;
178 moltypes[moltp].nmol++;
182 fprintf(stderr, "Found %d%s molecule type%s:\n",
183 nrmoltypes, nrmoltypes == 1 ? "" : " different", nrmoltypes == 1 ? "" : "s");
184 for (j = 0; j < nrmoltypes; j++)
188 moltypes[j].res0 = 0;
192 moltypes[j].res0 = moltypes[j-1].res0+moltypes[j-1].nmol;
194 fprintf(stderr, "%7s (%4d atoms): %5d residues\n",
195 moltypes[j].name, moltypes[j].natoms, moltypes[j].nmol);
198 /* if we have only 1 moleculetype, we don't have to sort */
201 /* find out which molecules should go where: */
202 moltypes[0].i = moltypes[0].i0 = 0;
203 for (j = 1; j < nrmoltypes; j++)
207 moltypes[j-1].i0+moltypes[j-1].natoms*moltypes[j-1].nmol;
210 /* now put them there: */
212 init_t_atoms(newatoms, atoms->nr, FALSE);
213 newatoms->nres = atoms->nres;
214 snew(newatoms->resinfo, atoms->nres);
215 snew(newx, atoms->nr);
218 snew(newv, atoms->nr);
220 snew(newr, atoms->nr);
225 for (moltp = 0; moltp < nrmoltypes; moltp++)
228 while (i < atoms->nr)
230 resi_o = atoms->atom[i].resind;
231 if (strcmp(*atoms->resinfo[resi_o].name, moltypes[moltp].name) == 0)
233 /* Copy the residue info */
234 newatoms->resinfo[resi_n] = atoms->resinfo[resi_o];
235 newatoms->resinfo[resi_n].nr = resnr;
236 /* Copy the atom info */
239 newatoms->atom[j] = atoms->atom[i];
240 newatoms->atomname[j] = atoms->atomname[i];
241 newatoms->atom[j].resind = resi_n;
242 copy_rvec(x[i], newx[j]);
245 copy_rvec(v[i], newv[j]);
251 while (i < atoms->nr && atoms->atom[i].resind == resi_o);
252 /* Increase the new residue counters */
258 /* Skip this residue */
263 while (i < atoms->nr && atoms->atom[i].resind == resi_o);
268 /* put them back into the original arrays and throw away temporary arrays */
269 sfree(atoms->atomname);
270 sfree(atoms->resinfo);
273 *atoms_solvt = newatoms;
274 for (i = 0; i < (*atoms_solvt)->nr; i++)
276 copy_rvec(newx[i], x[i]);
279 copy_rvec(newv[i], v[i]);
293 void rm_res_pbc(t_atoms *atoms, rvec *x, matrix box)
295 int i, start, n, d, nat;
301 for (n = 0; n < atoms->nr; n++)
303 if (!is_hydrogen(*(atoms->atomname[n])))
308 if ( (n+1 == atoms->nr) ||
309 (atoms->atom[n+1].resind != atoms->atom[n].resind) )
311 /* if nat==0 we have only hydrogens in the solvent,
312 we take last coordinate as cg */
316 copy_rvec(x[n], xcg);
318 svmul(1.0/nat, xcg, xcg);
319 for (d = 0; d < DIM; d++)
323 for (i = start; i <= n; i++)
325 x[i][d] += box[d][d];
329 while (xcg[d] >= box[d][d])
331 for (i = start; i <= n; i++)
333 x[i][d] -= box[d][d];
345 /* This is a (maybe) slow workaround to avoid the neighbor searching in addconf.c, which
346 * leaks memory (May 2012). The function could be deleted as soon as the momory leaks
347 * in addconf.c are fixed.
348 * However, when inserting a small molecule in a system containing not too many atoms,
349 * allPairsDistOk is probably even faster than addconf.c
352 allPairsDistOk(t_atoms *atoms, rvec *x, real *r,
353 int ePBC, matrix box,
354 t_atoms *atoms_insrt, rvec *x_n, real *r_insrt)
361 set_pbc(&pbc, ePBC, box);
362 for (i = 0; i < atoms->nr; i++)
364 for (j = 0; j < atoms_insrt->nr; j++)
366 pbc_dx(&pbc, x[i], x_n[j], dx);
368 r2 = sqr(r[i]+r_insrt[j]);
378 /* enum for random rotations of inserted solutes */
380 en_rot, en_rotXYZ, en_rotZ, en_rotNone, en_NR
383 static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int seed,
384 t_atoms *atoms, rvec **x, real **r, int ePBC, matrix box,
386 real r_distance, real r_scale, real rshell,
387 const output_env_t oenv,
388 const char* posfn, const rvec deltaR, int enum_rot,
389 gmx_bool bCheckAllPairDist)
392 static char *title_insrt;
398 int i, mol, onr, ncol;
399 real alfa = 0., beta = 0., gamma = 0.;
404 set_pbc(&pbc, ePBC, box);
406 /* read number of atoms of insert molecules */
407 get_stx_coordnum(mol_insrt, &atoms_insrt.nr);
408 if (atoms_insrt.nr == 0)
410 gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
412 /* allocate memory for atom coordinates of insert molecules */
413 snew(x_insrt, atoms_insrt.nr);
414 snew(r_insrt, atoms_insrt.nr);
415 snew(atoms_insrt.resinfo, atoms_insrt.nr);
416 snew(atoms_insrt.atomname, atoms_insrt.nr);
417 snew(atoms_insrt.atom, atoms_insrt.nr);
418 atoms_insrt.pdbinfo = NULL;
419 snew(x_n, atoms_insrt.nr);
420 snew(title_insrt, STRLEN);
422 /* read residue number, residue names, atomnames, coordinates etc. */
423 fprintf(stderr, "Reading molecule configuration \n");
424 read_stx_conf(mol_insrt, title_insrt, &atoms_insrt, x_insrt, NULL,
425 &ePBC_insrt, box_insrt);
426 fprintf(stderr, "%s\nContaining %d atoms in %d residue\n",
427 title_insrt, atoms_insrt.nr, atoms_insrt.nres);
428 srenew(atoms_insrt.resinfo, atoms_insrt.nres);
430 /* initialise van der waals arrays of insert molecules */
431 mk_vdw(&atoms_insrt, r_insrt, aps, r_distance, r_scale);
433 /* With -ip, take nmol_insrt from file posfn */
436 nmol_insrt = read_xvg(posfn, &rpos, &ncol);
439 gmx_fatal(FARGS, "Expected 3 columns (x/y/z coordinates) in file %s\n", ncol, posfn);
441 fprintf(stderr, "Read %d positions from file %s\n\n", nmol_insrt, posfn);
444 srenew(atoms->resinfo, (atoms->nres+nmol_insrt*atoms_insrt.nres));
445 srenew(atoms->atomname, (atoms->nr+atoms_insrt.nr*nmol_insrt));
446 srenew(atoms->atom, (atoms->nr+atoms_insrt.nr*nmol_insrt));
447 srenew(*x, (atoms->nr+atoms_insrt.nr*nmol_insrt));
448 srenew(*r, (atoms->nr+atoms_insrt.nr*nmol_insrt));
451 while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
453 fprintf(stderr, "\rTry %d", trial++);
454 for (i = 0; (i < atoms_insrt.nr); i++)
456 copy_rvec(x_insrt[i], x_n[i]);
461 alfa = 2*M_PI *rando(&seed);
462 beta = 2*M_PI *rando(&seed);
463 gamma = 2*M_PI *rando(&seed);
467 gamma = 2*M_PI*rando(&seed);
470 alfa = beta = gamma = 0.;
473 if (enum_rot == en_rotXYZ || (enum_rot == en_rotZ))
475 rotate_conf(atoms_insrt.nr, x_n, NULL, alfa, beta, gamma);
479 /* insert at random positions */
480 offset_x[XX] = box[XX][XX]*rando(&seed);
481 offset_x[YY] = box[YY][YY]*rando(&seed);
482 offset_x[ZZ] = box[ZZ][ZZ]*rando(&seed);
483 gen_box(0, atoms_insrt.nr, x_n, box_insrt, offset_x, TRUE);
484 if (!in_box(&pbc, x_n[0]) || !in_box(&pbc, x_n[atoms_insrt.nr-1]))
491 /* Insert at positions taken from option -ip file */
492 offset_x[XX] = rpos[XX][mol] + deltaR[XX]*(2*rando(&seed)-1);
493 offset_x[YY] = rpos[YY][mol] + deltaR[YY]*(2*rando(&seed)-1);
494 offset_x[ZZ] = rpos[ZZ][mol] + deltaR[ZZ]*(2*rando(&seed)-1);
495 for (i = 0; i < atoms_insrt.nr; i++)
497 rvec_inc(x_n[i], offset_x);
503 /* This is a (maybe) slow workaround to avoid too many calls of add_conf, which
504 * leaks memory (status May 2012). If the momory leaks in add_conf() are fixed,
505 * this check could be removed. Note, however, that allPairsDistOk is probably
506 * even faster than add_conf() when inserting a small molecule into a moderately
509 if (bCheckAllPairDist && !allPairsDistOk(atoms, *x, *r, ePBC, box, &atoms_insrt, x_n, r_insrt))
514 add_conf(atoms, x, NULL, r, FALSE, ePBC, box, TRUE,
515 &atoms_insrt, x_n, NULL, r_insrt, FALSE, rshell, 0, oenv);
517 if (atoms->nr == (atoms_insrt.nr+onr))
520 fprintf(stderr, " success (now %d atoms)!\n", atoms->nr);
523 srenew(atoms->resinfo, atoms->nres);
524 srenew(atoms->atomname, atoms->nr);
525 srenew(atoms->atom, atoms->nr);
526 srenew(*x, atoms->nr);
527 srenew(*r, atoms->nr);
529 fprintf(stderr, "\n");
530 /* print number of molecules added */
531 fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n",
532 mol, nmol_insrt, *atoms_insrt.resinfo[0].name);
537 static void add_solv(const char *fn, t_atoms *atoms, rvec **x, rvec **v, real **r,
538 int ePBC, matrix box,
540 real r_distance, real r_scale, int *atoms_added,
541 int *residues_added, real rshell, int max_sol,
542 const output_env_t oenv)
546 char filename[STRLEN];
547 char title_solvt[STRLEN];
548 t_atoms *atoms_solvt;
549 rvec *x_solvt, *v_solvt = NULL;
557 strncpy(filename, lfn, STRLEN);
559 snew(atoms_solvt, 1);
560 get_stx_coordnum(filename, &(atoms_solvt->nr));
561 if (atoms_solvt->nr == 0)
563 gmx_fatal(FARGS, "No solvent in %s, please check your input\n", filename);
565 snew(x_solvt, atoms_solvt->nr);
568 snew(v_solvt, atoms_solvt->nr);
570 snew(r_solvt, atoms_solvt->nr);
571 snew(atoms_solvt->resinfo, atoms_solvt->nr);
572 snew(atoms_solvt->atomname, atoms_solvt->nr);
573 snew(atoms_solvt->atom, atoms_solvt->nr);
574 atoms_solvt->pdbinfo = NULL;
575 fprintf(stderr, "Reading solvent configuration%s\n",
576 v_solvt ? " and velocities" : "");
577 read_stx_conf(filename, title_solvt, atoms_solvt, x_solvt, v_solvt,
578 &ePBC_solvt, box_solvt);
579 fprintf(stderr, "\"%s\"\n", title_solvt);
580 fprintf(stderr, "solvent configuration contains %d atoms in %d residues\n",
581 atoms_solvt->nr, atoms_solvt->nres);
582 fprintf(stderr, "\n");
584 /* apply pbc for solvent configuration for whole molecules */
585 rm_res_pbc(atoms_solvt, x_solvt, box_solvt);
587 /* initialise van der waals arrays of solvent configuration */
588 mk_vdw(atoms_solvt, r_solvt, aps, r_distance, r_scale);
590 /* calculate the box multiplication factors n_box[0...DIM] */
592 for (i = 0; (i < DIM); i++)
595 while (n_box[i]*box_solvt[i][i] < box[i][i])
601 fprintf(stderr, "Will generate new solvent configuration of %dx%dx%d boxes\n",
602 n_box[XX], n_box[YY], n_box[ZZ]);
604 /* realloc atoms_solvt for the new solvent configuration */
605 srenew(atoms_solvt->resinfo, atoms_solvt->nres*nmol);
606 srenew(atoms_solvt->atomname, atoms_solvt->nr*nmol);
607 srenew(atoms_solvt->atom, atoms_solvt->nr*nmol);
608 srenew(x_solvt, atoms_solvt->nr*nmol);
611 srenew(v_solvt, atoms_solvt->nr*nmol);
613 srenew(r_solvt, atoms_solvt->nr*nmol);
615 /* generate a new solvent configuration */
616 genconf(atoms_solvt, x_solvt, v_solvt, r_solvt, box_solvt, n_box);
619 print_stat(x_solvt, atoms_solvt->nr, box_solvt);
623 print_stat(x_solvt, atoms_solvt->nr, box_solvt);
625 /* Sort the solvent mixture, not the protein... */
626 sort_molecule(&atoms_solvt, x_solvt, v_solvt, r_solvt);
628 /* add the two configurations */
631 add_conf(atoms, x, v, r, TRUE, ePBC, box, FALSE,
632 atoms_solvt, x_solvt, v_solvt, r_solvt, TRUE, rshell, max_sol, oenv);
633 *atoms_added = atoms->nr-onr;
634 *residues_added = atoms->nres-onres;
639 fprintf(stderr, "Generated solvent containing %d atoms in %d residues\n",
640 *atoms_added, *residues_added);
643 static char *read_prot(const char *confin, t_atoms *atoms, rvec **x, rvec **v,
644 real **r, int *ePBC, matrix box, gmx_atomprop_t aps,
645 real r_distance, real r_scale)
651 get_stx_coordnum(confin, &natoms);
653 /* allocate memory for atom coordinates of configuration 1 */
660 init_t_atoms(atoms, natoms, FALSE);
662 /* read residue number, residue names, atomnames, coordinates etc. */
663 fprintf(stderr, "Reading solute configuration%s\n", v ? " and velocities" : "");
664 read_stx_conf(confin, title, atoms, *x, v ? *v : NULL, ePBC, box);
665 fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
666 title, atoms->nr, atoms->nres);
668 /* initialise van der waals arrays of configuration 1 */
669 mk_vdw(atoms, *r, aps, r_distance, r_scale);
674 static void update_top(t_atoms *atoms, matrix box, int NFILE, t_filenm fnm[],
677 #define TEMP_FILENM "temp.top"
679 char buf[STRLEN], buf2[STRLEN], *temp;
680 const char *topinout;
682 gmx_bool bSystem, bMolecules, bSkip;
687 for (i = 0; (i < atoms->nres); i++)
689 /* calculate number of SOLvent molecules */
690 if ( (strcmp(*atoms->resinfo[i].name, "SOL") == 0) ||
691 (strcmp(*atoms->resinfo[i].name, "WAT") == 0) ||
692 (strcmp(*atoms->resinfo[i].name, "HOH") == 0) )
698 for (i = 0; (i < atoms->nr); i++)
700 gmx_atomprop_query(aps, epropMass,
701 *atoms->resinfo[atoms->atom[i].resind].name,
702 *atoms->atomname[i], &mm);
708 fprintf(stderr, "Volume : %10g (nm^3)\n", vol);
709 fprintf(stderr, "Density : %10g (g/l)\n",
710 (mtot*1e24)/(AVOGADRO*vol));
711 fprintf(stderr, "Number of SOL molecules: %5d \n\n", nsol);
713 /* open topology file and append sol molecules */
714 topinout = ftp2fn(efTOP, NFILE, fnm);
715 if (ftp2bSet(efTOP, NFILE, fnm) )
717 fprintf(stderr, "Processing topology\n");
718 fpin = ffopen(topinout, "r");
719 fpout = ffopen(TEMP_FILENM, "w");
721 bSystem = bMolecules = FALSE;
722 while (fgets(buf, STRLEN, fpin))
727 if ((temp = strchr(buf2, '\n')) != NULL)
735 if ((temp = strchr(buf2, '\n')) != NULL)
740 if (buf2[strlen(buf2)-1] == ']')
742 buf2[strlen(buf2)-1] = '\0';
745 bSystem = (gmx_strcasecmp(buf2, "system") == 0);
746 bMolecules = (gmx_strcasecmp(buf2, "molecules") == 0);
749 else if (bSystem && nsol && (buf[0] != ';') )
751 /* if sol present, append "in water" to system name */
753 if (buf2[0] && (!strstr(buf2, " water")) )
755 sprintf(buf, "%s in water\n", buf2);
761 /* check if this is a line with solvent molecules */
762 sscanf(buf, "%4095s", buf2);
763 if (strcmp(buf2, "SOL") == 0)
765 sscanf(buf, "%*4095s %20d", &i);
776 if ((temp = strchr(buf, '\n')) != NULL)
780 fprintf(stdout, "Removing line #%d '%s' from topology file (%s)\n",
781 line, buf, topinout);
785 fprintf(fpout, "%s", buf);
791 fprintf(stdout, "Adding line for %d solvent molecules to "
792 "topology file (%s)\n", nsol, topinout);
793 fprintf(fpout, "%-15s %5d\n", "SOL", nsol);
796 /* use ffopen to generate backup of topinout */
797 fpout = ffopen(topinout, "w");
799 rename(TEMP_FILENM, topinout);
804 int gmx_genbox(int argc, char *argv[])
806 const char *desc[] = {
807 "[TT]genbox[tt] can do one of 4 things:[PAR]",
809 "1) Generate a box of solvent. Specify [TT]-cs[tt] and [TT]-box[tt]. Or specify [TT]-cs[tt] and",
810 "[TT]-cp[tt] with a structure file with a box, but without atoms.[PAR]",
812 "2) Solvate a solute configuration, e.g. a protein, in a bath of solvent ",
813 "molecules. Specify [TT]-cp[tt] (solute) and [TT]-cs[tt] (solvent). ",
814 "The box specified in the solute coordinate file ([TT]-cp[tt]) is used,",
815 "unless [TT]-box[tt] is set.",
816 "If you want the solute to be centered in the box,",
817 "the program [TT]editconf[tt] has sophisticated options",
818 "to change the box dimensions and center the solute.",
819 "Solvent molecules are removed from the box where the ",
820 "distance between any atom of the solute molecule(s) and any atom of ",
821 "the solvent molecule is less than the sum of the van der Waals radii of ",
822 "both atoms. A database ([TT]vdwradii.dat[tt]) of van der Waals radii is ",
823 "read by the program, and atoms not in the database are ",
824 "assigned a default distance [TT]-vdwd[tt].",
825 "Note that this option will also influence the distances between",
826 "solvent molecules if they contain atoms that are not in the database.",
829 "3) Insert a number ([TT]-nmol[tt]) of extra molecules ([TT]-ci[tt]) ",
830 "at random positions.",
831 "The program iterates until [TT]nmol[tt] molecules",
832 "have been inserted in the box. To test whether an insertion is ",
833 "successful the same van der Waals criterium is used as for removal of ",
834 "solvent molecules. When no appropriately-sized ",
835 "holes (holes that can hold an extra molecule) are available, the ",
836 "program tries for [TT]-nmol[tt] * [TT]-try[tt] times before giving up. ",
837 "Increase [TT]-try[tt] if you have several small holes to fill.",
838 "Option [TT]-rot[tt] defines if the molecules are randomly oriented.",
841 "4) Insert a number of molecules ([TT]-ci[tt]) at positions defined in",
842 "positions.dat ([TT]-ip[tt]). positions.dat should have 3 columns (x/y/z),",
843 "that give the displacements compared to the input molecule position ([TT]-ci[tt]).",
844 "Hence, if positions.dat should contain the absolut positions, the molecule ",
845 "must be centered to 0/0/0 before using genbox (use, e.g., editconf -center).",
846 "Comments in positions.dat starting with # are ignored. Option [TT]-dr[tt]",
847 "defines the maximally allowed displacements during insertial trials.",
848 "[TT]-try[tt] and [TT]-rot[tt] work as in mode (3) (see above)",
851 "If you need to do more than one of the above operations, it can be",
852 "best to call [TT]genbox[tt] separately for each operation, so that",
853 "you are sure of the order in which the operations occur.[PAR]",
855 "The default solvent is Simple Point Charge water (SPC), with coordinates ",
856 "from [TT]$GMXLIB/spc216.gro[tt]. These coordinates can also be used",
857 "for other 3-site water models, since a short equibilibration will remove",
858 "the small differences between the models.",
859 "Other solvents are also supported, as well as mixed solvents. The",
860 "only restriction to solvent types is that a solvent molecule consists",
861 "of exactly one residue. The residue information in the coordinate",
862 "files is used, and should therefore be more or less consistent.",
863 "In practice this means that two subsequent solvent molecules in the ",
864 "solvent coordinate file should have different residue number.",
865 "The box of solute is built by stacking the coordinates read from",
866 "the coordinate file. This means that these coordinates should be ",
867 "equlibrated in periodic boundary conditions to ensure a good",
868 "alignment of molecules on the stacking interfaces.",
869 "The [TT]-maxsol[tt] option simply adds only the first [TT]-maxsol[tt]",
870 "solvent molecules and leaves out the rest that would have fitted",
871 "into the box. This can create a void that can cause problems later.",
872 "Choose your volume wisely.[PAR]",
874 "The program can optionally rotate the solute molecule to align the",
875 "longest molecule axis along a box edge. This way the amount of solvent",
876 "molecules necessary is reduced.",
877 "It should be kept in mind that this only works for",
878 "short simulations, as e.g. an alpha-helical peptide in solution can ",
879 "rotate over 90 degrees, within 500 ps. In general it is therefore ",
880 "better to make a more or less cubic box.[PAR]",
882 "Setting [TT]-shell[tt] larger than zero will place a layer of water of",
883 "the specified thickness (nm) around the solute. Hint: it is a good",
884 "idea to put the protein in the center of a box first (using [TT]editconf[tt]).",
887 "Finally, [TT]genbox[tt] will optionally remove lines from your topology file in ",
888 "which a number of solvent molecules is already added, and adds a ",
889 "line with the total number of solvent molecules in your coordinate file."
892 const char *bugs[] = {
893 "Molecules must be whole in the initial configurations.",
894 "Many repeated neighbor searchings with -ci blows up the allocated memory. "
895 "Option -allpair avoids this using all-to-all distance checks (slow for large systems)"
899 gmx_bool bSol, bProt, bBox;
900 const char *conf_prot, *confout;
906 /* protein configuration data */
913 /* other data types */
914 int atoms_added, residues_added;
917 { efSTX, "-cp", "protein", ffOPTRD },
918 { efSTX, "-cs", "spc216", ffLIBOPTRD},
919 { efSTX, "-ci", "insert", ffOPTRD},
920 { efDAT, "-ip", "positions", ffOPTRD},
921 { efSTO, NULL, NULL, ffWRITE},
922 { efTOP, NULL, NULL, ffOPTRW},
924 #define NFILE asize(fnm)
926 static int nmol_ins = 0, nmol_try = 10, seed = 1997, enum_rot;
927 static real r_distance = 0.105, r_shell = 0, r_scale = 0.57;
928 static rvec new_box = {0.0, 0.0, 0.0}, deltaR = {0.0, 0.0, 0.0};
929 static gmx_bool bReadV = FALSE, bCheckAllPairDist = FALSE;
930 static int max_sol = 0;
932 const char *enum_rot_string[] = {NULL, "xyz", "z", "none", NULL};
934 { "-box", FALSE, etRVEC, {new_box},
936 { "-nmol", FALSE, etINT, {&nmol_ins},
937 "Number of extra molecules to insert" },
938 { "-try", FALSE, etINT, {&nmol_try},
939 "Try inserting [TT]-nmol[tt] times [TT]-try[tt] times" },
940 { "-seed", FALSE, etINT, {&seed},
941 "Random generator seed"},
942 { "-vdwd", FALSE, etREAL, {&r_distance},
943 "Default van der Waals distance"},
944 { "-vdwscale", FALSE, etREAL, {&r_scale},
945 "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." },
946 { "-shell", FALSE, etREAL, {&r_shell},
947 "Thickness of optional water layer around solute" },
948 { "-maxsol", FALSE, etINT, {&max_sol},
949 "Maximum number of solvent molecules to add if they fit in the box. If zero (default) this is ignored" },
950 { "-vel", FALSE, etBOOL, {&bReadV},
951 "Keep velocities from input solute and solvent" },
952 { "-dr", FALSE, etRVEC, {deltaR},
953 "Allowed displacement in x/y/z from positions in [TT]-ip[tt] file" },
954 { "-rot", FALSE, etENUM, {enum_rot_string},
955 "rotate inserted molecules randomly" },
956 { "-allpair", FALSE, etBOOL, {&bCheckAllPairDist},
957 "Avoid momory leaks during neighbor searching with option -ci. May be slow for large systems." },
960 if (!parse_common_args(&argc, argv, PCA_BE_NICE, NFILE, fnm, asize(pa), pa,
961 asize(desc), desc, asize(bugs), bugs, &oenv))
966 bInsert = opt2bSet("-ci", NFILE, fnm) && ((nmol_ins > 0) || opt2bSet("-ip", NFILE, fnm));
967 bSol = opt2bSet("-cs", NFILE, fnm);
968 bProt = opt2bSet("-cp", NFILE, fnm);
969 bBox = opt2parg_bSet("-box", asize(pa), pa);
970 enum_rot = nenum(enum_rot_string);
973 if (bInsert && (nmol_ins <= 0 && !opt2bSet("-ip", NFILE, fnm)))
975 gmx_fatal(FARGS, "When specifying inserted molecules (-ci), "
976 "-nmol must be larger than 0 or positions must be given with -ip");
980 gmx_fatal(FARGS, "When no solute (-cp) is specified, "
981 "a box size (-box) must be specified");
984 aps = gmx_atomprop_init();
988 /*generate a solute configuration */
989 conf_prot = opt2fn("-cp", NFILE, fnm);
990 title = read_prot(conf_prot, &atoms, &x, bReadV ? &v : NULL, &r, &ePBC, box,
991 aps, r_distance, r_scale);
994 fprintf(stderr, "Note: no velocities found\n");
998 fprintf(stderr, "Note: no atoms in %s\n", conf_prot);
1006 atoms.resinfo = NULL;
1007 atoms.atomname = NULL;
1009 atoms.pdbinfo = NULL;
1017 box[XX][XX] = new_box[XX];
1018 box[YY][YY] = new_box[YY];
1019 box[ZZ][ZZ] = new_box[ZZ];
1023 gmx_fatal(FARGS, "Undefined solute box.\nCreate one with editconf "
1024 "or give explicit -box command line option");
1027 /* add nmol_ins molecules of atoms_ins
1028 in random orientation at random place */
1031 title_ins = insert_mols(opt2fn("-ci", NFILE, fnm), nmol_ins, nmol_try, seed,
1032 &atoms, &x, &r, ePBC, box, aps,
1033 r_distance, r_scale, r_shell,
1034 oenv, opt2fn_null("-ip", NFILE, fnm), deltaR, enum_rot,
1039 title_ins = strdup("Generated by genbox");
1045 add_solv(opt2fn("-cs", NFILE, fnm), &atoms, &x, v ? &v : NULL, &r, ePBC, box,
1046 aps, r_distance, r_scale, &atoms_added, &residues_added, r_shell, max_sol,
1050 /* write new configuration 1 to file confout */
1051 confout = ftp2fn(efSTO, NFILE, fnm);
1052 fprintf(stderr, "Writing generated configuration to %s\n", confout);
1055 write_sto_conf(confout, title, &atoms, x, v, ePBC, box);
1056 /* print box sizes and box type to stderr */
1057 fprintf(stderr, "%s\n", title);
1061 write_sto_conf(confout, title_ins, &atoms, x, v, ePBC, box);
1066 /* print size of generated configuration */
1067 fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
1068 atoms.nr, atoms.nres);
1069 update_top(&atoms, box, NFILE, fnm, aps);
1071 gmx_atomprop_destroy(aps);