#include "gmx_ana.h"
#include "nsfactor.h"
+#ifdef GMX_OPENMP
+#include <omp.h>
+#endif
+
int gmx_sans(int argc,char *argv[])
{
static real start_q=0.0, end_q=2.0, q_step=0.01;
static real mcover=-1;
static unsigned int seed=0;
+ static int nthreads=-1;
static const char *emode[]= { NULL, "direct", "mc", NULL };
static const char *emethod[]={ NULL, "debye", "fft", NULL };
{ "-mode", FALSE, etENUM, {emode},
"Mode for sans spectra calculation" },
{ "-mcover", FALSE, etREAL, {&mcover},
- "Monte-Carlo coverage"},
+ "Monte-Carlo coverage should be -1(default) or (0,1]"},
{ "-method", FALSE, etENUM, {emethod},
"[HIDDEN]Method for sans spectra calculation" },
{ "-pbc", FALSE, etBOOL, {&bPBC},
"Stepping in q (1/nm)"},
{ "-seed", FALSE, etINT, {&seed},
"Random seed for Monte-Carlo"},
+#ifdef GMX_OPENMP
+ { "-nt", FALSE, etINT, {&nthreads},
+ "Number of threads to start"},
+#endif
};
FILE *fp;
const char *fnTPX,*fnNDX,*fnDAT=NULL;
{ efXVG, "-pr", "pr", ffWRITE }
};
+#ifdef GMX_OPENMP
+ nthreads = omp_get_max_threads();
+#endif
+
CopyRight(stderr,argv[0]);
parse_common_args(&argc,argv,PCA_BE_NICE,
NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
/* check that binwidth not smaller than smallers distance */
check_binwidth(binwidth);
+ check_mcover(mcover);
+ /* setting number of omp threads globaly */
+#ifdef GMX_OPENMP
+ omp_set_num_threads(nthreads);
+#endif
/* Now try to parse opts for modes */
switch(emethod[0][0]) {
case 'd':
#include "vec.h"
#include "nsfactor.h"
+#ifdef GMX_OPENMP
+#include <omp.h>
+#endif
+
void check_binwidth(real binwidth) {
real smallest_bin=0.1;
if (binwidth<smallest_bin)
gmx_fatal(FARGS,"Binwidth shouldnt be smaller then smallest bond length (H-H bond ~0.1nm) in a box");
}
+void check_mcover(real mcover) {
+ if (mcover>1.0) {
+ gmx_fatal(FARGS,"mcover should be -1 or (0,1]");
+ } else if ((mcover<0)&(mcover != -1)) {
+ gmx_fatal(FARGS,"mcover should be -1 or (0,1]");
+ } else {
+ return;
+ }
+}
+
void normalize_probability(int n,double *a){
int i;
double norm=0.0;
real mcover,
unsigned int seed) {
gmx_radial_distribution_histogram_t *pr=NULL;
- rvec dist;
- double rmax;
- int i,j;
- gmx_large_int_t mc=0,max;
- gmx_rng_t rng=NULL;
+ rvec dist;
+ double rmax;
+ int i,j;
+#ifdef GMX_OPENMP
+ double **tgr;
+ int tid;
+ int nthreads;
+ gmx_rng_t *trng=NULL;
+#endif
+ gmx_large_int_t mc=0,max;
+ gmx_rng_t rng=NULL;
/* allocate memory for pr */
snew(pr,1);
max=(gmx_large_int_t)floor(0.5*mcover*isize*(isize-1));
}
rng=gmx_rng_init(seed);
- while(mc<max) {
+#ifdef GMX_OPENMP
+ nthreads = omp_get_max_threads();
+ snew(tgr,nthreads);
+ snew(trng,nthreads);
+ for(i=0;i<nthreads;i++){
+ snew(tgr[i],pr->grn);
+ trng[i]=gmx_rng_init(gmx_rng_uniform_uint32(rng));
+ }
+ #pragma omp parallel shared(tgr,trng,mc) private(tid,i,j)
+ {
+ tid = omp_get_thread_num();
+ /* now starting parallel threads */
+ #pragma omp for
+ for(mc=0;mc<max;mc++) {
+ i=(int)floor(gmx_rng_uniform_real(trng[tid])*isize);
+ j=(int)floor(gmx_rng_uniform_real(trng[tid])*isize);
+ if(i!=j) {
+ tgr[tid][(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
+ }
+ }
+ }
+ /* collecting data from threads */
+ for(i=0;i<pr->grn;i++) {
+ for(j=0;j<nthreads;j++) {
+ pr->gr[i] += tgr[j][i];
+ }
+ }
+ /* freeing memory for tgr and destroying trng */
+ for(i=0;i<nthreads;i++) {
+ sfree(tgr[i]);
+ gmx_rng_destroy(trng[i]);
+ }
+ sfree(tgr);
+ sfree(trng);
+#else
+ for(mc=0;mc<max;mc++) {
i=(int)floor(gmx_rng_uniform_real(rng)*isize);
j=(int)floor(gmx_rng_uniform_real(rng)*isize);
if(i!=j)
pr->gr[(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
- mc++;
}
+#endif
gmx_rng_destroy(rng);
} else {
- for(i=0;i<isize;i++)
- for(j=0;j<i;j++)
+#ifdef GMX_OPENMP
+ nthreads = omp_get_max_threads();
+ /* Allocating memory for tgr arrays */
+ snew(tgr,nthreads);
+ for(i=0;i<nthreads;i++) {
+ snew(tgr[i],pr->grn);
+ }
+ #pragma omp parallel shared(tgr) private(tid,i,j)
+ {
+ tid = omp_get_thread_num();
+ /* starting parallel threads */
+ #pragma omp for
+ for(i=0;i<isize;i++) {
+ for(j=0;j<i;j++) {
+ tgr[tid][(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
+ }
+ }
+ }
+ /* collecating data for pr->gr */
+ for(i=0;i<pr->grn;i++) {
+ for(j=0;j<nthreads;j++) {
+ pr->gr[i] += tgr[j][i];
+ }
+ }
+ /* freeing memory for tgr */
+ for(i=0;i<nthreads;i++) {
+ sfree(tgr[i]);
+ }
+ sfree(tgr);
+#else
+ for(i=0;i<isize;i++) {
+ for(j=0;j<i;j++) {
pr->gr[(int)floor(sqrt(distance2(x[index[i]],x[index[j]]))/binwidth)]+=gsans->slength[index[i]]*gsans->slength[index[j]];
+ }
+ }
+#endif
}
/* normalize */
void check_binwidth(real binwidth);
+void check_mcover(real mcover);
+
void normalize_probability(int n, double *a);
gmx_nentron_atomic_structurefactors_t *gmx_neutronstructurefactors_init(const char *datfn);
gmx_sans_t *gmx_sans_init(t_topology *top, gmx_nentron_atomic_structurefactors_t *gnsf);
-gmx_radial_distribution_histogram_t *calc_radial_distribution_histogram ( gmx_sans_t *gsans,
+gmx_radial_distribution_histogram_t *calc_radial_distribution_histogram (gmx_sans_t *gsans,
rvec *x,
matrix box,
atom_id *index,