2cae68baa5c3d37628331e7b544e81541d72e812
[alexxy/gromacs.git] / src / tools / gmx_sans.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  *
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  *
30  * For more info, check our website at http://www.gromacs.org
31  *
32  * And Hey:
33  * Green Red Orange Magenta Azure Cyan Skyblue
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <ctype.h>
41 #include "smalloc.h"
42 #include "sysstuff.h"
43 #include "typedefs.h"
44 #include "macros.h"
45 #include "vec.h"
46 #include "pbc.h"
47 #include "xvgr.h"
48 #include "copyrite.h"
49 #include "futil.h"
50 #include "statutil.h"
51 #include "tpxio.h"
52 #include "index.h"
53 #include "gstat.h"
54 #include "matio.h"
55 #include "gmx_ana.h"
56 #include "nsfactor.h"
57
58 #ifdef GMX_OPENMP
59 #include <omp.h>
60 #endif
61
62
63 int gmx_sans(int argc,char *argv[])
64 {
65     const char *desc[] = {
66         "This is simple tool to compute SANS spectra using Debye formula",
67         "It currently uses topology file (since it need to assigne element for each atom)",
68         "[PAR]",
69         "[TT]-pr[tt] Computes normalized g(r) function",
70         "[PAR]",
71         "[TT]-sq[tt] Computes SANS intensity curve for needed q diapason",
72         "[PAR]",
73         "[TT]-startq[tt] Starting q value in nm",
74         "[PAR]",
75         "[TT]-endq[tt] Ending q value in nm",
76         "[PAR]",
77         "[TT]-qstep[tt] Stepping in q space",
78         "[PAR]",
79         "Note: When using Debye direct method computational cost increases as",
80         "1/2 * N * (N - 1) where N is atom number in group of interest"
81     };
82     static gmx_bool bPBC=TRUE;
83     static real binwidth=0.2,grid=0.05; /* bins shouldnt be smaller then bond (~0.1nm) length */
84     static real start_q=0.0, end_q=2.0, q_step=0.01;
85     static real mcover=-1;
86     static unsigned int  seed=0;
87     static int           nthreads=-1;
88
89     static const char *emode[]= { NULL, "direct", "mc", NULL };
90     static const char *emethod[]={ NULL, "debye", "fft", NULL };
91
92     gmx_nentron_atomic_structurefactors_t    *gnsf;
93     gmx_sans_t              *gsans;
94
95 #define NPA asize(pa)
96
97     t_pargs pa[] = {
98         { "-bin", FALSE, etREAL, {&binwidth},
99           "[HIDDEN]Binwidth (nm)" },
100         { "-mode", FALSE, etENUM, {emode},
101           "Mode for sans spectra calculation" },
102         { "-mcover", FALSE, etREAL, {&mcover},
103           "Monte-Carlo coverage should be -1(default) or (0,1]"},
104         { "-method", FALSE, etENUM, {emethod},
105           "[HIDDEN]Method for sans spectra calculation" },
106         { "-pbc", FALSE, etBOOL, {&bPBC},
107           "Use periodic boundary conditions for computing distances" },
108         { "-grid", FALSE, etREAL, {&grid},
109           "[HIDDEN]Grid spacing (in nm) for FFTs" },
110         {"-startq", FALSE, etREAL, {&start_q},
111           "Starting q (1/nm) "},
112         {"-endq", FALSE, etREAL, {&end_q},
113           "Ending q (1/nm)"},
114         { "-qstep", FALSE, etREAL, {&q_step},
115           "Stepping in q (1/nm)"},
116         { "-seed",     FALSE, etINT,  {&seed},
117           "Random seed for Monte-Carlo"},
118 #ifdef GMX_OPENMP
119         { "-nt",  FALSE, etINT, {&nthreads},
120           "Number of threads to start"},
121 #endif
122     };
123   FILE      *fp;
124   const char *fnTPX,*fnNDX,*fnDAT=NULL;
125   t_trxstatus *status;
126   t_topology *top=NULL;
127   t_atom    *atom=NULL;
128   gmx_rmpbc_t  gpbc=NULL;
129   gmx_bool  bTPX;
130   gmx_bool  bFFT=FALSE, bDEBYE=FALSE;
131   gmx_bool  bMC=FALSE;
132   int        ePBC=-1;
133   matrix     box;
134   char       title[STRLEN];
135   rvec       *x;
136   int       natoms;
137   real       t;
138   char       **grpname=NULL;
139   atom_id    *index=NULL;
140   int        isize;
141   int         i,j;
142   gmx_radial_distribution_histogram_t  *pr=NULL;
143   gmx_static_structurefator_t  *sq=NULL;
144   output_env_t oenv;
145
146 #define NFILE asize(fnm)
147
148   t_filenm   fnm[] = {
149       { efTPX,  "-s",         NULL,   ffREAD },
150       { efNDX,  NULL,         NULL,   ffOPTRD },
151       { efDAT,  "-d",   "nsfactor",   ffOPTRD },
152       { efXVG, "-sq",         "sq",   ffWRITE },
153       { efXVG, "-pr",         "pr",   ffWRITE }
154   };
155
156 #ifdef GMX_OPENMP
157     nthreads = omp_get_max_threads();
158 #endif
159
160   CopyRight(stderr,argv[0]);
161   parse_common_args(&argc,argv,PCA_BE_NICE,
162                     NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
163
164   /* check that binwidth not smaller than smallers distance */
165   check_binwidth(binwidth);
166   check_mcover(mcover);
167
168   /* setting number of omp threads globaly */
169 #ifdef GMX_OPENMP
170   omp_set_num_threads(nthreads);
171 #endif
172   /* Now try to parse opts for modes */
173   switch(emethod[0][0]) {
174   case 'd':
175       bDEBYE=TRUE;
176       switch(emode[0][0]) {
177       case 'd':
178           bMC=FALSE;
179           break;
180       case 'm':
181           bMC=TRUE;
182           break;
183       default:
184           break;
185       }
186       break;
187   case 'f':
188       bFFT=TRUE;
189       break;
190   default:
191       break;
192   }
193
194   if (!bDEBYE && !bFFT)
195       gmx_fatal(FARGS,"Unknown method. Set pr or fft!\n");
196   /* Try to read files */
197   fnDAT = ftp2fn(efDAT,NFILE,fnm);
198   fnTPX = ftp2fn(efTPX,NFILE,fnm);
199
200   gnsf = gmx_neutronstructurefactors_init(fnDAT);
201   fprintf(stderr,"Read %d atom names from %s with neutron scattering parameters\n\n",gnsf->nratoms,fnDAT);
202
203   snew(top,1);
204   snew(grpname,1);
205   snew(index,1);
206
207   bTPX=read_tps_conf(fnTPX,title,top,&ePBC,&x,NULL,box,TRUE);
208
209   printf("\nPlease select group for SANS spectra calculation:\n");
210   get_index(&(top->atoms),ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,grpname);
211
212   gsans = gmx_sans_init(top,gnsf);
213
214   /* Prepare reference frame */
215   if (bPBC) {
216       gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
217       gmx_rmpbc(gpbc,top->atoms.nr,box,x);
218   }
219
220   natoms=top->atoms.nr;
221
222   if (bDEBYE) {
223       if (bMC) {
224           fprintf(stderr,"Using Monte Carlo Debye method to calculate spectrum\n");
225       } else {
226           fprintf(stderr,"Using direct Debye method to calculate spectrum\n");
227       }
228   } else if (bFFT) {
229       gmx_fatal(FARGS,"Not implented!");
230   } else {
231       gmx_fatal(FARGS,"Whats this!");
232   }
233
234   /*  realy calc p(r) */
235   pr = calc_radial_distribution_histogram(gsans,x,box,index,isize,binwidth,bMC,mcover,seed);
236
237   /* prepare pr.xvg */
238   fp = xvgropen(opt2fn_null("-pr",NFILE,fnm),"G(r)","Distance (nm)","Probability",oenv);
239   for(i=0;i<pr->grn;i++)
240       fprintf(fp,"%10.6lf%10.6lf\n",pr->r[i],pr->gr[i]);
241   xvgrclose(fp);
242
243   /* prepare sq.xvg */
244   sq = convert_histogram_to_intensity_curve(pr,start_q,end_q,q_step);
245   fp = xvgropen(opt2fn_null("-sq",NFILE,fnm),"I(q)","q (nm^-1)","s(q)/s(0)",oenv);
246   for(i=0;i<sq->qn;i++) {
247       fprintf(fp,"%10.6lf%10.6lf\n",sq->q[i],sq->s[i]);
248   }
249   xvgrclose(fp);
250
251   sfree(pr);
252
253   please_cite(stdout,"Garmay2012");
254   thanx(stderr);
255
256   return 0;
257 }