int gmx_dielectric(int argc,char *argv[]) { const char *desc[] = { "[TT]g_dielectric[tt] calculates frequency dependent dielectric constants", "from the autocorrelation function of the total dipole moment in", "your simulation. This ACF can be generated by [TT]g_dipoles[tt].", "The functional forms of the available functions are:[PAR]", "One parameter: y = Exp[-a1 x],[BR]", "Two parameters: y = a2 Exp[-a1 x],[BR]", "Three parameters: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x].[BR]", "Start values for the fit procedure can be given on the command line.", "It is also possible to fix parameters at their start value, use [TT]-fix[tt]", "with the number of the parameter you want to fix.", "[PAR]", "Three output files are generated, the first contains the ACF,", "an exponential fit to it with 1, 2 or 3 parameters, and the", "numerical derivative of the combination data/fit.", "The second file contains the real and imaginary parts of the", "frequency-dependent dielectric constant, the last gives a plot", "known as the Cole-Cole plot, in which the imaginary", "component is plotted as a function of the real component.", "For a pure exponential relaxation (Debye relaxation) the latter", "plot should be one half of a circle." }; t_filenm fnm[] = { { efXVG, "-f", "dipcorr",ffREAD }, { efXVG, "-d", "deriv", ffWRITE }, { efXVG, "-o", "epsw", ffWRITE }, { efXVG, "-c", "cole", ffWRITE } }; #define NFILE asize(fnm) output_env_t oenv; int i,j,nx,ny,nxtail,eFitFn,nfitparm; real dt,integral,fitintegral,*fitparms,fac,rffac; double **yd; real **y; const char *legend[] = { "Correlation", "Std. Dev.", "Fit", "Combined", "Derivative" }; static int fix=0,bFour = 0,bX = 1,nsmooth=3; static real tendInt=5.0,tbegin=5.0,tend=500.0; static real A=0.5,tau1=10.0,tau2=1.0,eps0=80,epsRF=78.5,tail=500.0; real lambda; t_pargs pa[] = { { "-fft", FALSE, etBOOL, {&bFour}, "use fast fourier transform for correlation function" }, { "-x1", FALSE, etBOOL, {&bX}, "use first column as [IT]x[it]-axis rather than first data set" }, { "-eint", FALSE, etREAL, {&tendInt}, "Time to end the integration of the data and start to use the fit"}, { "-bfit", FALSE, etREAL, {&tbegin}, "Begin time of fit" }, { "-efit", FALSE, etREAL, {&tend}, "End time of fit" }, { "-tail", FALSE, etREAL, {&tail}, "Length of function including data and tail from fit" }, { "-A", FALSE, etREAL, {&A}, "Start value for fit parameter A" }, { "-tau1", FALSE, etREAL, {&tau1}, "Start value for fit parameter [GRK]tau[grk]1" }, { "-tau2", FALSE, etREAL, {&tau2}, "Start value for fit parameter [GRK]tau[grk]2" }, { "-eps0", FALSE, etREAL, {&eps0}, "[GRK]epsilon[grk]0 of your liquid" }, { "-epsRF", FALSE, etREAL, {&epsRF}, "[GRK]epsilon[grk] of the reaction field used in your simulation. A value of 0 means infinity." }, { "-fix", FALSE, etINT, {&fix}, "Fix parameters at their start values, A (2), tau1 (1), or tau2 (4)" }, { "-ffn", FALSE, etENUM, {s_ffn}, "Fit function" }, { "-nsmooth", FALSE, etINT, {&nsmooth}, "Number of points for smoothing" } }; CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); please_cite(stdout,"Spoel98a"); printf("WARNING: non-polarizable models can never yield an infinite\n" "dielectric constant that is different from 1. This is incorrect\n" "in the reference given above (Spoel98a).\n\n"); nx = read_xvg(opt2fn("-f",NFILE,fnm),&yd,&ny); dt = yd[0][1] - yd[0][0]; nxtail = min(tail/dt,nx); printf("Read data set containing %d colums and %d rows\n",ny,nx); printf("Assuming (from data) that timestep is %g, nxtail = %d\n", dt,nxtail); snew(y,6); for(i=0; (i<ny); i++) snew(y[i],max(nx,nxtail)); for(i=0; (i<nx); i++) { y[0][i] = yd[0][i]; for(j=1; (j<ny); j++) y[j][i] = yd[j][i]; } if (nxtail > nx) { for(i=nx; (i<nxtail); i++) { y[0][i] = dt*i+y[0][0]; for(j=1; (j<ny); j++) y[j][i] = 0.0; } nx=nxtail; } /* We have read a file WITHOUT standard deviations, so we make our own... */ if (ny==2) { printf("Creating standard deviation numbers ...\n"); srenew(y,3); snew(y[2],nx); fac=1.0/((real)nx); for(i=0; (i<nx); i++) y[2][i] = fac; } eFitFn = sffn2effn(s_ffn); nfitparm = nfp_ffn[eFitFn]; snew(fitparms,4); fitparms[0]=tau1; if (nfitparm > 1) fitparms[1]=A; if (nfitparm > 2) fitparms[2]=tau2; snew(y[3],nx); snew(y[4],nx); snew(y[5],nx); integral = print_and_integrate(NULL,calc_nbegin(nx,y[0],tbegin), dt,y[1],NULL,1); integral += do_lmfit(nx,y[1],y[2],dt,y[0],tbegin,tend, oenv,TRUE,eFitFn,fitparms,fix); for(i=0; i<nx; i++) y[3][i] = fit_function(eFitFn,fitparms,y[0][i]); if (epsRF == 0) { /* This means infinity! */ lambda = 0; rffac = 1; } else { lambda = (eps0 - 1.0)/(2*epsRF - 1.0); rffac = (2*epsRF+eps0)/(2*epsRF+1); } printf("DATA INTEGRAL: %5.1f, tauD(old) = %5.1f ps, " "tau_slope = %5.1f, tau_slope,D = %5.1f ps\n", integral,integral*rffac,fitparms[0],fitparms[0]*rffac); printf("tau_D from tau1 = %8.3g , eps(Infty) = %8.3f\n", fitparms[0]*(1 + fitparms[1]*lambda), 1 + ((1 - fitparms[1])*(eps0 - 1))/(1 + fitparms[1]*lambda)); fitintegral=numerical_deriv(nx,y[0],y[1],y[3],y[4],y[5],tendInt,nsmooth); printf("FIT INTEGRAL (tau_M): %5.1f, tau_D = %5.1f\n", fitintegral,fitintegral*rffac); /* Now we have the negative gradient of <Phi(0) Phi(t)> */ write_xvg(opt2fn("-d",NFILE,fnm),"Data",nx-1,6,y,legend,oenv); /* Do FFT and analysis */ do_four(opt2fn("-o",NFILE,fnm),opt2fn("-c",NFILE,fnm), nx-1,y[0],y[5],eps0,epsRF,oenv); do_view(oenv,opt2fn("-o",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-c",NFILE,fnm),NULL); do_view(oenv,opt2fn("-d",NFILE,fnm),"-nxy"); thanx(stderr); return 0; }
void atoms2md(gmx_mtop_t *mtop, t_inputrec *ir, int nindex, int *index, int start, int homenr, t_mdatoms *md) { gmx_mtop_atomlookup_t alook; int i; t_grpopts *opts; real c6, c12; gmx_groups_t *groups; gmx_molblock_t *molblock; opts = &ir->opts; groups = &mtop->groups; molblock = mtop->molblock; /* Index==NULL indicates particle decomposition, * unless we have an empty DD node, so also check for homenr and start. * This should be signaled properly with an extra parameter or nindex==-1. */ if (index == NULL && (homenr > 0 || start > 0)) { md->nr = mtop->natoms; } else { md->nr = nindex; } if (md->nr > md->nalloc) { md->nalloc = over_alloc_dd(md->nr); if (md->nMassPerturbed) { srenew(md->massA, md->nalloc); srenew(md->massB, md->nalloc); } srenew(md->massT, md->nalloc); srenew(md->invmass, md->nalloc); srenew(md->chargeA, md->nalloc); srenew(md->c6A, md->nalloc); srenew(md->sigmaA, md->nalloc); srenew(md->sigma3A, md->nalloc); if (md->nPerturbed) { srenew(md->chargeB, md->nalloc); srenew(md->c6B, md->nalloc); srenew(md->sigmaB, md->nalloc); srenew(md->sigma3B, md->nalloc); } srenew(md->typeA, md->nalloc); if (md->nPerturbed) { srenew(md->typeB, md->nalloc); } srenew(md->ptype, md->nalloc); if (opts->ngtc > 1) { srenew(md->cTC, md->nalloc); /* We always copy cTC with domain decomposition */ } srenew(md->cENER, md->nalloc); if (opts->ngacc > 1) { srenew(md->cACC, md->nalloc); } if (opts->nFreeze && (opts->ngfrz > 1 || opts->nFreeze[0][XX] || opts->nFreeze[0][YY] || opts->nFreeze[0][ZZ])) { srenew(md->cFREEZE, md->nalloc); } if (md->bVCMgrps) { srenew(md->cVCM, md->nalloc); } if (md->bOrires) { srenew(md->cORF, md->nalloc); } if (md->nPerturbed) { srenew(md->bPerturbed, md->nalloc); } /* Note that these user t_mdatoms array pointers are NULL * when there is only one group present. * Therefore, when adding code, the user should use something like: * gprnrU1 = (md->cU1==NULL ? 0 : md->cU1[localatindex]) */ if (mtop->groups.grpnr[egcUser1] != NULL) { srenew(md->cU1, md->nalloc); } if (mtop->groups.grpnr[egcUser2] != NULL) { srenew(md->cU2, md->nalloc); } if (ir->bQMMM) { srenew(md->bQM, md->nalloc); } if (ir->bAdress) { srenew(md->wf, md->nalloc); srenew(md->tf_table_index, md->nalloc); } } alook = gmx_mtop_atomlookup_init(mtop); #pragma omp parallel for num_threads(gmx_omp_nthreads_get(emntDefault)) schedule(static) for (i = 0; i < md->nr; i++) { int g, ag, molb; real mA, mB, fac; t_atom *atom; if (index == NULL) { ag = i; } else { ag = index[i]; } gmx_mtop_atomnr_to_atom(alook, ag, &atom); if (md->cFREEZE) { md->cFREEZE[i] = ggrpnr(groups, egcFREEZE, ag); } if (EI_ENERGY_MINIMIZATION(ir->eI)) { /* Displacement is proportional to F, masses used for constraints */ mA = 1.0; mB = 1.0; } else if (ir->eI == eiBD) { /* With BD the physical masses are irrelevant. * To keep the code simple we use most of the normal MD code path * for BD. Thus for constraining the masses should be proportional * to the friction coefficient. We set the absolute value such that * m/2<(dx/dt)^2> = m/2*2kT/fric*dt = kT/2 => m=fric*dt/2 * Then if we set the (meaningless) velocity to v=dx/dt, we get the * correct kinetic energy and temperature using the usual code path. * Thus with BD v*dt will give the displacement and the reported * temperature can signal bad integration (too large time step). */ if (ir->bd_fric > 0) { mA = 0.5*ir->bd_fric*ir->delta_t; mB = 0.5*ir->bd_fric*ir->delta_t; } else { /* The friction coefficient is mass/tau_t */ fac = ir->delta_t/opts->tau_t[md->cTC ? groups->grpnr[egcTC][ag] : 0]; mA = 0.5*atom->m*fac; mB = 0.5*atom->mB*fac; } } else { mA = atom->m; mB = atom->mB; } if (md->nMassPerturbed) { md->massA[i] = mA; md->massB[i] = mB; } md->massT[i] = mA; if (mA == 0.0) { md->invmass[i] = 0; } else if (md->cFREEZE) { g = md->cFREEZE[i]; if (opts->nFreeze[g][XX] && opts->nFreeze[g][YY] && opts->nFreeze[g][ZZ]) { /* Set the mass of completely frozen particles to ALMOST_ZERO iso 0 * to avoid div by zero in lincs or shake. * Note that constraints can still move a partially frozen particle. */ md->invmass[i] = ALMOST_ZERO; } else { md->invmass[i] = 1.0/mA; } } else { md->invmass[i] = 1.0/mA; } md->chargeA[i] = atom->q; md->typeA[i] = atom->type; c6 = mtop->ffparams.iparams[atom->type*(mtop->ffparams.atnr+1)].lj.c6; c12 = mtop->ffparams.iparams[atom->type*(mtop->ffparams.atnr+1)].lj.c12; md->c6A[i] = sqrt(c6); if (c6 == 0.0 || c12 == 0.0) { md->sigmaA[i] = 1.0; } else { md->sigmaA[i] = pow(c12/c6, 1.0/6.0); } md->sigma3A[i] = 1/(md->sigmaA[i]*md->sigmaA[i]*md->sigmaA[i]); if (md->nPerturbed) { md->chargeB[i] = atom->qB; md->typeB[i] = atom->typeB; c6 = mtop->ffparams.iparams[atom->typeB*(mtop->ffparams.atnr+1)].lj.c6; c12 = mtop->ffparams.iparams[atom->typeB*(mtop->ffparams.atnr+1)].lj.c12; md->c6B[i] = sqrt(c6); if (c6 == 0.0 || c12 == 0.0) { md->sigmaB[i] = 1.0; } else { md->sigmaB[i] = pow(c12/c6, 1.0/6.0); } md->bPerturbed[i] = PERTURBED(*atom); md->sigma3B[i] = 1/(md->sigmaB[i]*md->sigmaB[i]*md->sigmaB[i]); } md->ptype[i] = atom->ptype; if (md->cTC) { md->cTC[i] = groups->grpnr[egcTC][ag]; } md->cENER[i] = (groups->grpnr[egcENER] ? groups->grpnr[egcENER][ag] : 0); if (md->cACC) { md->cACC[i] = groups->grpnr[egcACC][ag]; } if (md->cVCM) { md->cVCM[i] = groups->grpnr[egcVCM][ag]; } if (md->cORF) { md->cORF[i] = groups->grpnr[egcORFIT][ag]; } if (md->cU1) { md->cU1[i] = groups->grpnr[egcUser1][ag]; } if (md->cU2) { md->cU2[i] = groups->grpnr[egcUser2][ag]; } if (ir->bQMMM) { if (groups->grpnr[egcQMMM] == 0 || groups->grpnr[egcQMMM][ag] < groups->grps[egcQMMM].nr-1) { md->bQM[i] = TRUE; } else { md->bQM[i] = FALSE; } } /* Initialize AdResS weighting functions to adressw */ if (ir->bAdress) { md->wf[i] = 1.0; /* if no tf table groups specified, use default table */ md->tf_table_index[i] = DEFAULT_TF_TABLE; if (ir->adress->n_tf_grps > 0) { /* if tf table groups specified, tf is only applied to thoose energy groups*/ md->tf_table_index[i] = NO_TF_TABLE; /* check wether atom is in one of the relevant energy groups and assign a table index */ for (g = 0; g < ir->adress->n_tf_grps; g++) { if (md->cENER[i] == ir->adress->tf_table_index[g]) { md->tf_table_index[i] = g; } } } } } gmx_mtop_atomlookup_destroy(alook); md->start = start; md->homenr = homenr; md->lambda = 0; }
static void init_lincs(FILE *log,t_topology *top,t_inputrec *ir, t_mdatoms *md,int start,int homenr, int *nrtot, rvec **r,int **bla1,int **bla2,int **blnr,int **blbnb, real **bllen,real **blc,real **blcc,real **blm, real **tmp1,real **tmp2,real **tmp3, real **lincslam,real **bllen0,real **ddist) { t_idef *idef=&(top->idef); t_iatom *iatom; int i,j,k,n,b1,b,cen; int ncons,nZeroLen; int type,a1,a2,b2,nr,n1,n2,nc4; real len=0,len1,sign; real im1,im2; int **at_c,*at_cn,*at_cm; ncons = idef->il[F_SHAKE].nr/3; *nrtot = 0; if (ncons > 0) { iatom=idef->il[F_SHAKE].iatoms; /* Make atom-constraint connection list for temporary use */ snew(at_c,homenr); snew(at_cn,homenr); snew(at_cm,homenr); for(i=0; i<ncons; i++) { a1=iatom[3*i+1]-start; a2=iatom[3*i+2]-start; if (at_cn[a1] >= at_cm[a1]) { at_cm[a1] += 4; srenew(at_c[a1],at_cm[a1]); } at_c[a1][at_cn[a1]] = i; at_cn[a1]++; if (at_cn[a2] >= at_cm[a2]) { at_cm[a2] += 4; srenew(at_c[a2],at_cm[a2]); } at_c[a2][at_cn[a2]] = i; at_cn[a2]++; } sfree(at_cm); for(i=0; i<ncons; i++) { a1=iatom[3*i+1]-start; a2=iatom[3*i+2]-start; *nrtot += at_cn[a1] + at_cn[a2] - 2; } snew(*r,ncons); snew(*bla1,ncons); snew(*bla2,ncons); snew(*blnr,ncons+1); snew(*bllen,ncons); snew(*blc,ncons); snew(*tmp1,ncons); snew(*tmp2,ncons); snew(*tmp3,ncons); snew(*lincslam,ncons); snew(*bllen0,ncons); snew(*ddist,ncons); snew(*blbnb,*nrtot); snew(*blcc,*nrtot); snew(*blm,*nrtot); /* Make constraint-neighbor list */ (*blnr)[0] = 0; nZeroLen = 0; for(i=0; (i<ncons); i++) { j=3*i; a1=iatom[j+1]; a2=iatom[j+2]; /* (*blnr)[i+1] = (*blnr)[i] + at_cn[a1] + at_cn[a2] - 2; */ type=iatom[j]; len =idef->iparams[type].shake.dA; len1=idef->iparams[type].shake.dB; if (( len<GMX_REAL_MIN || len1<GMX_REAL_MIN) && fabs(len1-len)>GMX_REAL_MIN) fatal_error(0,"It is not allowed to have a constraint length " "zero and non-zero in the A and B topology"); if (len < GMX_REAL_MIN) nZeroLen++; (*bla1)[i]=a1; (*bla2)[i]=a2; (*bllen)[i]=len; (*bllen0)[i]=len; (*ddist)[i]=len1-len; im1=md->invmass[a1]; im2=md->invmass[a2]; (*blc)[i]=invsqrt(im1+im2); /* Construct the constraint connection matrix blbnb */ (*blnr)[i+1]=(*blnr)[i]; for(k=0; k<at_cn[a1-start]; k++) if (at_c[a1-start][k] != i) (*blbnb)[((*blnr)[i+1])++]=at_c[a1-start][k]; for(k=0; k<at_cn[a2-start]; k++) if (at_c[a2-start][k] != i) (*blbnb)[((*blnr)[i+1])++]=at_c[a2-start][k]; /* Order the blbnb matrix to optimize memory access */ qsort(&((*blbnb)[(*blnr)[i]]),(*blnr)[i+1]-(*blnr)[i], sizeof((*blbnb)[0]),int_comp); } sfree(at_cn); for(i=0; i<homenr; i++) sfree(at_c[i]); sfree(at_c); if(log) { fprintf(log,"\nInitializing LINear Constraint Solver\n"); fprintf(log," number of constraints is %d\n",ncons); fprintf(log," average number of constraints coupled to one constraint is %.1f\n", (real)(*nrtot)/ncons); if (nZeroLen) fprintf(log," found %d constraints with zero length\n",nZeroLen); fprintf(log,"\n"); fflush(log); } /* Construct the coupling coefficient matrix blcc */ for(b=0; (b<ncons); b++) { i=(*bla1)[b]; j=(*bla2)[b]; for(n=(*blnr)[b]; (n<(*blnr)[b+1]);n++) { k = (*blbnb)[n]; if (i==(*bla1)[k] || j==(*bla2)[k]) sign=-1; else sign=1; if (i==(*bla1)[k] || i==(*bla2)[k]) cen=i; else cen=j; (*blcc)[n]=sign*md->invmass[cen]*(*blc)[b]*(*blc)[k]; } } #ifdef DEBUG for(i=0; i<ncons; i++) { fprintf(log,"%d %d %d %g %g %d\n",i,(*bla1)[i],(*bla2)[i], (*bllen)[i],(*blc)[i],(*blnr)[i+1]-(*blnr)[i]); for(n=(*blnr)[i]; (n<(*blnr)[i+1]);n++) { k = (*blbnb)[n]; fprintf(log," %d %g\n",k,(*blcc)[n]); } } #endif } }
void read_resall(char *rrdb, int *nrtpptr, t_restp **rtp, gpp_atomtype_t atype, t_symtab *tab, gmx_bool bAllowOverrideRTP) { FILE *in; char filebase[STRLEN], line[STRLEN], header[STRLEN]; int i, nrtp, maxrtp, bt, nparam; int dum1, dum2, dum3; t_restp *rrtp, *header_settings; gmx_bool bNextResidue, bError; int firstrtp; fflib_filename_base(rrdb, filebase, STRLEN); in = fflib_open(rrdb); if (debug) { fprintf(debug, "%9s %5s", "Residue", "atoms"); for (i = 0; i < ebtsNR; i++) { fprintf(debug, " %10s", btsNames[i]); } fprintf(debug, "\n"); } snew(header_settings, 1); /* these bonded parameters will overwritten be when * * there is a [ bondedtypes ] entry in the .rtp file */ header_settings->rb[ebtsBONDS].type = 1; /* normal bonds */ header_settings->rb[ebtsANGLES].type = 1; /* normal angles */ header_settings->rb[ebtsPDIHS].type = 1; /* normal dihedrals */ header_settings->rb[ebtsIDIHS].type = 2; /* normal impropers */ header_settings->rb[ebtsEXCLS].type = 1; /* normal exclusions */ header_settings->rb[ebtsCMAP].type = 1; /* normal cmap torsions */ header_settings->bKeepAllGeneratedDihedrals = FALSE; header_settings->nrexcl = 3; header_settings->bGenerateHH14Interactions = TRUE; header_settings->bRemoveDihedralIfWithImproper = TRUE; /* Column 5 & 6 aren't really bonded types, but we include * them here to avoid introducing a new section: * Column 5 : This controls the generation of dihedrals from the bonding. * All possible dihedrals are generated automatically. A value of * 1 here means that all these are retained. A value of * 0 here requires generated dihedrals be removed if * * there are any dihedrals on the same central atoms * specified in the residue topology, or * * there are other identical generated dihedrals * sharing the same central atoms, or * * there are other generated dihedrals sharing the * same central bond that have fewer hydrogen atoms * Column 6: Number of bonded neighbors to exclude. * Column 7: Generate 1,4 interactions between two hydrogen atoms * Column 8: Remove proper dihedrals if centered on the same bond * as an improper dihedral */ get_a_line(in, line, STRLEN); if (!get_header(line, header)) { gmx_fatal(FARGS, "in .rtp file at line:\n%s\n", line); } if (gmx_strncasecmp("bondedtypes", header, 5) == 0) { get_a_line(in, line, STRLEN); if ((nparam = sscanf(line, "%d %d %d %d %d %d %d %d", &header_settings->rb[ebtsBONDS].type, &header_settings->rb[ebtsANGLES].type, &header_settings->rb[ebtsPDIHS].type, &header_settings->rb[ebtsIDIHS].type, &dum1, &header_settings->nrexcl, &dum2, &dum3)) < 4) { gmx_fatal(FARGS, "need 4 to 8 parameters in the header of .rtp file %s at line:\n%s\n", rrdb, line); } header_settings->bKeepAllGeneratedDihedrals = (dum1 != 0); header_settings->bGenerateHH14Interactions = (dum2 != 0); header_settings->bRemoveDihedralIfWithImproper = (dum3 != 0); get_a_line(in, line, STRLEN); if (nparam < 5) { fprintf(stderr, "Using default: not generating all possible dihedrals\n"); header_settings->bKeepAllGeneratedDihedrals = FALSE; } if (nparam < 6) { fprintf(stderr, "Using default: excluding 3 bonded neighbors\n"); header_settings->nrexcl = 3; } if (nparam < 7) { fprintf(stderr, "Using default: generating 1,4 H--H interactions\n"); header_settings->bGenerateHH14Interactions = TRUE; } if (nparam < 8) { fprintf(stderr, "Using default: removing proper dihedrals found on the same bond as a proper dihedral\n"); header_settings->bRemoveDihedralIfWithImproper = TRUE; } } else { fprintf(stderr, "Reading .rtp file without '[ bondedtypes ]' directive,\n" "Will proceed as if the entry was:\n"); print_resall_header(stderr, header_settings); } /* We don't know the current size of rrtp, but simply realloc immediately */ nrtp = *nrtpptr; rrtp = *rtp; maxrtp = nrtp; while (!feof(in)) { if (nrtp >= maxrtp) { maxrtp += 100; srenew(rrtp, maxrtp); } /* Initialise rtp entry structure */ rrtp[nrtp] = *header_settings; if (!get_header(line, header)) { gmx_fatal(FARGS, "in .rtp file at line:\n%s\n", line); } rrtp[nrtp].resname = gmx_strdup(header); rrtp[nrtp].filebase = gmx_strdup(filebase); get_a_line(in, line, STRLEN); bError = FALSE; bNextResidue = FALSE; do { if (!get_header(line, header)) { bError = TRUE; } else { bt = get_bt(header); if (bt != NOTSET) { /* header is an bonded directive */ bError = !read_bondeds(bt, in, line, &rrtp[nrtp]); } else if (gmx_strncasecmp("atoms", header, 5) == 0) { /* header is the atoms directive */ bError = !read_atoms(in, line, &(rrtp[nrtp]), tab, atype); } else { /* else header must be a residue name */ bNextResidue = TRUE; } } if (bError) { gmx_fatal(FARGS, "in .rtp file in residue %s at line:\n%s\n", rrtp[nrtp].resname, line); } } while (!feof(in) && !bNextResidue); if (rrtp[nrtp].natom == 0) { gmx_fatal(FARGS, "No atoms found in .rtp file in residue %s\n", rrtp[nrtp].resname); } if (debug) { fprintf(debug, "%3d %5s %5d", nrtp+1, rrtp[nrtp].resname, rrtp[nrtp].natom); for (i = 0; i < ebtsNR; i++) { fprintf(debug, " %10d", rrtp[nrtp].rb[i].nb); } fprintf(debug, "\n"); } firstrtp = -1; for (i = 0; i < nrtp; i++) { if (gmx_strcasecmp(rrtp[i].resname, rrtp[nrtp].resname) == 0) { firstrtp = i; } } if (firstrtp == -1) { nrtp++; fprintf(stderr, "\rResidue %d", nrtp); } else { if (firstrtp >= *nrtpptr) { gmx_fatal(FARGS, "Found a second entry for '%s' in '%s'", rrtp[nrtp].resname, rrdb); } if (bAllowOverrideRTP) { fprintf(stderr, "\n"); fprintf(stderr, "Found another rtp entry for '%s' in '%s', ignoring this entry and keeping the one from '%s.rtp'\n", rrtp[nrtp].resname, rrdb, rrtp[firstrtp].filebase); /* We should free all the data for this entry. * The current code gives a lot of dangling pointers. */ clear_t_restp(&rrtp[nrtp]); } else { gmx_fatal(FARGS, "Found rtp entries for '%s' in both '%s' and '%s'. If you want the first definition to override the second one, set the -rtpo option of pdb2gmx.", rrtp[nrtp].resname, rrtp[firstrtp].filebase, rrdb); } } } gmx_ffclose(in); /* give back unused memory */ srenew(rrtp, nrtp); fprintf(stderr, "\nSorting it all out...\n"); qsort(rrtp, nrtp, (size_t)sizeof(rrtp[0]), comprtp); check_rtp(nrtp, rrtp, rrdb); *nrtpptr = nrtp; *rtp = rrtp; }
static void dielectric(FILE *fmj, FILE *fmd, FILE *outf, FILE *fcur, FILE *mcor, FILE *fmjdsp, gmx_bool bNoJump, gmx_bool bACF, gmx_bool bINT, int ePBC, t_topology top, t_trxframe fr, real temp, real bfit, real efit, real bvit, real evit, t_trxstatus *status, int isize, int nmols, int nshift, int *index0, int indexm[], real mass2[], real qmol[], real eps_rf, const gmx_output_env_t *oenv) { int i, j; int valloc, nalloc, nfr, nvfr; int vshfr; real *xshfr = NULL; int *vfr = NULL; real refr = 0.0; real *cacf = NULL; real *time = NULL; real *djc = NULL; real corint = 0.0; real prefactorav = 0.0; real prefactor = 0.0; real volume; real volume_av = 0.0; real dk_s, dk_d, dk_f; real mj = 0.0; real mj2 = 0.0; real mjd = 0.0; real mjdav = 0.0; real md2 = 0.0; real mdav2 = 0.0; real sgk; rvec mja_tmp; rvec mjd_tmp; rvec mdvec; rvec *mu = NULL; rvec *xp = NULL; rvec *v0 = NULL; rvec *mjdsp = NULL; real *dsp2 = NULL; real t0; real rtmp; rvec tmp; rvec *mtrans = NULL; /* * Variables for the least-squares fit for Einstein-Helfand and Green-Kubo */ int bi, ei, ie, ii; real rest = 0.0; real sigma = 0.0; real malt = 0.0; real err = 0.0; real *xfit; real *yfit; gmx_rmpbc_t gpbc = NULL; /* * indices for EH */ ei = 0; bi = 0; /* * indices for GK */ ii = 0; ie = 0; t0 = 0; sgk = 0.0; /* This is the main loop over frames */ nfr = 0; nvfr = 0; vshfr = 0; nalloc = 0; valloc = 0; clear_rvec(mja_tmp); clear_rvec(mjd_tmp); clear_rvec(mdvec); clear_rvec(tmp); gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms); do { refr = (nfr+1); if (nfr >= nalloc) { nalloc += 100; srenew(time, nalloc); srenew(mu, nalloc); srenew(mjdsp, nalloc); srenew(dsp2, nalloc); srenew(mtrans, nalloc); srenew(xshfr, nalloc); for (i = nfr; i < nalloc; i++) { clear_rvec(mjdsp[i]); clear_rvec(mu[i]); clear_rvec(mtrans[i]); dsp2[i] = 0.0; xshfr[i] = 0.0; } } GMX_RELEASE_ASSERT(time != NULL, "Memory not allocated correctly - time array is NULL"); if (nfr == 0) { t0 = fr.time; } time[nfr] = fr.time-t0; if (time[nfr] <= bfit) { bi = nfr; } if (time[nfr] <= efit) { ei = nfr; } if (bNoJump) { if (xp) { remove_jump(fr.box, fr.natoms, xp, fr.x); } else { snew(xp, fr.natoms); } for (i = 0; i < fr.natoms; i++) { copy_rvec(fr.x[i], xp[i]); } } gmx_rmpbc_trxfr(gpbc, &fr); calc_mj(top, ePBC, fr.box, bNoJump, nmols, indexm, fr.x, mtrans[nfr], mass2, qmol); for (i = 0; i < isize; i++) { j = index0[i]; svmul(top.atoms.atom[j].q, fr.x[j], fr.x[j]); rvec_inc(mu[nfr], fr.x[j]); } /*if(mod(nfr,nshift)==0){*/ if (nfr%nshift == 0) { for (j = nfr; j >= 0; j--) { rvec_sub(mtrans[nfr], mtrans[j], tmp); dsp2[nfr-j] += norm2(tmp); xshfr[nfr-j] += 1.0; } } if (fr.bV) { if (nvfr >= valloc) { valloc += 100; srenew(vfr, valloc); if (bINT) { srenew(djc, valloc); } srenew(v0, valloc); if (bACF) { srenew(cacf, valloc); } } if (time[nfr] <= bvit) { ii = nvfr; } if (time[nfr] <= evit) { ie = nvfr; } vfr[nvfr] = nfr; clear_rvec(v0[nvfr]); if (bACF) { cacf[nvfr] = 0.0; } if (bINT) { djc[nvfr] = 0.0; } for (i = 0; i < isize; i++) { j = index0[i]; svmul(mass2[j], fr.v[j], fr.v[j]); svmul(qmol[j], fr.v[j], fr.v[j]); rvec_inc(v0[nvfr], fr.v[j]); } fprintf(fcur, "%.3f\t%.6f\t%.6f\t%.6f\n", time[nfr], v0[nfr][XX], v0[nfr][YY], v0[nfr][ZZ]); if (bACF || bINT) { /*if(mod(nvfr,nshift)==0){*/ if (nvfr%nshift == 0) { for (j = nvfr; j >= 0; j--) { if (bACF) { cacf[nvfr-j] += iprod(v0[nvfr], v0[j]); } if (bINT) { djc[nvfr-j] += iprod(mu[vfr[j]], v0[nvfr]); } } vshfr++; } } nvfr++; } volume = det(fr.box); volume_av += volume; rvec_inc(mja_tmp, mtrans[nfr]); mjd += iprod(mu[nfr], mtrans[nfr]); rvec_inc(mdvec, mu[nfr]); mj2 += iprod(mtrans[nfr], mtrans[nfr]); md2 += iprod(mu[nfr], mu[nfr]); fprintf(fmj, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n", time[nfr], mtrans[nfr][XX], mtrans[nfr][YY], mtrans[nfr][ZZ], mj2/refr, norm(mja_tmp)/refr); fprintf(fmd, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n", \ time[nfr], mu[nfr][XX], mu[nfr][YY], mu[nfr][ZZ], md2/refr, norm(mdvec)/refr); nfr++; } while (read_next_frame(oenv, status, &fr)); gmx_rmpbc_done(gpbc); volume_av /= refr; prefactor = 1.0; prefactor /= 3.0*EPSILON0*volume_av*BOLTZ*temp; prefactorav = E_CHARGE*E_CHARGE; prefactorav /= volume_av*BOLTZMANN*temp*NANO*6.0; fprintf(stderr, "Prefactor fit E-H: 1 / 6.0*V*k_B*T: %g\n", prefactorav); calc_mjdsp(fmjdsp, prefactorav, dsp2, time, nfr, xshfr); /* * Now we can average and calculate the correlation functions */ mj2 /= refr; mjd /= refr; md2 /= refr; svmul(1.0/refr, mdvec, mdvec); svmul(1.0/refr, mja_tmp, mja_tmp); mdav2 = norm2(mdvec); mj = norm2(mja_tmp); mjdav = iprod(mdvec, mja_tmp); printf("\n\nAverage translational dipole moment M_J [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mja_tmp[XX], mja_tmp[YY], mja_tmp[ZZ], mj2); printf("\n\nAverage molecular dipole moment M_D [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mdvec[XX], mdvec[YY], mdvec[ZZ], md2); if (v0 != NULL) { if (bINT) { printf("\nCalculating M_D - current correlation integral ... \n"); corint = calc_cacf(mcor, prefactorav/EPSI0, djc, time, nvfr, vfr, ie, nshift); } if (bACF) { printf("\nCalculating current autocorrelation ... \n"); sgk = calc_cacf(outf, prefactorav/PICO, cacf, time, nvfr, vfr, ie, nshift); if (ie > ii) { snew(xfit, ie-ii+1); snew(yfit, ie-ii+1); for (i = ii; i <= ie; i++) { xfit[i-ii] = std::log(time[vfr[i]]); rtmp = std::abs(cacf[i]); yfit[i-ii] = std::log(rtmp); } lsq_y_ax_b(ie-ii, xfit, yfit, &sigma, &malt, &err, &rest); malt = std::exp(malt); sigma += 1.0; malt *= prefactorav*2.0e12/sigma; sfree(xfit); sfree(yfit); } } } /* Calculation of the dielectric constant */ fprintf(stderr, "\n********************************************\n"); dk_s = calceps(prefactor, md2, mj2, mjd, eps_rf, FALSE); fprintf(stderr, "\nAbsolute values:\n epsilon=%f\n", dk_s); fprintf(stderr, " <M_D^2> , <M_J^2>, <(M_J*M_D)^2>: (%f, %f, %f)\n\n", md2, mj2, mjd); fprintf(stderr, "********************************************\n"); dk_f = calceps(prefactor, md2-mdav2, mj2-mj, mjd-mjdav, eps_rf, FALSE); fprintf(stderr, "\n\nFluctuations:\n epsilon=%f\n\n", dk_f); fprintf(stderr, "\n deltaM_D , deltaM_J, deltaM_JD: (%f, %f, %f)\n", md2-mdav2, mj2-mj, mjd-mjdav); fprintf(stderr, "\n********************************************\n"); if (bINT) { dk_d = calceps(prefactor, md2-mdav2, mj2-mj, corint, eps_rf, TRUE); fprintf(stderr, "\nStatic dielectric constant using integral and fluctuations: %f\n", dk_d); fprintf(stderr, "\n < M_JM_D > via integral: %.3f\n", -1.0*corint); } fprintf(stderr, "\n***************************************************"); fprintf(stderr, "\n\nAverage volume V=%f nm^3 at T=%f K\n", volume_av, temp); fprintf(stderr, "and corresponding refactor 1.0 / 3.0*V*k_B*T*EPSILON_0: %f \n", prefactor); if (bACF && (ii < nvfr)) { fprintf(stderr, "Integral and integrated fit to the current acf yields at t=%f:\n", time[vfr[ii]]); fprintf(stderr, "sigma=%8.3f (pure integral: %.3f)\n", sgk-malt*std::pow(time[vfr[ii]], sigma), sgk); } if (ei > bi) { fprintf(stderr, "\nStart fit at %f ps (%f).\n", time[bi], bfit); fprintf(stderr, "End fit at %f ps (%f).\n\n", time[ei], efit); snew(xfit, ei-bi+1); snew(yfit, ei-bi+1); for (i = bi; i <= ei; i++) { xfit[i-bi] = time[i]; yfit[i-bi] = dsp2[i]; } lsq_y_ax_b(ei-bi, xfit, yfit, &sigma, &malt, &err, &rest); sigma *= 1e12; dk_d = calceps(prefactor, md2, 0.5*malt/prefactorav, corint, eps_rf, TRUE); fprintf(stderr, "Einstein-Helfand fit to the MSD of the translational dipole moment yields:\n\n"); fprintf(stderr, "sigma=%.4f\n", sigma); fprintf(stderr, "translational fraction of M^2: %.4f\n", 0.5*malt/prefactorav); fprintf(stderr, "Dielectric constant using EH: %.4f\n", dk_d); sfree(xfit); sfree(yfit); } else { fprintf(stderr, "Too few points for a fit.\n"); } if (v0 != NULL) { sfree(v0); } if (bACF) { sfree(cacf); } if (bINT) { sfree(djc); } sfree(time); sfree(mjdsp); sfree(mu); }
char *wrap_lines(char *buf,int line_width, int indent) { char *b2; int i,i0,i2,j,b2len,lspace=0,l2space=0; bool bFirst,bFitsOnLine; /* characters are copied from buf to b2 with possible spaces changed * into newlines and extra space added for indentation. * i indexes buf (source buffer) and i2 indexes b2 (destination buffer) * i0 points to the beginning of the current line (in buf, source) * lspace and l2space point to the last space on the current line * bFirst is set to prevent indentation of first line * bFitsOnLine says if the first space occurred before line_width, if * that is not the case, we have a word longer than line_width which * will also not fit on the next line, so we might as well keep it on * the current line (where it also won't fit, but looks better) */ b2=NULL; b2len=strlen(buf)+1; snew(b2,b2len); i0=0; i2=0; bFirst=TRUE; do { l2space = -1; /* find the last space before end of line */ for(i=i0; ((i-i0 < line_width) || (l2space==-1)) && (buf[i]); i++) { b2[i2++] = buf[i]; /* remember the position of a space */ if (buf[i] == ' ') { lspace = i; l2space = i2-1; } /* if we have a newline before the line is full, reset counters */ if (buf[i]=='\n' && buf[i+1]) { i0=i+1; b2len+=indent; srenew(b2, b2len); /* add indentation after the newline */ for(j=0; (j<indent); j++) b2[i2++]=' '; } } /* check if one word does not fit on the line */ bFitsOnLine = (i-i0 <= line_width); /* if we're not at the end of the string */ if (buf[i]) { /* reset line counters to just after the space */ i0 = lspace+1; i2 = l2space+1; /* if the words fit on the line, and we're beyond the indentation part */ if ( (bFitsOnLine) && (l2space >= indent) ) { /* start a new line */ b2[l2space] = '\n'; /* and add indentation */ if (indent) { if (bFirst) { line_width-=indent; bFirst=FALSE; } b2len+=indent; srenew(b2, b2len); for(j=0; (j<indent); j++) b2[i2++]=' '; /* no extra spaces after indent; */ while(buf[i0]==' ') i0++; } } } } while (buf[i]); b2[i2] = '\0'; return b2; }
static void strip_dssp(char *dsspfile,int nres, bool bPhobres[],real t, real *acc,FILE *fTArea, t_matrix *mat,int average_area[]) { static bool bFirst=TRUE; static char *ssbuf; FILE *tapeout; static int xsize,frame; char buf[STRLEN+1]; char SSTP; int i,nr,iacc; real iaccf,iaccb; t_xpmelmt c; tapeout=ffopen(dsspfile,"r"); /* Skip header */ do { fgets2(buf,STRLEN,tapeout); } while (strstr(buf,"KAPPA") == NULL); if (bFirst) { snew(ssbuf,nres+10); } iaccb=iaccf=0; for(nr=0; (fgets2(buf,STRLEN,tapeout) != NULL); nr++) { SSTP=buf[16]==' ' ? '~' : buf[16]; ssbuf[nr]=SSTP; buf[39]='\0'; sscanf(&(buf[34]),"%d",&iacc); acc[nr]=iacc; average_area[nr]+=iacc; if (bPhobres[nr]) iaccb+=iacc; else iaccf+=iacc; } ssbuf[nr]='\0'; if (bFirst) { sprintf(mat->title,"Secondary structure"); mat->legend[0]=0; sprintf(mat->label_x,"%s",time_label()); sprintf(mat->label_y,"Residue"); mat->bDiscrete=TRUE; mat->ny=nr; snew(mat->axis_y,nr); for(i=0; i<nr; i++) mat->axis_y[i]=i+1; mat->axis_x=NULL; mat->matrix=NULL; xsize=0; frame=0; bFirst=FALSE; } if (frame>=xsize) { xsize+=10; srenew(mat->axis_x,xsize); srenew(mat->matrix,xsize); } mat->axis_x[frame]=t; snew(mat->matrix[frame],nr); c.c2=0; for(i=0; i<nr; i++) { c.c1=ssbuf[i]; mat->matrix[frame][i] = max(0,searchcmap(mat->nmap,mat->map,c)); } frame++; mat->nx=frame; if (fTArea) fprintf(fTArea,"%10g %10g %10g\n",t,0.01*iaccb,0.01*iaccf); fclose(tapeout); }
/*! \brief Looks up SETTLE constraints for a range of charge-groups */ static void atoms_to_settles(gmx_domdec_t *dd, const gmx_mtop_t *mtop, const int *cginfo, const int **at2settle_mt, int cg_start, int cg_end, t_ilist *ils_local, ind_req_t *ireq) { gmx_ga2la_t *ga2la; gmx_mtop_atomlookup_t alook; int settle; int nral, sa; int cg, a, a_gl, a_glsa, a_gls[3], a_locs[3]; int mb, molnr, a_mol, offset; const gmx_molblock_t *molb; const t_iatom *ia1; gmx_bool a_home[3]; int nlocal; gmx_bool bAssign; ga2la = dd->ga2la; alook = gmx_mtop_atomlookup_settle_init(mtop); nral = NRAL(F_SETTLE); for (cg = cg_start; cg < cg_end; cg++) { if (GET_CGINFO_SETTLE(cginfo[cg])) { for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++) { a_gl = dd->gatindex[a]; gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol); molb = &mtop->molblock[mb]; settle = at2settle_mt[molb->type][a_mol]; if (settle >= 0) { offset = a_gl - a_mol; ia1 = mtop->moltype[molb->type].ilist[F_SETTLE].iatoms; bAssign = FALSE; nlocal = 0; for (sa = 0; sa < nral; sa++) { a_glsa = offset + ia1[settle*(1+nral)+1+sa]; a_gls[sa] = a_glsa; a_home[sa] = ga2la_get_home(ga2la, a_glsa, &a_locs[sa]); if (a_home[sa]) { if (nlocal == 0 && a_gl == a_glsa) { bAssign = TRUE; } nlocal++; } } if (bAssign) { if (ils_local->nr+1+nral > ils_local->nalloc) { ils_local->nalloc = over_alloc_dd(ils_local->nr+1+nral); srenew(ils_local->iatoms, ils_local->nalloc); } ils_local->iatoms[ils_local->nr++] = ia1[settle*4]; for (sa = 0; sa < nral; sa++) { if (ga2la_get_home(ga2la, a_gls[sa], &a_locs[sa])) { ils_local->iatoms[ils_local->nr++] = a_locs[sa]; } else { ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1; /* Add this non-home atom to the list */ if (ireq->n+1 > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+1); srenew(ireq->ind, ireq->nalloc); } ireq->ind[ireq->n++] = a_gls[sa]; /* A check on double atom requests is * not required for settle. */ } } } } } } } gmx_mtop_atomlookup_destroy(alook); }
/*! \brief Looks up constraint for the local atoms */ static void atoms_to_constraints(gmx_domdec_t *dd, const gmx_mtop_t *mtop, const int *cginfo, const t_blocka *at2con_mt, int nrec, t_ilist *ilc_local, ind_req_t *ireq) { const t_blocka *at2con; gmx_ga2la_t *ga2la; gmx_mtop_atomlookup_t alook; int ncon1; gmx_molblock_t *molb; t_iatom *ia1, *ia2, *iap; int nhome, cg, a, a_gl, a_mol, a_loc, b_lo, offset, mb, molnr, b_mol, i, con, con_offset; gmx_domdec_constraints_t *dc; gmx_domdec_specat_comm_t *dcc; dc = dd->constraints; dcc = dd->constraint_comm; ga2la = dd->ga2la; alook = gmx_mtop_atomlookup_init(mtop); nhome = 0; for (cg = 0; cg < dd->ncg_home; cg++) { if (GET_CGINFO_CONSTR(cginfo[cg])) { for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++) { a_gl = dd->gatindex[a]; gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol); molb = &mtop->molblock[mb]; ncon1 = mtop->moltype[molb->type].ilist[F_CONSTR].nr/NRAL(F_SETTLE); ia1 = mtop->moltype[molb->type].ilist[F_CONSTR].iatoms; ia2 = mtop->moltype[molb->type].ilist[F_CONSTRNC].iatoms; /* Calculate the global constraint number offset for the molecule. * This is only required for the global index to make sure * that we use each constraint only once. */ con_offset = dc->molb_con_offset[mb] + molnr*dc->molb_ncon_mol[mb]; /* The global atom number offset for this molecule */ offset = a_gl - a_mol; at2con = &at2con_mt[molb->type]; for (i = at2con->index[a_mol]; i < at2con->index[a_mol+1]; i++) { con = at2con->a[i]; iap = constr_iatomptr(ncon1, ia1, ia2, con); if (a_mol == iap[1]) { b_mol = iap[2]; } else { b_mol = iap[1]; } if (ga2la_get_home(ga2la, offset+b_mol, &a_loc)) { /* Add this fully home constraint at the first atom */ if (a_mol < b_mol) { if (dc->ncon+1 > dc->con_nalloc) { dc->con_nalloc = over_alloc_large(dc->ncon+1); srenew(dc->con_gl, dc->con_nalloc); srenew(dc->con_nlocat, dc->con_nalloc); } dc->con_gl[dc->ncon] = con_offset + con; dc->con_nlocat[dc->ncon] = 2; if (ilc_local->nr + 3 > ilc_local->nalloc) { ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3); srenew(ilc_local->iatoms, ilc_local->nalloc); } b_lo = a_loc; ilc_local->iatoms[ilc_local->nr++] = iap[0]; ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a : b_lo); ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a ); dc->ncon++; nhome++; } } else { /* We need the nrec constraints coupled to this constraint, * so we need to walk out of the home cell by nrec+1 atoms, * since already atom bg is not locally present. * Therefore we call walk_out with nrec recursions to go * after this first call. */ walk_out(con, con_offset, b_mol, offset, nrec, ncon1, ia1, ia2, at2con, dd->ga2la, TRUE, dc, dcc, ilc_local, ireq); } } } } } gmx_mtop_atomlookup_destroy(alook); if (debug) { fprintf(debug, "Constraints: home %3d border %3d atoms: %3d\n", nhome, dc->ncon-nhome, dd->constraint_comm ? ireq->n : 0); } }
void connelly_plot(const char *fn,int ndots,real dots[],rvec x[],t_atoms *atoms, t_symtab *symtab,int ePBC,matrix box,gmx_bool bSave) { static const char *atomnm="DOT"; static const char *resnm ="DOT"; static const char *title ="Connely Dot Surface Generated by g_sas"; int i,i0,r0,ii0,k; rvec *xnew; t_atoms aaa; if (bSave) { i0 = atoms->nr; r0 = atoms->nres; srenew(atoms->atom,atoms->nr+ndots); srenew(atoms->atomname,atoms->nr+ndots); srenew(atoms->resinfo,r0+1); atoms->atom[i0].resind = r0; t_atoms_set_resinfo(atoms,i0,symtab,resnm,r0+1,' ',0,' '); srenew(atoms->pdbinfo,atoms->nr+ndots); snew(xnew,atoms->nr+ndots); for(i=0; (i<atoms->nr); i++) copy_rvec(x[i],xnew[i]); for(i=k=0; (i<ndots); i++) { ii0 = i0+i; atoms->atomname[ii0] = put_symtab(symtab,atomnm); atoms->pdbinfo[ii0].type = epdbATOM; atoms->pdbinfo[ii0].atomnr= ii0; atoms->atom[ii0].resind = r0; xnew[ii0][XX] = dots[k++]; xnew[ii0][YY] = dots[k++]; xnew[ii0][ZZ] = dots[k++]; atoms->pdbinfo[ii0].bfac = 0.0; atoms->pdbinfo[ii0].occup = 0.0; } atoms->nr = i0+ndots; atoms->nres = r0+1; write_sto_conf(fn,title,atoms,xnew,NULL,ePBC,box); atoms->nres = r0; atoms->nr = i0; } else { init_t_atoms(&aaa,ndots,TRUE); aaa.atom[0].resind = 0; t_atoms_set_resinfo(&aaa,0,symtab,resnm,1,' ',0,' '); snew(xnew,ndots); for(i=k=0; (i<ndots); i++) { ii0 = i; aaa.atomname[ii0] = put_symtab(symtab,atomnm); aaa.pdbinfo[ii0].type = epdbATOM; aaa.pdbinfo[ii0].atomnr= ii0; aaa.atom[ii0].resind = 0; xnew[ii0][XX] = dots[k++]; xnew[ii0][YY] = dots[k++]; xnew[ii0][ZZ] = dots[k++]; aaa.pdbinfo[ii0].bfac = 0.0; aaa.pdbinfo[ii0].occup = 0.0; } aaa.nr = ndots; write_sto_conf(fn,title,&aaa,xnew,NULL,ePBC,box); do_conect(fn,ndots,xnew); free_t_atoms(&aaa,FALSE); } sfree(xnew); }
/*! \brief Walks over the constraints out from the local atoms into the non-local atoms and adds them to a list */ static void walk_out(int con, int con_offset, int a, int offset, int nrec, int ncon1, const t_iatom *ia1, const t_iatom *ia2, const t_blocka *at2con, const gmx_ga2la_t *ga2la, gmx_bool bHomeConnect, gmx_domdec_constraints_t *dc, gmx_domdec_specat_comm_t *dcc, t_ilist *il_local, ind_req_t *ireq) { int a1_gl, a2_gl, a_loc, i, coni, b; const t_iatom *iap; if (dc->gc_req[con_offset+con] == 0) { /* Add this non-home constraint to the list */ if (dc->ncon+1 > dc->con_nalloc) { dc->con_nalloc = over_alloc_large(dc->ncon+1); srenew(dc->con_gl, dc->con_nalloc); srenew(dc->con_nlocat, dc->con_nalloc); } dc->con_gl[dc->ncon] = con_offset + con; dc->con_nlocat[dc->ncon] = (bHomeConnect ? 1 : 0); dc->gc_req[con_offset+con] = 1; if (il_local->nr + 3 > il_local->nalloc) { il_local->nalloc = over_alloc_dd(il_local->nr+3); srenew(il_local->iatoms, il_local->nalloc); } iap = constr_iatomptr(ncon1, ia1, ia2, con); il_local->iatoms[il_local->nr++] = iap[0]; a1_gl = offset + iap[1]; a2_gl = offset + iap[2]; /* The following indexing code can probably be optizimed */ if (ga2la_get_home(ga2la, a1_gl, &a_loc)) { il_local->iatoms[il_local->nr++] = a_loc; } else { /* We set this index later */ il_local->iatoms[il_local->nr++] = -a1_gl - 1; } if (ga2la_get_home(ga2la, a2_gl, &a_loc)) { il_local->iatoms[il_local->nr++] = a_loc; } else { /* We set this index later */ il_local->iatoms[il_local->nr++] = -a2_gl - 1; } dc->ncon++; } /* Check to not ask for the same atom more than once */ if (gmx_hash_get_minone(dc->ga2la, offset+a) == -1) { assert(dcc); /* Add this non-home atom to the list */ if (ireq->n+1 > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+1); srenew(ireq->ind, ireq->nalloc); } ireq->ind[ireq->n++] = offset + a; /* Temporarily mark with -2, we get the index later */ gmx_hash_set(dc->ga2la, offset+a, -2); } if (nrec > 0) { for (i = at2con->index[a]; i < at2con->index[a+1]; i++) { coni = at2con->a[i]; if (coni != con) { /* Walk further */ iap = constr_iatomptr(ncon1, ia1, ia2, coni); if (a == iap[1]) { b = iap[2]; } else { b = iap[1]; } if (!ga2la_get_home(ga2la, offset+b, &a_loc)) { walk_out(coni, con_offset, b, offset, nrec-1, ncon1, ia1, ia2, at2con, ga2la, FALSE, dc, dcc, il_local, ireq); } } } } }
int gmx_confrms(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the root mean square deviation (RMSD) of two", "structures after least-squares fitting the second structure on the first one.", "The two structures do NOT need to have the same number of atoms,", "only the two index groups used for the fit need to be identical.", "With [TT]-name[tt] only matching atom names from the selected groups", "will be used for the fit and RMSD calculation. This can be useful ", "when comparing mutants of a protein.", "[PAR]", "The superimposed structures are written to file. In a [TT].pdb[tt] file", "the two structures will be written as separate models", "(use [TT]rasmol -nmrpdb[tt]). Also in a [TT].pdb[tt] file, B-factors", "calculated from the atomic MSD values can be written with [TT]-bfac[tt].", }; static gmx_bool bOne = FALSE, bRmpbc = FALSE, bMW = TRUE, bName = FALSE, bBfac = FALSE, bFit = TRUE, bLabel = FALSE; t_pargs pa[] = { { "-one", FALSE, etBOOL, {&bOne}, "Only write the fitted structure to file" }, { "-mw", FALSE, etBOOL, {&bMW}, "Mass-weighted fitting and RMSD" }, { "-pbc", FALSE, etBOOL, {&bRmpbc}, "Try to make molecules whole again" }, { "-fit", FALSE, etBOOL, {&bFit}, "Do least squares superposition of the target structure to the reference" }, { "-name", FALSE, etBOOL, {&bName}, "Only compare matching atom names" }, { "-label", FALSE, etBOOL, {&bLabel}, "Added chain labels A for first and B for second structure"}, { "-bfac", FALSE, etBOOL, {&bBfac}, "Output B-factors from atomic MSD values" } }; t_filenm fnm[] = { { efTPS, "-f1", "conf1.gro", ffREAD }, { efSTX, "-f2", "conf2", ffREAD }, { efSTO, "-o", "fit.pdb", ffWRITE }, { efNDX, "-n1", "fit1", ffOPTRD }, { efNDX, "-n2", "fit2", ffOPTRD }, { efNDX, "-no", "match", ffOPTWR } }; #define NFILE asize(fnm) /* the two structure files */ const char *conf1file, *conf2file, *matchndxfile, *outfile; FILE *fp; char title1[STRLEN], title2[STRLEN], *name1, *name2; t_topology *top1, *top2; int ePBC1, ePBC2; t_atoms *atoms1, *atoms2; int warn = 0; atom_id at; real *w_rls, mass, totmass; rvec *x1, *v1, *x2, *v2, *fit_x; matrix box1, box2; output_env_t oenv; /* counters */ int i, j, m; /* center of mass calculation */ real tmas1, tmas2; rvec xcm1, xcm2; /* variables for fit */ char *groupnames1, *groupnames2; int isize1, isize2; atom_id *index1, *index2; real rms, msd, minmsd, maxmsd; real *msds; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } matchndxfile = opt2fn_null("-no", NFILE, fnm); conf1file = ftp2fn(efTPS, NFILE, fnm); conf2file = ftp2fn(efSTX, NFILE, fnm); /* reading reference structure from first structure file */ fprintf(stderr, "\nReading first structure file\n"); snew(top1, 1); read_tps_conf(conf1file, title1, top1, &ePBC1, &x1, &v1, box1, TRUE); atoms1 = &(top1->atoms); fprintf(stderr, "%s\nContaining %d atoms in %d residues\n", title1, atoms1->nr, atoms1->nres); if (bRmpbc) { rm_gropbc(atoms1, x1, box1); } fprintf(stderr, "Select group from first structure\n"); get_index(atoms1, opt2fn_null("-n1", NFILE, fnm), 1, &isize1, &index1, &groupnames1); printf("\n"); if (bFit && (isize1 < 3)) { gmx_fatal(FARGS, "Need >= 3 points to fit!\n"); } /* reading second structure file */ fprintf(stderr, "\nReading second structure file\n"); snew(top2, 1); read_tps_conf(conf2file, title2, top2, &ePBC2, &x2, &v2, box2, TRUE); atoms2 = &(top2->atoms); fprintf(stderr, "%s\nContaining %d atoms in %d residues\n", title2, atoms2->nr, atoms2->nres); if (bRmpbc) { rm_gropbc(atoms2, x2, box2); } fprintf(stderr, "Select group from second structure\n"); get_index(atoms2, opt2fn_null("-n2", NFILE, fnm), 1, &isize2, &index2, &groupnames2); if (bName) { find_matching_names(&isize1, index1, atoms1, &isize2, index2, atoms2); if (matchndxfile) { fp = gmx_ffopen(matchndxfile, "w"); fprintf(fp, "; Matching atoms between %s from %s and %s from %s\n", groupnames1, conf1file, groupnames2, conf2file); fprintf(fp, "[ Match_%s_%s ]\n", conf1file, groupnames1); for (i = 0; i < isize1; i++) { fprintf(fp, "%4u%s", index1[i]+1, (i%15 == 14 || i == isize1-1) ? "\n" : " "); } fprintf(fp, "[ Match_%s_%s ]\n", conf2file, groupnames2); for (i = 0; i < isize2; i++) { fprintf(fp, "%4u%s", index2[i]+1, (i%15 == 14 || i == isize2-1) ? "\n" : " "); } } } /* check isizes, must be equal */ if (isize2 != isize1) { gmx_fatal(FARGS, "You selected groups with differen number of atoms.\n"); } for (i = 0; i < isize1; i++) { name1 = *atoms1->atomname[index1[i]]; name2 = *atoms2->atomname[index2[i]]; if (strcmp(name1, name2)) { if (warn < 20) { fprintf(stderr, "Warning: atomnames at index %d don't match: %u %s, %u %s\n", i+1, index1[i]+1, name1, index2[i]+1, name2); } warn++; } if (!bMW) { atoms1->atom[index1[i]].m = 1; atoms2->atom[index2[i]].m = 1; } } if (warn) { fprintf(stderr, "%d atomname%s did not match\n", warn, (warn == 1) ? "" : "s"); } if (bFit) { /* calculate and remove center of mass of structures */ calc_rm_cm(isize1, index1, atoms1, x1, xcm1); calc_rm_cm(isize2, index2, atoms2, x2, xcm2); snew(w_rls, atoms2->nr); snew(fit_x, atoms2->nr); for (at = 0; (at < isize1); at++) { w_rls[index2[at]] = atoms1->atom[index1[at]].m; copy_rvec(x1[index1[at]], fit_x[index2[at]]); } /* do the least squares fit to the reference structure */ do_fit(atoms2->nr, w_rls, fit_x, x2); sfree(fit_x); sfree(w_rls); w_rls = NULL; } else { clear_rvec(xcm1); clear_rvec(xcm2); w_rls = NULL; } /* calculate the rms deviation */ rms = 0; totmass = 0; maxmsd = -1e18; minmsd = 1e18; snew(msds, isize1); for (at = 0; at < isize1; at++) { mass = atoms1->atom[index1[at]].m; for (m = 0; m < DIM; m++) { msd = sqr(x1[index1[at]][m] - x2[index2[at]][m]); rms += msd*mass; msds[at] += msd; } maxmsd = max(maxmsd, msds[at]); minmsd = min(minmsd, msds[at]); totmass += mass; } rms = sqrt(rms/totmass); printf("Root mean square deviation after lsq fit = %g nm\n", rms); if (bBfac) { printf("Atomic MSD's range from %g to %g nm^2\n", minmsd, maxmsd); } if (bFit) { /* reset coordinates of reference and fitted structure */ for (i = 0; i < atoms1->nr; i++) { for (m = 0; m < DIM; m++) { x1[i][m] += xcm1[m]; } } for (i = 0; i < atoms2->nr; i++) { for (m = 0; m < DIM; m++) { x2[i][m] += xcm1[m]; } } } outfile = ftp2fn(efSTO, NFILE, fnm); switch (fn2ftp(outfile)) { case efPDB: case efBRK: case efENT: if (bBfac || bLabel) { srenew(atoms1->pdbinfo, atoms1->nr); srenew(atoms1->atom, atoms1->nr); /* Why renew atom? */ /* Avoid segfaults when writing the pdb-file */ for (i = 0; i < atoms1->nr; i++) { atoms1->pdbinfo[i].type = eptAtom; atoms1->pdbinfo[i].occup = 1.00; atoms1->pdbinfo[i].bAnisotropic = FALSE; if (bBfac) { atoms1->pdbinfo[i].bfac = 0; } if (bLabel) { atoms1->resinfo[atoms1->atom[i].resind].chainid = 'A'; } } for (i = 0; i < isize1; i++) { /* atoms1->pdbinfo[index1[i]].type = eptAtom; */ /* atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE; */ if (bBfac) { atoms1->pdbinfo[index1[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i]; } /* if (bLabel) */ /* atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A'; */ } srenew(atoms2->pdbinfo, atoms2->nr); srenew(atoms2->atom, atoms2->nr); /* Why renew atom? */ for (i = 0; i < atoms2->nr; i++) { atoms2->pdbinfo[i].type = eptAtom; atoms2->pdbinfo[i].occup = 1.00; atoms2->pdbinfo[i].bAnisotropic = FALSE; if (bBfac) { atoms2->pdbinfo[i].bfac = 0; } if (bLabel) { atoms2->resinfo[atoms1->atom[i].resind].chainid = 'B'; } } for (i = 0; i < isize2; i++) { /* atoms2->pdbinfo[index2[i]].type = eptAtom; */ /* atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE; */ if (bBfac) { atoms2->pdbinfo[index2[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i]; } /* if (bLabel) */ /* atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B'; */ } } fp = gmx_ffopen(outfile, "w"); if (!bOne) { write_pdbfile(fp, title1, atoms1, x1, ePBC1, box1, ' ', 1, NULL, TRUE); } write_pdbfile(fp, title2, atoms2, x2, ePBC2, box2, ' ', bOne ? -1 : 2, NULL, TRUE); gmx_ffclose(fp); break; case efGRO: if (bBfac) { fprintf(stderr, "WARNING: cannot write B-factor values to gro file\n"); } fp = gmx_ffopen(outfile, "w"); if (!bOne) { write_hconf_p(fp, title1, atoms1, 3, x1, v1, box1); } write_hconf_p(fp, title2, atoms2, 3, x2, v2, box2); gmx_ffclose(fp); break; default: if (bBfac) { fprintf(stderr, "WARNING: cannot write B-factor values to %s file\n", ftp2ext(fn2ftp(outfile))); } if (!bOne) { fprintf(stderr, "WARNING: cannot write the reference structure to %s file\n", ftp2ext(fn2ftp(outfile))); } write_sto_conf(outfile, title2, atoms2, x2, v2, ePBC2, box2); break; } view_all(oenv, NFILE, fnm); return 0; }
void set_lincs(t_idef *idef,t_mdatoms *md, gmx_bool bDynamics,t_commrec *cr, struct gmx_lincsdata *li) { int start,natoms,nflexcon; t_blocka at2con; t_iatom *iatom; int i,k,ncc_alloc,ni,con,nconnect,concon; int type,a1,a2; real lenA=0,lenB; gmx_bool bLocal; li->nc = 0; li->ncc = 0; /* This is the local topology, so there are only F_CONSTR constraints */ if (idef->il[F_CONSTR].nr == 0) { /* There are no constraints, * we do not need to fill any data structures. */ return; } if (debug) { fprintf(debug,"Building the LINCS connectivity\n"); } if (DOMAINDECOMP(cr)) { if (cr->dd->constraints) { dd_get_constraint_range(cr->dd,&start,&natoms); } else { natoms = cr->dd->nat_home; } start = 0; } else if(PARTDECOMP(cr)) { pd_get_constraint_range(cr->pd,&start,&natoms); } else { start = md->start; natoms = md->homenr; } at2con = make_at2con(start,natoms,idef->il,idef->iparams,bDynamics, &nflexcon); if (idef->il[F_CONSTR].nr/3 > li->nc_alloc || li->nc_alloc == 0) { li->nc_alloc = over_alloc_dd(idef->il[F_CONSTR].nr/3); srenew(li->bllen0,li->nc_alloc); srenew(li->ddist,li->nc_alloc); srenew(li->bla,2*li->nc_alloc); srenew(li->blc,li->nc_alloc); srenew(li->blc1,li->nc_alloc); srenew(li->blnr,li->nc_alloc+1); srenew(li->bllen,li->nc_alloc); srenew(li->tmpv,li->nc_alloc); srenew(li->tmp1,li->nc_alloc); srenew(li->tmp2,li->nc_alloc); srenew(li->tmp3,li->nc_alloc); srenew(li->lambda,li->nc_alloc); if (li->ncg_triangle > 0) { /* This is allocating too much, but it is difficult to improve */ srenew(li->triangle,li->nc_alloc); srenew(li->tri_bits,li->nc_alloc); } } iatom = idef->il[F_CONSTR].iatoms; ncc_alloc = li->ncc_alloc; li->blnr[0] = 0; ni = idef->il[F_CONSTR].nr/3; con = 0; nconnect = 0; li->blnr[con] = nconnect; for(i=0; i<ni; i++) { bLocal = TRUE; type = iatom[3*i]; a1 = iatom[3*i+1]; a2 = iatom[3*i+2]; lenA = idef->iparams[type].constr.dA; lenB = idef->iparams[type].constr.dB; /* Skip the flexible constraints when not doing dynamics */ if (bDynamics || lenA!=0 || lenB!=0) { li->bllen0[con] = lenA; li->ddist[con] = lenB - lenA; /* Set the length to the topology A length */ li->bllen[con] = li->bllen0[con]; li->bla[2*con] = a1; li->bla[2*con+1] = a2; /* Construct the constraint connection matrix blbnb */ for(k=at2con.index[a1-start]; k<at2con.index[a1-start+1]; k++) { concon = at2con.a[k]; if (concon != i) { if (nconnect >= ncc_alloc) { ncc_alloc = over_alloc_small(nconnect+1); srenew(li->blbnb,ncc_alloc); } li->blbnb[nconnect++] = concon; } } for(k=at2con.index[a2-start]; k<at2con.index[a2-start+1]; k++) { concon = at2con.a[k]; if (concon != i) { if (nconnect+1 > ncc_alloc) { ncc_alloc = over_alloc_small(nconnect+1); srenew(li->blbnb,ncc_alloc); } li->blbnb[nconnect++] = concon; } } li->blnr[con+1] = nconnect; if (cr->dd == NULL) { /* Order the blbnb matrix to optimize memory access */ qsort(&(li->blbnb[li->blnr[con]]),li->blnr[con+1]-li->blnr[con], sizeof(li->blbnb[0]),int_comp); } /* Increase the constraint count */ con++; } } done_blocka(&at2con); /* This is the real number of constraints, * without dynamics the flexible constraints are not present. */ li->nc = con; li->ncc = li->blnr[con]; if (cr->dd == NULL) { /* Since the matrix is static, we can free some memory */ ncc_alloc = li->ncc; srenew(li->blbnb,ncc_alloc); } if (ncc_alloc > li->ncc_alloc) { li->ncc_alloc = ncc_alloc; srenew(li->blmf,li->ncc_alloc); srenew(li->blmf1,li->ncc_alloc); srenew(li->tmpncc,li->ncc_alloc); } if (debug) { fprintf(debug,"Number of constraints is %d, couplings %d\n", li->nc,li->ncc); } set_lincs_matrix(li,md->invmass,md->lambda); }
static void make_cyl_refgrps(t_commrec *cr, struct pull_t *pull, t_mdatoms *md, t_pbc *pbc, double t, rvec *x) { /* The size and stride per coord for the reduction buffer */ const int stride = 9; int c, i, ii, m, start, end; rvec g_x, dx, dir; double inv_cyl_r2; pull_comm_t *comm; gmx_ga2la_t *ga2la = NULL; comm = &pull->comm; if (comm->dbuf_cyl == NULL) { snew(comm->dbuf_cyl, pull->ncoord*stride); } if (cr && DOMAINDECOMP(cr)) { ga2la = cr->dd->ga2la; } start = 0; end = md->homenr; inv_cyl_r2 = 1.0/gmx::square(pull->params.cylinder_r); /* loop over all groups to make a reference group for each*/ for (c = 0; c < pull->ncoord; c++) { pull_coord_work_t *pcrd; double sum_a, wmass, wwmass; dvec radf_fac0, radf_fac1; pcrd = &pull->coord[c]; sum_a = 0; wmass = 0; wwmass = 0; clear_dvec(radf_fac0); clear_dvec(radf_fac1); if (pcrd->params.eGeom == epullgCYL) { pull_group_work_t *pref, *pgrp, *pdyna; /* pref will be the same group for all pull coordinates */ pref = &pull->group[pcrd->params.group[0]]; pgrp = &pull->group[pcrd->params.group[1]]; pdyna = &pull->dyna[c]; copy_rvec(pcrd->vec, dir); pdyna->nat_loc = 0; /* We calculate distances with respect to the reference location * of this cylinder group (g_x), which we already have now since * we reduced the other group COM over the ranks. This resolves * any PBC issues and we don't need to use a PBC-atom here. */ if (pcrd->params.rate != 0) { /* With rate=0, value_ref is set initially */ pcrd->value_ref = pcrd->params.init + pcrd->params.rate*t; } for (m = 0; m < DIM; m++) { g_x[m] = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref; } /* loop over all atoms in the main ref group */ for (i = 0; i < pref->params.nat; i++) { ii = pref->params.ind[i]; if (ga2la) { if (!ga2la_get_home(ga2la, pref->params.ind[i], &ii)) { ii = -1; } } if (ii >= start && ii < end) { double dr2, dr2_rel, inp; dvec dr; pbc_dx_aiuc(pbc, x[ii], g_x, dx); inp = iprod(dir, dx); dr2 = 0; for (m = 0; m < DIM; m++) { /* Determine the radial components */ dr[m] = dx[m] - inp*dir[m]; dr2 += dr[m]*dr[m]; } dr2_rel = dr2*inv_cyl_r2; if (dr2_rel < 1) { double mass, weight, dweight_r; dvec mdw; /* add to index, to sum of COM, to weight array */ if (pdyna->nat_loc >= pdyna->nalloc_loc) { pdyna->nalloc_loc = over_alloc_large(pdyna->nat_loc+1); srenew(pdyna->ind_loc, pdyna->nalloc_loc); srenew(pdyna->weight_loc, pdyna->nalloc_loc); srenew(pdyna->mdw, pdyna->nalloc_loc); srenew(pdyna->dv, pdyna->nalloc_loc); } pdyna->ind_loc[pdyna->nat_loc] = ii; mass = md->massT[ii]; /* The radial weight function is 1-2x^2+x^4, * where x=r/cylinder_r. Since this function depends * on the radial component, we also get radial forces * on both groups. */ weight = 1 + (-2 + dr2_rel)*dr2_rel; dweight_r = (-4 + 4*dr2_rel)*inv_cyl_r2; pdyna->weight_loc[pdyna->nat_loc] = weight; sum_a += mass*weight*inp; wmass += mass*weight; wwmass += mass*weight*weight; dsvmul(mass*dweight_r, dr, mdw); copy_dvec(mdw, pdyna->mdw[pdyna->nat_loc]); /* Currently we only have the axial component of the * distance (inp) up to an unkown offset. We add this * offset after the reduction needs to determine the * COM of the cylinder group. */ pdyna->dv[pdyna->nat_loc] = inp; for (m = 0; m < DIM; m++) { radf_fac0[m] += mdw[m]; radf_fac1[m] += mdw[m]*inp; } pdyna->nat_loc++; } } } } comm->dbuf_cyl[c*stride+0] = wmass; comm->dbuf_cyl[c*stride+1] = wwmass; comm->dbuf_cyl[c*stride+2] = sum_a; comm->dbuf_cyl[c*stride+3] = radf_fac0[XX]; comm->dbuf_cyl[c*stride+4] = radf_fac0[YY]; comm->dbuf_cyl[c*stride+5] = radf_fac0[ZZ]; comm->dbuf_cyl[c*stride+6] = radf_fac1[XX]; comm->dbuf_cyl[c*stride+7] = radf_fac1[YY]; comm->dbuf_cyl[c*stride+8] = radf_fac1[ZZ]; } if (cr != NULL && PAR(cr)) { /* Sum the contributions over the ranks */ pull_reduce_double(cr, comm, pull->ncoord*stride, comm->dbuf_cyl); } for (c = 0; c < pull->ncoord; c++) { pull_coord_work_t *pcrd; pcrd = &pull->coord[c]; if (pcrd->params.eGeom == epullgCYL) { pull_group_work_t *pdyna, *pgrp; double wmass, wwmass, dist; pdyna = &pull->dyna[c]; pgrp = &pull->group[pcrd->params.group[1]]; wmass = comm->dbuf_cyl[c*stride+0]; wwmass = comm->dbuf_cyl[c*stride+1]; pdyna->mwscale = 1.0/wmass; /* Cylinder pulling can't be used with constraints, but we set * wscale and invtm anyhow, in case someone would like to use them. */ pdyna->wscale = wmass/wwmass; pdyna->invtm = wwmass/(wmass*wmass); /* We store the deviation of the COM from the reference location * used above, since we need it when we apply the radial forces * to the atoms in the cylinder group. */ pcrd->cyl_dev = 0; for (m = 0; m < DIM; m++) { g_x[m] = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref; dist = -pcrd->vec[m]*comm->dbuf_cyl[c*stride+2]*pdyna->mwscale; pdyna->x[m] = g_x[m] - dist; pcrd->cyl_dev += dist; } /* Now we know the exact COM of the cylinder reference group, * we can determine the radial force factor (ffrad) that when * multiplied with the axial pull force will give the radial * force on the pulled (non-cylinder) group. */ for (m = 0; m < DIM; m++) { pcrd->ffrad[m] = (comm->dbuf_cyl[c*stride+6+m] + comm->dbuf_cyl[c*stride+3+m]*pcrd->cyl_dev)/wmass; } if (debug) { fprintf(debug, "Pull cylinder group %d:%8.3f%8.3f%8.3f m:%8.3f\n", c, pdyna->x[0], pdyna->x[1], pdyna->x[2], 1.0/pdyna->invtm); fprintf(debug, "ffrad %8.3f %8.3f %8.3f\n", pcrd->ffrad[XX], pcrd->ffrad[YY], pcrd->ffrad[ZZ]); } } } }
static void atomcat(t_atoms *dest, t_atoms *src, int copies, int maxres_renum, int *maxresnr) { int i,j,l,size; int srcnr=src->nr; int destnr=dest->nr; if (srcnr) { size=destnr+copies*srcnr; srenew(dest->atom,size); srenew(dest->atomname,size); srenew(dest->atomtype,size); srenew(dest->atomtypeB,size); } if (src->nres) { size=dest->nres+copies*src->nres; srenew(dest->resinfo,size); } /* residue information */ for (l=dest->nres,j=0; (j<copies); j++,l+=src->nres) { memcpy((char *) &(dest->resinfo[l]),(char *) &(src->resinfo[0]), (size_t)(src->nres*sizeof(src->resinfo[0]))); } for (l=destnr,j=0; (j<copies); j++,l+=srcnr) { memcpy((char *) &(dest->atomname[l]),(char *) &(src->atomname[0]), (size_t)(srcnr*sizeof(src->atomname[0]))); memcpy((char *) &(dest->atomtype[l]),(char *) &(src->atomtype[0]), (size_t)(srcnr*sizeof(src->atomtype[0]))); memcpy((char *) &(dest->atomtypeB[l]),(char *) &(src->atomtypeB[0]), (size_t)(srcnr*sizeof(src->atomtypeB[0]))); memcpy((char *) &(dest->atom[l]),(char *) &(src->atom[0]), (size_t)(srcnr*sizeof(src->atom[0]))); } /* Increment residue indices */ for (l=destnr,j=0; (j<copies); j++) { for (i=0; (i<srcnr); i++,l++) { dest->atom[l].resind = dest->nres+j*src->nres+src->atom[i].resind; } } if (src->nres <= maxres_renum) { /* Single residue molecule, continue counting residues */ for (j=0; (j<copies); j++) { for (l=0; l<src->nres; l++) { (*maxresnr)++; dest->resinfo[dest->nres+j*src->nres+l].nr = *maxresnr; } } } dest->nres += copies*src->nres; dest->nr += copies*src->nr; }
int dd_make_local_constraints(gmx_domdec_t *dd, int at_start, const struct gmx_mtop_t *mtop, const int *cginfo, gmx_constr_t constr, int nrec, t_ilist *il_local) { gmx_domdec_constraints_t *dc; t_ilist *ilc_local, *ils_local; ind_req_t *ireq; const t_blocka *at2con_mt; const int **at2settle_mt; gmx_hash_t *ga2la_specat; int at_end, i, j; t_iatom *iap; // This code should not be called unless this condition is true, // because that's the only time init_domdec_constraints is // called... GMX_RELEASE_ASSERT(dd->bInterCGcons || dd->bInterCGsettles, "dd_make_local_constraints called when there are no local constraints"); // ... and init_domdec_constraints always sets // dd->constraint_comm... GMX_RELEASE_ASSERT(dd->constraint_comm, "Invalid use of dd_make_local_constraints before construction of constraint_comm"); // ... which static analysis needs to be reassured about, because // otherwise, when dd->bInterCGsettles is // true. dd->constraint_comm is unilaterally dereferenced before // the call to atoms_to_settles. dc = dd->constraints; ilc_local = &il_local[F_CONSTR]; ils_local = &il_local[F_SETTLE]; dc->ncon = 0; ilc_local->nr = 0; if (dd->constraint_comm) { at2con_mt = atom2constraints_moltype(constr); ireq = &dd->constraint_comm->ireq[0]; ireq->n = 0; } else { // Currently unreachable at2con_mt = NULL; ireq = NULL; } if (dd->bInterCGsettles) { at2settle_mt = atom2settle_moltype(constr); ils_local->nr = 0; } else { /* Settle works inside charge groups, we assigned them already */ at2settle_mt = NULL; } if (at2settle_mt == NULL) { atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec, ilc_local, ireq); } else { int t0_set; int thread; /* Do the constraints, if present, on the first thread. * Do the settles on all other threads. */ t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0); #pragma omp parallel for num_threads(dc->nthread) schedule(static) for (thread = 0; thread < dc->nthread; thread++) { try { if (at2con_mt && thread == 0) { atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec, ilc_local, ireq); } if (thread >= t0_set) { int cg0, cg1; t_ilist *ilst; ind_req_t *ireqt; /* Distribute the settle check+assignments over * dc->nthread or dc->nthread-1 threads. */ cg0 = (dd->ncg_home*(thread-t0_set ))/(dc->nthread-t0_set); cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set); if (thread == t0_set) { ilst = ils_local; } else { ilst = &dc->ils[thread]; } ilst->nr = 0; ireqt = &dd->constraint_comm->ireq[thread]; if (thread > 0) { ireqt->n = 0; } atoms_to_settles(dd, mtop, cginfo, at2settle_mt, cg0, cg1, ilst, ireqt); } } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; } /* Combine the generate settles and requested indices */ for (thread = 1; thread < dc->nthread; thread++) { t_ilist *ilst; ind_req_t *ireqt; int ia; if (thread > t0_set) { ilst = &dc->ils[thread]; if (ils_local->nr + ilst->nr > ils_local->nalloc) { ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr); srenew(ils_local->iatoms, ils_local->nalloc); } for (ia = 0; ia < ilst->nr; ia++) { ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia]; } ils_local->nr += ilst->nr; } ireqt = &dd->constraint_comm->ireq[thread]; if (ireq->n+ireqt->n > ireq->nalloc) { ireq->nalloc = over_alloc_large(ireq->n+ireqt->n); srenew(ireq->ind, ireq->nalloc); } for (ia = 0; ia < ireqt->n; ia++) { ireq->ind[ireq->n+ia] = ireqt->ind[ia]; } ireq->n += ireqt->n; } if (debug) { fprintf(debug, "Settles: total %3d\n", ils_local->nr/4); } } if (dd->constraint_comm) { int nral1; at_end = setup_specat_communication(dd, ireq, dd->constraint_comm, dd->constraints->ga2la, at_start, 2, "constraint", " or lincs-order"); /* Fill in the missing indices */ ga2la_specat = dd->constraints->ga2la; nral1 = 1 + NRAL(F_CONSTR); for (i = 0; i < ilc_local->nr; i += nral1) { iap = ilc_local->iatoms + i; for (j = 1; j < nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1); } } } nral1 = 1 + NRAL(F_SETTLE); for (i = 0; i < ils_local->nr; i += nral1) { iap = ils_local->iatoms + i; for (j = 1; j < nral1; j++) { if (iap[j] < 0) { iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1); } } } } else { // Currently unreachable at_end = at_start; } return at_end; }
int gmx_enemat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] extracts an energy matrix from the energy file ([TT]-f[tt]).", "With [TT]-groups[tt] a file must be supplied with on each", "line a group of atoms to be used. For these groups matrix of", "interaction energies will be extracted from the energy file", "by looking for energy groups with names corresponding to pairs", "of groups of atoms, e.g. if your [TT]-groups[tt] file contains::", "", " 2", " Protein", " SOL", "", "then energy groups with names like 'Coul-SR:Protein-SOL' and ", "'LJ:Protein-SOL' are expected in the energy file (although", "[THISMODULE] is most useful if many groups are analyzed", "simultaneously). Matrices for different energy types are written", "out separately, as controlled by the", "[TT]-[no]coul[tt], [TT]-[no]coulr[tt], [TT]-[no]coul14[tt], ", "[TT]-[no]lj[tt], [TT]-[no]lj14[tt], ", "[TT]-[no]bham[tt] and [TT]-[no]free[tt] options.", "Finally, the total interaction energy energy per group can be ", "calculated ([TT]-etot[tt]).[PAR]", "An approximation of the free energy can be calculated using:", "[MATH]E[SUB]free[sub] = E[SUB]0[sub] + kT [LOG][CHEVRON][EXP](E-E[SUB]0[sub])/kT[exp][chevron][log][math], where '[MATH][CHEVRON][chevron][math]'", "stands for time-average. A file with reference free energies", "can be supplied to calculate the free energy difference", "with some reference state. Group names (e.g. residue names)", "in the reference file should correspond to the group names", "as used in the [TT]-groups[tt] file, but a appended number", "(e.g. residue number) in the [TT]-groups[tt] will be ignored", "in the comparison." }; static gmx_bool bSum = FALSE; static gmx_bool bMeanEmtx = TRUE; static int skip = 0, nlevels = 20; static real cutmax = 1e20, cutmin = -1e20, reftemp = 300.0; static gmx_bool bCoulSR = TRUE, bCoul14 = FALSE; static gmx_bool bLJSR = TRUE, bLJ14 = FALSE, bBhamSR = FALSE, bFree = TRUE; t_pargs pa[] = { { "-sum", FALSE, etBOOL, {&bSum}, "Sum the energy terms selected rather than display them all" }, { "-skip", FALSE, etINT, {&skip}, "Skip number of frames between data points" }, { "-mean", FALSE, etBOOL, {&bMeanEmtx}, "with [TT]-groups[tt] extracts matrix of mean energies instead of " "matrix for each timestep" }, { "-nlevels", FALSE, etINT, {&nlevels}, "number of levels for matrix colors"}, { "-max", FALSE, etREAL, {&cutmax}, "max value for energies"}, { "-min", FALSE, etREAL, {&cutmin}, "min value for energies"}, { "-coulsr", FALSE, etBOOL, {&bCoulSR}, "extract Coulomb SR energies"}, { "-coul14", FALSE, etBOOL, {&bCoul14}, "extract Coulomb 1-4 energies"}, { "-ljsr", FALSE, etBOOL, {&bLJSR}, "extract Lennard-Jones SR energies"}, { "-lj14", FALSE, etBOOL, {&bLJ14}, "extract Lennard-Jones 1-4 energies"}, { "-bhamsr", FALSE, etBOOL, {&bBhamSR}, "extract Buckingham SR energies"}, { "-free", FALSE, etBOOL, {&bFree}, "calculate free energy"}, { "-temp", FALSE, etREAL, {&reftemp}, "reference temperature for free energy calculation"} }; /* We will define egSP more energy-groups: egTotal (total energy) */ #define egTotal egNR #define egSP 1 gmx_bool egrp_use[egNR+egSP]; ener_file_t in; FILE *out; int timecheck = 0; gmx_enxnm_t *enm = NULL; t_enxframe *fr; int teller = 0; real sum; gmx_bool bCont, bRef; gmx_bool bCutmax, bCutmin; real **eneset, *time = NULL; int *set, i, j, k, prevk, m = 0, n, nre, nset, nenergy; char **groups = NULL; char groupname[255], fn[255]; int ngroups; t_rgb rlo, rhi, rmid; real emax, emid, emin; real ***emat, **etot, *groupnr; double beta, expE, **e, *eaver, *efree = NULL, edum; char label[234]; char **ereflines, **erefres = NULL; real *eref = NULL, *edif = NULL; int neref = 0; gmx_output_env_t *oenv; t_filenm fnm[] = { { efEDR, "-f", NULL, ffOPTRD }, { efDAT, "-groups", "groups", ffREAD }, { efDAT, "-eref", "eref", ffOPTRD }, { efXPM, "-emat", "emat", ffWRITE }, { efXVG, "-etot", "energy", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } for (i = 0; (i < egNR+egSP); i++) { egrp_use[i] = FALSE; } egrp_use[egCOULSR] = bCoulSR; egrp_use[egLJSR] = bLJSR; egrp_use[egBHAMSR] = bBhamSR; egrp_use[egCOUL14] = bCoul14; egrp_use[egLJ14] = bLJ14; egrp_use[egTotal] = TRUE; bRef = opt2bSet("-eref", NFILE, fnm); in = open_enx(ftp2fn(efEDR, NFILE, fnm), "r"); do_enxnms(in, &nre, &enm); if (nre == 0) { gmx_fatal(FARGS, "No energies!\n"); } bCutmax = opt2parg_bSet("-max", asize(pa), pa); bCutmin = opt2parg_bSet("-min", asize(pa), pa); nenergy = 0; /* Read groupnames from input file and construct selection of energy groups from it*/ fprintf(stderr, "Will read groupnames from inputfile\n"); ngroups = get_lines(opt2fn("-groups", NFILE, fnm), &groups); fprintf(stderr, "Read %d groups\n", ngroups); snew(set, static_cast<size_t>(gmx::square(ngroups)*egNR/2)); n = 0; prevk = 0; for (i = 0; (i < ngroups); i++) { fprintf(stderr, "\rgroup %d", i); for (j = i; (j < ngroups); j++) { for (m = 0; (m < egNR); m++) { if (egrp_use[m]) { sprintf(groupname, "%s:%s-%s", egrp_nm[m], groups[i], groups[j]); #ifdef DEBUG fprintf(stderr, "\r%-15s %5d", groupname, n); #endif for (k = prevk; (k < prevk+nre); k++) { if (std::strcmp(enm[k%nre].name, groupname) == 0) { set[n++] = k; break; } } if (k == prevk+nre) { fprintf(stderr, "WARNING! could not find group %s (%d,%d)" "in energy file\n", groupname, i, j); } else { prevk = k; } } } } } fprintf(stderr, "\n"); nset = n; snew(eneset, nset+1); fprintf(stderr, "Will select half-matrix of energies with %d elements\n", n); /* Start reading energy frames */ snew(fr, 1); do { do { bCont = do_enx(in, fr); if (bCont) { timecheck = check_times(fr->t); } } while (bCont && (timecheck < 0)); if (timecheck == 0) { #define DONTSKIP(cnt) (skip) ? ((cnt % skip) == 0) : TRUE if (bCont) { fprintf(stderr, "\rRead frame: %d, Time: %.3f", teller, fr->t); if ((nenergy % 1000) == 0) { srenew(time, nenergy+1000); for (i = 0; (i <= nset); i++) { srenew(eneset[i], nenergy+1000); } } time[nenergy] = fr->t; sum = 0; for (i = 0; (i < nset); i++) { eneset[i][nenergy] = fr->ener[set[i]].e; sum += fr->ener[set[i]].e; } if (bSum) { eneset[nset][nenergy] = sum; } nenergy++; } teller++; } } while (bCont && (timecheck == 0)); fprintf(stderr, "\n"); fprintf(stderr, "Will build energy half-matrix of %d groups, %d elements, " "over %d frames\n", ngroups, nset, nenergy); snew(emat, egNR+egSP); for (j = 0; (j < egNR+egSP); j++) { if (egrp_use[m]) { snew(emat[j], ngroups); for (i = 0; (i < ngroups); i++) { snew(emat[j][i], ngroups); } } } snew(groupnr, ngroups); for (i = 0; (i < ngroups); i++) { groupnr[i] = i+1; } rlo.r = 1.0, rlo.g = 0.0, rlo.b = 0.0; rmid.r = 1.0, rmid.g = 1.0, rmid.b = 1.0; rhi.r = 0.0, rhi.g = 0.0, rhi.b = 1.0; if (bMeanEmtx) { snew(e, ngroups); for (i = 0; (i < ngroups); i++) { snew(e[i], nenergy); } n = 0; for (i = 0; (i < ngroups); i++) { for (j = i; (j < ngroups); j++) { for (m = 0; (m < egNR); m++) { if (egrp_use[m]) { for (k = 0; (k < nenergy); k++) { emat[m][i][j] += eneset[n][k]; e[i][k] += eneset[n][k]; /* *0.5; */ e[j][k] += eneset[n][k]; /* *0.5; */ } n++; emat[egTotal][i][j] += emat[m][i][j]; emat[m][i][j] /= nenergy; emat[m][j][i] = emat[m][i][j]; } } emat[egTotal][i][j] /= nenergy; emat[egTotal][j][i] = emat[egTotal][i][j]; } } if (bFree) { if (bRef) { fprintf(stderr, "Will read reference energies from inputfile\n"); neref = get_lines(opt2fn("-eref", NFILE, fnm), &ereflines); fprintf(stderr, "Read %d reference energies\n", neref); snew(eref, neref); snew(erefres, neref); for (i = 0; (i < neref); i++) { snew(erefres[i], 5); sscanf(ereflines[i], "%s %lf", erefres[i], &edum); eref[i] = edum; } } snew(eaver, ngroups); for (i = 0; (i < ngroups); i++) { for (k = 0; (k < nenergy); k++) { eaver[i] += e[i][k]; } eaver[i] /= nenergy; } beta = 1.0/(BOLTZ*reftemp); snew(efree, ngroups); snew(edif, ngroups); for (i = 0; (i < ngroups); i++) { expE = 0; for (k = 0; (k < nenergy); k++) { expE += std::exp(beta*(e[i][k]-eaver[i])); } efree[i] = std::log(expE/nenergy)/beta + eaver[i]; if (bRef) { n = search_str2(neref, erefres, groups[i]); if (n != -1) { edif[i] = efree[i]-eref[n]; } else { edif[i] = efree[i]; fprintf(stderr, "WARNING: group %s not found " "in reference energies.\n", groups[i]); } } else { edif[i] = 0; } } } emid = 0.0; /*(emin+emax)*0.5;*/ egrp_nm[egTotal] = "total"; for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { emin = 1e10; emax = -1e10; for (i = 0; (i < ngroups); i++) { for (j = i; (j < ngroups); j++) { if (emat[m][i][j] > emax) { emax = emat[m][i][j]; } else if (emat[m][i][j] < emin) { emin = emat[m][i][j]; } } } if (emax == emin) { fprintf(stderr, "Matrix of %s energy is uniform at %f " "(will not produce output).\n", egrp_nm[m], emax); } else { fprintf(stderr, "Matrix of %s energy ranges from %f to %f\n", egrp_nm[m], emin, emax); if ((bCutmax) || (emax > cutmax)) { emax = cutmax; } if ((bCutmin) || (emin < cutmin)) { emin = cutmin; } if ((emax == cutmax) || (emin == cutmin)) { fprintf(stderr, "Energy range adjusted: %f to %f\n", emin, emax); } sprintf(fn, "%s%s", egrp_nm[m], ftp2fn(efXPM, NFILE, fnm)); sprintf(label, "%s Interaction Energies", egrp_nm[m]); out = gmx_ffopen(fn, "w"); if (emin >= emid) { write_xpm(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emid, emax, rmid, rhi, &nlevels); } else if (emax <= emid) { write_xpm(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emin, emid, rlo, rmid, &nlevels); } else { write_xpm3(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emin, emid, emax, rlo, rmid, rhi, &nlevels); } gmx_ffclose(out); } } } snew(etot, egNR+egSP); for (m = 0; (m < egNR+egSP); m++) { snew(etot[m], ngroups); for (i = 0; (i < ngroups); i++) { for (j = 0; (j < ngroups); j++) { etot[m][i] += emat[m][i][j]; } } } out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Mean Energy", "Residue", "kJ/mol", oenv); xvgr_legend(out, 0, NULL, oenv); j = 0; if (output_env_get_print_xvgr_codes(oenv)) { char str1[STRLEN], str2[STRLEN]; if (output_env_get_xvg_format(oenv) == exvgXMGR) { sprintf(str1, "@ legend string "); sprintf(str2, " "); } else { sprintf(str1, "@ s"); sprintf(str2, " legend "); } for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, egrp_nm[m]); } } if (bFree) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Free"); } if (bFree) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Diff"); } fprintf(out, "@TYPE xy\n"); fprintf(out, "#%3s", "grp"); for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, " %9s", egrp_nm[m]); } } if (bFree) { fprintf(out, " %9s", "Free"); } if (bFree) { fprintf(out, " %9s", "Diff"); } fprintf(out, "\n"); } for (i = 0; (i < ngroups); i++) { fprintf(out, "%3.0f", groupnr[i]); for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, " %9.5g", etot[m][i]); } } if (bFree) { fprintf(out, " %9.5g", efree[i]); } if (bRef) { fprintf(out, " %9.5g", edif[i]); } fprintf(out, "\n"); } xvgrclose(out); } else { fprintf(stderr, "While typing at your keyboard, suddenly...\n" "...nothing happens.\nWARNING: Not Implemented Yet\n"); /* out=ftp2FILE(efMAT,NFILE,fnm,"w"); n=0; emin=emax=0.0; for (k=0; (k<nenergy); k++) { for (i=0; (i<ngroups); i++) for (j=i+1; (j<ngroups); j++) emat[i][j]=eneset[n][k]; sprintf(label,"t=%.0f ps",time[k]); write_matrix(out,ngroups,1,ngroups,groupnr,emat,label,emin,emax,nlevels); n++; } gmx_ffclose(out); */ } close_enx(in); return 0; }
int gmx_vanhove(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the Van Hove correlation function.", "The Van Hove G(r,t) is the probability that a particle that is at r[SUB]0[sub]", "at time zero can be found at position r[SUB]0[sub]+r at time t.", "[THISMODULE] determines G not for a vector r, but for the length of r.", "Thus it gives the probability that a particle moves a distance of r", "in time t.", "Jumps across the periodic boundaries are removed.", "Corrections are made for scaling due to isotropic", "or anisotropic pressure coupling.", "[PAR]", "With option [TT]-om[tt] the whole matrix can be written as a function", "of t and r or as a function of [SQRT]t[sqrt] and r (option [TT]-sqrt[tt]).", "[PAR]", "With option [TT]-or[tt] the Van Hove function is plotted for one", "or more values of t. Option [TT]-nr[tt] sets the number of times,", "option [TT]-fr[tt] the number spacing between the times.", "The binwidth is set with option [TT]-rbin[tt]. The number of bins", "is determined automatically.", "[PAR]", "With option [TT]-ot[tt] the integral up to a certain distance", "(option [TT]-rt[tt]) is plotted as a function of time.", "[PAR]", "For all frames that are read the coordinates of the selected particles", "are stored in memory. Therefore the program may use a lot of memory.", "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.", "This is because the calculation scales as the number of frames times", "[TT]-fm[tt] or [TT]-ft[tt].", "Note that with the [TT]-dt[tt] option the memory usage and calculation", "time can be reduced." }; static int fmmax = 0, ftmax = 0, nlev = 81, nr = 1, fshift = 0; static real sbin = 0, rmax = 2, rbin = 0.01, mmax = 0, rint = 0; t_pargs pa[] = { { "-sqrt", FALSE, etREAL, {&sbin}, "Use [SQRT]t[sqrt] on the matrix axis which binspacing # in [SQRT]ps[sqrt]" }, { "-fm", FALSE, etINT, {&fmmax}, "Number of frames in the matrix, 0 is plot all" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum r in the matrix (nm)" }, { "-rbin", FALSE, etREAL, {&rbin}, "Binwidth in the matrix and for [TT]-or[tt] (nm)" }, { "-mmax", FALSE, etREAL, {&mmax}, "Maximum density in the matrix, 0 is calculate (1/nm)" }, { "-nlevels", FALSE, etINT, {&nlev}, "Number of levels in the matrix" }, { "-nr", FALSE, etINT, {&nr}, "Number of curves for the [TT]-or[tt] output" }, { "-fr", FALSE, etINT, {&fshift}, "Frame spacing for the [TT]-or[tt] output" }, { "-rt", FALSE, etREAL, {&rint}, "Integration limit for the [TT]-ot[tt] output (nm)" }, { "-ft", FALSE, etINT, {&ftmax}, "Number of frames in the [TT]-ot[tt] output, 0 is plot all" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-om", "vanhove", ffOPTWR }, { efXVG, "-or", "vanhove_r", ffOPTWR }, { efXVG, "-ot", "vanhove_t", ffOPTWR } }; #define NFILE asize(fnm) output_env_t oenv; const char *matfile, *otfile, *orfile; char title[256]; t_topology top; int ePBC; matrix boxtop, box, *sbox, avbox, corr; rvec *xtop, *x, **sx; int isize, nalloc, nallocn, natom; t_trxstatus *status; atom_id *index; char *grpname; int nfr, f, ff, i, m, mat_nx = 0, nbin = 0, bin, mbin, fbin; real *time, t, invbin = 0, rmax2 = 0, rint2 = 0, d2; real invsbin = 0, matmax, normfac, dt, *tickx, *ticky; char buf[STRLEN], **legend; real **mat = NULL; int *pt = NULL, **pr = NULL, *mcount = NULL, *tcount = NULL, *rcount = NULL; FILE *fp; t_rgb rlo = {1, 1, 1}, rhi = {0, 0, 0}; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } matfile = opt2fn_null("-om", NFILE, fnm); if (opt2parg_bSet("-fr", NPA, pa)) { orfile = opt2fn("-or", NFILE, fnm); } else { orfile = opt2fn_null("-or", NFILE, fnm); } if (opt2parg_bSet("-rt", NPA, pa)) { otfile = opt2fn("-ot", NFILE, fnm); } else { otfile = opt2fn_null("-ot", NFILE, fnm); } if (!matfile && !otfile && !orfile) { fprintf(stderr, "For output set one (or more) of the output file options\n"); exit(0); } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, boxtop, FALSE); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); nalloc = 0; time = NULL; sbox = NULL; sx = NULL; clear_mat(avbox); natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); nfr = 0; do { if (nfr >= nalloc) { nalloc += 100; srenew(time, nalloc); srenew(sbox, nalloc); srenew(sx, nalloc); } assert(time != NULL); assert(sbox != NULL); time[nfr] = t; copy_mat(box, sbox[nfr]); /* This assumes that the off-diagonal box elements * are not affected by jumps across the periodic boundaries. */ m_add(avbox, box, avbox); snew(sx[nfr], isize); for (i = 0; i < isize; i++) { copy_rvec(x[index[i]], sx[nfr][i]); } nfr++; } while (read_next_x(oenv, status, &t, x, box)); /* clean up */ sfree(x); close_trj(status); fprintf(stderr, "Read %d frames\n", nfr); dt = (time[nfr-1] - time[0])/(nfr - 1); /* Some ugly rounding to get nice nice times in the output */ dt = (int)(10000.0*dt + 0.5)/10000.0; invbin = 1.0/rbin; if (matfile) { if (fmmax <= 0 || fmmax >= nfr) { fmmax = nfr - 1; } snew(mcount, fmmax); nbin = (int)(rmax*invbin + 0.5); if (sbin == 0) { mat_nx = fmmax + 1; } else { invsbin = 1.0/sbin; mat_nx = sqrt(fmmax*dt)*invsbin + 1; } snew(mat, mat_nx); for (f = 0; f < mat_nx; f++) { snew(mat[f], nbin); } rmax2 = sqr(nbin*rbin); /* Initialize time zero */ mat[0][0] = nfr*isize; mcount[0] += nfr; } else { fmmax = 0; } if (orfile) { snew(pr, nr); nalloc = 0; snew(rcount, nr); } if (otfile) { if (ftmax <= 0) { ftmax = nfr - 1; } snew(tcount, ftmax); snew(pt, nfr); rint2 = rint*rint; /* Initialize time zero */ pt[0] = nfr*isize; tcount[0] += nfr; } else { ftmax = 0; } msmul(avbox, 1.0/nfr, avbox); for (f = 0; f < nfr; f++) { if (f % 100 == 0) { fprintf(stderr, "\rProcessing frame %d", f); } /* Scale all the configuration to the average box */ m_inv_ur0(sbox[f], corr); mmul_ur0(avbox, corr, corr); for (i = 0; i < isize; i++) { mvmul_ur0(corr, sx[f][i], sx[f][i]); if (f > 0) { /* Correct for periodic jumps */ for (m = DIM-1; m >= 0; m--) { while (sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m]) { rvec_dec(sx[f][i], avbox[m]); } while (sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m]) { rvec_inc(sx[f][i], avbox[m]); } } } } for (ff = 0; ff < f; ff++) { fbin = f - ff; if (fbin <= fmmax || fbin <= ftmax) { if (sbin == 0) { mbin = fbin; } else { mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5); } for (i = 0; i < isize; i++) { d2 = distance2(sx[f][i], sx[ff][i]); if (mbin < mat_nx && d2 < rmax2) { bin = (int)(sqrt(d2)*invbin + 0.5); if (bin < nbin) { mat[mbin][bin] += 1; } } if (fbin <= ftmax && d2 <= rint2) { pt[fbin]++; } } if (matfile) { mcount[mbin]++; } if (otfile) { tcount[fbin]++; } } } if (orfile) { for (fbin = 0; fbin < nr; fbin++) { ff = f - (fbin + 1)*fshift; if (ff >= 0) { for (i = 0; i < isize; i++) { d2 = distance2(sx[f][i], sx[ff][i]); bin = (int)(sqrt(d2)*invbin + 0.5); if (bin >= nalloc) { nallocn = 10*(bin/10) + 11; for (m = 0; m < nr; m++) { srenew(pr[m], nallocn); for (i = nalloc; i < nallocn; i++) { pr[m][i] = 0; } } nalloc = nallocn; } pr[fbin][bin]++; } rcount[fbin]++; } } } } fprintf(stderr, "\n"); if (matfile) { matmax = 0; for (f = 0; f < mat_nx; f++) { normfac = 1.0/(mcount[f]*isize*rbin); for (i = 0; i < nbin; i++) { mat[f][i] *= normfac; if (mat[f][i] > matmax && (f != 0 || i != 0)) { matmax = mat[f][i]; } } } fprintf(stdout, "Value at (0,0): %.3f, maximum of the rest %.3f\n", mat[0][0], matmax); if (mmax > 0) { matmax = mmax; } snew(tickx, mat_nx); for (f = 0; f < mat_nx; f++) { if (sbin == 0) { tickx[f] = f*dt; } else { tickx[f] = f*sbin; } } snew(ticky, nbin+1); for (i = 0; i <= nbin; i++) { ticky[i] = i*rbin; } fp = gmx_ffopen(matfile, "w"); write_xpm(fp, MAT_SPATIAL_Y, "Van Hove function", "G (1/nm)", sbin == 0 ? "time (ps)" : "sqrt(time) (ps^1/2)", "r (nm)", mat_nx, nbin, tickx, ticky, mat, 0, matmax, rlo, rhi, &nlev); gmx_ffclose(fp); } if (orfile) { fp = xvgropen(orfile, "Van Hove function", "r (nm)", "G (nm\\S-1\\N)", oenv); fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname); snew(legend, nr); for (fbin = 0; fbin < nr; fbin++) { sprintf(buf, "%g ps", (fbin + 1)*fshift*dt); legend[fbin] = strdup(buf); } xvgr_legend(fp, nr, (const char**)legend, oenv); for (i = 0; i < nalloc; i++) { fprintf(fp, "%g", i*rbin); for (fbin = 0; fbin < nr; fbin++) { fprintf(fp, " %g", (real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i == 0 ? 0.5 : 1))); } fprintf(fp, "\n"); } gmx_ffclose(fp); } if (otfile) { sprintf(buf, "Probability of moving less than %g nm", rint); fp = xvgropen(otfile, buf, "t (ps)", "", oenv); fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname); for (f = 0; f <= ftmax; f++) { fprintf(fp, "%g %g\n", f*dt, (real)pt[f]/(tcount[f]*isize)); } gmx_ffclose(fp); } do_view(oenv, matfile, NULL); do_view(oenv, orfile, NULL); do_view(oenv, otfile, NULL); return 0; }
int main(int argc,char *argv[]) { static char *desc[] = { "do_dssp ", "reads a trajectory file and computes the secondary structure for", "each time frame ", "calling the dssp program. If you do not have the dssp program,", "get it. do_dssp assumes that the dssp executable is", "/usr/local/bin/dssp. If this is not the case, then you should", "set an environment variable [BB]DSSP[bb] pointing to the dssp", "executable, e.g.: [PAR]", "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]", "The structure assignment for each residue and time is written to an", "[TT].xpm[tt] matrix file. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].", "The number of residues with each secondary structure type and the", "total secondary structure ([TT]-sss[tt]) count as a function of", "time are also written to file ([TT]-sc[tt]).[PAR]", "Solvent accessible surface (SAS) per residue can be calculated, both in", "absolute values (A^2) and in fractions of the maximal accessible", "surface of a residue. The maximal accessible surface is defined as", "the accessible surface of a residue in a chain of glycines.", "[BB]Note[bb] that the program [TT]g_sas[tt] can also compute SAS", "and that is more efficient.[PAR]", "Finally, this program can dump the secondary structure in a special file", "[TT]ssdump.dat[tt] for usage in the program [TT]g_chi[tt]. Together", "these two programs can be used to analyze dihedral properties as a", "function of secondary structure type." }; static bool bVerbose; static char *ss_string="HEBT"; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "HIDDENGenerate miles of useless information" }, { "-sss", FALSE, etSTR, {&ss_string}, "Secondary structures for structure count"} }; int status; FILE *tapein; FILE *ss,*acc,*fTArea,*tmpf; char *fnSCount,*fnArea,*fnTArea,*fnAArea; char *leg[] = { "Phobic", "Phylic" }; t_topology top; int ePBC; t_atoms *atoms; t_matrix mat; int nres,nr0,naccr; bool *bPhbres,bDoAccSurf; real t; int i,j,natoms,nframe=0; matrix box; int gnx; char *grpnm,*ss_str; atom_id *index; rvec *xp,*x; int *average_area; real **accr,*av_area, *norm_av_area; char pdbfile[32],tmpfile[32],title[256]; char dssp[256],*dptr; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-ssdump", "ssdump", ffOPTWR }, { efMAP, "-map", "ss", ffLIBRD }, { efXPM, "-o", "ss", ffWRITE }, { efXVG, "-sc", "scount", ffWRITE }, { efXPM, "-a", "area", ffOPTWR }, { efXVG, "-ta", "totarea", ffOPTWR }, { efXVG, "-aa", "averarea",ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT | PCA_BE_NICE , NFILE,fnm, asize(pa),pa, asize(desc),desc,0,NULL); fnSCount= opt2fn("-sc",NFILE,fnm); fnArea = opt2fn_null("-a", NFILE,fnm); fnTArea = opt2fn_null("-ta",NFILE,fnm); fnAArea = opt2fn_null("-aa",NFILE,fnm); bDoAccSurf=(fnArea || fnTArea || fnAArea); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xp,NULL,box,FALSE); atoms=&(top.atoms); check_oo(atoms); bPhbres=bPhobics(atoms); get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpnm); nres=0; nr0=-1; for(i=0; (i<gnx); i++) { if (atoms->atom[index[i]].resnr != nr0) { nr0=atoms->atom[index[i]].resnr; nres++; } } fprintf(stderr,"There are %d residues in your selected group\n",nres); strcpy(pdbfile,"ddXXXXXX"); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) { sprintf(pdbfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile,"w")) == NULL) gmx_fatal(FARGS,"Can not open tmp file %s",pdbfile); } else fclose(tmpf); strcpy(tmpfile,"ddXXXXXX"); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile,"w")) == NULL) { sprintf(tmpfile,"%ctmp%cfilterXXXXXX",DIR_SEPARATOR,DIR_SEPARATOR); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile,"w")) == NULL) gmx_fatal(FARGS,"Can not open tmp file %s",tmpfile); } else fclose(tmpf); if ((dptr=getenv("DSSP")) == NULL) dptr="/usr/local/bin/dssp"; if (!fexist(dptr)) gmx_fatal(FARGS,"DSSP executable (%s) does not exist (use setenv DSSP)", dptr); sprintf(dssp,"%s %s %s %s > /dev/null %s", dptr,bDoAccSurf?"":"-na",pdbfile,tmpfile,bVerbose?"":"2> /dev/null"); if (bVerbose) fprintf(stderr,"dssp cmd='%s'\n",dssp); if (fnTArea) { fTArea=xvgropen(fnTArea,"Solvent Accessible Surface Area", xvgr_tlabel(),"Area (nm\\S2\\N)"); xvgr_legend(fTArea,2,leg); } else fTArea=NULL; mat.map=NULL; mat.nmap=getcmap(libopen(opt2fn("-map",NFILE,fnm)), opt2fn("-map",NFILE,fnm),&(mat.map)); natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); if (natoms > atoms->nr) gmx_fatal(FARGS,"\nTrajectory does not match topology!"); if (gnx > natoms) gmx_fatal(FARGS,"\nTrajectory does not match selected group!"); snew(average_area,atoms->nres+10); snew(av_area,atoms->nres+10); snew(norm_av_area,atoms->nres+10); accr=NULL; naccr=0; do { t = convert_time(t); if (nframe>=naccr) { naccr+=10; srenew(accr,naccr); for(i=naccr-10; i<naccr; i++) snew(accr[i],atoms->nres+10); } rm_pbc(&(top.idef),ePBC,natoms,box,x,x); tapein=ffopen(pdbfile,"w"); write_pdbfile_indexed(tapein,NULL,atoms,x,ePBC,box,0,-1,gnx,index); fclose(tapein); #ifdef GMX_NO_SYSTEM printf("Warning-- No calls to system(3) supported on this platform."); printf("Warning-- Skipping execution of 'system(\"%s\")'.", dssp); exit(1); #else if(0 != system(dssp)) { gmx_fatal(FARGS,"Failed to execute command: %s",dssp); } #endif strip_dssp(tmpfile,nres,bPhbres,t, accr[nframe],fTArea,&mat,average_area); remove(tmpfile); remove(pdbfile); nframe++; } while(read_next_x(status,&t,natoms,x,box)); fprintf(stderr,"\n"); close_trj(status); if (fTArea) ffclose(fTArea); prune_ss_legend(&mat); ss=opt2FILE("-o",NFILE,fnm,"w"); write_xpm_m(ss,mat); ffclose(ss); if (opt2bSet("-ssdump",NFILE,fnm)) { snew(ss_str,nres+1); for(i=0; (i<nres); i++) ss_str[i] = mat.map[mat.matrix[0][i]].code.c1; ss_str[i] = '\0'; ss = opt2FILE("-ssdump",NFILE,fnm,"w"); fprintf(ss,"%d\n%s\n",nres,ss_str); fclose(ss); sfree(ss_str); } analyse_ss(fnSCount,&mat,ss_string); if (bDoAccSurf) { write_sas_mat(fnArea,accr,nframe,nres,&mat); for(i=0; i<atoms->nres; i++) av_area[i] = (average_area[i] / (real)nframe); norm_acc(atoms, nres, av_area, norm_av_area); if (fnAArea) { acc=xvgropen(fnAArea,"Average Accessible Area", "Residue","A\\S2"); for(i=0; (i<nres); i++) fprintf(acc,"%5d %10g %10g\n",i+1,av_area[i], norm_av_area[i]); ffclose(acc); } } view_all(NFILE, fnm); thanx(stderr); return 0; }
static void edit_index(int natoms, t_atoms *atoms, rvec *x, t_blocka *block, char ***gn, gmx_bool bVerbose) { static char **atnames, *ostring; static gmx_bool bFirst = TRUE; char inp_string[STRLEN], *string; char gname[STRLEN], gname1[STRLEN], gname2[STRLEN]; int i, i0, i1, sel_nr, sel_nr2, newgroup; atom_id nr, nr1, nr2, *index, *index1, *index2; gmx_bool bAnd, bOr, bPrintOnce; if (bFirst) { bFirst = FALSE; snew(atnames, MAXNAMES); for (i = 0; i < MAXNAMES; i++) { snew(atnames[i], NAME_LEN+1); } } string = NULL; snew(index, natoms); snew(index1, natoms); snew(index2, natoms); newgroup = NOTSET; bPrintOnce = TRUE; do { gname1[0] = '\0'; if (bVerbose || bPrintOnce || newgroup != NOTSET) { printf("\n"); if (bVerbose || bPrintOnce || newgroup == NOTSET) { i0 = 0; i1 = block->nr; } else { i0 = newgroup; i1 = newgroup+1; } for (i = i0; i < i1; i++) { printf("%3d %-20s: %5d atoms\n", i, (*gn)[i], block->index[i+1]-block->index[i]); } newgroup = NOTSET; } if (bVerbose || bPrintOnce) { printf("\n"); printf(" nr : group ! 'name' nr name 'splitch' nr Enter: list groups\n"); printf(" 'a': atom & 'del' nr 'splitres' nr 'l': list residues\n"); printf(" 't': atom type | 'keep' nr 'splitat' nr 'h': help\n"); printf(" 'r': residue 'res' nr 'chain' char\n"); printf(" \"name\": group 'case': case %s 'q': save and quit\n", bCase ? "insensitive" : "sensitive "); printf(" 'ri': residue index\n"); bPrintOnce = FALSE; } printf("\n"); printf("> "); if (NULL == fgets(inp_string, STRLEN, stdin)) { gmx_fatal(FARGS, "Error reading user input"); } inp_string[strlen(inp_string)-1] = 0; printf("\n"); string = inp_string; while (string[0] == ' ') { string++; } ostring = string; nr = 0; if (string[0] == 'h') { printf(" nr : selects an index group by number or quoted string.\n"); printf(" The string is first matched against the whole group name,\n"); printf(" then against the beginning and finally against an\n"); printf(" arbitrary substring. A multiple match is an error.\n"); printf(" 'a' nr1 [nr2 ...] : selects atoms, atom numbering starts at 1.\n"); printf(" 'a' nr1 - nr2 : selects atoms in the range from nr1 to nr2.\n"); printf(" 'a' name1[*] [name2[*] ...] : selects atoms by name(s), '?' matches any char,\n"); printf(" wildcard '*' allowed at the end of a name.\n"); printf(" 't' type1[*] [type2[*] ...] : as 'a', but for type, run input file required.\n"); printf(" 'r' nr1[ic1] [nr2[ic2] ...] : selects residues by number and insertion code.\n"); printf(" 'r' nr1 - nr2 : selects residues in the range from nr1 to nr2.\n"); printf(" 'r' name1[*] [name2[*] ...] : as 'a', but for residue names.\n"); printf(" 'ri' nr1 - nr2 : selects residue indices, 1-indexed, (as opposed to numbers) in the range from nr1 to nr2.\n"); printf(" 'chain' ch1 [ch2 ...] : selects atoms by chain identifier(s),\n"); printf(" not available with a .gro file as input.\n"); printf(" ! : takes the complement of a group with respect to all\n"); printf(" the atoms in the input file.\n"); printf(" & | : AND and OR, can be placed between any of the options\n"); printf(" above, the input is processed from left to right.\n"); printf(" 'name' nr name : rename group nr to name.\n"); printf(" 'del' nr1 [- nr2] : deletes one group or groups in the range from nr1 to nr2.\n"); printf(" 'keep' nr : deletes all groups except nr.\n"); printf(" 'case' : make all name compares case (in)sensitive.\n"); printf(" 'splitch' nr : split group into chains using CA distances.\n"); printf(" 'splitres' nr : split group into residues.\n"); printf(" 'splitat' nr : split group into atoms.\n"); printf(" 'res' nr : interpret numbers in group as residue numbers\n"); printf(" Enter : list the currently defined groups and commands\n"); printf(" 'l' : list the residues.\n"); printf(" 'h' : show this help.\n"); printf(" 'q' : save and quit.\n"); printf("\n"); printf(" Examples:\n"); printf(" > 2 | 4 & r 3-5\n"); printf(" selects all atoms from group 2 and 4 that have residue numbers 3, 4 or 5\n"); printf(" > a C* & !a C CA\n"); printf(" selects all atoms starting with 'C' but not the atoms 'C' and 'CA'\n"); printf(" > \"protein\" & ! \"backb\"\n"); printf(" selects all atoms that are in group 'protein' and not in group 'backbone'\n"); if (bVerbose) { printf("\npress Enter "); getchar(); } } else if (strncmp(string, "del", 3) == 0) { string += 3; if (parse_int(&string, &sel_nr)) { while (string[0] == ' ') { string++; } if (string[0] == '-') { string++; parse_int(&string, &sel_nr2); } else { sel_nr2 = NOTSET; } while (string[0] == ' ') { string++; } if (string[0] == '\0') { remove_group(sel_nr, sel_nr2, block, gn); } else { printf("\nSyntax error: \"%s\"\n", string); } } } else if (strncmp(string, "keep", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { remove_group(sel_nr+1, block->nr-1, block, gn); remove_group(0, sel_nr-1, block, gn); } } else if (strncmp(string, "name", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { if ((sel_nr >= 0) && (sel_nr < block->nr)) { sscanf(string, "%s", gname); sfree((*gn)[sel_nr]); (*gn)[sel_nr] = strdup(gname); } } } else if (strncmp(string, "case", 4) == 0) { bCase = !bCase; printf("Switched to case %s\n", bCase ? "sensitive" : "insensitive"); } else if (string[0] == 'v') { bVerbose = !bVerbose; printf("Turned verbose %s\n", bVerbose ? "on" : "off"); } else if (string[0] == 'l') { if (check_have_atoms(atoms, ostring) ) { list_residues(atoms); } } else if (strncmp(string, "splitch", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_chain(atoms, x, sel_nr, block, gn); } } else if (strncmp(string, "splitres", 8) == 0) { string += 8; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, FALSE); } } else if (strncmp(string, "splitat", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, TRUE); } } else if (string[0] == '\0') { bPrintOnce = TRUE; } else if (string[0] != 'q') { nr1 = -1; nr2 = -1; if (parse_entry(&string, natoms, atoms, block, gn, &nr, index, gname)) { do { while (string[0] == ' ') { string++; } bAnd = FALSE; bOr = FALSE; if (string[0] == '&') { bAnd = TRUE; } else if (string[0] == '|') { bOr = TRUE; } if (bAnd || bOr) { string++; nr1 = nr; for (i = 0; i < nr; i++) { index1[i] = index[i]; } strcpy(gname1, gname); if (parse_entry(&string, natoms, atoms, block, gn, &nr2, index2, gname2)) { if (bOr) { or_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_%s", gname1, gname2); } else { and_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_&_%s", gname1, gname2); } } } } while (bAnd || bOr); } while (string[0] == ' ') { string++; } if (string[0]) { printf("\nSyntax error: \"%s\"\n", string); } else if (nr > 0) { copy2block(nr, index, block); srenew(*gn, block->nr); newgroup = block->nr-1; (*gn)[newgroup] = strdup(gname); } else { printf("Group is empty\n"); } } } while (string[0] != 'q'); sfree(index); sfree(index1); sfree(index2); }
int gmx_saltbr(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots the distance between all combination of charged groups", "as a function of time. The groups are combined in different ways.", "A minimum distance can be given (i.e. a cut-off), such that groups", "that are never closer than that distance will not be plotted.[PAR]", "Output will be in a number of fixed filenames, [TT]min-min.xvg[tt], [TT]plus-min.xvg[tt]", "and [TT]plus-plus.xvg[tt], or files for every individual ion pair if the [TT]-sep[tt]", "option is selected. In this case, files are named as [TT]sb-(Resname)(Resnr)-(Atomnr)[tt].", "There may be [BB]many[bb] such files." }; static gmx_bool bSep = FALSE; static real truncate = 1000.0; t_pargs pa[] = { { "-t", FALSE, etREAL, {&truncate}, "Groups that are never closer than this distance are not plotted" }, { "-sep", FALSE, etBOOL, {&bSep}, "Use separate files for each interaction (may be MANY)" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPR, NULL, NULL, ffREAD }, }; #define NFILE asize(fnm) FILE *out[3], *fp; static const char *title[3] = { "Distance between positively charged groups", "Distance between negatively charged groups", "Distance between oppositely charged groups" }; static const char *fn[3] = { "plus-plus.xvg", "min-min.xvg", "plus-min.xvg" }; int nset[3] = {0, 0, 0}; t_topology *top; int ePBC; char *buf; t_trxstatus *status; int i, j, k, m, nnn, teller, ncg; real t, *time, qi, qj; t_charge *cg; real ***cgdist; int **nWithin; t_pbc pbc; rvec *x; matrix box; gmx_output_env_t *oenv; if (!parse_common_args(&argc, argv, PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); cg = mk_charge(&top->atoms, &(top->cgs), &ncg); snew(cgdist, ncg); snew(nWithin, ncg); for (i = 0; (i < ncg); i++) { snew(cgdist[i], ncg); snew(nWithin[i], ncg); } read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); teller = 0; time = NULL; do { srenew(time, teller+1); time[teller] = t; set_pbc(&pbc, ePBC, box); for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { srenew(cgdist[i][j], teller+1); cgdist[i][j][teller] = calc_dist(&pbc, x, &(top->cgs), cg[i].cg, cg[j].cg); if (cgdist[i][j][teller] < truncate) { nWithin[i][j] = 1; } } } teller++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); close_trj(status); if (bSep) { snew(buf, 256); for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { if (nWithin[i][j]) { sprintf(buf, "sb-%s:%s.xvg", cg[i].label, cg[j].label); fp = xvgropen(buf, buf, "Time (ps)", "Distance (nm)", oenv); for (k = 0; (k < teller); k++) { fprintf(fp, "%10g %10g\n", time[k], cgdist[i][j][k]); } xvgrclose(fp); } } } sfree(buf); } else { for (m = 0; (m < 3); m++) { out[m] = xvgropen(fn[m], title[m], "Time (ps)", "Distance (nm)", oenv); } snew(buf, 256); for (i = 0; (i < ncg); i++) { qi = cg[i].q; for (j = i+1; (j < ncg); j++) { qj = cg[j].q; if (nWithin[i][j]) { sprintf(buf, "%s:%s", cg[i].label, cg[j].label); if (qi*qj < 0) { nnn = 2; } else if (qi+qj > 0) { nnn = 0; } else { nnn = 1; } if (nset[nnn] == 0) { xvgr_legend(out[nnn], 1, (const char**)&buf, oenv); } else { if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(out[nnn], "@ legend string %d \"%s\"\n", nset[nnn], buf); } else if (output_env_get_xvg_format(oenv) == exvgXMGRACE) { fprintf(out[nnn], "@ s%d legend \"%s\"\n", nset[nnn], buf); } } nset[nnn]++; nWithin[i][j] = nnn+1; } } } for (k = 0; (k < teller); k++) { for (m = 0; (m < 3); m++) { fprintf(out[m], "%10g", time[k]); } for (i = 0; (i < ncg); i++) { for (j = i+1; (j < ncg); j++) { nnn = nWithin[i][j]; if (nnn > 0) { fprintf(out[nnn-1], " %10g", cgdist[i][j][k]); } } } for (m = 0; (m < 3); m++) { fprintf(out[m], "\n"); } } for (m = 0; (m < 3); m++) { xvgrclose(out[m]); if (nset[m] == 0) { remove(fn[m]); } } } return 0; }
int gmx_make_ndx(int argc, char *argv[]) { const char *desc[] = { "Index groups are necessary for almost every GROMACS program.", "All these programs can generate default index groups. You ONLY", "have to use [THISMODULE] when you need SPECIAL index groups.", "There is a default index group for the whole system, 9 default", "index groups for proteins, and a default index group", "is generated for every other residue name.[PAR]", "When no index file is supplied, also [THISMODULE] will generate the", "default groups.", "With the index editor you can select on atom, residue and chain names", "and numbers.", "When a run input file is supplied you can also select on atom type.", "You can use NOT, AND and OR, you can split groups", "into chains, residues or atoms. You can delete and rename groups.[PAR]", "The atom numbering in the editor and the index file starts at 1.[PAR]", "The [TT]-twin[tt] switch duplicates all index groups with an offset of", "[TT]-natoms[tt], which is useful for Computational Electrophysiology", "double-layer membrane setups." }; static int natoms = 0; static gmx_bool bVerbose = FALSE; static gmx_bool bDuplicate = FALSE; t_pargs pa[] = { { "-natoms", FALSE, etINT, {&natoms}, "set number of atoms (default: read from coordinate or index file)" }, { "-twin", FALSE, etBOOL, {&bDuplicate}, "Duplicate all index groups with an offset of -natoms" }, { "-verbose", FALSE, etBOOL, {&bVerbose}, "HIDDENVerbose output" } }; #define NPA asize(pa) output_env_t oenv; char title[STRLEN]; int nndxin; const char *stxfile; char **ndxinfiles; const char *ndxoutfile; gmx_bool bNatoms; int i, j; t_atoms *atoms; rvec *x, *v; int ePBC; matrix box; t_blocka *block, *block2; char **gnames, **gnames2; t_filenm fnm[] = { { efSTX, "-f", NULL, ffOPTRD }, { efNDX, "-n", NULL, ffOPTRDMULT }, { efNDX, "-o", NULL, ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, 0, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } stxfile = ftp2fn_null(efSTX, NFILE, fnm); if (opt2bSet("-n", NFILE, fnm)) { nndxin = opt2fns(&ndxinfiles, "-n", NFILE, fnm); } else { nndxin = 0; } ndxoutfile = opt2fn("-o", NFILE, fnm); bNatoms = opt2parg_bSet("-natoms", NPA, pa); if (!stxfile && !nndxin) { gmx_fatal(FARGS, "No input files (structure or index)"); } if (stxfile) { snew(atoms, 1); get_stx_coordnum(stxfile, &(atoms->nr)); init_t_atoms(atoms, atoms->nr, TRUE); snew(x, atoms->nr); snew(v, atoms->nr); fprintf(stderr, "\nReading structure file\n"); read_stx_conf(stxfile, title, atoms, x, v, &ePBC, box); natoms = atoms->nr; bNatoms = TRUE; } else { atoms = NULL; x = NULL; } /* read input file(s) */ block = new_blocka(); gnames = NULL; printf("Going to read %d old index file(s)\n", nndxin); if (nndxin) { for (i = 0; i < nndxin; i++) { block2 = init_index(ndxinfiles[i], &gnames2); srenew(gnames, block->nr+block2->nr); for (j = 0; j < block2->nr; j++) { gnames[block->nr+j] = gnames2[j]; } sfree(gnames2); merge_blocks(block, block2); sfree(block2->a); sfree(block2->index); /* done_block(block2); */ sfree(block2); } } else { snew(gnames, 1); analyse(atoms, block, &gnames, FALSE, TRUE); } if (!bNatoms) { natoms = block2natoms(block); printf("Counted atom numbers up to %d in index file\n", natoms); } edit_index(natoms, atoms, x, block, &gnames, bVerbose); write_index(ndxoutfile, block, gnames, bDuplicate, natoms); return 0; }
static void dd_pmeredist_pos_coeffs(struct gmx_pme_t *pme, int n, gmx_bool bX, rvec *x, real *data, pme_atomcomm_t *atc) { int *commnode, *buf_index; int nnodes_comm, i, nsend, local_pos, buf_pos, node, scount, rcount; commnode = atc->node_dest; buf_index = atc->buf_index; nnodes_comm = min(2*atc->maxshift, atc->nslab-1); nsend = 0; for (i = 0; i < nnodes_comm; i++) { buf_index[commnode[i]] = nsend; nsend += atc->count[commnode[i]]; } if (bX) { if (atc->count[atc->nodeid] + nsend != n) { gmx_fatal(FARGS, "%d particles communicated to PME rank %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n" "This usually means that your system is not well equilibrated.", n - (atc->count[atc->nodeid] + nsend), pme->nodeid, 'x'+atc->dimind); } if (nsend > pme->buf_nalloc) { pme->buf_nalloc = over_alloc_dd(nsend); srenew(pme->bufv, pme->buf_nalloc); srenew(pme->bufr, pme->buf_nalloc); } atc->n = atc->count[atc->nodeid]; for (i = 0; i < nnodes_comm; i++) { scount = atc->count[commnode[i]]; /* Communicate the count */ if (debug) { fprintf(debug, "dimind %d PME rank %d send to rank %d: %d\n", atc->dimind, atc->nodeid, commnode[i], scount); } pme_dd_sendrecv(atc, FALSE, i, &scount, sizeof(int), &atc->rcount[i], sizeof(int)); atc->n += atc->rcount[i]; } pme_realloc_atomcomm_things(atc); } local_pos = 0; for (i = 0; i < n; i++) { node = atc->pd[i]; if (node == atc->nodeid) { /* Copy direct to the receive buffer */ if (bX) { copy_rvec(x[i], atc->x[local_pos]); } atc->coefficient[local_pos] = data[i]; local_pos++; } else { /* Copy to the send buffer */ if (bX) { copy_rvec(x[i], pme->bufv[buf_index[node]]); } pme->bufr[buf_index[node]] = data[i]; buf_index[node]++; } } buf_pos = 0; for (i = 0; i < nnodes_comm; i++) { scount = atc->count[commnode[i]]; rcount = atc->rcount[i]; if (scount > 0 || rcount > 0) { if (bX) { /* Communicate the coordinates */ pme_dd_sendrecv(atc, FALSE, i, pme->bufv[buf_pos], scount*sizeof(rvec), atc->x[local_pos], rcount*sizeof(rvec)); } /* Communicate the coefficients */ pme_dd_sendrecv(atc, FALSE, i, pme->bufr+buf_pos, scount*sizeof(real), atc->coefficient+local_pos, rcount*sizeof(real)); buf_pos += scount; local_pos += atc->rcount[i]; } } }
static int split_chain(t_atoms *atoms, rvec *x, int sel_nr, t_blocka *block, char ***gn) { char buf[STRLEN]; int j, nchain; atom_id i, a, natoms, *start = NULL, *end = NULL, ca_start, ca_end; rvec vec; natoms = atoms->nr; nchain = 0; ca_start = 0; while (ca_start < natoms) { while ((ca_start < natoms) && strcmp(*atoms->atomname[ca_start], "CA")) { ca_start++; } if (ca_start < natoms) { srenew(start, nchain+1); srenew(end, nchain+1); start[nchain] = ca_start; while ((start[nchain] > 0) && (atoms->atom[start[nchain]-1].resind == atoms->atom[ca_start].resind)) { start[nchain]--; } i = ca_start; do { ca_end = i; do { i++; } while ((i < natoms) && strcmp(*atoms->atomname[i], "CA")); if (i < natoms) { rvec_sub(x[ca_end], x[i], vec); } } while ((i < natoms) && (norm(vec) < 0.45)); end[nchain] = ca_end; while ((end[nchain]+1 < natoms) && (atoms->atom[end[nchain]+1].resind == atoms->atom[ca_end].resind)) { end[nchain]++; } ca_start = end[nchain]+1; nchain++; } } if (nchain == 1) { printf("Found 1 chain, will not split\n"); } else { printf("Found %d chains\n", nchain); } for (j = 0; j < nchain; j++) { printf("%d:%6d atoms (%d to %d)\n", j+1, end[j]-start[j]+1, start[j]+1, end[j]+1); } if (nchain > 1) { srenew(block->a, block->nra+block->index[sel_nr+1]-block->index[sel_nr]); for (j = 0; j < nchain; j++) { block->nr++; srenew(block->index, block->nr+1); srenew(*gn, block->nr); sprintf(buf, "%s_chain%d", (*gn)[sel_nr], j+1); (*gn)[block->nr-1] = strdup(buf); for (i = block->index[sel_nr]; i < block->index[sel_nr+1]; i++) { a = block->a[i]; if ((a >= start[j]) && (a <= end[j])) { block->a[block->nra] = a; block->nra++; } } block->index[block->nr] = block->nra; if (block->index[block->nr-1] == block->index[block->nr]) { remove_group(block->nr-1, NOTSET, block, gn); } } } sfree(start); sfree(end); return nchain; }
static void update_topol(const char *topinout, int p_num, int n_num, const char *p_name, const char *n_name, char *grpname) { FILE *fpin, *fpout; char buf[STRLEN], buf2[STRLEN], *temp, **mol_line = NULL; int line, i, nmol_line, sol_line, nsol_last; gmx_bool bMolecules; char temporary_filename[STRLEN]; printf("\nProcessing topology\n"); fpin = gmx_ffopen(topinout, "r"); std::strncpy(temporary_filename, "temp.topXXXXXX", STRLEN); fpout = gmx_fopen_temporary(temporary_filename); line = 0; bMolecules = FALSE; nmol_line = 0; sol_line = -1; nsol_last = -1; while (fgets(buf, STRLEN, fpin)) { line++; std::strcpy(buf2, buf); if ((temp = std::strchr(buf2, '\n')) != NULL) { temp[0] = '\0'; } ltrim(buf2); if (buf2[0] == '[') { buf2[0] = ' '; if ((temp = std::strchr(buf2, '\n')) != NULL) { temp[0] = '\0'; } rtrim(buf2); if (buf2[std::strlen(buf2)-1] == ']') { buf2[std::strlen(buf2)-1] = '\0'; ltrim(buf2); rtrim(buf2); bMolecules = (gmx_strcasecmp(buf2, "molecules") == 0); } fprintf(fpout, "%s", buf); } else if (!bMolecules) { fprintf(fpout, "%s", buf); } else { /* Check if this is a line with solvent molecules */ sscanf(buf, "%s", buf2); if (gmx_strcasecmp(buf2, grpname) == 0) { sol_line = nmol_line; sscanf(buf, "%*s %d", &nsol_last); } /* Store this molecules section line */ srenew(mol_line, nmol_line+1); mol_line[nmol_line] = gmx_strdup(buf); nmol_line++; } } gmx_ffclose(fpin); if (sol_line == -1) { gmx_ffclose(fpout); gmx_fatal(FARGS, "No line with moleculetype '%s' found the [ molecules ] section of file '%s'", grpname, topinout); } if (nsol_last < p_num+n_num) { gmx_ffclose(fpout); gmx_fatal(FARGS, "The last entry for moleculetype '%s' in the [ molecules ] section of file '%s' has less solvent molecules (%d) than were replaced (%d)", grpname, topinout, nsol_last, p_num+n_num); } /* Print all the molecule entries */ for (i = 0; i < nmol_line; i++) { if (i != sol_line) { fprintf(fpout, "%s", mol_line[i]); } else { printf("Replacing %d solute molecules in topology file (%s) " " by %d %s and %d %s ions.\n", p_num+n_num, topinout, p_num, p_name, n_num, n_name); nsol_last -= p_num + n_num; if (nsol_last > 0) { fprintf(fpout, "%-10s %d\n", grpname, nsol_last); } if (p_num > 0) { fprintf(fpout, "%-15s %d\n", p_name, p_num); } if (n_num > 0) { fprintf(fpout, "%-15s %d\n", n_name, n_num); } } } gmx_ffclose(fpout); make_backup(topinout); gmx_file_rename(temporary_filename, topinout); }
/*! * \param[in,out] g Index group structure. * * Resizes the memory allocated for holding the indices such that the * current contents fit. */ void gmx_ana_index_squeeze(gmx_ana_index_t *g) { srenew(g->index, g->isize); g->nalloc_index = g->isize; }
int gmx_genconf(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] multiplies a given coordinate file by simply stacking them", "on top of each other, like a small child playing with wooden blocks.", "The program makes a grid of [IT]user-defined[it]", "proportions ([TT]-nbox[tt]), ", "and interspaces the grid point with an extra space [TT]-dist[tt].[PAR]", "When option [TT]-rot[tt] is used the program does not check for overlap", "between molecules on grid points. It is recommended to make the box in", "the input file at least as big as the coordinates + ", "van der Waals radius.[PAR]", "If the optional trajectory file is given, conformations are not", "generated, but read from this file and translated appropriately to", "build the grid." }; const char *bugs[] = { "The program should allow for random displacement of lattice points." }; int vol; t_atoms *atoms; /* list with all atoms */ rvec *x, *xx, *v; /* coordinates? */ real t; vec4 *xrot, *vrot; int ePBC; matrix box, boxx; /* box length matrix */ rvec shift; int natoms; /* number of atoms in one molecule */ int nres; /* number of molecules? */ int i, j, k, l, m, ndx, nrdx, nx, ny, nz; t_trxstatus *status; gmx_bool bTRX; output_env_t oenv; gmx_rng_t rng; t_filenm fnm[] = { { efSTX, "-f", "conf", ffREAD }, { efSTO, "-o", "out", ffWRITE }, { efTRX, "-trj", NULL, ffOPTRD } }; #define NFILE asize(fnm) static rvec nrbox = {1, 1, 1}; static int seed = 0; /* seed for random number generator */ static int nmolat = 3; static int nblock = 1; static gmx_bool bShuffle = FALSE; static gmx_bool bSort = FALSE; static gmx_bool bRandom = FALSE; /* False: no random rotations */ static gmx_bool bRenum = TRUE; /* renumber residues */ static rvec dist = {0, 0, 0}; /* space added between molecules ? */ static rvec max_rot = {180, 180, 180}; /* maximum rotation */ t_pargs pa[] = { { "-nbox", FALSE, etRVEC, {nrbox}, "Number of boxes" }, { "-dist", FALSE, etRVEC, {dist}, "Distance between boxes" }, { "-seed", FALSE, etINT, {&seed}, "Random generator seed, if 0 generated from the time" }, { "-rot", FALSE, etBOOL, {&bRandom}, "Randomly rotate conformations" }, { "-shuffle", FALSE, etBOOL, {&bShuffle}, "Random shuffling of molecules" }, { "-sort", FALSE, etBOOL, {&bSort}, "Sort molecules on X coord" }, { "-block", FALSE, etINT, {&nblock}, "Divide the box in blocks on this number of cpus" }, { "-nmolat", FALSE, etINT, {&nmolat}, "Number of atoms per molecule, assumed to start from 0. " "If you set this wrong, it will screw up your system!" }, { "-maxrot", FALSE, etRVEC, {max_rot}, "Maximum random rotation" }, { "-renumber", FALSE, etBOOL, {&bRenum}, "Renumber residues" } }; if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv)) { return 0; } if (seed == 0) { rng = gmx_rng_init(gmx_rng_make_seed()); } else { rng = gmx_rng_init(seed); } bTRX = ftp2bSet(efTRX, NFILE, fnm); nx = (int)(nrbox[XX]+0.5); ny = (int)(nrbox[YY]+0.5); nz = (int)(nrbox[ZZ]+0.5); if ((nx <= 0) || (ny <= 0) || (nz <= 0)) { gmx_fatal(FARGS, "Number of boxes (-nbox) should be larger than zero"); } if ((nmolat <= 0) && bShuffle) { gmx_fatal(FARGS, "Can not shuffle if the molecules only have %d atoms", nmolat); } vol = nx*ny*nz; /* calculate volume in grid points (= nr. molecules) */ t_topology *top; snew(top, 1); atoms = &top->atoms; read_tps_conf(opt2fn("-f", NFILE, fnm), top, &ePBC, &x, &v, box, FALSE); natoms = atoms->nr; nres = atoms->nres; /* nr of residues in one element? */ /* make space for all the atoms */ add_t_atoms(atoms, natoms*(vol-1), nres*(vol-1)); srenew(x, natoms*vol); /* get space for coordinates of all atoms */ srenew(v, natoms*vol); /* velocities. not really needed? */ snew(xrot, natoms); /* get space for rotation matrix? */ snew(vrot, natoms); if (bTRX) { if (!read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &xx, boxx)) { gmx_fatal(FARGS, "No atoms in trajectory %s", ftp2fn(efTRX, NFILE, fnm)); } } else { snew(xx, natoms); for (i = 0; i < natoms; i++) { copy_rvec(x[i], xx[i]); } } for (k = 0; (k < nz); k++) /* loop over all gridpositions */ { shift[ZZ] = k*(dist[ZZ]+box[ZZ][ZZ]); for (j = 0; (j < ny); j++) { shift[YY] = j*(dist[YY]+box[YY][YY])+k*box[ZZ][YY]; for (i = 0; (i < nx); i++) { shift[XX] = i*(dist[XX]+box[XX][XX])+j*box[YY][XX]+k*box[ZZ][XX]; ndx = (i*ny*nz+j*nz+k)*natoms; nrdx = (i*ny*nz+j*nz+k)*nres; /* Random rotation on input coords */ if (bRandom) { rand_rot(natoms, xx, v, xrot, vrot, rng, max_rot); } for (l = 0; (l < natoms); l++) { for (m = 0; (m < DIM); m++) { if (bRandom) { x[ndx+l][m] = xrot[l][m]; v[ndx+l][m] = vrot[l][m]; } else { x[ndx+l][m] = xx[l][m]; v[ndx+l][m] = v[l][m]; } } if (ePBC == epbcSCREW && i % 2 == 1) { /* Rotate around x axis */ for (m = YY; m <= ZZ; m++) { x[ndx+l][m] = box[YY][m] + box[ZZ][m] - x[ndx+l][m]; v[ndx+l][m] = -v[ndx+l][m]; } } for (m = 0; (m < DIM); m++) { x[ndx+l][m] += shift[m]; } atoms->atom[ndx+l].resind = nrdx + atoms->atom[l].resind; atoms->atomname[ndx+l] = atoms->atomname[l]; } for (l = 0; (l < nres); l++) { atoms->resinfo[nrdx+l] = atoms->resinfo[l]; if (bRenum) { atoms->resinfo[nrdx+l].nr += nrdx; } } if (bTRX) { if (!read_next_x(oenv, status, &t, xx, boxx) && ((i+1)*(j+1)*(k+1) < vol)) { gmx_fatal(FARGS, "Not enough frames in trajectory"); } } } } } if (bTRX) { close_trj(status); } /* make box bigger */ for (m = 0; (m < DIM); m++) { box[m][m] += dist[m]; } svmul(nx, box[XX], box[XX]); svmul(ny, box[YY], box[YY]); svmul(nz, box[ZZ], box[ZZ]); if (ePBC == epbcSCREW && nx % 2 == 0) { /* With an even number of boxes in x we can forgot about the screw */ ePBC = epbcXYZ; } /* move_x(natoms*vol,x,box); */ /* put atoms in box? */ atoms->nr *= vol; atoms->nres *= vol; /*depending on how you look at it, this is either a nasty hack or the way it should work*/ if (bRenum) { for (i = 0; i < atoms->nres; i++) { atoms->resinfo[i].nr = i+1; } } if (bShuffle) { randwater(0, atoms->nr/nmolat, nmolat, x, v, rng); } else if (bSort) { sortwater(0, atoms->nr/nmolat, nmolat, x, v); } else if (opt2parg_bSet("-block", asize(pa), pa)) { mkcompact(0, atoms->nr/nmolat, nmolat, x, v, nblock, box); } gmx_rng_destroy(rng); write_sto_conf(opt2fn("-o", NFILE, fnm), *top->name, atoms, x, v, ePBC, box); return 0; }
/*! * \param[in,out] t Output block. * \param[in] top Topology structure * (only used if \p type is \ref INDEX_RES or \ref INDEX_MOL, can be NULL * otherwise). * \param[in] g Index group * (can be NULL if \p type is \ref INDEX_UNKNOWN). * \param[in] type Type of partitioning to make. * \param[in] bComplete * If true, the index group is expanded to include any residue/molecule * (depending on \p type) that is partially contained in the group. * If \p type is not INDEX_RES or INDEX_MOL, this has no effect. * * \p m should have been initialized somehow (calloc() is enough) unless * \p type is INDEX_UNKNOWN. * \p g should be sorted. */ void gmx_ana_index_make_block(t_blocka *t, t_topology *top, gmx_ana_index_t *g, e_index_t type, bool bComplete) { int i, j, ai; int id, cur; if (type == INDEX_UNKNOWN) { t->nr = 1; snew(t->index, 2); t->nalloc_index = 2; t->index[0] = 0; t->index[1] = 0; t->nra = 0; t->a = NULL; t->nalloc_a = 0; return; } /* bComplete only does something for INDEX_RES or INDEX_MOL, so turn it * off otherwise. */ if (type != INDEX_RES && type != INDEX_MOL) { bComplete = false; } /* Allocate memory for the atom array and fill it unless we are using * completion. */ if (bComplete) { t->nra = 0; /* We may allocate some extra memory here because we don't know in * advance how much will be needed. */ if (t->nalloc_a < top->atoms.nr) { srenew(t->a, top->atoms.nr); t->nalloc_a = top->atoms.nr; } } else { t->nra = g->isize; if (t->nalloc_a < g->isize) { srenew(t->a, g->isize); t->nalloc_a = g->isize; } std::memcpy(t->a, g->index, g->isize*sizeof(*(t->a))); } /* Allocate memory for the block index. We don't know in advance * how much will be needed, so we allocate some extra and free it in the * end. */ if (t->nalloc_index < g->isize + 1) { srenew(t->index, g->isize + 1); t->nalloc_index = g->isize + 1; } /* Clear counters */ t->nr = 0; j = 0; /* j is used by residue completion for the first atom not stored */ id = cur = -1; for (i = 0; i < g->isize; ++i) { ai = g->index[i]; /* Find the ID number of the atom/residue/molecule corresponding to * atom ai. */ switch (type) { case INDEX_ATOM: id = ai; break; case INDEX_RES: id = top->atoms.atom[ai].resind; break; case INDEX_MOL: while (ai >= top->mols.index[id+1]) { id++; } break; case INDEX_UNKNOWN: /* Should not occur */ case INDEX_ALL: id = 0; break; } /* If this is the first atom in a new block, initialize the block. */ if (id != cur) { if (bComplete) { /* For completion, we first set the start of the block. */ t->index[t->nr++] = t->nra; /* And then we find all the atoms that should be included. */ switch (type) { case INDEX_RES: while (top->atoms.atom[j].resind != id) { ++j; } while (j < top->atoms.nr && top->atoms.atom[j].resind == id) { t->a[t->nra++] = j; ++j; } break; case INDEX_MOL: for (j = top->mols.index[id]; j < top->mols.index[id+1]; ++j) { t->a[t->nra++] = j; } break; default: /* Should not be reached */ gmx_bug("internal error"); break; } } else { /* If not using completion, simply store the start of the block. */ t->index[t->nr++] = i; } cur = id; } } /* Set the end of the last block */ t->index[t->nr] = t->nra; /* Free any unnecessary memory */ srenew(t->index, t->nr+1); t->nalloc_index = t->nr+1; if (bComplete) { srenew(t->a, t->nra); t->nalloc_a = t->nra; } }
static int low_fflib_search_file_end(const char *ffdir, gmx_bool bAddCWD, const char *file_end, gmx_bool bFatalError, char ***filenames, char ***filenames_short) { char **fns = NULL, **fns_short = NULL; int n = 0; try { std::vector<std::string> libPaths; bool bEnvIsSet = false; if (ffdir != NULL) { /* Search ffdir in current dir and library dirs */ libPaths.push_back(gmxlibfn(ffdir)); } else { /* GMXLIB can be a path now */ if (bAddCWD) { libPaths.push_back("."); } const char *lib = getenv("GMXLIB"); if (lib != NULL) { bEnvIsSet = true; gmx::Path::splitPathEnvironment(lib, &libPaths); } else { libPaths.push_back(gmx::getProgramContext().defaultLibraryDataPath()); } } const int len_fe = strlen(file_end); std::vector<std::string>::const_iterator i; for (i = libPaths.begin(); i != libPaths.end(); ++i) { const char *dir = i->c_str(); gmx_directory_t dirhandle; const int rc = gmx_directory_open(&dirhandle, dir); if (rc == 0) { char nextname[STRLEN]; int n_thisdir = 0; while (gmx_directory_nextfile(dirhandle, nextname, STRLEN-1) == 0) { nextname[STRLEN-1] = 0; if (debug) { fprintf(debug, "dir '%s' %d file '%s'\n", dir, n_thisdir, nextname); } const int len_name = strlen(nextname); /* What about case sensitivity? */ if (len_name >= len_fe && strcmp(nextname+len_name-len_fe, file_end) == 0) { char fn_dir[GMX_PATH_MAX]; /* We have a match */ srenew(fns, n+1); sprintf(fn_dir, "%s%c%s", dir, DIR_SEPARATOR, nextname); /* Copy the file name, possibly including the path. */ fns[n] = gmx_strdup(fn_dir); if (ffdir == NULL) { /* We are searching in a path. * Use the relative path when we use share/top * from the installation. * Add the full path when we use the current * working directory of GMXLIB. */ srenew(fns_short, n+1); if (strcmp(dir, ".") == 0 || bEnvIsSet) { fns_short[n] = gmx_strdup(fn_dir); } else { fns_short[n] = gmx_strdup(nextname); } } n++; n_thisdir++; } } gmx_directory_close(dirhandle); sort_filenames(n_thisdir, fns+n-n_thisdir, fns_short == NULL ? NULL : fns_short+n-n_thisdir); } } } GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR; if (n == 0 && bFatalError) { if (ffdir != NULL) { gmx_fatal(FARGS, "Could not find any files ending on '%s' in the force field directory '%s'", file_end, ffdir); } else { gmx_fatal(FARGS, "Could not find any files ending on '%s' in the current directory or the GROMACS library search path", file_end); } } *filenames = fns; if (ffdir == NULL) { *filenames_short = fns_short; } return n; }
int sscan_list(int *list[], const char *str, const char *listname) { /*this routine scans a string of the form 1,3-6,9 and returns the selected numbers (in this case 1 3 4 5 6 9) in NULL-terminated array of integers. memory for this list will be allocated in this routine -- sscan_list expects *list to be a NULL-Pointer listname is a string used in the errormessage*/ int i, istep; char c; char *pos, *startpos, *step; int n = strlen(str); /*enums to define the different lexical stati */ enum { sBefore, sNumber, sMinus, sRange, sZero, sSmaller, sError, sSteppedRange }; int status = sBefore; /*status of the deterministic automat to scan str */ int number = 0; int end_number = 0; char *start = NULL; /*holds the string of the number behind a ','*/ char *end = NULL; /*holds the string of the number behind a '-' */ int nvecs = 0; /* counts the number of vectors in the list*/ step = NULL; snew(pos, n+4); startpos = pos; strcpy(pos, str); pos[n] = ','; pos[n+1] = '1'; pos[n+2] = '\0'; *list = NULL; while ((c = *pos) != 0) { switch (status) { /* expect a number */ case sBefore: if (isdigit(c)) { start = pos; status = sNumber; break; } else { status = sError; } break; /* have read a number, expect ',' or '-' */ case sNumber: if (c == ',') { /*store number*/ srenew(*list, nvecs+1); (*list)[nvecs++] = number = strtol(start, NULL, 10); status = sBefore; if (number == 0) { status = sZero; } break; } else if (c == '-') { status = sMinus; break; } else if (isdigit(c)) { break; } else { status = sError; } break; /* have read a '-' -> expect a number */ case sMinus: if (isdigit(c)) { end = pos; status = sRange; break; } else { status = sError; } break; case sSteppedRange: if (isdigit(c)) { if (step) { status = sError; break; } else { step = pos; } status = sRange; break; } else { status = sError; } break; /* have read the number after a minus, expect ',' or ':' */ case sRange: if (c == ',') { /*store numbers*/ end_number = strtol(end, NULL, 10); number = strtol(start, NULL, 10); status = sBefore; if (number == 0) { status = sZero; break; } if (end_number <= number) { status = sSmaller; break; } srenew(*list, nvecs+end_number-number+1); if (step) { istep = strtol(step, NULL, 10); step = NULL; } else { istep = 1; } for (i = number; i <= end_number; i += istep) { (*list)[nvecs++] = i; } break; } else if (c == ':') { status = sSteppedRange; break; } else if (isdigit(c)) { break; } else { status = sError; } break; /* format error occured */ case sError: gmx_fatal(FARGS, "Error in the list of eigenvectors for %s at pos %d with char %c", listname, pos-startpos, *(pos-1)); break; /* logical error occured */ case sZero: gmx_fatal(FARGS, "Error in the list of eigenvectors for %s at pos %d: eigenvector 0 is not valid", listname, pos-startpos); break; case sSmaller: gmx_fatal(FARGS, "Error in the list of eigenvectors for %s at pos %d: second index %d is not bigger than %d", listname, pos-startpos, end_number, number); break; } ++pos; /* read next character */ } /*scanner has finished */ /* append zero to list of eigenvectors */ srenew(*list, nvecs+1); (*list)[nvecs] = 0; sfree(startpos); return nvecs; } /*sscan_list*/