Esempio n. 1
0
static void generate_trial_conf(int atomCount, const rvec xin[],
                                const rvec offset, int enum_rot, gmx_rng_t rng,
                                rvec xout[])
{
    for (int i = 0; i < atomCount; ++i)
    {
        copy_rvec(xin[i], xout[i]);
    }
    real alfa = 0.0, beta = 0.0, gamma = 0.0;
    switch (enum_rot)
    {
        case en_rotXYZ:
            alfa  = 2*M_PI * gmx_rng_uniform_real(rng);
            beta  = 2*M_PI * gmx_rng_uniform_real(rng);
            gamma = 2*M_PI * gmx_rng_uniform_real(rng);
            break;
        case en_rotZ:
            alfa  = beta = 0.;
            gamma = 2*M_PI * gmx_rng_uniform_real(rng);
            break;
        case en_rotNone:
            alfa = beta = gamma = 0.;
            break;
    }
    if (enum_rot == en_rotXYZ || (enum_rot == en_rotZ))
    {
        rotate_conf(atomCount, xout, NULL, alfa, beta, gamma);
    }
    for (int i = 0; i < atomCount; ++i)
    {
        rvec_inc(xout[i], offset);
    }
}
Esempio n. 2
0
static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int seed,
                         t_atoms *atoms, rvec **x, real **r, int ePBC, matrix box,
                         gmx_atomprop_t aps, real r_distance, real rshell,
                         const output_env_t oenv)
{
    t_pbc            pbc;
    static  char    *title_insrt;
    t_atoms          atoms_insrt;
    rvec            *x_insrt, *x_n;
    real            *r_insrt;
    int              ePBC_insrt;
    matrix           box_insrt;
    int              i, mol, onr;
    real             alfa, beta, gamma;
    rvec             offset_x;
    int              trial;

    set_pbc(&pbc, ePBC, box);

    /* read number of atoms of insert molecules */
    get_stx_coordnum(mol_insrt, &atoms_insrt.nr);
    if (atoms_insrt.nr == 0)
    {
        gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
    }
    /* allocate memory for atom coordinates of insert molecules */
    snew(x_insrt, atoms_insrt.nr);
    snew(r_insrt, atoms_insrt.nr);
    snew(atoms_insrt.resinfo, atoms_insrt.nr);
    snew(atoms_insrt.atomname, atoms_insrt.nr);
    snew(atoms_insrt.atom, atoms_insrt.nr);
    atoms_insrt.pdbinfo = NULL;
    snew(x_n, atoms_insrt.nr);
    snew(title_insrt, STRLEN);

    /* read residue number, residue names, atomnames, coordinates etc. */
    fprintf(stderr, "Reading molecule configuration \n");
    read_stx_conf(mol_insrt, title_insrt, &atoms_insrt, x_insrt, NULL,
                  &ePBC_insrt, box_insrt);
    fprintf(stderr, "%s\nContaining %d atoms in %d residue\n",
            title_insrt, atoms_insrt.nr, atoms_insrt.nres);
    srenew(atoms_insrt.resinfo, atoms_insrt.nres);

    /* initialise van der waals arrays of insert molecules */
    mk_vdw(&atoms_insrt, r_insrt, aps, r_distance);

    srenew(atoms->resinfo, (atoms->nres+nmol_insrt*atoms_insrt.nres));
    srenew(atoms->atomname, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(atoms->atom, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*x, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*r, (atoms->nr+atoms_insrt.nr*nmol_insrt));

    trial = mol = 0;
    while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
    {
        fprintf(stderr, "\rTry %d", trial++);
        for (i = 0; (i < atoms_insrt.nr); i++)
        {
            copy_rvec(x_insrt[i], x_n[i]);
        }
        alfa  = 2*M_PI*rando( &seed);
        beta  = 2*M_PI*rando( &seed);
        gamma = 2*M_PI*rando( &seed);
        rotate_conf(atoms_insrt.nr, x_n, NULL, alfa, beta, gamma);
        offset_x[XX] = box[XX][XX]*rando(&seed);
        offset_x[YY] = box[YY][YY]*rando(&seed);
        offset_x[ZZ] = box[ZZ][ZZ]*rando(&seed);
        gen_box(0, atoms_insrt.nr, x_n, box_insrt, offset_x, TRUE);
        if (!in_box(&pbc, x_n[0]) || !in_box(&pbc, x_n[atoms_insrt.nr-1]))
        {
            continue;
        }
        onr = atoms->nr;

        add_conf(atoms, x, NULL, r, FALSE, ePBC, box, TRUE,
                 &atoms_insrt, x_n, NULL, r_insrt, FALSE, rshell, 0, oenv);

        if (atoms->nr == (atoms_insrt.nr+onr))
        {
            mol++;
            fprintf(stderr, " success (now %d atoms)!", atoms->nr);
        }
    }
    srenew(atoms->resinfo,  atoms->nres);
    srenew(atoms->atomname, atoms->nr);
    srenew(atoms->atom,     atoms->nr);
    srenew(*x,              atoms->nr);
    srenew(*r,              atoms->nr);

    fprintf(stderr, "\n");
    /* print number of molecules added */
    fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n",
            mol, nmol_insrt, *atoms_insrt.resinfo[0].name);

    return title_insrt;
}
Esempio n. 3
0
static char *insert_mols(char *mol_insrt,int nmol_insrt,int ntry,int seed,
			 t_atoms *atoms,rvec **x,real **r,int ePBC,matrix box,
			 gmx_atomprop_t aps,real r_distance,real rshell)
{
  t_pbc   pbc;
  static  char    *title_insrt;
  t_atoms atoms_insrt;
  rvec    *x_insrt,*x_n;
  real    *r_insrt;
  int     ePBC_insrt;
  matrix  box_insrt;
  int     i,mol,onr;
  real    alfa,beta,gamma;
  rvec    offset_x;
  int     try;
   
  set_pbc(&pbc,ePBC,box);
  
  /* read number of atoms of insert molecules */
  get_stx_coordnum(mol_insrt,&atoms_insrt.nr);
  if (atoms_insrt.nr == 0)
    gmx_fatal(FARGS,"No molecule in %s, please check your input\n",mol_insrt);
  /* allocate memory for atom coordinates of insert molecules */
  snew(x_insrt,atoms_insrt.nr);
  snew(r_insrt,atoms_insrt.nr);
  snew(atoms_insrt.resname,atoms_insrt.nr);
  snew(atoms_insrt.atomname,atoms_insrt.nr);
  snew(atoms_insrt.atom,atoms_insrt.nr);
  atoms_insrt.pdbinfo = NULL;
  snew(x_n,atoms_insrt.nr);
  snew(title_insrt,STRLEN);
  
  /* read residue number, residue names, atomnames, coordinates etc. */
  fprintf(stderr,"Reading molecule configuration \n");
  read_stx_conf(mol_insrt,title_insrt,&atoms_insrt,x_insrt,NULL,
		&ePBC_insrt,box_insrt);
  fprintf(stderr,"%s\nContaining %d atoms in %d residue\n",
	  title_insrt,atoms_insrt.nr,atoms_insrt.nres);
  srenew(atoms_insrt.resname,atoms_insrt.nres);  
    
  /* initialise van der waals arrays of insert molecules */
  mk_vdw(&atoms_insrt,r_insrt,aps,r_distance);

  srenew(atoms->resname,(atoms->nres+nmol_insrt));
  srenew(atoms->atomname,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(atoms->atom,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(*x,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  srenew(*r,(atoms->nr+atoms_insrt.nr*nmol_insrt));
  
  try=mol=0;
  while ((mol < nmol_insrt) && (try < ntry*nmol_insrt)) {
    fprintf(stderr,"\rTry %d",try++);
    for (i=0;(i<atoms_insrt.nr);i++) {
      if (atoms_insrt.atom[i].resnr!=0) 
	gmx_fatal(FARGS,"more then one residue in insert molecules\n"
		    "program terminated\n");
      copy_rvec(x_insrt[i],x_n[i]);
    }
    alfa=2*M_PI*rando(&seed);
    beta=2*M_PI*rando(&seed);
    gamma=2*M_PI*rando(&seed);
    rotate_conf(atoms_insrt.nr,x_n,NULL,alfa,beta,gamma);
    offset_x[XX]=box[XX][XX]*rando(&seed);
    offset_x[YY]=box[YY][YY]*rando(&seed);
    offset_x[ZZ]=box[ZZ][ZZ]*rando(&seed);
    gen_box(0,atoms_insrt.nr,x_n,box_insrt,offset_x,TRUE);
    if (!in_box(&pbc,x_n[0]) || !in_box(&pbc,x_n[atoms_insrt.nr-1]))
      continue;
    onr=atoms->nr;
    
    add_conf(atoms,x,NULL,r,FALSE,ePBC,box,TRUE,
	     &atoms_insrt,x_n,NULL,r_insrt,FALSE,rshell,0);
    
    if (atoms->nr==(atoms_insrt.nr+onr)) {
      mol++;
      fprintf(stderr," success (now %d atoms)!",atoms->nr);
    }
  }
  srenew(atoms->resname,  atoms->nres);
  srenew(atoms->atomname, atoms->nr);
  srenew(atoms->atom,     atoms->nr);
  srenew(*x,              atoms->nr);
  srenew(*r,              atoms->nr);
  
  fprintf(stderr,"\n");
  /* print number of molecules added */
  fprintf(stderr,"Added %d molecules (out of %d requested) of %s\n",
	  mol,nmol_insrt,*atoms_insrt.resname[0]); 
    
  return title_insrt;
}

static void add_solv(char *fn,t_atoms *atoms,rvec **x,rvec **v,real **r,
		     int ePBC,matrix box,
		     gmx_atomprop_t aps,real r_distance,int *atoms_added,
		     int *residues_added,real rshell,int max_sol)
{
  int     i,nmol;
  ivec    n_box;
  char    filename[STRLEN];
  char    title_solvt[STRLEN];
  t_atoms *atoms_solvt;
  rvec    *x_solvt,*v_solvt=NULL;
  real    *r_solvt;
  int     ePBC_solvt;
  matrix  box_solvt;
  int     onr,onres;

  strncpy(filename,libfn(fn),STRLEN);
  snew(atoms_solvt,1);
  get_stx_coordnum(filename,&(atoms_solvt->nr)); 
  if (atoms_solvt->nr == 0)
    gmx_fatal(FARGS,"No solvent in %s, please check your input\n",filename);
  snew(x_solvt,atoms_solvt->nr);
  if (v) snew(v_solvt,atoms_solvt->nr);
  snew(r_solvt,atoms_solvt->nr);
  snew(atoms_solvt->resname,atoms_solvt->nr);
  snew(atoms_solvt->atomname,atoms_solvt->nr);
  snew(atoms_solvt->atom,atoms_solvt->nr);
  atoms_solvt->pdbinfo = NULL;
  fprintf(stderr,"Reading solvent configuration%s\n",
	  v_solvt?" and velocities":"");
  read_stx_conf(filename,title_solvt,atoms_solvt,x_solvt,v_solvt,
		&ePBC_solvt,box_solvt);
  fprintf(stderr,"\"%s\"\n",title_solvt);
  fprintf(stderr,"solvent configuration contains %d atoms in %d residues\n",
	  atoms_solvt->nr,atoms_solvt->nres);
  fprintf(stderr,"\n");
  
  /* apply pbc for solvent configuration for whole molecules */
  rm_res_pbc(atoms_solvt,x_solvt,box_solvt);
  
  /* initialise van der waals arrays of solvent configuration */
  mk_vdw(atoms_solvt,r_solvt,aps,r_distance);
  
  /* calculate the box multiplication factors n_box[0...DIM] */
  nmol=1;
  for (i=0; (i < DIM);i++) {
    n_box[i] = 1;
    while (n_box[i]*box_solvt[i][i] < box[i][i])
      n_box[i]++;
    nmol*=n_box[i];
  }
  fprintf(stderr,"Will generate new solvent configuration of %dx%dx%d boxes\n",
	  n_box[XX],n_box[YY],n_box[ZZ]);
  
  /* realloc atoms_solvt for the new solvent configuration */
  srenew(atoms_solvt->resname,atoms_solvt->nres*nmol);
  srenew(atoms_solvt->atomname,atoms_solvt->nr*nmol);
  srenew(atoms_solvt->atom,atoms_solvt->nr*nmol);
  srenew(x_solvt,atoms_solvt->nr*nmol);
  if (v_solvt) srenew(v_solvt,atoms_solvt->nr*nmol);
  srenew(r_solvt,atoms_solvt->nr*nmol);
  
  /* generate a new solvent configuration */
  genconf(atoms_solvt,x_solvt,v_solvt,r_solvt,box_solvt,n_box);

#ifdef DEBUG
  print_stat(x_solvt,atoms_solvt->nr,box_solvt);
#endif
  
#ifdef DEBUG
  print_stat(x_solvt,atoms_solvt->nr,box_solvt);
#endif
  /* Sort the solvent mixture, not the protein... */
  sort_molecule(&atoms_solvt,x_solvt,v_solvt,r_solvt);
  
  /* add the two configurations */
  onr=atoms->nr;
  onres=atoms->nres;
  add_conf(atoms,x,v,r,TRUE,ePBC,box,FALSE,
	   atoms_solvt,x_solvt,v_solvt,r_solvt,TRUE,rshell,max_sol);
  *atoms_added=atoms->nr-onr;
  *residues_added=atoms->nres-onres;
  
  sfree(x_solvt);
  sfree(r_solvt);

  fprintf(stderr,"Generated solvent containing %d atoms in %d residues\n",
	  *atoms_added,*residues_added);
}
Esempio n. 4
0
void orient(int natom,rvec *x,rvec *v, rvec angle,matrix box)
{
  real longest,rij,rzi;
  int  i,j,m,max_i=0,max_j=0;
  rvec origin;
  int  temp;
  real alfa=0,beta=0,gamma=0;
  t_pbc pbc;

  set_pbc(&pbc,-1,box);

  /*first i am going to look for the longest atom-atom distance*/
  longest=dist2(&pbc,x[0],x[1]);
  i=0;
  j=1;
  for (i=0;(i<natom);i++) {
    for (j=0;(j<natom);j++) {
      rij=dist2(&pbc,x[i],x[j]);
      if (rij>longest) {
	max_i=i;
	max_j=j;
	longest=rij;
      }
    }
  }
  /* first check if x[max_i]<x[max_j] else swap*/
  if (x[max_i][2]>x[max_j][2]) {
    temp=max_i;
    max_i=max_j;
    max_j=temp;
  }
  
  /*set the origin to x[i]*/
  for(m=0;(m<DIM);m++) 
    origin[m]=x[max_i][m];
  for(i=0;(i<natom);i++)
    for(m=0;(m<DIM);m++)
      x[i][m]-=origin[m];
      
  /* calculate the rotation angles alfa(x_axis) and beta(y_axis)
   * the rotation angles must be calculated clockwise looking 
   * along the rotation axis to the origin*
   * alfa (x-axis)
   */
  alfa=atan(x[max_j][ZZ]/x[max_j][YY])-M_PI_2;
  beta=M_PI_2-atan(x[max_j][ZZ]/x[max_j][XX]);
  rotate_conf(natom,x,v,alfa,beta,gamma);
  
  /* now search the longest distance for rotation along the z_axis */
  longest=distance_to_z(x[0]);
  max_i=0;
  for (i=1;(i<natom);i++) {
    rzi=distance_to_z(x[i]);
    if (rzi>longest) {
      longest = rzi;
      max_i=i;
    }
  }
  gamma=atan(x[max_i][YY]/x[max_i][XX])-M_PI_2;
  rotate_conf(natom,x,v,0,0,gamma);
  angle[0]=alfa;
  angle[1]=beta;
  angle[2]=gamma;
} /*orient()*/
Esempio n. 5
0
int main(int argc,char *argv[])
{
    const char *desc[] = {
	"[TT]do_multiprot[tt] ", 
	"reads a trajectory file and aligns it to a reference structure  ",
	"each time frame",
	"calling the multiprot program. This allows you to use a reference",
	"structure whose sequence is different than that of the protein in the ",
	"trajectory, since the alignment is based on the geometry, not sequence.",
	"The output of [TT]do_multiprot[tt] includes the rmsd and the number of residues",
	"on which it was calculated.",
	"[PAR]",
	"An aligned trajectory file is generated with the [TT]-ox[tt] option.[PAR]",
	"With the [TT]-cr[tt] option, the number of hits in the alignment is given",
	"per residue. This number can be between 0 and the number of frames, and",
	"indicates the structural conservation of this residue.[PAR]",
	"If you do not have the [TT]multiprot[tt] program, get it. [TT]do_multiprot[tt] assumes", 
	"that the [TT]multiprot[tt] executable is [TT]/usr/local/bin/multiprot[tt]. If this is ",
	"not the case, then you should set an environment variable [BB]MULTIPROT[bb]", 
	"pointing to the [TT]multiprot[tt] executable, e.g.: [PAR]",
	"[TT]setenv MULTIPROT /usr/MultiProtInstall/multiprot.Linux[tt][PAR]",
	"Note that at the current implementation only binary alignment (your",
	"molecule to a reference) is supported. In addition, note that the ",
	"by default [TT]multiprot[tt] aligns the two proteins on their C-alpha carbons.",
	"and that this depends on the [TT]multiprot[tt] parameters which are not dealt ",
	"with here. Thus, the C-alpha carbons is expected to give the same "
	"results as choosing the whole protein and will be slightly faster.[PAR]",
	"For information about [TT]multiprot[tt], see:",
	"http://bioinfo3d.cs.tau.ac.il/MultiProt/.[PAR]"
    };
    static bool bVerbose;
    t_pargs pa[] = {
	{ "-v",  FALSE, etBOOL, {&bVerbose},
	  "HIDDENGenerate miles of useless information" }
    };
  
    const char *bugs[] = { 
	"The program is very slow, since multiprot is run externally"
    };
  
    t_trxstatus *status;
    t_trxstatus *trxout=NULL;
    FILE        *tapein,*fo,*frc,*tmpf,*out=NULL,*fres=NULL;
    const char  *fnRef;
    const char  *fn="2_sol.res";
    t_topology  top;
    int         ePBC;
    t_atoms     *atoms,ratoms,useatoms;
    t_trxframe  fr;
    t_pdbinfo   p;
    int         nres,nres2,nr0;
    real        t;
    int         i,j,natoms,nratoms,nframe=0,model_nr=-1;
    int         cur_res,prev_res;
    int         nout;
    t_countres  *countres=NULL;
    matrix      box,rbox;
    int         gnx;
    char        *grpnm,*ss_str; 
    atom_id     *index;
    rvec        *xp,*x,*xr;
    char        pdbfile[32],refpdb[256],title[256],rtitle[256],filemode[5];
    char        out_title[256];
    char        multiprot[256],*mptr;
    int         ftp;
    int         outftp=-1;
    real        rmsd;
    bool        bTrjout,bCountres;
    const char  *TrjoutFile=NULL;
    output_env_t oenv;
    static rvec translation={0,0,0},rotangles={0,0,0};
    gmx_rmpbc_t gpbc=NULL;
    
    t_filenm   fnm[] = {
	{ efTRX, "-f",   NULL,      ffREAD },
	{ efTPS, NULL,   NULL,      ffREAD },
	{ efNDX, NULL,   NULL,      ffOPTRD },
	{ efSTX, "-r",   NULL     , ffREAD },
	{ efXVG, "-o",  "rmss",     ffWRITE },
	{ efXVG, "-rc", "rescount", ffWRITE},
	{ efXVG, "-cr", "countres", ffOPTWR},
	{ efTRX, "-ox", "aligned",  ffOPTWR }
    };
#define NFILE asize(fnm)
    
    CopyRight(stderr,argv[0]);
    parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT,
		      NFILE,fnm, asize(pa),pa, asize(desc),desc,
		      asize(bugs),bugs,&oenv
	);
    fnRef=opt2fn("-r",NFILE,fnm);
    bTrjout = opt2bSet("-ox",NFILE,fnm);
    bCountres=  opt2bSet("-cr",NFILE,fnm);
    
    if (bTrjout) {
	TrjoutFile = opt2fn_null("-ox",NFILE,fnm);
    }
    
    read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xp,NULL,box,FALSE);
    gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
    atoms=&(top.atoms);

    ftp=fn2ftp(fnRef);
 
    get_stx_coordnum(fnRef,&nratoms);
    init_t_atoms(&ratoms,nratoms,TRUE);  
    snew(xr,nratoms);
    read_stx_conf(fnRef,rtitle,&ratoms,xr,NULL,&ePBC,rbox);
    
    if (bVerbose) {
	fprintf(stderr,"Read %d atoms\n",atoms->nr); 
	fprintf(stderr,"Read %d reference atoms\n",ratoms.nr); 
    }
    if (bCountres) {
	snew(countres,ratoms.nres);
	j=0;
	cur_res=0;
	for (i=0;i<ratoms.nr;i++) {
	    prev_res=cur_res;
	    cur_res=ratoms.atom[i].resind;
	    if (cur_res != prev_res) {
		countres[j].resnr=cur_res;
		countres[j].count=0;
		j++;
	    }
	}
    }
    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]].resind != nr0) {
	    nr0=atoms->atom[index[i]].resind;
	    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 {
	gmx_ffclose(tmpf);
    }

    if (ftp != efPDB) {
	strcpy(refpdb,"ddXXXXXX");
	gmx_tmpnam(refpdb);
	strcat(refpdb,".pdb");
	write_sto_conf(refpdb,rtitle,&ratoms,xr,NULL,ePBC,rbox);
    }
    else {
	strcpy(refpdb,fnRef);
    }

    if ((mptr=getenv("MULTIPROT")) == NULL) {
	mptr="/usr/local/bin/multiprot";
    }
    if (!gmx_fexist(mptr)) {
	gmx_fatal(FARGS,"MULTIPROT executable (%s) does not exist (use setenv MULTIPROT)",
		  mptr);
    }
    sprintf (multiprot,"%s %s %s > /dev/null %s",
	     mptr, refpdb, pdbfile, "2> /dev/null");
    
    if (bVerbose)
	fprintf(stderr,"multiprot cmd='%s'\n",multiprot);
    
    if (!read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_READ_X)) 
      	gmx_fatal(FARGS,"Could not read a frame from %s",ftp2fn(efTRX,NFILE,fnm));
    natoms = fr.natoms;

    if (bTrjout) {
	nout=natoms;
	/* open file now */
	outftp=fn2ftp(TrjoutFile);
	if (bVerbose)
	    fprintf(stderr,"Will write %s: %s\n",ftp2ext(ftp),ftp2desc(outftp));
	strcpy(filemode,"w");
	switch (outftp) {
	    case efXTC:
	    case efG87:
	    case efTRR:
	    case efTRJ:
		out=NULL;
		trxout = open_trx(TrjoutFile,filemode);
		break;
	    case efGRO:
	    case efG96:
	    case efPDB:
		/* Make atoms struct for output in GRO or PDB files */
		/* get memory for stuff to go in pdb file */
		init_t_atoms(&useatoms,nout,FALSE);
		sfree(useatoms.resinfo);
		useatoms.resinfo=atoms->resinfo;
		for(i=0;(i<nout);i++) {
		    useatoms.atomname[i]=atoms->atomname[i];
		    useatoms.atom[i]=atoms->atom[i];
		    useatoms.nres=max(useatoms.nres,useatoms.atom[i].resind+1);
		}
		useatoms.nr=nout;
		out=gmx_ffopen(TrjoutFile,filemode);
		break;
	}
    }
    
    if (natoms > atoms->nr) {
	gmx_fatal(FARGS,"\nTrajectory does not match topology!");
    }
    if (gnx > natoms) {
	gmx_fatal(FARGS,"\nTrajectory does not match selected group!");
    }

    fo = xvgropen(opt2fn("-o",NFILE,fnm),"RMSD","Time (ps)","RMSD (nm)",oenv);
    frc = xvgropen(opt2fn("-rc",NFILE,fnm),"Number of Residues in the alignment","Time (ps)","Residues",oenv);
    
    do {
	t = output_env_conv_time(oenv,fr.time);
	gmx_rmpbc(gpbc,natoms,fr.box,fr.x);
	tapein=gmx_ffopen(pdbfile,"w");
	write_pdbfile_indexed(tapein,NULL,atoms,fr.x,ePBC,fr.box,' ',-1,gnx,index,NULL,TRUE); 
	gmx_ffclose(tapein);
	system(multiprot);
	remove(pdbfile);
	process_multiprot_output(fn, &rmsd, &nres2,rotangles,translation,bCountres,countres);
	fprintf(fo,"%12.7f",t);
	fprintf(fo," %12.7f\n",rmsd);
	fprintf(frc,"%12.7f",t);
	fprintf(frc,"%12d\n",nres2);
	if (bTrjout) {
	    rotate_conf(natoms,fr.x,NULL,rotangles[XX],rotangles[YY],rotangles[ZZ]);
	    for(i=0; i<natoms; i++) {
		rvec_inc(fr.x[i],translation);
	    }
	    switch(outftp) {
		case efTRJ:
		case efTRR:
		case efG87:
		case efXTC:
		    write_trxframe(trxout,&fr,NULL);
		    break;
		case efGRO:
		case efG96:
		case efPDB:
		    sprintf(out_title,"Generated by do_multiprot : %s t= %g %s",
			    title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv));
		    switch(outftp) {
			case efGRO: 
			    write_hconf_p(out,out_title,&useatoms,prec2ndec(fr.prec),
					  fr.x,NULL,fr.box);
			    break;
			case efPDB:
			    fprintf(out,"REMARK    GENERATED BY DO_MULTIPROT\n");
			    sprintf(out_title,"%s t= %g %s",title,output_env_conv_time(oenv,fr.time),output_env_get_time_unit(oenv));
			    /* if reading from pdb, we want to keep the original 
			       model numbering else we write the output frame
			       number plus one, because model 0 is not allowed in pdb */
			    if (ftp==efPDB && fr.step > model_nr) {
				model_nr = fr.step;
			    }
			    else {
				model_nr++;
			    }
			    write_pdbfile(out,out_title,&useatoms,fr.x,ePBC,fr.box,' ',model_nr,NULL,TRUE);
			    break;
			case efG96:
			    fr.title = out_title;
			    fr.bTitle = (nframe == 0);
			    fr.bAtoms = FALSE;
			    fr.bStep = TRUE;
			    fr.bTime = TRUE;
			    write_g96_conf(out,&fr,-1,NULL);
		    }
		    break;
	    }
	}
	nframe++;
    } while(read_next_frame(oenv,status,&fr));
    if (bCountres) {
	fres=  xvgropen(opt2fn("-cr",NFILE,fnm),"Number of frames in which the residues are aligned to","Residue","Number",oenv);
	for (i=0;i<ratoms.nres;i++) {
	    fprintf(fres,"%10d  %12d\n",countres[i].resnr,countres[i].count);
	}
	gmx_ffclose(fres);
    }
    gmx_ffclose(fo);
    gmx_ffclose(frc);
    fprintf(stderr,"\n");
    close_trj(status);
    if (trxout != NULL) {
	close_trx(trxout);
    }
    else if (out != NULL) {
	gmx_ffclose(out);
    }
    view_all(oenv,NFILE, fnm);
    sfree(xr);
    if (bCountres) {
	sfree(countres);
    }
    free_t_atoms(&ratoms,TRUE);
    if (bTrjout) {
	if (outftp==efPDB || outftp==efGRO || outftp==efG96) {
	    free_t_atoms(&useatoms,TRUE);
	}
    }
    gmx_thanx(stderr);
    return 0;
}
Esempio n. 6
0
int gmx_editconf(int argc, char *argv[])
{
    const char
        *desc[] =
            {
                "editconf converts generic structure format to [TT].gro[tt], [TT].g96[tt]",
                "or [TT].pdb[tt].",
                "[PAR]",
                "The box can be modified with options [TT]-box[tt], [TT]-d[tt] and",
                "[TT]-angles[tt]. Both [TT]-box[tt] and [TT]-d[tt]",
                "will center the system in the box, unless [TT]-noc[tt] is used.",
                "[PAR]",
                "Option [TT]-bt[tt] determines the box type: [TT]triclinic[tt] is a",
                "triclinic box, [TT]cubic[tt] is a rectangular box with all sides equal",
                "[TT]dodecahedron[tt] represents a rhombic dodecahedron and",
                "[TT]octahedron[tt] is a truncated octahedron.",
                "The last two are special cases of a triclinic box.",
                "The length of the three box vectors of the truncated octahedron is the",
                "shortest distance between two opposite hexagons.",
                "The volume of a dodecahedron is 0.71 and that of a truncated octahedron",
                "is 0.77 of that of a cubic box with the same periodic image distance.",
                "[PAR]",
                "Option [TT]-box[tt] requires only",
                "one value for a cubic box, dodecahedron and a truncated octahedron.",
                "[PAR]",
                "With [TT]-d[tt] and a [TT]triclinic[tt] box the size of the system in the x, y",
                "and z directions is used. With [TT]-d[tt] and [TT]cubic[tt],",
                "[TT]dodecahedron[tt] or [TT]octahedron[tt] boxes, the dimensions are set",
                "to the diameter of the system (largest distance between atoms) plus twice",
                "the specified distance.",
                "[PAR]",
                "Option [TT]-angles[tt] is only meaningful with option [TT]-box[tt] and",
                "a triclinic box and can not be used with option [TT]-d[tt].",
                "[PAR]",
                "When [TT]-n[tt] or [TT]-ndef[tt] is set, a group",
                "can be selected for calculating the size and the geometric center,",
                "otherwise the whole system is used.",
                "[PAR]",
                "[TT]-rotate[tt] rotates the coordinates and velocities.",
                "[PAR]",
                "[TT]-princ[tt] aligns the principal axes of the system along the",
                "coordinate axes, this may allow you to decrease the box volume,",
                "but beware that molecules can rotate significantly in a nanosecond.",
                "[PAR]",
                "Scaling is applied before any of the other operations are",
                "performed. Boxes and coordinates can be scaled to give a certain density (option",
                "[TT]-density[tt]). Note that this may be inaccurate in case a gro",
                "file is given as input. A special feature of the scaling option, when the",
                "factor -1 is given in one dimension, one obtains a mirror image,",
                "mirrored in one of the plains, when one uses -1 in three dimensions",
                "a point-mirror image is obtained.[PAR]",
                "Groups are selected after all operations have been applied.[PAR]",
                "Periodicity can be removed in a crude manner.",
                "It is important that the box sizes at the bottom of your input file",
                "are correct when the periodicity is to be removed.",
                "[PAR]",
                "When writing [TT].pdb[tt] files, B-factors can be",
                "added with the [TT]-bf[tt] option. B-factors are read",
                "from a file with with following format: first line states number of",
                "entries in the file, next lines state an index",
                "followed by a B-factor. The B-factors will be attached per residue",
                "unless an index is larger than the number of residues or unless the",
                "[TT]-atom[tt] option is set. Obviously, any type of numeric data can",
                "be added instead of B-factors. [TT]-legend[tt] will produce",
                "a row of CA atoms with B-factors ranging from the minimum to the",
                "maximum value found, effectively making a legend for viewing.",
                "[PAR]",
                "With the option -mead a special pdb (pqr) file for the MEAD electrostatics",
                "program (Poisson-Boltzmann solver) can be made. A further prerequisite",
                "is that the input file is a run input file.",
                "The B-factor field is then filled with the Van der Waals radius",
                "of the atoms while the occupancy field will hold the charge.",
                "[PAR]",
                "The option -grasp is similar, but it puts the charges in the B-factor",
                "and the radius in the occupancy.",
                "[PAR]",
                "Option [TT]-align[tt] allows alignment",
                "of the principal axis of a specified group against the given vector, ",
				"with an optional center of rotation specified by [TT]-aligncenter[tt].",
                "[PAR]",
                "Finally with option [TT]-label[tt] editconf can add a chain identifier",
                "to a pdb file, which can be useful for analysis with e.g. rasmol.",
                    "[PAR]",
                "To convert a truncated octrahedron file produced by a package which uses",
                "a cubic box with the corners cut off (such as Gromos) use:[BR]",
                "[TT]editconf -f <in> -rotate 0 45 35.264 -bt o -box <veclen> -o <out>[tt][BR]",
                "where [TT]veclen[tt] is the size of the cubic box times sqrt(3)/2." };
    const char *bugs[] =
        {
            "For complex molecules, the periodicity removal routine may break down, ",
                "in that case you can use trjconv." };
    static real dist = 0.0, rbox = 0.0, to_diam = 0.0;
    static gmx_bool bNDEF = FALSE, bRMPBC = FALSE, bCenter = FALSE, bReadVDW =
        FALSE, bCONECT = FALSE;
    static gmx_bool peratom = FALSE, bLegend = FALSE, bOrient = FALSE, bMead =
        FALSE, bGrasp = FALSE, bSig56 = FALSE;
    static rvec scale =
        { 1, 1, 1 }, newbox =
        { 0, 0, 0 }, newang =
        { 90, 90, 90 };
    static real rho = 1000.0, rvdw = 0.12;
    static rvec center =
        { 0, 0, 0 }, translation =
        { 0, 0, 0 }, rotangles =
        { 0, 0, 0 }, aligncenter =
		{ 0, 0, 0 }, targetvec =
        { 0, 0, 0 };
    static const char *btype[] =
        { NULL, "triclinic", "cubic", "dodecahedron", "octahedron", NULL },
        *label = "A";
    static rvec visbox =
        { 0, 0, 0 };
    t_pargs
        pa[] =
            {
                    { "-ndef", FALSE, etBOOL,
                        { &bNDEF }, "Choose output from default index groups" },
                    { "-visbox", FALSE, etRVEC,
                        { visbox },
                        "HIDDENVisualize a grid of boxes, -1 visualizes the 14 box images" },
                    { "-bt", FALSE, etENUM,
                        { btype }, "Box type for -box and -d" },
                    { "-box", FALSE, etRVEC,
                        { newbox }, "Box vector lengths (a,b,c)" },
                    { "-angles", FALSE, etRVEC,
                        { newang }, "Angles between the box vectors (bc,ac,ab)" },
                    { "-d", FALSE, etREAL,
                        { &dist }, "Distance between the solute and the box" },
                    { "-c", FALSE, etBOOL,
                        { &bCenter },
                        "Center molecule in box (implied by -box and -d)" },
                    { "-center", FALSE, etRVEC,
                        { center }, "Coordinates of geometrical center" },
                    { "-aligncenter", FALSE, etRVEC,
                        { aligncenter }, "Center of rotation for alignment" },
                    { "-align", FALSE, etRVEC,
                        { targetvec },
                        "Align to target vector" },
                    { "-translate", FALSE, etRVEC,
                        { translation }, "Translation" },
                    { "-rotate", FALSE, etRVEC,
                        { rotangles },
                        "Rotation around the X, Y and Z axes in degrees" },
                    { "-princ", FALSE, etBOOL,
                        { &bOrient },
                        "Orient molecule(s) along their principal axes" },
                    { "-scale", FALSE, etRVEC,
                        { scale }, "Scaling factor" },
                    { "-density", FALSE, etREAL,
                        { &rho },
                        "Density (g/l) of the output box achieved by scaling" },
                    { "-pbc", FALSE, etBOOL,
                        { &bRMPBC },
                        "Remove the periodicity (make molecule whole again)" },
                    { "-grasp", FALSE, etBOOL,
                        { &bGrasp },
                        "Store the charge of the atom in the B-factor field and the radius of the atom in the occupancy field" },
                    {
                        "-rvdw", FALSE, etREAL,
                         { &rvdw },
                        "Default Van der Waals radius (in nm) if one can not be found in the database or if no parameters are present in the topology file" },
                    { "-sig56", FALSE, etREAL,
                        { &bSig56 },
                        "Use rmin/2 (minimum in the Van der Waals potential) rather than sigma/2 " },
                    {
                        "-vdwread", FALSE, etBOOL,
                        { &bReadVDW },
                        "Read the Van der Waals radii from the file vdwradii.dat rather than computing the radii based on the force field" },
                    { "-atom", FALSE, etBOOL,
                        { &peratom }, "Force B-factor attachment per atom" },
                    { "-legend", FALSE, etBOOL,
                        { &bLegend }, "Make B-factor legend" },
                    { "-label", FALSE, etSTR,
                        { &label }, "Add chain label for all residues" },
                    {
                        "-conect", FALSE, etBOOL,
                        { &bCONECT },
                        "Add CONECT records to a pdb file when written. Can only be done when a topology is present" } };
#define NPA asize(pa)

    FILE *out;
    const char *infile, *outfile;
    char title[STRLEN];
    int outftp, inftp, natom, i, j, n_bfac, itype, ntype;
    double *bfac = NULL, c6, c12;
    int *bfac_nr = NULL;
    t_topology *top = NULL;
    t_atoms atoms;
    char *grpname, *sgrpname, *agrpname;
    int isize, ssize, tsize, asize;
    atom_id *index, *sindex, *tindex, *aindex;
    rvec *x, *v, gc, min, max, size;
    int ePBC;
    matrix box,rotmatrix,trans;
	rvec princd,tmpvec;
    gmx_bool bIndex, bSetSize, bSetAng, bCubic, bDist, bSetCenter, bAlign;
    gmx_bool bHaveV, bScale, bRho, bTranslate, bRotate, bCalcGeom, bCalcDiam;
    real xs, ys, zs, xcent, ycent, zcent, diam = 0, mass = 0, d, vdw;
    gmx_atomprop_t aps;
    gmx_conect conect;
    output_env_t oenv;
    t_filenm fnm[] =
        {
            { efSTX, "-f", NULL, ffREAD },
            { efNDX, "-n", NULL, ffOPTRD },
            { efSTO, NULL, NULL, ffOPTWR },
            { efPQR, "-mead", "mead", ffOPTWR },
            { efDAT, "-bf", "bfact", ffOPTRD } };
#define NFILE asize(fnm)

    CopyRight(stderr, argv[0]);
    parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, NPA, pa,
                      asize(desc), desc, asize(bugs), bugs, &oenv);

    bIndex = opt2bSet("-n", NFILE, fnm) || bNDEF;
    bMead = opt2bSet("-mead", NFILE, fnm);
    bSetSize = opt2parg_bSet("-box", NPA, pa);
    bSetAng = opt2parg_bSet("-angles", NPA, pa);
    bSetCenter = opt2parg_bSet("-center", NPA, pa);
    bDist = opt2parg_bSet("-d", NPA, pa);
	bAlign = opt2parg_bSet("-align", NPA, pa);
    /* Only automatically turn on centering without -noc */
    if ((bDist || bSetSize || bSetCenter) && !opt2parg_bSet("-c", NPA, pa))
    {
        bCenter = TRUE;
    }
    bScale = opt2parg_bSet("-scale", NPA, pa);
    bRho = opt2parg_bSet("-density", NPA, pa);
    bTranslate = opt2parg_bSet("-translate", NPA, pa);
    bRotate = opt2parg_bSet("-rotate", NPA, pa);
    if (bScale && bRho)
        fprintf(stderr, "WARNING: setting -density overrides -scale\n");
    bScale = bScale || bRho;
    bCalcGeom = bCenter || bRotate || bOrient || bScale;
    bCalcDiam = btype[0][0] == 'c' || btype[0][0] == 'd' || btype[0][0] == 'o';

    infile = ftp2fn(efSTX, NFILE, fnm);
    if (bMead)
        outfile = ftp2fn(efPQR, NFILE, fnm);
    else
        outfile = ftp2fn(efSTO, NFILE, fnm);
    outftp = fn2ftp(outfile);
    inftp = fn2ftp(infile);

    aps = gmx_atomprop_init();

    if (bMead && bGrasp)
    {
        printf("Incompatible options -mead and -grasp. Turning off -grasp\n");
        bGrasp = FALSE;
    }
    if (bGrasp && (outftp != efPDB))
        gmx_fatal(FARGS, "Output file should be a .pdb file"
        " when using the -grasp option\n");
        if ((bMead || bGrasp) && !((fn2ftp(infile) == efTPR) ||
                (fn2ftp(infile) == efTPA) ||
                (fn2ftp(infile) == efTPB)))
        gmx_fatal(FARGS,"Input file should be a .tp[abr] file"
            " when using the -mead option\n");

        get_stx_coordnum(infile,&natom);
        init_t_atoms(&atoms,natom,TRUE);
        snew(x,natom);
        snew(v,natom);
        read_stx_conf(infile,title,&atoms,x,v,&ePBC,box);
        if (fn2ftp(infile) == efPDB)
        {
            get_pdb_atomnumber(&atoms,aps);
        }
        printf("Read %d atoms\n",atoms.nr);

        /* Get the element numbers if available in a pdb file */
        if (fn2ftp(infile) == efPDB)
        get_pdb_atomnumber(&atoms,aps);

        if (ePBC != epbcNONE)
        {
            real vol = det(box);
            printf("Volume: %g nm^3, corresponds to roughly %d electrons\n",
                vol,100*((int)(vol*4.5)));
        }

        if (bMead || bGrasp || bCONECT)
        top = read_top(infile,NULL);

        if (bMead || bGrasp)
        {
            if (atoms.nr != top->atoms.nr)
            gmx_fatal(FARGS,"Atom numbers don't match (%d vs. %d)",atoms.nr,top->atoms.nr);
        snew(atoms.pdbinfo,top->atoms.nr); 
        ntype = top->idef.atnr;
        for(i=0; (i<atoms.nr); i++) {
            /* Determine the Van der Waals radius from the force field */
            if (bReadVDW) {
                if (!gmx_atomprop_query(aps,epropVDW,
                                        *top->atoms.resinfo[top->atoms.atom[i].resind].name,
                                        *top->atoms.atomname[i],&vdw))
                    vdw = rvdw;
            }
            else {
                itype = top->atoms.atom[i].type;
                c12   = top->idef.iparams[itype*ntype+itype].lj.c12;
                c6    = top->idef.iparams[itype*ntype+itype].lj.c6;
                if ((c6 != 0) && (c12 != 0)) {
                    real sig6; 
                    if (bSig56)
                        sig6 = 2*c12/c6;
                    else
                        sig6 = c12/c6;
                    vdw   = 0.5*pow(sig6,1.0/6.0);
                }
                else
                    vdw = rvdw;
            }
            /* Factor of 10 for nm -> Angstroms */
            vdw *= 10;

            if (bMead) {
                atoms.pdbinfo[i].occup = top->atoms.atom[i].q;
                atoms.pdbinfo[i].bfac  = vdw;
            }
            else {
                atoms.pdbinfo[i].occup = vdw;
                atoms.pdbinfo[i].bfac  = top->atoms.atom[i].q;
            }
        }
    }
    bHaveV=FALSE;
    for (i=0; (i<natom) && !bHaveV; i++)
        for (j=0; (j<DIM) && !bHaveV; j++)
            bHaveV=bHaveV || (v[i][j]!=0);
    printf("%selocities found\n",bHaveV?"V":"No v");

    if (visbox[0] > 0) {
        if (bIndex)
            gmx_fatal(FARGS,"Sorry, can not visualize box with index groups");
        if (outftp != efPDB)
            gmx_fatal(FARGS,"Sorry, can only visualize box with a pdb file");
    } else if (visbox[0] == -1)
        visualize_images("images.pdb",ePBC,box);

    /* remove pbc */
    if (bRMPBC) 
        rm_gropbc(&atoms,x,box);

    if (bCalcGeom) {
        if (bIndex) {
            fprintf(stderr,"\nSelect a group for determining the system size:\n");
            get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),
                      1,&ssize,&sindex,&sgrpname);
        } else {
            ssize = atoms.nr;
            sindex = NULL;
        }
        diam=calc_geom(ssize,sindex,x,gc,min,max,bCalcDiam);
        rvec_sub(max, min, size);
        printf("    system size :%7.3f%7.3f%7.3f (nm)\n",
               size[XX], size[YY], size[ZZ]);
        if (bCalcDiam)
            printf("    diameter    :%7.3f               (nm)\n",diam);
        printf("    center      :%7.3f%7.3f%7.3f (nm)\n", gc[XX], gc[YY], gc[ZZ]);
        printf("    box vectors :%7.3f%7.3f%7.3f (nm)\n", 
               norm(box[XX]), norm(box[YY]), norm(box[ZZ]));
        printf("    box angles  :%7.2f%7.2f%7.2f (degrees)\n",
               norm2(box[ZZ])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])),
        norm2(box[ZZ])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])),
        norm2(box[YY])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY])));
        printf("    box volume  :%7.2f               (nm^3)\n",det(box));
    }

    if (bRho || bOrient || bAlign)
        mass = calc_mass(&atoms,!fn2bTPX(infile),aps);

    if (bOrient) {
        atom_id *index;
        char    *grpnames;

        /* Get a group for principal component analysis */
        fprintf(stderr,"\nSelect group for the determining the orientation\n");
        get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpnames);

        /* Orient the principal axes along the coordinate axes */
        orient_princ(&atoms,isize,index,natom,x,bHaveV ? v : NULL, NULL);
        sfree(index);
        sfree(grpnames);
    }

    if ( bScale ) {
        /* scale coordinates and box */
        if (bRho) {
            /* Compute scaling constant */
            real vol,dens;

            vol = det(box);
            dens = (mass*AMU)/(vol*NANO*NANO*NANO);
            fprintf(stderr,"Volume  of input %g (nm^3)\n",vol);
            fprintf(stderr,"Mass    of input %g (a.m.u.)\n",mass);
            fprintf(stderr,"Density of input %g (g/l)\n",dens);
            if (vol==0 || mass==0)
                gmx_fatal(FARGS,"Cannot scale density with "
                          "zero mass (%g) or volume (%g)\n",mass,vol);

            scale[XX] = scale[YY] = scale[ZZ] = pow(dens/rho,1.0/3.0);
            fprintf(stderr,"Scaling all box vectors by %g\n",scale[XX]);
        }
        scale_conf(atoms.nr,x,box,scale);
    }

	if (bAlign) {
		if (bIndex) {
            fprintf(stderr,"\nSelect a group that you want to align:\n");
            get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),
                      1,&asize,&aindex,&agrpname);
        } else {
            asize = atoms.nr;
            snew(aindex,asize);
			for (i=0;i<asize;i++)
				aindex[i]=i;
        }
		printf("Aligning %d atoms (out of %d) to %g %g %g, center of rotation %g %g %g\n",asize,natom,
			targetvec[XX],targetvec[YY],targetvec[ZZ],
			aligncenter[XX],aligncenter[YY],aligncenter[ZZ]);
		/*subtract out pivot point*/
		for(i=0; i<asize; i++)
			rvec_dec(x[aindex[i]],aligncenter);
		/*now determine transform and rotate*/
		/*will this work?*/
		principal_comp(asize,aindex,atoms.atom,x, trans,princd);

		unitv(targetvec,targetvec);
		printf("Using %g %g %g as principal axis\n", trans[0][2],trans[1][2],trans[2][2]);
		tmpvec[XX]=trans[0][2]; tmpvec[YY]=trans[1][2]; tmpvec[ZZ]=trans[2][2];
		calc_rotmatrix(tmpvec, targetvec, rotmatrix);
		/* rotmatrix finished */

		for (i=0;i<asize;++i)
		{
			mvmul(rotmatrix,x[aindex[i]],tmpvec);
			copy_rvec(tmpvec,x[aindex[i]]);
		}

		/*add pivot point back*/
		for(i=0; i<asize; i++)
			rvec_inc(x[aindex[i]],aligncenter);
		if (!bIndex)
			sfree(aindex);
	}

    if (bTranslate) {
        if (bIndex) {
            fprintf(stderr,"\nSelect a group that you want to translate:\n");
            get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),
                      1,&ssize,&sindex,&sgrpname);
        } else {
            ssize = atoms.nr;
            sindex = NULL;
        }
        printf("Translating %d atoms (out of %d) by %g %g %g nm\n",ssize,natom,
               translation[XX],translation[YY],translation[ZZ]);
        if (sindex) {
            for(i=0; i<ssize; i++)
                rvec_inc(x[sindex[i]],translation);
        }
        else {
            for(i=0; i<natom; i++)
                rvec_inc(x[i],translation);
        }
    }
    if (bRotate) {
        /* Rotate */
        printf("Rotating %g, %g, %g degrees around the X, Y and Z axis respectively\n",rotangles[XX],rotangles[YY],rotangles[ZZ]);
        for(i=0; i<DIM; i++)
            rotangles[i] *= DEG2RAD;
        rotate_conf(natom,x,v,rotangles[XX],rotangles[YY],rotangles[ZZ]);
    }

    if (bCalcGeom) {
        /* recalc geometrical center and max and min coordinates and size */
        calc_geom(ssize,sindex,x,gc,min,max,FALSE);
        rvec_sub(max, min, size);
        if (bScale || bOrient || bRotate)
            printf("new system size : %6.3f %6.3f %6.3f\n",
                   size[XX],size[YY],size[ZZ]);
    }

    if (bSetSize || bDist || (btype[0][0]=='t' && bSetAng)) {
        ePBC = epbcXYZ;
        if (!(bSetSize || bDist))
            for (i=0; i<DIM; i++)
                newbox[i] = norm(box[i]);
        clear_mat(box);
        /* calculate new boxsize */
        switch(btype[0][0]){
        case 't':
            if (bDist)
                for(i=0; i<DIM; i++)
                    newbox[i] = size[i]+2*dist;
            if (!bSetAng) {
                box[XX][XX] = newbox[XX];
                box[YY][YY] = newbox[YY];
                box[ZZ][ZZ] = newbox[ZZ];
            } else {
                matrix_convert(box,newbox,newang);
            }
            break;
        case 'c':
        case 'd':
        case 'o':
            if (bSetSize)
                d = newbox[0];
            else
                d = diam+2*dist;
            if (btype[0][0] == 'c')
                for(i=0; i<DIM; i++)
                    box[i][i] = d;
            else if (btype[0][0] == 'd') {
                box[XX][XX] = d;
                box[YY][YY] = d;
                box[ZZ][XX] = d/2;
                box[ZZ][YY] = d/2;
                box[ZZ][ZZ] = d*sqrt(2)/2;
            } else {
                box[XX][XX] = d;
                box[YY][XX] = d/3;
                box[YY][YY] = d*sqrt(2)*2/3;
                box[ZZ][XX] = -d/3;
                box[ZZ][YY] = d*sqrt(2)/3;
                box[ZZ][ZZ] = d*sqrt(6)/3;
            }
            break;
        } 
    }

    /* calculate new coords for geometrical center */
    if (!bSetCenter)
        calc_box_center(ecenterDEF,box,center);

    /* center molecule on 'center' */
    if (bCenter)
        center_conf(natom,x,center,gc);

    /* print some */
    if (bCalcGeom) {
        calc_geom(ssize,sindex,x, gc, min, max, FALSE);
        printf("new center      :%7.3f%7.3f%7.3f (nm)\n",gc[XX],gc[YY],gc[ZZ]);
    }
    if (bOrient || bScale || bDist || bSetSize) {
        printf("new box vectors :%7.3f%7.3f%7.3f (nm)\n", 
               norm(box[XX]), norm(box[YY]), norm(box[ZZ]));
        printf("new box angles  :%7.2f%7.2f%7.2f (degrees)\n",
               norm2(box[ZZ])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[YY],box[ZZ])),
        norm2(box[ZZ])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[XX],box[ZZ])),
        norm2(box[YY])==0 ? 0 :
        RAD2DEG*acos(cos_angle_no_table(box[XX],box[YY])));
        printf("new box volume  :%7.2f               (nm^3)\n",det(box));
    }  

    if (check_box(epbcXYZ,box))
        printf("\nWARNING: %s\n",check_box(epbcXYZ,box));

    if (bDist && btype[0][0]=='t')
    {
        if(TRICLINIC(box))
        {
            printf("\nWARNING: Your box is triclinic with non-orthogonal axes. In this case, the\n"
                "distance from the solute to a box surface along the corresponding normal\n"
                "vector might be somewhat smaller than your specified value %f.\n"
                "You can check the actual value with g_mindist -pi\n",dist);
        }
        else
        {
            printf("\nWARNING: No boxtype specified - distance condition applied in each dimension.\n"
                "If the molecule rotates the actual distance will be smaller. You might want\n"
                "to use a cubic box instead, or why not try a dodecahedron today?\n");
        }
    }
    if (bCONECT && (outftp == efPDB) && (inftp == efTPR)) 
        conect = gmx_conect_generate(top);
    else
        conect = NULL;

    if (bIndex) {
        fprintf(stderr,"\nSelect a group for output:\n");
        get_index(&atoms,opt2fn_null("-n",NFILE,fnm),
                  1,&isize,&index,&grpname);
        if (opt2parg_bSet("-label",NPA,pa)) {
            for(i=0; (i<atoms.nr); i++) 
                atoms.resinfo[atoms.atom[i].resind].chainid=label[0];
        }
                
        if (opt2bSet("-bf",NFILE,fnm) || bLegend)
        {
            gmx_fatal(FARGS,"Sorry, cannot do bfactors with an index group.");
        }

        if (outftp == efPDB) 
        {
            out=ffopen(outfile,"w");
            write_pdbfile_indexed(out,title,&atoms,x,ePBC,box,' ',1,isize,index,conect,TRUE);
            ffclose(out);
        }
        else
        {
            write_sto_conf_indexed(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box,isize,index); 
        }
    }
    else {
        if ((outftp == efPDB) || (outftp == efPQR)) {
            out=ffopen(outfile,"w");
            if (bMead) {
                set_pdb_wide_format(TRUE);
                fprintf(out,"REMARK    "
                        "The B-factors in this file hold atomic radii\n");
                fprintf(out,"REMARK    "
                        "The occupancy in this file hold atomic charges\n");
            }
            else if (bGrasp) {
                fprintf(out,"GRASP PDB FILE\nFORMAT NUMBER=1\n");
                fprintf(out,"REMARK    "
                        "The B-factors in this file hold atomic charges\n");
                fprintf(out,"REMARK    "
                        "The occupancy in this file hold atomic radii\n");
            }
            else if (opt2bSet("-bf",NFILE,fnm)) {
                read_bfac(opt2fn("-bf",NFILE,fnm),&n_bfac,&bfac,&bfac_nr);
                set_pdb_conf_bfac(atoms.nr,atoms.nres,&atoms,
                                  n_bfac,bfac,bfac_nr,peratom);
            }
            if (opt2parg_bSet("-label",NPA,pa)) {
                for(i=0; (i<atoms.nr); i++) 
                    atoms.resinfo[atoms.atom[i].resind].chainid=label[0];
            }
            write_pdbfile(out,title,&atoms,x,ePBC,box,' ',-1,conect,TRUE);
            if (bLegend)
                pdb_legend(out,atoms.nr,atoms.nres,&atoms,x);
            if (visbox[0] > 0)
                visualize_box(out,bLegend ? atoms.nr+12 : atoms.nr,
                    bLegend? atoms.nres=12 : atoms.nres,box,visbox);
            ffclose(out);
        }
        else
            write_sto_conf(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box); 
    }
    gmx_atomprop_destroy(aps);

    do_view(oenv,outfile,NULL);

    thanx(stderr);

    return 0;
}
Esempio n. 7
0
double do_tpi(FILE *fplog, t_commrec *cr,
              int nfile, const t_filenm fnm[],
              const output_env_t oenv, gmx_bool bVerbose, gmx_bool gmx_unused bCompact,
              int gmx_unused nstglobalcomm,
              gmx_vsite_t gmx_unused *vsite, gmx_constr_t gmx_unused constr,
              int gmx_unused stepout,
              t_inputrec *inputrec,
              gmx_mtop_t *top_global, t_fcdata *fcd,
              t_state *state,
              t_mdatoms *mdatoms,
              t_nrnb *nrnb, gmx_wallcycle_t wcycle,
              gmx_edsam_t gmx_unused ed,
              t_forcerec *fr,
              int gmx_unused repl_ex_nst, int gmx_unused repl_ex_nex, int gmx_unused repl_ex_seed,
              gmx_membed_t gmx_unused membed,
              real gmx_unused cpt_period, real gmx_unused max_hours,
              const char gmx_unused *deviceOptions,
              int gmx_unused imdport,
              unsigned long gmx_unused Flags,
              gmx_walltime_accounting_t walltime_accounting)
{
    const char     *TPI = "Test Particle Insertion";
    gmx_localtop_t *top;
    gmx_groups_t   *groups;
    gmx_enerdata_t *enerd;
    rvec           *f;
    real            lambda, t, temp, beta, drmax, epot;
    double          embU, sum_embU, *sum_UgembU, V, V_all, VembU_all;
    t_trxstatus    *status;
    t_trxframe      rerun_fr;
    gmx_bool        bDispCorr, bCharge, bRFExcl, bNotLastFrame, bStateChanged, bNS;
    tensor          force_vir, shake_vir, vir, pres;
    int             cg_tp, a_tp0, a_tp1, ngid, gid_tp, nener, e;
    rvec           *x_mol;
    rvec            mu_tot, x_init, dx, x_tp;
    int             nnodes, frame;
    gmx_int64_t     frame_step_prev, frame_step;
    gmx_int64_t     nsteps, stepblocksize = 0, step;
    gmx_int64_t     rnd_count_stride, rnd_count;
    gmx_int64_t     seed;
    double          rnd[4];
    int             i, start, end;
    FILE           *fp_tpi = NULL;
    char           *ptr, *dump_pdb, **leg, str[STRLEN], str2[STRLEN];
    double          dbl, dump_ener;
    gmx_bool        bCavity;
    int             nat_cavity  = 0, d;
    real           *mass_cavity = NULL, mass_tot;
    int             nbin;
    double          invbinw, *bin, refvolshift, logV, bUlogV;
    real            dvdl, prescorr, enercorr, dvdlcorr;
    gmx_bool        bEnergyOutOfBounds;
    const char     *tpid_leg[2] = {"direct", "reweighted"};

    /* Since there is no upper limit to the insertion energies,
     * we need to set an upper limit for the distribution output.
     */
    real bU_bin_limit      = 50;
    real bU_logV_bin_limit = bU_bin_limit + 10;

    nnodes = cr->nnodes;

    top = gmx_mtop_generate_local_top(top_global, inputrec);

    groups = &top_global->groups;

    bCavity = (inputrec->eI == eiTPIC);
    if (bCavity)
    {
        ptr = getenv("GMX_TPIC_MASSES");
        if (ptr == NULL)
        {
            nat_cavity = 1;
        }
        else
        {
            /* Read (multiple) masses from env var GMX_TPIC_MASSES,
             * The center of mass of the last atoms is then used for TPIC.
             */
            nat_cavity = 0;
            while (sscanf(ptr, "%lf%n", &dbl, &i) > 0)
            {
                srenew(mass_cavity, nat_cavity+1);
                mass_cavity[nat_cavity] = dbl;
                fprintf(fplog, "mass[%d] = %f\n",
                        nat_cavity+1, mass_cavity[nat_cavity]);
                nat_cavity++;
                ptr += i;
            }
            if (nat_cavity == 0)
            {
                gmx_fatal(FARGS, "Found %d masses in GMX_TPIC_MASSES", nat_cavity);
            }
        }
    }

    /*
       init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
       state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
    /* We never need full pbc for TPI */
    fr->ePBC = epbcXYZ;
    /* Determine the temperature for the Boltzmann weighting */
    temp = inputrec->opts.ref_t[0];
    if (fplog)
    {
        for (i = 1; (i < inputrec->opts.ngtc); i++)
        {
            if (inputrec->opts.ref_t[i] != temp)
            {
                fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
                fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
            }
        }
        fprintf(fplog,
                "\n  The temperature for test particle insertion is %.3f K\n\n",
                temp);
    }
    beta = 1.0/(BOLTZ*temp);

    /* Number of insertions per frame */
    nsteps = inputrec->nsteps;

    /* Use the same neighborlist with more insertions points
     * in a sphere of radius drmax around the initial point
     */
    /* This should be a proper mdp parameter */
    drmax = inputrec->rtpi;

    /* An environment variable can be set to dump all configurations
     * to pdb with an insertion energy <= this value.
     */
    dump_pdb  = getenv("GMX_TPI_DUMP");
    dump_ener = 0;
    if (dump_pdb)
    {
        sscanf(dump_pdb, "%lf", &dump_ener);
    }

    atoms2md(top_global, inputrec, 0, NULL, top_global->natoms, mdatoms);
    update_mdatoms(mdatoms, inputrec->fepvals->init_lambda);

    snew(enerd, 1);
    init_enerdata(groups->grps[egcENER].nr, inputrec->fepvals->n_lambda, enerd);
    snew(f, top_global->natoms);

    /* Print to log file  */
    walltime_accounting_start(walltime_accounting);
    wallcycle_start(wcycle, ewcRUN);
    print_start(fplog, cr, walltime_accounting, "Test Particle Insertion");

    /* The last charge group is the group to be inserted */
    cg_tp = top->cgs.nr - 1;
    a_tp0 = top->cgs.index[cg_tp];
    a_tp1 = top->cgs.index[cg_tp+1];
    if (debug)
    {
        fprintf(debug, "TPI cg %d, atoms %d-%d\n", cg_tp, a_tp0, a_tp1);
    }
    if (a_tp1 - a_tp0 > 1 &&
        (inputrec->rlist < inputrec->rcoulomb ||
         inputrec->rlist < inputrec->rvdw))
    {
        gmx_fatal(FARGS, "Can not do TPI for multi-atom molecule with a twin-range cut-off");
    }
    snew(x_mol, a_tp1-a_tp0);

    bDispCorr = (inputrec->eDispCorr != edispcNO);
    bCharge   = FALSE;
    for (i = a_tp0; i < a_tp1; i++)
    {
        /* Copy the coordinates of the molecule to be insterted */
        copy_rvec(state->x[i], x_mol[i-a_tp0]);
        /* Check if we need to print electrostatic energies */
        bCharge |= (mdatoms->chargeA[i] != 0 ||
                    (mdatoms->chargeB && mdatoms->chargeB[i] != 0));
    }
    bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype != eelRF_NEC);

    calc_cgcm(fplog, cg_tp, cg_tp+1, &(top->cgs), state->x, fr->cg_cm);
    if (bCavity)
    {
        if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog)
        {
            fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
            fprintf(stderr, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
        }
    }
    else
    {
        /* Center the molecule to be inserted at zero */
        for (i = 0; i < a_tp1-a_tp0; i++)
        {
            rvec_dec(x_mol[i], fr->cg_cm[cg_tp]);
        }
    }

    if (fplog)
    {
        fprintf(fplog, "\nWill insert %d atoms %s partial charges\n",
                a_tp1-a_tp0, bCharge ? "with" : "without");

        fprintf(fplog, "\nWill insert %d times in each frame of %s\n",
                (int)nsteps, opt2fn("-rerun", nfile, fnm));
    }

    if (!bCavity)
    {
        if (inputrec->nstlist > 1)
        {
            if (drmax == 0 && a_tp1-a_tp0 == 1)
            {
                gmx_fatal(FARGS, "Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense", inputrec->nstlist, drmax);
            }
            if (fplog)
            {
                fprintf(fplog, "Will use the same neighborlist for %d insertions in a sphere of radius %f\n", inputrec->nstlist, drmax);
            }
        }
    }
    else
    {
        if (fplog)
        {
            fprintf(fplog, "Will insert randomly in a sphere of radius %f around the center of the cavity\n", drmax);
        }
    }

    ngid   = groups->grps[egcENER].nr;
    gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
    nener  = 1 + ngid;
    if (bDispCorr)
    {
        nener += 1;
    }
    if (bCharge)
    {
        nener += ngid;
        if (bRFExcl)
        {
            nener += 1;
        }
        if (EEL_FULL(fr->eeltype))
        {
            nener += 1;
        }
    }
    snew(sum_UgembU, nener);

    /* Copy the random seed set by the user */
    seed = inputrec->ld_seed;
    /* We use the frame step number as one random counter.
     * The second counter use the insertion (step) count. But we
     * need multiple random numbers per insertion. This number is
     * not fixed, since we generate random locations in a sphere
     * by putting locations in a cube and some of these fail.
     * A count of 20 is already extremely unlikely, so 10000 is
     * a safe margin for random numbers per insertion.
     */
    rnd_count_stride = 10000;

    if (MASTER(cr))
    {
        fp_tpi = xvgropen(opt2fn("-tpi", nfile, fnm),
                          "TPI energies", "Time (ps)",
                          "(kJ mol\\S-1\\N) / (nm\\S3\\N)", oenv);
        xvgr_subtitle(fp_tpi, "f. are averages over one frame", oenv);
        snew(leg, 4+nener);
        e = 0;
        sprintf(str, "-kT log(<Ve\\S-\\betaU\\N>/<V>)");
        leg[e++] = strdup(str);
        sprintf(str, "f. -kT log<e\\S-\\betaU\\N>");
        leg[e++] = strdup(str);
        sprintf(str, "f. <e\\S-\\betaU\\N>");
        leg[e++] = strdup(str);
        sprintf(str, "f. V");
        leg[e++] = strdup(str);
        sprintf(str, "f. <Ue\\S-\\betaU\\N>");
        leg[e++] = strdup(str);
        for (i = 0; i < ngid; i++)
        {
            sprintf(str, "f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
                    *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
            leg[e++] = strdup(str);
        }
        if (bDispCorr)
        {
            sprintf(str, "f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
            leg[e++] = strdup(str);
        }
        if (bCharge)
        {
            for (i = 0; i < ngid; i++)
            {
                sprintf(str, "f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
                        *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
                leg[e++] = strdup(str);
            }
            if (bRFExcl)
            {
                sprintf(str, "f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
                leg[e++] = strdup(str);
            }
            if (EEL_FULL(fr->eeltype))
            {
                sprintf(str, "f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
                leg[e++] = strdup(str);
            }
        }
        xvgr_legend(fp_tpi, 4+nener, (const char**)leg, oenv);
        for (i = 0; i < 4+nener; i++)
        {
            sfree(leg[i]);
        }
        sfree(leg);
    }
    clear_rvec(x_init);
    V_all     = 0;
    VembU_all = 0;

    invbinw = 10;
    nbin    = 10;
    snew(bin, nbin);

    /* Avoid frame step numbers <= -1 */
    frame_step_prev = -1;

    bNotLastFrame = read_first_frame(oenv, &status, opt2fn("-rerun", nfile, fnm),
                                     &rerun_fr, TRX_NEED_X);
    frame = 0;

    if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
        mdatoms->nr - (a_tp1 - a_tp0))
    {
        gmx_fatal(FARGS, "Number of atoms in trajectory (%d)%s "
                  "is not equal the number in the run input file (%d) "
                  "minus the number of atoms to insert (%d)\n",
                  rerun_fr.natoms, bCavity ? " minus one" : "",
                  mdatoms->nr, a_tp1-a_tp0);
    }

    refvolshift = log(det(rerun_fr.box));

    switch (inputrec->eI)
    {
        case eiTPI:
            stepblocksize = inputrec->nstlist;
            break;
        case eiTPIC:
            stepblocksize = 1;
            break;
        default:
            gmx_fatal(FARGS, "Unknown integrator %s", ei_names[inputrec->eI]);
    }

#ifdef GMX_SIMD
    /* Make sure we don't detect SIMD overflow generated before this point */
    gmx_simd_check_and_reset_overflow();
#endif

    while (bNotLastFrame)
    {
        frame_step      = rerun_fr.step;
        if (frame_step <= frame_step_prev)
        {
            /* We don't have step number in the trajectory file,
             * or we have constant or decreasing step numbers.
             * Ensure we have increasing step numbers, since we use
             * the step numbers as a counter for random numbers.
             */
            frame_step  = frame_step_prev + 1;
        }
        frame_step_prev = frame_step;

        lambda = rerun_fr.lambda;
        t      = rerun_fr.time;

        sum_embU = 0;
        for (e = 0; e < nener; e++)
        {
            sum_UgembU[e] = 0;
        }

        /* Copy the coordinates from the input trajectory */
        for (i = 0; i < rerun_fr.natoms; i++)
        {
            copy_rvec(rerun_fr.x[i], state->x[i]);
        }
        copy_mat(rerun_fr.box, state->box);

        V    = det(state->box);
        logV = log(V);

        bStateChanged = TRUE;
        bNS           = TRUE;

        step = cr->nodeid*stepblocksize;
        while (step < nsteps)
        {
            /* Initialize the second counter for random numbers using
             * the insertion step index. This ensures that we get
             * the same random numbers independently of how many
             * MPI ranks we use. Also for the same seed, we get
             * the same initial random sequence for different nsteps.
             */
            rnd_count = step*rnd_count_stride;

            if (!bCavity)
            {
                /* Random insertion in the whole volume */
                bNS = (step % inputrec->nstlist == 0);
                if (bNS)
                {
                    /* Generate a random position in the box */
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                    for (d = 0; d < DIM; d++)
                    {
                        x_init[d] = rnd[d]*state->box[d][d];
                    }
                }
                if (inputrec->nstlist == 1)
                {
                    copy_rvec(x_init, x_tp);
                }
                else
                {
                    /* Generate coordinates within |dx|=drmax of x_init */
                    do
                    {
                        gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                        gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                        for (d = 0; d < DIM; d++)
                        {
                            dx[d] = (2*rnd[d] - 1)*drmax;
                        }
                    }
                    while (norm2(dx) > drmax*drmax);
                    rvec_add(x_init, dx, x_tp);
                }
            }
            else
            {
                /* Random insertion around a cavity location
                 * given by the last coordinate of the trajectory.
                 */
                if (step == 0)
                {
                    if (nat_cavity == 1)
                    {
                        /* Copy the location of the cavity */
                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1], x_init);
                    }
                    else
                    {
                        /* Determine the center of mass of the last molecule */
                        clear_rvec(x_init);
                        mass_tot = 0;
                        for (i = 0; i < nat_cavity; i++)
                        {
                            for (d = 0; d < DIM; d++)
                            {
                                x_init[d] +=
                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
                            }
                            mass_tot += mass_cavity[i];
                        }
                        for (d = 0; d < DIM; d++)
                        {
                            x_init[d] /= mass_tot;
                        }
                    }
                }
                /* Generate coordinates within |dx|=drmax of x_init */
                do
                {
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                    for (d = 0; d < DIM; d++)
                    {
                        dx[d] = (2*rnd[d] - 1)*drmax;
                    }
                }
                while (norm2(dx) > drmax*drmax);
                rvec_add(x_init, dx, x_tp);
            }

            if (a_tp1 - a_tp0 == 1)
            {
                /* Insert a single atom, just copy the insertion location */
                copy_rvec(x_tp, state->x[a_tp0]);
            }
            else
            {
                /* Copy the coordinates from the top file */
                for (i = a_tp0; i < a_tp1; i++)
                {
                    copy_rvec(x_mol[i-a_tp0], state->x[i]);
                }
                /* Rotate the molecule randomly */
                gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                rotate_conf(a_tp1-a_tp0, state->x+a_tp0, NULL,
                            2*M_PI*rnd[0],
                            2*M_PI*rnd[1],
                            2*M_PI*rnd[2]);
                /* Shift to the insertion location */
                for (i = a_tp0; i < a_tp1; i++)
                {
                    rvec_inc(state->x[i], x_tp);
                }
            }

            /* Clear some matrix variables  */
            clear_mat(force_vir);
            clear_mat(shake_vir);
            clear_mat(vir);
            clear_mat(pres);

            /* Set the charge group center of mass of the test particle */
            copy_rvec(x_init, fr->cg_cm[top->cgs.nr-1]);

            /* Calc energy (no forces) on new positions.
             * Since we only need the intermolecular energy
             * and the RF exclusion terms of the inserted molecule occur
             * within a single charge group we can pass NULL for the graph.
             * This also avoids shifts that would move charge groups
             * out of the box.
             *
             * Some checks above ensure than we can not have
             * twin-range interactions together with nstlist > 1,
             * therefore we do not need to remember the LR energies.
             */
            /* Make do_force do a single node force calculation */
            cr->nnodes = 1;
            do_force(fplog, cr, inputrec,
                     step, nrnb, wcycle, top, &top_global->groups,
                     state->box, state->x, &state->hist,
                     f, force_vir, mdatoms, enerd, fcd,
                     state->lambda,
                     NULL, fr, NULL, mu_tot, t, NULL, NULL, FALSE,
                     GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY |
                     (bNS ? GMX_FORCE_DYNAMICBOX | GMX_FORCE_NS | GMX_FORCE_DO_LR : 0) |
                     (bStateChanged ? GMX_FORCE_STATECHANGED : 0));
            cr->nnodes    = nnodes;
            bStateChanged = FALSE;
            bNS           = FALSE;

            /* Calculate long range corrections to pressure and energy */
            calc_dispcorr(fplog, inputrec, fr, step, top_global->natoms, state->box,
                          lambda, pres, vir, &prescorr, &enercorr, &dvdlcorr);
            /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
            enerd->term[F_DISPCORR]  = enercorr;
            enerd->term[F_EPOT]     += enercorr;
            enerd->term[F_PRES]     += prescorr;
            enerd->term[F_DVDL_VDW] += dvdlcorr;

            epot               = enerd->term[F_EPOT];
            bEnergyOutOfBounds = FALSE;
#ifdef GMX_SIMD_X86_SSE2_OR_HIGHER
            /* With SSE the energy can overflow, check for this */
            if (gmx_mm_check_and_reset_overflow())
            {
                if (debug)
                {
                    fprintf(debug, "Found an SSE overflow, assuming the energy is out of bounds\n");
                }
                bEnergyOutOfBounds = TRUE;
            }
#endif
            /* If the compiler doesn't optimize this check away
             * we catch the NAN energies.
             * The epot>GMX_REAL_MAX check catches inf values,
             * which should nicely result in embU=0 through the exp below,
             * but it does not hurt to check anyhow.
             */
            /* Non-bonded Interaction usually diverge at r=0.
             * With tabulated interaction functions the first few entries
             * should be capped in a consistent fashion between
             * repulsion, dispersion and Coulomb to avoid accidental
             * negative values in the total energy.
             * The table generation code in tables.c does this.
             * With user tbales the user should take care of this.
             */
            if (epot != epot || epot > GMX_REAL_MAX)
            {
                bEnergyOutOfBounds = TRUE;
            }
            if (bEnergyOutOfBounds)
            {
                if (debug)
                {
                    fprintf(debug, "\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n", t, (int)step, epot);
                }
                embU = 0;
            }
            else
            {
                embU      = exp(-beta*epot);
                sum_embU += embU;
                /* Determine the weighted energy contributions of each energy group */
                e                = 0;
                sum_UgembU[e++] += epot*embU;
                if (fr->bBHAM)
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] +=
                            (enerd->grpp.ener[egBHAMSR][GID(i, gid_tp, ngid)] +
                             enerd->grpp.ener[egBHAMLR][GID(i, gid_tp, ngid)])*embU;
                    }
                }
                else
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] +=
                            (enerd->grpp.ener[egLJSR][GID(i, gid_tp, ngid)] +
                             enerd->grpp.ener[egLJLR][GID(i, gid_tp, ngid)])*embU;
                    }
                }
                if (bDispCorr)
                {
                    sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
                }
                if (bCharge)
                {
                    for (i = 0; i < ngid; i++)
                    {
                        sum_UgembU[e++] +=
                            (enerd->grpp.ener[egCOULSR][GID(i, gid_tp, ngid)] +
                             enerd->grpp.ener[egCOULLR][GID(i, gid_tp, ngid)])*embU;
                    }
                    if (bRFExcl)
                    {
                        sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
                    }
                    if (EEL_FULL(fr->eeltype))
                    {
                        sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
                    }
                }
            }

            if (embU == 0 || beta*epot > bU_bin_limit)
            {
                bin[0]++;
            }
            else
            {
                i = (int)((bU_logV_bin_limit
                           - (beta*epot - logV + refvolshift))*invbinw
                          + 0.5);
                if (i < 0)
                {
                    i = 0;
                }
                if (i >= nbin)
                {
                    realloc_bins(&bin, &nbin, i+10);
                }
                bin[i]++;
            }

            if (debug)
            {
                fprintf(debug, "TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
                        (int)step, epot, x_tp[XX], x_tp[YY], x_tp[ZZ]);
            }

            if (dump_pdb && epot <= dump_ener)
            {
                sprintf(str, "t%g_step%d.pdb", t, (int)step);
                sprintf(str2, "t: %f step %d ener: %f", t, (int)step, epot);
                write_sto_conf_mtop(str, str2, top_global, state->x, state->v,
                                    inputrec->ePBC, state->box);
            }

            step++;
            if ((step/stepblocksize) % cr->nnodes != cr->nodeid)
            {
                /* Skip all steps assigned to the other MPI ranks */
                step += (cr->nnodes - 1)*stepblocksize;
            }
        }

        if (PAR(cr))
        {
            /* When running in parallel sum the energies over the processes */
            gmx_sumd(1,    &sum_embU, cr);
            gmx_sumd(nener, sum_UgembU, cr);
        }

        frame++;
        V_all     += V;
        VembU_all += V*sum_embU/nsteps;

        if (fp_tpi)
        {
            if (bVerbose || frame%10 == 0 || frame < 10)
            {
                fprintf(stderr, "mu %10.3e <mu> %10.3e\n",
                        -log(sum_embU/nsteps)/beta, -log(VembU_all/V_all)/beta);
            }

            fprintf(fp_tpi, "%10.3f %12.5e %12.5e %12.5e %12.5e",
                    t,
                    VembU_all == 0 ? 20/beta : -log(VembU_all/V_all)/beta,
                    sum_embU == 0  ? 20/beta : -log(sum_embU/nsteps)/beta,
                    sum_embU/nsteps, V);
            for (e = 0; e < nener; e++)
            {
                fprintf(fp_tpi, " %12.5e", sum_UgembU[e]/nsteps);
            }
            fprintf(fp_tpi, "\n");
            fflush(fp_tpi);
        }

        bNotLastFrame = read_next_frame(oenv, status, &rerun_fr);
    } /* End of the loop  */
    walltime_accounting_end(walltime_accounting);

    close_trj(status);

    if (fp_tpi != NULL)
    {
        gmx_fio_fclose(fp_tpi);
    }

    if (fplog != NULL)
    {
        fprintf(fplog, "\n");
        fprintf(fplog, "  <V>  = %12.5e nm^3\n", V_all/frame);
        fprintf(fplog, "  <mu> = %12.5e kJ/mol\n", -log(VembU_all/V_all)/beta);
    }

    /* Write the Boltzmann factor histogram */
    if (PAR(cr))
    {
        /* When running in parallel sum the bins over the processes */
        i = nbin;
        global_max(cr, &i);
        realloc_bins(&bin, &nbin, i);
        gmx_sumd(nbin, bin, cr);
    }
    if (MASTER(cr))
    {
        fp_tpi = xvgropen(opt2fn("-tpid", nfile, fnm),
                          "TPI energy distribution",
                          "\\betaU - log(V/<V>)", "count", oenv);
        sprintf(str, "number \\betaU > %g: %9.3e", bU_bin_limit, bin[0]);
        xvgr_subtitle(fp_tpi, str, oenv);
        xvgr_legend(fp_tpi, 2, (const char **)tpid_leg, oenv);
        for (i = nbin-1; i > 0; i--)
        {
            bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
            fprintf(fp_tpi, "%6.2f %10d %12.5e\n",
                    bUlogV,
                    (int)(bin[i]+0.5),
                    bin[i]*exp(-bUlogV)*V_all/VembU_all);
        }
        gmx_fio_fclose(fp_tpi);
    }
    sfree(bin);

    sfree(sum_UgembU);

    walltime_accounting_set_nsteps_done(walltime_accounting, frame*inputrec->nsteps);

    return 0;
}
Esempio n. 8
0
static char *insert_mols(const char *mol_insrt, int nmol_insrt, int ntry, int seed,
                         t_atoms *atoms, rvec **x, real **r, int ePBC, matrix box,
                         gmx_atomprop_t aps, 
                         real r_distance, real r_scale, real rshell,
                         const output_env_t oenv,
                         const char* posfn, const rvec deltaR, int enum_rot,
                         gmx_bool bCheckAllPairDist)
{
    t_pbc            pbc;
    static  char    *title_insrt;
    t_atoms          atoms_insrt;
    rvec            *x_insrt, *x_n;
    real            *r_insrt;
    int              ePBC_insrt;
    matrix           box_insrt;
    int              i, mol, onr, ncol;
    real             alfa = 0., beta = 0., gamma = 0.;
    rvec             offset_x;
    int              trial;
    double         **rpos;

    set_pbc(&pbc, ePBC, box);

    /* read number of atoms of insert molecules */
    get_stx_coordnum(mol_insrt, &atoms_insrt.nr);
    if (atoms_insrt.nr == 0)
    {
        gmx_fatal(FARGS, "No molecule in %s, please check your input\n", mol_insrt);
    }
    /* allocate memory for atom coordinates of insert molecules */
    snew(x_insrt, atoms_insrt.nr);
    snew(r_insrt, atoms_insrt.nr);
    snew(atoms_insrt.resinfo, atoms_insrt.nr);
    snew(atoms_insrt.atomname, atoms_insrt.nr);
    snew(atoms_insrt.atom, atoms_insrt.nr);
    atoms_insrt.pdbinfo = NULL;
    snew(x_n, atoms_insrt.nr);
    snew(title_insrt, STRLEN);

    /* read residue number, residue names, atomnames, coordinates etc. */
    fprintf(stderr, "Reading molecule configuration \n");
    read_stx_conf(mol_insrt, title_insrt, &atoms_insrt, x_insrt, NULL,
                  &ePBC_insrt, box_insrt);
    fprintf(stderr, "%s\nContaining %d atoms in %d residue\n",
            title_insrt, atoms_insrt.nr, atoms_insrt.nres);
    srenew(atoms_insrt.resinfo, atoms_insrt.nres);

    /* initialise van der waals arrays of insert molecules */
    mk_vdw(&atoms_insrt, r_insrt, aps, r_distance, r_scale);

    /* With -ip, take nmol_insrt from file posfn */
    if (posfn != NULL)
    {
        nmol_insrt = read_xvg(posfn, &rpos, &ncol);
        if (ncol != 3)
        {
            gmx_fatal(FARGS, "Expected 3 columns (x/y/z coordinates) in file %s\n", ncol, posfn);
        }
        fprintf(stderr, "Read %d positions from file %s\n\n", nmol_insrt, posfn);
    }

    srenew(atoms->resinfo, (atoms->nres+nmol_insrt*atoms_insrt.nres));
    srenew(atoms->atomname, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(atoms->atom, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*x, (atoms->nr+atoms_insrt.nr*nmol_insrt));
    srenew(*r, (atoms->nr+atoms_insrt.nr*nmol_insrt));

    trial = mol = 0;
    while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
    {
        fprintf(stderr, "\rTry %d", trial++);
        for (i = 0; (i < atoms_insrt.nr); i++)
        {
            copy_rvec(x_insrt[i], x_n[i]);
        }
        switch (enum_rot)
        {
            case en_rotXYZ:
                alfa  = 2*M_PI *rando(&seed);
                beta  = 2*M_PI *rando(&seed);
                gamma = 2*M_PI *rando(&seed);
                break;
            case en_rotZ:
                alfa  = beta = 0.;
                gamma = 2*M_PI*rando(&seed);
                break;
            case en_rotNone:
                alfa = beta = gamma = 0.;
                break;
        }
        if (enum_rot == en_rotXYZ || (enum_rot == en_rotZ))
        {
            rotate_conf(atoms_insrt.nr, x_n, NULL, alfa, beta, gamma);
        }
        if (posfn == NULL)
        {
            /* insert at random positions */
            offset_x[XX] = box[XX][XX]*rando(&seed);
            offset_x[YY] = box[YY][YY]*rando(&seed);
            offset_x[ZZ] = box[ZZ][ZZ]*rando(&seed);
            gen_box(0, atoms_insrt.nr, x_n, box_insrt, offset_x, TRUE);
            if (!in_box(&pbc, x_n[0]) || !in_box(&pbc, x_n[atoms_insrt.nr-1]))
            {
                continue;
            }
        }
        else
        {
            /* Insert at positions taken from option -ip file */
            offset_x[XX] = rpos[XX][mol] + deltaR[XX]*(2*rando(&seed)-1);
            offset_x[YY] = rpos[YY][mol] + deltaR[YY]*(2*rando(&seed)-1);
            offset_x[ZZ] = rpos[ZZ][mol] + deltaR[ZZ]*(2*rando(&seed)-1);
            for (i = 0; i < atoms_insrt.nr; i++)
            {
                rvec_inc(x_n[i], offset_x);
            }
        }

        onr = atoms->nr;

        /* This is a (maybe) slow workaround to avoid too many calls of add_conf, which
         * leaks memory (status May 2012). If the momory leaks in add_conf() are fixed,
         * this check could be removed. Note, however, that allPairsDistOk is probably
         * even faster than add_conf() when inserting a small molecule into a moderately
         * small system.
         */
        if (bCheckAllPairDist && !allPairsDistOk(atoms, *x, *r, ePBC, box, &atoms_insrt, x_n, r_insrt))
        {
            continue;
        }

        add_conf(atoms, x, NULL, r, FALSE, ePBC, box, TRUE,
                 &atoms_insrt, x_n, NULL, r_insrt, FALSE, rshell, 0, oenv);

        if (atoms->nr == (atoms_insrt.nr+onr))
        {
            mol++;
            fprintf(stderr, " success (now %d atoms)!\n", atoms->nr);
        }
    }
    srenew(atoms->resinfo,  atoms->nres);
    srenew(atoms->atomname, atoms->nr);
    srenew(atoms->atom,     atoms->nr);
    srenew(*x,              atoms->nr);
    srenew(*r,              atoms->nr);

    fprintf(stderr, "\n");
    /* print number of molecules added */
    fprintf(stderr, "Added %d molecules (out of %d requested) of %s\n",
            mol, nmol_insrt, *atoms_insrt.resinfo[0].name);

    return title_insrt;
}