Exemplo n.º 1
0
void calc_rotmatrix(rvec principal_axis, rvec targetvec, matrix rotmatrix)
{
	rvec rotvec;
	real ux,uy,uz,costheta,sintheta;
	
	costheta = cos_angle(principal_axis,targetvec);
	sintheta=sqrt(1.0-costheta*costheta); /* sign is always positive since 0<theta<pi */
                
	/* Determine rotation from cross product with target vector */
	cprod(principal_axis,targetvec,rotvec);
	unitv(rotvec,rotvec);
	printf("Aligning %g %g %g to %g %g %g : xprod  %g %g %g\n",
		principal_axis[XX],principal_axis[YY],principal_axis[ZZ],targetvec[XX],targetvec[YY],targetvec[ZZ],
		rotvec[XX],rotvec[YY],rotvec[ZZ]);
		
	ux=rotvec[XX]; 
	uy=rotvec[YY]; 
	uz=rotvec[ZZ]; 
	rotmatrix[0][0]=ux*ux + (1.0-ux*ux)*costheta;
	rotmatrix[0][1]=ux*uy*(1-costheta)-uz*sintheta;
	rotmatrix[0][2]=ux*uz*(1-costheta)+uy*sintheta;
	rotmatrix[1][0]=ux*uy*(1-costheta)+uz*sintheta;
	rotmatrix[1][1]=uy*uy + (1.0-uy*uy)*costheta;
	rotmatrix[1][2]=uy*uz*(1-costheta)-ux*sintheta;
	rotmatrix[2][0]=ux*uz*(1-costheta)-uy*sintheta;
	rotmatrix[2][1]=uy*uz*(1-costheta)+ux*sintheta;
	rotmatrix[2][2]=uz*uz + (1.0-uz*uz)*costheta;
	
	printf("Rotation matrix: \n%g %g %g\n%g %g %g\n%g %g %g\n",
		rotmatrix[0][0],rotmatrix[0][1],rotmatrix[0][2],
		rotmatrix[1][0],rotmatrix[1][1],rotmatrix[1][2],
		rotmatrix[2][0],rotmatrix[2][1],rotmatrix[2][2]);
}
Exemplo n.º 2
0
void norm_and_scale_vectors(int nframes,real c1[],real scale)
{
  int  j,m;
  real *rij;
  
  for(j=0; (j<nframes); j++) {
    rij = &(c1[j*DIM]);
    unitv(rij,rij);
    for(m=0; (m<DIM); m++)
      rij[m]*=scale;
  }
}
Exemplo n.º 3
0
static void calc_axes(rvec x[],t_atom atom[],int gnx[],atom_id *index[],
		      gmx_bool bRot,t_bundle *bun)
{
  int  end,i,div,d;
  real *mtot,m;
  rvec axis[MAX_ENDS],cent;
  
  snew(mtot,bun->n);

  for(end=0; end<bun->nend; end++) {
    for(i=0; i<bun->n; i++) {
      clear_rvec(bun->end[end][i]);
      mtot[i] = 0;
    }
    div = gnx[end]/bun->n;
    for(i=0; i<gnx[end]; i++) {
      m = atom[index[end][i]].m;
      for(d=0; d<DIM; d++)
	bun->end[end][i/div][d] += m*x[index[end][i]][d];
      mtot[i/div] += m;
    }
    clear_rvec(axis[end]);
    for(i=0; i<bun->n; i++) {
      svmul(1.0/mtot[i],bun->end[end][i],bun->end[end][i]);
      rvec_inc(axis[end],bun->end[end][i]);
    }
    svmul(1.0/bun->n,axis[end],axis[end]);
  }
  sfree(mtot);

  rvec_add(axis[0],axis[1],cent);
  svmul(0.5,cent,cent);
  /* center the bundle on the origin */
  for(end=0; end<bun->nend; end++) {
    rvec_dec(axis[end],cent);
    for(i=0; i<bun->n; i++)
      rvec_dec(bun->end[end][i],cent);
  }
  if (bRot) {
    /* rotate the axis parallel to the z-axis */
    rotate_ends(bun,axis[0],YY,ZZ);
    rotate_ends(bun,axis[0],XX,ZZ);
  }
  for(i=0; i<bun->n; i++) {
    rvec_add(bun->end[0][i],bun->end[1][i],bun->mid[i]);
    svmul(0.5,bun->mid[i],bun->mid[i]);
    rvec_sub(bun->end[0][i],bun->end[1][i],bun->dir[i]);
    bun->len[i] = norm(bun->dir[i]);
    unitv(bun->dir[i],bun->dir[i]);
  }
}
Exemplo n.º 4
0
static void rotate_ends(t_bundle *bun,rvec axis,int c0,int c1)
{
  int  end,i;
  rvec ax,tmp;

  unitv(axis,ax);
  for(end=0; end<bun->nend; end++)
    for(i=0; i<bun->n; i++) {
      copy_rvec(bun->end[end][i],tmp);
      bun->end[end][i][c0] = ax[c1]*tmp[c0] - ax[c0]*tmp[c1];
      bun->end[end][i][c1] = ax[c0]*tmp[c0] + ax[c1]*tmp[c1];
    }
  copy_rvec(axis,tmp);
  axis[c0] = ax[c1]*tmp[c0] - ax[c0]*tmp[c1];
  axis[c1] = ax[c0]*tmp[c0] + ax[c1]*tmp[c1];
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
static void do_sdf(char *fnNDX,char *fnTPS,char *fnTRX, char *fnSDF, 
                   char *fnREF, bool bRef, rvec cutoff, real binwidth,
                   int mode, rvec triangle, rvec dtri)
{
  FILE       *fp;
  int        status;
  int        ng,natoms,i,j,k,l,X,Y,Z,lc,dest;
  ivec       nbin;
  int        ***count;
  /* real       ***sdf; */
  real       sdf,min_sdf=1e10,max_sdf=0;
  char       **grpname;
  int        *isize;
  int        isize_cg=0;
  int        isize_ref=3;
  int        ref_resind[3];
  int        nrefmol=0,refc=0;
  atom_id    **index;
  atom_id    *index_cg=NULL;
  atom_id    *index_ref=NULL;
  real       t,boxmin,hbox,normfac;
  real       invbinw;
  rvec       tri_upper,tri_lower;
  rvec       *x,xcog,dx,*x_i1,xi,*x_refmol;
  matrix     box;
  matrix     rot; /* rotation matrix := unit vectors for the molecule frame */
  rvec       k_mol,i1_mol,i2_mol,dx_mol;
  real       delta;
  atom_id    ix,jx;
  t_topology top;
  int        ePBC=-1;
  t_pbc      pbc;
  bool       bTop=FALSE,bRefDone=FALSE,bInGroup=FALSE;
  char       title[STRLEN];


  /* Read Topology */
  if (fnTPS) {
    bTop=read_tps_conf(fnTPS,title,&top,&ePBC,&x,NULL,box,TRUE);
  }
  


  if ( !bTop ) {
    fprintf(stderr,"\nNeed tpr-file to make a reference structure.\n");
    fprintf(stderr,"Option -r will be ignored!\n");
    bRef = FALSE;
  }


  /* Allocate memory for 4 groups, 3 dummy groups and a group for the ref 
structure if needed */
  ng = 4;
  snew(grpname,ng);
  /* the dummy groups are used to dynamically store triples of atoms */
  /* for molecular coordinate systems */
  if ( bRef )
    {
      snew(isize,ng+4);
      snew(index,ng+4);
    }
  else 
    {
      snew(isize,ng+3);
      snew(index,ng+3);
    }


  /* Read the index groups */
  fprintf(stderr,"\nSelect the 3 reference groups and the SDF group:\n");
  if (fnTPS)
    get_index(&top.atoms,fnNDX,ng,isize,index,grpname);
  else
    rd_index(fnNDX,ng,isize,index,grpname);


  isize[NDX_REF1]=isize[G_REF1];
  for (i=NDX_REF1; i<=NDX_REF3; i++)
    snew(index[i],isize[NDX_REF1]);


  /* Read first frame and check it */
  natoms=read_first_x(&status,fnTRX,&t,&x,box);
  if ( !natoms )
    gmx_fatal(FARGS,"Could not read coordinates from statusfile!\n");


  /* check with topology */
  if (fnTPS)
    if ( natoms > top.atoms.nr )
      gmx_fatal(FARGS,"Trajectory (%d atoms) does not match topology (%d atoms)!\n",
                  natoms,top.atoms.nr);


  /* check with index groups */
  for (i=0; i<ng; i++)
    for (j=0; j<isize[i]; j++)
      if ( index[i][j] >= natoms )
        gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) larger "
                    "than number of atoms in trajectory (%d atoms)!\n",
                    index[i][j],grpname[i],isize[i],natoms);


  /* check reference groups */
  if ( mode == 1 )
    {
      if ( isize[G_REF1] != isize[G_REF2] || isize[G_REF1] != isize[G_REF3] || 
           isize[G_REF2] != isize[G_REF3] )
        gmx_fatal(FARGS,"For single particle SDF, all reference groups"
                    "must have the same size.\n");


      /* for single particle SDF dynamic triples are not needed */
      /* so we build them right here */


      /* copy all triples from G_REFx to NDX_REFx */    
      for (i=0; i<isize[G_REF1]; i++)
        {
          /* check if all three atoms come from the same molecule */
          for (j=G_REF1; j<=G_REF3; j++)
            ref_resind[j] = top.atoms.atom[index[j][i]].resind;


          if ( ref_resind[G_REF1] != ref_resind[G_REF2] ||
                 ref_resind[G_REF2] != ref_resind[G_REF3] ||
                 ref_resind[G_REF3] != ref_resind[G_REF1] )
              {
                fprintf(stderr,"\nWarning: reference triple (%d) will be skipped.\n",i);
                fprintf(stderr,  "         resnr[1]: %d, resnr[2]: %d, resnr[3]: %d\n",
                        ref_resind[G_REF1],ref_resind[G_REF2], ref_resind[G_REF3]);
                isize[NDX_REF1]--;
                for (j=NDX_REF1; j<=NDX_REF3; j++)
                  srenew(index[j],isize[NDX_REF1]);
                continue;
              }
          else
            /* check if all entries are unique*/
            if ( index[G_REF1][i] == index[G_REF2][i] ||
                 index[G_REF2][i] == index[G_REF3][i] ||
                 index[G_REF3][i] == index[G_REF1][i] )
              {
                fprintf(stderr,"Warning: reference triple (%d) will be skipped.\n",i);
                fprintf(stderr,  "         index[1]: %d, index[2]: %d, index[3]: %d\n",
                        index[G_REF1][i],index[G_REF2][i],index[G_REF3][i]);    
                isize[NDX_REF1]--;
                for (j=NDX_REF1; j<=NDX_REF3; j++)
                  srenew(index[j],isize[NDX_REF1]);
                continue;
              }
            else /* everythings fine, copy that one */
              for (j=G_REF1; j<=G_REF3; j++)
                index[j+4][i] = index[j][i];
        }
    }
  else if ( mode == 2 )
    {
      if ( isize[G_REF1] != isize[G_REF2] )
        gmx_fatal(FARGS,"For two particle SDF, reference groups 1 and 2"
                    "must have the same size.\n");


      for (i=0; i<isize[G_REF1]; i++)
        {
          /* check consistency for atoms 1 and 2 */
          for (j=G_REF1; j<=G_REF2; j++)
            ref_resind[j] = top.atoms.atom[index[j][i]].resind;


          if ( ref_resind[G_REF1] != ref_resind[G_REF2] ||
               index[G_REF1][i] == index[G_REF2][i] )
            {
              if ( ref_resind[G_REF1] != ref_resind[G_REF2] )
                {
                  fprintf(stderr,"\nWarning: bond (%d) not from one molecule."
                          "Will not be used for SDF.\n",i);
                  fprintf(stderr,  "         resnr[1]: %d, resnr[2]: %d\n",
                          ref_resind[G_REF1],ref_resind[G_REF2]);
                }
              else
                {
                  fprintf(stderr,"\nWarning: atom1 and atom2 are identical."
                          "Bond (%d) will not be used for SDF.\n",i);
                  fprintf(stderr,  "         index[1]: %d, index[2]: %d\n",
                          index[G_REF1][i],index[G_REF2][i]);
                }
              for (j=NDX_REF1; j<=NDX_REF2; j++)
                {
                  for (k=i; k<isize[G_REF1]-1; k++)
                    index[j][k]=index[j][k+1];
                  isize[j]--;
                  srenew(index[j],isize[j]);
                }
            }
        }
    }


  /* Read Atoms for refmol group */
  if ( bRef )
    {
      snew(index[G_REFMOL],1);


      for (i=G_REF1; i<=G_REF3; i++)
        ref_resind[i] = top.atoms.atom[index[i][0]].resind;


      for (i=0; i<natoms; i++)
        {
          if (  ref_resind[G_REF1] == top.atoms.atom[i].resind ||
                ref_resind[G_REF2] == top.atoms.atom[i].resind ||
                ref_resind[G_REF3] == top.atoms.atom[i].resind )
            nrefmol++;
        }
      srenew(index[G_REFMOL],nrefmol);
      isize[G_REFMOL] = nrefmol;
      nrefmol = 0;


      for (i=0; i<natoms; i++)
        {
          if (  ref_resind[G_REF1] == top.atoms.atom[i].resind ||
                ref_resind[G_REF2] == top.atoms.atom[i].resind ||
                ref_resind[G_REF3] == top.atoms.atom[i].resind )
            {
              index[G_REFMOL][nrefmol] = i;
              nrefmol++;
            }
        }
    }


  /* initialize some stuff */
  boxmin = min( norm(box[XX]), min( norm(box[YY]), norm(box[ZZ]) ) );
  hbox   = boxmin / 2.0;


  for (i=0; i<DIM; i++)
    {
      cutoff[i] = cutoff[i] / 2;
      nbin[i]   = (int)(2 * cutoff[i] / binwidth) + 1;
      invbinw = 1.0 / binwidth;
      tri_upper[i] = triangle[i] + dtri[i];
      tri_upper[i] = sqr(tri_upper[i]);
      tri_lower[i] = triangle[i] - dtri[i];
      tri_lower[i] = sqr(tri_lower[i]);
    }


  /* Allocate the array's for sdf */
  snew(count,nbin[0]+1);
  for(i=0; i<nbin[0]+1; i++) 
    {
      snew(count[i],nbin[1]+1);
      for (j=0; j<nbin[1]+1; j++) 
        snew(count[i][j],nbin[2]+1);
    }


  /* Allocate space for the coordinates */
  snew(x_i1,isize[G_SDF]);
  snew(x_refmol,isize[G_REFMOL]);
  for (i=0; i<isize[G_REFMOL]; i++)
    for (j=XX; j<=ZZ; j++)
      x_refmol[i][j] = 0;


  normfac = 0;


  do {
    /* Must init pbc every step because of pressure coupling */
    set_pbc(&pbc,ePBC,box);
    rm_pbc(&top.idef,ePBC,natoms,box,x,x);


    /* Dynamically build the ref tripels */
    if ( mode == 2 )
      {
        isize[NDX_REF1]=0;
        for (j=NDX_REF1; j<=NDX_REF3; j++)
          srenew(index[j],isize[NDX_REF1]+1);


        /* consistancy of G_REF[1,2] has already been check */
        /* hence we can look for the third atom right away */


        for (i=0; i<isize[G_REF1]; i++)
          {
            for (j=0; j<isize[G_REF3]; j++)
              {
                /* Avoid expensive stuff if possible */
                if ( top.atoms.atom[index[G_REF1][i]].resind != 
                     top.atoms.atom[index[G_REF3][j]].resind &&
                     index[G_REF1][i] != index[G_REF3][j] &&
                     index[G_REF2][i] != index[G_REF3][j] )
                  {
                    pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF3][j]],dx);
                    delta = norm2(dx);
                    if ( delta < tri_upper[G_REF1] &&
                         delta > tri_lower[G_REF1] )
                      {
                        pbc_dx(&pbc,x[index[G_REF2][i]],x[index[G_REF3][j]],dx);
                        delta = norm2(dx);
                        if ( delta < tri_upper[G_REF2] &&
                             delta > tri_lower[G_REF2] )
                          {
                            /* found triple */
                            index[NDX_REF1][isize[NDX_REF1]]=index[G_REF1][i];
                            index[NDX_REF2][isize[NDX_REF1]]=index[G_REF2][i];
                            index[NDX_REF3][isize[NDX_REF1]]=index[G_REF3][j];


                            /* resize groups */
                            isize[NDX_REF1]++;
                            for (k=NDX_REF1; k<=NDX_REF3; k++)
                              srenew(index[k],isize[NDX_REF1]+1);
                          }
                      }
                  }
              }
          }
      }
    else if ( mode ==3 )
      {
        isize[NDX_REF1]=0;
        for (j=NDX_REF1; j<=NDX_REF3; j++)
          srenew(index[j],isize[NDX_REF1]+1);

        /* consistancy will be checked while searching */


        for (i=0; i<isize[G_REF1]; i++)
          {
            for (j=0; j<isize[G_REF2]; j++)
              {
                /* Avoid expensive stuff if possible */
                if ( top.atoms.atom[index[G_REF1][i]].resind != 
                     top.atoms.atom[index[G_REF2][j]].resind &&
                     index[G_REF1][i] != index[G_REF2][j] )
                  {
                    pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF2][j]],dx);
                    delta = norm2(dx);
                    if ( delta < tri_upper[G_REF3] &&
                         delta > tri_lower[G_REF3] )
                      {
                        for (k=0; k<isize[G_REF3]; k++)
                          {
                            if ( top.atoms.atom[index[G_REF1][i]].resind != 
                                 top.atoms.atom[index[G_REF3][k]].resind &&
                                 top.atoms.atom[index[G_REF2][j]].resind != 
                                 top.atoms.atom[index[G_REF3][k]].resind &&
                                 index[G_REF1][i] != index[G_REF3][k] &&
                                 index[G_REF2][j] != index[G_REF3][k])
                              {
                                pbc_dx(&pbc,x[index[G_REF1][i]],x[index[G_REF3][k]],dx);
                                delta = norm2(dx);
                                if ( delta < tri_upper[G_REF1] &&
                                     delta > tri_lower[G_REF1] )
                                  {
                                    pbc_dx(&pbc,x[index[G_REF2][j]],x[index[G_REF3][k]],dx);
                                    delta = norm2(dx);
                                    if ( delta < tri_upper[G_REF2] &&
                                         delta > tri_lower[G_REF2] )
                                      {
                                        /* found triple */
                                        index[NDX_REF1][isize[NDX_REF1]]=index[G_REF1][i];
                                        index[NDX_REF2][isize[NDX_REF1]]=index[G_REF2][j];
                                        index[NDX_REF3][isize[NDX_REF1]]=index[G_REF3][k];
                                    
                                        /* resize groups */
                                        isize[NDX_REF1]++;
                                        for (l=NDX_REF1; l<=NDX_REF3; l++)
                                          srenew(index[l],isize[NDX_REF1]+1);
                                      }
                                  }
                              }
                          }
                      }
                  }
              }
          }
      }
 
    for (i=0; i<isize[NDX_REF1]; i++)
      {
        /* setup the molecular coordinate system (i',j',k') */
        /* because the coodinate system of the box forms a unit matrix */
        /* (i',j',k') is identical with the rotation matrix */
        clear_mat(rot);


        /* k' = unitv(r(atom0) - r(atom1)) */
        pbc_dx(&pbc,x[index[NDX_REF1][i]],x[index[NDX_REF2][i]],k_mol);
        unitv(k_mol,rot[2]);
        
        /* i' = unitv(k' x (r(atom2) - r(atom1))) */
        pbc_dx(&pbc,x[index[NDX_REF3][i]],x[index[NDX_REF2][i]],i1_mol);
        cprod(i1_mol,rot[2],i2_mol);
        unitv(i2_mol,rot[0]);
      
        /* j' = k' x i' */
        cprod(rot[2],rot[0],rot[1]);


        /* set the point of reference */
        if ( mode == 2 )
          copy_rvec(x[index[NDX_REF3][i]],xi);
        else
          copy_rvec(x[index[NDX_REF1][i]],xi);


        /* make the reference */
        if ( bRef )
          {
            for (j=0; j<isize[G_REFMOL]; j++)
              {
                pbc_dx(&pbc,xi,x[index[G_REFMOL][j]],dx);
                mvmul(rot,dx,dx_mol);
                rvec_inc(x_refmol[j],dx_mol);
                for(k=XX; k<=ZZ; k++)
                   x_refmol[j][k] = x_refmol[j][k] / 2;
              }
          }


        /* Copy the indexed coordinates to a continuous array */
        for(j=0; j<isize[G_SDF]; j++)
          copy_rvec(x[index[G_SDF][j]],x_i1[j]);
        
        /* count the SDF */
        for(j=0; j<isize[G_SDF]; j++) 
          {
            /* Exclude peaks from the reference set */
            bInGroup=FALSE;
            for (k=NDX_REF1; k<=NDX_REF3; k++)
              if ( index[G_SDF][j] == index[k][i] )
                bInGroup=TRUE;


            if ( !bInGroup )
              {
                pbc_dx(&pbc,xi,x_i1[j],dx);
            
                /* transfer dx to the molecular coordinate system */
                mvmul(rot,dx,dx_mol);


                /* check cutoff's and count */
                if ( dx_mol[XX] > -cutoff[XX] && dx_mol[XX] < cutoff[XX] )
                  if ( dx_mol[YY] > -cutoff[YY] && dx_mol[YY] < cutoff[YY] )
                    if ( dx_mol[ZZ] > -cutoff[ZZ] && dx_mol[ZZ] < cutoff[ZZ] )
                      {
                        X = (int)(floor(dx_mol[XX]*invbinw)) + (nbin[XX]-1)/2 
+1;
                        Y = (int)(floor(dx_mol[YY]*invbinw)) + (nbin[YY]-1)/2 
+1;
                        Z = (int)(floor(dx_mol[ZZ]*invbinw)) + (nbin[ZZ]-1)/2 
+1;
                        count[X][Y][Z]++;
                        normfac++;
                      }
              }
          }
      }
  } while (read_next_x(status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  close_trj(status);
  
  sfree(x);


  /* write the reference strcture*/
  if ( bRef )
    {
      fp=ffopen(fnREF,"w"); 
      fprintf(fp,"%s\n",title);
      fprintf(fp,"  %d\n",isize[G_REFMOL]);


      for (i=0; i<isize[G_REFMOL]; i++)
        fprintf(fp,"%5d%5s%5s%5d%8.3f%8.3f%8.3f\n",
                top.atoms.resinfo[top.atoms.atom[index[G_REFMOL][i]].resind].nr,
                *(top.atoms.resinfo[top.atoms.atom[index[G_REFMOL][i]].resind].name),
                *(top.atoms.atomname[index[G_REFMOL][i]]),i+1,
                -1*x_refmol[i][XX],-1*x_refmol[i][YY],-1*x_refmol[i][ZZ]);
      /* Inserted -1* on the line above three times */
      fprintf(fp,"   10.00000   10.00000   10.00000\n");
      ffclose(fp);
      fprintf(stderr,"\nWrote reference structure. (%d Atoms)\n",isize[G_REFMOL]);
    }


  /* Calculate the mean probability density */
  fprintf(stderr,"\nNumber of configuations used for SDF: %d\n",(int)normfac);


  normfac = nbin[0]*nbin[1]*nbin[2] / normfac;


  fprintf(stderr,"\nMean probability density: %f\n",1/normfac);


  /* normalize the SDF and write output */
  /* see http://www.csc.fi/gopenmol/index.phtml for documentation */
  fp=ffopen(fnSDF,"wb"); 


  /* rank */
  i_write(fp,3);


  /* Type of surface */
  i_write(fp,42);


  /* Zdim, Ydim, Xdim */
  for (i=ZZ; i>=XX; i--)
    i_write(fp,nbin[i]);


  /* [Z,Y,X][min,max] (box corners in Angstroem)*/
  for (i=ZZ; i>=XX; i--)
    {
      f_write(fp,-cutoff[i]*10);
      f_write(fp,cutoff[i]*10);
    }


/* Original Code
  for (i=1; i<nbin[2]+1; i++)
    for (j=1; j<nbin[1]+1; j++)
      for (k=1; k<nbin[0]+1; k++) 
        {
          sdf = normfac * count[k][j][i];
          if ( sdf < min_sdf ) min_sdf = sdf;
          if ( sdf > max_sdf ) max_sdf = sdf;
          f_write(fp,sdf);
        }*/
/* Changed Code to Mirror SDF to correct coordinates */
  for (i=nbin[2]; i>0; i--)
    for (j=nbin[1]; j>0; j--)
      for (k=nbin[0]; k>0; k--)
        {
          sdf = normfac * count[k][j][i];
          if ( sdf < min_sdf ) min_sdf = sdf;
          if ( sdf > max_sdf ) max_sdf = sdf;
          f_write(fp,sdf);
        }

  fprintf(stderr,"\nMin: %f Max: %f\n",min_sdf,max_sdf);


  ffclose(fp); 


  /* Give back the mem */
  for(i=0; i<nbin[0]+1; i++)
    {
      for (j=0; j<nbin[1]+1; j++)
        {
          sfree(count[i][j]);
        }
      sfree(count[i]);
    }
  sfree(count);
}
Exemplo n.º 7
0
static void find_tetra_order_grid(t_topology top, int ePBC,
                                  int natoms, matrix box,
                                  rvec x[], int maxidx, atom_id index[],
                                  real time, real *sgmean, real *skmean,
                                  int nslicex, int nslicey, int nslicez,
                                  real ***sggrid, real ***skgrid)
{
    int         ix, jx, i, j, k, l, n, *nn[4];
    rvec        dx, rj, rk, urk, urj;
    real        cost, cost2, *sgmol, *skmol, rmean, rmean2, r2, box2, *r_nn[4];
    t_pbc       pbc;
    int         slindex_x, slindex_y, slindex_z;
    int      ***sl_count;
    real        onethird = 1.0/3.0;
    gmx_rmpbc_t gpbc;

    /*  dmat = init_mat(maxidx, FALSE); */

    box2 = box[XX][XX] * box[XX][XX];

    /* Initialize expanded sl_count array */
    snew(sl_count, nslicex);
    for (i = 0; i < nslicex; i++)
    {
        snew(sl_count[i], nslicey);
        for (j = 0; j < nslicey; j++)
        {
            snew(sl_count[i][j], nslicez);
        }
    }


    for (i = 0; (i < 4); i++)
    {
        snew(r_nn[i], natoms);
        snew(nn[i], natoms);

        for (j = 0; (j < natoms); j++)
        {
            r_nn[i][j] = box2;
        }
    }

    snew(sgmol, maxidx);
    snew(skmol, maxidx);

    /* Must init pbc every step because of pressure coupling */
    set_pbc(&pbc,ePBC,box);
    gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms, box);
    gmx_rmpbc(gpbc, natoms, box, x);

    *sgmean = 0.0;
    *skmean = 0.0;
    l       = 0;
    for (i = 0; (i < maxidx); i++)
    {   /* loop over index file */
        ix = index[i];
        for (j = 0; (j < maxidx); j++)
        {

            if (i == j)
            {
                continue;
            }

            jx = index[j];

            pbc_dx(&pbc, x[ix], x[jx], dx);
            r2 = iprod(dx, dx);

            /* set_mat_entry(dmat,i,j,r2); */

            /* determine the nearest neighbours */
            if (r2 < r_nn[0][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r_nn[1][i]; nn[2][i] = nn[1][i];
                r_nn[1][i] = r_nn[0][i]; nn[1][i] = nn[0][i];
                r_nn[0][i] = r2;         nn[0][i] = j;
            }
            else if (r2 < r_nn[1][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r_nn[1][i]; nn[2][i] = nn[1][i];
                r_nn[1][i] = r2;         nn[1][i] = j;
            }
            else if (r2 < r_nn[2][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r2;         nn[2][i] = j;
            }
            else if (r2 < r_nn[3][i])
            {
                r_nn[3][i] = r2;         nn[3][i] = j;
            }
        }


        /* calculate mean distance between nearest neighbours */
        rmean = 0;
        for (j = 0; (j < 4); j++)
        {
            r_nn[j][i] = sqrt(r_nn[j][i]);
            rmean     += r_nn[j][i];
        }
        rmean /= 4;

        n        = 0;
        sgmol[i] = 0.0;
        skmol[i] = 0.0;

        /* Chau1998a eqn 3 */
        /* angular part tetrahedrality order parameter per atom */
        for (j = 0; (j < 3); j++)
        {
            for (k = j+1; (k < 4); k++)
            {
                pbc_dx(&pbc, x[ix], x[index[nn[k][i]]], rk);
                pbc_dx(&pbc, x[ix], x[index[nn[j][i]]], rj);

                unitv(rk, urk);
                unitv(rj, urj);

                cost  = iprod(urk, urj) + onethird;
                cost2 = cost * cost;

                sgmol[i] += cost2;
                l++;
                n++;
            }
        }
        /* normalize sgmol between 0.0 and 1.0 */
        sgmol[i] = 3*sgmol[i]/32;
        *sgmean += sgmol[i];

        /* distance part tetrahedrality order parameter per atom */
        rmean2 = 4 * 3 * rmean * rmean;
        for (j = 0; (j < 4); j++)
        {
            skmol[i] += (rmean - r_nn[j][i]) * (rmean - r_nn[j][i]) / rmean2;
            /*      printf("%d %f (%f %f %f %f) \n",
                    i, skmol[i], rmean, rmean2, r_nn[j][i], (rmean - r_nn[j][i]) );
             */
        }

        *skmean += skmol[i];

        /* Compute sliced stuff in x y z*/
        slindex_x = gmx_nint((1+x[i][XX]/box[XX][XX])*nslicex) % nslicex;
        slindex_y = gmx_nint((1+x[i][YY]/box[YY][YY])*nslicey) % nslicey;
        slindex_z = gmx_nint((1+x[i][ZZ]/box[ZZ][ZZ])*nslicez) % nslicez;
        sggrid[slindex_x][slindex_y][slindex_z] += sgmol[i];
        skgrid[slindex_x][slindex_y][slindex_z] += skmol[i];
        (sl_count[slindex_x][slindex_y][slindex_z])++;
    } /* loop over entries in index file */

    *sgmean /= maxidx;
    *skmean /= maxidx;

    for (i = 0; (i < nslicex); i++)
    {
        for (j = 0; j < nslicey; j++)
        {
            for (k = 0; k < nslicez; k++)
            {
                if (sl_count[i][j][k] > 0)
                {
                    sggrid[i][j][k] /= sl_count[i][j][k];
                    skgrid[i][j][k] /= sl_count[i][j][k];
                }
            }
        }
    }

    sfree(sl_count);
    sfree(sgmol);
    sfree(skmol);
    for (i = 0; (i < 4); i++)
    {
        sfree(r_nn[i]);
        sfree(nn[i]);
    }
}
Exemplo n.º 8
0
int gmx_tcaf(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes tranverse current autocorrelations.",
        "These are used to estimate the shear viscosity, [GRK]eta[grk].",
        "For details see: Palmer, Phys. Rev. E 49 (1994) pp 359-366.[PAR]",
        "Transverse currents are calculated using the",
        "k-vectors (1,0,0) and (2,0,0) each also in the [IT]y[it]- and [IT]z[it]-direction,",
        "(1,1,0) and (1,-1,0) each also in the 2 other planes (these vectors",
        "are not independent) and (1,1,1) and the 3 other box diagonals (also",
        "not independent). For each k-vector the sine and cosine are used, in",
        "combination with the velocity in 2 perpendicular directions. This gives",
        "a total of 16*2*2=64 transverse currents. One autocorrelation is",
        "calculated fitted for each k-vector, which gives 16 TCAFs. Each of",
        "these TCAFs is fitted to [MATH]f(t) = [EXP]-v[exp]([COSH]Wv[cosh] + 1/W [SINH]Wv[sinh])[math],",
        "[MATH]v = -t/(2 [GRK]tau[grk])[math], [MATH]W = [SQRT]1 - 4 [GRK]tau[grk] [GRK]eta[grk]/[GRK]rho[grk] k^2[sqrt][math], which gives 16 values of [GRK]tau[grk]",
        "and [GRK]eta[grk]. The fit weights decay exponentially with time constant [MATH]w[math] (given with [TT]-wt[tt]) as [MATH][EXP]-t/w[exp][math], and the TCAF and",
        "fit are calculated up to time [MATH]5*w[math].",
        "The [GRK]eta[grk] values should be fitted to [MATH]1 - a [GRK]eta[grk](k) k^2[math], from which",
        "one can estimate the shear viscosity at k=0.[PAR]",
        "When the box is cubic, one can use the option [TT]-oc[tt], which",
        "averages the TCAFs over all k-vectors with the same length.",
        "This results in more accurate TCAFs.",
        "Both the cubic TCAFs and fits are written to [TT]-oc[tt]",
        "The cubic [GRK]eta[grk] estimates are also written to [TT]-ov[tt].[PAR]",
        "With option [TT]-mol[tt], the transverse current is determined of",
        "molecules instead of atoms. In this case, the index group should",
        "consist of molecule numbers instead of atom numbers.[PAR]",
        "The k-dependent viscosities in the [TT]-ov[tt] file should be",
        "fitted to [MATH][GRK]eta[grk](k) = [GRK]eta[grk][SUB]0[sub] (1 - a k^2)[math] to obtain the viscosity at",
        "infinite wavelength.[PAR]",
        "[BB]Note:[bb] make sure you write coordinates and velocities often enough.",
        "The initial, non-exponential, part of the autocorrelation function",
        "is very important for obtaining a good fit."
    };

    static gmx_bool   bMol = FALSE, bK34 = FALSE;
    static real       wt   = 5;
    t_pargs           pa[] = {
        { "-mol", FALSE, etBOOL, {&bMol},
          "Calculate TCAF of molecules" },
        { "-k34", FALSE, etBOOL, {&bK34},
          "Also use k=(3,0,0) and k=(4,0,0)" },
        { "-wt", FALSE, etREAL, {&wt},
          "Exponential decay time for the TCAF fit weights" }
    };

    t_topology        top;
    int               ePBC;
    t_trxframe        fr;
    matrix            box;
    gmx_bool          bTop;
    int               gnx;
    int              *index, *atndx = NULL, at;
    char             *grpname;
    char              title[256];
    real              t0, t1, dt, m, mtot, sysmass, rho, sx, cx;
    t_trxstatus      *status;
    int               nframes, n_alloc, i, j, k, d;
    rvec              mv_mol, cm_mol, kfac[NK];
    int               nkc, nk, ntc;
    real            **tc;
    gmx_output_env_t *oenv;

#define NHISTO 360

    t_filenm  fnm[] = {
        { efTRN, "-f",    NULL,      ffREAD  },
        { efTPS, NULL,    NULL,      ffOPTRD },
        { efNDX, NULL,    NULL,      ffOPTRD },
        { efXVG, "-ot",  "transcur", ffOPTWR },
        { efXVG, "-oa",  "tcaf_all", ffWRITE },
        { efXVG, "-o",   "tcaf",     ffWRITE },
        { efXVG, "-of",  "tcaf_fit", ffWRITE },
        { efXVG, "-oc",  "tcaf_cub", ffOPTWR },
        { efXVG, "-ov",  "visc_k",   ffWRITE }
    };
#define NFILE asize(fnm)
    int       npargs;
    t_pargs  *ppa;

    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);

    if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, NULL, NULL, box,
                         TRUE);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname);

    if (bMol)
    {
        if (!bTop)
        {
            gmx_fatal(FARGS, "Need a topology to determine the molecules");
        }
        atndx = top.mols.index;
    }

    if (bK34)
    {
        nkc = NKC;
    }
    else
    {
        nkc = NKC0;
    }
    nk  = kset_c[nkc];
    ntc = nk*NPK;

    sprintf(title, "Velocity Autocorrelation Function for %s", grpname);

    sysmass = 0;
    for (i = 0; i < nk; i++)
    {
        if (iprod(v0[i], v1[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        if (iprod(v0[i], v2[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        if (iprod(v1[i], v2[i]) != 0)
        {
            gmx_fatal(FARGS, "DEATH HORROR: vectors not orthogonal");
        }
        unitv(v1[i], v1[i]);
        unitv(v2[i], v2[i]);
    }
    snew(tc, ntc);
    for (i = 0; i < top.atoms.nr; i++)
    {
        sysmass += top.atoms.atom[i].m;
    }

    read_first_frame(oenv, &status, ftp2fn(efTRN, NFILE, fnm), &fr,
                     TRX_NEED_X | TRX_NEED_V);
    t0 = fr.time;

    n_alloc = 0;
    nframes = 0;
    rho     = 0;

    do
    {

        if (nframes >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < ntc; i++)
            {
                srenew(tc[i], n_alloc);
            }
        }

        rho += 1/det(fr.box);
        for (k = 0; k < nk; k++)
        {
            for (d = 0; d < DIM; d++)
            {
                kfac[k][d] = 2*M_PI*v0[k][d]/fr.box[d][d];
            }
        }
        for (i = 0; i < ntc; i++)
        {
            tc[i][nframes] = 0;
        }

        for (i = 0; i < gnx; i++)
        {
            if (bMol)
            {
                clear_rvec(mv_mol);
                clear_rvec(cm_mol);
                mtot = 0;
                for (j = 0; j < atndx[index[i]+1] - atndx[index[i]]; j++)
                {
                    at          = atndx[index[i]] + j;
                    m           = top.atoms.atom[at].m;
                    mv_mol[XX] += m*fr.v[at][XX];
                    mv_mol[YY] += m*fr.v[at][YY];
                    mv_mol[ZZ] += m*fr.v[at][ZZ];
                    cm_mol[XX] += m*fr.x[at][XX];
                    cm_mol[YY] += m*fr.x[at][YY];
                    cm_mol[ZZ] += m*fr.x[at][ZZ];
                    mtot       += m;
                }
                svmul(1.0/mtot, cm_mol, cm_mol);
            }
            else
            {
                svmul(top.atoms.atom[index[i]].m, fr.v[index[i]], mv_mol);
            }

            if (!bMol)
            {
                copy_rvec(fr.x[index[i]], cm_mol);
            }
            j = 0;
            for (k = 0; k < nk; k++)
            {
                sx              = std::sin(iprod(kfac[k], cm_mol));
                cx              = std::cos(iprod(kfac[k], cm_mol));
                tc[j][nframes] += sx*iprod(v1[k], mv_mol);
                j++;
                tc[j][nframes] += cx*iprod(v1[k], mv_mol);
                j++;
                tc[j][nframes] += sx*iprod(v2[k], mv_mol);
                j++;
                tc[j][nframes] += cx*iprod(v2[k], mv_mol);
                j++;
            }
        }

        t1 = fr.time;
        nframes++;
    }
    while (read_next_frame(oenv, status, &fr));
    close_trj(status);

    dt = (t1-t0)/(nframes-1);

    rho *= sysmass/nframes*AMU/(NANO*NANO*NANO);
    fprintf(stdout, "Density = %g (kg/m^3)\n", rho);
    process_tcaf(nframes, dt, nkc, tc, kfac, rho, wt,
                 opt2fn_null("-ot", NFILE, fnm),
                 opt2fn("-oa", NFILE, fnm), opt2fn("-o", NFILE, fnm),
                 opt2fn("-of", NFILE, fnm), opt2fn_null("-oc", NFILE, fnm),
                 opt2fn("-ov", NFILE, fnm), oenv);

    return 0;
}
Exemplo n.º 9
0
static void do_lincs(rvec *x,rvec *xp,matrix box,t_pbc *pbc,
                     struct gmx_lincsdata *lincsd,real *invmass,
					 t_commrec *cr,
                     real wangle,int *warn,
                     real invdt,rvec *v,
                     gmx_bool bCalcVir,tensor rmdr)
{
    int     b,i,j,k,n,iter;
    real    tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,len2,dlen2,wfac,lam;  
    rvec    dx;
    int     ncons,*bla,*blnr,*blbnb;
    rvec    *r;
    real    *blc,*blmf,*bllen,*blcc,*rhs1,*rhs2,*sol,*lambda;
    int     *nlocat;
    
    ncons  = lincsd->nc;
    bla    = lincsd->bla;
    r      = lincsd->tmpv;
    blnr   = lincsd->blnr;
    blbnb  = lincsd->blbnb;
    blc    = lincsd->blc;
    blmf   = lincsd->blmf;
    bllen  = lincsd->bllen;
    blcc   = lincsd->tmpncc;
    rhs1   = lincsd->tmp1;
    rhs2   = lincsd->tmp2;
    sol    = lincsd->tmp3;
    lambda = lincsd->lambda;
    
    if (DOMAINDECOMP(cr) && cr->dd->constraints)
    {
        nlocat = dd_constraints_nlocalatoms(cr->dd);
    }
    else if (PARTDECOMP(cr))
    {
        nlocat = pd_constraints_nlocalatoms(cr->pd);
    }
    else
    {
        nlocat = NULL;
    }
    
    *warn = 0;

    if (pbc)
    {
        /* Compute normalized i-j vectors */
        for(b=0; b<ncons; b++)
        {
            pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
            unitv(dx,r[b]);
        }  
        for(b=0; b<ncons; b++)
        {
            for(n=blnr[b]; n<blnr[b+1]; n++)
            {
                blcc[n] = blmf[n]*iprod(r[b],r[blbnb[n]]);
            }
            pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx);
            mvb = blc[b]*(iprod(r[b],dx) - bllen[b]);
            rhs1[b] = mvb;
            sol[b]  = mvb;
        }
    }
    else
    {
        /* Compute normalized i-j vectors */
        for(b=0; b<ncons; b++)
        {
            i = bla[2*b];
            j = bla[2*b+1];
            tmp0 = x[i][0] - x[j][0];
            tmp1 = x[i][1] - x[j][1];
            tmp2 = x[i][2] - x[j][2];
            rlen = gmx_invsqrt(tmp0*tmp0+tmp1*tmp1+tmp2*tmp2);
            r[b][0] = rlen*tmp0;
            r[b][1] = rlen*tmp1;
            r[b][2] = rlen*tmp2;
        } /* 16 ncons flops */
        
        for(b=0; b<ncons; b++)
        {
            tmp0 = r[b][0];
            tmp1 = r[b][1];
            tmp2 = r[b][2];
            len = bllen[b];
            i = bla[2*b];
            j = bla[2*b+1];
            for(n=blnr[b]; n<blnr[b+1]; n++)
            {
                k = blbnb[n];
                blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); 
            } /* 6 nr flops */
            mvb = blc[b]*(tmp0*(xp[i][0] - xp[j][0]) +
                          tmp1*(xp[i][1] - xp[j][1]) +    
                          tmp2*(xp[i][2] - xp[j][2]) - len);
            rhs1[b] = mvb;
            sol[b]  = mvb;
            /* 10 flops */
        }
        /* Together: 26*ncons + 6*nrtot flops */
    }
    
    lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
    /* nrec*(ncons+2*nrtot) flops */
    
    for(b=0; b<ncons; b++)
    {
        i = bla[2*b];
        j = bla[2*b+1];
        mvb = blc[b]*sol[b];
        lambda[b] = -mvb;
        im1 = invmass[i];
        im2 = invmass[j];
        tmp0 = r[b][0]*mvb;
        tmp1 = r[b][1]*mvb;
        tmp2 = r[b][2]*mvb;
        xp[i][0] -= tmp0*im1;
        xp[i][1] -= tmp1*im1;
        xp[i][2] -= tmp2*im1;
        xp[j][0] += tmp0*im2;
        xp[j][1] += tmp1*im2;
        xp[j][2] += tmp2*im2;
    } /* 16 ncons flops */


    /*     
     ********  Correction for centripetal effects  ********  
     */
  
    wfac = cos(DEG2RAD*wangle);
    wfac = wfac*wfac;
	
    for(iter=0; iter<lincsd->nIter; iter++)
    {
        if (DOMAINDECOMP(cr) && cr->dd->constraints)
        {
            /* Communicate the corrected non-local coordinates */
            dd_move_x_constraints(cr->dd,box,xp,NULL);
        } 
		else if (PARTDECOMP(cr))
		{
			pd_move_x_constraints(cr,xp,NULL);
		}	
        
        for(b=0; b<ncons; b++)
        {
            len = bllen[b];
            if (pbc)
            {
                pbc_dx_aiuc(pbc,xp[bla[2*b]],xp[bla[2*b+1]],dx);
            }
            else
            {
                rvec_sub(xp[bla[2*b]],xp[bla[2*b+1]],dx);
            }
            len2 = len*len;
            dlen2 = 2*len2 - norm2(dx);
            if (dlen2 < wfac*len2 && (nlocat==NULL || nlocat[b]))
            {
                *warn = b;
            }
            if (dlen2 > 0)
            {
                mvb = blc[b]*(len - dlen2*gmx_invsqrt(dlen2));
            }
            else
            {
                mvb = blc[b]*len;
            }
            rhs1[b] = mvb;
            sol[b]  = mvb;
        } /* 20*ncons flops */
        
        lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
        /* nrec*(ncons+2*nrtot) flops */
        
        for(b=0; b<ncons; b++)
        {
            i = bla[2*b];
            j = bla[2*b+1];
            lam = lambda[b];
            mvb = blc[b]*sol[b];
            lambda[b] = lam - mvb;
            im1 = invmass[i];
            im2 = invmass[j];
            tmp0 = r[b][0]*mvb;
            tmp1 = r[b][1]*mvb;
            tmp2 = r[b][2]*mvb;
            xp[i][0] -= tmp0*im1;
            xp[i][1] -= tmp1*im1;
            xp[i][2] -= tmp2*im1;
            xp[j][0] += tmp0*im2;
            xp[j][1] += tmp1*im2;
            xp[j][2] += tmp2*im2;
        } /* 17 ncons flops */
    } /* nit*ncons*(37+9*nrec) flops */
    
    if (v)
    {
        /* Correct the velocities */
        for(b=0; b<ncons; b++)
        {
            i = bla[2*b];
            j = bla[2*b+1];
            im1 = invmass[i]*lambda[b]*invdt;
            im2 = invmass[j]*lambda[b]*invdt;
            v[i][0] += im1*r[b][0];
            v[i][1] += im1*r[b][1];
            v[i][2] += im1*r[b][2];
            v[j][0] -= im2*r[b][0];
            v[j][1] -= im2*r[b][1];
            v[j][2] -= im2*r[b][2];
        } /* 16 ncons flops */
    }
    
    if (nlocat)
    {
        /* Only account for local atoms */
        for(b=0; b<ncons; b++)
        {
            lambda[b] *= 0.5*nlocat[b];
        }
    }
    
    if (bCalcVir)
    {
        /* Constraint virial */
        for(b=0; b<ncons; b++)
        {
            tmp0 = bllen[b]*lambda[b];
            for(i=0; i<DIM; i++)
            {
                tmp1 = tmp0*r[b][i];
                for(j=0; j<DIM; j++)
                {
                    rmdr[i][j] -= tmp1*r[b][j];
                }
            }
        } /* 22 ncons flops */
    }
    
    /* Total:
     * 26*ncons + 6*nrtot + nrec*(ncons+2*nrtot)
     * + nit * (20*ncons + nrec*(ncons+2*nrtot) + 17 ncons)
     *
     * (26+nrec)*ncons + (6+2*nrec)*nrtot
     * + nit * ((37+nrec)*ncons + 2*nrec*nrtot)
     * if nit=1
     * (63+nrec)*ncons + (6+4*nrec)*nrtot
     */
}
Exemplo n.º 10
0
static void do_lincsp(rvec *x,rvec *f,rvec *fp,t_pbc *pbc,
                      struct gmx_lincsdata *lincsd,real *invmass,
                      int econq,real *dvdlambda,
                      gmx_bool bCalcVir,tensor rmdf)
{
    int     b,i,j,k,n;
    real    tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,wfac,lam;  
    rvec    dx;
    int     ncons,*bla,*blnr,*blbnb;
    rvec    *r;
    real    *blc,*blmf,*blcc,*rhs1,*rhs2,*sol;
    
    ncons  = lincsd->nc;
    bla    = lincsd->bla;
    r      = lincsd->tmpv;
    blnr   = lincsd->blnr;
    blbnb  = lincsd->blbnb;
    if (econq != econqForce)
    {
        /* Use mass-weighted parameters */
        blc  = lincsd->blc;
        blmf = lincsd->blmf; 
    }
    else
    {
        /* Use non mass-weighted parameters */
        blc  = lincsd->blc1;
        blmf = lincsd->blmf1;
    }
    blcc   = lincsd->tmpncc;
    rhs1   = lincsd->tmp1;
    rhs2   = lincsd->tmp2;
    sol    = lincsd->tmp3;
    
    if (econq != econqForce)
    {
        dvdlambda = NULL;
    }
    
    /* Compute normalized i-j vectors */
    if (pbc)
    {
        for(b=0; b<ncons; b++)
        {
            pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
            unitv(dx,r[b]);
        }
    }
    else
    {
        for(b=0; b<ncons; b++)
        {
            rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx);
            unitv(dx,r[b]);
        } /* 16 ncons flops */
    }
    
    for(b=0; b<ncons; b++)
    {
        tmp0 = r[b][0];
        tmp1 = r[b][1];
        tmp2 = r[b][2];
        i = bla[2*b];
        j = bla[2*b+1];
        for(n=blnr[b]; n<blnr[b+1]; n++)
        {
            k = blbnb[n];
            blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); 
        } /* 6 nr flops */
        mvb = blc[b]*(tmp0*(f[i][0] - f[j][0]) +
                      tmp1*(f[i][1] - f[j][1]) +    
                      tmp2*(f[i][2] - f[j][2]));
        rhs1[b] = mvb;
        sol[b]  = mvb;
        /* 7 flops */
    }
    /* Together: 23*ncons + 6*nrtot flops */
    
    lincs_matrix_expand(lincsd,blcc,rhs1,rhs2,sol);
    /* nrec*(ncons+2*nrtot) flops */
    
    if (econq != econqForce)
    {
        for(b=0; b<ncons; b++)
        {
            /* With econqDeriv_FlexCon only use the flexible constraints */
            if (econq != econqDeriv_FlexCon ||
                (lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0))
            {
                i = bla[2*b];
                j = bla[2*b+1];
                mvb = blc[b]*sol[b];
                im1 = invmass[i];
                im2 = invmass[j];
                tmp0 = r[b][0]*mvb;
                tmp1 = r[b][1]*mvb;
                tmp2 = r[b][2]*mvb;
                fp[i][0] -= tmp0*im1;
                fp[i][1] -= tmp1*im1;
                fp[i][2] -= tmp2*im1;
                fp[j][0] += tmp0*im2;
                fp[j][1] += tmp1*im2;
                fp[j][2] += tmp2*im2;
                if (dvdlambda)
                {
                    /* This is only correct with forces and invmass=1 */
                    *dvdlambda -= mvb*lincsd->ddist[b];
                }
            }
        } /* 16 ncons flops */
    }
    else
    {
        for(b=0; b<ncons; b++)
        {
            i = bla[2*b];
            j = bla[2*b+1];
            mvb = blc[b]*sol[b];
            tmp0 = r[b][0]*mvb;
            tmp1 = r[b][1]*mvb;
            tmp2 = r[b][2]*mvb;
            fp[i][0] -= tmp0;
            fp[i][1] -= tmp1;
            fp[i][2] -= tmp2;
            fp[j][0] += tmp0;
            fp[j][1] += tmp1;
            fp[j][2] += tmp2;
            if (dvdlambda)
            {
                *dvdlambda -= mvb*lincsd->ddist[b];
            }
        }
        /* 10 ncons flops */
    }
    
    if (bCalcVir)
    {
        /* Constraint virial,
         * determines sum r_bond x delta f,
         * where delta f is the constraint correction
         * of the quantity that is being constrained.
         */
        for(b=0; b<ncons; b++)
        {
            mvb = lincsd->bllen[b]*blc[b]*sol[b];
            for(i=0; i<DIM; i++)
            {
                tmp1 = mvb*r[b][i];
                for(j=0; j<DIM; j++)
                {
                    rmdf[i][j] += tmp1*r[b][j];
                }
            }
        } /* 23 ncons flops */
    }
}
Exemplo n.º 11
0
double compute_delta(double jd, double moon[])
{
    double earth[3];
    get_earth_helio_coordsv (jd, earth);

    double jupiter[3];
    get_jupiter_helio_coordsv(jd, jupiter);

    double moonl[3];
    double moond[3];
    double Avector[3];
    double Cvector[3];
    int j = 0;
    for (j = 0; j < 3; j++) {
        moond[j] = jupiter[j] + moon[j];
        Avector[j] = moond[j] - earth[j];
        Cvector[j] = jupiter[j] - earth[j];
    }

    // double theta = acos(dotprod(Avector, Cvector) / (mag(Avector) * mag(Cvector)));
    /* double Cross[3]; */
    /* Cross[0] = Cvector[1] * Avector[2] - Cvector[2] * Avector[1]; */
    /* Cross[1] = Cvector[2] * Avector[0] - Cvector[0] * Avector[2]; */
    /* Cross[2] = Cvector[0] * Avector[1] - Cvector[1] * Avector[0]; */

    // double y = mag(Avector) * sin(theta);
    
    // printf("Z: %10.10f\n", Cvector[0] * Avector[1] - Cvector[1] * Avector[0]);

    double moonv[3];
    crossprod(Cvector, Avector, moonv);

    double planev[3] = {0.0, 0.0, 1.0};
    // crossprod(earth, jupiter, planev);
    
    double inplanev[3];
    crossprod(planev, Avector, inplanev);

    double inplanevunit[3];
    unitv(inplanev, inplanevunit);

    double y = dotprod(inplanevunit, moon);

    double z = moonv[2];
    moonv[2] = 0; // this makes us work in a plane
    
    //    double y = mag(moonv);
    
    /* double A = mag(Avector); // sqrt(pow(earth[0] - moond[0], 2) + pow(earth[1] - moond[1], 2) + pow(earth[2] - moond[2], 2)); */
    /* double B = mag(moon); // sqrt(pow(moon[0], 2) + pow(moon[1], 2) + pow(moon[2], 2));  */
    /* double C = mag(Cvector); // sqrt(pow(earth[0] - jupiter[0], 2) + pow(earth[1] - jupiter[1], 2) + pow(earth[2] - jupiter[2], 2));  */
    
    /* double y = sqrtl(powl(A,2) - (powl( ( powl(C,2) + powl(A,2) - powl(B,2) ) / (2*C) , 2 ) ) );  */

    /* double z = Cvector[0] * Avector[1] - Cvector[1] * Avector[0]; */

    if (z < 0) {
        // y = -1.0 * y;
    }
    
    return (double)y;
}
Exemplo n.º 12
0
int gmx_spol(int argc, char *argv[])
{
    t_topology  *top;
    t_inputrec  *ir;
    t_atom      *atom;
    t_trxstatus *status;
    int          nrefat, natoms, nf, ntot;
    real         t;
    rvec        *x, xref, trial, dx = {0}, dip, dir;
    matrix       box;

    FILE        *fp;
    int         *isize, nrefgrp;
    atom_id    **index, *molindex;
    char       **grpname;
    real         rmin2, rmax2, rcut, rcut2, rdx2 = 0, rtry2, qav, q, dip2, invbw;
    int          nbin, i, m, mol, a0, a1, a, d;
    double       sdip, sdip2, sinp, sdinp, nmol;
    int         *hist;
    t_pbc        pbc;
    gmx_rmpbc_t  gpbc = NULL;


    const char     *desc[] = {
        "[THISMODULE] analyzes dipoles around a solute; it is especially useful",
        "for polarizable water. A group of reference atoms, or a center",
        "of mass reference (option [TT]-com[tt]) and a group of solvent",
        "atoms is required. The program splits the group of solvent atoms",
        "into molecules. For each solvent molecule the distance to the",
        "closest atom in reference group or to the COM is determined.",
        "A cumulative distribution of these distances is plotted.",
        "For each distance between [TT]-rmin[tt] and [TT]-rmax[tt]",
        "the inner product of the distance vector",
        "and the dipole of the solvent molecule is determined.",
        "For solvent molecules with net charge (ions), the net charge of the ion",
        "is subtracted evenly from all atoms in the selection of each ion.",
        "The average of these dipole components is printed.",
        "The same is done for the polarization, where the average dipole is",
        "subtracted from the instantaneous dipole. The magnitude of the average",
        "dipole is set with the option [TT]-dip[tt], the direction is defined",
        "by the vector from the first atom in the selected solvent group",
        "to the midpoint between the second and the third atom."
    };

    output_env_t    oenv;
    static gmx_bool bCom   = FALSE;
    static int      srefat = 1;
    static real     rmin   = 0.0, rmax = 0.32, refdip = 0, bw = 0.01;
    t_pargs         pa[]   = {
        { "-com",  FALSE, etBOOL,  {&bCom},
          "Use the center of mass as the reference postion" },
        { "-refat",  FALSE, etINT, {&srefat},
          "The reference atom of the solvent molecule" },
        { "-rmin",  FALSE, etREAL, {&rmin}, "Maximum distance (nm)" },
        { "-rmax",  FALSE, etREAL, {&rmax}, "Maximum distance (nm)" },
        { "-dip",   FALSE, etREAL, {&refdip}, "The average dipole (D)" },
        { "-bw",    FALSE, etREAL, {&bw}, "The bin width" }
    };

    t_filenm        fnm[] = {
        { efTRX, NULL,  NULL,  ffREAD },
        { efTPR, NULL,  NULL,  ffREAD },
        { efNDX, NULL,  NULL,  ffOPTRD },
        { efXVG, NULL,  "scdist",  ffWRITE }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    snew(top, 1);
    snew(ir, 1);
    read_tpx_top(ftp2fn(efTPR, NFILE, fnm),
                 ir, box, &natoms, NULL, NULL, NULL, top);

    /* get index groups */
    printf("Select a group of reference particles and a solvent group:\n");
    snew(grpname, 2);
    snew(index, 2);
    snew(isize, 2);
    get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname);

    if (bCom)
    {
        nrefgrp = 1;
        nrefat  = isize[0];
    }
    else
    {
        nrefgrp = isize[0];
        nrefat  = 1;
    }

    spol_atom2molindex(&(isize[1]), index[1], &(top->mols));
    srefat--;

    /* initialize reading trajectory:                         */
    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    rcut  = 0.99*std::sqrt(max_cutoff2(ir->ePBC, box));
    if (rcut == 0)
    {
        rcut = 10*rmax;
    }
    rcut2 = sqr(rcut);
    invbw = 1/bw;
    nbin  = static_cast<int>(rcut*invbw)+2;
    snew(hist, nbin);

    rmin2 = sqr(rmin);
    rmax2 = sqr(rmax);

    nf    = 0;
    ntot  = 0;
    sdip  = 0;
    sdip2 = 0;
    sinp  = 0;
    sdinp = 0;

    molindex = top->mols.index;
    atom     = top->atoms.atom;

    gpbc = gmx_rmpbc_init(&top->idef, ir->ePBC, natoms);

    /* start analysis of trajectory */
    do
    {
        /* make molecules whole again */
        gmx_rmpbc(gpbc, natoms, box, x);

        set_pbc(&pbc, ir->ePBC, box);
        if (bCom)
        {
            calc_com_pbc(nrefat, top, x, &pbc, index[0], xref, ir->ePBC);
        }

        for (m = 0; m < isize[1]; m++)
        {
            mol = index[1][m];
            a0  = molindex[mol];
            a1  = molindex[mol+1];
            for (i = 0; i < nrefgrp; i++)
            {
                pbc_dx(&pbc, x[a0+srefat], bCom ? xref : x[index[0][i]], trial);
                rtry2 = norm2(trial);
                if (i == 0 || rtry2 < rdx2)
                {
                    copy_rvec(trial, dx);
                    rdx2 = rtry2;
                }
            }
            if (rdx2 < rcut2)
            {
                hist[static_cast<int>(std::sqrt(rdx2)*invbw)+1]++;
            }
            if (rdx2 >= rmin2 && rdx2 < rmax2)
            {
                unitv(dx, dx);
                clear_rvec(dip);
                qav = 0;
                for (a = a0; a < a1; a++)
                {
                    qav += atom[a].q;
                }
                qav /= (a1 - a0);
                for (a = a0; a < a1; a++)
                {
                    q = atom[a].q - qav;
                    for (d = 0; d < DIM; d++)
                    {
                        dip[d] += q*x[a][d];
                    }
                }
                for (d = 0; d < DIM; d++)
                {
                    dir[d] = -x[a0][d];
                }
                for (a = a0+1; a < a0+3; a++)
                {
                    for (d = 0; d < DIM; d++)
                    {
                        dir[d] += 0.5*x[a][d];
                    }
                }
                unitv(dir, dir);

                svmul(ENM2DEBYE, dip, dip);
                dip2   = norm2(dip);
                sdip  += std::sqrt(dip2);
                sdip2 += dip2;
                for (d = 0; d < DIM; d++)
                {
                    sinp  += dx[d]*dip[d];
                    sdinp += dx[d]*(dip[d] - refdip*dir[d]);
                }

                ntot++;
            }
        }
        nf++;

    }
    while (read_next_x(oenv, status, &t, x, box));

    gmx_rmpbc_done(gpbc);

    /* clean up */
    sfree(x);
    close_trj(status);

    fprintf(stderr, "Average number of molecules within %g nm is %.1f\n",
            rmax, static_cast<real>(ntot)/nf);
    if (ntot > 0)
    {
        sdip  /= ntot;
        sdip2 /= ntot;
        sinp  /= ntot;
        sdinp /= ntot;
        fprintf(stderr, "Average dipole:                               %f (D), std.dev. %f\n",
                sdip, std::sqrt(sdip2-sqr(sdip)));
        fprintf(stderr, "Average radial component of the dipole:       %f (D)\n",
                sinp);
        fprintf(stderr, "Average radial component of the polarization: %f (D)\n",
                sdinp);
    }

    fp = xvgropen(opt2fn("-o", NFILE, fnm),
                  "Cumulative solvent distribution", "r (nm)", "molecules", oenv);
    nmol = 0;
    for (i = 0; i <= nbin; i++)
    {
        nmol += hist[i];
        fprintf(fp, "%g %g\n", i*bw, nmol/nf);
    }
    xvgrclose(fp);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);

    return 0;
}
Exemplo n.º 13
0
int gmx_sorient(int argc, char *argv[])
{
    t_topology        top;
    int               ePBC = -1;
    t_trxstatus      *status;
    int               natoms;
    real              t;
    rvec             *xtop, *x;
    matrix            box;

    FILE             *fp;
    int               i, p, sa0, sa1, sa2, n, ntot, nf, m, *hist1, *hist2, *histn, nbin1, nbin2, nrbin;
    real             *histi1, *histi2, invbw, invrbw;
    double            sum1, sum2;
    int              *isize, nrefgrp, nrefat;
    int             **index;
    char            **grpname;
    real              inp, outp, nav, normfac, rmin2, rmax2, rcut, rcut2, r2, r;
    real              c1, c2;
    char              str[STRLEN];
    gmx_bool          bTPS;
    rvec              xref, dx, dxh1, dxh2, outer;
    gmx_rmpbc_t       gpbc = NULL;
    t_pbc             pbc;
    const char       *legr[] = {
        "<cos(\\8q\\4\\s1\\N)>",
        "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>"
    };
    const char       *legc[] = {
        "cos(\\8q\\4\\s1\\N)",
        "3cos\\S2\\N(\\8q\\4\\s2\\N)-1"
    };

    const char       *desc[] = {
        "[THISMODULE] analyzes solvent orientation around solutes.",
        "It calculates two angles between the vector from one or more",
        "reference positions to the first atom of each solvent molecule:",
        "",
        " * [GRK]theta[grk][SUB]1[sub]: the angle with the vector from the first atom of the solvent",
        "   molecule to the midpoint between atoms 2 and 3.",
        " * [GRK]theta[grk][SUB]2[sub]: the angle with the normal of the solvent plane, defined by the",
        "   same three atoms, or, when the option [TT]-v23[tt] is set, ",
        "   the angle with the vector between atoms 2 and 3.",
        "",
        "The reference can be a set of atoms or",
        "the center of mass of a set of atoms. The group of solvent atoms should",
        "consist of 3 atoms per solvent molecule.",
        "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are",
        "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]",
        "[TT]-o[tt]: distribtion of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] for rmin<=r<=rmax.[PAR]",
        "[TT]-no[tt]: distribution of [MATH][COS][GRK]theta[grk][SUB]2[sub][cos][math] for rmin<=r<=rmax.[PAR]",
        "[TT]-ro[tt]: [MATH][CHEVRON][COS][GRK]theta[grk][SUB]1[sub][cos][chevron][math] and [MATH][CHEVRON]3[COS]^2[GRK]theta[grk][SUB]2[sub][cos]-1[chevron][math] as a function of the",
        "distance.[PAR]",
        "[TT]-co[tt]: the sum over all solvent molecules within distance r",
        "of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] and [MATH]3[COS]^2([GRK]theta[grk][SUB]2[sub])-1[cos][math] as a function of r.[PAR]",
        "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r"
    };

    gmx_output_env_t *oenv;
    static gmx_bool   bCom = FALSE, bVec23 = FALSE, bPBC = FALSE;
    static real       rmin = 0.0, rmax = 0.5, binwidth = 0.02, rbinw = 0.02;
    t_pargs           pa[] = {
        {   "-com",  FALSE, etBOOL,  {&bCom},
            "Use the center of mass as the reference postion"
        },
        {   "-v23",  FALSE, etBOOL,  {&bVec23},
            "Use the vector between atoms 2 and 3"
        },
        { "-rmin",  FALSE, etREAL, {&rmin}, "Minimum distance (nm)" },
        { "-rmax",  FALSE, etREAL, {&rmax}, "Maximum distance (nm)" },
        { "-cbin",  FALSE, etREAL, {&binwidth}, "Binwidth for the cosine" },
        { "-rbin",  FALSE, etREAL, {&rbinw}, "Binwidth for r (nm)" },
        { "-pbc",   FALSE, etBOOL, {&bPBC}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." }
    };

    t_filenm          fnm[] = {
        { efTRX, NULL,  NULL,  ffREAD },
        { efTPS, NULL,  NULL,  ffREAD },
        { efNDX, NULL,  NULL,  ffOPTRD },
        { efXVG, NULL,  "sori",   ffWRITE },
        { efXVG, "-no", "snor",   ffWRITE },
        { efXVG, "-ro", "sord",   ffWRITE },
        { efXVG, "-co", "scum",   ffWRITE },
        { efXVG, "-rc", "scount", ffWRITE }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    bTPS = (opt2bSet("-s", NFILE, fnm) || !opt2bSet("-n", NFILE, fnm) || bCom);
    if (bTPS)
    {
        read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, NULL, box,
                      bCom);
    }

    /* get index groups */
    printf("Select a group of reference particles and a solvent group:\n");
    snew(grpname, 2);
    snew(index, 2);
    snew(isize, 2);
    if (bTPS)
    {
        get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname);
    }
    else
    {
        get_index(NULL, ftp2fn(efNDX, NFILE, fnm), 2, isize, index, grpname);
    }

    if (bCom)
    {
        nrefgrp = 1;
        nrefat  = isize[0];
    }
    else
    {
        nrefgrp = isize[0];
        nrefat  = 1;
    }

    if (isize[1] % 3)
    {
        gmx_fatal(FARGS, "The number of solvent atoms (%d) is not a multiple of 3",
                  isize[1]);
    }

    /* initialize reading trajectory:                         */
    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    rmin2 = sqr(rmin);
    rmax2 = sqr(rmax);
    rcut  = 0.99*std::sqrt(max_cutoff2(guess_ePBC(box), box));
    if (rcut == 0)
    {
        rcut = 10*rmax;
    }
    rcut2 = sqr(rcut);

    invbw = 1/binwidth;
    nbin1 = 1+static_cast<int>(2*invbw + 0.5);
    nbin2 = 1+static_cast<int>(invbw + 0.5);

    invrbw = 1/rbinw;

    snew(hist1, nbin1);
    snew(hist2, nbin2);
    nrbin = 1+static_cast<int>(rcut/rbinw);
    if (nrbin == 0)
    {
        nrbin = 1;
    }
    snew(histi1, nrbin);
    snew(histi2, nrbin);
    snew(histn, nrbin);

    ntot = 0;
    nf   = 0;
    sum1 = 0;
    sum2 = 0;

    if (bTPS)
    {
        /* make molecules whole again */
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    }
    /* start analysis of trajectory */
    do
    {
        if (bTPS)
        {
            /* make molecules whole again */
            gmx_rmpbc(gpbc, natoms, box, x);
        }

        set_pbc(&pbc, ePBC, box);
        n    = 0;
        inp  = 0;
        for (p = 0; (p < nrefgrp); p++)
        {
            if (bCom)
            {
                calc_com_pbc(nrefat, &top, x, &pbc, index[0], xref, bPBC);
            }
            else
            {
                copy_rvec(x[index[0][p]], xref);
            }

            for (m = 0; m < isize[1]; m += 3)
            {
                sa0 = index[1][m];
                sa1 = index[1][m+1];
                sa2 = index[1][m+2];
                range_check(sa0, 0, natoms);
                range_check(sa1, 0, natoms);
                range_check(sa2, 0, natoms);
                pbc_dx(&pbc, x[sa0], xref, dx);
                r2  = norm2(dx);
                if (r2 < rcut2)
                {
                    r = std::sqrt(r2);
                    if (!bVec23)
                    {
                        /* Determine the normal to the plain */
                        rvec_sub(x[sa1], x[sa0], dxh1);
                        rvec_sub(x[sa2], x[sa0], dxh2);
                        rvec_inc(dxh1, dxh2);
                        svmul(1/r, dx, dx);
                        unitv(dxh1, dxh1);
                        inp = iprod(dx, dxh1);
                        cprod(dxh1, dxh2, outer);
                        unitv(outer, outer);
                        outp = iprod(dx, outer);
                    }
                    else
                    {
                        /* Use the vector between the 2nd and 3rd atom */
                        rvec_sub(x[sa2], x[sa1], dxh2);
                        unitv(dxh2, dxh2);
                        outp = iprod(dx, dxh2)/r;
                    }
                    {
                        int ii = static_cast<int>(invrbw*r);
                        range_check(ii, 0, nrbin);
                        histi1[ii] += inp;
                        histi2[ii] += 3*sqr(outp) - 1;
                        histn[ii]++;
                    }
                    if ((r2 >= rmin2) && (r2 < rmax2))
                    {
                        int ii1 = static_cast<int>(invbw*(inp + 1));
                        int ii2 = static_cast<int>(invbw*std::abs(outp));

                        range_check(ii1, 0, nbin1);
                        range_check(ii2, 0, nbin2);
                        hist1[ii1]++;
                        hist2[ii2]++;
                        sum1 += inp;
                        sum2 += outp;
                        n++;
                    }
                }
            }
        }
        ntot += n;
        nf++;

    }
    while (read_next_x(oenv, status, &t, x, box));

    /* clean up */
    sfree(x);
    close_trj(status);
    gmx_rmpbc_done(gpbc);

    /* Add the bin for the exact maximum to the previous bin */
    hist1[nbin1-1] += hist1[nbin1];
    hist2[nbin2-1] += hist2[nbin2];

    nav     = static_cast<real>(ntot)/(nrefgrp*nf);
    normfac = invbw/ntot;

    fprintf(stderr,  "Average nr of molecules between %g and %g nm: %.1f\n",
            rmin, rmax, nav);
    if (ntot > 0)
    {
        sum1 /= ntot;
        sum2 /= ntot;
        fprintf(stderr, "Average cos(theta1)     between %g and %g nm: %6.3f\n",
                rmin, rmax, sum1);
        fprintf(stderr, "Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n",
                rmin, rmax, sum2);
    }

    sprintf(str, "Solvent orientation between %g and %g nm", rmin, rmax);
    fp = xvgropen(opt2fn("-o", NFILE, fnm), str, "cos(\\8q\\4\\s1\\N)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav);
    }
    for (i = 0; i < nbin1; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*binwidth-1, 2*normfac*hist1[i]);
    }
    xvgrclose(fp);

    sprintf(str, "Solvent normal orientation between %g and %g nm", rmin, rmax);
    fp = xvgropen(opt2fn("-no", NFILE, fnm), str, "cos(\\8q\\4\\s2\\N)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav);
    }
    for (i = 0; i < nbin2; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*binwidth, normfac*hist2[i]);
    }
    xvgrclose(fp);


    sprintf(str, "Solvent orientation");
    fp = xvgropen(opt2fn("-ro", NFILE, fnm), str, "r (nm)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    xvgr_legend(fp, 2, legr, oenv);
    for (i = 0; i < nrbin; i++)
    {
        fprintf(fp, "%g %g %g\n", (i+0.5)*rbinw,
                histn[i] ? histi1[i]/histn[i] : 0,
                histn[i] ? histi2[i]/histn[i] : 0);
    }
    xvgrclose(fp);

    sprintf(str, "Cumulative solvent orientation");
    fp = xvgropen(opt2fn("-co", NFILE, fnm), str, "r (nm)", "", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    xvgr_legend(fp, 2, legc, oenv);
    normfac = 1.0/(nrefgrp*nf);
    c1      = 0;
    c2      = 0;
    fprintf(fp, "%g %g %g\n", 0.0, c1, c2);
    for (i = 0; i < nrbin; i++)
    {
        c1 += histi1[i]*normfac;
        c2 += histi2[i]*normfac;
        fprintf(fp, "%g %g %g\n", (i+1)*rbinw, c1, c2);
    }
    xvgrclose(fp);

    sprintf(str, "Solvent distribution");
    fp = xvgropen(opt2fn("-rc", NFILE, fnm), str, "r (nm)", "molecules/nm", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"as a function of distance\"\n");
    }
    normfac = 1.0/(rbinw*nf);
    for (i = 0; i < nrbin; i++)
    {
        fprintf(fp, "%g %g\n", (i+0.5)*rbinw, histn[i]*normfac);
    }
    xvgrclose(fp);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-no", NFILE, fnm), NULL);
    do_view(oenv, opt2fn("-ro", NFILE, fnm), "-nxy");
    do_view(oenv, opt2fn("-co", NFILE, fnm), "-nxy");

    return 0;
}
Exemplo n.º 14
0
/* LINCS projection, works on derivatives of the coordinates */
static void do_lincsp(rvec *x,rvec *f,rvec *fp,t_pbc *pbc,
                      struct gmx_lincsdata *lincsd,int th,
                      real *invmass,
                      int econq,real *dvdlambda,
                      gmx_bool bCalcVir,tensor rmdf)
{
    int     b0,b1,b,i,j,k,n;
    real    tmp0,tmp1,tmp2,im1,im2,mvb,rlen,len,wfac,lam;  
    rvec    dx;
    int     *bla,*blnr,*blbnb;
    rvec    *r;
    real    *blc,*blmf,*blcc,*rhs1,*rhs2,*sol;

    b0 = lincsd->th[th].b0;
    b1 = lincsd->th[th].b1;
    
    bla    = lincsd->bla;
    r      = lincsd->tmpv;
    blnr   = lincsd->blnr;
    blbnb  = lincsd->blbnb;
    if (econq != econqForce)
    {
        /* Use mass-weighted parameters */
        blc  = lincsd->blc;
        blmf = lincsd->blmf; 
    }
    else
    {
        /* Use non mass-weighted parameters */
        blc  = lincsd->blc1;
        blmf = lincsd->blmf1;
    }
    blcc   = lincsd->tmpncc;
    rhs1   = lincsd->tmp1;
    rhs2   = lincsd->tmp2;
    sol    = lincsd->tmp3;
    
    /* Compute normalized i-j vectors */
    if (pbc)
    {
        for(b=b0; b<b1; b++)
        {
            pbc_dx_aiuc(pbc,x[bla[2*b]],x[bla[2*b+1]],dx);
            unitv(dx,r[b]);
        }
    }
    else
    {
        for(b=b0; b<b1; b++)
        {
            rvec_sub(x[bla[2*b]],x[bla[2*b+1]],dx);
            unitv(dx,r[b]);
        } /* 16 ncons flops */
    }
    
#pragma omp barrier
    for(b=b0; b<b1; b++)
    {
        tmp0 = r[b][0];
        tmp1 = r[b][1];
        tmp2 = r[b][2];
        i = bla[2*b];
        j = bla[2*b+1];
        for(n=blnr[b]; n<blnr[b+1]; n++)
        {
            k = blbnb[n];
            blcc[n] = blmf[n]*(tmp0*r[k][0] + tmp1*r[k][1] + tmp2*r[k][2]); 
        } /* 6 nr flops */
        mvb = blc[b]*(tmp0*(f[i][0] - f[j][0]) +
                      tmp1*(f[i][1] - f[j][1]) +    
                      tmp2*(f[i][2] - f[j][2]));
        rhs1[b] = mvb;
        sol[b]  = mvb;
        /* 7 flops */
    }
    /* Together: 23*ncons + 6*nrtot flops */
    
    lincs_matrix_expand(lincsd,b0,b1,blcc,rhs1,rhs2,sol);
    /* nrec*(ncons+2*nrtot) flops */
    
    if (econq == econqDeriv_FlexCon)
    {
        /* We only want to constraint the flexible constraints,
         * so we mask out the normal ones by setting sol to 0.
         */
        for(b=b0; b<b1; b++)
        {
            if (!(lincsd->bllen0[b] == 0 && lincsd->ddist[b] == 0))
            {
                sol[b] = 0;
            }
        }
    }

    if (econq != econqForce)
    {
        lincs_update_atoms(lincsd,th,1.0,sol,r,invmass,fp);
    }
    else
    {
        for(b=b0; b<b1; b++)
        {
            i = bla[2*b];
            j = bla[2*b+1];
            mvb = blc[b]*sol[b];
            tmp0 = r[b][0]*mvb;
            tmp1 = r[b][1]*mvb;
            tmp2 = r[b][2]*mvb;
            fp[i][0] -= tmp0;
            fp[i][1] -= tmp1;
            fp[i][2] -= tmp2;
            fp[j][0] += tmp0;
            fp[j][1] += tmp1;
            fp[j][2] += tmp2;
        }

        if (dvdlambda != NULL)
        {
#pragma omp barrier
            for(b=b0; b<b1; b++)
            {
                *dvdlambda -= blc[b]*sol[b]*lincsd->ddist[b];
            }
        }
        /* 10 ncons flops */
    }

    if (bCalcVir)
    {
        /* Constraint virial,
         * determines sum r_bond x delta f,
         * where delta f is the constraint correction
         * of the quantity that is being constrained.
         */
        for(b=b0; b<b1; b++)
        {
            mvb = lincsd->bllen[b]*blc[b]*sol[b];
            for(i=0; i<DIM; i++)
            {
                tmp1 = mvb*r[b][i];
                for(j=0; j<DIM; j++)
                {
                    rmdf[i][j] += tmp1*r[b][j];
                }
            }
        } /* 23 ncons flops */
    }
}
Exemplo n.º 15
0
int gmx_dyecoupl(int argc, char *argv[])
{
    const char *desc[] =
    {
        "[THISMODULE] extracts dye dynamics from trajectory files.",
        "Currently, R and kappa^2 between dyes is extracted for (F)RET",
        "simulations with assumed dipolar coupling as in the Foerster equation.",
        "It further allows the calculation of R(t) and kappa^2(t), R and",
        "kappa^2 histograms and averages, as well as the instantaneous FRET",
        "efficiency E(t) for a specified Foerster radius R_0 (switch [TT]-R0[tt]).",
        "The input dyes have to be whole (see res and mol pbc options",
        "in [TT]trjconv[tt]).",
        "The dye transition dipole moment has to be defined by at least",
        "a single atom pair, however multiple atom pairs can be provided ",
        "in the index file. The distance R is calculated on the basis of",
        "the COMs of the given atom pairs.",
        "The [TT]-pbcdist[tt] option calculates distances to the nearest periodic",
        "image instead to the distance in the box. This works however only,"
        "for periodic boundaries in all 3 dimensions.",
        "The [TT]-norm[tt] option (area-) normalizes the histograms."
    };

    static gmx_bool   bPBCdist = FALSE, bNormHist = FALSE;
    int               histbins = 50;
    gmx_output_env_t *oenv;
    real              R0 = -1;

    t_pargs           pa[] =
    {
        { "-pbcdist", FALSE, etBOOL, { &bPBCdist }, "Distance R based on PBC" },
        { "-norm", FALSE, etBOOL, { &bNormHist }, "Normalize histograms" },
        { "-bins", FALSE, etINT, {&histbins}, "# of histogram bins" },
        { "-R0", FALSE, etREAL, {&R0}, "Foerster radius including kappa^2=2/3 in nm" }
    };
#define NPA asize(pa)

    t_filenm fnm[] =
    {
        { efTRX, "-f", NULL, ffREAD },
        { efNDX, NULL, NULL, ffREAD },
        { efXVG, "-ot", "rkappa", ffOPTWR },
        { efXVG, "-oe", "insteff", ffOPTWR },
        { efDAT, "-o", "rkappa", ffOPTWR },
        { efXVG, "-rhist", "rhist", ffOPTWR },
        { efXVG, "-khist", "khist", ffOPTWR }
    };
#define NFILE asize(fnm)


    const char  *in_trajfile, *out_xvgrkfile = NULL, *out_xvginstefffile = NULL, *out_xvgrhistfile = NULL, *out_xvgkhistfile = NULL, *out_datfile = NULL;
    gmx_bool     bHaveFirstFrame, bHaveNextFrame, indexOK = TRUE;
    int          ndon, nacc;
    atom_id     *donindex, *accindex;
    char        *grpnm;
    t_trxstatus *status;
    t_trxframe   fr;

    int          flags;
    int          allocblock = 1000;
    real         histexpand = 1e-6;
    rvec         donvec, accvec, donpos, accpos, dist, distnorm;
    int          natoms;

    /*we rely on PBC autodetection (...currently)*/
    int         ePBC = -1;

    real       *rvalues = NULL, *kappa2values = NULL, *rhist = NULL, *khist = NULL;
    t_pbc      *pbc     = NULL;
    int         i, bin;
    FILE       *rkfp = NULL, *rhfp = NULL, *khfp = NULL, *datfp = NULL, *iefp = NULL;
    gmx_bool    bRKout, bRhistout, bKhistout, bDatout, bInstEffout, grident;

    const char *rkleg[2] = { "R", "\\f{Symbol}k\\f{}\\S2\\N" };
    const char *rhleg[1] = { "p(R)" };
    const char *khleg[1] = { "p(\\f{Symbol}k\\f{}\\S2\\N)" };
    const char *ieleg[1] = { "E\\sRET\\N(t)" };

    real        R, kappa2, insteff, Rs = 0., kappa2s = 0., insteffs = 0., rmax, rmin, kmin = 0., kmax = 4.,
                rrange, krange, rincr, kincr, Rfrac;
    int         rkcount = 0, rblocksallocated = 0, kblocksallocated = 0;

    if (!parse_common_args(&argc, argv, PCA_CAN_BEGIN | PCA_CAN_END | PCA_CAN_VIEW | PCA_TIME_UNIT,
                           NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }


    /* Check command line options for filenames and set bool flags when switch used*/
    in_trajfile        = opt2fn("-f", NFILE, fnm);
    out_xvgrkfile      = opt2fn("-ot", NFILE, fnm);
    out_xvgrhistfile   = opt2fn("-rhist", NFILE, fnm);
    out_xvgkhistfile   = opt2fn("-khist", NFILE, fnm);
    out_xvginstefffile = opt2fn("-oe", NFILE, fnm);
    out_datfile        = opt2fn("-o", NFILE, fnm);

    bRKout      = opt2bSet("-ot", NFILE, fnm);
    bRhistout   = opt2bSet("-rhist", NFILE, fnm);
    bKhistout   = opt2bSet("-khist", NFILE, fnm);
    bDatout     = opt2bSet("-o", NFILE, fnm);
    bInstEffout = opt2bSet("-oe", NFILE, fnm);


    /* PBC warning. */
    if (bPBCdist)
    {
        printf("Calculating distances to periodic image.\n");
        printf("Be careful! This produces only valid results for PBC in all three dimensions\n");
    }


    if (bInstEffout && R0 <= 0.)
    {
        gmx_fatal(FARGS, "You have to specify R0 and R0 has to be larger than 0 nm.\n\n");
    }

    printf("Select group with donor atom pairs defining the transition moment\n");
    get_index(NULL, ftp2fn_null(efNDX, NFILE, fnm), 1, &ndon, &donindex, &grpnm);

    printf("Select group with acceptor atom pairs defining the transition moment\n");
    get_index(NULL, ftp2fn_null(efNDX, NFILE, fnm), 1, &nacc, &accindex, &grpnm);

    /*check if groups are identical*/
    grident = TRUE;

    if (ndon == nacc)
    {
        for (i = 0; i < nacc; i++)
        {
            if (accindex[i] != donindex[i])
            {
                grident = FALSE;
                break;
            }
        }
    }

    if (grident)
    {
        gmx_fatal(FARGS, "Donor and acceptor group are identical. This makes no sense.");
    }

    printf("Reading first frame\n");
    /* open trx file for reading */
    flags           = 0;
    flags           = flags | TRX_READ_X;
    bHaveFirstFrame = read_first_frame(oenv, &status, in_trajfile, &fr, flags);

    if (bHaveFirstFrame)
    {
        printf("First frame is OK\n");
        natoms = fr.natoms;
        if ((ndon % 2 != 0) || (nacc % 2 != 0))
        {
            indexOK = FALSE;
        }
        else
        {
            for (i = 0; i < ndon; i++)
            {
                if (donindex[i] >= natoms)
                {
                    indexOK = FALSE;
                }
            }
            for (i = 0; i < nacc; i++)
            {
                if (accindex[i] >= natoms)
                {
                    indexOK = FALSE;
                }
            }
        }

        if (indexOK)
        {

            if (bDatout)
            {
                datfp = gmx_ffopen(out_datfile, "w");
            }

            if (bRKout)
            {
                rkfp = xvgropen(out_xvgrkfile,
                                "Distance and \\f{Symbol}k\\f{}\\S2\\N trajectory",
                                "Time (ps)", "Distance (nm) / \\f{Symbol}k\\f{}\\S2\\N",
                                oenv);
                xvgr_legend(rkfp, 2, rkleg, oenv);
            }

            if (bInstEffout)
            {
                iefp = xvgropen(out_xvginstefffile,
                                "Instantaneous RET Efficiency",
                                "Time (ps)", "RET Efficiency",
                                oenv);
                xvgr_legend(iefp, 1, ieleg, oenv);
            }


            if (bRhistout)
            {
                snew(rvalues, allocblock);
                rblocksallocated += 1;
                snew(rhist, histbins);
            }

            if (bKhistout)
            {
                snew(kappa2values, allocblock);
                kblocksallocated += 1;
                snew(khist, histbins);
            }

            do
            {
                clear_rvec(donvec);
                clear_rvec(accvec);
                clear_rvec(donpos);
                clear_rvec(accpos);
                for (i = 0; i < ndon / 2; i++)
                {
                    rvec_sub(donvec, fr.x[donindex[2 * i]], donvec);
                    rvec_add(donvec, fr.x[donindex[2 * i + 1]], donvec);
                    rvec_add(donpos, fr.x[donindex[2 * i]], donpos);
                    rvec_add(donpos, fr.x[donindex[2 * i + 1]], donpos);
                }

                for (i = 0; i < nacc / 2; i++)
                {
                    rvec_sub(accvec, fr.x[accindex[2 * i]], accvec);
                    rvec_add(accvec, fr.x[accindex[2 * i + 1]], accvec);
                    rvec_add(accpos, fr.x[accindex[2 * i]], accpos);
                    rvec_add(accpos, fr.x[accindex[2 * i + 1]], accpos);
                }

                unitv(donvec, donvec);
                unitv(accvec, accvec);

                svmul(1.0 / ndon, donpos, donpos);
                svmul(1.0 / nacc, accpos, accpos);

                if (bPBCdist)
                {
                    set_pbc(pbc, ePBC, fr.box);
                    pbc_dx(pbc, donpos, accpos, dist);
                }
                else
                {
                    rvec_sub(donpos, accpos, dist);
                }

                unitv(dist, distnorm);
                R       = norm(dist);
                kappa2  = iprod(donvec, accvec)- 3.* (iprod(donvec, distnorm) * iprod(distnorm, accvec));
                kappa2 *= kappa2;
                if (R0 > 0)
                {
                    Rfrac     = R/R0;
                    insteff   = 1/(1+(Rfrac*Rfrac*Rfrac*Rfrac*Rfrac*Rfrac)*2/3/kappa2);
                    insteffs += insteff;

                    if (bInstEffout)
                    {
                        fprintf(iefp, "%12.7f %12.7f\n", fr.time, insteff);
                    }
                }


                Rs      += R;
                kappa2s += kappa2;
                rkcount++;

                if (bRKout)
                {
                    fprintf(rkfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
                }

                if (bDatout)
                {
                    fprintf(datfp, "%12.7f %12.7f %12.7f\n", fr.time, R, kappa2);
                }

                if (bRhistout)
                {
                    rvalues[rkcount-1] = R;
                    if (rkcount % allocblock == 0)
                    {
                        srenew(rvalues, allocblock*(rblocksallocated+1));
                        rblocksallocated += 1;
                    }
                }

                if (bKhistout)
                {
                    kappa2values[rkcount-1] = kappa2;
                    if (rkcount % allocblock == 0)
                    {
                        srenew(kappa2values, allocblock*(kblocksallocated+1));
                        kblocksallocated += 1;
                    }
                }

                bHaveNextFrame = read_next_frame(oenv, status, &fr);
            }
            while (bHaveNextFrame);

            if (bRKout)
            {
                xvgrclose(rkfp);
            }

            if (bDatout)
            {
                gmx_ffclose(datfp);
            }

            if (bInstEffout)
            {
                xvgrclose(iefp);
            }


            if (bRhistout)
            {
                printf("Writing R-Histogram\n");
                rmin = rvalues[0];
                rmax = rvalues[0];
                for (i = 1; i < rkcount; i++)
                {
                    if (rvalues[i] < rmin)
                    {
                        rmin = rvalues[i];
                    }
                    else if (rvalues[i] > rmax)
                    {
                        rmax = rvalues[i];
                    }
                }
                rmin -= histexpand;
                rmax += histexpand;

                rrange = rmax - rmin;
                rincr  = rrange / histbins;

                for (i = 1; i < rkcount; i++)
                {
                    bin         = static_cast<int>((rvalues[i] - rmin) / rincr);
                    rhist[bin] += 1;
                }
                if (bNormHist)
                {
                    for (i = 0; i < histbins; i++)
                    {
                        rhist[i] /= rkcount * rrange/histbins;
                    }
                    rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
                                    "R (nm)", "Normalized Probability", oenv);
                }
                else
                {
                    rhfp = xvgropen(out_xvgrhistfile, "Distance Distribution",
                                    "R (nm)", "Probability", oenv);
                }
                xvgr_legend(rhfp, 1, rhleg, oenv);
                for (i = 0; i < histbins; i++)
                {
                    fprintf(rhfp, "%12.7f %12.7f\n", (i + 0.5) * rincr + rmin,
                            rhist[i]);
                }
                xvgrclose(rhfp);
            }

            if (bKhistout)
            {
                printf("Writing kappa^2-Histogram\n");
                krange = kmax - kmin;
                kincr  = krange / histbins;

                for (i = 1; i < rkcount; i++)
                {
                    bin         = static_cast<int>((kappa2values[i] - kmin) / kincr);
                    khist[bin] += 1;
                }
                if (bNormHist)
                {
                    for (i = 0; i < histbins; i++)
                    {
                        khist[i] /= rkcount * krange/histbins;
                    }
                    khfp = xvgropen(out_xvgkhistfile,
                                    "\\f{Symbol}k\\f{}\\S2\\N Distribution",
                                    "\\f{Symbol}k\\f{}\\S2\\N",
                                    "Normalized Probability", oenv);
                }
                else
                {
                    khfp = xvgropen(out_xvgkhistfile,
                                    "\\f{Symbol}k\\f{}\\S2\\N Distribution",
                                    "\\f{Symbol}k\\f{}\\S2\\N", "Probability", oenv);
                }
                xvgr_legend(khfp, 1, khleg, oenv);
                for (i = 0; i < histbins; i++)
                {
                    fprintf(khfp, "%12.7f %12.7f\n", (i + 0.5) * kincr + kmin,
                            khist[i]);
                }
                xvgrclose(khfp);
            }

            printf("\nAverages:\n");
            printf("R_avg   = %8.4f nm\nKappa^2 = %8.4f\n", Rs / rkcount,
                   kappa2s / rkcount);
            if (R0 > 0)
            {
                printf("E_RETavg   = %8.4f\n", insteffs / rkcount);
            }
            please_cite(stdout, "Hoefling2011");
        }
        else
        {
            gmx_fatal(FARGS, "Index file invalid, check your index file for correct pairs.\n");
        }
    }
    else
    {
        gmx_fatal(FARGS, "Could not read first frame of the trajectory.\n");
    }

    return 0;
}
Exemplo n.º 16
0
void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
                real ***slOrder, real *slWidth, int nslices, gmx_bool bSliced,
                gmx_bool bUnsat, t_topology *top, int ePBC, int ngrps, int axis,
                gmx_bool permolecule, gmx_bool radial, gmx_bool distcalc, const char *radfn,
                real ***distvals,
                const gmx_output_env_t *oenv)
{
    /* if permolecule = TRUE, order parameters will be calculed per molecule
     * and stored in slOrder with #slices = # molecules */
    rvec *x0,                                    /* coordinates with pbc                           */
    *x1,                                         /* coordinates without pbc                        */
          dist;                                  /* vector between two atoms                       */
    matrix       box;                            /* box (3x3)                                      */
    t_trxstatus *status;
    rvec         cossum,                         /* sum of vector angles for three axes            */
                 Sx, Sy, Sz,                     /* the three molecular axes                       */
                 tmp1, tmp2,                     /* temp. rvecs for calculating dot products       */
                 frameorder;                     /* order parameters for one frame                 */
    real *slFrameorder;                          /* order parameter for one frame, per slice      */
    real  length,                                /* total distance between two atoms               */
          t,                                     /* time from trajectory                           */
          z_ave, z1, z2;                         /* average z, used to det. which slice atom is in */
    int natoms,                                  /* nr. atoms in trj                               */
        nr_tails,                                /* nr tails, to check if index file is correct    */
        size = 0,                                /* nr. of atoms in group. same as nr_tails        */
        i, j, m, k, teller = 0,
        slice,                                   /* current slice number                           */
        nr_frames = 0;
    int         *slCount;                        /* nr. of atoms in one slice                      */
    real         sdbangle               = 0;     /* sum of these angles                            */
    gmx_bool     use_unitvector         = FALSE; /* use a specified unit vector instead of axis to specify unit normal*/
    rvec         direction, com, dref, dvec;
    int          comsize, distsize;
    atom_id     *comidx  = NULL, *distidx = NULL;
    char        *grpname = NULL;
    t_pbc        pbc;
    real         arcdist, tmpdist;
    gmx_rmpbc_t  gpbc = NULL;

    /* PBC added for center-of-mass vector*/
    /* Initiate the pbc structure */
    std::memset(&pbc, 0, sizeof(pbc));

    if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0)
    {
        gmx_fatal(FARGS, "Could not read coordinates from statusfile\n");
    }

    nr_tails = index[1] - index[0];
    fprintf(stderr, "Number of elements in first group: %d\n", nr_tails);
    /* take first group as standard. Not rocksolid, but might catch error in index*/

    if (permolecule)
    {
        nslices = nr_tails;
        bSliced = FALSE; /*force slices off */
        fprintf(stderr, "Calculating order parameters for each of %d molecules\n",
                nslices);
    }

    if (radial)
    {
        use_unitvector = TRUE;
        fprintf(stderr, "Select an index group to calculate the radial membrane normal\n");
        get_index(&top->atoms, radfn, 1, &comsize, &comidx, &grpname);
    }
    if (distcalc)
    {
        if (grpname != NULL)
        {
            sfree(grpname);
        }
        fprintf(stderr, "Select an index group to use as distance reference\n");
        get_index(&top->atoms, radfn, 1, &distsize, &distidx, &grpname);
        bSliced = FALSE; /*force slices off*/
    }

    if (use_unitvector && bSliced)
    {
        fprintf(stderr, "Warning:  slicing and specified unit vectors are not currently compatible\n");
    }

    snew(slCount, nslices);
    snew(*slOrder, nslices);
    for (i = 0; i < nslices; i++)
    {
        snew((*slOrder)[i], ngrps);
    }
    if (distcalc)
    {
        snew(*distvals, nslices);
        for (i = 0; i < nslices; i++)
        {
            snew((*distvals)[i], ngrps);
        }
    }
    snew(*order, ngrps);
    snew(slFrameorder, nslices);
    snew(x1, natoms);

    if (bSliced)
    {
        *slWidth = box[axis][axis]/nslices;
        fprintf(stderr, "Box divided in %d slices. Initial width of slice: %f\n",
                nslices, *slWidth);
    }


