863b658e6e3e687685a3e19b5c19ed98d7c7b16a
[alexxy/gromacs.git] / src / tools / nsfactor.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  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <ctype.h>
40 #include <string.h>
41 #include "futil.h"
42 #include "gmx_random.h"
43 #include "smalloc.h"
44 #include "sysstuff.h"
45 #include "strdb.h"
46 #include "vec.h"
47 #include "nsfactor.h"
48 #include "gmx_omp.h"
49
50 void check_binwidth(real binwidth) {
51     real smallest_bin=0.1;
52     if (binwidth<smallest_bin)
53         gmx_fatal(FARGS,"Binwidth shouldnt be smaller then smallest bond length (H-H bond ~0.1nm) in a box");
54 }
55
56 void check_mcover(real mcover) {
57     if (mcover>1.0) {
58         gmx_fatal(FARGS,"mcover should be -1 or (0,1]");
59     } else if ((mcover<0)&(mcover != -1)) {
60         gmx_fatal(FARGS,"mcover should be -1 or (0,1]");
61     } else {
62         return;
63     }
64 }
65
66 void normalize_probability(int n,double *a){
67     int i;
68     double norm=0.0;
69     for (i=0;i<n;i++) norm +=a[i];
70     for (i=0;i<n;i++) a[i]/=norm;
71 }
72
73 gmx_nentron_atomic_structurefactors_t *gmx_neutronstructurefactors_init(const char *datfn) {
74     /* read nsfactor.dat */
75     FILE    *fp;
76     char    line[STRLEN];
77     int     nralloc=10;
78     int     n,p;
79     int     i, line_no;
80     char    atomnm[8];
81     double  slength;
82     gmx_nentron_atomic_structurefactors_t   *gnsf;
83
84     fp=libopen(datfn);
85     line_no = 0;
86     /* allocate memory for structure */
87     snew(gnsf,nralloc);
88     snew(gnsf->atomnm,nralloc);
89     snew(gnsf->p,nralloc);
90     snew(gnsf->n,nralloc);
91     snew(gnsf->slength,nralloc);
92
93     gnsf->nratoms=line_no;
94
95     while(get_a_line(fp,line,STRLEN)) {
96         i=line_no;
97         if (sscanf(line,"%s %d %d %lf",atomnm,&p,&n,&slength) == 4) {
98             gnsf->atomnm[i]=strdup(atomnm);
99             gnsf->n[i]=n;
100             gnsf->p[i]=p;
101             gnsf->slength[i]=slength;
102             line_no++;
103             gnsf->nratoms=line_no;
104             if (line_no==nralloc){
105                 nralloc++;
106                 srenew(gnsf->atomnm,nralloc);
107                 srenew(gnsf->p,nralloc);
108                 srenew(gnsf->n,nralloc);
109                 srenew(gnsf->slength,nralloc);
110             }
111         } else
112             fprintf(stderr,"WARNING: Error in file %s at line %d ignored\n",
113                     datfn,line_no);
114     }
115     srenew(gnsf->atomnm,gnsf->nratoms);
116     srenew(gnsf->p,gnsf->nratoms);
117     srenew(gnsf->n,gnsf->nratoms);
118     srenew(gnsf->slength,gnsf->nratoms);
119
120     fclose(fp);
121
122     return (gmx_nentron_atomic_structurefactors_t *) gnsf;
123 }
124
125 gmx_sans_t *gmx_sans_init (t_topology *top, gmx_nentron_atomic_structurefactors_t *gnsf) {
126     gmx_sans_t    *gsans=NULL;
127     int     i,j;
128     /* Try to assing scattering length from nsfactor.dat */
129     snew(gsans,1);
130     snew(gsans->slength,top->atoms.nr);
131     /* copy topology data */
132     gsans->top = top;
133     for(i=0;i<top->atoms.nr;i++) {
134         for(j=0;j<gnsf->nratoms;j++) {
135             if(top->atoms.atom[i].atomnumber == gnsf->p[j]) {
136                 /* we need special case for H and D */
137                 if(top->atoms.atom[i].atomnumber == 1) {
138                     if(top->atoms.atom[i].m == 1.008000) {
139                         gsans->slength[i] = gnsf->slength[0];
140                     } else
141                         gsans->slength[i] = gnsf->slength[1];
142                 } else
143                     gsans->slength[i] = gnsf->slength[j];
144             }
145         }
146     }
147
148     return (gmx_sans_t *) gsans;
149 }
150
151 gmx_radial_distribution_histogram_t *calc_radial_distribution_histogram (
152                             gmx_sans_t *gsans,
153                             rvec *x,
154                             matrix box,
155                             atom_id *index,
156                             int isize,
157                             double binwidth,
158                             gmx_bool bMC,
159                             real mcover,
160                             unsigned int seed) {
161     gmx_radial_distribution_histogram_t    *pr=NULL;
162     rvec            dist;
163     double          rmax;
164     int             i,j;
165 #ifdef GMX_OPENMP
166     double          **tgr;
167     int             tid;
168     int             nthreads;
169     gmx_rng_t       *trng=NULL;
170 #endif
171     gmx_large_int_t mc=0,max;
172     gmx_rng_t       rng=NULL;
173
174     /* allocate memory for pr */
175     snew(pr,1);
176     /* set some fields */
177     pr->binwidth=binwidth;
178
179     /*
180     * create max dist rvec
181     * dist = box[xx] + box[yy] + box[zz]
182     */
183     rvec_add(box[XX],box[YY],dist);
184     rvec_add(box[ZZ],dist,dist);
185
186     rmax=norm(dist);
187
188     pr->grn=(int)floor(rmax/pr->binwidth)+1;
189     rmax=pr->grn*pr->binwidth;
190
191     snew(pr->gr,pr->grn);
192
193     if(bMC) {
194         /* Special case for setting automaticaly number of mc iterations to 1% of total number of direct iterations */
195         if (mcover==-1) {
196             max=(gmx_large_int_t)floor(0.5*0.01*isize*(isize-1));
197         } else {
198             max=(gmx_large_int_t)floor(0.5*mcover*isize*(isize-1));
199         }
200         rng=gmx_rng_init(seed);
201 #ifdef GMX_OPENMP
202         nthreads = gmx_omp_get_max_threads();
203         snew(tgr,nthreads);
204         snew(trng,nthreads);
205         for(i=0;i<nthreads;i++){
206             snew(tgr[i],pr->grn);
207             trng[i]=gmx_rng_init(gmx_rng_uniform_uint32(rng));
208         }
209         #pragma omp parallel shared(tgr,trng,mc) private(tid,i,j)
210         {
211             tid = gmx_omp_get_thread_num();
212             /* now starting parallel threads */
213             #pragma omp for
214             for(mc=0;mc<max;mc++) {
215                 i=(int)floor(gmx_rng_uniform_real(trng[tid])*isize);
216                 j=(int)floor(gmx_rng_uniform_real(trng[tid])*isize);
217                 if(i!=j) {
218                     tgr[tid][(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
219                 }
220             }
221         }
222         /* collecting data from threads */
223         for(i=0;i<pr->grn;i++) {
224             for(j=0;j<nthreads;j++) {
225                 pr->gr[i] += tgr[j][i];
226             }
227         }
228         /* freeing memory for tgr and destroying trng */
229         for(i=0;i<nthreads;i++) {
230             sfree(tgr[i]);
231             gmx_rng_destroy(trng[i]);
232         }
233         sfree(tgr);
234         sfree(trng);
235 #else
236         for(mc=0;mc<max;mc++) {
237             i=(int)floor(gmx_rng_uniform_real(rng)*isize);
238             j=(int)floor(gmx_rng_uniform_real(rng)*isize);
239             if(i!=j)
240                 pr->gr[(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
241         }
242 #endif
243         gmx_rng_destroy(rng);
244     } else {
245 #ifdef GMX_OPENMP
246         nthreads = gmx_omp_get_max_threads();
247         /* Allocating memory for tgr arrays */
248         snew(tgr,nthreads);
249         for(i=0;i<nthreads;i++) {
250             snew(tgr[i],pr->grn);
251         }
252         #pragma omp parallel shared(tgr) private(tid,i,j)
253         {
254             tid = gmx_omp_get_thread_num();
255             /* starting parallel threads */
256             #pragma omp for
257             for(i=0;i<isize;i++) {
258                 for(j=0;j<i;j++) {
259                     tgr[tid][(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
260                 }
261             }
262         }
263         /* collecating data for pr->gr */
264         for(i=0;i<pr->grn;i++) {
265             for(j=0;j<nthreads;j++) {
266                 pr->gr[i] += tgr[j][i];
267             }
268         }
269         /* freeing memory for tgr */
270         for(i=0;i<nthreads;i++) {
271             sfree(tgr[i]);
272         }
273         sfree(tgr);
274 #else
275         for(i=0;i<isize;i++) {
276             for(j=0;j<i;j++) {
277                 pr->gr[(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
278             }
279         }
280 #endif
281     }
282
283     /* normalize */
284     normalize_probability(pr->grn,pr->gr);
285     snew(pr->r,pr->grn);
286     for(i=0;i<pr->grn;i++)
287         pr->r[i]=(pr->binwidth*i+pr->binwidth*0.5);
288
289     return (gmx_radial_distribution_histogram_t *) pr;
290 }
291
292 gmx_static_structurefator_t *convert_histogram_to_intensity_curve (gmx_radial_distribution_histogram_t *pr, double start_q, double end_q, double q_step) {
293     gmx_static_structurefator_t    *sq=NULL;
294     int         i,j;
295     /* init data */
296     snew(sq,1);
297     sq->qn=(int)floor((end_q-start_q)/q_step);
298     snew(sq->q,sq->qn);
299     snew(sq->s,sq->qn);
300     for(i=0;i<sq->qn;i++)
301         sq->q[i]=start_q+i*q_step;
302
303     if(start_q==0.0) {
304         sq->s[0]=1.0;
305         for(i=1;i<sq->qn;i++) {
306             for(j=0;j<pr->grn;j++)
307                 sq->s[i]+=(pr->gr[j]/pr->r[j])*sin(sq->q[i]*pr->r[j]);
308             sq->s[i] /= sq->q[i];
309         }
310     } else {
311         for(i=0;i<sq->qn;i++) {
312             for(j=0;j<pr->grn;j++)
313                 sq->s[i]+=(pr->gr[j]/pr->r[j])*sin(sq->q[i]*pr->r[j]);
314             sq->s[i] /= sq->q[i];
315         }
316     }
317
318     return (gmx_static_structurefator_t *) sq;
319 }