2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
52 #include "gmx_fatal.h"
65 static t_charge *mk_charge(t_atoms *atoms,t_block *cgs,int *nncg)
69 int i,j,ncg,resnr,anr;
72 /* Find the charged groups */
74 for(i=0; (i<cgs->nr); i++) {
76 for(j=cgs->index[i]; (j<cgs->index[i+1]); j++) {
79 if (fabs(qq) > 1.0e-5) {
84 resnr=atoms->atom[anr].resind;
85 sprintf(buf,"%s%d-%d",
86 *(atoms->resinfo[resnr].name),
87 atoms->resinfo[resnr].nr,
89 cg[ncg].label=strdup(buf);
95 for(i=0; (i<ncg); i++) {
96 printf("CG: %10s Q: %6g Atoms:",
98 for(j=cgs->index[cg[i].cg]; (j<cgs->index[cg[i].cg+1]); j++)
106 static real calc_dist(t_pbc *pbc,rvec x[],t_block *cgs,int icg,int jcg)
110 real d2,mindist2=1000;
112 for(i=cgs->index[icg]; (i<cgs->index[icg+1]); i++) {
113 for(j=cgs->index[jcg]; (j<cgs->index[jcg+1]); j++) {
114 pbc_dx(pbc,x[i],x[j],dx);
120 return sqrt(mindist2);
123 int gmx_saltbr(int argc,char *argv[])
125 const char *desc[] = {
126 "[TT]g_saltbr[tt] plots the distance between all combination of charged groups",
127 "as a function of time. The groups are combined in different ways.",
128 "A minimum distance can be given (i.e. a cut-off), such that groups",
129 "that are never closer than that distance will not be plotted.[PAR]",
130 "Output will be in a number of fixed filenames, [TT]min-min.xvg[tt], [TT]plus-min.xvg[tt]",
131 "and [TT]plus-plus.xvg[tt], or files for every individual ion pair if the [TT]-sep[tt]",
132 "option is selected. In this case, files are named as [TT]sb-(Resname)(Resnr)-(Atomnr)[tt].",
133 "There may be [BB]many[bb] such files."
135 static gmx_bool bSep=FALSE;
136 static real truncate=1000.0;
138 { "-t", FALSE, etREAL, {&truncate},
139 "Groups that are never closer than this distance are not plotted" },
140 { "-sep", FALSE, etBOOL, {&bSep},
141 "Use separate files for each interaction (may be MANY)" }
144 { efTRX, "-f", NULL, ffREAD },
145 { efTPX, NULL, NULL, ffREAD },
147 #define NFILE asize(fnm)
150 static const char *title[3] = {
151 "Distance between positively charged groups",
152 "Distance between negatively charged groups",
153 "Distance between oppositely charged groups"
155 static const char *fn[3] = {
166 int i,j,k,m,nnn,teller,ncg,n1,n2,n3,natoms;
179 CopyRight(stderr,argv[0]);
181 parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,
182 NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
184 top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC);
185 cg=mk_charge(&top->atoms,&(top->cgs),&ncg);
188 for(i=0; (i<ncg); i++) {
190 snew(nWithin[i],ncg);
193 natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
198 srenew(time,teller+1);
201 set_pbc(&pbc,ePBC,box);
203 for(i=0; (i<ncg); i++) {
204 for(j=i+1; (j<ncg); j++) {
205 srenew(cgdist[i][j],teller+1);
206 cgdist[i][j][teller]=
207 calc_dist(&pbc,x,&(top->cgs),cg[i].cg,cg[j].cg);
208 if (cgdist[i][j][teller] < truncate)
214 } while (read_next_x(oenv,status,&t,natoms,x,box));
215 fprintf(stderr,"\n");
220 for(i=0; (i<ncg); i++)
221 for(j=i+1; (j<ncg); j++) {
223 sprintf(buf,"sb-%s:%s.xvg",cg[i].label,cg[j].label);
224 fp=xvgropen(buf,buf,"Time (ps)","Distance (nm)",oenv);
225 for(k=0; (k<teller); k++)
226 fprintf(fp,"%10g %10g\n",time[k],cgdist[i][j][k]);
235 out[m]=xvgropen(fn[m],title[m],"Time (ps)","Distance (nm)",oenv);
238 for(i=0; (i<ncg); i++) {
240 for(j=i+1; (j<ncg); j++) {
243 sprintf(buf,"%s:%s",cg[i].label,cg[j].label);
252 xvgr_legend(out[nnn],1,(const char**)&buf,oenv);
254 if (output_env_get_xvg_format(oenv) == exvgXMGR) {
255 fprintf(out[nnn],"@ legend string %d \"%s\"\n",nset[nnn],buf);
256 } else if (output_env_get_xvg_format(oenv) == exvgXMGRACE) {
257 fprintf(out[nnn],"@ s%d legend \"%s\"\n",nset[nnn],buf);
265 for(k=0; (k<teller); k++) {
267 fprintf(out[m],"%10g",time[k]);
269 for(i=0; (i<ncg); i++) {
270 for(j=i+1; (j<ncg); j++) {
273 fprintf(out[nnn-1]," %10g",cgdist[i][j][k]);
277 fprintf(out[m],"\n");
279 for(m=0; (m<3); m++) {