#if 0
    nr_tails = index[1] - index[0];
    fprintf(stderr, "Number of elements in first group: %d\n", nr_tails);
    /* take first group as standard. Not rocksolid, but might catch error
       in index*/
#endif

    teller = 0;

    gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
    /*********** Start processing trajectory ***********/
    do
    {
        if (bSliced)
        {
            *slWidth = box[axis][axis]/nslices;
        }
        teller++;

        set_pbc(&pbc, ePBC, box);
        gmx_rmpbc_copy(gpbc, natoms, box, x0, x1);

        /* Now loop over all groups. There are ngrps groups, the order parameter can
           be calculated for grp 1 to grp ngrps - 1. For each group, loop over all
           atoms in group, which is index[i] to (index[i+1] - 1) See block.h. Of
           course, in this case index[i+1] -index[i] has to be the same for all
           groups, namely the number of tails. i just runs over all atoms in a tail,
           so for DPPC ngrps = 16 and i runs from 1 to 14, including 14
         */


        if (radial)
        {
            /*center-of-mass determination*/
            com[XX] = 0.0; com[YY] = 0.0; com[ZZ] = 0.0;
            for (j = 0; j < comsize; j++)
            {
                rvec_inc(com, x1[comidx[j]]);
            }
            svmul(1.0/comsize, com, com);
        }
        if (distcalc)
        {
            dref[XX] = 0.0; dref[YY] = 0.0; dref[ZZ] = 0.0;
            for (j = 0; j < distsize; j++)
            {
                rvec_inc(dist, x1[distidx[j]]);
            }
            svmul(1.0/distsize, dref, dref);
            if (radial)
            {
                pbc_dx(&pbc, dref, com, dvec);
                unitv(dvec, dvec);
            }
        }

        for (i = 1; i < ngrps - 1; i++)
        {
            clear_rvec(frameorder);

            size = index[i+1] - index[i];
            if (size != nr_tails)
            {
                gmx_fatal(FARGS, "grp %d does not have same number of"
                          " elements as grp 1\n", i);
            }

            for (j = 0; j < size; j++)
            {
                if (radial)
                /*create unit vector*/
                {
                    pbc_dx(&pbc, x1[a[index[i]+j]], com, direction);
                    unitv(direction, direction);
                    /*DEBUG*/
                    /*if (j==0)
                        fprintf(stderr,"X %f %f %f\tcom %f %f %f\tdirection %f %f %f\n",x1[a[index[i]+j]][0],x1[a[index[i]+j]][1],x1[a[index[i]+j]][2],com[0],com[1],com[2],
                            direction[0],direction[1],direction[2]);*/
                }

                if (bUnsat)
                {
                    /* Using convention for unsaturated carbons */
                    /* first get Sz, the vector from Cn to Cn+1 */
                    rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], dist);
                    length = norm(dist);
                    check_length(length, a[index[i]+j], a[index[i+1]+j]);
                    svmul(1.0/length, dist, Sz);

                    /* this is actually the cosine of the angle between the double bond
                       and axis, because Sz is normalized and the two other components of
                       the axis on the bilayer are zero */
                    if (use_unitvector)
                    {
                        sdbangle += gmx_angle(direction, Sz); /*this can probably be optimized*/
                    }
                    else
                    {
                        sdbangle += std::acos(Sz[axis]);
                    }
                }
                else
                {
                    /* get vector dist(Cn-1,Cn+1) for tail atoms */
                    rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i-1]+j]], dist);
                    length = norm(dist); /* determine distance between two atoms */
                    check_length(length, a[index[i-1]+j], a[index[i+1]+j]);

                    svmul(1.0/length, dist, Sz);
                    /* Sz is now the molecular axis Sz, normalized and all that */
                }

                /* now get Sx. Sx is normal to the plane of Cn-1, Cn and Cn+1 so
                   we can use the outer product of Cn-1->Cn and Cn+1->Cn, I hope */
                rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], tmp1);
                rvec_sub(x1[a[index[i-1]+j]], x1[a[index[i]+j]], tmp2);
                cprod(tmp1, tmp2, Sx);
                svmul(1.0/norm(Sx), Sx, Sx);

                /* now we can get Sy from the outer product of Sx and Sz   */
                cprod(Sz, Sx, Sy);
                svmul(1.0/norm(Sy), Sy, Sy);

                /* the square of cosine of the angle between dist and the axis.
                   Using the innerproduct, but two of the three elements are zero
                   Determine the sum of the orderparameter of all atoms in group
                 */
                if (use_unitvector)
                {
                    cossum[XX] = sqr(iprod(Sx, direction)); /* this is allowed, since Sa is normalized */
                    cossum[YY] = sqr(iprod(Sy, direction));
                    cossum[ZZ] = sqr(iprod(Sz, direction));
                }
                else
                {
                    cossum[XX] = sqr(Sx[axis]); /* this is allowed, since Sa is normalized */
                    cossum[YY] = sqr(Sy[axis]);
                    cossum[ZZ] = sqr(Sz[axis]);
                }

                for (m = 0; m < DIM; m++)
                {
                    frameorder[m] += 0.5 * (3.0 * cossum[m] - 1.0);
                }

                if (bSliced)
                {
                    /* get average coordinate in box length for slicing,
                       determine which slice atom is in, increase count for that
                       slice. slFrameorder and slOrder are reals, not
                       rvecs. Only the component [axis] of the order tensor is
                       kept, until I find it necessary to know the others too
                     */

                    z1    = x1[a[index[i-1]+j]][axis];
                    z2    = x1[a[index[i+1]+j]][axis];
                    z_ave = 0.5 * (z1 + z2);
                    if (z_ave < 0)
                    {
                        z_ave += box[axis][axis];
                    }
                    if (z_ave > box[axis][axis])
                    {
                        z_ave -= box[axis][axis];
                    }

                    slice  = static_cast<int>((0.5 + (z_ave / (*slWidth))) - 1);
                    slCount[slice]++;     /* determine slice, increase count */

                    slFrameorder[slice] += 0.5 * (3 * cossum[axis] - 1);
                }
                else if (permolecule)
                {
                    /*  store per-molecule order parameter
                     *  To just track single-axis order: (*slOrder)[j][i] += 0.5 * (3 * iprod(cossum,direction) - 1);
                     *  following is for Scd order: */
                    (*slOrder)[j][i] += -1* (1.0/3.0 * (3 * cossum[XX] - 1) + 1.0/3.0 * 0.5 * (3.0 * cossum[YY] - 1));
                }
                if (distcalc)
                {
                    if (radial)
                    {
                        /* bin order parameter by arc distance from reference group*/
                        arcdist            = gmx_angle(dvec, direction);
                        (*distvals)[j][i] += arcdist;
                    }
                    else if (i == 1)
                    {
                        /* Want minimum lateral distance to first group calculated */
                        tmpdist = trace(box);  /* should be max value */
                        for (k = 0; k < distsize; k++)
                        {
                            pbc_dx(&pbc, x1[distidx[k]], x1[a[index[i]+j]], dvec);
                            /* at the moment, just remove dvec[axis] */
                            dvec[axis] = 0;
                            tmpdist    = std::min(tmpdist, norm2(dvec));
                        }
                        //fprintf(stderr, "Min dist %f; trace %f\n", tmpdist, trace(box));
                        (*distvals)[j][i] += std::sqrt(tmpdist);
                    }
                }
            } /* end loop j, over all atoms in group */

            for (m = 0; m < DIM; m++)
            {
                (*order)[i][m] += (frameorder[m]/size);
            }

            if (!permolecule)
            {   /*Skip following if doing per-molecule*/
                for (k = 0; k < nslices; k++)
                {
                    if (slCount[k]) /* if no elements, nothing has to be added */
                    {
                        (*slOrder)[k][i] += slFrameorder[k]/slCount[k];
                        slFrameorder[k]   = 0; slCount[k] = 0;
                    }
                }
            } /* end loop i, over all groups in indexfile */
        }
        nr_frames++;

    }
    while (read_next_x(oenv, status, &t, x0, box));
    /*********** done with status file **********/

    fprintf(stderr, "\nRead trajectory. Printing parameters to file\n");
    gmx_rmpbc_done(gpbc);

    /* average over frames */
    for (i = 1; i < ngrps - 1; i++)
    {
        svmul(1.0/nr_frames, (*order)[i], (*order)[i]);
        fprintf(stderr, "Atom %d Tensor: x=%g , y=%g, z=%g\n", i, (*order)[i][XX],
                (*order)[i][YY], (*order)[i][ZZ]);
        if (bSliced || permolecule)
        {
            for (k = 0; k < nslices; k++)
            {
                (*slOrder)[k][i] /= nr_frames;
            }
        }
        if (distcalc)
        {
            for (k = 0; k < nslices; k++)
            {
                (*distvals)[k][i] /= nr_frames;
            }
        }
    }

    if (bUnsat)
    {
        fprintf(stderr, "Average angle between double bond and normal: %f\n",
                180*sdbangle/(nr_frames * size*M_PI));
    }

    sfree(x0); /* free memory used by coordinate arrays */
    sfree(x1);
    if (comidx != NULL)
    {
        sfree(comidx);
    }
    if (distidx != NULL)
    {
        sfree(distidx);
    }
    if (grpname != NULL)
    {
        sfree(grpname);
    }
}
Exemplo n.º 17
0
int gmx_polystat(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] plots static properties of polymers as a function of time",
        "and prints the average.[PAR]",
        "By default it determines the average end-to-end distance and radii",
        "of gyration of polymers. It asks for an index group and split this",
        "into molecules. The end-to-end distance is then determined using",
        "the first and the last atom in the index group for each molecules.",
        "For the radius of gyration the total and the three principal components",
        "for the average gyration tensor are written.",
        "With option [TT]-v[tt] the eigenvectors are written.",
        "With option [TT]-pc[tt] also the average eigenvalues of the individual",
        "gyration tensors are written.",
        "With option [TT]-i[tt] the mean square internal distances are",
        "written.[PAR]",
        "With option [TT]-p[tt] the persistence length is determined.",
        "The chosen index group should consist of atoms that are",
        "consecutively bonded in the polymer mainchains.",
        "The persistence length is then determined from the cosine of",
        "the angles between bonds with an index difference that is even,",
        "the odd pairs are not used, because straight polymer backbones",
        "are usually all trans and therefore only every second bond aligns.",
        "The persistence length is defined as number of bonds where",
        "the average cos reaches a value of 1/e. This point is determined",
        "by a linear interpolation of [LOG]<cos>[log]."
    };
    static gmx_bool bMW  = TRUE, bPC = FALSE;
    t_pargs         pa[] = {
        { "-mw", FALSE, etBOOL, {&bMW},
          "Use the mass weighting for radii of gyration" },
        { "-pc", FALSE, etBOOL, {&bPC},
          "Plot average eigenvalues" }
    };

    t_filenm        fnm[] = {
        { efTPR, nullptr, nullptr,  ffREAD  },
        { efTRX, "-f", nullptr,  ffREAD  },
        { efNDX, nullptr, nullptr,  ffOPTRD },
        { efXVG, "-o", "polystat",  ffWRITE },
        { efXVG, "-v", "polyvec", ffOPTWR },
        { efXVG, "-p", "persist",  ffOPTWR },
        { efXVG, "-i", "intdist", ffOPTWR }
    };
