Esempio n. 1
0
int gmx_do_dssp(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] ",
        "reads a trajectory file and computes the secondary structure for",
        "each time frame ",
        "calling the dssp program. If you do not have the dssp program,",
        "get it from http://swift.cmbi.ru.nl/gv/dssp. [THISMODULE] assumes ",
        "that the dssp executable is located in ",
        "[TT]/usr/local/bin/dssp[tt]. If this is not the case, then you should",
        "set an environment variable [TT]DSSP[tt] pointing to the dssp",
        "executable, e.g.: [PAR]",
        "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]",
        "Since version 2.0.0, dssp is invoked with a syntax that differs",
        "from earlier versions. If you have an older version of dssp,",
        "use the [TT]-ver[tt] option to direct do_dssp to use the older syntax.",
        "By default, do_dssp uses the syntax introduced with version 2.0.0.",
        "Even newer versions (which at the time of writing are not yet released)",
        "are assumed to have the same syntax as 2.0.0.[PAR]",
        "The structure assignment for each residue and time is written to an",
        "[TT].xpm[tt] matrix file. This file can be visualized with for instance",
        "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].",
        "Individual chains are separated by light grey lines in the [TT].xpm[tt] and",
        "postscript files.",
        "The number of residues with each secondary structure type and the",
        "total secondary structure ([TT]-sss[tt]) count as a function of",
        "time are also written to file ([TT]-sc[tt]).[PAR]",
        "Solvent accessible surface (SAS) per residue can be calculated, both in",
        "absolute values (A^2) and in fractions of the maximal accessible",
        "surface of a residue. The maximal accessible surface is defined as",
        "the accessible surface of a residue in a chain of glycines.",
        "[BB]Note[bb] that the program [gmx-sas] can also compute SAS",
        "and that is more efficient.[PAR]",
        "Finally, this program can dump the secondary structure in a special file",
        "[TT]ssdump.dat[tt] for usage in the program [gmx-chi]. Together",
        "these two programs can be used to analyze dihedral properties as a",
        "function of secondary structure type."
    };
    static gmx_bool    bVerbose;
    static const char *ss_string   = "HEBT";
    static int         dsspVersion = 2;
    t_pargs            pa[]        = {
        { "-v",  FALSE, etBOOL, {&bVerbose},
          "HIDDENGenerate miles of useless information" },
        { "-sss", FALSE, etSTR, {&ss_string},
          "Secondary structures for structure count"},
        { "-ver", FALSE, etINT, {&dsspVersion},
          "DSSP major version. Syntax changed with version 2"}
    };

    t_trxstatus       *status;
    FILE              *tapein;
    FILE              *ss, *acc, *fTArea, *tmpf;
    const char        *fnSCount, *fnArea, *fnTArea, *fnAArea;
    const char        *leg[] = { "Phobic", "Phylic" };
    t_topology         top;
    int                ePBC;
    t_atoms           *atoms;
    t_matrix           mat;
    int                nres, nr0, naccr, nres_plus_separators;
    gmx_bool          *bPhbres, bDoAccSurf;
    real               t;
    int                i, j, natoms, nframe = 0;
    matrix             box = {{0}};
    int                gnx;
    char              *grpnm, *ss_str;
    atom_id           *index;
    rvec              *xp, *x;
    int               *average_area;
    real             **accr, *accr_ptr = NULL, *av_area, *norm_av_area;
    char               pdbfile[32], tmpfile[32], title[256];
    char               dssp[256];
    const char        *dptr;
    output_env_t       oenv;
    gmx_rmpbc_t        gpbc = NULL;

    t_filenm           fnm[] = {
        { efTRX, "-f",   NULL,      ffREAD },
        { efTPS, NULL,   NULL,      ffREAD },
        { efNDX, NULL,   NULL,      ffOPTRD },
        { efDAT, "-ssdump", "ssdump", ffOPTWR },
        { efMAP, "-map", "ss",      ffLIBRD },
        { efXPM, "-o",   "ss",      ffWRITE },
        { efXVG, "-sc",  "scount",  ffWRITE },
        { efXPM, "-a",   "area",    ffOPTWR },
        { efXVG, "-ta",  "totarea", ffOPTWR },
        { efXVG, "-aa",  "averarea", ffOPTWR }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv,
                           PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }
    fnSCount   = opt2fn("-sc", NFILE, fnm);
    fnArea     = opt2fn_null("-a", NFILE, fnm);
    fnTArea    = opt2fn_null("-ta", NFILE, fnm);
    fnAArea    = opt2fn_null("-aa", NFILE, fnm);
    bDoAccSurf = (fnArea || fnTArea || fnAArea);

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xp, NULL, box, FALSE);
    atoms = &(top.atoms);
    check_oo(atoms);
    bPhbres = bPhobics(atoms);

    get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpnm);
    nres = 0;
    nr0  = -1;
    for (i = 0; (i < gnx); i++)
    {
        if (atoms->atom[index[i]].resind != nr0)
        {
            nr0 = atoms->atom[index[i]].resind;
            nres++;
        }
    }
    fprintf(stderr, "There are %d residues in your selected group\n", nres);

    strcpy(pdbfile, "ddXXXXXX");
    gmx_tmpnam(pdbfile);
    if ((tmpf = fopen(pdbfile, "w")) == NULL)
    {
        sprintf(pdbfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
        gmx_tmpnam(pdbfile);
        if ((tmpf = fopen(pdbfile, "w")) == NULL)
        {
            gmx_fatal(FARGS, "Can not open tmp file %s", pdbfile);
        }
    }
    else
    {
        fclose(tmpf);
    }

    strcpy(tmpfile, "ddXXXXXX");
    gmx_tmpnam(tmpfile);
    if ((tmpf = fopen(tmpfile, "w")) == NULL)
    {
        sprintf(tmpfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR);
        gmx_tmpnam(tmpfile);
        if ((tmpf = fopen(tmpfile, "w")) == NULL)
        {
            gmx_fatal(FARGS, "Can not open tmp file %s", tmpfile);
        }
    }
    else
    {
        fclose(tmpf);
    }

    if ((dptr = getenv("DSSP")) == NULL)
    {
        dptr = "/usr/local/bin/dssp";
    }
    if (!gmx_fexist(dptr))
    {
        gmx_fatal(FARGS, "DSSP executable (%s) does not exist (use setenv DSSP)",
                  dptr);
    }
    if (dsspVersion >= 2)
    {
        if (dsspVersion > 2)
        {
            printf("\nWARNING: You use DSSP version %d, which is not explicitly\nsupported by do_dssp. Assuming version 2 syntax.\n\n", dsspVersion);
        }

        sprintf(dssp, "%s -i %s -o %s > /dev/null %s",
                dptr, pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null");
    }
    else
    {
        sprintf(dssp, "%s %s %s %s > /dev/null %s",
                dptr, bDoAccSurf ? "" : "-na", pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null");

    }
    fprintf(stderr, "dssp cmd='%s'\n", dssp);

    if (fnTArea)
    {
        fTArea = xvgropen(fnTArea, "Solvent Accessible Surface Area",
                          output_env_get_xvgr_tlabel(oenv), "Area (nm\\S2\\N)", oenv);
        xvgr_legend(fTArea, 2, leg, oenv);
    }
    else
    {
        fTArea = NULL;
    }

    mat.map  = NULL;
    mat.nmap = readcmap(opt2fn("-map", NFILE, fnm), &(mat.map));

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    if (natoms > atoms->nr)
    {
        gmx_fatal(FARGS, "\nTrajectory does not match topology!");
    }
    if (gnx > natoms)
    {
        gmx_fatal(FARGS, "\nTrajectory does not match selected group!");
    }

    snew(average_area, atoms->nres);
    snew(av_area, atoms->nres);
    snew(norm_av_area, atoms->nres);
    accr  = NULL;
    naccr = 0;

    gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    do
    {
        t = output_env_conv_time(oenv, t);
        if (bDoAccSurf && nframe >= naccr)
        {
            naccr += 10;
            srenew(accr, naccr);
            for (i = naccr-10; i < naccr; i++)
            {
                snew(accr[i], 2*atoms->nres-1);
            }
        }
        gmx_rmpbc(gpbc, natoms, box, x);
        tapein = gmx_ffopen(pdbfile, "w");
        write_pdbfile_indexed(tapein, NULL, atoms, x, ePBC, box, ' ', -1, gnx, index, NULL, TRUE);
        gmx_ffclose(tapein);

#ifdef GMX_NO_SYSTEM
        printf("Warning-- No calls to system(3) supported on this platform.");
        printf("Warning-- Skipping execution of 'system(\"%s\")'.", dssp);
        exit(1);
#else
        if (0 != system(dssp))
        {
            gmx_fatal(FARGS, "Failed to execute command: %s\n",
                      "Try specifying your dssp version with the -ver option.", dssp);
        }
#endif

        /* strip_dssp returns the number of lines found in the dssp file, i.e.
         * the number of residues plus the separator lines */

        if (bDoAccSurf)
        {
            accr_ptr = accr[nframe];
        }

        nres_plus_separators = strip_dssp(tmpfile, nres, bPhbres, t,
                                          accr_ptr, fTArea, &mat, average_area, oenv);
        remove(tmpfile);
        remove(pdbfile);
        nframe++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    fprintf(stderr, "\n");
    close_trj(status);
    if (fTArea)
    {
        gmx_ffclose(fTArea);
    }
    gmx_rmpbc_done(gpbc);

    prune_ss_legend(&mat);

    ss        = opt2FILE("-o", NFILE, fnm, "w");
    mat.flags = 0;
    write_xpm_m(ss, mat);
    gmx_ffclose(ss);

    if (opt2bSet("-ssdump", NFILE, fnm))
    {
        ss = opt2FILE("-ssdump", NFILE, fnm, "w");
        snew(ss_str, nres+1);
        fprintf(ss, "%d\n", nres);
        for (j = 0; j < mat.nx; j++)
        {
            for (i = 0; (i < mat.ny); i++)
            {
                ss_str[i] = mat.map[mat.matrix[j][i]].code.c1;
            }
            ss_str[i] = '\0';
            fprintf(ss, "%s\n", ss_str);
        }
        gmx_ffclose(ss);
        sfree(ss_str);
    }
    analyse_ss(fnSCount, &mat, ss_string, oenv);

    if (bDoAccSurf)
    {
        write_sas_mat(fnArea, accr, nframe, nres_plus_separators, &mat);

        for (i = 0; i < atoms->nres; i++)
        {
            av_area[i] = (average_area[i] / (real)nframe);
        }

        norm_acc(atoms, nres, av_area, norm_av_area);

        if (fnAArea)
        {
            acc = xvgropen(fnAArea, "Average Accessible Area",
                           "Residue", "A\\S2", oenv);
            for (i = 0; (i < nres); i++)
            {
                fprintf(acc, "%5d  %10g %10g\n", i+1, av_area[i], norm_av_area[i]);
            }
            gmx_ffclose(acc);
        }
    }

    view_all(oenv, NFILE, fnm);

    return 0;
}
Esempio n. 2
0
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac,
                         real rho, real wt, const char *fn_trans,
                         const char *fn_tca, const char *fn_tc,
                         const char *fn_tcf, const char *fn_cub,
                         const char *fn_vk, const output_env_t oenv)
{
    FILE  *fp, *fp_vk, *fp_cub = NULL;
    int    nk, ntc;
    real **tcaf, **tcafc = NULL, eta;
    int    i, j, k, kc;
    int    ncorr;
    real   fitparms[3], *sig;

    nk  = kset_c[nkc];
    ntc = nk*NPK;

    if (fn_trans)
    {
        fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)",
                      oenv);
        for (i = 0; i < nframes; i++)
        {
            fprintf(fp, "%g", i*dt);
            for (j = 0; j < ntc; j++)
            {
                fprintf(fp, " %g", tc[j][i]);
            }
            fprintf(fp, "\n");
        }
        ffclose(fp);
        do_view(oenv, fn_trans, "-nxy");
    }

    ncorr = (nframes+1)/2;
    if (ncorr > (int)(5*wt/dt+0.5))
    {
        ncorr = (int)(5*wt/dt+0.5)+1;
    }
    snew(tcaf, nk);
    for (k = 0; k < nk; k++)
    {
        snew(tcaf[k], ncorr);
    }
    if (fn_cub)
    {
        snew(tcafc, nkc);
        for (k = 0; k < nkc; k++)
        {
            snew(tcafc[k], ncorr);
        }
    }
    snew(sig, ncorr);
    for (i = 0; i < ncorr; i++)
    {
        sig[i] = exp(0.5*i*dt/wt);
    }

    low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions",
                    nframes, ntc, ncorr, tc, dt, eacNormal,
                    1, FALSE, FALSE, FALSE, 0, 0, 0);
    do_view(oenv, fn_tca, "-nxy");

    fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions",
                  "Time (ps)", "TCAF", oenv);
    for (i = 0; i < ncorr; i++)
    {
        kc = 0;
        fprintf(fp, "%g", i*dt);
        for (k = 0; k < nk; k++)
        {
            for (j = 0; j < NPK; j++)
            {
                tcaf[k][i] += tc[NPK*k+j][i];
            }
            if (fn_cub)
            {
                for (j = 0; j < NPK; j++)
                {
                    tcafc[kc][i] += tc[NPK*k+j][i];
                }
            }
            if (i == 0)
            {
                fprintf(fp, " %g", 1.0);
            }
            else
            {
                tcaf[k][i] /= tcaf[k][0];
                fprintf(fp, " %g", tcaf[k][i]);
            }
            if (k+1 == kset_c[kc+1])
            {
                kc++;
            }
        }
        fprintf(fp, "\n");
    }
    ffclose(fp);
    do_view(oenv, fn_tc, "-nxy");

    if (fn_cub)
    {
        fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv);
        for (kc = 0; kc < nkc; kc++)
        {
            fprintf(fp_cub, "%g %g\n", 0.0, 1.0);
            for (i = 1; i < ncorr; i++)
            {
                tcafc[kc][i] /= tcafc[kc][0];
                fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]);
            }
            fprintf(fp_cub, "&\n");
            tcafc[kc][0] = 1.0;
        }
    }

    fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)",
                     "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv);
    fprintf(fp_vk, "@    s0 symbol 2\n");
    fprintf(fp_vk, "@    s0 symbol color 1\n");
    fprintf(fp_vk, "@    s0 linestyle 0\n");
    if (fn_cub)
    {
        fprintf(fp_vk, "@    s1 symbol 3\n");
        fprintf(fp_vk, "@    s1 symbol color 2\n");
    }
    fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv);
    for (k = 0; k < nk; k++)
    {
        tcaf[k][0]   = 1.0;
        fitparms[0]  = 1;
        fitparms[1]  = 1;
        do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt,
                 oenv, bDebugMode(), effnVAC, fitparms, 0);
        eta = 1000*fitparms[1]*rho/
            (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO));
        fprintf(stdout, "k %6.3f  tau %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                norm(kfac[k]), fitparms[0], eta);
        fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta);
        for (i = 0; i < ncorr; i++)
        {
            fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
        }
        fprintf(fp, "&\n");
    }
    ffclose(fp);
    do_view(oenv, fn_tcf, "-nxy");

    if (fn_cub)
    {
        fprintf(stdout, "Averaged over k-vectors:\n");
        fprintf(fp_vk, "&\n");
        for (k = 0; k < nkc; k++)
        {
            tcafc[k][0]  = 1.0;
            fitparms[0]  = 1;
            fitparms[1]  = 1;
            do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt,
                     oenv, bDebugMode(), effnVAC, fitparms, 0);
            eta = 1000*fitparms[1]*rho/
                (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO));
            fprintf(stdout,
                    "k %6.3f  tau %6.3f  Omega %6.3f  eta %8.5f 10^-3 kg/(m s)\n",
                    norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta);
            fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta);
            for (i = 0; i < ncorr; i++)
            {
                fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt));
            }
            fprintf(fp_cub, "&\n");
        }
        fprintf(fp_vk, "&\n");
        ffclose(fp_cub);
        do_view(oenv, fn_cub, "-nxy");
    }
    ffclose(fp_vk);
    do_view(oenv, fn_vk, "-nxy");
}
Esempio n. 3
0
int gmx_genion(int argc, char *argv[])
{
  const char *desc[] = {
    "genion replaces solvent molecules by monoatomic ions at",
    "the position of the first atoms with the most favorable electrostatic",
    "potential or at random. The potential is calculated on all atoms, using",
    "normal GROMACS particle based methods (in contrast to other methods",
    "based on solving the Poisson-Boltzmann equation).",
    "The potential is recalculated after every ion insertion.",
    "If specified in the run input file, a reaction field, shift function",
    "or user function can be used. For the user function a table file",
    "can be specified with the option [TT]-table[tt].",
    "The group of solvent molecules should be continuous and all molecules",
    "should have the same number of atoms.",
    "The user should add the ion molecules to the topology file and include",
    "the file [TT]ions.itp[tt].",
    "Ion names for Gromos96 should include the charge.[PAR]",
    "With the option [TT]-pot[tt] the potential can be written as B-factors",
    "in a pdb file (for visualisation using e.g. rasmol).",
    "The unit of the potential is 1000 kJ/(mol e), the scaling be changed",
    "with the [TT]-scale[tt] option.[PAR]",
    "For larger ions, e.g. sulfate we recommended to use genbox."
  };
  const char *bugs[] = {
    "Calculation of the potential is not reliable, therefore the [TT]-random[tt] option is now turned on by default.",
    "If you specify a salt concentration existing ions are not taken into account. In effect you therefore specify the amount of salt to be added."
  };
  static int  p_num=0,n_num=0,p_q=1,n_q=-1;
  static const char *p_name="Na",*n_name="Cl";
  static real rmin=0.6,scale=0.001,conc=0;
  static int  seed=1993;
  static bool bRandom=TRUE,bNeutral=FALSE;
  static t_pargs pa[] = {
    { "-np",    FALSE, etINT,  {&p_num}, "Number of positive ions"       },
    { "-pname", FALSE, etSTR,  {&p_name},"Name of the positive ion"      },
    { "-pq",    FALSE, etINT,  {&p_q},   "Charge of the positive ion"    },
    { "-nn",    FALSE, etINT,  {&n_num}, "Number of negative ions"       },
    { "-nname", FALSE, etSTR,  {&n_name},"Name of the negative ion"      },
    { "-nq",    FALSE, etINT,  {&n_q},   "Charge of the negative ion"    },
    { "-rmin",  FALSE, etREAL, {&rmin},  "Minimum distance between ions" },
    { "-random",FALSE,etBOOL, {&bRandom},"Use random placement of ions instead of based on potential. The rmin option should still work" },
    { "-seed",  FALSE, etINT,  {&seed},  "Seed for random number generator" },
    { "-scale", FALSE, etREAL, {&scale}, "Scaling factor for the potential for -pot" },
    { "-conc",  FALSE, etREAL, {&conc},  
      "Specify salt concentration (mol/liter). This will add sufficient ions to reach up to the specified concentration as computed from the volume of the cell in the input tpr file. Overrides the -np and  nn options." },
    { "-neutral", FALSE, etBOOL, {&bNeutral},
      "This option will add enough ions to neutralize the system. In combination with the concentration option a neutral system at a given salt concentration will be generated." }
  };
  gmx_mtop_t  *mtop;
  gmx_localtop_t *top;
  t_inputrec  inputrec;
  t_commrec   *cr;
  t_mdatoms   *mdatoms;
  gmx_enerdata_t enerd;
  t_graph     *graph;
  t_forcerec  *fr;
  rvec        *x,*v;
  real        *pot,vol,qtot;
  matrix      box;
  t_atoms     atoms;
  t_pbc       pbc;
  int         *repl;
  atom_id     *index;
  char        *grpname;
  bool        *bSet,bPDB;
  int         i,nw,nwa,nsa,nsalt,iqtot;
  FILE        *fplog;
  t_filenm fnm[] = {
    { efTPX, NULL,  NULL,      ffREAD  },
    { efXVG, "-table","table", ffOPTRD },
    { efNDX, NULL,  NULL,      ffOPTRD },
    { efSTO, "-o",  NULL,      ffWRITE },
    { efLOG, "-g",  "genion",  ffWRITE },
    { efPDB, "-pot", "pot",    ffOPTWR },
    { efTOP, "-p",  "topol",   ffOPTRW }
  };
#define NFILE asize(fnm)
  
  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_BE_NICE,NFILE,fnm,asize(pa),pa,asize(desc),desc,
		    asize(bugs),bugs);
  bPDB = ftp2bSet(efPDB,NFILE,fnm);
  if (bRandom && bPDB) {
    fprintf(stderr,"Not computing potential with random option!\n");
    bPDB = FALSE;
  }
    
  /* Check input for something sensible */
  if ((p_num<0) || (n_num<0))
    gmx_fatal(FARGS,"Negative number of ions to add?");

  snew(mtop,1);
  snew(top,1);
  fplog = init_calcpot(ftp2fn(efLOG,NFILE,fnm),ftp2fn(efTPX,NFILE,fnm),
		       opt2fn("-table",NFILE,fnm),mtop,top,&inputrec,&cr,
		       &graph,&mdatoms,&fr,&enerd,&pot,box,&x);

  atoms = gmx_mtop_global_atoms(mtop);

  qtot = 0;
  for(i=0; (i<atoms.nr); i++)
    qtot += atoms.atom[i].q;
  iqtot = gmx_nint(qtot);
    
  if ((conc > 0) || bNeutral) {
    /* Compute number of ions to be added */
    vol = det(box);
    if (conc > 0) {
      nsalt = gmx_nint(conc*vol*AVOGADRO/1e24);
      p_num = abs(nsalt*n_q);
      n_num = abs(nsalt*p_q);
      if (bNeutral) {
	int qdelta = 0;
	do {
	  qdelta = (p_num*p_q + n_num*n_q + iqtot);
	  if (qdelta < 0) {
	    p_num  += abs(qdelta/p_q);
	    qdelta = (p_num*p_q + n_num*n_q + iqtot);
	  }
	  if (qdelta > 0) {
	    n_num  += abs(qdelta/n_q);
	    qdelta = (p_num*p_q + n_num*n_q + iqtot);
	  } 
	} while (qdelta != 0);
      }
    }
  }
	       
  if ((p_num == 0) && (n_num == 0)) {
    if (!bPDB) {
      fprintf(stderr,"No ions to add and no potential to calculate.\n");
      exit(0);
    }
    nw  = 0;
    nsa = 0; /* to keep gcc happy */
  } else {
    printf("Will try to add %d %s ions and %d %s ions.\n",
	   p_num,p_name,n_num,n_name);
    printf("Select a continuous group of solvent molecules\n");
    get_index(&atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&nwa,&index,&grpname);
    for(i=1; i<nwa; i++)
      if (index[i] != index[i-1]+1)
	gmx_fatal(FARGS,"The solvent group %s is not continuous: "
		  "index[%d]=%d, index[%d]=%d",
		  grpname,i,index[i-1]+1,i+1,index[i]+1);
    nsa = 1;
    while ((nsa<nwa) &&
	   (atoms.atom[index[nsa]].resind ==
	    atoms.atom[index[nsa-1]].resind))
      nsa++;
    if (nwa % nsa)
      gmx_fatal(FARGS,"Your solvent group size (%d) is not a multiple of %d",
		  nwa,nsa);
    nw = nwa/nsa;
    fprintf(stderr,"Number of (%d-atomic) solvent molecules: %d\n",nsa,nw);
	if (p_num+n_num > nw)
      gmx_fatal(FARGS,"Not enough solvent for adding ions");
  }
  
  if (opt2bSet("-p",NFILE,fnm)) 
    update_topol(opt2fn("-p",NFILE,fnm),p_num,n_num,p_name,n_name,grpname);
    
  snew(bSet,nw);
  snew(repl,nw);
  
  snew(v,atoms.nr);
  snew(atoms.pdbinfo,atoms.nr);

  set_pbc(&pbc,inputrec.ePBC,box);

  /* Now loop over the ions that have to be placed */
  do {
    if (!bRandom) {
      calc_pot(fplog,cr,mtop,&inputrec,top,x,fr,&enerd,mdatoms,pot,box,graph);
      if (bPDB || debug) {
	char buf[STRLEN];
	
	if (debug)
	  sprintf(buf,"%d_%s",p_num+n_num,ftp2fn(efPDB,NFILE,fnm));
	else
	  strcpy(buf,ftp2fn(efPDB,NFILE,fnm));
	for(i=0; (i<atoms.nr); i++)
	    atoms.pdbinfo[i].bfac = pot[i]*scale;
	write_sto_conf(buf,"Potential calculated by genion",
		       &atoms,x,v,inputrec.ePBC,box);
	bPDB = FALSE;
      }
    }
    if ((p_num > 0) && (p_num >= n_num))  {
      insert_ion(nsa,&nw,bSet,repl,index,pot,x,&pbc,
		 1,p_q,p_name,mdatoms,rmin,bRandom,&seed);
      p_num--;
    }
    else if (n_num > 0) {
      insert_ion(nsa,&nw,bSet,repl,index,pot,x,&pbc,
		 -1,n_q,n_name,mdatoms,rmin,bRandom,&seed);
      n_num--;
    }
  } while (p_num+n_num > 0);
  fprintf(stderr,"\n");

  if (nw)
    sort_ions(nsa,nw,repl,index,&atoms,x,p_name,n_name);
  
  sfree(atoms.pdbinfo);
  atoms.pdbinfo = NULL;
  write_sto_conf(ftp2fn(efSTO,NFILE,fnm),*mtop->name,&atoms,x,NULL,
		 inputrec.ePBC,box);
  
  thanx(stderr);

  gmx_log_close(fplog);
  
  return 0;
}
Esempio n. 4
0
/* Allocate memory for the inputinfo struct: */
static void create_info(t_inputinfo *info)
{
    snew(info->fac, info->n_entries);
    snew(info->rcoulomb, info->n_entries);
    snew(info->rvdw, info->n_entries);
    snew(info->nkx, info->n_entries);
    snew(info->nky, info->n_entries);
    snew(info->nkz, info->n_entries);
    snew(info->fourier_sp, info->n_entries);
    snew(info->ewald_rtol, info->n_entries);
    snew(info->ewald_beta, info->n_entries);
    snew(info->pme_order, info->n_entries);
    snew(info->fn_out, info->n_entries);
    snew(info->e_dir, info->n_entries);
    snew(info->e_rec, info->n_entries);
}
Esempio n. 5
0
int gmx_potential(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] computes the electrostatical potential across the box. The potential is",
        "calculated by first summing the charges per slice and then integrating",
        "twice of this charge distribution. Periodic boundaries are not taken",
        "into account. Reference of potential is taken to be the left side of",
        "the box. It is also possible to calculate the potential in spherical",
        "coordinates as function of r by calculating a charge distribution in",
        "spherical slices and twice integrating them. epsilon_r is taken as 1,",
        "but 2 is more appropriate in many cases."
    };
    output_env_t       oenv;
    static int         axis       = 2;       /* normal to memb. default z  */
    static const char *axtitle    = "Z";
    static int         nslices    = 10;      /* nr of slices defined       */
    static int         ngrps      = 1;
    static gmx_bool    bSpherical = FALSE;   /* default is bilayer types   */
    static real        fudge_z    = 0;       /* translate coordinates      */
    static gmx_bool    bCorrect   = 0;
    t_pargs            pa []      = {
        {   "-d",   FALSE, etSTR, {&axtitle},
            "Take the normal on the membrane in direction X, Y or Z."
        },
        {   "-sl",  FALSE, etINT, {&nslices},
            "Calculate potential as function of boxlength, dividing the box"
            " in this number of slices."
        },
        {   "-cb",  FALSE, etINT, {&cb},
            "Discard this number of  first slices of box for integration"
        },
        {   "-ce",  FALSE, etINT, {&ce},
            "Discard this number of last slices of box for integration"
        },
        {   "-tz",  FALSE, etREAL, {&fudge_z},
            "Translate all coordinates by this distance in the direction of the box"
        },
        {   "-spherical", FALSE, etBOOL, {&bSpherical},
            "Calculate spherical thingie"
        },
        {   "-ng",       FALSE, etINT, {&ngrps},
            "Number of groups to consider"
        },
        {   "-correct",  FALSE, etBOOL, {&bCorrect},
            "Assume net zero charge of groups to improve accuracy"
        }
    };
    const char        *bugs[] = {
        "Discarding slices for integration should not be necessary."
    };

    double           **potential,              /* potential per slice        */
                     **charge,                                  /* total charge per slice     */
                     **field,                                   /* field per slice            */
                     slWidth;                /* width of one slice         */
    char      **grpname;                       /* groupnames                 */
    int        *ngx;                           /* sizes of groups            */
    t_topology *top;                           /* topology        */
    int         ePBC;
    atom_id   **index;                         /* indices for all groups     */
    t_filenm    fnm[] = {                      /* files for g_order       */
        { efTRX, "-f", NULL,  ffREAD },        /* trajectory file             */
        { efNDX, NULL, NULL,  ffREAD },        /* index file          */
        { efTPX, NULL, NULL,  ffREAD },        /* topology file               */
        { efXVG, "-o", "potential", ffWRITE }, /* xvgr output file    */
        { efXVG, "-oc", "charge", ffWRITE },   /* xvgr output file    */
        { efXVG, "-of", "field", ffWRITE },    /* xvgr output file    */
    };

