Introduce SimulatorBuilder
[gromacs.git] / src / gromacs / gmxana / gmx_dyecoupl.cpp
blob09f12d6843be23102eb2f0fab03402aae3922038
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015,2017,2018, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 #include "gmxpre.h"
37 #include "gromacs/commandline/filenm.h"
38 #include "gromacs/commandline/pargs.h"
39 #include "gromacs/fileio/trxio.h"
40 #include "gromacs/fileio/xvgr.h"
41 #include "gromacs/gmxana/gmx_ana.h"
42 #include "gromacs/math/vec.h"
43 #include "gromacs/pbcutil/pbc.h"
44 #include "gromacs/topology/index.h"
45 #include "gromacs/trajectory/trajectoryframe.h"
46 #include "gromacs/utility/arraysize.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/futil.h"
49 #include "gromacs/utility/pleasecite.h"
50 #include "gromacs/utility/smalloc.h"
52 int gmx_dyecoupl(int argc, char *argv[])
54 const char *desc[] =
56 "[THISMODULE] extracts dye dynamics from trajectory files.",
57 "Currently, R and kappa^2 between dyes is extracted for (F)RET",
58 "simulations with assumed dipolar coupling as in the Foerster equation.",
59 "It further allows the calculation of R(t) and kappa^2(t), R and",
60 "kappa^2 histograms and averages, as well as the instantaneous FRET",
61 "efficiency E(t) for a specified Foerster radius R_0 (switch [TT]-R0[tt]).",
62 "The input dyes have to be whole (see res and mol pbc options",
63 "in [TT]trjconv[tt]).",
64 "The dye transition dipole moment has to be defined by at least",
65 "a single atom pair, however multiple atom pairs can be provided ",
66 "in the index file. The distance R is calculated on the basis of",
67 "the COMs of the given atom pairs.",
68 "The [TT]-pbcdist[tt] option calculates distances to the nearest periodic",
69 "image instead to the distance in the box. This works however only,",
70 "for periodic boundaries in all 3 dimensions.",
71 "The [TT]-norm[tt] option (area-) normalizes the histograms."
74 static gmx_bool bPBCdist = FALSE, bNormHist = FALSE;
75 int histbins = 50;
76 gmx_output_env_t *oenv;
77 real R0 = -1;
79 t_pargs pa[] =
81 { "-pbcdist", FALSE, etBOOL, { &bPBCdist }, "Distance R based on PBC" },
82 { "-norm", FALSE, etBOOL, { &bNormHist }, "Normalize histograms" },
83 { "-bins", FALSE, etINT, {&histbins}, "# of histogram bins" },
84 { "-R0", FALSE, etREAL, {&R0}, "Foerster radius including kappa^2=2/3 in nm" }
86 #define NPA asize(pa)
88 t_filenm fnm[] =
90 { efTRX, "-f", nullptr, ffREAD },
91 { efNDX, nullptr, nullptr, ffREAD },
92 { efXVG, "-ot", "rkappa", ffOPTWR },
93 { efXVG, "-oe", "insteff", ffOPTWR },
94 { efDAT, "-o", "rkappa", ffOPTWR },
95 { efXVG, "-rhist", "rhist", ffOPTWR },
96 { efXVG, "-khist", "khist", ffOPTWR }
98 #define NFILE asize(fnm)
101 const char *in_trajfile, *out_xvgrkfile = nullptr, *out_xvginstefffile = nullptr, *out_xvgrhistfile = nullptr, *out_xvgkhistfile = nullptr, *out_datfile = nullptr;
102 gmx_bool bHaveFirstFrame, bHaveNextFrame, indexOK = TRUE;
103 int ndon, nacc;
104 int *donindex, *accindex;
105 char *grpnm;
106 t_trxstatus *status;
107 t_trxframe fr;
109 int flags;
110 int allocblock = 1000;
111 real histexpand = 1e-6;
112 rvec donvec, accvec, donpos, accpos, dist, distnorm;
113 int natoms;
115 /*we rely on PBC autodetection (...currently)*/
116 int ePBC = -1;
118 real *rvalues = nullptr, *kappa2values = nullptr, *rhist = nullptr, *khist = nullptr;
119 t_pbc *pbc = nullptr;
120 int i, bin;
121 FILE *rkfp = nullptr, *rhfp = nullptr, *khfp = nullptr, *datfp = nullptr, *iefp = nullptr;
122 gmx_bool bRKout, bRhistout, bKhistout, bDatout, bInstEffout, grident;
124 const char *rkleg[2] = { "R", "\\f{Symbol}k\\f{}\\S2\\N" };
125 const char *rhleg[1] = { "p(R)" };
126 const char *khleg[1] = { "p(\\f{Symbol}k\\f{}\\S2\\N)" };
127 const char *ieleg[1] = { "E\\sRET\\N(t)" };
129 real R, kappa2, insteff, Rs = 0., kappa2s = 0., insteffs = 0., rmax, rmin, kmin = 0., kmax = 4.,
130 rrange, krange, rincr, kincr, Rfrac;
131 int rkcount = 0, rblocksallocated = 0, kblocksallocated = 0;
133 if (!parse_common_args(&argc, argv, PCA_CAN_BEGIN | PCA_CAN_END | PCA_CAN_VIEW | PCA_TIME_UNIT,
134 NFILE, fnm, NPA, pa, asize(desc), desc, 0, nullptr, &oenv))
136 return 0;
140 /* Check command line options for filenames and set bool flags when switch used*/
141 in_trajfile = opt2fn("-f", NFILE, fnm);
142 out_xvgrkfile = opt2fn("-ot", NFILE, fnm);
143 out_xvgrhistfile = opt2fn("-rhist", NFILE, fnm);
144 out_xvgkhistfile = opt2fn("-khist", NFILE, fnm);
145 out_xvginstefffile = opt2fn("-oe", NFILE, fnm);
146 out_datfile = opt2fn("-o", NFILE, fnm);
148 bRKout = opt2bSet("-ot", NFILE, fnm);
149 bRhistout = opt2bSet("-rhist", NFILE, fnm);
150 bKhistout = opt2bSet("-khist", NFILE, fnm);
151 bDatout = opt2bSet("-o", NFILE, fnm);
152 bInstEffout = opt2bSet("-oe", NFILE, fnm);
155 /* PBC warning. */
156 if (bPBCdist)
158 printf("Calculating distances to periodic image.\n");
159 printf("Be careful! This produces only valid results for PBC in all three dimensions\n");
163 if (bInstEffout && R0 <= 0.)
165 gmx_fatal(FARGS, "You have to specify R0 and R0 has to be larger than 0 nm.\n\n");
168 printf("Select group with donor atom pairs defining the transition moment\n");
169 get_index(nullptr, ftp2fn_null(efNDX, NFILE, fnm), 1, &ndon, &donindex, &grpnm);
171 printf("Select group with acceptor atom pairs defining the transition moment\n");
172 get_index(nullptr, ftp2fn_null(efNDX, NFILE, fnm), 1, &nacc, &accindex, &grpnm);
174 /*check if groups are identical*/
175 grident = TRUE;
177 if (ndon == nacc)
179 for (i = 0; i < nacc; i++)
181 if (accindex[i] != donindex[i])
183 grident = FALSE;
184 break;
189 if (grident)
191 gmx_fatal(FARGS, "Donor and acceptor group are identical. This makes no sense.");
194 printf("Reading first frame\n");
195 /* open trx file for reading */
196 flags = 0;
197 flags = flags | TRX_READ_X;
198 bHaveFirstFrame = read_first_frame(oenv, &status, in_trajfile, &fr, flags);
200 if (bHaveFirstFrame)
202 printf("First frame is OK\n");
203 natoms = fr.natoms;
204 if ((ndon % 2 != 0) || (nacc % 2 != 0))
206 indexOK = FALSE;
208 else
210 for (i = 0; i < ndon; i++)
212 if (donindex[i] >= natoms)
214 indexOK = FALSE;
217 for (i = 0; i < nacc; i++)
219 if (accindex[i] >= natoms)
221 indexOK = FALSE;
226 if (indexOK)
229 if (bDatout)
231 datfp = gmx_ffopen(out_datfile, "w");
234 if (bRKout)
236 rkfp = xvgropen(out_xvgrkfile,
237 "Distance and \\f{Symbol}k\\f{}\\S2\\N trajectory",
238 "Time (ps)", "Distance (nm) / \\f{Symbol}k\\f{}\\S2\\N",
239 oenv);
240 xvgr_legend(rkfp, 2, rkleg, oenv);
243 if (bInstEffout)
245 iefp = xvgropen(out_xvginstefffile,
246 "Instantaneous RET Efficiency",
247 "Time (ps)", "RET Efficiency",
248 oenv);
249 xvgr_legend(iefp, 1, ieleg, oenv);
253 if (bRhistout)
255 snew(rvalues, allocblock);
256 rblocksallocated += 1;
257 snew(rhist, histbins);
260 if (bKhistout)
262 snew(kappa2values, allocblock);
263 kblocksallocated += 1;
264 snew(khist, histbins);
269 clear_rvec(donvec);
270 clear_rvec(accvec);
271 clear_rvec(donpos);
272 clear_rvec(accpos);
273 for (i = 0; i < ndon / 2; i++)
275 rvec_sub(donvec, fr.x[donindex[2 * i]], donvec);
276 rvec_add(donvec, fr.x[donindex[2 * i + 1]], donvec);
277 rvec_add(donpos, fr.x[donindex[2 * i]], donpos);
278 rvec_add(donpos, fr.x[donindex[2 * i + 1]], donpos);
281 for (i = 0; i < nacc / 2; i++)
283 rvec_sub(accvec, fr.x[accindex[2 * i]], accvec);
284 rvec_add(accvec, fr.x[accindex[2 * i + 1]], accvec);
285 rvec_add(accpos, fr.x[accindex[2 * i]], accpos);
286 rvec_add(accpos, fr.x[accindex[2 * i + 1]], accpos);
289 unitv(donvec, donvec);
290 unitv(accvec, accvec);
292 svmul(1.0 / ndon, donpos, donpos);
293 svmul(1.0 / nacc, accpos, accpos);
295 if (bPBCdist)
297 set_pbc(pbc, ePBC, fr.box);
298 pbc_dx(pbc, donpos, accpos, dist);
300 else
302 rvec_sub(donpos, accpos, dist);
305 unitv(dist, distnorm);
306 R = norm(dist);
307 kappa2 = iprod(donvec, accvec)- 3.* (iprod(donvec, distnorm) * iprod(distnorm, accvec));
308 kappa2 *= kappa2;
309 if (R0 > 0)
311 Rfrac = R/R0;
312 insteff = 1/(1+(Rfrac*Rfrac*Rfrac*Rfrac*Rfrac*Rfrac)*2/3/kappa2);
313 insteffs += insteff;
315 if (bInstEffout)
317 fprintf(iefp, "%12.7f %12.7f\n", fr.time, insteff);
322 Rs += R;
323 kappa2s += kappa2;
324 rkcount++;
326 if (bRKout)
328 fprintf(rkfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
331 if (bDatout)
333 fprintf(datfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
336 if (bRhistout)
338 rvalues[rkcount-1] = R;
339 if (rkcount % allocblock == 0)
341 srenew(rvalues, allocblock*(rblocksallocated+1));
342 rblocksallocated += 1;
346 if (bKhistout)
348 kappa2values[rkcount-1] = kappa2;
349 if (rkcount % allocblock == 0)
351 srenew(kappa2values, allocblock*(kblocksallocated+1));
352 kblocksallocated += 1;
356 bHaveNextFrame = read_next_frame(oenv, status, &fr);
358 while (bHaveNextFrame);
360 if (bRKout)
362 xvgrclose(rkfp);
365 if (bDatout)
367 gmx_ffclose(datfp);
370 if (bInstEffout)
372 xvgrclose(iefp);
376 if (bRhistout)
378 printf("Writing R-Histogram\n");
379 rmin = rvalues[0];
380 rmax = rvalues[0];
381 for (i = 1; i < rkcount; i++)
383 if (rvalues[i] < rmin)
385 rmin = rvalues[i];
387 else if (rvalues[i] > rmax)
389 rmax = rvalues[i];
392 rmin -= histexpand;
393 rmax += histexpand;
395 rrange = rmax - rmin;
396 rincr = rrange / histbins;
398 for (i = 1; i < rkcount; i++)
400 bin = static_cast<int>((rvalues[i] - rmin) / rincr);
401 rhist[bin] += 1;
403 if (bNormHist)
405 for (i = 0; i < histbins; i++)
407 rhist[i] /= rkcount * rrange/histbins;
409 rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
410 "R (nm)", "Normalized Probability", oenv);
412 else
414 rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
415 "R (nm)", "Probability", oenv);
417 xvgr_legend(rhfp, 1, rhleg, oenv);
418 for (i = 0; i < histbins; i++)
420 fprintf(rhfp, "%12.7f %12.7f\n", (i + 0.5) * rincr + rmin,
421 rhist[i]);
423 xvgrclose(rhfp);
426 if (bKhistout)
428 printf("Writing kappa^2-Histogram\n");
429 krange = kmax - kmin;
430 kincr = krange / histbins;
432 for (i = 1; i < rkcount; i++)
434 bin = static_cast<int>((kappa2values[i] - kmin) / kincr);
435 khist[bin] += 1;
437 if (bNormHist)
439 for (i = 0; i < histbins; i++)
441 khist[i] /= rkcount * krange/histbins;
443 khfp = xvgropen(out_xvgkhistfile,
444 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
445 "\\f{Symbol}k\\f{}\\S2\\N",
446 "Normalized Probability", oenv);
448 else
450 khfp = xvgropen(out_xvgkhistfile,
451 "\\f{Symbol}k\\f{}\\S2\\N Distribution",
452 "\\f{Symbol}k\\f{}\\S2\\N", "Probability", oenv);
454 xvgr_legend(khfp, 1, khleg, oenv);
455 for (i = 0; i < histbins; i++)
457 fprintf(khfp, "%12.7f %12.7f\n", (i + 0.5) * kincr + kmin,
458 khist[i]);
460 xvgrclose(khfp);
463 printf("\nAverages:\n");
464 printf("R_avg = %8.4f nm\nKappa^2 = %8.4f\n", Rs / rkcount,
465 kappa2s / rkcount);
466 if (R0 > 0)
468 printf("E_RETavg = %8.4f\n", insteffs / rkcount);
470 please_cite(stdout, "Hoefling2011");
472 else
474 gmx_fatal(FARGS, "Index file invalid, check your index file for correct pairs.\n");
477 else
479 gmx_fatal(FARGS, "Could not read first frame of the trajectory.\n");
482 return 0;