#define NFILE asize(fnm)

    t_topology       *top;
    gmx_output_env_t *oenv;
    int               ePBC;
    int               isize, *index, nmol, *molind, mol, nat_min = 0, nat_max = 0;
    char             *grpname;
    t_trxstatus      *status;
    real              t;
    rvec             *x, *bond = nullptr;
    matrix            box;
    int               natoms, i, j, frame, ind0, ind1, a, d, d2, ord[DIM] = {0};
    dvec              cm, sum_eig = {0, 0, 0};
    double          **gyr, **gyr_all, eig[DIM], **eigv;
    double            sum_eed2, sum_eed2_tot, sum_gyro, sum_gyro_tot, sum_pers_tot;
    int              *ninp    = nullptr;
    double           *sum_inp = nullptr, pers;
    double           *intd, ymax, ymin;
    double            mmol, m;
    char              title[STRLEN];
    FILE             *out, *outv, *outp, *outi;
    const char       *leg[8] = {
        "end to end", "<R\\sg\\N>",
        "<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3",
        "<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>"
    };
    char            **legp, buf[STRLEN];
    gmx_rmpbc_t       gpbc = nullptr;

    if (!parse_common_args(&argc, argv,
                           PCA_CAN_VIEW | PCA_CAN_TIME | PCA_TIME_UNIT,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
    {
        return 0;
    }

    snew(top, 1);
    ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm),
                        nullptr, box, &natoms, nullptr, nullptr, top);

    fprintf(stderr, "Select a group of polymer mainchain atoms:\n");
    get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm),
              1, &isize, &index, &grpname);

    snew(molind, top->mols.nr+1);
    nmol = 0;
    mol  = -1;
    for (i = 0; i < isize; i++)
    {
        if (i == 0 || index[i] >= top->mols.index[mol+1])
        {
            molind[nmol++] = i;
            do
            {
                mol++;
            }
            while (index[i] >= top->mols.index[mol+1]);
        }
    }
    molind[nmol] = i;
    nat_min      = top->atoms.nr;
    nat_max      = 0;
    for (mol = 0; mol < nmol; mol++)
    {
        nat_min = std::min(nat_min, molind[mol+1]-molind[mol]);
        nat_max = std::max(nat_max, molind[mol+1]-molind[mol]);
    }
    fprintf(stderr, "Group %s consists of %d molecules\n", grpname, nmol);
    fprintf(stderr, "Group size per molecule, min: %d atoms, max %d atoms\n",
            nat_min, nat_max);

    sprintf(title, "Size of %d polymers", nmol);
    out = xvgropen(opt2fn("-o", NFILE, fnm), title, output_env_get_xvgr_tlabel(oenv), "(nm)",
                   oenv);
    xvgr_legend(out, bPC ? 8 : 5, leg, oenv);

    if (opt2bSet("-v", NFILE, fnm))
    {
        outv = xvgropen(opt2fn("-v", NFILE, fnm), "Principal components",
                        output_env_get_xvgr_tlabel(oenv), "(nm)", oenv);
        snew(legp, DIM*DIM);
        for (d = 0; d < DIM; d++)
        {
            for (d2 = 0; d2 < DIM; d2++)
            {
                sprintf(buf, "eig%d %c", d+1, 'x'+d2);
                legp[d*DIM+d2] = gmx_strdup(buf);
            }
        }
        xvgr_legend(outv, DIM*DIM, (const char**)legp, oenv);
    }
    else
    {
        outv = nullptr;
    }

    if (opt2bSet("-p", NFILE, fnm))
    {
        outp = xvgropen(opt2fn("-p", NFILE, fnm), "Persistence length",
                        output_env_get_xvgr_tlabel(oenv), "bonds", oenv);
        snew(bond, nat_max-1);
        snew(sum_inp, nat_min/2);
        snew(ninp, nat_min/2);
    }
    else
    {
        outp = nullptr;
    }

    if (opt2bSet("-i", NFILE, fnm))
    {
        outi = xvgropen(opt2fn("-i", NFILE, fnm), "Internal distances",
                        "n", "<R\\S2\\N(n)>/n (nm\\S2\\N)", oenv);
        i = index[molind[1]-1] - index[molind[0]]; /* Length of polymer -1 */
        snew(intd, i);
    }
    else
    {
        intd = nullptr;
        outi = nullptr;
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    snew(gyr, DIM);
    snew(gyr_all, DIM);
    snew(eigv, DIM);
    for (d = 0; d < DIM; d++)
    {
        snew(gyr[d], DIM);
        snew(gyr_all[d], DIM);
        snew(eigv[d], DIM);
    }

    frame        = 0;
    sum_eed2_tot = 0;
    sum_gyro_tot = 0;
    sum_pers_tot = 0;

    gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);

    do
    {
        gmx_rmpbc(gpbc, natoms, box, x);

        sum_eed2 = 0;
        for (d = 0; d < DIM; d++)
        {
            clear_dvec(gyr_all[d]);
        }

        if (bPC)
        {
            clear_dvec(sum_eig);
        }

        if (outp)
        {
            for (i = 0; i < nat_min/2; i++)
            {
                sum_inp[i] = 0;
                ninp[i]    = 0;
            }
        }

        for (mol = 0; mol < nmol; mol++)
        {
            ind0 = molind[mol];
            ind1 = molind[mol+1];

            /* Determine end to end distance */
            sum_eed2 += distance2(x[index[ind0]], x[index[ind1-1]]);

            /* Determine internal distances */
            if (outi)
            {
                calc_int_dist(intd, x, index[ind0], index[ind1-1]);
            }

            /* Determine the radius of gyration */
            clear_dvec(cm);
            for (d = 0; d < DIM; d++)
            {
                clear_dvec(gyr[d]);
            }
            mmol = 0;

            for (i = ind0; i < ind1; i++)
            {
                a = index[i];
                if (bMW)
                {
                    m = top->atoms.atom[a].m;
                }
                else
                {
                    m = 1;
                }
                mmol += m;
                for (d = 0; d < DIM; d++)
                {
                    cm[d] += m*x[a][d];
                    for (d2 = 0; d2 < DIM; d2++)
                    {
                        gyr[d][d2] += m*x[a][d]*x[a][d2];
                    }
                }
            }
            dsvmul(1/mmol, cm, cm);
            for (d = 0; d < DIM; d++)
            {
                for (d2 = 0; d2 < DIM; d2++)
                {
                    gyr[d][d2]      = gyr[d][d2]/mmol - cm[d]*cm[d2];
                    gyr_all[d][d2] += gyr[d][d2];
                }
            }
            if (bPC)
            {
                gyro_eigen(gyr, eig, eigv, ord);
                for (d = 0; d < DIM; d++)
                {
                    sum_eig[d] += eig[ord[d]];
                }
            }
            if (outp)
            {
                for (i = ind0; i < ind1-1; i++)
                {
                    rvec_sub(x[index[i+1]], x[index[i]], bond[i-ind0]);
                    unitv(bond[i-ind0], bond[i-ind0]);
                }
                for (i = ind0; i < ind1-1; i++)
                {
                    for (j = 0; (i+j < ind1-1 && j < nat_min/2); j += 2)
                    {
                        sum_inp[j] += iprod(bond[i-ind0], bond[i-ind0+j]);
                        ninp[j]++;
                    }
                }
            }
        }
        sum_eed2 /= nmol;

        sum_gyro = 0;
        for (d = 0; d < DIM; d++)
        {
            for (d2 = 0; d2 < DIM; d2++)
            {
                gyr_all[d][d2] /= nmol;
            }
            sum_gyro += gyr_all[d][d];
        }

        gyro_eigen(gyr_all, eig, eigv, ord);

        fprintf(out, "%10.3f %8.4f %8.4f %8.4f %8.4f %8.4f",
                t*output_env_get_time_factor(oenv),
                std::sqrt(sum_eed2), sqrt(sum_gyro),
                std::sqrt(eig[ord[0]]), std::sqrt(eig[ord[1]]), std::sqrt(eig[ord[2]]));
        if (bPC)
        {
            for (d = 0; d < DIM; d++)
            {
                fprintf(out, " %8.4f", std::sqrt(sum_eig[d]/nmol));
            }
        }
        fprintf(out, "\n");

        if (outv)
        {
            fprintf(outv, "%10.3f", t*output_env_get_time_factor(oenv));
            for (d = 0; d < DIM; d++)
            {
                for (d2 = 0; d2 < DIM; d2++)
                {
                    fprintf(outv, " %6.3f", eigv[ord[d]][d2]);
                }
            }
            fprintf(outv, "\n");
        }

        sum_eed2_tot += sum_eed2;
        sum_gyro_tot += sum_gyro;

        if (outp)
        {
            i = -1;
            for (j = 0; j < nat_min/2; j += 2)
            {
                sum_inp[j] /= ninp[j];
                if (i == -1 && sum_inp[j] <= std::exp(-1.0))
                {
                    i = j;
                }
            }
            if (i == -1)
            {
                pers = j;
            }
            else
            {
                /* Do linear interpolation on a log scale */
                pers = i - 2.0
                    + 2.0*(std::log(sum_inp[i-2]) + 1.0)/(std::log(sum_inp[i-2]) - std::log(sum_inp[i]));
            }
            fprintf(outp, "%10.3f %8.4f\n", t*output_env_get_time_factor(oenv), pers);
            sum_pers_tot += pers;
        }

        frame++;
    }
    while (read_next_x(oenv, status, &t, x, box));

    gmx_rmpbc_done(gpbc);

    close_trx(status);

    xvgrclose(out);
    if (outv)
    {
        xvgrclose(outv);
    }
    if (outp)
    {
        xvgrclose(outp);
    }

    sum_eed2_tot /= frame;
    sum_gyro_tot /= frame;
    sum_pers_tot /= frame;
    fprintf(stdout, "\nAverage end to end distance: %.3f (nm)\n",
            std::sqrt(sum_eed2_tot));
    fprintf(stdout, "\nAverage radius of gyration:  %.3f (nm)\n",
            std::sqrt(sum_gyro_tot));
    if (opt2bSet("-p", NFILE, fnm))
    {
        fprintf(stdout, "\nAverage persistence length:  %.2f bonds\n",
                sum_pers_tot);
    }

    /* Handle printing of internal distances. */
    if (outi)
    {
        if (output_env_get_print_xvgr_codes(oenv))
        {
            fprintf(outi, "@    xaxes scale Logarithmic\n");
        }
        ymax = -1;
        ymin = 1e300;
        j    = index[molind[1]-1] - index[molind[0]]; /* Polymer length -1. */
        for (i = 0; i < j; i++)
        {
            intd[i] /= (i + 1) * frame * nmol;
            if (intd[i] > ymax)
            {
                ymax = intd[i];
            }
            if (intd[i] < ymin)
            {
                ymin = intd[i];
            }
        }
        xvgr_world(outi, 1, ymin, j, ymax, oenv);
        for (i = 0; i < j; i++)
        {
            fprintf(outi, "%d  %8.4f\n", i+1, intd[i]);
        }
        xvgrclose(outi);
    }

    do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy");
    if (opt2bSet("-v", NFILE, fnm))
    {
        do_view(oenv, opt2fn("-v", NFILE, fnm), "-nxy");
    }
    if (opt2bSet("-p", NFILE, fnm))
    {
        do_view(oenv, opt2fn("-p", NFILE, fnm), "-nxy");
    }

    return 0;
}
Exemplo n.º 18
0
static void find_nearest_neighbours(int ePBC,
                                    int natoms, matrix box,
                                    rvec x[], int maxidx, atom_id index[],
                                    real *sgmean, real *skmean,
                                    int nslice, int slice_dim,
                                    real sgslice[], real skslice[],
                                    gmx_rmpbc_t gpbc)
{
    int      ix, jx, nsgbin, *sgbin;
    int      i, ibin, j, k, l, n, *nn[4];
    rvec     dx, rj, rk, urk, urj;
    real     cost, cost2, *sgmol, *skmol, rmean, rmean2, r2, box2, *r_nn[4];
    t_pbc    pbc;
    int      sl_index;
    int     *sl_count;
    real     onethird = 1.0/3.0;
    /*  dmat = init_mat(maxidx, FALSE); */
    box2 = box[XX][XX] * box[XX][XX];
    snew(sl_count, nslice);
    for (i = 0; (i < 4); i++)
    {
        snew(r_nn[i], natoms);
        snew(nn[i], natoms);

        for (j = 0; (j < natoms); j++)
        {
            r_nn[i][j] = box2;
        }
    }

    snew(sgmol, maxidx);
    snew(skmol, maxidx);

    /* Must init pbc every step because of pressure coupling */
    set_pbc(&pbc, ePBC, box);

    gmx_rmpbc(gpbc, natoms, box, x);

    nsgbin = 2001; // Calculated as (1 + 1/0.0005)
    snew(sgbin, nsgbin);

    *sgmean = 0.0;
    *skmean = 0.0;
    l       = 0;
    for (i = 0; (i < maxidx); i++) /* loop over index file */
    {
        ix = index[i];
        for (j = 0; (j < maxidx); j++)
        {
            if (i == j)
            {
                continue;
            }

            jx = index[j];

            pbc_dx(&pbc, x[ix], x[jx], dx);
            r2 = iprod(dx, dx);

            /* set_mat_entry(dmat,i,j,r2); */

            /* determine the nearest neighbours */
            if (r2 < r_nn[0][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r_nn[1][i]; nn[2][i] = nn[1][i];
                r_nn[1][i] = r_nn[0][i]; nn[1][i] = nn[0][i];
                r_nn[0][i] = r2;         nn[0][i] = j;
            }
            else if (r2 < r_nn[1][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r_nn[1][i]; nn[2][i] = nn[1][i];
                r_nn[1][i] = r2;         nn[1][i] = j;
            }
            else if (r2 < r_nn[2][i])
            {
                r_nn[3][i] = r_nn[2][i]; nn[3][i] = nn[2][i];
                r_nn[2][i] = r2;         nn[2][i] = j;
            }
            else if (r2 < r_nn[3][i])
            {
                r_nn[3][i] = r2;         nn[3][i] = j;
            }
        }


        /* calculate mean distance between nearest neighbours */
        rmean = 0;
        for (j = 0; (j < 4); j++)
        {
            r_nn[j][i] = std::sqrt(r_nn[j][i]);
            rmean     += r_nn[j][i];
        }
        rmean /= 4;

        n        = 0;
        sgmol[i] = 0.0;
        skmol[i] = 0.0;

        /* Chau1998a eqn 3 */
        /* angular part tetrahedrality order parameter per atom */
        for (j = 0; (j < 3); j++)
        {
            for (k = j+1; (k < 4); k++)
            {
                pbc_dx(&pbc, x[ix], x[index[nn[k][i]]], rk);
                pbc_dx(&pbc, x[ix], x[index[nn[j][i]]], rj);

                unitv(rk, urk);
                unitv(rj, urj);

                cost  = iprod(urk, urj) + onethird;
                cost2 = cost * cost;

                /* sgmol[i] += 3*cost2/32;  */
                sgmol[i] += cost2;

                /* determine distribution */
                ibin = static_cast<int>(nsgbin * cost2);
                if (ibin < nsgbin)
                {
                    sgbin[ibin]++;
                }
                /* printf("%d %d %f %d %d\n", j, k, cost * cost, ibin, sgbin[ibin]);*/
                l++;
                n++;
            }
        }

        /* normalize sgmol between 0.0 and 1.0 */
        sgmol[i] = 3*sgmol[i]/32;
        *sgmean += sgmol[i];

        /* distance part tetrahedrality order parameter per atom */
        rmean2 = 4 * 3 * rmean * rmean;
        for (j = 0; (j < 4); j++)
        {
            skmol[i] += (rmean - r_nn[j][i]) * (rmean - r_nn[j][i]) / rmean2;
            /*      printf("%d %f (%f %f %f %f) \n",
                i, skmol[i], rmean, rmean2, r_nn[j][i], (rmean - r_nn[j][i]) );
             */
        }

        *skmean += skmol[i];

        /* Compute sliced stuff */
        sl_index           = static_cast<int>(std::round((1+x[i][slice_dim]/box[slice_dim][slice_dim])*nslice)) % nslice;
        sgslice[sl_index] += sgmol[i];
        skslice[sl_index] += skmol[i];
        sl_count[sl_index]++;
    } /* loop over entries in index file */

    *sgmean /= maxidx;
    *skmean /= maxidx;

    for (i = 0; (i < nslice); i++)
    {
        if (sl_count[i] > 0)
        {
            sgslice[i] /= sl_count[i];
            skslice[i] /= sl_count[i];
        }
    }
    sfree(sl_count);
    sfree(sgbin);
    sfree(sgmol);
    sfree(skmol);
    for (i = 0; (i < 4); i++)
    {
        sfree(r_nn[i]);
        sfree(nn[i]);
    }
}
Exemplo n.º 19
0
int gmx_densmap(int argc,char *argv[])
{
    const char *desc[] = {
        "[TT]g_densmap[tt] computes 2D number-density maps.",
        "It can make planar and axial-radial density maps.",
        "The output [TT].xpm[tt] file can be visualized with for instance xv",
        "and can be converted to postscript with [TT]xpm2ps[tt].",
        "Optionally, output can be in text form to a [TT].dat[tt] file with [TT]-od[tt], instead of the usual [TT].xpm[tt] file with [TT]-o[tt].",
        "[PAR]",
        "The default analysis is a 2-D number-density map for a selected",
        "group of atoms in the x-y plane.",
        "The averaging direction can be changed with the option [TT]-aver[tt].",
        "When [TT]-xmin[tt] and/or [TT]-xmax[tt] are set only atoms that are",
        "within the limit(s) in the averaging direction are taken into account.",
        "The grid spacing is set with the option [TT]-bin[tt].",
        "When [TT]-n1[tt] or [TT]-n2[tt] is non-zero, the grid",
        "size is set by this option.",
        "Box size fluctuations are properly taken into account.",
        "[PAR]",
        "When options [TT]-amax[tt] and [TT]-rmax[tt] are set, an axial-radial",
        "number-density map is made. Three groups should be supplied, the centers",
        "of mass of the first two groups define the axis, the third defines the",
        "analysis group. The axial direction goes from -amax to +amax, where",
        "the center is defined as the midpoint between the centers of mass and",
        "the positive direction goes from the first to the second center of mass.",
        "The radial direction goes from 0 to rmax or from -rmax to +rmax",
        "when the [TT]-mirror[tt] option has been set.",
        "[PAR]",
        "The normalization of the output is set with the [TT]-unit[tt] option.",
        "The default produces a true number density. Unit [TT]nm-2[tt] leaves out",
        "the normalization for the averaging or the angular direction.",
        "Option [TT]count[tt] produces the count for each grid cell.",
        "When you do not want the scale in the output to go",
        "from zero to the maximum density, you can set the maximum",
        "with the option [TT]-dmax[tt]."
    };
    static int n1=0,n2=0;
    static real xmin=-1,xmax=-1,bin=0.02,dmin=0,dmax=0,amax=0,rmax=0;
    static gmx_bool bMirror=FALSE, bSums=FALSE;
    static const char *eaver[]= { NULL, "z", "y", "x", NULL };
    static const char *eunit[]= { NULL, "nm-3", "nm-2", "count", NULL };

    t_pargs pa[] = {
        {   "-bin", FALSE, etREAL, {&bin},
            "Grid size (nm)"
        },
        {   "-aver", FALSE, etENUM, {eaver},
            "The direction to average over"
        },
        {   "-xmin", FALSE, etREAL, {&xmin},
            "Minimum coordinate for averaging"
        },
        {   "-xmax", FALSE, etREAL, {&xmax},
            "Maximum coordinate for averaging"
        },
        {   "-n1", FALSE, etINT, {&n1},
            "Number of grid cells in the first direction"
        },
        {   "-n2", FALSE, etINT, {&n2},
            "Number of grid cells in the second direction"
        },
        {   "-amax", FALSE, etREAL, {&amax},
            "Maximum axial distance from the center"
        },
        {   "-rmax", FALSE, etREAL, {&rmax},
            "Maximum radial distance"
        },
        {   "-mirror", FALSE, etBOOL, {&bMirror},
            "Add the mirror image below the axial axis"
        },
        {   "-sums", FALSE, etBOOL, {&bSums},
            "Print density sums (1D map) to stdout"
        },
        {   "-unit", FALSE, etENUM, {eunit},
            "Unit for the output"
        },
        {   "-dmin", FALSE, etREAL, {&dmin},
            "Minimum density in output"
        },
        {   "-dmax", FALSE, etREAL, {&dmax},
            "Maximum density in output (0 means calculate it)"
        },
    };
    gmx_bool       bXmin,bXmax,bRadial;
    FILE       *fp;
    t_trxstatus *status;
    t_topology top;
    int        ePBC=-1;
    rvec       *x,xcom[2],direction,center,dx;
    matrix     box;
    real       t,m,mtot;
    t_pbc      pbc;
    int        cav=0,c1=0,c2=0,natoms;
    char       **grpname,title[256],buf[STRLEN];
    const char *unit;
    int        i,j,k,l,ngrps,anagrp,*gnx=NULL,nindex,nradial=0,nfr,nmpower;
    atom_id    **ind=NULL,*index;
    real       **grid,maxgrid,m1,m2,box1,box2,*tickx,*tickz,invcellvol;
    real       invspa=0,invspz=0,axial,r,vol_old,vol,rowsum;
    int        nlev=51;
    t_rgb rlo= {1,1,1}, rhi= {0,0,0};
    output_env_t oenv;
    const char *label[]= { "x (nm)", "y (nm)", "z (nm)" };
    t_filenm fnm[] = {
        { efTRX, "-f",   NULL,       ffREAD },
        { efTPS, NULL,   NULL,       ffOPTRD },
        { efNDX, NULL,   NULL,       ffOPTRD },
        { efDAT, "-od",  "densmap",   ffOPTWR },
        { efXPM, "-o",   "densmap",   ffWRITE }
    };
#define NFILE asize(fnm)
    int     npargs;

    CopyRight(stderr,argv[0]);
    npargs = asize(pa);

    parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
                      NFILE,fnm,npargs,pa,asize(desc),desc,0,NULL,&oenv);

    bXmin = opt2parg_bSet("-xmin",npargs,pa);
    bXmax = opt2parg_bSet("-xmax",npargs,pa);
    bRadial = (amax>0 || rmax>0);
    if (bRadial) {
        if (amax<=0 || rmax<=0)
            gmx_fatal(FARGS,"Both amax and rmax should be larger than zero");
    }

    if (strcmp(eunit[0],"nm-3") == 0) {
        nmpower = -3;
        unit = "(nm^-3)";
    } else if (strcmp(eunit[0],"nm-2") == 0) {
        nmpower = -2;
        unit = "(nm^-2)";
    } else {
        nmpower = 0;
        unit = "count";
    }

    if (ftp2bSet(efTPS,NFILE,fnm) || !ftp2bSet(efNDX,NFILE,fnm))
        read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,
                      bRadial);
    if (!bRadial) {
        ngrps = 1;
        fprintf(stderr,"\nSelect an analysis group\n");
    } else {
        ngrps = 3;
        fprintf(stderr,
                "\nSelect two groups to define the axis and an analysis group\n");
    }
    snew(gnx,ngrps);
    snew(grpname,ngrps);
    snew(ind,ngrps);
    get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),ngrps,gnx,ind,grpname);
    anagrp = ngrps - 1;
    nindex = gnx[anagrp];
    index = ind[anagrp];
    if (bRadial) {
        if ((gnx[0]>1 || gnx[1]>1) && !ftp2bSet(efTPS,NFILE,fnm))
            gmx_fatal(FARGS,"No run input file was supplied (option -s), this is required for the center of mass calculation");
    }

    switch (eaver[0][0]) {
    case 'x':
        cav = XX;
        c1 = YY;
        c2 = ZZ;
        break;
    case 'y':
        cav = YY;
        c1 = XX;
        c2 = ZZ;
        break;
    case 'z':
        cav = ZZ;
        c1 = XX;
        c2 = YY;
        break;
    }

    natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);

    if (!bRadial) {
        if (n1 == 0)
            n1 = (int)(box[c1][c1]/bin + 0.5);
        if (n2 == 0)
            n2 = (int)(box[c2][c2]/bin + 0.5);
    } else {
        n1 = (int)(2*amax/bin + 0.5);
        nradial = (int)(rmax/bin + 0.5);
        invspa = n1/(2*amax);
        invspz = nradial/rmax;
        if (bMirror)
            n2 = 2*nradial;
        else
            n2 = nradial;
    }

    snew(grid,n1);
    for(i=0; i<n1; i++)
        snew(grid[i],n2);

    box1 = 0;
    box2 = 0;
    nfr = 0;
    do {
        if (!bRadial) {
            box1 += box[c1][c1];
            box2 += box[c2][c2];
            invcellvol = n1*n2;
            if (nmpower == -3)
                invcellvol /= det(box);
            else if (nmpower == -2)
                invcellvol /= box[c1][c1]*box[c2][c2];
            for(i=0; i<nindex; i++) {
                j = index[i];
                if ((!bXmin || x[j][cav] >= xmin) &&
                        (!bXmax || x[j][cav] <= xmax)) {
                    m1 = x[j][c1]/box[c1][c1];
                    if (m1 >= 1)
                        m1 -= 1;
                    if (m1 < 0)
                        m1 += 1;
                    m2 = x[j][c2]/box[c2][c2];
                    if (m2 >= 1)
                        m2 -= 1;
                    if (m2 < 0)
                        m2 += 1;
                    grid[(int)(m1*n1)][(int)(m2*n2)] += invcellvol;
                }
            }
        } else {
            set_pbc(&pbc,ePBC,box);
            for(i=0; i<2; i++) {
                if (gnx[i] == 1) {
                    /* One atom, just copy the coordinates */
                    copy_rvec(x[ind[i][0]],xcom[i]);
                } else {
                    /* Calculate the center of mass */
                    clear_rvec(xcom[i]);
                    mtot = 0;
                    for(j=0; j<gnx[i]; j++) {
                        k = ind[i][j];
                        m = top.atoms.atom[k].m;
                        for(l=0; l<DIM; l++)
                            xcom[i][l] += m*x[k][l];
                        mtot += m;
                    }
                    svmul(1/mtot,xcom[i],xcom[i]);
                }
            }
            pbc_dx(&pbc,xcom[1],xcom[0],direction);
            for(i=0; i<DIM; i++)
                center[i] = xcom[0][i] + 0.5*direction[i];
            unitv(direction,direction);
            for(i=0; i<nindex; i++) {
                j = index[i];
                pbc_dx(&pbc,x[j],center,dx);
                axial = iprod(dx,direction);
                r = sqrt(norm2(dx) - axial*axial);
                if (axial>=-amax && axial<amax && r<rmax) {
                    if (bMirror)
                        r += rmax;
                    grid[(int)((axial + amax)*invspa)][(int)(r*invspz)] += 1;
                }
            }
        }
        nfr++;
    } while(read_next_x(oenv,status,&t,natoms,x,box));
    close_trj(status);

    /* normalize gridpoints */
    maxgrid = 0;
    if (!bRadial) {
        for (i=0; i<n1; i++) {
            for (j=0; j<n2; j++) {
                grid[i][j] /= nfr;
                if (grid[i][j] > maxgrid)
                    maxgrid = grid[i][j];
            }
        }
    } else {
        for (i=0; i<n1; i++) {
            vol_old = 0;
            for (j=0; j<nradial; j++) {
                switch (nmpower) {
                case -3:
                    vol = M_PI*(j+1)*(j+1)/(invspz*invspz*invspa);
                    break;
                case -2:
                    vol =            (j+1)/(invspz*invspa);
                    break;
                default:
                    vol =             j+1;
                    break;
                }
                if (bMirror)
                    k = j + nradial;
                else
                    k = j;
                grid[i][k] /= nfr*(vol - vol_old);
                if (bMirror)
                    grid[i][nradial-1-j] = grid[i][k];
                vol_old = vol;
                if (grid[i][k] > maxgrid)
                    maxgrid = grid[i][k];
            }
        }
    }
    fprintf(stdout,"\n  The maximum density is %f %s\n",maxgrid,unit);
    if (dmax > 0)
        maxgrid = dmax;

    snew(tickx,n1+1);
    snew(tickz,n2+1);
    if (!bRadial) {
        /* normalize box-axes */
        box1 /= nfr;
        box2 /= nfr;
        for (i=0; i<=n1; i++)
            tickx[i] = i*box1/n1;
        for (i=0; i<=n2; i++)
            tickz[i] = i*box2/n2;
    } else {
        for (i=0; i<=n1; i++)
            tickx[i] = i/invspa - amax;
        if (bMirror) {
            for (i=0; i<=n2; i++)
                tickz[i] = i/invspz - rmax;
        } else {
            for (i=0; i<=n2; i++)
                tickz[i] = i/invspz;
        }
    }

    if (bSums)
    {
        for (i=0; i<n1; ++i)
        {
            fprintf(stdout,"Density sums:\n");
            rowsum=0;
            for (j=0; j<n2; ++j)
                rowsum+=grid[i][j];
            fprintf(stdout,"%g\t",rowsum);
        }
        fprintf(stdout,"\n");
    }

    sprintf(buf,"%s number density",grpname[anagrp]);
    if (!bRadial && (bXmin || bXmax)) {
        if (!bXmax)
            sprintf(buf+strlen(buf),", %c > %g nm",eaver[0][0],xmin);
        else if (!bXmin)
            sprintf(buf+strlen(buf),", %c < %g nm",eaver[0][0],xmax);
        else
            sprintf(buf+strlen(buf),", %c: %g - %g nm",eaver[0][0],xmin,xmax);
    }
    if (ftp2bSet(efDAT,NFILE,fnm))
    {
        fp = ffopen(ftp2fn(efDAT,NFILE,fnm),"w");
        /*optional text form output:  first row is tickz; first col is tickx */
        fprintf(fp,"0\t");
        for(j=0; j<n2; ++j)
            fprintf(fp,"%g\t",tickz[j]);
        fprintf(fp,"\n");

        for (i=0; i<n1; ++i)
        {
            fprintf(fp,"%g\t",tickx[i]);
            for (j=0; j<n2; ++j)
                fprintf(fp,"%g\t",grid[i][j]);
            fprintf(fp,"\n");
        }
        ffclose(fp);
    }
    else
    {
        fp = ffopen(ftp2fn(efXPM,NFILE,fnm),"w");
        write_xpm(fp,MAT_SPATIAL_X | MAT_SPATIAL_Y,buf,unit,
                  bRadial ? "axial (nm)" : label[c1],bRadial ? "r (nm)" : label[c2],
                  n1,n2,tickx,tickz,grid,dmin,maxgrid,rlo,rhi,&nlev);
        ffclose(fp);
    }

    thanx(stderr);

    do_view(oenv,opt2fn("-o",NFILE,fnm),NULL);

    return 0;
}
Exemplo n.º 20
0
void do_mmcg (int natoms,		// number of atoms in simulation
 	    t_inputrec   *inputrec, 	// input record and box stuff
	    t_mdatoms    *md,		// the atoms
	    t_state      *state,	// positions & velocities
	    gmx_mtop_t   *top,		// global topology
	    t_commrec    *cr,   	// communicators
	    rvec         *cg_cm,	// centre of mass of charge groups
	    int *allcgid, 		// charge groups ids
	    int allcgnr,		// charge groups number
	    int *allsolid,		// solvent groups ids
	    int allsolnr,		// solvent groups number
    	    FILE *log)			// logfile
{
 int i, j, p, q, qmin;
 real dvmod, shell2w2, dmin, d;
 rvec vecdist, dv, *v;
 shell2w2 = pow (inputrec->mmcg.shell2wt, 2.0);	// Threshold
 v = state->v;			               	// Velocities
 t_block cgs;					// charge groups
 cgs = gmx_mtop_global_cgs(top);
 rvec *all_cg_cm=NULL;
 snew(all_cg_cm,allcgnr);

 // for DD, we need to get cg_cm of all given charge groups (fr->cg_cm is local), 
 // the nearest one from a monitored water
 // may be more than one DD cell distant.
 if (DOMAINDECOMP(cr)) {
    if(cr->nnodes!=1) gmx_barrier(cr);
    for(i=0; i<allcgnr; i++) {
	int sender = 0,senderf,k;
	for(j=0; j<cr->dd->ncg_home; j++) { // is the cg a home cg ?
	   if(cr->dd->index_gl[j]==allcgid[i] ) {
		sender = cr->sim_nodeid;
		for(k=0;k<3;k++) all_cg_cm[i][k]=cg_cm[j][k];//FIXME improve ! compilation error when done with pointers
	   } 
	}
	MPI_Allreduce(&sender,&senderf,1,MPI_INT,MPI_SUM,cr->dd->mpi_comm_all);
	for(k=0;k<3;k++) MPI_Bcast(&all_cg_cm[i][k],sizeof(all_cg_cm[i][k]),MPI_BYTE,senderf,cr->dd->mpi_comm_all); //FIXME again !
    }
 }

 for(i=0; i<allsolnr; i++) {	// Loop over waters - START
    p = allsolid[i];
    if (PARTDECOMP(cr)) { // water i is in the node
        if((cgs.index[p]>=md->start) && (cgs.index[p]<(md->start+md->homenr))) {
      		for (j=0; j<allcgnr; j++) { // Looking for min dist (dmin)
		   q = allcgid[j];	    // and for the nearest charge group (qmin)
		   d = distance2(cg_cm[p],cg_cm[q]);
		   if(!j) 		{ dmin = d; qmin = q; } 
		   else if (d < dmin) 	{ dmin = d; qmin = q; }
        	}
	
      		if (dmin >= shell2w2) {	// Modifing velocity
		    rvec_sub(cg_cm[p], cg_cm[qmin], vecdist);
	 	    unitv (vecdist, vecdist);
		      for (j=cgs.index[p]; j<(3+cgs.index[p]); j++) {
	  		 dvmod = iprod (v[j], vecdist);
	  		 if (dvmod <= 0) continue;
	  		 svmul (2.0*dvmod, vecdist, dv);
	  		 rvec_dec (&v[j], dv); // Warning (=>?)				
		      }
      		}
	}
    }
    if (DOMAINDECOMP(cr)) { 
	int g_atnr; // global atom ID
	int l_atnr; // local atom ID in the DD cell
	int l_cgnr; // local charge group number

	for(g_atnr=cgs.index[p];g_atnr<=cgs.index[p]+2;g_atnr++) {
	    if(ga2la_get_home(cr->dd->ga2la,g_atnr,&l_atnr)) {// search in global to local lookup table 
							      // if the atom (not water) is in home atoms 
							      // and get local atom number
      		l_cgnr = cr->dd->la2lc[l_atnr]; // get local charge group number
	
		for (j=0; j<allcgnr; j++) { // Looking for min dist (dmin)
					    // and for the nearest charge group (qmin)
		   d = distance2(cg_cm[l_cgnr],all_cg_cm[j]);
		   if(!j) 		{ dmin = d; qmin = j; } 
		   else if (d < dmin) 	{ dmin = d; qmin = j; }
        	}

      		if (dmin >= shell2w2) {	// Modifing velocity
		    rvec_sub(cg_cm[l_cgnr], all_cg_cm[qmin], vecdist);
	 	    unitv (vecdist, vecdist);
	  	    dvmod = iprod (v[l_atnr], vecdist);
	  	    if (dvmod <= 0) continue;
	  	    svmul (2.0*dvmod, vecdist, dv);
	  	    rvec_dec (&v[l_atnr], dv);	// Warning (=>?)
      		}
	    }
	}
    }
  } // Loop over waters - END
  return;
}