#define NFILE asize(fnm)

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

    /* Calculate axis */
    axis = toupper(axtitle[0]) - 'X';

    top = read_top(ftp2fn(efTPX, NFILE, fnm), &ePBC); /* read topology file */

    snew(grpname, ngrps);
    snew(index, ngrps);
    snew(ngx, ngrps);

    rd_index(ftp2fn(efNDX, NFILE, fnm), ngrps, ngx, index, grpname);


    calc_potential(ftp2fn(efTRX, NFILE, fnm), index, ngx,
                   &potential, &charge, &field,
                   &nslices, top, ePBC, axis, ngrps, &slWidth, fudge_z,
                   bSpherical, bCorrect, oenv);

    plot_potential(potential, charge, field, opt2fn("-o", NFILE, fnm),
                   opt2fn("-oc", NFILE, fnm), opt2fn("-of", NFILE, fnm),
                   nslices, ngrps, (const char**)grpname, slWidth, oenv);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);  /* view xvgr file */
    do_view(oenv, opt2fn("-oc", NFILE, fnm), NULL); /* view xvgr file */
    do_view(oenv, opt2fn("-of", NFILE, fnm), NULL); /* view xvgr file */

    return 0;
}
Esempio n. 6
0
static void check_solvent(FILE *fp,t_topology *top,t_forcerec *fr,
			  t_mdatoms *md,t_nsborder *nsb)
{
  /* This routine finds out whether a charge group can be used as
   * solvent in the innerloops. The routine should be called once
   * at the beginning of the MD program.
   */
  t_block *cgs,*excl,*mols;
  atom_id *cgid;
  int     i,j,m,j0,j1,nj,k,aj,ak,tjA,tjB,nl_m,nl_n,nl_o;
  int     warncount;
  bool    bOneCG;
  bool    *bAllExcl,bAE,bOrder;
  bool    *bHaveLJ,*bHaveCoul;
  
  cgs  = &(top->blocks[ebCGS]);
  excl = &(top->atoms.excl);
  mols = &(top->blocks[ebMOLS]);

  if (fp)
    fprintf(fp,"Going to determine what solvent types we have.\n");
  snew(fr->solvent_type,cgs->nr+1);
  snew(fr->mno_index,(cgs->nr+1)*3);
  
  /* Generate charge group number for all atoms */
  cgid = make_invblock(cgs,cgs->nra);
  
  warncount=0;

  /* Loop over molecules */
  if (fp)
    fprintf(fp,"There are %d molecules, %d charge groups and %d atoms\n",
	    mols->nr,cgs->nr,cgs->nra);
  for(i=0; (i<mols->nr); i++) {
    /* Set boolean that determines whether the molecules consists of one CG */
    bOneCG = TRUE;
    /* Set some counters */
    j0     = mols->index[i];
    j1     = mols->index[i+1];
    nj     = j1-j0;
    for(j=j0+1; (j<j1); j++) {
      bOneCG = bOneCG && (cgid[mols->a[j]] == cgid[mols->a[j-1]]);
    }
    if (fr->bSolvOpt && bOneCG && nj>1) {
      /* Check whether everything is excluded */
      snew(bAllExcl,nj);
      bAE = TRUE;
      /* Loop over all atoms in molecule */
      for(j=j0; (j<j1) && bAE; j++) {
	/* Set a flag for each atom in the molecule that determines whether
	 * it is excluded or not 
	 */
	for(k=0; (k<nj); k++)
	  bAllExcl[k] = FALSE;
	/* Now check all the exclusions of this atom */
	for(k=excl->index[j]; (k<excl->index[j+1]); k++) {
	  ak = excl->a[k];
	  /* Consistency and range check */
	  if ((ak < j0) || (ak >= j1)) 
	    fatal_error(0,"Exclusion outside molecule? ak = %d, j0 = %d, j1 = 5d, mol is %d",ak,j0,j1,i);
	  bAllExcl[ak-j0] = TRUE;
	}
	/* Now sum up the booleans */
	for(k=0; (k<nj); k++)
	  bAE = bAE && bAllExcl[k];
      }
      if (bAE) {
	snew(bHaveCoul,nj);
	snew(bHaveLJ,nj);
	for(j=j0; (j<j1); j++) {
	  /* Check for coulomb */
	  aj = mols->a[j];
	  bHaveCoul[j-j0] = ( (fabs(top->atoms.atom[aj].q ) > GMX_REAL_MIN) ||
			      (fabs(top->atoms.atom[aj].qB) > GMX_REAL_MIN));
	  /* Check for LJ. */
	  tjA = top->atoms.atom[aj].type;
	  tjB = top->atoms.atom[aj].typeB;
	  bHaveLJ[j-j0] = FALSE;
	  for(k=0; (k<fr->ntype); k++) {
	    if (fr->bBHAM) 
	      bHaveLJ[j-j0] = (bHaveLJ[j-j0] || 
			       (fabs(BHAMA(fr->nbfp,fr->ntype,tjA,k)) > GMX_REAL_MIN) ||
			       (fabs(BHAMB(fr->nbfp,fr->ntype,tjA,k)) > GMX_REAL_MIN) ||
			       (fabs(BHAMC(fr->nbfp,fr->ntype,tjA,k)) > GMX_REAL_MIN) ||
			       (fabs(BHAMA(fr->nbfp,fr->ntype,tjB,k)) > GMX_REAL_MIN) ||
			       (fabs(BHAMB(fr->nbfp,fr->ntype,tjB,k)) > GMX_REAL_MIN) ||
			       (fabs(BHAMC(fr->nbfp,fr->ntype,tjB,k)) > GMX_REAL_MIN));
	    else
	      bHaveLJ[j-j0] = (bHaveLJ[j-j0] || 
			       (fabs(C6(fr->nbfp,fr->ntype,tjA,k))  > GMX_REAL_MIN) ||
			       (fabs(C12(fr->nbfp,fr->ntype,tjA,k)) > GMX_REAL_MIN) ||
			       (fabs(C6(fr->nbfp,fr->ntype,tjB,k))  > GMX_REAL_MIN) ||
			       (fabs(C12(fr->nbfp,fr->ntype,tjB,k)) > GMX_REAL_MIN));
	  }
	}
	/* Now we have determined what particles have which interactions 
	 * In the case of water-like molecules we only check for the number
	 * of particles and the LJ, not for the Coulomb. Let's just assume
	 * that the water loops are faster than the MNO loops anyway. DvdS
	 */
	/* No - there's another problem: To optimize the water
	 * innerloop assumes the charge of the first i atom is constant
	 * qO, and charge on atoms 2/3 is constant qH. /EL
	 */
	/* I won't write any altivec versions of the general solvent inner 
         * loops. Thus, when USE_PPC_ALTIVEC is defined it is faster 
	 * to use the normal loops instead of the MNO solvent version. /EL
	 */
	aj=mols->a[j0];
	if((nj==3) && bHaveCoul[0] && bHaveLJ[0] &&
	   !bHaveLJ[1] && !bHaveLJ[2] &&
	   fabs(top->atoms.atom[aj+1].q - top->atoms.atom[aj+2].q) < GMX_REAL_MIN)
	  fr->solvent_type[cgid[aj]] = esolWATER;
	else {
#ifdef USE_PPC_ALTIVEC
          fr->solvent_type[cgid[aj]] = esolNO;
#else
	  /* Time to compute M & N & O */
	  for(k=0; (k<nj) && (bHaveLJ[k] && bHaveCoul[k]); k++)
	    ;
	  nl_n = k;
	  for(; (k<nj) && (!bHaveLJ[k] && bHaveCoul[k]); k++)
	    ;
	  nl_o = k;
	  for(; (k<nj) && (bHaveLJ[k] && !bHaveCoul[k]); k++)
	    ;
	  nl_m = k;
	  /* Now check whether we're at the end of the pack */
	  bOrder = FALSE;
	  for(; (k<nj); k++)
	    bOrder = bOrder || (bHaveLJ[k] || bHaveCoul[k]);
	  if (bOrder) {
	    /* If we have a solvent molecule with LJC everywhere, then
	     * we shouldn't issue a warning. Only if we suspect something
	     * could be better.
	     */
	    if (nl_n != nj) {
	      warncount++;
	      if(warncount<11 && fp) 
 	        fprintf(fp,"The order in molecule %d could be optimized"
		        " for better performance\n",i);
	      if(warncount==10 && fp)
              fprintf(fp,"(More than 10 molecules where the order can be optimized)\n");
	    }
	    nl_m = nl_n = nl_o = nj;
	  }
	  fr->mno_index[cgid[aj]*3]   = nl_m;
	  fr->mno_index[cgid[aj]*3+1] = nl_n;
	  fr->mno_index[cgid[aj]*3+2] = nl_o;
	  fr->solvent_type[cgid[aj]]  = esolMNO;
#endif /* MNO solvent if not using altivec */
	}

	/* Last check for perturbed atoms */
	for(j=j0; (j<j1); j++)
	  if (md->bPerturbed[mols->a[j]])
	    fr->solvent_type[cgid[mols->a[j0]]] = esolNO;
	
	sfree(bHaveLJ);
	sfree(bHaveCoul);
      }
      else {
	/* Turn off solvent optimization for all cg's in the molecule,
	 * here there is only one.
	 */
	fr->solvent_type[cgid[mols->a[j0]]] = esolNO;
      }
      sfree(bAllExcl);
    }
    else {
      /* Turn off solvent optimization for all cg's in the molecule */
      for(j=mols->index[i]; (j<mols->index[i+1]); j++) {
	fr->solvent_type[cgid[mols->a[j]]] = esolNO;
      }
    }
  }
  if (debug) {
    for(i=0; (i<cgs->nr); i++) 
      fprintf(debug,"MNO: cg = %5d, m = %2d, n = %2d, o = %2d\n",
	      i,fr->mno_index[3*i],fr->mno_index[3*i+1],fr->mno_index[3*i+2]);
  }

  /* Now compute the number of solvent molecules, could be merged with code above */
  fr->nMNOMol = 0;
  fr->nWatMol = 0;
  for(m=0; m<3; m++)
    fr->nMNOav[m] = 0;
  for(i=0; i<mols->nr; i++) {
    j = mols->a[mols->index[i]];
    if (j>=START(nsb) && j<START(nsb)+HOMENR(nsb)) {
	if (fr->solvent_type[cgid[j]] == esolMNO) {
	  fr->nMNOMol++;
	  for(m=0; m<3; m++)
	    fr->nMNOav[m] += fr->mno_index[3*cgid[j]+m];
	}
	else if (fr->solvent_type[cgid[j]] == esolWATER)
	  fr->nWatMol++;
    }
  }
  if (fr->nMNOMol > 0)
    for(m=0; (m<3); m++)
      fr->nMNOav[m] /= fr->nMNOMol;
  
  sfree(cgid);

  if (fp) {
    fprintf(fp,"There are %d optimized solvent molecules on node %d\n",
	    fr->nMNOMol,nsb->nodeid);
    if (fr->nMNOMol > 0)
      fprintf(fp,"  aver. nr. of atoms per molecule: vdwc %.1f coul %.1f vdw %.1f\n",
	      fr->nMNOav[1],fr->nMNOav[2]-fr->nMNOav[1],fr->nMNOav[0]-fr->nMNOav[2]);
    fprintf(fp,"There are %d optimized water molecules on node %d\n",
	    fr->nWatMol,nsb->nodeid);
  }
}
Esempio n. 7
0
int gmx_pme_error(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] estimates the error of the electrostatic forces",
        "if using the sPME algorithm. The flag [TT]-tune[tt] will determine",
        "the splitting parameter such that the error is equally",
        "distributed over the real and reciprocal space part.",
        "The part of the error that stems from self interaction of the particles "
        "is computationally demanding. However, a good a approximation is to",
        "just use a fraction of the particles for this term which can be",
        "indicated by the flag [TT]-self[tt].[PAR]",
    };

    real            fs        = 0.0; /* 0 indicates: not set by the user */
    real            user_beta = -1.0;
    real            fracself  = 1.0;
    t_inputinfo     info;
    t_state         state;     /* The state from the tpr input file */
    gmx_mtop_t      mtop;      /* The topology from the tpr input file */
    t_inputrec     *ir = NULL; /* The inputrec from the tpr file */
    FILE           *fp = NULL;
    t_commrec      *cr;
    unsigned long   PCA_Flags;
    gmx_bool        bTUNE    = FALSE;
    gmx_bool        bVerbose = FALSE;
    int             seed     = 0;


    static t_filenm fnm[] = {
        { efTPR, "-s",     NULL,    ffREAD },
        { efOUT, "-o",    "error",  ffWRITE },
        { efTPR, "-so",   "tuned",  ffOPTWR }
    };

    output_env_t    oenv = NULL;

    t_pargs         pa[] = {
        { "-beta",     FALSE, etREAL, {&user_beta},
          "If positive, overwrite ewald_beta from [TT].tpr[tt] file with this value" },
        { "-tune",     FALSE, etBOOL, {&bTUNE},
          "Tune the splitting parameter such that the error is equally distributed between real and reciprocal space" },
        { "-self",     FALSE, etREAL, {&fracself},
          "If between 0.0 and 1.0, determine self interaction error from just this fraction of the charged particles" },
        { "-seed",     FALSE, etINT,  {&seed},
          "Random number seed used for Monte Carlo algorithm when [TT]-self[tt] is set to a value between 0.0 and 1.0" },
        { "-v",        FALSE, etBOOL, {&bVerbose},
          "Be loud and noisy" }
    };


