static void generate_trial_conf(int atomCount, const rvec xin[], const rvec offset, int enum_rot, gmx_rng_t rng, rvec xout[]) { for (int i = 0; i < atomCount; ++i) { copy_rvec(xin[i], xout[i]); } real alfa = 0.0, beta = 0.0, gamma = 0.0; switch (enum_rot) { case en_rotXYZ: alfa = 2*M_PI * gmx_rng_uniform_real(rng); beta = 2*M_PI * gmx_rng_uniform_real(rng); gamma = 2*M_PI * gmx_rng_uniform_real(rng); break; case en_rotZ: alfa = beta = 0.; gamma = 2*M_PI * gmx_rng_uniform_real(rng); break; case en_rotNone: alfa = beta = gamma = 0.; break; } if (enum_rot == en_rotXYZ || (enum_rot == en_rotZ)) { rotate_conf(atomCount, xout, NULL, alfa, beta, gamma); } for (int i = 0; i < atomCount; ++i) { rvec_inc(xout[i], offset); } }
static real vrescale_gamdev(int ia, gmx_rng_t rng) /* Gamma distribution, adapted from numerical recipes */ { int j; real am,e,s,v1,v2,x,y; if (ia < 6) { x = 1.0; for(j=1; j<=ia; j++) { x *= gmx_rng_uniform_real(rng); } x = -log(x); } else { do { do { do { v1 = gmx_rng_uniform_real(rng); v2 = 2.0*gmx_rng_uniform_real(rng)-1.0; } while (v1*v1 + v2*v2 > 1.0); y = v2/v1; am = ia - 1; s = sqrt(2.0*am + 1.0); x = s*y + am; } while (x <= 0.0); e = (1.0 + y*y)*exp(am*log(x/am) - s*y); } while (gmx_rng_uniform_real(rng) > e); } return x; }
static real vrescale_gamdev(int ia, gmx_rng_t rng) /* Gamma distribution, adapted from numerical recipes */ { int j; real am,e,s,v1,v2,x,y; if (ia < 6) { do { x = 1.0; for(j=1; j<=ia; j++) { x *= gmx_rng_uniform_real(rng); } } while (x == 0); x = -log(x); } else { do { do { do { v1 = gmx_rng_uniform_real(rng); v2 = 2.0*gmx_rng_uniform_real(rng)-1.0; } while (v1*v1 + v2*v2 > 1.0 || v1*v1*GMX_REAL_MAX < 3.0*ia); /* The last check above ensures that both x (3.0 > 2.0 in s) * and the pre-factor for e do not go out of range. */ y = v2/v1; am = ia - 1; s = sqrt(2.0*am + 1.0); x = s*y + am; } while (x <= 0.0); e = (1.0 + y*y)*exp(am*log(x/am) - s*y); } while (gmx_rng_uniform_real(rng) > e); } return x; }
static void pukeit(const char *db, const char *defstring, char *retstring, int retsize, int *cqnum) { FILE *fp; char **help; int i, nhlp; gmx_rng_t rng; if (be_cool() && ((fp = low_libopen(db, FALSE)) != NULL)) { nhlp = fget_lines(fp, &help); /* for libraries we can use the low-level close routines */ gmx_ffclose(fp); rng = gmx_rng_init(gmx_rng_make_seed()); *cqnum = static_cast<int>(nhlp*gmx_rng_uniform_real(rng)); gmx_rng_destroy(rng); if (strlen(help[*cqnum]) >= STRLEN) { help[*cqnum][STRLEN-1] = '\0'; } strncpy(retstring, help[*cqnum], retsize); for (i = 0; (i < nhlp); i++) { sfree(help[i]); } sfree(help); } else { *cqnum = -1; strncpy(retstring, defstring, retsize); } }
static void horizontal() { gmx_rng_t rng; gmx_stats_t straight; int i, ok, n = 1000; real y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh; FILE *fp; rng = gmx_rng_init(13); straight = gmx_stats_init(); for (i = 0; (i < n); i++) { y = gmx_rng_uniform_real(rng); if ((ok = gmx_stats_add_point(straight, i, y, 0, 0)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } } /* Horizontal test */ if ((ok = gmx_stats_get_ase(straight, &aver, &sigma, &error)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } fp = fopen("straight.xvg", "w"); if ((ok = gmx_stats_dump_xy(straight, fp)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } fclose(fp); printf("Horizontal line: average %g, sigma %g, error %g\n", aver, sigma, error); if ((ok = gmx_stats_done(straight)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } }
static void histogram() { gmx_rng_t rng; gmx_stats_t camel; int i, ok, n = 1000, norm; real y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh; const real a0 = 0.23, b0 = 2.7; FILE *fp; char fn[256]; for (norm = 0; (norm < 2); norm++) { rng = gmx_rng_init(13); camel = gmx_stats_init(); for (i = 0; (i < n); i++) { y = sqr(gmx_rng_uniform_real(rng)); if ((ok = gmx_stats_add_point(camel, i, y+1, 0, 0)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } y = sqr(gmx_rng_uniform_real(rng)); if ((ok = gmx_stats_add_point(camel, i+0.5, y+2, 0, 0)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } } /* Histogram test */ if ((ok = gmx_stats_make_histogram(camel, 0, 101, norm, &xh, &yh)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } sprintf(fn, "histo%d-data.xvg", norm); fp = fopen(fn, "w"); gmx_stats_dump_xy(camel, fp); fclose(fp); sprintf(fn, "histo%d.xvg", norm); fp = fopen(fn, "w"); for (i = 0; (i < 101); i++) { fprintf(fp, "%12g %12g\n", xh[i], yh[i]); } fclose(fp); sfree(xh); sfree(yh); } }
static void insert_ion(int nsa, int *nwater, gmx_bool bSet[], int repl[], atom_id index[], rvec x[], t_pbc *pbc, int sign, int q, const char *ionname, t_atoms *atoms, real rmin, gmx_rng_t rng) { int i, ei, nw; real rmin2; rvec dx; gmx_int64_t maxrand; ei = -1; nw = *nwater; maxrand = nw; maxrand *= 1000; do { ei = nw*gmx_rng_uniform_real(rng); maxrand--; } while (bSet[ei] && (maxrand > 0)); if (bSet[ei]) { gmx_fatal(FARGS, "No more replaceable solvent!"); } fprintf(stderr, "Replacing solvent molecule %d (atom %d) with %s\n", ei, index[nsa*ei], ionname); /* Replace solvent molecule charges with ion charge */ bSet[ei] = TRUE; repl[ei] = sign; atoms->atom[index[nsa*ei]].q = q; for (i = 1; i < nsa; i++) { atoms->atom[index[nsa*ei+i]].q = 0; } /* Mark all solvent molecules within rmin as unavailable for substitution */ if (rmin > 0) { rmin2 = rmin*rmin; for (i = 0; (i < nw); i++) { if (!bSet[i]) { pbc_dx(pbc, x[index[nsa*ei]], x[index[nsa*i]], dx); if (iprod(dx, dx) < rmin2) { bSet[i] = TRUE; } } } } }
static void line() { gmx_rng_t rng; gmx_stats_t line; int i, dy, ok, n = 1000; real y, a, b, da, db, aver, sigma, error, chi2, R, rfit; const real a0 = 0.23, b0 = 2.7; FILE *fp; for (dy = 0; (dy < 2); dy++) { rng = gmx_rng_init(13); line = gmx_stats_init(); for (i = 0; (i < n); i++) { y = a0*i+b0+50*(gmx_rng_uniform_real(rng)-0.5); if ((ok = gmx_stats_add_point(line, i, y, 0, dy*0.1)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } } /* Line with slope test */ if ((ok = gmx_stats_get_ab(line, elsqWEIGHT_NONE, &a, &b, &da, &db, &chi2, &rfit)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } if ((ok = gmx_stats_get_corr_coeff(line, &R)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } if (dy == 0) { fp = fopen("line0.xvg", "w"); } else { fp = fopen("line1.xvg", "w"); } if ((ok = gmx_stats_dump_xy(line, fp)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } fclose(fp); printf("Line with eqn. y = %gx + %g with noise%s\n", a0, b0, (dy == 0) ? "" : " and uncertainties"); printf("Found: a = %g +/- %g, b = %g +/- %g\n", a, da, b, db); if ((ok = gmx_stats_done(line)) != estatsOK) { fprintf(stderr, "%s\n", gmx_stats_message(ok)); } gmx_rng_destroy(rng); } }
static void rand_rot(int natoms, rvec x[], rvec v[], vec4 xrot[], vec4 vrot[], gmx_rng_t rng, rvec max_rot) { mat4 mt1, mt2, mr[DIM], mtemp1, mtemp2, mtemp3, mxtot, mvtot; rvec xcm; real phi; int i, m; clear_rvec(xcm); for (i = 0; (i < natoms); i++) { for (m = 0; (m < DIM); m++) { xcm[m] += x[i][m]/natoms; /* get center of mass of one molecule */ } } fprintf(stderr, "center of geometry: %f, %f, %f\n", xcm[0], xcm[1], xcm[2]); /* move c.o.ma to origin */ gmx_mat4_init_translation(-xcm[XX], -xcm[YY], -xcm[ZZ], mt1); for (m = 0; (m < DIM); m++) { phi = M_PI*max_rot[m]*(2*gmx_rng_uniform_real(rng) - 1)/180; gmx_mat4_init_rotation(m, phi, mr[m]); } gmx_mat4_init_translation(xcm[XX], xcm[YY], xcm[ZZ], mt2); /* For gmx_mat4_mmul() we need to multiply in the opposite order * compared to normal mathematical notation. */ gmx_mat4_mmul(mtemp1, mt1, mr[XX]); gmx_mat4_mmul(mtemp2, mr[YY], mr[ZZ]); gmx_mat4_mmul(mtemp3, mtemp1, mtemp2); gmx_mat4_mmul(mxtot, mtemp3, mt2); gmx_mat4_mmul(mvtot, mr[XX], mtemp2); for (i = 0; (i < natoms); i++) { gmx_mat4_transform_point(mxtot, x[i], xrot[i]); gmx_mat4_transform_point(mvtot, v[i], vrot[i]); } }
/* Estimate the reciprocal space part error of the SPME Ewald sum. */ static real estimate_reciprocal( t_inputinfo *info, rvec x[], /* array of particles */ real q[], /* array of charges */ int nr, /* number of charges = size of the charge array */ FILE *fp_out, gmx_bool bVerbose, unsigned int seed, /* The seed for the random number generator */ int *nsamples, /* Return the number of samples used if Monte Carlo * algorithm is used for self energy error estimate */ t_commrec *cr) { real e_rec=0; /* reciprocal error estimate */ real e_rec1=0; /* Error estimate term 1*/ real e_rec2=0; /* Error estimate term 2*/ real e_rec3=0; /* Error estimate term 3 */ real e_rec3x=0; /* part of Error estimate term 3 in x */ real e_rec3y=0; /* part of Error estimate term 3 in y */ real e_rec3z=0; /* part of Error estimate term 3 in z */ int i,ci; int nx,ny,nz; /* grid coordinates */ real q2_all=0; /* sum of squared charges */ rvec gridpx; /* reciprocal grid point in x direction*/ rvec gridpxy; /* reciprocal grid point in x and y direction*/ rvec gridp; /* complete reciprocal grid point in 3 directions*/ rvec tmpvec; /* template to create points from basis vectors */ rvec tmpvec2; /* template to create points from basis vectors */ real coeff=0; /* variable to compute coefficients of the error estimate */ real coeff2=0; /* variable to compute coefficients of the error estimate */ real tmp=0; /* variables to compute different factors from vectors */ real tmp1=0; real tmp2=0; gmx_bool bFraction; /* Random number generator */ gmx_rng_t rng=NULL; int *numbers=NULL; /* Index variables for parallel work distribution */ int startglobal,stopglobal; int startlocal, stoplocal; int x_per_core; int xtot; #ifdef TAKETIME double t0=0.0; double t1=0.0; #endif rng=gmx_rng_init(seed); clear_rvec(gridpx); clear_rvec(gridpxy); clear_rvec(gridp); clear_rvec(tmpvec); clear_rvec(tmpvec2); for(i=0;i<nr;i++) { q2_all += q[i]*q[i]; } /* Calculate indices for work distribution */ startglobal=-info->nkx[0]/2; stopglobal = info->nkx[0]/2; xtot = stopglobal*2+1; if (PAR(cr)) { x_per_core = ceil((real)xtot / (real)cr->nnodes); startlocal = startglobal + x_per_core*cr->nodeid; stoplocal = startlocal + x_per_core -1; if (stoplocal > stopglobal) stoplocal = stopglobal; } else { startlocal = startglobal; stoplocal = stopglobal; x_per_core = xtot; } /* #ifdef GMX_LIB_MPI MPI_Barrier(MPI_COMM_WORLD); #endif */ #ifdef GMX_LIB_MPI #ifdef TAKETIME if (MASTER(cr)) t0 = MPI_Wtime(); #endif #endif if (MASTER(cr)){ fprintf(stderr, "Calculating reciprocal error part 1 ..."); } for(nx=startlocal; nx<=stoplocal; nx++) { svmul(nx,info->recipbox[XX],gridpx); for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++) { svmul(ny,info->recipbox[YY],tmpvec); rvec_add(gridpx,tmpvec,gridpxy); for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++) { if ( 0 == nx && 0 == ny && 0 == nz ) continue; svmul(nz,info->recipbox[ZZ],tmpvec); rvec_add(gridpxy,tmpvec,gridp); tmp=norm2(gridp); coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] ) ; coeff/= 2.0 * M_PI * info->volume * tmp; coeff2=tmp ; tmp=eps_poly2(nx,info->nkx[0],info->pme_order[0]); tmp+=eps_poly2(ny,info->nkx[0],info->pme_order[0]); tmp+=eps_poly2(nz,info->nkx[0],info->pme_order[0]); tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp2=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp1+=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp1+=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp+= tmp1 * tmp1; e_rec1+= 32.0 * M_PI * M_PI * coeff * coeff * coeff2 * tmp * q2_all * q2_all / nr ; tmp1=eps_poly3(nx,info->nkx[0],info->pme_order[0]); tmp1*=info->nkx[0]; tmp2=iprod(gridp,info->recipbox[XX]); tmp=tmp1*tmp2; tmp1=eps_poly3(ny,info->nky[0],info->pme_order[0]); tmp1*=info->nky[0]; tmp2=iprod(gridp,info->recipbox[YY]); tmp+=tmp1*tmp2; tmp1=eps_poly3(nz,info->nkz[0],info->pme_order[0]); tmp1*=info->nkz[0]; tmp2=iprod(gridp,info->recipbox[ZZ]); tmp+=tmp1*tmp2; tmp*=4.0 * M_PI; tmp1=eps_poly4(nx,info->nkx[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[XX]); tmp1*=info->nkx[0] * info->nkx[0]; tmp+=tmp1; tmp1=eps_poly4(ny,info->nky[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[YY]); tmp1*=info->nky[0] * info->nky[0]; tmp+=tmp1; tmp1=eps_poly4(nz,info->nkz[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[ZZ]); tmp1*=info->nkz[0] * info->nkz[0]; tmp+=tmp1; e_rec2+= 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr ; } } if (MASTER(cr)) fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core)); } if (MASTER(cr)) fprintf(stderr, "\n"); /* Use just a fraction of all charges to estimate the self energy error term? */ bFraction = (info->fracself > 0.0) && (info->fracself < 1.0); if (bFraction) { /* Here xtot is the number of samples taken for the Monte Carlo calculation * of the average of term IV of equation 35 in Wang2010. Round up to a * number of samples that is divisible by the number of nodes */ x_per_core = ceil(info->fracself * nr / (real)cr->nnodes); xtot = x_per_core * cr->nnodes; } else { /* In this case we use all nr particle positions */ xtot = nr; x_per_core = ceil( (real)xtot / (real)cr->nnodes ); } startlocal = x_per_core * cr->nodeid; stoplocal = min(startlocal + x_per_core, xtot); /* min needed if xtot == nr */ if (bFraction) { /* Make shure we get identical results in serial and parallel. Therefore, * take the sample indices from a single, global random number array that * is constructed on the master node and that only depends on the seed */ snew(numbers, xtot); if (MASTER(cr)) { for (i=0; i<xtot; i++) { numbers[i] = floor(gmx_rng_uniform_real(rng) * nr ); } } /* Broadcast the random number array to the other nodes */ if (PAR(cr)) { nblock_bc(cr,xtot,numbers); } if (bVerbose && MASTER(cr)) { fprintf(stdout, "Using %d sample%s to approximate the self interaction error term", xtot, xtot==1?"":"s"); if (PAR(cr)) fprintf(stdout, " (%d sample%s per node)", x_per_core, x_per_core==1?"":"s"); fprintf(stdout, ".\n"); } } /* Return the number of positions used for the Monte Carlo algorithm */ *nsamples = xtot; for(i=startlocal;i<stoplocal;i++) { e_rec3x=0; e_rec3y=0; e_rec3z=0; if (bFraction) { /* Randomly pick a charge */ ci = numbers[i]; } else { /* Use all charges */ ci = i; } /* for(nx=startlocal; nx<=stoplocal; nx++)*/ for(nx=-info->nkx[0]/2; nx<info->nkx[0]/2+1; nx++) { svmul(nx,info->recipbox[XX],gridpx); for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++) { svmul(ny,info->recipbox[YY],tmpvec); rvec_add(gridpx,tmpvec,gridpxy); for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++) { if ( 0 == nx && 0 == ny && 0 == nz) continue; svmul(nz,info->recipbox[ZZ],tmpvec); rvec_add(gridpxy,tmpvec,gridp); tmp=norm2(gridp); coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] ); coeff/= tmp ; e_rec3x+=coeff*eps_self(nx,info->nkx[0],info->recipbox[XX],info->pme_order[0],x[ci]); e_rec3y+=coeff*eps_self(ny,info->nky[0],info->recipbox[YY],info->pme_order[0],x[ci]); e_rec3z+=coeff*eps_self(nz,info->nkz[0],info->recipbox[ZZ],info->pme_order[0],x[ci]); } } } clear_rvec(tmpvec2); svmul(e_rec3x,info->recipbox[XX],tmpvec); rvec_inc(tmpvec2,tmpvec); svmul(e_rec3y,info->recipbox[YY],tmpvec); rvec_inc(tmpvec2,tmpvec); svmul(e_rec3z,info->recipbox[ZZ],tmpvec); rvec_inc(tmpvec2,tmpvec); e_rec3 += q[ci]*q[ci]*q[ci]*q[ci]*norm2(tmpvec2) / ( xtot * M_PI * info->volume * M_PI * info->volume); if (MASTER(cr)){ fprintf(stderr, "\rCalculating reciprocal error part 2 ... %3.0f%%", 100.0*(i+1)/stoplocal); } } if (MASTER(cr)) fprintf(stderr, "\n"); #ifdef GMX_LIB_MPI #ifdef TAKETIME if (MASTER(cr)) { t1= MPI_Wtime() - t0; fprintf(fp_out, "Recip. err. est. took : %lf s\n", t1); } #endif #endif #ifdef DEBUG if (PAR(cr)) { fprintf(stderr, "Node %3d: nx=[%3d...%3d] e_rec3=%e\n", cr->nodeid, startlocal, stoplocal, e_rec3); } #endif if (PAR(cr)) { gmx_sum(1,&e_rec1,cr); gmx_sum(1,&e_rec2,cr); gmx_sum(1,&e_rec3,cr); } /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ; e_rec2*= q2_all / M_PI / M_PI / info->volume / info->volume / nr ; e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ; */ e_rec=sqrt(e_rec1+e_rec2+e_rec3); return ONE_4PI_EPS0 * e_rec; }
gmx_radial_distribution_histogram_t *calc_radial_distribution_histogram ( gmx_sans_t *gsans, rvec *x, matrix box, atom_id *index, int isize, double binwidth, gmx_bool bMC, gmx_bool bNORM, real mcover, unsigned int seed) { gmx_radial_distribution_histogram_t *pr = 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); /* set some fields */ pr->binwidth = binwidth; /* * create max dist rvec * dist = box[xx] + box[yy] + box[zz] */ rvec_add(box[XX], box[YY], dist); rvec_add(box[ZZ], dist, dist); rmax = norm(dist); pr->grn = (int)floor(rmax/pr->binwidth)+1; rmax = pr->grn*pr->binwidth; snew(pr->gr, pr->grn); if (bMC) { /* Special case for setting automaticaly number of mc iterations to 1% of total number of direct iterations */ if (mcover == -1) { max = (gmx_large_int_t)floor(0.5*0.01*isize*(isize-1)); } else { max = (gmx_large_int_t)floor(0.5*mcover*isize*(isize-1)); } rng = gmx_rng_init(seed); #ifdef GMX_OPENMP nthreads = gmx_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 = gmx_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]]; } } #endif gmx_rng_destroy(rng); } else { #ifdef GMX_OPENMP nthreads = gmx_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 = gmx_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 if needed */ if (bNORM) { normalize_probability(pr->grn, pr->gr); } snew(pr->r, pr->grn); for (i = 0; i < pr->grn; i++) { pr->r[i] = (pr->binwidth*i+pr->binwidth*0.5); } return (gmx_radial_distribution_histogram_t *) pr; }
int gmx_nmens(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] generates an ensemble around an average structure", "in a subspace that is defined by a set of normal modes (eigenvectors).", "The eigenvectors are assumed to be mass-weighted.", "The position along each eigenvector is randomly taken from a Gaussian", "distribution with variance kT/eigenvalue.[PAR]", "By default the starting eigenvector is set to 7, since the first six", "normal modes are the translational and rotational degrees of freedom." }; static int nstruct = 100, first = 7, last = -1, seed = -1; static real temp = 300.0; t_pargs pa[] = { { "-temp", FALSE, etREAL, {&temp}, "Temperature in Kelvin" }, { "-seed", FALSE, etINT, {&seed}, "Random seed, -1 generates a seed from time and pid" }, { "-num", FALSE, etINT, {&nstruct}, "Number of structures to generate" }, { "-first", FALSE, etINT, {&first}, "First eigenvector to use (-1 is select)" }, { "-last", FALSE, etINT, {&last}, "Last eigenvector to use (-1 is till the last)" } }; #define NPA asize(pa) t_trxstatus *out; int status, trjout; t_topology top; int ePBC; t_atoms *atoms; rvec *xtop, *xref, *xav, *xout1, *xout2; gmx_bool bDMR, bDMA, bFit; int nvec, *eignr = NULL; rvec **eigvec = NULL; matrix box; real *eigval, totmass, *invsqrtm, t, disp; int natoms, neigval; char *grpname, title[STRLEN]; const char *indexfile; int i, j, d, s, v; int nout, *iout, noutvec, *outvec; atom_id *index; real rfac, invfr, rhalf, jr; int * eigvalnr; output_env_t oenv; gmx_rng_t rng; unsigned long jran; const unsigned long im = 0xffff; const unsigned long ia = 1093; const unsigned long ic = 18257; t_filenm fnm[] = { { efTRN, "-v", "eigenvec", ffREAD }, { efXVG, "-e", "eigenval", ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efTRO, "-o", "ensemble", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_BE_NICE, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } indexfile = ftp2fn_null(efNDX, NFILE, fnm); read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit, &xref, &bDMR, &xav, &bDMA, &nvec, &eignr, &eigvec, &eigval); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, box, bDMA); atoms = &top.atoms; printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n", natoms); get_index(atoms, indexfile, 1, &i, &index, &grpname); if (i != natoms) { gmx_fatal(FARGS, "you selected a group with %d elements instead of %d", i, natoms); } printf("\n"); snew(invsqrtm, natoms); if (bDMA) { for (i = 0; (i < natoms); i++) { invsqrtm[i] = gmx_invsqrt(atoms->atom[index[i]].m); } } else { for (i = 0; (i < natoms); i++) { invsqrtm[i] = 1.0; } } if (last == -1) { last = natoms*DIM; } if (first > -1) { /* make an index from first to last */ nout = last-first+1; snew(iout, nout); for (i = 0; i < nout; i++) { iout[i] = first-1+i; } } else { printf("Select eigenvectors for output, end your selection with 0\n"); nout = -1; iout = NULL; do { nout++; srenew(iout, nout+1); if (1 != scanf("%d", &iout[nout])) { gmx_fatal(FARGS, "Error reading user input"); } iout[nout]--; } while (iout[nout] >= 0); printf("\n"); } /* make an index of the eigenvectors which are present */ snew(outvec, nout); noutvec = 0; for (i = 0; i < nout; i++) { j = 0; while ((j < nvec) && (eignr[j] != iout[i])) { j++; } if ((j < nvec) && (eignr[j] == iout[i])) { outvec[noutvec] = j; iout[noutvec] = iout[i]; noutvec++; } } fprintf(stderr, "%d eigenvectors selected for output\n", noutvec); if (seed == -1) { seed = (int)gmx_rng_make_seed(); rng = gmx_rng_init(seed); } else { rng = gmx_rng_init(seed); } fprintf(stderr, "Using seed %d and a temperature of %g K\n", seed, temp); snew(xout1, natoms); snew(xout2, atoms->nr); out = open_trx(ftp2fn(efTRO, NFILE, fnm), "w"); jran = (unsigned long)((real)im*gmx_rng_uniform_real(rng)); gmx_rng_destroy(rng); for (s = 0; s < nstruct; s++) { for (i = 0; i < natoms; i++) { copy_rvec(xav[i], xout1[i]); } for (j = 0; j < noutvec; j++) { v = outvec[j]; /* (r-0.5) n times: var_n = n * var_1 = n/12 n=4: var_n = 1/3, so multiply with 3 */ rfac = sqrt(3.0 * BOLTZ*temp/eigval[iout[j]]); rhalf = 2.0*rfac; rfac = rfac/(real)im; jran = (jran*ia+ic) & im; jr = (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; disp = rfac * jr - rhalf; for (i = 0; i < natoms; i++) { for (d = 0; d < DIM; d++) { xout1[i][d] += disp*eigvec[v][i][d]*invsqrtm[i]; } } } for (i = 0; i < natoms; i++) { copy_rvec(xout1[i], xout2[index[i]]); } t = s+1; write_trx(out, natoms, index, atoms, 0, t, box, xout2, NULL, NULL); fprintf(stderr, "\rGenerated %d structures", s+1); } fprintf(stderr, "\n"); close_trx(out); return 0; }
double do_tpi(FILE *fplog,t_commrec *cr, int nfile, const t_filenm fnm[], const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact, int nstglobalcomm, gmx_vsite_t *vsite,gmx_constr_t constr, int stepout, t_inputrec *inputrec, gmx_mtop_t *top_global,t_fcdata *fcd, t_state *state, t_mdatoms *mdatoms, t_nrnb *nrnb,gmx_wallcycle_t wcycle, gmx_edsam_t ed, t_forcerec *fr, int repl_ex_nst,int repl_ex_seed, real cpt_period,real max_hours, const char *deviceOptions, unsigned long Flags, gmx_runtime_t *runtime) { const char *TPI="Test Particle Insertion"; gmx_localtop_t *top; gmx_groups_t *groups; gmx_enerdata_t *enerd; rvec *f; real lambda,t,temp,beta,drmax,epot; double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all; t_trxstatus *status; t_trxframe rerun_fr; gmx_bool bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep; tensor force_vir,shake_vir,vir,pres; int cg_tp,a_tp0,a_tp1,ngid,gid_tp,nener,e; rvec *x_mol; rvec mu_tot,x_init,dx,x_tp; int nnodes,frame,nsteps,step; int i,start,end; gmx_rng_t tpi_rand; FILE *fp_tpi=NULL; char *ptr,*dump_pdb,**leg,str[STRLEN],str2[STRLEN]; double dbl,dump_ener; gmx_bool bCavity; int nat_cavity=0,d; real *mass_cavity=NULL,mass_tot; int nbin; double invbinw,*bin,refvolshift,logV,bUlogV; real dvdl,prescorr,enercorr,dvdlcorr; gmx_bool bEnergyOutOfBounds; const char *tpid_leg[2]={"direct","reweighted"}; /* Since there is no upper limit to the insertion energies, * we need to set an upper limit for the distribution output. */ real bU_bin_limit = 50; real bU_logV_bin_limit = bU_bin_limit + 10; nnodes = cr->nnodes; top = gmx_mtop_generate_local_top(top_global,inputrec); groups = &top_global->groups; bCavity = (inputrec->eI == eiTPIC); if (bCavity) { ptr = getenv("GMX_TPIC_MASSES"); if (ptr == NULL) { nat_cavity = 1; } else { /* Read (multiple) masses from env var GMX_TPIC_MASSES, * The center of mass of the last atoms is then used for TPIC. */ nat_cavity = 0; while (sscanf(ptr,"%lf%n",&dbl,&i) > 0) { srenew(mass_cavity,nat_cavity+1); mass_cavity[nat_cavity] = dbl; fprintf(fplog,"mass[%d] = %f\n", nat_cavity+1,mass_cavity[nat_cavity]); nat_cavity++; ptr += i; } if (nat_cavity == 0) gmx_fatal(FARGS,"Found %d masses in GMX_TPIC_MASSES",nat_cavity); } } /* init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot, state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/ /* We never need full pbc for TPI */ fr->ePBC = epbcXYZ; /* Determine the temperature for the Boltzmann weighting */ temp = inputrec->opts.ref_t[0]; if (fplog) { for(i=1; (i<inputrec->opts.ngtc); i++) { if (inputrec->opts.ref_t[i] != temp) { fprintf(fplog,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n"); fprintf(stderr,"\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n"); } } fprintf(fplog, "\n The temperature for test particle insertion is %.3f K\n\n", temp); } beta = 1.0/(BOLTZ*temp); /* Number of insertions per frame */ nsteps = inputrec->nsteps; /* Use the same neighborlist with more insertions points * in a sphere of radius drmax around the initial point */ /* This should be a proper mdp parameter */ drmax = inputrec->rtpi; /* An environment variable can be set to dump all configurations * to pdb with an insertion energy <= this value. */ dump_pdb = getenv("GMX_TPI_DUMP"); dump_ener = 0; if (dump_pdb) sscanf(dump_pdb,"%lf",&dump_ener); atoms2md(top_global,inputrec,0,NULL,0,top_global->natoms,mdatoms); update_mdatoms(mdatoms,inputrec->init_lambda); snew(enerd,1); init_enerdata(groups->grps[egcENER].nr,inputrec->n_flambda,enerd); snew(f,top_global->natoms); /* Print to log file */ runtime_start(runtime); print_date_and_time(fplog,cr->nodeid, "Started Test Particle Insertion",runtime); wallcycle_start(wcycle,ewcRUN); /* The last charge group is the group to be inserted */ cg_tp = top->cgs.nr - 1; a_tp0 = top->cgs.index[cg_tp]; a_tp1 = top->cgs.index[cg_tp+1]; if (debug) fprintf(debug,"TPI cg %d, atoms %d-%d\n",cg_tp,a_tp0,a_tp1); if (a_tp1 - a_tp0 > 1 && (inputrec->rlist < inputrec->rcoulomb || inputrec->rlist < inputrec->rvdw)) gmx_fatal(FARGS,"Can not do TPI for multi-atom molecule with a twin-range cut-off"); snew(x_mol,a_tp1-a_tp0); bDispCorr = (inputrec->eDispCorr != edispcNO); bCharge = FALSE; for(i=a_tp0; i<a_tp1; i++) { /* Copy the coordinates of the molecule to be insterted */ copy_rvec(state->x[i],x_mol[i-a_tp0]); /* Check if we need to print electrostatic energies */ bCharge |= (mdatoms->chargeA[i] != 0 || (mdatoms->chargeB && mdatoms->chargeB[i] != 0)); } bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype!=eelRF_NEC); calc_cgcm(fplog,cg_tp,cg_tp+1,&(top->cgs),state->x,fr->cg_cm); if (bCavity) { if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog) { fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n"); fprintf(stderr,"WARNING: Your TPI molecule is not centered at 0,0,0\n"); } } else { /* Center the molecule to be inserted at zero */ for(i=0; i<a_tp1-a_tp0; i++) rvec_dec(x_mol[i],fr->cg_cm[cg_tp]); } if (fplog) { fprintf(fplog,"\nWill insert %d atoms %s partial charges\n", a_tp1-a_tp0,bCharge ? "with" : "without"); fprintf(fplog,"\nWill insert %d times in each frame of %s\n", nsteps,opt2fn("-rerun",nfile,fnm)); } if (!bCavity) { if (inputrec->nstlist > 1) { if (drmax==0 && a_tp1-a_tp0==1) { gmx_fatal(FARGS,"Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense",inputrec->nstlist,drmax); } if (fplog) { fprintf(fplog,"Will use the same neighborlist for %d insertions in a sphere of radius %f\n",inputrec->nstlist,drmax); } } } else { if (fplog) { fprintf(fplog,"Will insert randomly in a sphere of radius %f around the center of the cavity\n",drmax); } } ngid = groups->grps[egcENER].nr; gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]); nener = 1 + ngid; if (bDispCorr) nener += 1; if (bCharge) { nener += ngid; if (bRFExcl) nener += 1; if (EEL_FULL(fr->eeltype)) nener += 1; } snew(sum_UgembU,nener); /* Initialize random generator */ tpi_rand = gmx_rng_init(inputrec->ld_seed); if (MASTER(cr)) { fp_tpi = xvgropen(opt2fn("-tpi",nfile,fnm), "TPI energies","Time (ps)", "(kJ mol\\S-1\\N) / (nm\\S3\\N)",oenv); xvgr_subtitle(fp_tpi,"f. are averages over one frame",oenv); snew(leg,4+nener); e = 0; sprintf(str,"-kT log(<Ve\\S-\\betaU\\N>/<V>)"); leg[e++] = strdup(str); sprintf(str,"f. -kT log<e\\S-\\betaU\\N>"); leg[e++] = strdup(str); sprintf(str,"f. <e\\S-\\betaU\\N>"); leg[e++] = strdup(str); sprintf(str,"f. V"); leg[e++] = strdup(str); sprintf(str,"f. <Ue\\S-\\betaU\\N>"); leg[e++] = strdup(str); for(i=0; i<ngid; i++) { sprintf(str,"f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>", *(groups->grpname[groups->grps[egcENER].nm_ind[i]])); leg[e++] = strdup(str); } if (bDispCorr) { sprintf(str,"f. <U\\sdisp c\\Ne\\S-\\betaU\\N>"); leg[e++] = strdup(str); } if (bCharge) { for(i=0; i<ngid; i++) { sprintf(str,"f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>", *(groups->grpname[groups->grps[egcENER].nm_ind[i]])); leg[e++] = strdup(str); } if (bRFExcl) { sprintf(str,"f. <U\\sRF excl\\Ne\\S-\\betaU\\N>"); leg[e++] = strdup(str); } if (EEL_FULL(fr->eeltype)) { sprintf(str,"f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>"); leg[e++] = strdup(str); } } xvgr_legend(fp_tpi,4+nener,(const char**)leg,oenv); for(i=0; i<4+nener; i++) sfree(leg[i]); sfree(leg); } clear_rvec(x_init); V_all = 0; VembU_all = 0; invbinw = 10; nbin = 10; snew(bin,nbin); bNotLastFrame = read_first_frame(oenv,&status,opt2fn("-rerun",nfile,fnm), &rerun_fr,TRX_NEED_X); frame = 0; if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) != mdatoms->nr - (a_tp1 - a_tp0)) gmx_fatal(FARGS,"Number of atoms in trajectory (%d)%s " "is not equal the number in the run input file (%d) " "minus the number of atoms to insert (%d)\n", rerun_fr.natoms,bCavity ? " minus one" : "", mdatoms->nr,a_tp1-a_tp0); refvolshift = log(det(rerun_fr.box)); #if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) /* Make sure we don't detect SSE overflow generated before this point */ gmx_mm_check_and_reset_overflow(); #endif while (bNotLastFrame) { lambda = rerun_fr.lambda; t = rerun_fr.time; sum_embU = 0; for(e=0; e<nener; e++) { sum_UgembU[e] = 0; } /* Copy the coordinates from the input trajectory */ for(i=0; i<rerun_fr.natoms; i++) { copy_rvec(rerun_fr.x[i],state->x[i]); } V = det(rerun_fr.box); logV = log(V); bStateChanged = TRUE; bNS = TRUE; for(step=0; step<nsteps; step++) { /* In parallel all nodes generate all random configurations. * In that way the result is identical to a single cpu tpi run. */ if (!bCavity) { /* Random insertion in the whole volume */ bNS = (step % inputrec->nstlist == 0); if (bNS) { /* Generate a random position in the box */ x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX]; x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY]; x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ]; } if (inputrec->nstlist == 1) { copy_rvec(x_init,x_tp); } else { /* Generate coordinates within |dx|=drmax of x_init */ do { dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; } while (norm2(dx) > drmax*drmax); rvec_add(x_init,dx,x_tp); } } else { /* Random insertion around a cavity location * given by the last coordinate of the trajectory. */ if (step == 0) { if (nat_cavity == 1) { /* Copy the location of the cavity */ copy_rvec(rerun_fr.x[rerun_fr.natoms-1],x_init); } else { /* Determine the center of mass of the last molecule */ clear_rvec(x_init); mass_tot = 0; for(i=0; i<nat_cavity; i++) { for(d=0; d<DIM; d++) { x_init[d] += mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d]; } mass_tot += mass_cavity[i]; } for(d=0; d<DIM; d++) { x_init[d] /= mass_tot; } } } /* Generate coordinates within |dx|=drmax of x_init */ do { dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax; } while (norm2(dx) > drmax*drmax); rvec_add(x_init,dx,x_tp); } if (a_tp1 - a_tp0 == 1) { /* Insert a single atom, just copy the insertion location */ copy_rvec(x_tp,state->x[a_tp0]); } else { /* Copy the coordinates from the top file */ for(i=a_tp0; i<a_tp1; i++) { copy_rvec(x_mol[i-a_tp0],state->x[i]); } /* Rotate the molecule randomly */ rotate_conf(a_tp1-a_tp0,state->x+a_tp0,NULL, 2*M_PI*gmx_rng_uniform_real(tpi_rand), 2*M_PI*gmx_rng_uniform_real(tpi_rand), 2*M_PI*gmx_rng_uniform_real(tpi_rand)); /* Shift to the insertion location */ for(i=a_tp0; i<a_tp1; i++) { rvec_inc(state->x[i],x_tp); } } /* Check if this insertion belongs to this node */ bOurStep = TRUE; if (PAR(cr)) { switch (inputrec->eI) { case eiTPI: bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid); break; case eiTPIC: bOurStep = (step % nnodes == cr->nodeid); break; default: gmx_fatal(FARGS,"Unknown integrator %s",ei_names[inputrec->eI]); } } if (bOurStep) { /* Clear some matrix variables */ clear_mat(force_vir); clear_mat(shake_vir); clear_mat(vir); clear_mat(pres); /* Set the charge group center of mass of the test particle */ copy_rvec(x_init,fr->cg_cm[top->cgs.nr-1]); /* Calc energy (no forces) on new positions. * Since we only need the intermolecular energy * and the RF exclusion terms of the inserted molecule occur * within a single charge group we can pass NULL for the graph. * This also avoids shifts that would move charge groups * out of the box. * * Some checks above ensure than we can not have * twin-range interactions together with nstlist > 1, * therefore we do not need to remember the LR energies. */ /* Make do_force do a single node force calculation */ cr->nnodes = 1; do_force(fplog,cr,inputrec, step,nrnb,wcycle,top,top_global,&top_global->groups, rerun_fr.box,state->x,&state->hist, f,force_vir,mdatoms,enerd,fcd, lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE, GMX_FORCE_NONBONDED | (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) | (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); cr->nnodes = nnodes; bStateChanged = FALSE; bNS = FALSE; /* Calculate long range corrections to pressure and energy */ calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box, lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr); /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */ enerd->term[F_DISPCORR] = enercorr; enerd->term[F_EPOT] += enercorr; enerd->term[F_PRES] += prescorr; enerd->term[F_DVDL] += dvdlcorr; epot = enerd->term[F_EPOT]; bEnergyOutOfBounds = FALSE; #if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) /* With SSE the energy can overflow, check for this */ if (gmx_mm_check_and_reset_overflow()) { if (debug) { fprintf(debug,"Found an SSE overflow, assuming the energy is out of bounds\n"); } bEnergyOutOfBounds = TRUE; } #endif /* If the compiler doesn't optimize this check away * we catch the NAN energies. * The epot>GMX_REAL_MAX check catches inf values, * which should nicely result in embU=0 through the exp below, * but it does not hurt to check anyhow. */ /* Non-bonded Interaction usually diverge at r=0. * With tabulated interaction functions the first few entries * should be capped in a consistent fashion between * repulsion, dispersion and Coulomb to avoid accidental * negative values in the total energy. * The table generation code in tables.c does this. * With user tbales the user should take care of this. */ if (epot != epot || epot > GMX_REAL_MAX) { bEnergyOutOfBounds = TRUE; } if (bEnergyOutOfBounds) { if (debug) { fprintf(debug,"\n time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n",t,step,epot); } embU = 0; } else { embU = exp(-beta*epot); sum_embU += embU; /* Determine the weighted energy contributions of each energy group */ e = 0; sum_UgembU[e++] += epot*embU; if (fr->bBHAM) { for(i=0; i<ngid; i++) { sum_UgembU[e++] += (enerd->grpp.ener[egBHAMSR][GID(i,gid_tp,ngid)] + enerd->grpp.ener[egBHAMLR][GID(i,gid_tp,ngid)])*embU; } } else { for(i=0; i<ngid; i++) { sum_UgembU[e++] += (enerd->grpp.ener[egLJSR][GID(i,gid_tp,ngid)] + enerd->grpp.ener[egLJLR][GID(i,gid_tp,ngid)])*embU; } } if (bDispCorr) { sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU; } if (bCharge) { for(i=0; i<ngid; i++) { sum_UgembU[e++] += (enerd->grpp.ener[egCOULSR][GID(i,gid_tp,ngid)] + enerd->grpp.ener[egCOULLR][GID(i,gid_tp,ngid)])*embU; } if (bRFExcl) { sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU; } if (EEL_FULL(fr->eeltype)) { sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU; } } } if (embU == 0 || beta*epot > bU_bin_limit) { bin[0]++; } else { i = (int)((bU_logV_bin_limit - (beta*epot - logV + refvolshift))*invbinw + 0.5); if (i < 0) { i = 0; } if (i >= nbin) { realloc_bins(&bin,&nbin,i+10); } bin[i]++; } if(fr->adress_do_drift ||fr->adress_icor == eAdressICThermoForce ){ sum_UgembU[e++] += enerd->term[F_ADR_DELTU]*embU; } if (debug) { fprintf(debug,"TPI %7d %12.5e %12.5f %12.5f %12.5f\n", step,epot,x_tp[XX],x_tp[YY],x_tp[ZZ]); } if (dump_pdb && epot <= dump_ener) { sprintf(str,"t%g_step%d.pdb",t,step); sprintf(str2,"t: %f step %d ener: %f",t,step,epot); write_sto_conf_mtop(str,str2,top_global,state->x,state->v, inputrec->ePBC,state->box); } } } if (PAR(cr)) { /* When running in parallel sum the energies over the processes */ gmx_sumd(1, &sum_embU, cr); gmx_sumd(nener,sum_UgembU,cr); } frame++; V_all += V; VembU_all += V*sum_embU/nsteps; if (fp_tpi) { if (bVerbose || frame%10==0 || frame<10) { fprintf(stderr,"mu %10.3e <mu> %10.3e\n", -log(sum_embU/nsteps)/beta,-log(VembU_all/V_all)/beta); } fprintf(fp_tpi,"%10.3f %12.5e %12.5e %12.5e %12.5e", t, VembU_all==0 ? 20/beta : -log(VembU_all/V_all)/beta, sum_embU==0 ? 20/beta : -log(sum_embU/nsteps)/beta, sum_embU/nsteps,V); for(e=0; e<nener; e++) { fprintf(fp_tpi," %12.5e",sum_UgembU[e]/nsteps); } fprintf(fp_tpi,"\n"); fflush(fp_tpi); } bNotLastFrame = read_next_frame(oenv, status,&rerun_fr); } /* End of the loop */ runtime_end(runtime); close_trj(status); if (fp_tpi != NULL) { gmx_fio_fclose(fp_tpi); } if (fplog != NULL) { fprintf(fplog,"\n"); fprintf(fplog," <V> = %12.5e nm^3\n",V_all/frame); fprintf(fplog," <mu> = %12.5e kJ/mol\n",-log(VembU_all/V_all)/beta); } /* Write the Boltzmann factor histogram */ if (PAR(cr)) { /* When running in parallel sum the bins over the processes */ i = nbin; global_max(cr,&i); realloc_bins(&bin,&nbin,i); gmx_sumd(nbin,bin,cr); } if (MASTER(cr)) { fp_tpi = xvgropen(opt2fn("-tpid",nfile,fnm), "TPI energy distribution", "\\betaU - log(V/<V>)","count",oenv); sprintf(str,"number \\betaU > %g: %9.3e",bU_bin_limit,bin[0]); xvgr_subtitle(fp_tpi,str,oenv); xvgr_legend(fp_tpi,2,(const char **)tpid_leg,oenv); for(i=nbin-1; i>0; i--) { bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame); fprintf(fp_tpi,"%6.2f %10d %12.5e\n", bUlogV, (int)(bin[i]+0.5), bin[i]*exp(-bUlogV)*V_all/VembU_all); } gmx_fio_fclose(fp_tpi); } sfree(bin); sfree(sum_UgembU); runtime->nsteps_done = frame*inputrec->nsteps; return 0; }
/* Estimate the reciprocal space part error of the SPME Ewald sum. */ static real estimate_reciprocal( t_inputinfo *info, rvec x[], /* array of particles */ real q[], /* array of charges */ int nr, /* number of charges = size of the charge array */ FILE *fp_out, t_commrec *cr) { real e_rec=0; /* reciprocal error estimate */ real e_rec1=0; /* Error estimate term 1*/ real e_rec2=0; /* Error estimate term 2*/ real e_rec3=0; /* Error estimate term 3 */ real e_rec3x=0; /* part of Error estimate term 3 in x */ real e_rec3y=0; /* part of Error estimate term 3 in y */ real e_rec3z=0; /* part of Error estimate term 3 in z */ int i,ci; int nx,ny,nz; /* grid coordinates */ real q2_all=0; /* sum of squared charges */ rvec gridpx; /* reciprocal grid point in x direction*/ rvec gridpxy; /* reciprocal grid point in x and y direction*/ rvec gridp; /* complete reciprocal grid point in 3 directions*/ rvec tmpvec; /* template to create points from basis vectors */ rvec tmpvec2; /* template to create points from basis vectors */ real coeff=0; /* variable to compute coefficients of the error estimate */ real coeff2=0; /* variable to compute coefficients of the error estimate */ real tmp=0; /* variables to compute different factors from vectors */ real tmp1=0; real tmp2=0; real xtmp=0; real ytmp=0; real ztmp=0; double ewald_error; /* Random number generator */ gmx_rng_t rng=NULL; /*rng=gmx_rng_init(gmx_rng_make_seed()); */ /* Index variables for parallel work distribution */ int startglobal,stopglobal; int startlocal, stoplocal; int x_per_core; int nrsamples; real xtot; /* #define TAKETIME */ #ifdef TAKETIME double t0=0.0; double t1=0.0; double t2=0.0; #endif rng=gmx_rng_init(cr->nodeid); clear_rvec(gridpx); clear_rvec(gridpxy); clear_rvec(gridp); clear_rvec(tmpvec); clear_rvec(tmpvec2); for(i=0;i<nr;i++) { q2_all += q[i]*q[i]; } /* Calculate indices for work distribution */ startglobal=-info->nkx[0]/2; stopglobal = info->nkx[0]/2; xtot = stopglobal*2+1; if (PAR(cr)) { x_per_core = ceil(xtot / cr->nnodes); startlocal = startglobal + x_per_core*cr->nodeid; stoplocal = startlocal + x_per_core -1; if (stoplocal > stopglobal) stoplocal = stopglobal; } else { startlocal = startglobal; stoplocal = stopglobal; x_per_core = xtot; } /* #ifdef GMX_MPI MPI_Barrier(MPI_COMM_WORLD); #endif */ #ifdef TAKETIME if (MASTER(cr)) t0 = MPI_Wtime(); #endif if (MASTER(cr)){ fprintf(stderr, "Calculating reciprocal error part 1 ..."); } for(nx=startlocal; nx<=stoplocal; nx++) { svmul(nx,info->recipbox[XX],gridpx); for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++) { svmul(ny,info->recipbox[YY],tmpvec); rvec_add(gridpx,tmpvec,gridpxy); for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++) { if ( 0 == nx && 0 == ny && 0 == nz ) continue; svmul(nz,info->recipbox[ZZ],tmpvec); rvec_add(gridpxy,tmpvec,gridp); tmp=norm2(gridp); coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] ) ; coeff/= 2.0 * M_PI * info->volume * tmp; coeff2=tmp ; tmp=eps_poly2(nx,info->nkx[0],info->pme_order[0]); tmp+=eps_poly2(ny,info->nkx[0],info->pme_order[0]); tmp+=eps_poly2(nz,info->nkx[0],info->pme_order[0]); tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp2=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp+=2.0 * tmp1 * tmp2; tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]); tmp1+=eps_poly1(ny,info->nky[0],info->pme_order[0]); tmp1+=eps_poly1(nz,info->nkz[0],info->pme_order[0]); tmp+= tmp1 * tmp1; e_rec1+= 32.0 * M_PI * M_PI * coeff * coeff * coeff2 * tmp * q2_all * q2_all / nr ; tmp1=eps_poly3(nx,info->nkx[0],info->pme_order[0]); tmp1*=info->nkx[0]; tmp2=iprod(gridp,info->recipbox[XX]); tmp=tmp1*tmp2; tmp1=eps_poly3(ny,info->nky[0],info->pme_order[0]); tmp1*=info->nky[0]; tmp2=iprod(gridp,info->recipbox[YY]); tmp+=tmp1*tmp2; tmp1=eps_poly3(nz,info->nkz[0],info->pme_order[0]); tmp1*=info->nkz[0]; tmp2=iprod(gridp,info->recipbox[ZZ]); tmp+=tmp1*tmp2; tmp*=4.0 * M_PI; tmp1=eps_poly4(nx,info->nkx[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[XX]); tmp1*=info->nkx[0] * info->nkx[0]; tmp+=tmp1; tmp1=eps_poly4(ny,info->nky[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[YY]); tmp1*=info->nky[0] * info->nky[0]; tmp+=tmp1; tmp1=eps_poly4(nz,info->nkz[0],info->pme_order[0]); tmp1*=norm2(info->recipbox[ZZ]); tmp1*=info->nkz[0] * info->nkz[0]; tmp+=tmp1; e_rec2+= 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr ; } } if (MASTER(cr)) fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core)); } /* #ifdef GMX_MPI MPI_Barrier(MPI_COMM_WORLD); #endif */ if (MASTER(cr)) fprintf(stderr, "\n"); if (info->fracself>0) { nrsamples=ceil(info->fracself*nr); } else { nrsamples=nr; } xtot=nrsamples; startglobal=0; stopglobal=nr; if(PAR(cr)) { x_per_core=ceil(xtot/cr->nnodes); startlocal=startglobal+x_per_core*cr->nodeid; stoplocal=startglobal+x_per_core*(cr->nodeid+1); if (stoplocal>stopglobal) stoplocal=stopglobal; } else { startlocal=startglobal; stoplocal=stopglobal; x_per_core=xtot; } for(i=startlocal;i<stoplocal;i++) { e_rec3x=0; e_rec3y=0; e_rec3z=0; if (info->fracself<0) { ci=i; }else { ci=floor(gmx_rng_uniform_real(rng) * nr ); if (ci==nr) { ci=nr-1; } } /* for(nx=startlocal; nx<=stoplocal; nx++)*/ for(nx=-info->nkx[0]/2; nx<info->nkx[0]/2+1; nx++) { svmul(nx,info->recipbox[XX],gridpx); for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++) { svmul(ny,info->recipbox[YY],tmpvec); rvec_add(gridpx,tmpvec,gridpxy); for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++) { if ( 0 == nx && 0 == ny && 0 == nz) continue; svmul(nz,info->recipbox[ZZ],tmpvec); rvec_add(gridpxy,tmpvec,gridp); tmp=norm2(gridp); coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] ); coeff/= tmp ; e_rec3x+=coeff*eps_self(nx,info->nkx[0],info->recipbox[XX],info->pme_order[0],x[ci]); e_rec3y+=coeff*eps_self(ny,info->nky[0],info->recipbox[YY],info->pme_order[0],x[ci]); e_rec3z+=coeff*eps_self(nz,info->nkz[0],info->recipbox[ZZ],info->pme_order[0],x[ci]); } } } clear_rvec(tmpvec2); svmul(e_rec3x,info->recipbox[XX],tmpvec); rvec_inc(tmpvec2,tmpvec); svmul(e_rec3y,info->recipbox[YY],tmpvec); rvec_inc(tmpvec2,tmpvec); svmul(e_rec3z,info->recipbox[ZZ],tmpvec); rvec_inc(tmpvec2,tmpvec); e_rec3 += q[ci]*q[ci]*q[ci]*q[ci]*norm2(tmpvec2) / ( nrsamples * M_PI * info->volume * M_PI * info->volume); if (MASTER(cr)){ fprintf(stderr, "\rCalculating reciprocal error part 2 ... %3.0f%%", 100.0*(i+1)/stoplocal); } } if (MASTER(cr)) fprintf(stderr, "\n"); #ifdef TAKETIME if (MASTER(cr)) { t1= MPI_Wtime() - t0; fprintf(fp_out, "Recip. err. est. took : %lf s\n", t1); } #endif #ifdef DEBUG if (PAR(cr)) { fprintf(stderr, "Node %3d: nx=[%3d...%3d] e_rec3=%e\n", cr->nodeid, startlocal, stoplocal, e_rec3); } #endif /* #ifdef GMX_MPI MPI_Barrier(MPI_COMM_WORLD); #endif */ #ifdef TAKETIME if (MASTER(cr)) { t2= MPI_Wtime() - t0; fprintf(fp_out, "barrier : %lf s\n", t2-t1); } #endif if (PAR(cr)) { gmx_sum(1,&e_rec1,cr); gmx_sum(1,&e_rec2,cr); gmx_sum(1,&e_rec3,cr); } #ifdef TAKETIME if (MASTER(cr)) fprintf(fp_out, "final reduce : %lf s\n", MPI_Wtime() - t0-t2); #endif /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ; e_rec2*= q2_all / M_PI / M_PI / info->volume / info->volume / nr ; e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ; */ e_rec=sqrt(e_rec1+e_rec2+e_rec3); return ONE_4PI_EPS0 * e_rec; }
static void insert_mols(int nmol_insrt, int ntry, int seed, t_atoms *atoms, rvec **x, real **exclusionDistances, t_atoms *atoms_insrt, rvec *x_insrt, real *exclusionDistances_insrt, int ePBC, matrix box, const char* posfn, const rvec deltaR, int enum_rot) { t_pbc pbc; rvec *x_n; int mol; int trial; double **rpos; const real maxInsertRadius = *std::max_element(exclusionDistances_insrt, exclusionDistances_insrt + atoms_insrt->nr); real maxRadius = maxInsertRadius; if (atoms->nr > 0) { const real maxExistingRadius = *std::max_element(*exclusionDistances, *exclusionDistances + atoms->nr); maxRadius = std::max(maxInsertRadius, maxExistingRadius); } // TODO: Make all of this exception-safe. gmx::AnalysisNeighborhood nb; nb.setCutoff(maxInsertRadius + maxRadius); gmx_rng_t rng = gmx_rng_init(seed); set_pbc(&pbc, ePBC, box); snew(x_n, atoms_insrt->nr); /* With -ip, take nmol_insrt from file posfn */ if (posfn != NULL) { int ncol; nmol_insrt = read_xvg(posfn, &rpos, &ncol); if (ncol != 3) { gmx_fatal(FARGS, "Expected 3 columns (x/y/z coordinates) in file %s\n", ncol, posfn); } fprintf(stderr, "Read %d positions from file %s\n\n", nmol_insrt, posfn); } { const int finalAtomCount = atoms->nr + nmol_insrt * atoms_insrt->nr; const int finalResidueCount = atoms->nres + nmol_insrt * atoms_insrt->nres; srenew(atoms->resinfo, finalResidueCount); srenew(atoms->atomname, finalAtomCount); srenew(atoms->atom, finalAtomCount); srenew(*x, finalAtomCount); srenew(*exclusionDistances, finalAtomCount); } trial = mol = 0; while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt)) { fprintf(stderr, "\rTry %d", trial++); rvec offset_x; if (posfn == NULL) { /* insert at random positions */ offset_x[XX] = box[XX][XX] * gmx_rng_uniform_real(rng); offset_x[YY] = box[YY][YY] * gmx_rng_uniform_real(rng); offset_x[ZZ] = box[ZZ][ZZ] * gmx_rng_uniform_real(rng); } else { /* Insert at positions taken from option -ip file */ offset_x[XX] = rpos[XX][mol] + deltaR[XX]*(2 * gmx_rng_uniform_real(rng)-1); offset_x[YY] = rpos[YY][mol] + deltaR[YY]*(2 * gmx_rng_uniform_real(rng)-1); offset_x[ZZ] = rpos[ZZ][mol] + deltaR[ZZ]*(2 * gmx_rng_uniform_real(rng)-1); } generate_trial_conf(atoms_insrt->nr, x_insrt, offset_x, enum_rot, rng, x_n); gmx::AnalysisNeighborhoodPositions pos(*x, atoms->nr); gmx::AnalysisNeighborhoodSearch search = nb.initSearch(&pbc, pos); if (is_insertion_allowed(&search, *exclusionDistances, atoms_insrt->nr, x_n, exclusionDistances_insrt)) { const int firstIndex = atoms->nr; for (int i = 0; i < atoms_insrt->nr; ++i) { copy_rvec(x_n[i], (*x)[firstIndex + i]); (*exclusionDistances)[firstIndex + i] = exclusionDistances_insrt[i]; } merge_atoms_noalloc(atoms, atoms_insrt); ++mol; fprintf(stderr, " success (now %d atoms)!\n", atoms->nr); } } gmx_rng_destroy(rng); srenew(atoms->resinfo, atoms->nres); srenew(atoms->atomname, atoms->nr); srenew(atoms->atom, atoms->nr); srenew(*x, atoms->nr); srenew(*exclusionDistances, atoms->nr); fprintf(stderr, "\n"); /* print number of molecules added */ fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n", mol, nmol_insrt, *atoms_insrt->resinfo[0].name); sfree(x_n); }
static void insert_mols(int nmol_insrt, int ntry, int seed, real defaultDistance, real scaleFactor, t_atoms *atoms, rvec **x, const t_atoms *atoms_insrt, const rvec *x_insrt, int ePBC, matrix box, const std::string &posfn, const rvec deltaR, int enum_rot) { t_pbc pbc; rvec *x_n; fprintf(stderr, "Initialising inter-atomic distances...\n"); gmx_atomprop_t aps = gmx_atomprop_init(); real *exclusionDistances = makeExclusionDistances(atoms, aps, defaultDistance, scaleFactor); real *exclusionDistances_insrt = makeExclusionDistances(atoms_insrt, aps, defaultDistance, scaleFactor); gmx_atomprop_destroy(aps); const real maxInsertRadius = *std::max_element(exclusionDistances_insrt, exclusionDistances_insrt + atoms_insrt->nr); real maxRadius = maxInsertRadius; if (atoms->nr > 0) { const real maxExistingRadius = *std::max_element(exclusionDistances, exclusionDistances + atoms->nr); maxRadius = std::max(maxInsertRadius, maxExistingRadius); } // TODO: Make all of this exception-safe. gmx::AnalysisNeighborhood nb; nb.setCutoff(maxInsertRadius + maxRadius); gmx_rng_t rng = gmx_rng_init(seed); set_pbc(&pbc, ePBC, box); snew(x_n, atoms_insrt->nr); /* With -ip, take nmol_insrt from file posfn */ double **rpos = NULL; if (!posfn.empty()) { int ncol; nmol_insrt = read_xvg(posfn.c_str(), &rpos, &ncol); if (ncol != 3) { gmx_fatal(FARGS, "Expected 3 columns (x/y/z coordinates) in file %s\n", posfn.c_str()); } fprintf(stderr, "Read %d positions from file %s\n\n", nmol_insrt, posfn.c_str()); } { const int finalAtomCount = atoms->nr + nmol_insrt * atoms_insrt->nr; const int finalResidueCount = atoms->nres + nmol_insrt * atoms_insrt->nres; srenew(atoms->resinfo, finalResidueCount); srenew(atoms->atomname, finalAtomCount); srenew(atoms->atom, finalAtomCount); srenew(*x, finalAtomCount); srenew(exclusionDistances, finalAtomCount); } int mol = 0; int trial = 0; int firstTrial = 0; int failed = 0; while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt)) { rvec offset_x; if (posfn.empty()) { // Insert at random positions. offset_x[XX] = box[XX][XX] * gmx_rng_uniform_real(rng); offset_x[YY] = box[YY][YY] * gmx_rng_uniform_real(rng); offset_x[ZZ] = box[ZZ][ZZ] * gmx_rng_uniform_real(rng); } else { // Skip a position if ntry trials were not successful. if (trial >= firstTrial + ntry) { fprintf(stderr, " skipped position (%.3f, %.3f, %.3f)\n", rpos[XX][mol], rpos[YY][mol], rpos[ZZ][mol]); ++mol; ++failed; } // Insert at positions taken from option -ip file. offset_x[XX] = rpos[XX][mol] + deltaR[XX]*(2 * gmx_rng_uniform_real(rng)-1); offset_x[YY] = rpos[YY][mol] + deltaR[YY]*(2 * gmx_rng_uniform_real(rng)-1); offset_x[ZZ] = rpos[ZZ][mol] + deltaR[ZZ]*(2 * gmx_rng_uniform_real(rng)-1); } fprintf(stderr, "\rTry %d", ++trial); generate_trial_conf(atoms_insrt->nr, x_insrt, offset_x, enum_rot, rng, x_n); gmx::AnalysisNeighborhoodPositions pos(*x, atoms->nr); gmx::AnalysisNeighborhoodSearch search = nb.initSearch(&pbc, pos); if (is_insertion_allowed(&search, exclusionDistances, atoms_insrt->nr, x_n, exclusionDistances_insrt)) { const int firstIndex = atoms->nr; for (int i = 0; i < atoms_insrt->nr; ++i) { copy_rvec(x_n[i], (*x)[firstIndex + i]); exclusionDistances[firstIndex + i] = exclusionDistances_insrt[i]; } merge_atoms_noalloc(atoms, atoms_insrt); ++mol; firstTrial = trial; fprintf(stderr, " success (now %d atoms)!\n", atoms->nr); } } gmx_rng_destroy(rng); srenew(atoms->resinfo, atoms->nres); srenew(atoms->atomname, atoms->nr); srenew(atoms->atom, atoms->nr); srenew(*x, atoms->nr); fprintf(stderr, "\n"); /* print number of molecules added */ fprintf(stderr, "Added %d molecules (out of %d requested)\n", mol - failed, nmol_insrt); sfree(x_n); sfree(exclusionDistances); sfree(exclusionDistances_insrt); if (rpos != NULL) { for (int i = 0; i < DIM; ++i) { sfree(rpos[i]); } sfree(rpos); } }