#define NFILE asize(fnm)

    cr = init_commrec();

    PCA_Flags  = PCA_NOEXIT_ON_ARGS;

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

    if (!bTUNE)
    {
        bTUNE = opt2bSet("-so", NFILE, fnm);
    }

    info.n_entries = 1;

    /* Allocate memory for the inputinfo struct: */
    create_info(&info);
    info.fourier_sp[0] = fs;

    /* Read in the tpr file and open logfile for reading */
    if (MASTER(cr))
    {
        snew(ir, 1);
        read_tpr_file(opt2fn("-s", NFILE, fnm), &info, &state, &mtop, ir, user_beta, fracself);

        fp = fopen(opt2fn("-o", NFILE, fnm), "w");
    }

    /* Check consistency if the user provided fourierspacing */
    if (fs > 0 && MASTER(cr))
    {
        /* Recalculate the grid dimensions using fourierspacing from user input */
        info.nkx[0] = 0;
        info.nky[0] = 0;
        info.nkz[0] = 0;
        calc_grid(stdout, state.box, info.fourier_sp[0], &(info.nkx[0]), &(info.nky[0]), &(info.nkz[0]));
        if ( (ir->nkx != info.nkx[0]) || (ir->nky != info.nky[0]) || (ir->nkz != info.nkz[0]) )
        {
            gmx_fatal(FARGS, "Wrong fourierspacing %f nm, input file grid = %d x %d x %d, computed grid = %d x %d x %d",
                      fs, ir->nkx, ir->nky, ir->nkz, info.nkx[0], info.nky[0], info.nkz[0]);
        }
    }

    /* Estimate (S)PME force error */

    /* Determine the volume of the simulation box */
    if (MASTER(cr))
    {
        info.volume = det(state.box);
        calc_recipbox(state.box, info.recipbox);
        info.natoms = mtop.natoms;
        info.bTUNE  = bTUNE;
    }

    if (PAR(cr))
    {
        bcast_info(&info, cr);
    }

    /* Get an error estimate of the input tpr file and do some tuning if requested */
    estimate_PME_error(&info, &state, &mtop, fp, bVerbose, seed, cr);

    if (MASTER(cr))
    {
        /* Write out optimized tpr file if requested */
        if (opt2bSet("-so", NFILE, fnm) || bTUNE)
        {
            ir->ewald_rtol = info.ewald_rtol[0];
            write_tpx_state(opt2fn("-so", NFILE, fnm), ir, &state, &mtop);
        }
        please_cite(fp, "Wang2010");
        fclose(fp);
    }

    return 0;
}
Esempio n. 8
0
void set_histp(t_atoms *pdba, rvec *x, real angle, real dist)
{
    static const char *prot_acc[] = {
        "O", "OD1", "OD2", "OE1", "OE2", "OG", "OG1", "OH", "OW"
    };
#define NPA asize(prot_acc)
    static const char *prot_don[] = {
        "N", "NH1", "NH2", "NE", "ND1", "ND2", "NE2", "NZ", "OG", "OG1", "OH", "NE1", "OW"
    };
#define NPD asize(prot_don)

    gmx_bool *donor, *acceptor;
    gmx_bool *hbond, bHaveH = FALSE;
    gmx_bool  bHDd, bHEd;
    rvec      xh1, xh2;
    int       natom;
    int       i, j, nd, na, aj, hisind, his0, type = -1;
    int       nd1, ne2, cg, cd2, ce1;
    t_blocka *hb;
    real      d;
    char     *atomnm;

    natom = pdba->nr;

    i = 0;
    while (i < natom &&
           gmx_strcasecmp(*pdba->resinfo[pdba->atom[i].resind].name, "HIS") != 0)
    {
        i++;
    }
    if (natom == i)
    {
        return;
    }

    /* A histidine residue exists that requires automated assignment, so
     * doing the analysis of donors and acceptors is worthwhile. */
    fprintf(stderr,
            "Analysing hydrogen-bonding network for automated assignment of histidine\n"
            " protonation.");

    snew(donor, natom);
    snew(acceptor, natom);
    snew(hbond, natom);
    snew(hb, 1);

    nd = na = 0;
    for (j = 0; (j < natom); j++)
    {
        if (in_strings(*pdba->atomname[j], NPA, prot_acc) != -1)
        {
            acceptor[j] = TRUE;
            na++;
        }
        if (in_strings(*pdba->atomname[j], NPD, prot_don) != -1)
        {
            donor[j] = TRUE;
            nd++;
        }
    }
    fprintf(stderr, " %d donors and %d acceptors were found.\n", nd, na);
    chk_allhb(pdba, x, hb, donor, acceptor, dist);
    if (debug)
    {
        pr_hbonds(debug, hb, pdba);
    }
    fprintf(stderr, "There are %d hydrogen bonds\n", hb->nra);

    /* Now do the HIS stuff */
    hisind = -1;
    while (i < natom)
    {
        if (gmx_strcasecmp(*pdba->resinfo[pdba->atom[i].resind].name, "HIS") != 0)
        {
            i++;
        }
        else
        {
            if (pdba->atom[i].resind != hisind)
            {
                hisind = pdba->atom[i].resind;

                /* Find the  atoms in the ring */
                nd1 = ne2 = cg = cd2 = ce1 = -1;
                while (i < natom && pdba->atom[i].resind == hisind)
                {
                    atomnm = *pdba->atomname[i];
                    if (strcmp(atomnm, "CD2") == 0)
                    {
                        cd2 = i;
                    }
                    else if (strcmp(atomnm, "CG") == 0)
                    {
                        cg  = i;
                    }
                    else if (strcmp(atomnm, "CE1") == 0)
                    {
                        ce1 = i;
                    }
                    else if (strcmp(atomnm, "ND1") == 0)
                    {
                        nd1 = i;
                    }
                    else if (strcmp(atomnm, "NE2") == 0)
                    {
                        ne2 = i;
                    }

                    i++;
                }

                if (!((cg == -1 ) || (cd2 == -1) || (ce1 == -1) ||
                      (nd1 == -1) || (ne2 == -1)))
                {
                    calc_ringh(x[nd1], x[cg], x[ce1], xh1);
                    calc_ringh(x[ne2], x[ce1], x[cd2], xh2);

                    bHDd = chk_hbonds(nd1, pdba, x, acceptor, hbond, xh1, angle, dist);
                    chk_hbonds(nd1, pdba, x, donor, hbond, xh1, angle, dist);
                    bHEd = chk_hbonds(ne2, pdba, x, acceptor, hbond, xh2, angle, dist);
                    chk_hbonds(ne2, pdba, x, donor, hbond, xh2, angle, dist);

                    if (bHDd)
                    {
                        if (bHEd)
                        {
                            type = ehisH;
                        }
                        else
                        {
                            type = ehisA;
                        }
                    }
                    else
                    {
                        type = ehisB;
                    }
                    fprintf(stderr, "Will use %s for residue %d\n",
                            hh[type], pdba->resinfo[hisind].nr);
                }
                else
                {
                    gmx_fatal(FARGS, "Incomplete ring in HIS%d",
                              pdba->resinfo[hisind].nr);
                }

                snew(pdba->resinfo[hisind].rtp, 1);
                *pdba->resinfo[hisind].rtp = strdup(hh[type]);
            }
        }
    }
    done_blocka(hb);
    sfree(hb);
    sfree(donor);
    sfree(acceptor);
    sfree(hbond);
}
Esempio n. 9
0
int gmx_helix(int argc,char *argv[])
{
  const char *desc[] = {
    "g_helix computes all kind of helix properties. First, the peptide",
    "is checked to find the longest helical part. This is determined by",
    "Hydrogen bonds and Phi/Psi angles.",
    "That bit is fitted",
    "to an ideal helix around the Z-axis and centered around the origin.",
    "Then the following properties are computed:[PAR]",
    "[BB]1.[bb] Helix radius (file radius.xvg). This is merely the",
    "RMS deviation in two dimensions for all Calpha atoms.",
    "it is calced as sqrt((SUM i(x^2(i)+y^2(i)))/N), where N is the number",
    "of backbone atoms. For an ideal helix the radius is 0.23 nm[BR]",
    "[BB]2.[bb] Twist (file twist.xvg). The average helical angle per",
    "residue is calculated. For alpha helix it is 100 degrees,",
    "for 3-10 helices it will be smaller,", 
    "for 5-helices it will be larger.[BR]",
    "[BB]3.[bb] Rise per residue (file rise.xvg). The helical rise per", 
    "residue is plotted as the difference in Z-coordinate between Ca", 
    "atoms. For an ideal helix this is 0.15 nm[BR]",
    "[BB]4.[bb] Total helix length (file len-ahx.xvg). The total length", 
    "of the", 
    "helix in nm. This is simply the average rise (see above) times the",  
    "number of helical residues (see below).[BR]",
    "[BB]5.[bb] Number of helical residues (file n-ahx.xvg). The title says",
    "it all.[BR]",
    "[BB]6.[bb] Helix Dipole, backbone only (file dip-ahx.xvg).[BR]",
    "[BB]7.[bb] RMS deviation from ideal helix, calculated for the Calpha",
    "atoms only (file rms-ahx.xvg).[BR]",
    "[BB]8.[bb] Average Calpha-Calpha dihedral angle (file phi-ahx.xvg).[BR]",
    "[BB]9.[bb] Average Phi and Psi angles (file phipsi.xvg).[BR]",
    "[BB]10.[bb] Ellipticity at 222 nm according to [IT]Hirst and Brooks[it]",
    "[PAR]"
  };
  static const char *ppp[efhNR+2] = { 
    NULL, "RAD", "TWIST", "RISE", "LEN", "NHX", "DIP", "RMS", "CPHI", 
    "RMSA", "PHI", "PSI", "HB3", "HB4", "HB5", "CD222", NULL
  };
  static gmx_bool bCheck=FALSE,bFit=TRUE,bDBG=FALSE,bEV=FALSE;
  static int  rStart=0,rEnd=0,r0=1;
  t_pargs pa [] = {
    { "-r0", FALSE, etINT, {&r0},
      "The first residue number in the sequence" },
    { "-q",  FALSE, etBOOL,{&bCheck},
      "Check at every step which part of the sequence is helical" },
    { "-F",  FALSE, etBOOL,{&bFit},
      "Toggle fit to a perfect helix" },
    { "-db", FALSE, etBOOL,{&bDBG},
      "Print debug info" },
    { "-prop", FALSE, etENUM, {ppp},
      "Select property to weight eigenvectors with. WARNING experimental stuff" },
    { "-ev", FALSE, etBOOL,{&bEV},
      "Write a new 'trajectory' file for ED" },
    { "-ahxstart", FALSE, etINT, {&rStart},
      "First residue in helix" },
    { "-ahxend", FALSE, etINT, {&rEnd},
      "Last residue in helix" }
  };

  typedef struct {
    FILE *fp,*fp2;
    gmx_bool bfp2;
    const char *filenm;
    const char *title;
    const char *xaxis;
    const char *yaxis;
    real val;
  } t_xvgrfile;
  
  t_xvgrfile xf[efhNR] = {
    { NULL, NULL, TRUE,  "radius",  "Helix radius",               NULL, "r (nm)" , 0.0 },
    { NULL, NULL, TRUE,  "twist",   "Twist per residue",          NULL, "Angle (deg)", 0.0 },
    { NULL, NULL, TRUE,  "rise",    "Rise per residue",           NULL, "Rise (nm)", 0.0 },
    { NULL, NULL, FALSE, "len-ahx", "Length of the Helix",        NULL, "Length (nm)", 0.0 },
    { NULL, NULL, FALSE, "dip-ahx", "Helix Backbone Dipole",      NULL, "rq (nm e)", 0.0 },
    { NULL, NULL, TRUE,  "rms-ahx", "RMS Deviation from Ideal Helix", NULL, "RMS (nm)", 0.0 },
    { NULL, NULL, FALSE, "rmsa-ahx","Average RMSD per Residue",   "Residue", "RMS (nm)", 0.0 },
    { NULL, NULL,FALSE,  "cd222",   "Ellipticity at 222 nm", NULL, "nm", 0.0 },
    { NULL, NULL, TRUE,  "pprms",   "RMS Distance from \\8a\\4-helix", NULL, "deg" , 0.0 },
    { NULL, NULL, TRUE,  "caphi",   "Average Ca-Ca Dihedral",     NULL, "\\8F\\4(deg)", 0.0 },
    { NULL, NULL, TRUE,  "phi",     "Average \\8F\\4 angles", NULL, "deg" , 0.0 },
    { NULL, NULL, TRUE,  "psi",     "Average \\8Y\\4 angles", NULL, "deg" , 0.0 },
    { NULL, NULL, TRUE,  "hb3",     "Average n-n+3 hbond length", NULL, "nm" , 0.0 },
    { NULL, NULL, TRUE,  "hb4",     "Average n-n+4 hbond length", NULL, "nm" , 0.0 },
    { NULL, NULL, TRUE,  "hb5",     "Average n-n+5 hbond length", NULL, "nm" , 0.0 },
    { NULL, NULL,FALSE,  "JCaHa",   "J-Coupling Values",        "Residue", "Hz" , 0.0 },
    { NULL, NULL,FALSE,  "helicity","Helicity per Residue",     "Residue", "% of time" , 0.0 }
  };
 
  output_env_t oenv;
  FILE       *otrj;
  char       buf[54],prop[256];
  t_trxstatus *status;
  int        natoms,nre,nres;
  t_bb       *bb;
  int        i,j,ai,m,nall,nbb,nca,teller,nSel=0;
  atom_id    *bbindex,*caindex,*allindex;
  t_topology *top;
  int        ePBC;
  rvec       *x,*xref,*xav;
  real       t;
  real       rms,fac;
  matrix     box;
  gmx_rmpbc_t  gpbc=NULL;
  gmx_bool       bRange;
  t_filenm  fnm[] = {
    { efTPX, NULL,  NULL,   ffREAD  },
    { efNDX, NULL,  NULL,   ffREAD  },
    { efTRX, "-f",  NULL,   ffREAD  },
    { efG87, "-to", NULL,   ffOPTWR },
    { efSTO, "-cz", "zconf",ffWRITE },
    { efSTO, "-co", "waver",ffWRITE }
  };
#define NFILE asize(fnm)

  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
  
  bRange=(opt2parg_bSet("-ahxstart",asize(pa),pa) &&
	  opt2parg_bSet("-ahxend",asize(pa),pa));
		        
  top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC);
  
  natoms=read_first_x(oenv,&status,opt2fn("-f",NFILE,fnm),&t,&x,box);

  if (opt2bSet("-to",NFILE,fnm)) {
    otrj=opt2FILE("-to",NFILE,fnm,"w");
    strcpy(prop,ppp[0]);
    fprintf(otrj,"%s Weighted Trajectory: %d atoms, NO box\n",prop,natoms);
  }
  else
    otrj=NULL;
    
  if (natoms != top->atoms.nr)
    gmx_fatal(FARGS,"Sorry can only run when the number of atoms in the run input file (%d) is equal to the number in the trajectory (%d)",
	    top->atoms.nr,natoms);
	    
  bb=mkbbind(ftp2fn(efNDX,NFILE,fnm),&nres,&nbb,r0,&nall,&allindex,
	     top->atoms.atomname,top->atoms.atom,top->atoms.resinfo);
  snew(bbindex,natoms);
  snew(caindex,nres);
  
  fprintf(stderr,"nall=%d\n",nall);
    
  /* Open output files, default x-axis is time */
  for(i=0; (i<efhNR); i++) {
    sprintf(buf,"%s.xvg",xf[i].filenm);
    remove(buf);
    xf[i].fp=xvgropen(buf,xf[i].title,
                      xf[i].xaxis ? xf[i].xaxis : "Time (ps)",
		      xf[i].yaxis,oenv);
    if (xf[i].bfp2) {
      sprintf(buf,"%s.out",xf[i].filenm);
      remove(buf);
      xf[i].fp2=ffopen(buf,"w");
    }
  }

  /* Read reference frame from tpx file to compute helix length */
  snew(xref,top->atoms.nr);
  read_tpx(ftp2fn(efTPX,NFILE,fnm),
	   NULL,NULL,&natoms,xref,NULL,NULL,NULL);
  calc_hxprops(nres,bb,xref,box);
  do_start_end(nres,bb,xref,&nbb,bbindex,&nca,caindex,bRange,rStart,rEnd);
  sfree(xref);
  if (bDBG) {
    fprintf(stderr,"nca=%d, nbb=%d\n",nca,nbb);
    pr_bb(stdout,nres,bb);
  }
  
  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);

  snew(xav,natoms);
  teller=0;
  do {
    if ((teller++ % 10) == 0)
      fprintf(stderr,"\rt=%.2f",t);
    gmx_rmpbc(gpbc,natoms,box,x);

    
    calc_hxprops(nres,bb,x,box);
    if (bCheck)
      do_start_end(nres,bb,x,&nbb,bbindex,&nca,caindex,FALSE,0,0);
    
    if (nca >= 5) {
      rms=fit_ahx(nres,bb,natoms,nall,allindex,x,nca,caindex,box,bFit);
      
      if (teller == 1) {
	write_sto_conf(opt2fn("-cz",NFILE,fnm),"Helix fitted to Z-Axis",
		       &(top->atoms),x,NULL,ePBC,box);
      }
            
      xf[efhRAD].val   = radius(xf[efhRAD].fp2,nca,caindex,x);
      xf[efhTWIST].val = twist(xf[efhTWIST].fp2,nca,caindex,x);
      xf[efhRISE].val  = rise(nca,caindex,x);
      xf[efhLEN].val   = ahx_len(nca,caindex,x,box);
      xf[efhCD222].val = ellipticity(nres,bb);
      xf[efhDIP].val   = dip(nbb,bbindex,x,top->atoms.atom);
      xf[efhRMS].val   = rms;
      xf[efhCPHI].val  = ca_phi(nca,caindex,x,box);
      xf[efhPPRMS].val = pprms(xf[efhPPRMS].fp2,nres,bb);
      
      for(j=0; (j<=efhCPHI); j++)
	fprintf(xf[j].fp,   "%10g  %10g\n",t,xf[j].val);
      
      av_phipsi(xf[efhPHI].fp,xf[efhPSI].fp,xf[efhPHI].fp2,xf[efhPSI].fp2,
		t,nres,bb);
      av_hblen(xf[efhHB3].fp,xf[efhHB3].fp2,
	       xf[efhHB4].fp,xf[efhHB4].fp2,
	       xf[efhHB5].fp,xf[efhHB5].fp2,
	       t,nres,bb);
      
      if (otrj) 
	dump_otrj(otrj,nall,allindex,x,xf[nSel].val,xav);
    }
  } while (read_next_x(oenv,status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  gmx_rmpbc_done(gpbc);

  close_trj(status);

  if (otrj) {
    ffclose(otrj);
    fac=1.0/teller;
    for(i=0; (i<nall); i++) {
      ai=allindex[i];
      for(m=0; (m<DIM); m++)
	xav[ai][m]*=fac;
    }
    write_sto_conf_indexed(opt2fn("-co",NFILE,fnm),
			   "Weighted and Averaged conformation",
			   &(top->atoms),xav,NULL,ePBC,box,nall,allindex);
  }
  
  for(i=0; (i<nres); i++) {
    if (bb[i].nrms > 0) {
      fprintf(xf[efhRMSA].fp,"%10d  %10g\n",r0+i,bb[i].rmsa/bb[i].nrms);
    }
    fprintf(xf[efhAHX].fp,"%10d  %10g\n",r0+i,(bb[i].nhx*100.0)/(real )teller);
    fprintf(xf[efhJCA].fp,"%10d  %10g\n",
	    r0+i,140.3+(bb[i].jcaha/(double)teller));
  }
  
  for(i=0; (i<efhNR); i++) {
    ffclose(xf[i].fp);
    if (xf[i].bfp2)
      ffclose(xf[i].fp2);
    do_view(oenv,xf[i].filenm,"-nxy");
  }
  
  thanx(stderr);
  
  return 0;
}
Esempio n. 10
0
static int scan_ene_files(char **fnms, int nfiles,
                          real *readtime, real *timestep, int *nremax)
{
    /* Check number of energy terms and start time of all files */
    int          f, nre, nremin = 0, nresav = 0;
    ener_file_t  in;
    real         t1, t2;
    char         inputstring[STRLEN];
    gmx_enxnm_t *enm;
    t_enxframe  *fr;

    snew(fr, 1);

    for (f = 0; f < nfiles; f++)
    {
        in  = open_enx(fnms[f], "r");
        enm = NULL;
        do_enxnms(in, &nre, &enm);

        if (f == 0)
        {
            nresav  = nre;
            nremin  = nre;
            *nremax = nre;
            do_enx(in, fr);
            t1 = fr->t;
            do_enx(in, fr);
            t2          = fr->t;
            *timestep   = t2-t1;
            readtime[f] = t1;
            close_enx(in);
        }
        else
        {
            nremin  = std::min(nremin, fr->nre);
            *nremax = std::max(*nremax, fr->nre);
            if (nre != nresav)
            {
                fprintf(stderr,
                        "Energy files don't match, different number of energies:\n"
                        " %s: %d\n %s: %d\n", fnms[f-1], nresav, fnms[f], fr->nre);
                fprintf(stderr,
                        "\nContinue conversion using only the first %d terms (n/y)?\n"
                        "(you should be sure that the energy terms match)\n", nremin);
                if (NULL == fgets(inputstring, STRLEN-1, stdin))
                {
                    gmx_fatal(FARGS, "Error reading user input");
                }
                if (inputstring[0] != 'y' && inputstring[0] != 'Y')
                {
                    fprintf(stderr, "Will not convert\n");
                    exit(0);
                }
                nresav = fr->nre;
            }
            do_enx(in, fr);
            readtime[f] = fr->t;
            close_enx(in);
        }
        fprintf(stderr, "\n");
        free_enxnms(nre, enm);
    }

    free_enxframe(fr);
    sfree(fr);

    return nremin;
}
Esempio n. 11
0
int gmx_eneconv(int argc, char *argv[])
{
    const char       *desc[] = {
        "With [IT]multiple files[it] specified for the [TT]-f[tt] option:[PAR]",
        "Concatenates several energy files in sorted order.",
        "In the case of double time frames, the one",
        "in the later file is used. By specifying [TT]-settime[tt] you will be",
        "asked for the start time of each file. The input files are taken",
        "from the command line,",
        "such that the command [TT]gmx eneconv -f *.edr -o fixed.edr[tt] should do",
        "the trick. [PAR]",
        "With [IT]one file[it] specified for [TT]-f[tt]:[PAR]",
        "Reads one energy file and writes another, applying the [TT]-dt[tt],",
        "[TT]-offset[tt], [TT]-t0[tt] and [TT]-settime[tt] options and",
        "converting to a different format if necessary (indicated by file",
        "extentions).[PAR]",
        "[TT]-settime[tt] is applied first, then [TT]-dt[tt]/[TT]-offset[tt]",
        "followed by [TT]-b[tt] and [TT]-e[tt] to select which frames to write."
    };
    const char       *bugs[] = {
        "When combining trajectories the sigma and E^2 (necessary for statistics) are not updated correctly. Only the actual energy is correct. One thus has to compute statistics in another way."
    };
    ener_file_t       in  = NULL, out = NULL;
    gmx_enxnm_t      *enm = NULL;
#if 0
    ener_file_t       in, out = NULL;
    gmx_enxnm_t      *enm = NULL;
#endif
    t_enxframe       *fr, *fro;
    gmx_int64_t       ee_sum_step = 0, ee_sum_nsteps, ee_sum_nsum;
    t_energy         *ee_sum;
    gmx_int64_t       lastfilestep, laststep, startstep_file = 0;
    int               noutfr;
    int               nre, nremax, this_nre, nfile, f, i, kkk, nset, *set = NULL;
    double            last_t;
    char            **fnms;
    real             *readtime, *settime, timestep, tadjust;
    char              buf[22], buf2[22];
    int              *cont_type;
    gmx_bool          bNewFile, bFirst, bNewOutput;
    gmx_output_env_t *oenv;
    gmx_bool          warned_about_dh = FALSE;
    t_enxblock       *blocks          = NULL;
    int               nblocks         = 0;
    int               nblocks_alloc   = 0;

    t_filenm          fnm[] = {
        { efEDR, "-f", NULL,    ffRDMULT },
        { efEDR, "-o", "fixed", ffWRITE  },
    };

#define NFILE asize(fnm)
    gmx_bool         bWrite;
    static real      delta_t   = 0.0, toffset = 0, scalefac = 1;
    static gmx_bool  bSetTime  = FALSE;
    static gmx_bool  bSort     = TRUE, bError = TRUE;
    static real      begin     = -1;
    static real      end       = -1;
    gmx_bool         remove_dh = FALSE;

    t_pargs          pa[] = {
        { "-b",        FALSE, etREAL, {&begin},
          "First time to use"},
        { "-e",        FALSE, etREAL, {&end},
          "Last time to use"},
        { "-dt",       FALSE, etREAL, {&delta_t},
          "Only write out frame when t MOD dt = offset" },
        { "-offset",   FALSE, etREAL, {&toffset},
          "Time offset for [TT]-dt[tt] option" },
        { "-settime",  FALSE, etBOOL, {&bSetTime},
          "Change starting time interactively" },
        { "-sort",     FALSE, etBOOL, {&bSort},
          "Sort energy files (not frames)"},
        { "-rmdh",     FALSE, etBOOL, {&remove_dh},
          "Remove free energy block data" },
        { "-scalefac", FALSE, etREAL, {&scalefac},
          "Multiply energy component by this factor" },
        { "-error",    FALSE, etBOOL, {&bError},
          "Stop on errors in the file" }
    };

    if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa),
                           pa, asize(desc), desc, asize(bugs), bugs, &oenv))
    {
        return 0;
    }
    tadjust  = 0;
    nremax   = 0;
    nset     = 0;
    timestep = 0.0;
    snew(fnms, argc);
    lastfilestep = 0;
    laststep     = 0;

    nfile = opt2fns(&fnms, "-f", NFILE, fnm);

    if (!nfile)
    {
        gmx_fatal(FARGS, "No input files!");
    }

    snew(settime, nfile+1);
    snew(readtime, nfile+1);
    snew(cont_type, nfile+1);

    nre = scan_ene_files(fnms, nfile, readtime, &timestep, &nremax);
    edit_files(fnms, nfile, readtime, settime, cont_type, bSetTime, bSort);

    ee_sum_nsteps = 0;
    ee_sum_nsum   = 0;
    snew(ee_sum, nremax);

    snew(fr, 1);
    snew(fro, 1);
    fro->t   = -1e20;
    fro->nre = nre;
    snew(fro->ener, nremax);

    noutfr = 0;
    bFirst = TRUE;

    last_t = fro->t;
    for (f = 0; f < nfile; f++)
    {
        bNewFile   = TRUE;
        bNewOutput = TRUE;
        in         = open_enx(fnms[f], "r");
        enm        = NULL;
        do_enxnms(in, &this_nre, &enm);
        if (f == 0)
        {
            if (scalefac != 1)
            {
                set = select_it(nre, enm, &nset);
            }

            /* write names to the output file */
            out = open_enx(opt2fn("-o", NFILE, fnm), "w");
            do_enxnms(out, &nre, &enm);
        }

        /* start reading from the next file */
        while ((fro->t <= (settime[f+1] + GMX_REAL_EPS)) &&
               do_enx(in, fr))
        {
            if (bNewFile)
            {
                startstep_file = fr->step;
                tadjust        = settime[f] - fr->t;
                if (cont_type[f+1] == TIME_LAST)
                {
                    settime[f+1]   = readtime[f+1]-readtime[f]+settime[f];
                    cont_type[f+1] = TIME_EXPLICIT;
                }
                bNewFile = FALSE;
            }

            if (tadjust + fr->t <= last_t)
            {
                /* Skip this frame, since we already have it / past it */
                if (debug)
                {
                    fprintf(debug, "fr->step %s, fr->t %.4f\n",
                            gmx_step_str(fr->step, buf), fr->t);
                    fprintf(debug, "tadjust %12.6e + fr->t %12.6e <= t %12.6e\n",
                            tadjust, fr->t, last_t);
                }
                continue;
            }

            fro->step = lastfilestep + fr->step - startstep_file;
            fro->t    = tadjust  + fr->t;

            bWrite = ((begin < 0 || (begin >= 0 && (fro->t >= begin-GMX_REAL_EPS))) &&
                      (end  < 0 || (end  >= 0 && (fro->t <= end  +GMX_REAL_EPS))) &&
                      (fro->t <= settime[f+1]+0.5*timestep));

            if (debug)
            {
                fprintf(debug,
                        "fr->step %s, fr->t %.4f, fro->step %s fro->t %.4f, w %d\n",
                        gmx_step_str(fr->step, buf), fr->t,
                        gmx_step_str(fro->step, buf2), fro->t, bWrite);
            }

            if (bError)
            {
                if ((end > 0) && (fro->t > end+GMX_REAL_EPS))
                {
                    f = nfile;
                    break;
                }
            }

            if (fro->t >= begin-GMX_REAL_EPS)
            {
                if (bFirst)
                {
                    bFirst    = FALSE;
                }
                if (bWrite)
                {
                    update_ee_sum(nre, &ee_sum_step, &ee_sum_nsteps, &ee_sum_nsum, ee_sum,
                                  fr, fro->step);
                }
            }

            /* determine if we should write it */
            if (bWrite && (delta_t == 0 || bRmod(fro->t, toffset, delta_t)))
            {
                laststep = fro->step;
                last_t   = fro->t;
                if (bNewOutput)
                {
                    bNewOutput = FALSE;
                    fprintf(stderr, "\nContinue writing frames from t=%g, step=%s\n",
                            fro->t, gmx_step_str(fro->step, buf));
                }

                /* Copy the energies */
                for (i = 0; i < nre; i++)
                {
                    fro->ener[i].e = fr->ener[i].e;
                }

                fro->nsteps = ee_sum_nsteps;
                fro->dt     = fr->dt;

                if (ee_sum_nsum <= 1)
                {
                    fro->nsum = 0;
                }
                else
                {
                    fro->nsum = gmx_int64_to_int(ee_sum_nsum,
                                                 "energy average summation");
                    /* Copy the energy sums */
                    for (i = 0; i < nre; i++)
                    {
                        fro->ener[i].esum = ee_sum[i].esum;
                        fro->ener[i].eav  = ee_sum[i].eav;
                    }
                }
                /* We wrote the energies, so reset the counts */
                ee_sum_nsteps = 0;
                ee_sum_nsum   = 0;

                if (scalefac != 1)
                {
                    for (kkk = 0; kkk < nset; kkk++)
                    {
                        fro->ener[set[kkk]].e    *= scalefac;
                        if (fro->nsum > 0)
                        {
                            fro->ener[set[kkk]].eav  *= scalefac*scalefac;
                            fro->ener[set[kkk]].esum *= scalefac;
                        }
                    }
                }
                /* Copy restraint stuff */
                /*fro->ndisre       = fr->ndisre;
                   fro->disre_rm3tav = fr->disre_rm3tav;
                   fro->disre_rt     = fr->disre_rt;*/
                fro->nblock       = fr->nblock;
                /*fro->nr           = fr->nr;*/
                fro->block        = fr->block;

                /* check if we have blocks with delta_h data and are throwing
                   away data */
                if (fro->nblock > 0)
                {
                    if (remove_dh)
                    {
                        int i;
                        if (!blocks || nblocks_alloc < fr->nblock)
                        {
                            /* we pre-allocate the blocks */
                            nblocks_alloc = fr->nblock;
                            snew(blocks, nblocks_alloc);
                        }
                        nblocks = 0; /* number of blocks so far */

                        for (i = 0; i < fr->nblock; i++)
                        {
                            if ( (fr->block[i].id != enxDHCOLL) &&
                                 (fr->block[i].id != enxDH) &&
                                 (fr->block[i].id != enxDHHIST) )
                            {
                                /* copy everything verbatim */
                                blocks[nblocks] = fr->block[i];
                                nblocks++;
                            }
                        }
                        /* now set the block pointer to the new blocks */
                        fro->nblock = nblocks;
                        fro->block  = blocks;
                    }
                    else if (delta_t > 0)
                    {
                        if (!warned_about_dh)
                        {
                            for (i = 0; i < fr->nblock; i++)
                            {
                                if (fr->block[i].id == enxDH ||
                                    fr->block[i].id == enxDHHIST)
                                {
                                    int size;
                                    if (fr->block[i].id == enxDH)
                                    {
                                        size = fr->block[i].sub[2].nr;
                                    }
                                    else
                                    {
                                        size = fr->nsteps;
                                    }
                                    if (size > 0)
                                    {
                                        printf("\nWARNING: %s contains delta H blocks or histograms for which\n"
                                               "         some data is thrown away on a block-by-block basis, where each block\n"
                                               "         contains up to %d samples.\n"
                                               "         This is almost certainly not what you want.\n"
                                               "         Use the -rmdh option to throw all delta H samples away.\n"
                                               "         Use g_energy -odh option to extract these samples.\n",
                                               fnms[f], size);
                                        warned_about_dh = TRUE;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }

                do_enx(out, fro);
                if (noutfr % 1000 == 0)
                {
                    fprintf(stderr, "Writing frame time %g    ", fro->t);
                }
                noutfr++;
            }
        }
        if (f == nfile)
        {
            f--;
        }
        printf("\nLast step written from %s: t %g, step %s\n",
               fnms[f], last_t, gmx_step_str(laststep, buf));
        lastfilestep = laststep;

        /* set the next time from the last in previous file */
        if (cont_type[f+1] == TIME_CONTINUE)
        {
            settime[f+1] = fro->t;
            /* in this case we have already written the last frame of
             * previous file, so update begin to avoid doubling it
             * with the start of the next file
             */
            begin = fro->t+0.5*timestep;
            /* cont_type[f+1]==TIME_EXPLICIT; */
        }

        if ((fro->t < end) && (f < nfile-1) &&
            (fro->t < settime[f+1]-1.5*timestep))
        {
            fprintf(stderr,
                    "\nWARNING: There might be a gap around t=%g\n", fro->t);
        }

        /* move energies to lastee */
        close_enx(in);
        free_enxnms(this_nre, enm);

        fprintf(stderr, "\n");
    }
    if (noutfr == 0)
    {
        fprintf(stderr, "No frames written.\n");
    }
    else
    {
        fprintf(stderr, "Last frame written was at step %s, time %f\n",
                gmx_step_str(fro->step, buf), fro->t);
        fprintf(stderr, "Wrote %d frames\n", noutfr);
    }

    return 0;
}
int gmx_convert_tpr(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] can edit run input files in four ways.[PAR]",
        "[BB]1.[bb] by modifying the number of steps in a run input file",
        "with options [TT]-extend[tt], [TT]-until[tt] or [TT]-nsteps[tt]",
        "(nsteps=-1 means unlimited number of steps)[PAR]",
        "[BB]2.[bb] (OBSOLETE) by creating a run input file",
        "for a continuation run when your simulation has crashed due to e.g.",
        "a full disk, or by making a continuation run input file.",
        "This option is obsolete, since mdrun now writes and reads",
        "checkpoint files.",
        "[BB]Note[bb] that a frame with coordinates and velocities is needed.",
        "When pressure and/or Nose-Hoover temperature coupling is used",
        "an energy file can be supplied to get an exact continuation",
        "of the original run.[PAR]",
        "[BB]3.[bb] by creating a [TT].tpx[tt] file for a subset of your original",
        "tpx file, which is useful when you want to remove the solvent from",
        "your [TT].tpx[tt] file, or when you want to make e.g. a pure C[GRK]alpha[grk] [TT].tpx[tt] file.",
        "Note that you may need to use [TT]-nsteps -1[tt] (or similar) to get",
        "this to work.",
        "[BB]WARNING: this [TT].tpx[tt] file is not fully functional[bb].[PAR]",
        "[BB]4.[bb] by setting the charges of a specified group",
        "to zero. This is useful when doing free energy estimates",
        "using the LIE (Linear Interaction Energy) method."
    };

    const char       *top_fn, *frame_fn;
    t_fileio         *fp;
    ener_file_t       fp_ener = NULL;
    t_trnheader       head;
    int               i;
    gmx_int64_t       nsteps_req, run_step, frame;
    double            run_t, state_t;
    gmx_bool          bOK, bNsteps, bExtend, bUntil, bTime, bTraj;
    gmx_bool          bFrame, bUse, bSel, bNeedEner, bReadEner, bScanEner, bFepState;
    gmx_mtop_t        mtop;
    t_atoms           atoms;
    t_inputrec       *ir, *irnew = NULL;
    t_gromppopts     *gopts;
    t_state           state;
    rvec             *newx = NULL, *newv = NULL, *tmpx, *tmpv;
    matrix            newbox;
    int               gnx;
    char             *grpname;
    atom_id          *index = NULL;
    int               nre;
    gmx_enxnm_t      *enm     = NULL;
    t_enxframe       *fr_ener = NULL;
    char              buf[200], buf2[200];
    output_env_t      oenv;
    t_filenm          fnm[] = {
        { efTPX, NULL,  NULL,    ffREAD  },
        { efTRN, "-f",  NULL,    ffOPTRD },
        { efEDR, "-e",  NULL,    ffOPTRD },
        { efNDX, NULL,  NULL,    ffOPTRD },
        { efTPX, "-o",  "tpxout", ffWRITE }
    };
#define NFILE asize(fnm)

    /* Command line options */
    static int      nsteps_req_int = 0;
    static real     start_t        = -1.0, extend_t = 0.0, until_t = 0.0;
    static int      init_fep_state = 0;
    static gmx_bool bContinuation  = TRUE, bZeroQ = FALSE, bVel = TRUE;
    static t_pargs  pa[]           = {
        { "-extend",        FALSE, etREAL, {&extend_t},
          "Extend runtime by this amount (ps)" },
        { "-until",         FALSE, etREAL, {&until_t},
          "Extend runtime until this ending time (ps)" },
        { "-nsteps",        FALSE, etINT,  {&nsteps_req_int},
          "Change the number of steps" },
        { "-time",          FALSE, etREAL, {&start_t},
          "Continue from frame at this time (ps) instead of the last frame" },
        { "-zeroq",         FALSE, etBOOL, {&bZeroQ},
          "Set the charges of a group (from the index) to zero" },
        { "-vel",           FALSE, etBOOL, {&bVel},
          "Require velocities from trajectory" },
        { "-cont",          FALSE, etBOOL, {&bContinuation},
          "For exact continuation, the constraints should not be applied before the first step" },
        { "-init_fep_state", FALSE, etINT, {&init_fep_state},
          "fep state to initialize from" },
    };
    int             nerror = 0;

    /* Parse the command line */
    if (!parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa,
                           asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    /* Convert int to gmx_int64_t */
    nsteps_req = nsteps_req_int;
    bNsteps    = opt2parg_bSet("-nsteps", asize(pa), pa);
    bExtend    = opt2parg_bSet("-extend", asize(pa), pa);
    bUntil     = opt2parg_bSet("-until", asize(pa), pa);
    bFepState  = opt2parg_bSet("-init_fep_state", asize(pa), pa);
    bTime      = opt2parg_bSet("-time", asize(pa), pa);
    bTraj      = (opt2bSet("-f", NFILE, fnm) || bTime);

    top_fn = ftp2fn(efTPX, NFILE, fnm);
    fprintf(stderr, "Reading toplogy and stuff from %s\n", top_fn);

    snew(ir, 1);
    read_tpx_state(top_fn, ir, &state, NULL, &mtop);
    run_step = ir->init_step;
    run_t    = ir->init_step*ir->delta_t + ir->init_t;

    if (!EI_STATE_VELOCITY(ir->eI))
    {
        bVel = FALSE;
    }

    if (bTraj)
    {
        fprintf(stderr, "\n"
                "NOTE: Reading the state from trajectory is an obsolete feature of gmx convert-tpr.\n"
                "      Continuation should be done by loading a checkpoint file with mdrun -cpi\n"
                "      This guarantees that all state variables are transferred.\n"
                "      gmx convert-tpr is now only useful for increasing nsteps,\n"
                "      but even that can often be avoided by using mdrun -maxh\n"
                "\n");

        if (ir->bContinuation != bContinuation)
        {
            fprintf(stderr, "Modifying ir->bContinuation to %s\n",
                    bool_names[bContinuation]);
        }
        ir->bContinuation = bContinuation;


        bNeedEner = (ir->epc == epcPARRINELLORAHMAN || ir->etc == etcNOSEHOOVER);
        bReadEner = (bNeedEner && ftp2bSet(efEDR, NFILE, fnm));
        bScanEner = (bReadEner && !bTime);

        if (ir->epc != epcNO || EI_SD(ir->eI) || ir->eI == eiBD)
        {
            fprintf(stderr, "NOTE: The simulation uses pressure coupling and/or stochastic dynamics.\n"
                    "gmx convert-tpr can not provide binary identical continuation.\n"
                    "If you want that, supply a checkpoint file to mdrun\n\n");
        }

        if (EI_SD(ir->eI) || ir->eI == eiBD)
        {
            fprintf(stderr, "\nChanging ld-seed from %"GMX_PRId64 " ", ir->ld_seed);
            ir->ld_seed = (gmx_int64_t)gmx_rng_make_seed();
            fprintf(stderr, "to %"GMX_PRId64 "\n\n", ir->ld_seed);
        }

        frame_fn = ftp2fn(efTRN, NFILE, fnm);

        if (fn2ftp(frame_fn) == efCPT)
        {
            int sim_part;

            fprintf(stderr,
                    "\nREADING STATE FROM CHECKPOINT %s...\n\n",
                    frame_fn);

            read_checkpoint_state(frame_fn, &sim_part,
                                  &run_step, &run_t, &state);
        }
        else
        {
            fprintf(stderr,
                    "\nREADING COORDS, VELS AND BOX FROM TRAJECTORY %s...\n\n",
                    frame_fn);

            fp = open_trn(frame_fn, "r");
            if (bScanEner)
            {
                fp_ener = open_enx(ftp2fn(efEDR, NFILE, fnm), "r");
                do_enxnms(fp_ener, &nre, &enm);
                snew(fr_ener, 1);
                fr_ener->t = -1e-12;
            }

            /* Now scan until the last set of x and v (step == 0)
             * or the ones at step step.
             */
            bFrame = TRUE;
            frame  = 0;
            while (bFrame)
            {
                bFrame = fread_trnheader(fp, &head, &bOK);
                if (bOK && frame == 0)
                {
                    if (mtop.natoms != head.natoms)
                    {
                        gmx_fatal(FARGS, "Number of atoms in Topology (%d) "
                                  "is not the same as in Trajectory (%d)\n",
                                  mtop.natoms, head.natoms);
                    }
                    snew(newx, head.natoms);
                    snew(newv, head.natoms);
                }
                bFrame = bFrame && bOK;
                if (bFrame)
                {
                    bOK = fread_htrn(fp, &head, newbox, newx, newv, NULL);
                }
                bFrame = bFrame && bOK;
                bUse   = FALSE;
                if (bFrame &&
                    (head.x_size) && (head.v_size || !bVel))
                {
                    bUse = TRUE;
                    if (bScanEner)
                    {
                        /* Read until the energy time is >= the trajectory time */
                        while (fr_ener->t < head.t && do_enx(fp_ener, fr_ener))
                        {
                            ;
                        }
                        bUse = (fr_ener->t == head.t);
                    }
                    if (bUse)
                    {
                        tmpx                  = newx;
                        newx                  = state.x;
                        state.x               = tmpx;
                        tmpv                  = newv;
                        newv                  = state.v;
                        state.v               = tmpv;
                        run_t                 = head.t;
                        run_step              = head.step;
                        state.fep_state       = head.fep_state;
                        state.lambda[efptFEP] = head.lambda;
                        copy_mat(newbox, state.box);
                    }
                }
                if (bFrame || !bOK)
                {
                    sprintf(buf, "\r%s %s frame %s%s: step %s%s time %s",
                            "%s", "%s", "%6", GMX_PRId64, "%6", GMX_PRId64, " %8.3f");
                    fprintf(stderr, buf,
                            bUse ? "Read   " : "Skipped", ftp2ext(fn2ftp(frame_fn)),
                            frame, head.step, head.t);
                    frame++;
                    if (bTime && (head.t >= start_t))
                    {
                        bFrame = FALSE;
                    }
                }
            }
            if (bScanEner)
            {
                close_enx(fp_ener);
                free_enxframe(fr_ener);
                free_enxnms(nre, enm);
            }
            close_trn(fp);
            fprintf(stderr, "\n");

            if (!bOK)
            {
                fprintf(stderr, "%s frame %s (step %s, time %g) is incomplete\n",
                        ftp2ext(fn2ftp(frame_fn)), gmx_step_str(frame-1, buf2),
                        gmx_step_str(head.step, buf), head.t);
            }
            fprintf(stderr, "\nUsing frame of step %s time %g\n",
                    gmx_step_str(run_step, buf), run_t);

            if (bNeedEner)
            {
                if (bReadEner)
                {
                    get_enx_state(ftp2fn(efEDR, NFILE, fnm), run_t, &mtop.groups, ir, &state);
                }
                else
                {
                    fprintf(stderr, "\nWARNING: The simulation uses %s temperature and/or %s pressure coupling,\n"
                            "         the continuation will only be exact when an energy file is supplied\n\n",
                            ETCOUPLTYPE(etcNOSEHOOVER),
                            EPCOUPLTYPE(epcPARRINELLORAHMAN));
                }
            }
            if (bFepState)
            {
                ir->fepvals->init_fep_state = init_fep_state;
            }
        }
    }

    if (bNsteps)
    {
        fprintf(stderr, "Setting nsteps to %s\n", gmx_step_str(nsteps_req, buf));
        ir->nsteps = nsteps_req;
    }
    else
    {
        /* Determine total number of steps remaining */
        if (bExtend)
        {
            ir->nsteps = ir->nsteps - (run_step - ir->init_step) + (gmx_int64_t)(extend_t/ir->delta_t + 0.5);
            printf("Extending remaining runtime of by %g ps (now %s steps)\n",
                   extend_t, gmx_step_str(ir->nsteps, buf));
        }
        else if (bUntil)
        {
            printf("nsteps = %s, run_step = %s, current_t = %g, until = %g\n",
                   gmx_step_str(ir->nsteps, buf),
                   gmx_step_str(run_step, buf2),
                   run_t, until_t);
            ir->nsteps = (gmx_int64_t)((until_t - run_t)/ir->delta_t + 0.5);
            printf("Extending remaining runtime until %g ps (now %s steps)\n",
                   until_t, gmx_step_str(ir->nsteps, buf));
        }
        else
        {
            ir->nsteps -= run_step - ir->init_step;
            /* Print message */
            printf("%s steps (%g ps) remaining from first run.\n",
                   gmx_step_str(ir->nsteps, buf), ir->nsteps*ir->delta_t);
        }
    }

    if (bNsteps || bZeroQ || (ir->nsteps > 0))
    {
        ir->init_step = run_step;

        if (ftp2bSet(efNDX, NFILE, fnm) ||
            !(bNsteps || bExtend || bUntil || bTraj))
        {
            atoms = gmx_mtop_global_atoms(&mtop);
            get_index(&atoms, ftp2fn_null(efNDX, NFILE, fnm), 1,
                      &gnx, &index, &grpname);
            if (!bZeroQ)
            {
                bSel = (gnx != state.natoms);
                for (i = 0; ((i < gnx) && (!bSel)); i++)
                {
                    bSel = (i != index[i]);
                }
            }
            else
            {
                bSel = FALSE;
            }
            if (bSel)
            {
                fprintf(stderr, "Will write subset %s of original tpx containing %d "
                        "atoms\n", grpname, gnx);
                reduce_topology_x(gnx, index, &mtop, state.x, state.v);
                state.natoms = gnx;
            }
            else if (bZeroQ)
            {
                zeroq(index, &mtop);
                fprintf(stderr, "Zero-ing charges for group %s\n", grpname);
            }
            else
            {
                fprintf(stderr, "Will write full tpx file (no selection)\n");
            }
        }

        state_t = ir->init_t + ir->init_step*ir->delta_t;
        sprintf(buf,   "Writing statusfile with starting step %s%s and length %s%s steps...\n", "%10", GMX_PRId64, "%10", GMX_PRId64);
        fprintf(stderr, buf, ir->init_step, ir->nsteps);
        fprintf(stderr, "                                 time %10.3f and length %10.3f ps\n",
                state_t, ir->nsteps*ir->delta_t);
        write_tpx_state(opt2fn("-o", NFILE, fnm), ir, &state, &mtop);
    }
    else
    {
        printf("You've simulated long enough. Not writing tpr file\n");
    }

    return 0;
}
Esempio n. 13
0
static game_params *dup_params(game_params *params)
{
    game_params *ret = snew(game_params);
    *ret = *params; /* struct copy */
    return ret;
}
Esempio n. 14
0
static int strip_dssp(char *dsspfile, int nres,
                      gmx_bool bPhobres[], real t,
                      real *acc, FILE *fTArea,
                      t_matrix *mat, int average_area[],
                      const output_env_t oenv)
{
    static gmx_bool bFirst = TRUE;
    static char    *ssbuf;
    FILE           *tapeout;
    static int      xsize, frame;
    char            buf[STRLEN+1];
    char            SSTP;
    int             i, nr, iacc, nresidues;
    int             naccf, naccb; /* Count hydrophobic and hydrophilic residues */
    real            iaccf, iaccb;
    t_xpmelmt       c;

    tapeout = gmx_ffopen(dsspfile, "r");

    /* Skip header */
    do
    {
        fgets2(buf, STRLEN, tapeout);
    }
    while (strstr(buf, "KAPPA") == NULL);
    if (bFirst)
    {
        /* Since we also have empty lines in the dssp output (temp) file,
         * and some line content is saved to the ssbuf variable,
         * we need more memory than just nres elements. To be shure,
         * we allocate 2*nres-1, since for each chain there is a
         * separating line in the temp file. (At most each residue
         * could have been defined as a separate chain.) */
        snew(ssbuf, 2*nres-1);
    }

    iaccb     = iaccf = 0;
    nresidues = 0;
    naccf     = 0;
    naccb     = 0;
    for (nr = 0; (fgets2(buf, STRLEN, tapeout) != NULL); nr++)
    {
        if (buf[13] == '!') /* Chain separator line has '!' at pos. 13 */
        {
            SSTP = '=';     /* Chain separator sign '=' */
        }
        else
        {
            SSTP = buf[16] == ' ' ? '~' : buf[16];
        }
        ssbuf[nr] = SSTP;

        buf[39] = '\0';

        /* Only calculate solvent accessible area if needed */
        if ((NULL != acc) && (buf[13] != '!'))
        {
            sscanf(&(buf[34]), "%d", &iacc);
            acc[nr] = iacc;
            /* average_area and bPhobres are counted from 0...nres-1 */
            average_area[nresidues] += iacc;
            if (bPhobres[nresidues])
            {
                naccb++;
                iaccb += iacc;
            }
            else
            {
                naccf++;
                iaccf += iacc;
            }
            /* Keep track of the residue number (do not count chain separator lines '!') */
            nresidues++;
        }
    }
    ssbuf[nr] = '\0';

    if (bFirst)
    {
        if (0 != acc)
        {
            fprintf(stderr, "%d residues were classified as hydrophobic and %d as hydrophilic.\n", naccb, naccf);
        }

        sprintf(mat->title, "Secondary structure");
        mat->legend[0] = 0;
        sprintf(mat->label_x, "%s", output_env_get_time_label(oenv));
        sprintf(mat->label_y, "Residue");
        mat->bDiscrete = TRUE;
        mat->ny        = nr;
        snew(mat->axis_y, nr);
        for (i = 0; i < nr; i++)
        {
            mat->axis_y[i] = i+1;
        }
        mat->axis_x = NULL;
        mat->matrix = NULL;
        xsize       = 0;
        frame       = 0;
        bFirst      = FALSE;
    }
    if (frame >= xsize)
    {
        xsize += 10;
        srenew(mat->axis_x, xsize);
        srenew(mat->matrix, xsize);
    }
    mat->axis_x[frame] = t;
    snew(mat->matrix[frame], nr);
    c.c2 = 0;
    for (i = 0; i < nr; i++)
    {
        c.c1                  = ssbuf[i];
        mat->matrix[frame][i] = max(0, searchcmap(mat->nmap, mat->map, c));
    }
    frame++;
    mat->nx = frame;

    if (fTArea)
    {
        fprintf(fTArea, "%10g  %10g  %10g\n", t, 0.01*iaccb, 0.01*iaccf);
    }
    gmx_ffclose(tapeout);

    /* Return the number of lines found in the dssp file (i.e. number
     * of redidues plus chain separator lines).
     * This is the number of y elements needed for the area xpm file */
    return nr;
}
Esempio n. 15
0
static void do_sham(const char *fn, const char *ndx,
                    const char *xpmP, const char *xpm, const char *xpm2,
                    const char *xpm3, const char *xpm4, const char *pdb,
                    const char *logf,
                    int n, int neig, real **eig,
                    gmx_bool bGE, int nenerT, real **enerT,
                    int nmap, real *mapindex, real **map,
                    real Tref,
                    real pmax, real gmax,
                    real *emin, real *emax, int nlevels, real pmin,
                    const char *mname, gmx_bool bSham, int *idim, int *ibox,
                    gmx_bool bXmin, real *xmin, gmx_bool bXmax, real *xmax)
{
    FILE        *fp;
    real        *min_eig, *max_eig;
    real        *axis_x, *axis_y, *axis_z, *axis = NULL;
    double      *P;
    real       **PP, *W, *E, **WW, **EE, *S, **SS, *M, **MM, *bE;
    rvec         xxx;
    char        *buf;
    double      *bfac, efac, bref, Pmax, Wmin, Wmax, Winf, Emin, Emax, Einf, Smin, Smax, Sinf, Mmin, Mmax, Minf;
    real        *delta;
    int          i, j, k, imin, len, index, d, *nbin, *bindex, bi;
    int         *nxyz, maxbox;
    t_blocka    *b;
    gmx_bool     bOutside;
    unsigned int flags;
    t_rgb        rlo  = { 0, 0, 0 };
    t_rgb        rhi  = { 1, 1, 1 };

    /* Determine extremes for the eigenvectors */
    snew(min_eig, neig);
    snew(max_eig, neig);
    snew(nxyz, neig);
    snew(bfac, neig);
    snew(delta, neig);

    for (i = 0; (i < neig); i++)
    {
        /* Check for input constraints */
        min_eig[i] = max_eig[i] = eig[i][0];
        for (j = 0; (j < n); j++)
        {
            min_eig[i] = min(min_eig[i], eig[i][j]);
            max_eig[i] = max(max_eig[i], eig[i][j]);
            delta[i]   = (max_eig[i]-min_eig[i])/(2.0*ibox[i]);
        }
        /* Add some extra space, half a bin on each side, unless the
         * user has set the limits.
         */
        if (bXmax)
        {
            if (max_eig[i] > xmax[i])
            {
                gmx_warning("Your xmax[%d] value %f is smaller than the largest data point %f", i, xmax[i], max_eig[i]);
            }
            max_eig[i] = xmax[i];
        }
        else
        {
            max_eig[i] += delta[i];
        }

        if (bXmin)
        {
            if (min_eig[i] < xmin[i])
            {
                gmx_warning("Your xmin[%d] value %f is larger than the smallest data point %f", i, xmin[i], min_eig[i]);
            }
            min_eig[i] = xmin[i];
        }
        else
        {
            min_eig[i] -= delta[i];
        }
        bfac[i]     = ibox[i]/(max_eig[i]-min_eig[i]);
    }
    /* Do the binning */
    bref = 1/(BOLTZ*Tref);
    snew(bE, n);
    if (bGE || nenerT == 2)
    {
        Emin = 1e8;
        for (j = 0; (j < n); j++)
        {
            if (bGE)
            {
                bE[j] = bref*enerT[0][j];
            }
            else
            {
                bE[j] = (bref - 1/(BOLTZ*enerT[1][j]))*enerT[0][j];
            }
            Emin  = min(Emin, bE[j]);
        }
    }
    else
    {
        Emin = 0;
    }
    len = 1;
    for (i = 0; (i < neig); i++)
    {
        len = len*ibox[i];
    }
    printf("There are %d bins in the %d-dimensional histogram. Beta-Emin = %g\n",
           len, neig, Emin);
    snew(P, len);
    snew(W, len);
    snew(E, len);
    snew(S, len);
    snew(M, len);
    snew(nbin, len);
    snew(bindex, n);


    /* Loop over projections */
    for (j = 0; (j < n); j++)
    {
        /* Loop over dimensions */
        bOutside = FALSE;
        for (i = 0; (i < neig); i++)
        {
            nxyz[i] = bfac[i]*(eig[i][j]-min_eig[i]);
            if (nxyz[i] < 0 || nxyz[i] >= ibox[i])
            {
                bOutside = TRUE;
            }
        }
        if (!bOutside)
        {
            index = indexn(neig, ibox, nxyz);
            range_check(index, 0, len);
            /* Compute the exponential factor */
            if (enerT)
            {
                efac = exp(-bE[j]+Emin);
            }
            else
            {
                efac = 1;
            }
            /* Apply the bin volume correction for a multi-dimensional distance */
            for (i = 0; i < neig; i++)
            {
                if (idim[i] == 2)
                {
                    efac /= eig[i][j];
                }
                else if (idim[i] == 3)
                {
                    efac /= sqr(eig[i][j]);
                }
                else if (idim[i] == -1)
                {
                    efac /= sin(DEG2RAD*eig[i][j]);
                }
            }
            /* Update the probability */
            P[index] += efac;
            /* Update the energy */
            if (enerT)
            {
                E[index] += enerT[0][j];
            }
            /* Statistics: which "structure" in which bin */
            nbin[index]++;
            bindex[j] = index;
        }
    }
    /* Normalize probability */
    normalize_p_e(len, P, nbin, E, pmin);
    Pmax = 0;
    /* Compute boundaries for the Free energy */
    Wmin = 1e8;
    imin = -1;
    Wmax = -1e8;
    /* Recompute Emin: it may have changed due to averaging */
    Emin = 1e8;
    Emax = -1e8;
    for (i = 0; (i < len); i++)
    {
        if (P[i] != 0)
        {
            Pmax = max(P[i], Pmax);
            W[i] = -BOLTZ*Tref*log(P[i]);
            if (W[i] < Wmin)
            {
                Wmin = W[i];
                imin = i;
            }
            Emin = min(E[i], Emin);
            Emax = max(E[i], Emax);
            Wmax = max(W[i], Wmax);
        }
    }
    if (pmax > 0)
    {
        Pmax = pmax;
    }
    if (gmax > 0)
    {
        Wmax = gmax;
    }
    else
    {
        Wmax -= Wmin;
    }
    Winf = Wmax+1;
    Einf = Emax+1;
    Smin = Emin-Wmax;
    Smax = Emax-Smin;
    Sinf = Smax+1;
    /* Write out the free energy as a function of bin index */
    fp = ffopen(fn, "w");
    for (i = 0; (i < len); i++)
    {
        if (P[i] != 0)
        {
            W[i] -= Wmin;
            S[i]  = E[i]-W[i]-Smin;
            fprintf(fp, "%5d  %10.5e  %10.5e  %10.5e\n", i, W[i], E[i], S[i]);
        }
        else
        {
            W[i] = Winf;
            E[i] = Einf;
            S[i] = Sinf;
        }
    }
    ffclose(fp);
    /* Organize the structures in the bins */
    snew(b, 1);
    snew(b->index, len+1);
    snew(b->a, n);
    b->index[0] = 0;
    for (i = 0; (i < len); i++)
    {
        b->index[i+1] = b->index[i]+nbin[i];
        nbin[i]       = 0;
    }
    for (i = 0; (i < n); i++)
    {
        bi = bindex[i];
        b->a[b->index[bi]+nbin[bi]] = i;
        nbin[bi]++;
    }
    /* Consistency check */
    /* This no longer applies when we allow the plot to be smaller
       than the sampled space.
       for(i=0; (i<len); i++) {
       if (nbin[i] != (b->index[i+1] - b->index[i]))
        gmx_fatal(FARGS,"nbin[%d] = %d, should be %d",i,nbin[i],
          b->index[i+1] - b->index[i]);
       }
     */
    /* Write the index file */
    fp = ffopen(ndx, "w");
    for (i = 0; (i < len); i++)
    {
        if (nbin[i] > 0)
        {
            fprintf(fp, "[ %d ]\n", i);
            for (j = b->index[i]; (j < b->index[i+1]); j++)
            {
                fprintf(fp, "%d\n", b->a[j]+1);
            }
        }
    }
    ffclose(fp);
    snew(axis_x, ibox[0]+1);
    snew(axis_y, ibox[1]+1);
    snew(axis_z, ibox[2]+1);
    maxbox = max(ibox[0], max(ibox[1], ibox[2]));
    snew(PP, maxbox*maxbox);
    snew(WW, maxbox*maxbox);
    snew(EE, maxbox*maxbox);
    snew(SS, maxbox*maxbox);
    for (i = 0; (i < min(neig, 3)); i++)
    {
        switch (i)
        {
            case 0: axis = axis_x; break;
            case 1: axis = axis_y; break;
            case 2: axis = axis_z; break;
            default: break;
        }
        for (j = 0; j <= ibox[i]; j++)
        {
            axis[j] = min_eig[i] + j/bfac[i];
        }
    }
    if (map)
    {
        snew(M, len);
        snew(MM, maxbox*maxbox);
        for (i = 0; (i < ibox[0]); i++)
        {
            MM[i] = &(M[i*ibox[1]]);
        }
        Mmin = 1e8;
        Mmax = -1e8;
        for (i = 0; (i < nmap); i++)
        {
            Mmin = min(Mmin, map[0][i]);
            Mmax = max(Mmax, map[0][i]);
        }
        Minf = Mmax*1.05;
        for (i = 0; (i < len); i++)
        {
            M[i] = Minf;
        }
        for (i = 0; (i < nmap); i++)
        {
            index = gmx_nint(mapindex[i]);
            if (index >= len)
            {
                gmx_fatal(FARGS, "Number of bins in file from -mdata option does not correspond to current analysis");
            }

            if (P[index] != 0)
            {
                M[index] = map[0][i];
            }
        }
    }
    else
    {
        MM   = NULL;
        Minf = NOTSET;
    }
    pick_minima(logf, ibox, neig, len, W);
    if (gmax <= 0)
    {
        gmax = Winf;
    }
    flags = MAT_SPATIAL_X | MAT_SPATIAL_Y;
    if (neig == 2)
    {
        /* Dump to XPM file */
        snew(PP, ibox[0]);
        for (i = 0; (i < ibox[0]); i++)
        {
            snew(PP[i], ibox[1]);
            for (j = 0; j < ibox[1]; j++)
            {
                PP[i][j] = P[i*ibox[1]+j];
            }
            WW[i] = &(W[i*ibox[1]]);
            EE[i] = &(E[i*ibox[1]]);
            SS[i] = &(S[i*ibox[1]]);
        }
        fp = ffopen(xpmP, "w");
        write_xpm(fp, flags, "Probability Distribution", "", "PC1", "PC2",
                  ibox[0], ibox[1], axis_x, axis_y, PP, 0, Pmax, rlo, rhi, &nlevels);
        ffclose(fp);
        fp = ffopen(xpm, "w");
        write_xpm(fp, flags, "Gibbs Energy Landscape", "G (kJ/mol)", "PC1", "PC2",
                  ibox[0], ibox[1], axis_x, axis_y, WW, 0, gmax, rlo, rhi, &nlevels);
        ffclose(fp);
        fp = ffopen(xpm2, "w");
        write_xpm(fp, flags, "Enthalpy Landscape", "H (kJ/mol)", "PC1", "PC2",
                  ibox[0], ibox[1], axis_x, axis_y, EE,
                  emin ? *emin : Emin, emax ? *emax : Einf, rlo, rhi, &nlevels);
        ffclose(fp);
        fp = ffopen(xpm3, "w");
        write_xpm(fp, flags, "Entropy Landscape", "TDS (kJ/mol)", "PC1", "PC2",
                  ibox[0], ibox[1], axis_x, axis_y, SS, 0, Sinf, rlo, rhi, &nlevels);
        ffclose(fp);
        if (map)
        {
            fp = ffopen(xpm4, "w");
            write_xpm(fp, flags, "Custom Landscape", mname, "PC1", "PC2",
                      ibox[0], ibox[1], axis_x, axis_y, MM, 0, Minf, rlo, rhi, &nlevels);
            ffclose(fp);
        }
    }
    else if (neig == 3)
    {
        /* Dump to PDB file */
        fp = ffopen(pdb, "w");
        for (i = 0; (i < ibox[0]); i++)
        {
            xxx[XX] = 3*(i+0.5-ibox[0]/2);
            for (j = 0; (j < ibox[1]); j++)
            {
                xxx[YY] = 3*(j+0.5-ibox[1]/2);
                for (k = 0; (k < ibox[2]); k++)
                {
                    xxx[ZZ] = 3*(k+0.5-ibox[2]/2);
                    index   = index3(ibox, i, j, k);
                    if (P[index] > 0)
                    {
                        fprintf(fp, "%-6s%5u  %-4.4s%3.3s  %4d    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
                                "ATOM", (index+1) %10000, "H", "H", (index+1)%10000,
                                xxx[XX], xxx[YY], xxx[ZZ], 1.0, W[index]);
                    }
                }
            }
        }
        ffclose(fp);
        write_xplor("out.xplor", W, ibox, min_eig, max_eig);
        if (map)
        {
            write_xplor("user.xplor", M, ibox, min_eig, max_eig);
        }
        nxyz[XX] = imin/(ibox[1]*ibox[2]);
        nxyz[YY] = (imin-nxyz[XX]*ibox[1]*ibox[2])/ibox[2];
        nxyz[ZZ] = imin % ibox[2];
        for (i = 0; (i < ibox[0]); i++)
        {
            snew(WW[i], maxbox);
            for (j = 0; (j < ibox[1]); j++)
            {
                WW[i][j] = W[index3(ibox, i, j, nxyz[ZZ])];
            }
        }
        snew(buf, strlen(xpm)+4);
        sprintf(buf, "%s", xpm);
        sprintf(&buf[strlen(xpm)-4], "12.xpm");
        fp = ffopen(buf, "w");
        write_xpm(fp, flags, "Gibbs Energy Landscape", "W (kJ/mol)", "PC1", "PC2",
                  ibox[0], ibox[1], axis_x, axis_y, WW, 0, gmax, rlo, rhi, &nlevels);
        ffclose(fp);
        for (i = 0; (i < ibox[0]); i++)
        {
            for (j = 0; (j < ibox[2]); j++)
            {
                WW[i][j] = W[index3(ibox, i, nxyz[YY], j)];
            }
        }
        sprintf(&buf[strlen(xpm)-4], "13.xpm");
        fp = ffopen(buf, "w");
        write_xpm(fp, flags, "SHAM Energy Landscape", "kJ/mol", "PC1", "PC3",
                  ibox[0], ibox[2], axis_x, axis_z, WW, 0, gmax, rlo, rhi, &nlevels);
        ffclose(fp);
        for (i = 0; (i < ibox[1]); i++)
        {
            for (j = 0; (j < ibox[2]); j++)
            {
                WW[i][j] = W[index3(ibox, nxyz[XX], i, j)];
            }
        }
        sprintf(&buf[strlen(xpm)-4], "23.xpm");
        fp = ffopen(buf, "w");
        write_xpm(fp, flags, "SHAM Energy Landscape", "kJ/mol", "PC2", "PC3",
                  ibox[1], ibox[2], axis_y, axis_z, WW, 0, gmax, rlo, rhi, &nlevels);
        ffclose(fp);
        sfree(buf);
    }
    if (map)
    {
        sfree(MM);
        sfree(M);
    }
}
Esempio n. 16
0
int main(int argc,char *argv[])
{
  static char *desc[] = {
    "The [TT]pmetest[tt] program tests the scaling of the PME code. When only given",
    "a [TT].tpr[tt] file it will compute PME for one frame. When given a trajectory",
    "it will do so for all the frames in the trajectory. Before the PME",
    "routine is called the coordinates are sorted along the X-axis.[PAR]",
    "As an extra service to the public the program can also compute",
    "long-range Coulomb energies for components of the system. When the",
    "[TT]-groups[tt] flag is given to the program the energy groups",
    "from the [TT].tpr[tt] file will be read, and half an energy matrix computed."
  };
  t_commrec    *cr,*mcr;
  static t_filenm fnm[] = {
    { efTPX, NULL,      NULL,       ffREAD  },
    { efTRN, "-o",      NULL,       ffWRITE },
    { efLOG, "-g",      "pme",      ffWRITE },
    { efTRX, "-f",      NULL,       ffOPTRD },
    { efXVG, "-x",      "ener-pme", ffWRITE }
  };
#define NFILE asize(fnm)

  /* Command line options ! */
  static gmx_bool bVerbose=FALSE;
  static gmx_bool bOptFFT=FALSE;
  static gmx_bool bSort=FALSE;
  static int  ewald_geometry=eewg3D;
  static int  nnodes=1;
  static int  pme_order=0;
  static rvec grid = { -1, -1, -1 };
  static real rc   = 0.0;
  static real dtol = 0.0;
  static gmx_bool bGroups = FALSE;
  static t_pargs pa[] = {
    { "-np",      FALSE, etINT, {&nnodes},
      "Number of nodes, must be the same as used for [TT]grompp[tt]" },
    { "-v",       FALSE, etBOOL,{&bVerbose},  
      "Be loud and noisy" },
    { "-sort",    FALSE, etBOOL,{&bSort},  
      "Sort coordinates. Crucial for domain decomposition." },
    { "-grid",    FALSE, etRVEC,{&grid},
      "Number of grid cells in X, Y, Z dimension (if -1 use from [TT].tpr[tt])" },
    { "-order",   FALSE, etINT, {&pme_order},
      "Order of the PME spreading algorithm" },
    { "-groups",  FALSE, etBOOL, {&bGroups},
      "Compute half an energy matrix based on the energy groups in your [TT].tpr[tt] file" },
    { "-rc",      FALSE, etREAL, {&rc},
      "Rcoulomb for Ewald summation" },
    { "-tol",     FALSE, etREAL, {&dtol},
      "Tolerance for Ewald summation" }
  };
  FILE        *fp;
  t_inputrec  *ir;
  t_topology  top;
  t_tpxheader tpx;
  t_nrnb      nrnb;
  t_nsborder  *nsb;
  t_forcerec  *fr;
  t_mdatoms   *mdatoms;
  char        title[STRLEN];
  int         natoms,step,status,i,ncg,root;
  real        t,lambda,ewaldcoeff,qtot;
  rvec        *x,*f,*xbuf;
  int         *index;
  gmx_bool        bCont;
  real        *charge,*qbuf,*qqbuf;
  matrix      box;
  
  /* Start the actual parallel code if necessary */
  cr   = init_par(&argc,&argv);
  root = 0;
  
  if (MASTER(cr)) 
    CopyRight(stderr,argv[0]);
  
  /* Parse command line on all processors, arguments are passed on in 
   * init_par (see above)
   */
  parse_common_args(&argc,argv,
		    PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_BE_NICE |
		    PCA_CAN_SET_DEFFNM | (MASTER(cr) ? 0 : PCA_QUIET),
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL);
  
#ifndef GMX_MPI
  if (nnodes > 1) 
    gmx_fatal(FARGS,"GROMACS compiled without MPI support - can't do parallel runs");
#endif

  /* Open log files on all processors */
  open_log(ftp2fn(efLOG,NFILE,fnm),cr);
  snew(ir,1);
  
  if (MASTER(cr)) {
    /* Read tpr file etc. */
    read_tpxheader(ftp2fn(efTPX,NFILE,fnm),&tpx,FALSE,NULL,NULL);
    snew(x,tpx.natoms);
    read_tpx(ftp2fn(efTPX,NFILE,fnm),&step,&t,&lambda,ir,
	     box,&natoms,x,NULL,NULL,&top);
    /* Charges */
    qtot = 0;
    snew(charge,natoms);
    for(i=0; (i<natoms); i++) {
      charge[i] = top.atoms.atom[i].q;
      qtot += charge[i];
    }
  
    /* Grid stuff */
    if (opt2parg_bSet("-grid",asize(pa),pa)) {
      ir->nkx = grid[XX];
      ir->nky = grid[YY];
      ir->nkz = grid[ZZ];
    }
    /* Check command line parameters for consistency */
    if ((ir->nkx <= 0) || (ir->nky <= 0) || (ir->nkz <= 0))
      gmx_fatal(FARGS,"PME grid = %d %d %d",ir->nkx,ir->nky,ir->nkz);
    if (opt2parg_bSet("-rc",asize(pa),pa)) 
      ir->rcoulomb = rc;
    if (ir->rcoulomb <= 0)
      gmx_fatal(FARGS,"rcoulomb should be > 0 (not %f)",ir->rcoulomb);
    if (opt2parg_bSet("-order",asize(pa),pa)) 
      ir->pme_order = pme_order;
    if (ir->pme_order <= 0)
      gmx_fatal(FARGS,"pme_order should be > 0 (not %d)",ir->pme_order);
    if (opt2parg_bSet("-tol",asize(pa),pa))
      ir->ewald_rtol = dtol;
    if (ir->ewald_rtol <= 0)
      gmx_fatal(FARGS,"ewald_tol should be > 0 (not %f)",ir->ewald_rtol);
  }
  else {
    init_top(&top);
  }

  /* Add parallellization code here */
  snew(nsb,1);
  if (MASTER(cr)) {
    ncg = top.blocks[ebCGS].multinr[0];
    for(i=0; (i<cr->nnodes-1); i++)
      top.blocks[ebCGS].multinr[i] = min(ncg,(ncg*(i+1))/cr->nnodes);
    for( ; (i<MAXNODES); i++)
      top.blocks[ebCGS].multinr[i] = ncg;
  }
  if (PAR(cr)) {
    /* Set some variables to zero to avoid core dumps */
    ir->opts.ngtc = ir->opts.ngacc = ir->opts.ngfrz = ir->opts.ngener = 0;
#ifdef GMX_MPI
    /* Distribute the data over processors */
    MPI_Bcast(&natoms,1,MPI_INT,root,MPI_COMM_WORLD);
    MPI_Bcast(ir,sizeof(*ir),MPI_BYTE,root,MPI_COMM_WORLD);
    MPI_Bcast(&qtot,1,GMX_MPI_REAL,root,MPI_COMM_WORLD);
#endif

    /* Call some dedicated communication routines, master sends n-1 times */
    if (MASTER(cr)) {
      for(i=1; (i<cr->nnodes); i++) {
	mv_block(i,&(top.blocks[ebCGS]));
	mv_block(i,&(top.atoms.excl));
      }
    }
    else {
      ld_block(root,&(top.blocks[ebCGS]));
      ld_block(root,&(top.atoms.excl));
    }
    if (!MASTER(cr)) {
      snew(charge,natoms);
      snew(x,natoms);
    }
#ifdef GMX_MPI
    MPI_Bcast(charge,natoms,GMX_MPI_REAL,root,MPI_COMM_WORLD);
#endif
  }
  ewaldcoeff = calc_ewaldcoeff(ir->rcoulomb,ir->ewald_rtol);
  
  
  if (bVerbose)
    pr_inputrec(stdlog,0,"Inputrec",ir);

  /* Allocate memory for temp arrays etc. */
  snew(xbuf,natoms);
  snew(f,natoms);
  snew(qbuf,natoms);
  snew(qqbuf,natoms);
  snew(index,natoms);

  /* Initialize the PME code */  
  init_pme(stdlog,cr,ir->nkx,ir->nky,ir->nkz,ir->pme_order,
	   natoms,FALSE,bOptFFT,ewald_geometry);
	   
  /* MFlops accounting */
  init_nrnb(&nrnb);
  
  /* Initialize the work division */
  calc_nsb(stdlog,&(top.blocks[ebCGS]),cr->nnodes,nsb,0);
  nsb->nodeid = cr->nodeid;
  print_nsb(stdlog,"pmetest",nsb);  

  /* Initiate forcerec */
  mdatoms = atoms2md(stdlog,&top.atoms,ir->opts.nFreeze,ir->eI,
		     ir->delta_t,0,ir->opts.tau_t,FALSE,FALSE);
  snew(fr,1);
  init_forcerec(stdlog,fr,ir,&top,cr,mdatoms,nsb,box,FALSE,NULL,NULL,FALSE);
  
  /* First do PME based on coordinates in tpr file, send them to
   * other processors if needed.
   */
  if (MASTER(cr))
    fprintf(stdlog,"-----\n"
	    "Results based on tpr file %s\n",ftp2fn(efTPX,NFILE,fnm));
#ifdef GMX_MPI
  if (PAR(cr)) {
    MPI_Bcast(x[0],natoms*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD);
    MPI_Bcast(box[0],DIM*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD);
    MPI_Bcast(&t,1,GMX_MPI_REAL,root,MPI_COMM_WORLD);
  }
#endif
  do_my_pme(stdlog,0,bVerbose,ir,x,xbuf,f,charge,qbuf,qqbuf,box,bSort,
	    cr,nsb,&nrnb,&(top.atoms.excl),qtot,fr,index,NULL,
	    bGroups ? ir->opts.ngener : 1,mdatoms->cENER);

  /* If we have a trajectry file, we will read the frames in it and compute
   * the PME energy.
   */
  if (ftp2bSet(efTRX,NFILE,fnm)) {
    fprintf(stdlog,"-----\n"
	    "Results based on trx file %s\n",ftp2fn(efTRX,NFILE,fnm));
    if (MASTER(cr)) {
      sfree(x);
      natoms = read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); 
      if (natoms != top.atoms.nr)
	gmx_fatal(FARGS,"natoms in trx = %d, in tpr = %d",natoms,top.atoms.nr);
      fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),"PME Energy","Time (ps)","E (kJ/mol)");
    }
    else
      fp = NULL;
    do {
      /* Send coordinates, box and time to the other nodes */
#ifdef GMX_MPI
      if (PAR(cr)) {
	MPI_Bcast(x[0],natoms*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD);
	MPI_Bcast(box[0],DIM*DIM,GMX_MPI_REAL,root,MPI_COMM_WORLD);
	MPI_Bcast(&t,1,GMX_MPI_REAL,root,MPI_COMM_WORLD);
      }
#endif
      rm_pbc(&top.idef,nsb->natoms,box,x,x);
      /* Call the PME wrapper function */
      do_my_pme(stdlog,t,bVerbose,ir,x,xbuf,f,charge,qbuf,qqbuf,box,bSort,cr,
		nsb,&nrnb,&(top.atoms.excl),qtot,fr,index,fp,
		bGroups ? ir->opts.ngener : 1,mdatoms->cENER);
      /* Only the master processor reads more data */
      if (MASTER(cr))
          bCont = read_next_x(status,&t,natoms,x,box);
      /* Check whether we need to continue */
#ifdef GMX_MPI
      if (PAR(cr))
          MPI_Bcast(&bCont,1,MPI_INT,root,MPI_COMM_WORLD);
#endif
      
    } while (bCont);
    
    /* Finish I/O, close files */
    if (MASTER(cr)) {
      close_trx(status);
      ffclose(fp);
    }
  }
  
  if (bVerbose) {
    /* Do some final I/O about performance, might be useful in debugging */
    fprintf(stdlog,"-----\n");
    print_nrnb(stdlog,&nrnb);
  }
  
  /* Finish the parallel stuff */  
  if (gmx_parallel_env_initialized())
    gmx_finalize(cr);

  /* Thank the audience, as usual */
  if (MASTER(cr)) 
    gmx_thanx(stderr);

  return 0;
}
Esempio n. 17
0
int gmx_sham(int argc, char *argv[])
{
    const char        *desc[] = {
        "[TT]g_sham[tt] makes multi-dimensional free-energy, enthalpy and entropy plots.",
        "[TT]g_sham[tt] reads one or more [TT].xvg[tt] files and analyzes data sets.",
        "The basic purpose of [TT]g_sham[tt] is to plot Gibbs free energy landscapes",
        "(option [TT]-ls[tt])",
        "by Bolzmann inverting multi-dimensional histograms (option [TT]-lp[tt]),",
        "but it can also",
        "make enthalpy (option [TT]-lsh[tt]) and entropy (option [TT]-lss[tt])",
        "plots. The histograms can be made for any quantities the user supplies.",
        "A line in the input file may start with a time",
        "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.",
        "Multiple sets can also be",
        "read when they are separated by & (option [TT]-n[tt]),",
        "in this case only one [IT]y[it]-value is read from each line.",
        "All lines starting with # and @ are skipped.",
        "[PAR]",
        "Option [TT]-ge[tt] can be used to supply a file with free energies",
        "when the ensemble is not a Boltzmann ensemble, but needs to be biased",
        "by this free energy. One free energy value is required for each",
        "(multi-dimensional) data point in the [TT]-f[tt] input.",
        "[PAR]",
        "Option [TT]-ene[tt] can be used to supply a file with energies.",
        "These energies are used as a weighting function in the single",
        "histogram analysis method by Kumar et al. When temperatures",
        "are supplied (as a second column in the file), an experimental",
        "weighting scheme is applied. In addition the vales",
        "are used for making enthalpy and entropy plots.",
        "[PAR]",
        "With option [TT]-dim[tt], dimensions can be gives for distances.",
        "When a distance is 2- or 3-dimensional, the circumference or surface",
        "sampled by two particles increases with increasing distance.",
        "Depending on what one would like to show, one can choose to correct",
        "the histogram and free-energy for this volume effect.",
        "The probability is normalized by r and r^2 for dimensions of 2 and 3, ",
        "respectively.",
        "A value of -1 is used to indicate an angle in degrees between two",
        "vectors: a sin(angle) normalization will be applied.",
        "[BB]Note[bb] that for angles between vectors the inner-product or cosine",
        "is the natural quantity to use, as it will produce bins of the same",
        "volume."
    };
    static real        tb        = -1, te = -1, frac = 0.5, filtlen = 0, binwidth = 0.1;
    static gmx_bool    bHaveT    = TRUE, bDer = FALSE, bSubAv = TRUE, bAverCorr = FALSE, bXYdy = FALSE;
    static gmx_bool    bEESEF    = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE;
    static gmx_bool    bShamEner = TRUE, bSham = TRUE;
    static real        Tref      = 298.15, pmin = 0, ttol = 0, pmax = 0, gmax = 0, emin = 0, emax = 0;
    static rvec        nrdim     = {1, 1, 1};
    static rvec        nrbox     = {32, 32, 32};
    static rvec        xmin      = {0, 0, 0}, xmax = {1, 1, 1};
    static int         nsets_in  = 1, nb_min = 4, resol = 10, nlevels = 25;
    static const char *mname     = "";
    t_pargs            pa[]      = {
        { "-time",    FALSE, etBOOL, {&bHaveT},
          "Expect a time in the input" },
        { "-b",       FALSE, etREAL, {&tb},
          "First time to read from set" },
        { "-e",       FALSE, etREAL, {&te},
          "Last time to read from set" },
        { "-ttol",     FALSE, etREAL, {&ttol},
          "Tolerance on time in appropriate units (usually ps)" },
        { "-n",       FALSE, etINT, {&nsets_in},
          "Read this number of sets separated by lines containing only an ampersand" },
        { "-d",       FALSE, etBOOL, {&bDer},
          "Use the derivative" },
        { "-bw",      FALSE, etREAL, {&binwidth},
          "Binwidth for the distribution" },
        { "-sham",    FALSE, etBOOL, {&bSham},
          "Turn off energy weighting even if energies are given" },
        { "-tsham",   FALSE, etREAL, {&Tref},
          "Temperature for single histogram analysis" },
        { "-pmin",    FALSE, etREAL, {&pmin},
          "Minimum probability. Anything lower than this will be set to zero" },
        { "-dim",     FALSE, etRVEC, {nrdim},
          "Dimensions for distances, used for volume correction (max 3 values, dimensions > 3 will get the same value as the last)" },
        { "-ngrid",   FALSE, etRVEC, {nrbox},
          "Number of bins for energy landscapes (max 3 values, dimensions > 3 will get the same value as the last)" },
        { "-xmin",    FALSE, etRVEC, {xmin},
          "Minimum for the axes in energy landscape (see above for > 3 dimensions)" },
        { "-xmax",    FALSE, etRVEC, {xmax},
          "Maximum for the axes in energy landscape (see above for > 3 dimensions)" },
        { "-pmax",    FALSE, etREAL, {&pmax},
          "Maximum probability in output, default is calculate" },
        { "-gmax",    FALSE, etREAL, {&gmax},
          "Maximum free energy in output, default is calculate" },
        { "-emin",    FALSE, etREAL, {&emin},
          "Minimum enthalpy in output, default is calculate" },
        { "-emax",    FALSE, etREAL, {&emax},
          "Maximum enthalpy in output, default is calculate" },
        { "-nlevels", FALSE, etINT,  {&nlevels},
          "Number of levels for energy landscape" },
        { "-mname",   FALSE, etSTR,  {&mname},
          "Legend label for the custom landscape" },
    };
#define NPA asize(pa)

    FILE           *out;
    int             n, e_n, d_n, nlast, s, nset, e_nset, d_nset, i, j = 0, *idim, *ibox;
    real          **val, **et_val, **dt_val, *t, *e_t, e_dt, d_dt, *d_t, dt, tot, error;
    real           *rmin, *rmax;
    double         *av, *sig, cum1, cum2, cum3, cum4, db;
    const char     *fn_ge, *fn_ene;
    output_env_t    oenv;
    gmx_large_int_t num_grid_points;

    t_filenm        fnm[] = {
        { efXVG, "-f",    "graph",    ffREAD   },
        { efXVG, "-ge",   "gibbs",    ffOPTRD  },
        { efXVG, "-ene",  "esham",    ffOPTRD  },
        { efXVG, "-dist", "ener",     ffOPTWR  },
        { efXVG, "-histo", "edist",    ffOPTWR  },
        { efNDX, "-bin",  "bindex",   ffOPTWR  },
        { efXPM, "-lp",   "prob",     ffOPTWR  },
        { efXPM, "-ls",   "gibbs",    ffOPTWR  },
        { efXPM, "-lsh",  "enthalpy", ffOPTWR  },
        { efXPM, "-lss",  "entropy",  ffOPTWR  },
        { efXPM, "-map",  "map",      ffOPTWR  },
        { efPDB, "-ls3",  "gibbs3",   ffOPTWR  },
        { efXVG, "-mdata", "mapdata",  ffOPTRD  },
        { efLOG, "-g",    "shamlog",  ffOPTWR  }
    };
#define NFILE asize(fnm)

    int     npargs;

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

    val = read_xvg_time(opt2fn("-f", NFILE, fnm), bHaveT,
                        opt2parg_bSet("-b", npargs, pa), tb-ttol,
                        opt2parg_bSet("-e", npargs, pa), te+ttol,
                        nsets_in, &nset, &n, &dt, &t);
    printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt);

    fn_ge  = opt2fn_null("-ge", NFILE, fnm);
    fn_ene = opt2fn_null("-ene", NFILE, fnm);

    if (fn_ge && fn_ene)
    {
        gmx_fatal(FARGS, "Can not do free energy and energy corrections at the same time");
    }

    if (fn_ge || fn_ene)
    {
        et_val = read_xvg_time(fn_ge ? fn_ge : fn_ene, bHaveT,
                               opt2parg_bSet("-b", npargs, pa), tb-ttol,
                               opt2parg_bSet("-e", npargs, pa), te+ttol,
                               1, &e_nset, &e_n, &e_dt, &e_t);
        if (fn_ge)
        {
            if (e_nset != 1)
            {
                gmx_fatal(FARGS, "Can only handle one free energy component in %s",
                          fn_ge);
            }
        }
        else
        {
            if (e_nset != 1 && e_nset != 2)
            {
                gmx_fatal(FARGS, "Can only handle one energy component or one energy and one T in %s",
                          fn_ene);
            }
        }
        if (e_n != n)
        {
            gmx_fatal(FARGS, "Number of energies (%d) does not match number of entries (%d) in %s", e_n, n, opt2fn("-f", NFILE, fnm));
        }
    }
    else
    {
        et_val = NULL;
    }

    if (opt2fn_null("-mdata", NFILE, fnm) != NULL)
    {
        dt_val = read_xvg_time(opt2fn("-mdata", NFILE, fnm), bHaveT,
                               FALSE, tb, FALSE, te,
                               nsets_in, &d_nset, &d_n, &d_dt, &d_t);
        if (d_nset != 1)
        {
            gmx_fatal(FARGS, "Can only handle one mapping data column in %s",
                      opt2fn("-mdata", NFILE, fnm));
        }
    }
    else
    {
        dt_val = NULL;
    }

    if (fn_ene && et_val)
    {
        ehisto(opt2fn("-histo", NFILE, fnm), e_n, et_val, oenv);
    }

    snew(idim, max(3, nset));
    snew(ibox, max(3, nset));
    snew(rmin, max(3, nset));
    snew(rmax, max(3, nset));
    for (i = 0; (i < min(3, nset)); i++)
    {
        idim[i] = nrdim[i];
        ibox[i] = nrbox[i];
        rmin[i] = xmin[i];
        rmax[i] = xmax[i];
    }
    for (; (i < nset); i++)
    {
        idim[i] = nrdim[2];
        ibox[i] = nrbox[2];
        rmin[i] = xmin[2];
        rmax[i] = xmax[2];
    }

    /* Check that the grid size is manageable. */
    num_grid_points = ibox[0];
    for (i = 1; i < nset; i++)
    {
        gmx_large_int_t result;
        if (!check_int_multiply_for_overflow(num_grid_points, ibox[i], &result))
        {
            gmx_fatal(FARGS,
                      "The number of dimensions and grid points is too large for this tool\n"
                      "to handle with what it knows about the architecture upon which it\n"
                      "is running. Use a different machine or consult the GROMACS mailing list.");
        }
        num_grid_points = result;
    }
    /* The number of grid points fits in a gmx_large_int_t. */

    do_sham(opt2fn("-dist", NFILE, fnm), opt2fn("-bin", NFILE, fnm),
            opt2fn("-lp", NFILE, fnm),
            opt2fn("-ls", NFILE, fnm), opt2fn("-lsh", NFILE, fnm),
            opt2fn("-lss", NFILE, fnm), opt2fn("-map", NFILE, fnm),
            opt2fn("-ls3", NFILE, fnm), opt2fn("-g", NFILE, fnm),
            n, nset, val, fn_ge != NULL, e_nset, et_val, d_n, d_t, dt_val, Tref,
            pmax, gmax,
            opt2parg_bSet("-emin", NPA, pa) ? &emin : NULL,
            opt2parg_bSet("-emax", NPA, pa) ? &emax : NULL,
            nlevels, pmin,
            mname, bSham, idim, ibox,
            opt2parg_bSet("-xmin", NPA, pa), rmin,
            opt2parg_bSet("-xmax", NPA, pa), rmax);

    thanx(stderr);

    return 0;
}
Esempio n. 18
0
static void do_my_pme(FILE *fp,real tm,gmx_bool bVerbose,t_inputrec *ir,
		      rvec x[],rvec xbuf[],rvec f[],
		      real charge[],real qbuf[],real qqbuf[],
		      matrix box,gmx_bool bSort,
		      t_commrec *cr,t_nsborder *nsb,t_nrnb *nrnb,
		      t_block *excl,real qtot,
		      t_forcerec *fr,int index[],FILE *fp_xvg,
		      int ngroups,unsigned short cENER[])
{
  real   ener,vcorr,q,xx,dvdl=0,vdip,vcharge;
  tensor vir,vir_corr,vir_tot;
  rvec   mu_tot[2];
  int    i,m,ii,ig,jg;
  real   **epme,*qptr;
  
  /* Initiate local variables */  
  fr->f_el_recip = f;
  clear_mat(vir);
  clear_mat(vir_corr);
  
  if (ngroups > 1) {
    fprintf(fp,"There are %d energy groups\n",ngroups);
    snew(epme,ngroups);
    for(i=0; (i<ngroups); i++)
      snew(epme[i],ngroups);
  }
    
  /* Put x is in the box, this part needs to be parallellized properly */
  /*put_atoms_in_box(box,nsb->natoms,x);*/
  /* Here sorting of X (and q) is done.
   * Alternatively, one could just put the atoms in one of the
   * cr->nnodes slabs. That is much cheaper than sorting.
   */
  for(i=0; (i<nsb->natoms); i++)
    index[i] = i;
  if (bSort) {
    xptr = x;
    qsort(index,nsb->natoms,sizeof(index[0]),comp_xptr);
    xptr = NULL; /* To trap unintentional use of the ptr */
  }
  /* After sorting we only need the part that is to be computed on 
   * this processor. We also compute the mu_tot here (system dipole)
   */
  clear_rvec(mu_tot[0]);
  for(i=START(nsb); (i<START(nsb)+HOMENR(nsb)); i++) {
    ii      = index[i];
    q       = charge[ii];
    qbuf[i] = q;
    for(m=0; (m<DIM); m++) {
      xx         = x[ii][m];
      xbuf[i][m] = xx;
      mu_tot[0][m] += q*xx;
    }
    clear_rvec(f[ii]);
  }
  copy_rvec(mu_tot[0],mu_tot[1]);
  if (debug) {
    pr_rvec(debug,0,"qbuf",qbuf,nsb->natoms,TRUE);
    pr_rvecs(debug,0,"xbuf",xbuf,nsb->natoms);
    pr_rvecs(debug,0,"box",box,DIM);
  }
  for(ig=0; (ig<ngroups); ig++) {
    for(jg=ig; (jg<ngroups); jg++) {
      if (ngroups > 1) {
	for(i=START(nsb); (i<START(nsb)+HOMENR(nsb)); i++) {
	  if ((cENER[i] == ig) || (cENER[i] == jg))
	    qqbuf[i] = qbuf[i];
	  else
	    qqbuf[i] = 0;
	}
	qptr = qqbuf;
      }
      else
	qptr = qbuf;
      ener  = do_pme(fp,bVerbose,ir,xbuf,f,qptr,qptr,box,cr,
		     nsb,nrnb,vir,fr->ewaldcoeff,FALSE,0,&dvdl,FALSE);
      vcorr = ewald_LRcorrection(fp,nsb,cr,fr,qptr,qptr,excl,xbuf,box,mu_tot,
				 ir->ewald_geometry,ir->epsilon_surface,
				 0,&dvdl,&vdip,&vcharge);
      gmx_sum(1,&ener,cr);
      gmx_sum(1,&vcorr,cr);
      if (ngroups > 1)
	epme[ig][jg] = ener+vcorr;
    }
  }
  if (ngroups > 1) {
    if (fp_xvg) 
      fprintf(fp_xvg,"%10.3f",tm);
    for(ig=0; (ig<ngroups); ig++) {
      for(jg=ig; (jg<ngroups); jg++) {
	if (ig != jg)
	  epme[ig][jg] -= epme[ig][ig]+epme[jg][jg];
	if (fp_xvg) 
	  fprintf(fp_xvg,"  %12.5e",epme[ig][jg]);
      }
    }
    if (fp_xvg) 
      fprintf(fp_xvg,"\n");
  }
  else {
    fprintf(fp,"Time: %10.3f Energy: %12.5e  Correction: %12.5e  Total: %12.5e\n",
	    tm,ener,vcorr,ener+vcorr);
    if (fp_xvg) 
      fprintf(fp_xvg,"%10.3f %12.5e %12.5e %12.5e\n",tm,ener+vcorr,vdip,vcharge);
    if (bVerbose) {
      m_add(vir,vir_corr,vir_tot);
      gmx_sum(9,vir_tot[0],cr);
      pr_rvecs(fp,0,"virial",vir_tot,DIM); 
    }
    fflush(fp);
  }
}
Esempio n. 19
0
void init_forcerec(FILE *fp,
		   t_forcerec *fr,
		   t_inputrec *ir,
		   t_topology *top,
		   t_commrec  *cr,
		   t_mdatoms  *mdatoms,
		   t_nsborder *nsb,
		   matrix     box,
		   bool       bMolEpot,
		   char       *tabfn,
		   bool       bNoSolvOpt)
{
  int     i,j,m,natoms,ngrp,tabelemsize;
  real    q,zsq,nrdf,T;
  rvec    box_size;
  double  rtab;
  t_block *mols,*cgs;
  t_idef  *idef;

  if (check_box(box))
    fatal_error(0,check_box(box));

  cgs            = &(top->blocks[ebCGS]);
  mols           = &(top->blocks[ebMOLS]);
  idef           = &(top->idef);
  
  natoms         = mdatoms->nr;

  /* Shell stuff */
  fr->fc_stepsize = ir->fc_stepsize;

  /* Free energy */
  fr->efep       = ir->efep;
  fr->sc_alpha   = ir->sc_alpha;
  fr->sc_sigma6  = pow(ir->sc_sigma,6);

  /* Neighbour searching stuff */
  fr->bGrid      = (ir->ns_type == ensGRID);
  fr->ndelta     = ir->ndelta;
  fr->ePBC       = ir->ePBC;
  fr->rlist      = ir->rlist;
  fr->rlistlong  = max(ir->rlist,max(ir->rcoulomb,ir->rvdw));
  fr->eeltype    = ir->coulombtype;
  fr->vdwtype    = ir->vdwtype;

  fr->bTwinRange = fr->rlistlong > fr->rlist;
  fr->bEwald     = fr->eeltype==eelPME || fr->eeltype==eelEWALD;
  fr->bvdwtab    = fr->vdwtype != evdwCUT;
  fr->bRF        = (fr->eeltype==eelRF || fr->eeltype==eelGRF) &&
		    fr->vdwtype==evdwCUT;
  fr->bcoultab   = (fr->eeltype!=eelCUT && !fr->bRF) || fr->bEwald;

#ifndef SPEC_CPU
  if (getenv("GMX_FORCE_TABLES")) {
    fr->bvdwtab  = TRUE;
    fr->bcoultab = TRUE;
  }
#endif
  if (fp) {
    fprintf(fp,"Table routines are used for coulomb: %s\n",bool_names[fr->bcoultab]);
    fprintf(fp,"Table routines are used for vdw:     %s\n",bool_names[fr->bvdwtab ]);
  }
  
  /* Tables are used for direct ewald sum */
  if(fr->bEwald) {
    fr->ewaldcoeff=calc_ewaldcoeff(ir->rcoulomb, ir->ewald_rtol);
    if (fp)
      fprintf(fp,"Using a Gaussian width (1/beta) of %g nm for Ewald\n",
	      1/fr->ewaldcoeff);
  }

  /* Domain decomposition parallellism... */
  fr->bDomDecomp = ir->bDomDecomp;
  fr->Dimension  = ir->decomp_dir;
  
  /* Electrostatics */
  fr->epsilon_r  = ir->epsilon_r;
  fr->fudgeQQ    = ir->fudgeQQ;
  fr->rcoulomb_switch = ir->rcoulomb_switch;
  fr->rcoulomb        = ir->rcoulomb;
  
#ifndef SPEC_CPU
  if (bNoSolvOpt || getenv("GMX_NO_SOLV_OPT"))
    fr->bSolvOpt = FALSE;
  else
#endif
    fr->bSolvOpt = TRUE;

  /* Parameters for generalized RF */
  fr->zsquare = 0.0;
  fr->temp    = 0.0;
  
  if (fr->eeltype == eelGRF) {
    zsq = 0.0;
    for (i=0; (i<cgs->nr); i++) {
      q = 0;
      for(j=cgs->index[i]; (j<cgs->index[i+1]); j++)
	q+=mdatoms->chargeT[cgs->a[j]];
      if (fabs(q) > GMX_REAL_MIN)
	/* Changed from square to fabs 990314 DvdS 
	 * Does not make a difference for monovalent ions, but doe for 
	 * divalent ions (Ca2+!!)
	 */
	zsq += fabs(q);
    }
    fr->zsquare = zsq;
    
    T    = 0.0;
    nrdf = 0.0;
    for(i=0; (i<ir->opts.ngtc); i++) {
      nrdf += ir->opts.nrdf[i];
      T    += (ir->opts.nrdf[i] * ir->opts.ref_t[i]);
    }
    if (nrdf < GMX_REAL_MIN) 
      fatal_error(0,"No degrees of freedom!");
    fr->temp   = T/nrdf;
  }
  else if (EEL_LR(fr->eeltype) || (fr->eeltype == eelSHIFT) || 
	   (fr->eeltype == eelUSER) || (fr->eeltype == eelSWITCH)) {
    /* We must use the long range cut-off for neighboursearching...
     * An extra range of e.g. 0.1 nm (half the size of a charge group)
     * is necessary for neighboursearching. This allows diffusion 
     * into the cut-off range (between neighborlist updates), 
     * and gives more accurate forces because all atoms within the short-range
     * cut-off rc must be taken into account, while the ns criterium takes
     * only those with the center of geometry within the cut-off.
     * (therefore we have to add half the size of a charge group, plus
     * something to account for diffusion if we have nstlist > 1)
     */
    for(m=0; (m<DIM); m++)
      box_size[m]=box[m][m];

    if (fr->phi == NULL)
      snew(fr->phi,mdatoms->nr);
    
    if ((fr->eeltype==eelPPPM) || (fr->eeltype==eelPOISSON) || 
	(fr->eeltype == eelSHIFT && fr->rcoulomb > fr->rcoulomb_switch))
	set_shift_consts(fp,fr->rcoulomb_switch,fr->rcoulomb,box_size,fr);
  }

  /* Initiate arrays */
  if (fr->bTwinRange) {
    snew(fr->f_twin,natoms);
    snew(fr->fshift_twin,SHIFTS);
  }
  
  if (EEL_LR(fr->eeltype)) {
    snew(fr->f_pme,natoms);
  }
  
  /* Mask that says whether or not this NBF list should be computed */
  /*  if (fr->bMask == NULL) {
      ngrp = ir->opts.ngener*ir->opts.ngener;
      snew(fr->bMask,ngrp);*/
  /* Defaults to always */
  /*    for(i=0; (i<ngrp); i++)
	fr->bMask[i] = TRUE;
	}*/
  
  if (fr->cg_cm == NULL)
    snew(fr->cg_cm,cgs->nr);
  if (fr->shift_vec == NULL)
    snew(fr->shift_vec,SHIFTS);
    
  if (fr->fshift == NULL)
    snew(fr->fshift,SHIFTS);
  
  if (bMolEpot && (fr->nmol==0)) {
    fr->nmol=mols->nr;
    fr->mol_nr=make_invblock(mols,natoms);
    snew(fr->mol_epot,fr->nmol);
    fr->nstcalc=ir->nstenergy;
  }
  
  if (fr->nbfp == NULL) {
    fr->ntype = idef->atnr;
    fr->bBHAM = (idef->functype[0] == F_BHAM);
    fr->nbfp  = mk_nbfp(idef,fr->bBHAM);
  }
  /* Copy the energy group exclusions */
  fr->eg_excl = ir->opts.eg_excl;

  /* Van der Waals stuff */
  fr->rvdw        = ir->rvdw;
  fr->rvdw_switch = ir->rvdw_switch;
  if ((fr->vdwtype != evdwCUT) && (fr->vdwtype != evdwUSER) && !fr->bBHAM) {
    if (fr->rvdw_switch >= fr->rvdw)
      fatal_error(0,"rvdw_switch (%g) must be < rvdw (%g)",
		  fr->rvdw_switch,fr->rvdw);
    if (fp)
      fprintf(fp,"Using %s Lennard-Jones, switch between %g and %g nm\n",
	      (fr->eeltype==eelSWITCH) ? "switched":"shifted",
	      fr->rvdw_switch,fr->rvdw);
  } 

  if (fp)
    fprintf(fp,"Cut-off's:   NS: %g   Coulomb: %g   %s: %g\n",
	    fr->rlist,fr->rcoulomb,fr->bBHAM ? "BHAM":"LJ",fr->rvdw);
  
  if (ir->eDispCorr != edispcNO)
    set_avcsix(fp,fr,mdatoms);
  if (fr->bBHAM)
    set_bham_b_max(fp,fr,mdatoms);
  
  /* Now update the rest of the vars */
  update_forcerec(fp,fr,box);
  /* if we are using LR electrostatics, and they are tabulated,
   * the tables will contain shifted coulomb interactions.
   * Since we want to use the non-shifted ones for 1-4
   * coulombic interactions, we must have an extra set of
   * tables. This should be done in tables.c, instead of this
   * ugly hack, but it works for now...
   */

#define MAX_14_DIST 1.0
  /* Shell to account for the maximum chargegroup radius (2*0.2 nm) *
   * and diffusion during nstlist steps (0.2 nm)                    */
#define TAB_EXT 0.6

  /* Construct tables.
   * A little unnecessary to make both vdw and coul tables sometimes,
   * but what the heck... */

  if (fr->bcoultab || fr->bvdwtab) {
    if (EEL_LR(fr->eeltype)) {
      bool bcoulsave,bvdwsave;
      /* generate extra tables for 1-4 interactions only
       * fake the forcerec so make_tables thinks it should
       * just create the non shifted version 
       */
      bcoulsave=fr->bcoultab;
      bvdwsave=fr->bvdwtab;
      fr->bcoultab=FALSE;
      fr->bvdwtab=FALSE;
      fr->rtab=MAX_14_DIST;
      make_tables(fp,fr,MASTER(cr),tabfn);
      fr->bcoultab=bcoulsave;
      fr->bvdwtab=bvdwsave;
      fr->coulvdw14tab=fr->coulvdwtab;
      fr->coulvdwtab=NULL;
    }
    fr->rtab = max(fr->rlistlong+TAB_EXT,MAX_14_DIST);
  }
  else if (fr->efep != efepNO) {
    if (fr->rlistlong < GMX_REAL_MIN) {
      char *ptr,*envvar="FEP_TABLE_LENGTH";
      fr->rtab = 5;
#ifdef SPEC_CPU
      ptr = NULL;
#else
      ptr = getenv(envvar);
#endif
      if (ptr) {
	sscanf(ptr,"%lf",&rtab);
	fr->rtab = rtab;
      }
      if (fp)
	fprintf(fp,"\nNote: Setting the free energy table length to %g nm\n"
		"      You can set this value with the environment variable %s"
		"\n\n",fr->rtab,envvar);
    } 
    else
      fr->rtab = max(fr->rlistlong+TAB_EXT,MAX_14_DIST);
  } 
  else
    fr->rtab = MAX_14_DIST;
  
  /* make tables for ordinary interactions */
  make_tables(fp,fr,MASTER(cr),tabfn);
  if(!(EEL_LR(fr->eeltype) && (fr->bcoultab || fr->bvdwtab)))
    fr->coulvdw14tab=fr->coulvdwtab;

  /* Copy the contents of the table to separate coulomb and LJ
   * tables too, to improve cache performance.
   */
  tabelemsize=fr->bBHAM ? 16 : 12;
  snew(fr->coultab,4*(fr->ntab+1)*sizeof(real));
  snew(fr->vdwtab,(tabelemsize-4)*(fr->ntab+1)*sizeof(real));  
  for(i=0; i<=fr->ntab; i++) {
    for(j=0; j<4; j++) 
      fr->coultab[4*i+j]=fr->coulvdwtab[tabelemsize*i+j];
    for(j=0; j<tabelemsize-4; j++) 
      fr->vdwtab[(tabelemsize-4)*i+j]=fr->coulvdwtab[tabelemsize*i+4+j];
  }
  if (!fr->mno_index)
    check_solvent(fp,top,fr,mdatoms,nsb);
}
Esempio n. 20
0
int gmx_nmeig(int argc, char *argv[])
{
    const char            *desc[] = {
        "[THISMODULE] calculates the eigenvectors/values of a (Hessian) matrix,",
        "which can be calculated with [gmx-mdrun].",
        "The eigenvectors are written to a trajectory file ([TT]-v[tt]).",
        "The structure is written first with t=0. The eigenvectors",
        "are written as frames with the eigenvector number as timestamp.",
        "The eigenvectors can be analyzed with [gmx-anaeig].",
        "An ensemble of structures can be generated from the eigenvectors with",
        "[gmx-nmens]. When mass weighting is used, the generated eigenvectors",
        "will be scaled back to plain Cartesian coordinates before generating the",
        "output. In this case, they will no longer be exactly orthogonal in the",
        "standard Cartesian norm, but in the mass-weighted norm they would be.[PAR]",
        "This program can be optionally used to compute quantum corrections to heat capacity",
        "and enthalpy by providing an extra file argument [TT]-qcorr[tt]. See the GROMACS",
        "manual, Chapter 1, for details. The result includes subtracting a harmonic",
        "degree of freedom at the given temperature.",
        "The total correction is printed on the terminal screen.",
        "The recommended way of getting the corrections out is:[PAR]",
        "[TT]gmx nmeig -s topol.tpr -f nm.mtx -first 7 -last 10000 -T 300 -qc [-constr][tt][PAR]",
        "The [TT]-constr[tt] option should be used when bond constraints were used during the",
        "simulation [BB]for all the covalent bonds[bb]. If this is not the case, ",
        "you need to analyze the [TT]quant_corr.xvg[tt] file yourself.[PAR]",
        "To make things more flexible, the program can also take virtual sites into account",
        "when computing quantum corrections. When selecting [TT]-constr[tt] and",
        "[TT]-qc[tt], the [TT]-begin[tt] and [TT]-end[tt] options will be set automatically as well.",
        "Again, if you think you know it better, please check the [TT]eigenfreq.xvg[tt]",
        "output."
    };

    static gmx_bool        bM    = TRUE, bCons = FALSE;
    static int             begin = 1, end = 50, maxspec = 4000;
    static real            T     = 298.15, width = 1;
    t_pargs                pa[]  =
    {
        { "-m",  FALSE, etBOOL, {&bM},
          "Divide elements of Hessian by product of sqrt(mass) of involved "
          "atoms prior to diagonalization. This should be used for 'Normal Modes' "
          "analysis" },
        { "-first", FALSE, etINT, {&begin},
          "First eigenvector to write away" },
        { "-last",  FALSE, etINT, {&end},
          "Last eigenvector to write away" },
        { "-maxspec", FALSE, etINT, {&maxspec},
          "Highest frequency (1/cm) to consider in the spectrum" },
        { "-T",     FALSE, etREAL, {&T},
          "Temperature for computing quantum heat capacity and enthalpy when using normal mode calculations to correct classical simulations" },
        { "-constr", FALSE, etBOOL, {&bCons},
          "If constraints were used in the simulation but not in the normal mode analysis (this is the recommended way of doing it) you will need to set this for computing the quantum corrections." },
        { "-width",  FALSE, etREAL, {&width},
          "Width (sigma) of the gaussian peaks (1/cm) when generating a spectrum" }
    };
    FILE                  *out, *qc, *spec;
    t_topology             top;
    gmx_mtop_t             mtop;
    rvec                  *top_x;
    matrix                 box;
    real                  *eigenvalues;
    real                  *eigenvectors;
    real                   qcvtot, qutot, qcv, qu;
    int                    i, j, k;
    t_tpxheader            tpx;
    real                   value, omega, nu;
    real                   factor_gmx_to_omega2;
    real                   factor_omega_to_wavenumber;
    real                  *spectrum = NULL;
    real                   wfac;
    gmx_output_env_t      *oenv;
    const char            *qcleg[] = {
        "Heat Capacity cV (J/mol K)",
        "Enthalpy H (kJ/mol)"
    };
    real *                 full_hessian   = NULL;
    gmx_sparsematrix_t *   sparse_hessian = NULL;

    t_filenm               fnm[] = {
        { efMTX, "-f", "hessian",    ffREAD  },
        { efTPR, NULL, NULL,         ffREAD  },
        { efXVG, "-of", "eigenfreq", ffWRITE },
        { efXVG, "-ol", "eigenval",  ffWRITE },
        { efXVG, "-os", "spectrum",  ffOPTWR },
        { efXVG, "-qc", "quant_corr",  ffOPTWR },
        { efTRN, "-v", "eigenvec",  ffWRITE }
    };
#define NFILE asize(fnm)

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

    /* Read tpr file for volume and number of harmonic terms */
    read_tpxheader(ftp2fn(efTPR, NFILE, fnm), &tpx, TRUE);
    snew(top_x, tpx.natoms);

    int natoms_tpx;
    read_tpx(ftp2fn(efTPR, NFILE, fnm), NULL, box, &natoms_tpx,
             top_x, NULL, &mtop);
    int nharm = 0;
    if (bCons)
    {
        nharm = get_nharm(&mtop);
    }
    std::vector<size_t> atom_index = get_atom_index(&mtop);

    top = gmx_mtop_t_to_t_topology(&mtop);

    bM       = TRUE;
    int ndim = DIM*atom_index.size();

    if (opt2bSet("-qc", NFILE, fnm))
    {
        begin = 7;
        end   = ndim;
    }
    if (begin < 1)
    {
        begin = 1;
    }
    if (end > ndim)
    {
        end = ndim;
    }
    printf("Using begin = %d and end = %d\n", begin, end);

    /*open Hessian matrix */
    int nrow, ncol;
    gmx_mtxio_read(ftp2fn(efMTX, NFILE, fnm), &nrow, &ncol, &full_hessian, &sparse_hessian);

    /* If the Hessian is in sparse format we can calculate max (ndim-1) eigenvectors,
     * If this is not valid we convert to full matrix storage,
     * but warn the user that we might run out of memory...
     */
    if ((sparse_hessian != NULL) && (end == ndim))
    {
        fprintf(stderr, "Cannot use sparse Hessian to calculate all eigenvectors.\n");

        fprintf(stderr, "Will try to allocate memory and convert to full matrix representation...\n");

        size_t hessianSize = static_cast<size_t>(nrow)*static_cast<size_t>(ncol);
        /* Allowing  Hessians larger than INT_MAX probably only makes sense
         * with (OpenMP) parallel diagonalization routines, since with a single
         * thread it will takes months.
         */
        if (hessianSize > INT_MAX)
        {
            gmx_fatal(FARGS, "Hessian size is %d x %d, which is larger than the maximum allowed %d elements.",
                      nrow, ncol, INT_MAX);
        }
        snew(full_hessian, hessianSize);
        for (i = 0; i < nrow*ncol; i++)
        {
            full_hessian[i] = 0;
        }

        for (i = 0; i < sparse_hessian->nrow; i++)
        {
            for (j = 0; j < sparse_hessian->ndata[i]; j++)
            {
                k                      = sparse_hessian->data[i][j].col;
                value                  = sparse_hessian->data[i][j].value;
                full_hessian[i*ndim+k] = value;
                full_hessian[k*ndim+i] = value;
            }
        }
        gmx_sparsematrix_destroy(sparse_hessian);
        sparse_hessian = NULL;
        fprintf(stderr, "Converted sparse to full matrix storage.\n");
    }

    snew(eigenvalues, nrow);

    if (full_hessian != NULL)
    {
        /* Using full matrix storage */
        eigenvectors = allocateEigenvectors(nrow, begin, end, false);

        nma_full_hessian(full_hessian, nrow, bM, &top, atom_index, begin, end,
                         eigenvalues, eigenvectors);
    }
    else
    {
        assert(sparse_hessian);
        /* Sparse memory storage, allocate memory for eigenvectors */
        eigenvectors = allocateEigenvectors(nrow, begin, end, true);

        nma_sparse_hessian(sparse_hessian, bM, &top, atom_index, end, eigenvalues, eigenvectors);
    }

    /* check the output, first 6 eigenvalues should be reasonably small */
    gmx_bool bSuck = FALSE;
    for (i = begin-1; (i < 6); i++)
    {
        if (std::abs(eigenvalues[i]) > 1.0e-3)
        {
            bSuck = TRUE;
        }
    }
    if (bSuck)
    {
        fprintf(stderr, "\nOne of the lowest 6 eigenvalues has a non-zero value.\n");
        fprintf(stderr, "This could mean that the reference structure was not\n");
        fprintf(stderr, "properly energy minimized.\n");
    }

    /* now write the output */
    fprintf (stderr, "Writing eigenvalues...\n");
    out = xvgropen(opt2fn("-ol", NFILE, fnm),
                   "Eigenvalues", "Eigenvalue index", "Eigenvalue [Gromacs units]",
                   oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        if (bM)
        {
            fprintf(out, "@ subtitle \"mass weighted\"\n");
        }
        else
        {
            fprintf(out, "@ subtitle \"not mass weighted\"\n");
        }
    }

    for (i = 0; i <= (end-begin); i++)
    {
        fprintf (out, "%6d %15g\n", begin+i, eigenvalues[i]);
    }
    xvgrclose(out);


    if (opt2bSet("-qc", NFILE, fnm))
    {
        qc = xvgropen(opt2fn("-qc", NFILE, fnm), "Quantum Corrections", "Eigenvector index", "", oenv);
        xvgr_legend(qc, asize(qcleg), qcleg, oenv);
        qcvtot = qutot = 0;
    }
    else
    {
        qc = NULL;
    }
    printf("Writing eigenfrequencies - negative eigenvalues will be set to zero.\n");

    out = xvgropen(opt2fn("-of", NFILE, fnm),
                   "Eigenfrequencies", "Eigenvector index", "Wavenumber [cm\\S-1\\N]",
                   oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        if (bM)
        {
            fprintf(out, "@ subtitle \"mass weighted\"\n");
        }
        else
        {
            fprintf(out, "@ subtitle \"not mass weighted\"\n");
        }
    }
    /* Spectrum ? */
    spec = NULL;
    if (opt2bSet("-os", NFILE, fnm) && (maxspec > 0))
    {
        snew(spectrum, maxspec);
        spec = xvgropen(opt2fn("-os", NFILE, fnm),
                        "Vibrational spectrum based on harmonic approximation",
                        "\\f{12}w\\f{4} (cm\\S-1\\N)",
                        "Intensity [Gromacs units]",
                        oenv);
        for (i = 0; (i < maxspec); i++)
        {
            spectrum[i] = 0;
        }
    }

    /* Gromacs units are kJ/(mol*nm*nm*amu),
     * where amu is the atomic mass unit.
     *
     * For the eigenfrequencies we want to convert this to spectroscopic absorption
     * wavenumbers given in cm^(-1), which is the frequency divided by the speed of
     * light. Do this by first converting to omega^2 (units 1/s), take the square
     * root, and finally divide by the speed of light (nm/ps in gromacs).
     */
    factor_gmx_to_omega2       = 1.0E21/(AVOGADRO*AMU);
    factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT);

    for (i = begin; (i <= end); i++)
    {
        value = eigenvalues[i-begin];
        if (value < 0)
        {
            value = 0;
        }
        omega = std::sqrt(value*factor_gmx_to_omega2);
        nu    = 1e-12*omega/(2*M_PI);
        value = omega*factor_omega_to_wavenumber;
        fprintf (out, "%6d %15g\n", i, value);
        if (NULL != spec)
        {
            wfac = eigenvalues[i-begin]/(width*std::sqrt(2*M_PI));
            for (j = 0; (j < maxspec); j++)
            {
                spectrum[j] += wfac*std::exp(-gmx::square(j-value)/(2*gmx::square(width)));
            }
        }
        if (NULL != qc)
        {
            qcv = cv_corr(nu, T);
            qu  = u_corr(nu, T);
            if (i > end-nharm)
            {
                qcv += BOLTZ*KILO;
                qu  += BOLTZ*T;
            }
            fprintf (qc, "%6d %15g %15g\n", i, qcv, qu);
            qcvtot += qcv;
            qutot  += qu;
        }
    }
    xvgrclose(out);
    if (NULL != spec)
    {
        for (j = 0; (j < maxspec); j++)
        {
            fprintf(spec, "%10g  %10g\n", 1.0*j, spectrum[j]);
        }
        xvgrclose(spec);
    }
    if (NULL != qc)
    {
        printf("Quantum corrections for harmonic degrees of freedom\n");
        printf("Use appropriate -first and -last options to get reliable results.\n");
        printf("There were %d constraints in the simulation\n", nharm);
        printf("Total correction to cV = %g J/mol K\n", qcvtot);
        printf("Total correction to  H = %g kJ/mol\n", qutot);
        xvgrclose(qc);
        please_cite(stdout, "Caleman2011b");
    }
    /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors
     * were scaled back from mass weighted cartesian to plain cartesian in the
     * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors
     * will not be strictly orthogonal in plain cartesian scalar products.
     */
    const real *eigenvectorPtr;
    if (full_hessian != NULL)
    {
        eigenvectorPtr = eigenvectors;
    }
    else
    {
        /* The sparse matrix diagonalization store all eigenvectors up to end */
        eigenvectorPtr = eigenvectors + (begin - 1)*atom_index.size();
    }
    write_eigenvectors(opt2fn("-v", NFILE, fnm), atom_index.size(), eigenvectorPtr, FALSE, begin, end,
                       eWXR_NO, NULL, FALSE, top_x, bM, eigenvalues);

    return 0;
}
Esempio n. 21
0
/* Estimate the reciprocal space part error of the SPME Ewald sum. */
static real estimate_reciprocal(
        t_inputinfo       *info,
        rvec               x[], /* array of particles */
        real               q[], /* array of charges */
        int                nr,  /* number of charges = size of the charge array */
        FILE  gmx_unused  *fp_out,
        gmx_bool           bVerbose,
        unsigned int       seed,     /* The seed for the random number generator */
        int               *nsamples, /* Return the number of samples used if Monte Carlo
                                      * algorithm is used for self energy error estimate */
        t_commrec         *cr)
{
    real     e_rec   = 0; /* reciprocal error estimate */
    real     e_rec1  = 0; /* Error estimate term 1*/
    real     e_rec2  = 0; /* Error estimate term 2*/
    real     e_rec3  = 0; /* Error estimate term 3 */
    real     e_rec3x = 0; /* part of Error estimate term 3 in x */
    real     e_rec3y = 0; /* part of Error estimate term 3 in y */
    real     e_rec3z = 0; /* part of Error estimate term 3 in z */
    int      i, ci;
    int      nx, ny, nz;  /* grid coordinates */
    real     q2_all = 0;  /* sum of squared charges */
    rvec     gridpx;      /* reciprocal grid point in x direction*/
    rvec     gridpxy;     /* reciprocal grid point in x and y direction*/
    rvec     gridp;       /* complete reciprocal grid point in 3 directions*/
    rvec     tmpvec;      /* template to create points from basis vectors */
    rvec     tmpvec2;     /* template to create points from basis vectors */
    real     coeff  = 0;  /* variable to compute coefficients of the error estimate */
    real     coeff2 = 0;  /* variable to compute coefficients of the error estimate */
    real     tmp    = 0;  /* variables to compute different factors from vectors */
    real     tmp1   = 0;
    real     tmp2   = 0;
    gmx_bool bFraction;

    /* Random number generator */
    gmx_rng_t rng     = NULL;
    int      *numbers = NULL;

    /* Index variables for parallel work distribution */
    int startglobal, stopglobal;
    int startlocal, stoplocal;
    int x_per_core;
    int xtot;

#ifdef TAKETIME
    double t0 = 0.0;
    double t1 = 0.0;
#endif

    rng = gmx_rng_init(seed);

    clear_rvec(gridpx);
    clear_rvec(gridpxy);
    clear_rvec(gridp);
    clear_rvec(tmpvec);
    clear_rvec(tmpvec2);

    for (i = 0; i < nr; i++)
    {
        q2_all += q[i]*q[i];
    }

    /* Calculate indices for work distribution */
    startglobal = -info->nkx[0]/2;
    stopglobal  = info->nkx[0]/2;
    xtot        = stopglobal*2+1;
    if (PAR(cr))
    {
        x_per_core = static_cast<int>(ceil(static_cast<real>(xtot) / cr->nnodes));
        startlocal = startglobal + x_per_core*cr->nodeid;
        stoplocal  = startlocal + x_per_core -1;
        if (stoplocal > stopglobal)
        {
            stoplocal = stopglobal;
        }
    }
    else
    {
        startlocal = startglobal;
        stoplocal  = stopglobal;
        x_per_core = xtot;
    }
/*
   #ifdef GMX_LIB_MPI
    MPI_Barrier(MPI_COMM_WORLD);
   #endif
 */

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
    {
        t0 = MPI_Wtime();
    }
#endif
#endif

    if (MASTER(cr))
    {

        fprintf(stderr, "Calculating reciprocal error part 1 ...");

    }

    for (nx = startlocal; nx <= stoplocal; nx++)
    {
        svmul(nx, info->recipbox[XX], gridpx);
        for (ny = -info->nky[0]/2; ny < info->nky[0]/2+1; ny++)
        {
            svmul(ny, info->recipbox[YY], tmpvec);
            rvec_add(gridpx, tmpvec, gridpxy);
            for (nz = -info->nkz[0]/2; nz < info->nkz[0]/2+1; nz++)
            {
                if (0 == nx &&  0 == ny &&  0 == nz)
                {
                    continue;
                }
                svmul(nz, info->recipbox[ZZ], tmpvec);
                rvec_add(gridpxy, tmpvec, gridp);
                tmp    = norm2(gridp);
                coeff  = exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                coeff /= 2.0 * M_PI * info->volume * tmp;
                coeff2 = tmp;


                tmp  = eps_poly2(nx, info->nkx[0], info->pme_order[0]);
                tmp += eps_poly2(ny, info->nkx[0], info->pme_order[0]);
                tmp += eps_poly2(nz, info->nkx[0], info->pme_order[0]);

                tmp1 = eps_poly1(nx, info->nkx[0], info->pme_order[0]);
                tmp2 = eps_poly1(ny, info->nky[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1 = eps_poly1(nz, info->nkz[0], info->pme_order[0]);
                tmp2 = eps_poly1(ny, info->nky[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1 = eps_poly1(nz, info->nkz[0], info->pme_order[0]);
                tmp2 = eps_poly1(nx, info->nkx[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1  = eps_poly1(nx, info->nkx[0], info->pme_order[0]);
                tmp1 += eps_poly1(ny, info->nky[0], info->pme_order[0]);
                tmp1 += eps_poly1(nz, info->nkz[0], info->pme_order[0]);

                tmp += tmp1 * tmp1;

                e_rec1 += 32.0 * M_PI * M_PI * coeff * coeff * coeff2 * tmp  * q2_all * q2_all / nr;

                tmp1  = eps_poly3(nx, info->nkx[0], info->pme_order[0]);
                tmp1 *= info->nkx[0];
                tmp2  = iprod(gridp, info->recipbox[XX]);

                tmp = tmp1*tmp2;

                tmp1  = eps_poly3(ny, info->nky[0], info->pme_order[0]);
                tmp1 *= info->nky[0];
                tmp2  = iprod(gridp, info->recipbox[YY]);

                tmp += tmp1*tmp2;

                tmp1  = eps_poly3(nz, info->nkz[0], info->pme_order[0]);
                tmp1 *= info->nkz[0];
                tmp2  = iprod(gridp, info->recipbox[ZZ]);

                tmp += tmp1*tmp2;

                tmp *= 4.0 * M_PI;

                tmp1  = eps_poly4(nx, info->nkx[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[XX]);
                tmp1 *= info->nkx[0] * info->nkx[0];

                tmp += tmp1;

                tmp1  = eps_poly4(ny, info->nky[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[YY]);
                tmp1 *= info->nky[0] * info->nky[0];

                tmp += tmp1;

                tmp1  = eps_poly4(nz, info->nkz[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[ZZ]);
                tmp1 *= info->nkz[0] * info->nkz[0];

                tmp += tmp1;

                e_rec2 += 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr;

            }
        }
        if (MASTER(cr))
        {
            fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core));
        }

    }

    if (MASTER(cr))
    {
        fprintf(stderr, "\n");
    }

    /* Use just a fraction of all charges to estimate the self energy error term? */
    bFraction =  (info->fracself > 0.0) && (info->fracself < 1.0);

    if (bFraction)
    {
        /* Here xtot is the number of samples taken for the Monte Carlo calculation
         * of the average of term IV of equation 35 in Wang2010. Round up to a
         * number of samples that is divisible by the number of nodes */
        x_per_core  = static_cast<int>(ceil(info->fracself * nr / cr->nnodes));
        xtot        = x_per_core * cr->nnodes;
    }
    else
    {
        /* In this case we use all nr particle positions */
        xtot       = nr;
        x_per_core = static_cast<int>(ceil(static_cast<real>(xtot) / cr->nnodes));
    }

    startlocal = x_per_core *  cr->nodeid;
    stoplocal  = std::min(startlocal + x_per_core, xtot);  /* min needed if xtot == nr */

    if (bFraction)
    {
        /* Make shure we get identical results in serial and parallel. Therefore,
         * take the sample indices from a single, global random number array that
         * is constructed on the master node and that only depends on the seed */
        snew(numbers, xtot);
        if (MASTER(cr))
        {
            for (i = 0; i < xtot; i++)
            {
                numbers[i] = static_cast<int>(floor(gmx_rng_uniform_real(rng) * nr));
            }
        }
        /* Broadcast the random number array to the other nodes */
        if (PAR(cr))
        {
            nblock_bc(cr, xtot, numbers);
        }

        if (bVerbose && MASTER(cr))
        {
            fprintf(stdout, "Using %d sample%s to approximate the self interaction error term",
                    xtot, xtot == 1 ? "" : "s");
            if (PAR(cr))
            {
                fprintf(stdout, " (%d sample%s per rank)", x_per_core, x_per_core == 1 ? "" : "s");
            }
            fprintf(stdout, ".\n");
        }
    }

    /* Return the number of positions used for the Monte Carlo algorithm */
    *nsamples = xtot;

    for (i = startlocal; i < stoplocal; i++)
    {
        e_rec3x = 0;
        e_rec3y = 0;
        e_rec3z = 0;

        if (bFraction)
        {
            /* Randomly pick a charge */
            ci = numbers[i];
        }
        else
        {
            /* Use all charges */
            ci = i;
        }

        /* for(nx=startlocal; nx<=stoplocal; nx++)*/
        for (nx = -info->nkx[0]/2; nx < info->nkx[0]/2+1; nx++)
        {
            svmul(nx, info->recipbox[XX], gridpx);
            for (ny = -info->nky[0]/2; ny < info->nky[0]/2+1; ny++)
            {
                svmul(ny, info->recipbox[YY], tmpvec);
                rvec_add(gridpx, tmpvec, gridpxy);
                for (nz = -info->nkz[0]/2; nz < info->nkz[0]/2+1; nz++)
                {

                    if (0 == nx && 0 == ny && 0 == nz)
                    {
                        continue;
                    }

                    svmul(nz, info->recipbox[ZZ], tmpvec);
                    rvec_add(gridpxy, tmpvec, gridp);
                    tmp      = norm2(gridp);
                    coeff    = exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                    coeff   /= tmp;
                    e_rec3x += coeff*eps_self(nx, info->nkx[0], info->recipbox[XX], info->pme_order[0], x[ci]);
                    e_rec3y += coeff*eps_self(ny, info->nky[0], info->recipbox[YY], info->pme_order[0], x[ci]);
                    e_rec3z += coeff*eps_self(nz, info->nkz[0], info->recipbox[ZZ], info->pme_order[0], x[ci]);

                }
            }
        }

        clear_rvec(tmpvec2);

        svmul(e_rec3x, info->recipbox[XX], tmpvec);
        rvec_inc(tmpvec2, tmpvec);
        svmul(e_rec3y, info->recipbox[YY], tmpvec);
        rvec_inc(tmpvec2, tmpvec);
        svmul(e_rec3z, info->recipbox[ZZ], tmpvec);
        rvec_inc(tmpvec2, tmpvec);

        e_rec3 += q[ci]*q[ci]*q[ci]*q[ci]*norm2(tmpvec2) / ( xtot * M_PI * info->volume * M_PI * info->volume);
        if (MASTER(cr))
        {
            fprintf(stderr, "\rCalculating reciprocal error part 2 ... %3.0f%%",
                    100.0*(i+1)/stoplocal);

        }
    }

    if (MASTER(cr))
    {
        fprintf(stderr, "\n");
    }

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
    {
        t1 = MPI_Wtime() - t0;
        fprintf(fp_out, "Recip. err. est. took   : %lf s\n", t1);
    }
#endif
#endif

#ifdef DEBUG
    if (PAR(cr))
    {
        fprintf(stderr, "Rank %3d: nx=[%3d...%3d]  e_rec3=%e\n",
                cr->nodeid, startlocal, stoplocal, e_rec3);
    }
#endif

    if (PAR(cr))
    {
        gmx_sum(1, &e_rec1, cr);
        gmx_sum(1, &e_rec2, cr);
        gmx_sum(1, &e_rec3, cr);
    }

    /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ;
       e_rec2*=  q2_all / M_PI / M_PI / info->volume / info->volume / nr ;
       e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ;
     */
    e_rec = sqrt(e_rec1+e_rec2+e_rec3);


    return ONE_4PI_EPS0 * e_rec;
}
Esempio n. 22
0
int gmx_sorient(int argc,char *argv[])
{
  t_topology top;
  int      ePBC;
  char     title[STRLEN];
  int      status;
  int      natoms;
  real     t;
  rvec     *xtop,*x;
  matrix   box;
  
  FILE    *fp;
  int     i,j,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;
  atom_id **index;
  char    **grpname;
  real    inp,outp,two_pi,nav,normfac,rmin2,rmax2,rcut,rcut2,r2,r,mass,mtot;
  real    c1,c2;
  char    str[STRLEN];
  bool    bTPS;
  rvec    xref,dx,dxh1,dxh2,outer;
  t_pbc   pbc;
  char    *legr[] = { "<cos(\\8q\\4\\s1\\N)>", 
		      "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" };
  char    *legc[] = { "cos(\\8q\\4\\s1\\N)", 
		      "3cos\\S2\\N(\\8q\\4\\s2\\N)-1" };
  
  static char *desc[] = {
    "g_sorient 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:[BR]"
    "theta1: the angle with the vector from the first atom of the solvent",
    "molecule to the midpoint between atoms 2 and 3.[BR]",
    "theta2: 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.[BR]",
    "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 cos(theta1) for rmin<=r<=rmax.[PAR]",
    "[TT]-no[tt]: distribution of cos(theta2) for rmin<=r<=rmax.[PAR]",
    "[TT]-ro[tt]: <cos(theta1)> and <3cos^2(theta2)-1> as a function of the",
    "distance.[PAR]",
    "[TT]-co[tt]: the sum over all solvent molecules within distance r",
    "of cos(theta1) and 3cos^2(theta2)-1 as a function of r.[PAR]",
    "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r"
  };
  
  static 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.xvg",  ffWRITE },
    { efXVG, "-no", "snor.xvg",  ffWRITE },
    { efXVG, "-ro", "sord.xvg",  ffWRITE },
    { efXVG, "-co", "scum.xvg",  ffWRITE },
    { efXVG, "-rc", "scount.xvg",  ffWRITE }
  };
#define NFILE asize(fnm)

  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL);
  
  two_pi = 2/M_PI;

  bTPS = (opt2bSet("-s",NFILE,fnm) || !opt2bSet("-n",NFILE,fnm) || bCom);
  if (bTPS) {
    read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&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(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);

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

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

  invrbw = 1/rbinw;
  
  snew(hist1,nbin1+1);
  snew(hist2,nbin2+1);
  nrbin = rcut/rbinw;
  if (nrbin == 0)
    nrbin = 1;
  snew(histi1,nrbin);
  snew(histi2,nrbin);
  snew(histn,nrbin);

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

  /* start analysis of trajectory */
  do {
    if (bTPS) {
      /* make molecules whole again */
      rm_pbc(&top.idef,ePBC,natoms,box,x,x);
    }
    
    set_pbc(&pbc,ePBC,box);
    n    = 0;
    inp  = 0;
    outp = 0;
    for(p=0; (p<nrefgrp); p++) {
      if (bCom)
	calc_com_pbc(nrefat,&top,x,&pbc,index[0],xref,bPBC,box);
      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];
	pbc_dx(&pbc,x[sa0],xref,dx);
	r2  = norm2(dx);
	if (r2 < rcut2) {
	  r = 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;
	  }
	  (histi1[(int)(invrbw*r)]) += inp;
	  (histi2[(int)(invrbw*r)]) += 3*sqr(outp) - 1;
	  (histn[(int)(invrbw*r)])++;
	  if (r2>=rmin2 && r2<rmax2) {
	    (hist1[(int)(invbw*(inp + 1))])++;
	    (hist2[(int)(invbw*fabs(outp))])++;
	    sum1 += inp;
	    sum2 += outp;
	     n++;
	  }
	}
      }
    }
    ntot += n;
    nf++;

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

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

  /* Add the bin for the exact maximum to the previous bin */
  hist1[nbin1-1] += hist1[nbin1];
  hist2[nbin2-1] += hist2[nbin2];
  
  nav     = (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)",""); 
  if (bPrintXvgrCodes())
    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]);
  }
  fclose(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)","");
  if (bPrintXvgrCodes())
    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]);
  }
  fclose(fp);

  
  sprintf(str,"Solvent orientation");
  fp=xvgropen(opt2fn("-ro",NFILE,fnm),str,"r (nm)","");
  if (bPrintXvgrCodes())
    fprintf(fp,"@ subtitle \"as a function of distance\"\n");
  xvgr_legend(fp,2,legr);
  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);
  fclose(fp);
  
  sprintf(str,"Cumulative solvent orientation");
  fp=xvgropen(opt2fn("-co",NFILE,fnm),str,"r (nm)","");
  if (bPrintXvgrCodes())
    fprintf(fp,"@ subtitle \"as a function of distance\"\n");
  xvgr_legend(fp,2,legc);
  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);
  }
  fclose(fp);

  sprintf(str,"Solvent distribution");
  fp=xvgropen(opt2fn("-rc",NFILE,fnm),str,"r (nm)","molecules/nm");
  if (bPrintXvgrCodes())
    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);
  }
  fclose(fp);

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

  thanx(stderr);
  
  return 0;
}
Esempio n. 23
0
void calc_potential(const char *fn, atom_id **index, int gnx[],
                    double ***slPotential, double ***slCharge,
                    double ***slField, int *nslices,
                    t_topology *top, int ePBC,
                    int axis, int nr_grps, double *slWidth,
                    double fudge_z, gmx_bool bSpherical, gmx_bool bCorrect,
                    const output_env_t oenv)
{
    rvec        *x0;      /* coordinates without pbc */
    matrix       box;     /* box (3x3) */
    int          natoms;  /* nr. atoms in trj */
    t_trxstatus *status;
    int        **slCount, /* nr. of atoms in one slice for a group */
               i, j, n, /* loop indices */
               teller    = 0,
               ax1       = 0, ax2 = 0,
               nr_frames = 0, /* number of frames */
               slice;         /* current slice */
    double       slVolume;      /* volume of slice for spherical averaging */
    double       qsum, nn;
    real         t;
    double       z;
    rvec         xcm;
    gmx_rmpbc_t  gpbc = NULL;

    switch (axis)
    {
    case 0:
        ax1 = 1;
        ax2 = 2;
        break;
    case 1:
        ax1 = 0;
        ax2 = 2;
        break;
    case 2:
        ax1 = 0;
        ax2 = 1;
        break;
    default:
        gmx_fatal(FARGS, "Invalid axes. Terminating\n");
    }

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

    if (!*nslices)
    {
        *nslices = (int)(box[axis][axis] * 10); /* default value */

    }
    fprintf(stderr, "\nDividing the box in %d slices\n", *nslices);

    snew(*slField, nr_grps);
    snew(*slCharge, nr_grps);
    snew(*slPotential, nr_grps);

    for (i = 0; i < nr_grps; i++)
    {
        snew((*slField)[i], *nslices);
        snew((*slCharge)[i], *nslices);
        snew((*slPotential)[i], *nslices);
    }


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

    /*********** Start processing trajectory ***********/
    do
    {
        *slWidth = box[axis][axis]/(*nslices);
        teller++;
        gmx_rmpbc(gpbc, natoms, box, x0);

        /* calculate position of center of mass based on group 1 */
        calc_xcm(x0, gnx[0], index[0], top->atoms.atom, xcm, FALSE);
        svmul(-1, xcm, xcm);

        for (n = 0; n < nr_grps; n++)
        {
            /* Check whether we actually have all positions of the requested index
             * group in the trajectory file */
            if (gnx[n] > natoms)
            {
                gmx_fatal(FARGS, "You selected a group with %d atoms, but only %d atoms\n"
                          "were found in the trajectory.\n", gnx[n], natoms);
            }
            for (i = 0; i < gnx[n]; i++) /* loop over all atoms in index file */
            {
                if (bSpherical)
                {
                    rvec_add(x0[index[n][i]], xcm, x0[index[n][i]]);
                    /* only distance from origin counts, not sign */
                    slice = norm(x0[index[n][i]])/(*slWidth);

                    /* this is a nice check for spherical groups but not for
                       all water in a cubic box since a lot will fall outside
                       the sphere
                       if (slice > (*nslices))
                       {
                       fprintf(stderr,"Warning: slice = %d\n",slice);
                       }
                     */
                    (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q;
                }
                else
                {
                    z = x0[index[n][i]][axis];
                    z = z + fudge_z;
                    if (z < 0)
                    {
                        z += box[axis][axis];
                    }
                    if (z > box[axis][axis])
                    {
                        z -= box[axis][axis];
                    }
                    /* determine which slice atom is in */
                    slice                  = (z / (*slWidth));
                    (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q;
                }
            }
        }
        nr_frames++;
    }
    while (read_next_x(oenv, status, &t, x0, box));

    gmx_rmpbc_done(gpbc);

    /*********** done with status file **********/
    close_trj(status);

    /* slCharge now contains the total charge per slice, summed over all
       frames. Now divide by nr_frames and integrate twice
     */


    if (bSpherical)
    {
        fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential"
                "in spherical coordinates\n", nr_frames);
    }
    else
    {
        fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential\n",
                nr_frames);
    }

    for (n = 0; n < nr_grps; n++)
    {
        for (i = 0; i < *nslices; i++)
        {
            if (bSpherical)
            {
                /* charge per volume is now the summed charge, divided by the nr
                   of frames and by the volume of the slice it's in, 4pi r^2 dr
                 */
                slVolume = 4*M_PI * sqr(i) * sqr(*slWidth) * *slWidth;
                if (slVolume == 0)
                {
                    (*slCharge)[n][i] = 0;
                }
                else
                {
                    (*slCharge)[n][i] = (*slCharge)[n][i] / (nr_frames * slVolume);
                }
            }
            else
            {
                /* get charge per volume */
                (*slCharge)[n][i] = (*slCharge)[n][i] * (*nslices) /
                                    (nr_frames * box[axis][axis] * box[ax1][ax1] * box[ax2][ax2]);
            }
        }
        /* Now we have charge densities */
    }

    if (bCorrect && !bSpherical)
    {
        for (n = 0; n < nr_grps; n++)
        {
            nn   = 0;
            qsum = 0;
            for (i = 0; i < *nslices; i++)
            {
                if (fabs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN)
                {
                    nn++;
                    qsum += (*slCharge)[n][i];
                }
            }
            qsum /= nn;
            for (i = 0; i < *nslices; i++)
            {
                if (fabs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN)
                {
                    (*slCharge)[n][i] -= qsum;
                }
            }
        }
    }

    for (n = 0; n < nr_grps; n++)
    {
        /* integrate twice to get field and potential */
        p_integrate((*slField)[n], (*slCharge)[n], *nslices, *slWidth);
    }


    if (bCorrect && !bSpherical)
    {
        for (n = 0; n < nr_grps; n++)
        {
            nn   = 0;
            qsum = 0;
            for (i = 0; i < *nslices; i++)
            {
                if (fabs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN)
                {
                    nn++;
                    qsum += (*slField)[n][i];
                }
            }
            qsum /= nn;
            for (i = 0; i < *nslices; i++)
            {
                if (fabs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN)
                {
                    (*slField)[n][i] -= qsum;
                }
            }
        }
    }

    for (n = 0; n < nr_grps; n++)
    {
        p_integrate((*slPotential)[n], (*slField)[n], *nslices, *slWidth);
    }

    /* Now correct for eps0 and in spherical case for r*/
    for (n = 0; n < nr_grps; n++)
    {
        for (i = 0; i < *nslices; i++)
        {
            if (bSpherical)
            {
                (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 /
                                       (EPS0 * i * (*slWidth));
                (*slField)[n][i] = ELC * (*slField)[n][i] * 1E18 /
                                   (EPS0 * i * (*slWidth));
            }
            else
            {
                (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 / EPS0;
                (*slField)[n][i]     = ELC * (*slField)[n][i] * 1E18 / EPS0;
            }
        }
    }

    sfree(x0); /* free memory used by coordinate array */
}
static void insert_mols(int nmol_insrt, int ntry, int seed,
                        real defaultDistance, real scaleFactor,
                        t_atoms *atoms, rvec **x,
                        const t_atoms *atoms_insrt, const rvec *x_insrt,
                        int ePBC, matrix box,
                        const std::string &posfn, const rvec deltaR, int enum_rot)
{
    t_pbc            pbc;
    rvec            *x_n;

    fprintf(stderr, "Initialising inter-atomic distances...\n");
    gmx_atomprop_t   aps = gmx_atomprop_init();
    real            *exclusionDistances
        = makeExclusionDistances(atoms, aps, defaultDistance, scaleFactor);
    real            *exclusionDistances_insrt
        = makeExclusionDistances(atoms_insrt, aps, defaultDistance, scaleFactor);
    gmx_atomprop_destroy(aps);

    const real       maxInsertRadius
        = *std::max_element(exclusionDistances_insrt,
                            exclusionDistances_insrt + atoms_insrt->nr);
    real             maxRadius = maxInsertRadius;
    if (atoms->nr > 0)
    {
        const real maxExistingRadius
            = *std::max_element(exclusionDistances,
                                exclusionDistances + atoms->nr);
        maxRadius = std::max(maxInsertRadius, maxExistingRadius);
    }

    // TODO: Make all of this exception-safe.
    gmx::AnalysisNeighborhood nb;
    nb.setCutoff(maxInsertRadius + maxRadius);

    gmx_rng_t        rng = gmx_rng_init(seed);
    set_pbc(&pbc, ePBC, box);

    snew(x_n, atoms_insrt->nr);

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

    {
        const int finalAtomCount    = atoms->nr + nmol_insrt * atoms_insrt->nr;
        const int finalResidueCount = atoms->nres + nmol_insrt * atoms_insrt->nres;
        srenew(atoms->resinfo,      finalResidueCount);
        srenew(atoms->atomname,     finalAtomCount);
        srenew(atoms->atom,         finalAtomCount);
        srenew(*x,                  finalAtomCount);
        srenew(exclusionDistances,  finalAtomCount);
    }

    int mol        = 0;
    int trial      = 0;
    int firstTrial = 0;
    int failed     = 0;
    while ((mol < nmol_insrt) && (trial < ntry*nmol_insrt))
    {
        rvec offset_x;
        if (posfn.empty())
        {
            // Insert at random positions.
            offset_x[XX] = box[XX][XX] * gmx_rng_uniform_real(rng);
            offset_x[YY] = box[YY][YY] * gmx_rng_uniform_real(rng);
            offset_x[ZZ] = box[ZZ][ZZ] * gmx_rng_uniform_real(rng);
        }
        else
        {
            // Skip a position if ntry trials were not successful.
            if (trial >= firstTrial + ntry)
            {
                fprintf(stderr, " skipped position (%.3f, %.3f, %.3f)\n",
                        rpos[XX][mol], rpos[YY][mol], rpos[ZZ][mol]);
                ++mol;
                ++failed;
            }
            // Insert at positions taken from option -ip file.
            offset_x[XX] = rpos[XX][mol] + deltaR[XX]*(2 * gmx_rng_uniform_real(rng)-1);
            offset_x[YY] = rpos[YY][mol] + deltaR[YY]*(2 * gmx_rng_uniform_real(rng)-1);
            offset_x[ZZ] = rpos[ZZ][mol] + deltaR[ZZ]*(2 * gmx_rng_uniform_real(rng)-1);
        }
        fprintf(stderr, "\rTry %d", ++trial);
        generate_trial_conf(atoms_insrt->nr, x_insrt, offset_x, enum_rot, rng,
                            x_n);
        gmx::AnalysisNeighborhoodPositions pos(*x, atoms->nr);
        gmx::AnalysisNeighborhoodSearch    search = nb.initSearch(&pbc, pos);
        if (is_insertion_allowed(&search, exclusionDistances, atoms_insrt->nr,
                                 x_n, exclusionDistances_insrt))
        {
            const int firstIndex = atoms->nr;
            for (int i = 0; i < atoms_insrt->nr; ++i)
            {
                copy_rvec(x_n[i], (*x)[firstIndex + i]);
                exclusionDistances[firstIndex + i] = exclusionDistances_insrt[i];
            }
            merge_atoms_noalloc(atoms, atoms_insrt);
            ++mol;
            firstTrial = trial;
            fprintf(stderr, " success (now %d atoms)!\n", atoms->nr);
        }
    }
    gmx_rng_destroy(rng);
    srenew(atoms->resinfo,  atoms->nres);
    srenew(atoms->atomname, atoms->nr);
    srenew(atoms->atom,     atoms->nr);
    srenew(*x,              atoms->nr);

    fprintf(stderr, "\n");
    /* print number of molecules added */
    fprintf(stderr, "Added %d molecules (out of %d requested)\n",
            mol - failed, nmol_insrt);

    sfree(x_n);
    sfree(exclusionDistances);
    sfree(exclusionDistances_insrt);
    if (rpos != NULL)
    {
        for (int i = 0; i < DIM; ++i)
        {
            sfree(rpos[i]);
        }
        sfree(rpos);
    }
}
Esempio n. 25
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        bTPS, bTop; /* ,bCubic; */
    int             gnx;
    atom_id        *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          **c1, **tc;
    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 | PCA_BE_NICE,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &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;
    /* bCubic = TRUE; */
    do
    {
        /*
           bCubic = bCubic && !TRICLINIC(fr.box) &&
           fabs(fr.box[XX][XX]-fr.box[YY][YY]) < 0.001*fr.box[XX][XX] &&
           fabs(fr.box[XX][XX]-fr.box[ZZ][ZZ]) < 0.001*fr.box[XX][XX];
         */

        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              = sin(iprod(kfac[k], cm_mol));
                cx              = 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;
}
Esempio n. 26
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]",
    "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 bool bNDEF=FALSE,bRMPBC=FALSE,bCenter=FALSE,bReadVDW=FALSE,bCONECT=FALSE;
  static 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};
  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"},
    { "-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;
  char       *infile,*outfile,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;
  int        isize,ssize,tsize;
  atom_id    *index,*sindex,*tindex;
  rvec       *x,*v,gc,min,max,size;
  int        ePBC;
  matrix     box;
  bool       bIndex,bSetSize,bSetAng,bCubic,bDist,bSetCenter;
  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;
  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);

  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);
  /* 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)
    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 (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 {
	svmul(DEG2RAD,newang,newang);
	box[XX][XX] = newbox[XX];
	box[YY][XX] = newbox[YY]*cos(newang[ZZ]);
	box[YY][YY] = newbox[YY]*sin(newang[ZZ]);
	box[ZZ][XX] = newbox[ZZ]*cos(newang[YY]);
	box[ZZ][YY] = newbox[ZZ]
	  *(cos(newang[XX])-cos(newang[YY])*cos(newang[ZZ]))/sin(newang[ZZ]);
	box[ZZ][ZZ] = sqrt(sqr(newbox[ZZ])
			   -box[ZZ][XX]*box[ZZ][XX]-box[ZZ][YY]*box[ZZ][YY]);
      }
      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 (opt2bSet("-bf",NFILE,fnm))
      gmx_fatal(FARGS,"combination not implemented: -bf -n  or -bf -ndef");
    else {
      if (outftp == efPDB) {
	out=ffopen(outfile,"w");
	write_pdbfile_indexed(out,title,&atoms,x,ePBC,box,' ',1,isize,index,conect);
	fclose(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].chain=label[0];
      }
      write_pdbfile(out,title,&atoms,x,ePBC,box,0,-1,conect);
      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);
      fclose(out);
    }
    else
      write_sto_conf(outfile,title,&atoms,x,bHaveV?v:NULL,ePBC,box); 
  }
  gmx_atomprop_destroy(aps);

  do_view(outfile,NULL);
    
  thanx(stderr);
  
  return 0;
}
Esempio n. 27
0
void sort_ions(int nsa,int nw,int repl[],atom_id index[],
	       t_atoms *atoms,rvec x[],
	       const char *p_name,const char *n_name)
{
  int i,j,k,r,np,nn,starta,startr,npi,nni;
  rvec *xt;
  char **pptr=NULL,**nptr=NULL,**paptr=NULL,**naptr=NULL;

  snew(xt,atoms->nr);

  /* Put all the solvent in front and count the added ions */
  np=0;
  nn=0;
  j=index[0];
  for(i=0; i<nw; i++) {
    r = repl[i];
    if (r == 0)
      for(k=0; k<nsa; k++)
	copy_rvec(x[index[nsa*i+k]],xt[j++]);
    else if (r>0)
      np++;
    else if (r<0)
      nn++;
  }

  if (np+nn > 0) {
    /* Put the positive and negative ions at the end */
    starta = index[nsa*(nw - np - nn)];
    startr = atoms->atom[starta].resind;

    if (np) {
      snew(pptr,1);
      pptr[0] = strdup(p_name);
      snew(paptr,1);
      paptr[0] = aname(p_name);
    }
    if (nn) {
      snew(nptr,1);
      nptr[0] = strdup(n_name);
      snew(naptr,1);
      naptr[0] = aname(n_name);
    }
    npi = 0;
    nni = 0;
    for(i=0; i<nw; i++) {
      r = repl[i];
      if (r > 0) {
	j = starta+npi;
	k = startr+npi;
	copy_rvec(x[index[nsa*i]],xt[j]);
	atoms->atomname[j] = paptr;
	atoms->atom[j].resind = k ;
	atoms->resinfo[k].name = pptr;
	npi++;
      } else if (r < 0) {
	j = starta+np+nni;
	k = startr+np+nni;
	copy_rvec(x[index[nsa*i]],xt[j]);
	atoms->atomname[j] = naptr;
	atoms->atom[j].resind = k;
	atoms->resinfo[k].name = nptr;
	nni++;
      }
    }
    for(i=index[nsa*nw-1]+1; i<atoms->nr; i++) {
      j = i-(nsa-1)*(np+nn);
      atoms->atomname[j] = atoms->atomname[i];
      atoms->atom[j] = atoms->atom[i];
      copy_rvec(x[i],xt[j]);
    }
    atoms->nr -= (nsa-1)*(np+nn);

    /* Copy the new positions back */
    for(i=index[0]; i<atoms->nr; i++)
      copy_rvec(xt[i],x[i]);
    sfree(xt);
  }
}
Esempio n. 28
0
static void pick_minima(const char *logfile, int *ibox, int ndim, int len, real W[])
{
    FILE      *fp;
    int        i, j, k, nmin;
    t_minimum *mm, this_min;
    int       *this_point;
    int        loopmax, loopcounter;

    snew(mm, len);
    nmin = 0;
    fp   = ffopen(logfile, "w");
    /* Loop over each element in the array of dimenion ndim seeking
     * minima with respect to every dimension. Specialized loops for
     * speed with ndim == 2 and ndim == 3. */
    switch (ndim)
    {
        case 0:
            /* This is probably impossible to reach anyway. */
            break;
        case 2:
            for (i = 0; (i < ibox[0]); i++)
            {
                for (j = 0; (j < ibox[1]); j++)
                {
                    /* Get the index of this point in the flat array */
                    this_min.index = index2(ibox, i, j);
                    this_min.ener  = W[this_min.index];
                    if (is_local_minimum_from_below(&this_min, i, 0,         index2(ibox, i-1, j  ), W) &&
                        is_local_minimum_from_above(&this_min, i, ibox[0]-1, index2(ibox, i+1, j  ), W) &&
                        is_local_minimum_from_below(&this_min, j, 0,         index2(ibox, i, j-1), W) &&
                        is_local_minimum_from_above(&this_min, j, ibox[1]-1, index2(ibox, i, j+1), W))
                    {
                        add_minimum(fp, nmin, &this_min, mm);
                        nmin++;
                    }
                }
            }
            break;
        case 3:
            for (i = 0; (i < ibox[0]); i++)
            {
                for (j = 0; (j < ibox[1]); j++)
                {
                    for (k = 0; (k < ibox[2]); k++)
                    {
                        /* Get the index of this point in the flat array */
                        this_min.index = index3(ibox, i, j, k);
                        this_min.ener  = W[this_min.index];
                        if (is_local_minimum_from_below(&this_min, i, 0,         index3(ibox, i-1, j, k  ), W) &&
                            is_local_minimum_from_above(&this_min, i, ibox[0]-1, index3(ibox, i+1, j, k  ), W) &&
                            is_local_minimum_from_below(&this_min, j, 0,         index3(ibox, i, j-1, k  ), W) &&
                            is_local_minimum_from_above(&this_min, j, ibox[1]-1, index3(ibox, i, j+1, k  ), W) &&
                            is_local_minimum_from_below(&this_min, k, 0,         index3(ibox, i, j, k-1), W) &&
                            is_local_minimum_from_above(&this_min, k, ibox[2]-1, index3(ibox, i, j, k+1), W))
                        {
                            add_minimum(fp, nmin, &this_min, mm);
                            nmin++;
                        }
                    }
                }
            }
            break;
        default:
            /* Note this treats ndim == 1 and ndim > 3 */

            /* Set up an ndim-dimensional vector to loop over the points
             * on the grid. (0,0,0, ... 0) is an acceptable place to
             * start. */
            snew(this_point, ndim);

            /* Determine the number of points of the ndim-dimensional
             * grid. */
            loopmax = ibox[0];
            for (i = 1; i < ndim; i++)
            {
                loopmax *= ibox[i];
            }

            loopcounter = 0;
            while (loopmax > loopcounter)
            {
                gmx_bool bMin = TRUE;

                /* Get the index of this_point in the flat array */
                this_min.index = indexn(ndim, ibox, this_point);
                this_min.ener  = W[this_min.index];

                /* Is this_point a minimum from above and below in each
                 * dimension? */
                for (i = 0; bMin && (i < ndim); i++)
                {
                    /* Save the index of this_point within the curent
                     * dimension so we can change that index in the
                     * this_point array for use with indexn(). */
                    int index = this_point[i];
                    this_point[i]--;
                    bMin = bMin &&
                        is_local_minimum_from_below(&this_min, index, 0,         indexn(ndim, ibox, this_point), W);
                    this_point[i] += 2;
                    bMin           = bMin &&
                        is_local_minimum_from_above(&this_min, index, ibox[i]-1, indexn(ndim, ibox, this_point), W);
                    this_point[i]--;
                }
                if (bMin)
                {
                    add_minimum(fp, nmin, &this_min, mm);
                    nmin++;
                }

                /* update global loop counter */
                loopcounter++;

                /* Avoid underflow of this_point[i] */
                if (loopmax > loopcounter)
                {
                    /* update this_point non-recursively */
                    i = ndim-1;
                    this_point[i]++;
                    while (ibox[i] == this_point[i])
                    {
                        this_point[i] = 0;
                        i--;
                        /* this_point[i] cannot underflow because
                         * loopmax > loopcounter. */
                        this_point[i]++;
                    }
                }
            }

            sfree(this_point);
            break;
    }
    qsort(mm, nmin, sizeof(mm[0]), comp_minima);
    fprintf(fp, "Minima sorted after energy\n");
    for (i = 0; (i < nmin); i++)
    {
        print_minimum(fp, i, &mm[i]);
    }
    ffclose(fp);
    sfree(mm);
}
Esempio n. 29
0
t_bb *mkbbind(const char *fn, int *nres, int *nbb, int res0,
              int *nall, atom_id **index,
              char ***atomname, t_atom atom[],
              t_resinfo *resinfo)
{
    static const char * bb_nm[] = { "N", "H", "CA", "C", "O", "HN" };
#define NBB asize(bb_nm)
    t_bb               *bb;
    char               *grpname;
    int                 ai, i, i0, i1, j, k, ri, rnr, gnx, r0, r1;

    fprintf(stderr, "Please select a group containing the entire backbone\n");
    rd_index(fn, 1, &gnx, index, &grpname);
    *nall = gnx;
    fprintf(stderr, "Checking group %s\n", grpname);
    r0 = r1 = atom[(*index)[0]].resind;
    for (i = 1; (i < gnx); i++)
    {
        r0 = min(r0, atom[(*index)[i]].resind);
        r1 = max(r1, atom[(*index)[i]].resind);
    }
    rnr = r1-r0+1;
    fprintf(stderr, "There are %d residues\n", rnr);
    snew(bb, rnr);
    for (i = 0; (i < rnr); i++)
    {
        bb[i].N = bb[i].H = bb[i].CA = bb[i].C = bb[i].O = -1, bb[i].resno = res0+i;
    }

    for (i = j = 0; (i < gnx); i++)
    {
        ai = (*index)[i];
        ri = atom[ai].resind-r0;
        if (strcmp(*(resinfo[ri].name), "PRO") == 0)
        {
            if (strcmp(*(atomname[ai]), "CD") == 0)
            {
                bb[ri].H = ai;
            }
        }
        for (k = 0; (k < NBB); k++)
        {
            if (strcmp(bb_nm[k], *(atomname[ai])) == 0)
            {
                j++;
                break;
            }
        }
        switch (k)
        {
            case 0:
                bb[ri].N = ai;
                break;
            case 1:
            case 5:
                /* No attempt to address the case where some weird input has both H and HN atoms in the group */
                bb[ri].H = ai;
                break;
            case 2:
                bb[ri].CA = ai;
                break;
            case 3:
                bb[ri].C = ai;
                break;
            case 4:
                bb[ri].O = ai;
                break;
            default:
                break;
        }
    }

    for (i0 = 0; (i0 < rnr); i0++)
    {
        if ((bb[i0].N != -1) && (bb[i0].H != -1) &&
            (bb[i0].CA != -1) &&
            (bb[i0].C != -1) && (bb[i0].O != -1))
        {
            break;
        }
    }
    for (i1 = rnr-1; (i1 >= 0); i1--)
    {
        if ((bb[i1].N != -1) && (bb[i1].H != -1) &&
            (bb[i1].CA != -1) &&
            (bb[i1].C != -1) && (bb[i1].O != -1))
        {
            break;
        }
    }
    if (i0 == 0)
    {
        i0++;
    }
    if (i1 == rnr-1)
    {
        i1--;
    }

    for (i = i0; (i < i1); i++)
    {
        bb[i].Cprev = bb[i-1].C;
        bb[i].Nnext = bb[i+1].N;
    }
    rnr = max(0, i1-i0+1);
    fprintf(stderr, "There are %d complete backbone residues (from %d to %d)\n",
            rnr, bb[i0].resno, bb[i1].resno);
    if (rnr == 0)
    {
        gmx_fatal(FARGS, "Zero complete backbone residues were found, cannot proceed");
    }
    for (i = 0; (i < rnr); i++, i0++)
    {
        bb[i] = bb[i0];
    }

    /* Set the labels */
    for (i = 0; (i < rnr); i++)
    {
        ri = atom[bb[i].CA].resind;
        sprintf(bb[i].label, "%s%d", *(resinfo[ri].name), ri+res0);
    }

    *nres = rnr;
    *nbb  = rnr*asize(bb_nm);

    return bb;
}
Esempio n. 30
0
void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string,
                const output_env_t oenv)
{
    FILE        *fp;
    t_mapping   *map;
    int          f, r, *count, *total, ss_count, total_count;
    size_t       s;
    const char** leg;

    map = mat->map;
    snew(count, mat->nmap);
    snew(total, mat->nmap);
    snew(leg, mat->nmap+1);
    leg[0] = "Structure";
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        leg[s+1] = gmx_strdup(map[s].desc);
    }

    fp = xvgropen(outfile, "Secondary Structure",
                  output_env_get_xvgr_tlabel(oenv), "Number of Residues", oenv);
    if (output_env_get_print_xvgr_codes(oenv))
    {
        fprintf(fp, "@ subtitle \"Structure = ");
    }
    for (s = 0; s < strlen(ss_string); s++)
    {
        if (s > 0)
        {
            fprintf(fp, " + ");
        }
        for (f = 0; f < mat->nmap; f++)
        {
            if (ss_string[s] == map[f].code.c1)
            {
                fprintf(fp, "%s", map[f].desc);
            }
        }
    }
    fprintf(fp, "\"\n");
    xvgr_legend(fp, mat->nmap+1, leg, oenv);

    total_count = 0;
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        total[s] = 0;
    }
    for (f = 0; f < mat->nx; f++)
    {
        ss_count = 0;
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            count[s] = 0;
        }
        for (r = 0; r < mat->ny; r++)
        {
            count[mat->matrix[f][r]]++;
            total[mat->matrix[f][r]]++;
        }
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            if (strchr(ss_string, map[s].code.c1))
            {
                ss_count    += count[s];
                total_count += count[s];
            }
        }
        fprintf(fp, "%8g %5d", mat->axis_x[f], ss_count);
        for (s = 0; s < (size_t)mat->nmap; s++)
        {
            fprintf(fp, " %5d", count[s]);
        }
        fprintf(fp, "\n");
    }
    /* now print column totals */
    fprintf(fp, "%-8s %5d", "# Totals", total_count);
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        fprintf(fp, " %5d", total[s]);
    }
    fprintf(fp, "\n");

    /* now print percentages */
    fprintf(fp, "%-8s %5.2f", "# SS %", total_count / (real) (mat->nx * mat->ny));
    for (s = 0; s < (size_t)mat->nmap; s++)
    {
        fprintf(fp, " %5.2f", total[s] / (real) (mat->nx * mat->ny));
    }
    fprintf(fp, "\n");

    gmx_ffclose(fp);
    sfree(leg);
    sfree(count);
}