예제 #1
0
static void horizontal()
{
    gmx_rng_t   rng;
    gmx_stats_t straight;
    int         i, ok, n = 1000;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh;
    FILE       *fp;

    rng      = gmx_rng_init(13);
    straight = gmx_stats_init();
    for (i = 0; (i < n); i++)
    {
        y = gmx_rng_uniform_real(rng);
        if ((ok = gmx_stats_add_point(straight, i, y, 0, 0)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
    }
    /* Horizontal test */
    if ((ok = gmx_stats_get_ase(straight, &aver, &sigma, &error)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
    fp = fopen("straight.xvg", "w");
    if ((ok = gmx_stats_dump_xy(straight, fp)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
    fclose(fp);
    printf("Horizontal line: average %g, sigma %g, error %g\n", aver, sigma, error);
    if ((ok = gmx_stats_done(straight)) != estatsOK)
    {
        fprintf(stderr, "%s\n", gmx_stats_message(ok));
    }
}
예제 #2
0
static void pukeit(const char *db, const char *defstring, char *retstring,
                   int retsize, int *cqnum)
{
    FILE     *fp;
    char    **help;
    int       i, nhlp;
    gmx_rng_t rng;

    if (be_cool() && ((fp = low_libopen(db, FALSE)) != NULL))
    {
        nhlp = fget_lines(fp, &help);
        /* for libraries we can use the low-level close routines */
        gmx_ffclose(fp);
        rng    = gmx_rng_init(gmx_rng_make_seed());
        *cqnum = static_cast<int>(nhlp*gmx_rng_uniform_real(rng));
        gmx_rng_destroy(rng);
        if (strlen(help[*cqnum]) >= STRLEN)
        {
            help[*cqnum][STRLEN-1] = '\0';
        }
        strncpy(retstring, help[*cqnum], retsize);
        for (i = 0; (i < nhlp); i++)
        {
            sfree(help[i]);
        }
        sfree(help);
    }
    else
    {
        *cqnum = -1;
        strncpy(retstring, defstring, retsize);
    }
}
예제 #3
0
static void line()
{
    gmx_rng_t   rng;
    gmx_stats_t line;
    int         i, dy, ok, n = 1000;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, rfit;
    const real  a0 = 0.23, b0 = 2.7;
    FILE       *fp;

    for (dy = 0; (dy < 2); dy++)
    {
        rng      = gmx_rng_init(13);
        line     = gmx_stats_init();
        for (i = 0; (i < n); i++)
        {
            y = a0*i+b0+50*(gmx_rng_uniform_real(rng)-0.5);
            if ((ok = gmx_stats_add_point(line, i, y, 0, dy*0.1)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
        }
        /* Line with slope test */
        if ((ok = gmx_stats_get_ab(line, elsqWEIGHT_NONE, &a, &b, &da, &db, &chi2, &rfit)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        if ((ok = gmx_stats_get_corr_coeff(line, &R)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        if (dy == 0)
        {
            fp = fopen("line0.xvg", "w");
        }
        else
        {
            fp = fopen("line1.xvg", "w");
        }
        if ((ok = gmx_stats_dump_xy(line, fp)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        fclose(fp);
        printf("Line with eqn. y = %gx + %g with noise%s\n", a0, b0,
               (dy == 0) ? "" : " and uncertainties");
        printf("Found: a = %g +/- %g, b = %g +/- %g\n", a, da, b, db);
        if ((ok = gmx_stats_done(line)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        gmx_rng_destroy(rng);
    }
}
예제 #4
0
gmx_stochd_t init_stochd(FILE *fplog,t_inputrec *ir)
{
  t_gmx_stochd *sd;
  gmx_sd_const_t *sdc;
  int  ngtc,n;
  real y;

  snew(sd,1);

  /* Initiate random number generator for langevin type dynamics,
   * for BD, SD or velocity rescaling temperature coupling.
   */
  sd->gaussrand = gmx_rng_init(ir->ld_seed);

  ngtc = ir->opts.ngtc;

  if (ir->eI == eiBD) {
    snew(sd->bd_rf,ngtc);
  } else if (EI_SD(ir->eI)) {
    snew(sd->sdc,ngtc);
    snew(sd->sdsig,ngtc);
    
    sdc = sd->sdc;
    for(n=0; n<ngtc; n++) {
      sdc[n].gdt = ir->delta_t/ir->opts.tau_t[n];
      sdc[n].eph = exp(sdc[n].gdt/2);
      sdc[n].emh = exp(-sdc[n].gdt/2);
      sdc[n].em  = exp(-sdc[n].gdt);
      if (sdc[n].gdt >= 0.05) {
	sdc[n].b = sdc[n].gdt*(sdc[n].eph*sdc[n].eph - 1) 
	  - 4*(sdc[n].eph - 1)*(sdc[n].eph - 1);
	sdc[n].c = sdc[n].gdt - 3 + 4*sdc[n].emh - sdc[n].em;
	sdc[n].d = 2 - sdc[n].eph - sdc[n].emh;
      } else {
	y = sdc[n].gdt/2;
	/* Seventh order expansions for small y */
	sdc[n].b = y*y*y*y*(1/3.0+y*(1/3.0+y*(17/90.0+y*7/9.0)));
	sdc[n].c = y*y*y*(2/3.0+y*(-1/2.0+y*(7/30.0+y*(-1/12.0+y*31/1260.0))));
	sdc[n].d = y*y*(-1+y*y*(-1/12.0-y*y/360.0));
      }
      if(debug)
	fprintf(debug,"SD const tc-grp %d: b %g  c %g  d %g\n",
		n,sdc[n].b,sdc[n].c,sdc[n].d);
    }
  }

  return sd;
}
예제 #5
0
void maxwell_speed(real tempi, unsigned int seed, gmx_mtop_t *mtop, rvec v[])
{
    gmx_rng_t rng;

    if (seed == 0)
    {
        seed = gmx_rng_make_seed();
        fprintf(stderr, "Using random seed %u for generating velocities\n", seed);
    }

    rng = gmx_rng_init(seed);

    low_mspeed(tempi, mtop, v, rng);

    gmx_rng_destroy(rng);
}
예제 #6
0
static void histogram()
{
    gmx_rng_t   rng;
    gmx_stats_t camel;
    int         i, ok, n = 1000, norm;
    real        y, a, b, da, db, aver, sigma, error, chi2, R, *xh, *yh;
    const real  a0 = 0.23, b0 = 2.7;
    FILE       *fp;
    char        fn[256];

    for (norm = 0; (norm < 2); norm++)
    {
        rng      = gmx_rng_init(13);
        camel    = gmx_stats_init();
        for (i = 0; (i < n); i++)
        {
            y = sqr(gmx_rng_uniform_real(rng));
            if ((ok = gmx_stats_add_point(camel, i, y+1, 0, 0)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
            y = sqr(gmx_rng_uniform_real(rng));
            if ((ok = gmx_stats_add_point(camel, i+0.5, y+2, 0, 0)) != estatsOK)
            {
                fprintf(stderr, "%s\n", gmx_stats_message(ok));
            }
        }
        /* Histogram test */
        if ((ok = gmx_stats_make_histogram(camel, 0, 101, norm, &xh, &yh)) != estatsOK)
        {
            fprintf(stderr, "%s\n", gmx_stats_message(ok));
        }
        sprintf(fn, "histo%d-data.xvg", norm);
        fp = fopen(fn, "w");
        gmx_stats_dump_xy(camel, fp);
        fclose(fp);
        sprintf(fn, "histo%d.xvg", norm);
        fp = fopen(fn, "w");
        for (i = 0; (i < 101); i++)
        {
            fprintf(fp, "%12g  %12g\n", xh[i], yh[i]);
        }
        fclose(fp);
        sfree(xh);
        sfree(yh);
    }
}
예제 #7
0
void maxwell_speed(real tempi,int seed,gmx_mtop_t *mtop, rvec v[])
{
  atom_id *dummy;
  int     i;
  gmx_rng_t rng;
  
  if (seed == -1) {
    seed = make_seed();
    fprintf(stderr,"Using random seed %d for generating velocities\n",seed);
  }
  
  rng = gmx_rng_init(seed);

  low_mspeed(tempi,mtop,v,rng);

  gmx_rng_destroy(rng);
}
예제 #8
0
int gmx_genion(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] randomly replaces solvent molecules with monoatomic ions.",
        "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 or use",
        "the [TT]-p[tt] option to automatically modify the topology.[PAR]",
        "The ion molecule type, residue and atom names in all force fields",
        "are the capitalized element names without sign. This molecule name",
        "should be given with [TT]-pname[tt] or [TT]-nname[tt], and the",
        "[TT][molecules][tt] section of your topology updated accordingly,",
        "either by hand or with [TT]-p[tt]. Do not use an atom name instead!",
        "[PAR]Ions which can have multiple charge states get the multiplicity",
        "added, without sign, for the uncommon states only.[PAR]",
        "For larger ions, e.g. sulfate we recommended using [gmx-insert-molecules]."
    };
    const char        *bugs[] = {
        "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, conc = 0;
    static int         seed     = 1993;
    static gmx_bool    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" },
        { "-seed",  FALSE, etINT,  {&seed},  "Seed for random number generator" },
        { "-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 [REF].tpr[ref] file. Overrides the [TT]-np[tt] and [TT]-nn[tt] options." },
        { "-neutral", FALSE, etBOOL, {&bNeutral}, "This option will add enough ions to neutralize the system. These ions are added on top of those specified with [TT]-np[tt]/[TT]-nn[tt] or [TT]-conc[tt]. "}
    };
    t_topology         top;
    rvec              *x, *v;
    real               vol, qtot;
    matrix             box;
    t_atoms            atoms;
    t_pbc              pbc;
    int               *repl, ePBC;
    atom_id           *index;
    char              *grpname;
    gmx_bool          *bSet;
    int                i, nw, nwa, nsa, nsalt, iqtot;
    gmx_output_env_t  *oenv;
    gmx_rng_t          rng;
    t_filenm           fnm[] = {
        { efTPR, NULL,  NULL,      ffREAD  },
        { efNDX, NULL,  NULL,      ffOPTRD },
        { efSTO, "-o",  NULL,      ffWRITE },
        { efTOP, "-p",  "topol",   ffOPTRW }
    };
#define NFILE asize(fnm)

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

    /* Check input for something sensible */
    if ((p_num < 0) || (n_num < 0))
    {
        gmx_fatal(FARGS, "Negative number of ions to add?");
    }

    if (conc > 0 && (p_num > 0 || n_num > 0))
    {
        fprintf(stderr, "WARNING: -conc specified, overriding -nn and -np.\n");
    }

    /* Read atom positions and charges */
    read_tps_conf(ftp2fn(efTPR, NFILE, fnm), &top, &ePBC, &x, &v, box, FALSE);
    atoms = top.atoms;

    /* Compute total charge */
    qtot = 0;
    for (i = 0; (i < atoms.nr); i++)
    {
        qtot += atoms.atom[i].q;
    }
    iqtot = std::round(qtot);


    if (conc > 0)
    {
        /* Compute number of ions to be added */
        vol   = det(box);
        nsalt = std::round(conc*vol*AVOGADRO/1e24);
        p_num = abs(nsalt*n_q);
        n_num = abs(nsalt*p_q);
    }
    if (bNeutral)
    {
        int qdelta = p_num*p_q + n_num*n_q + iqtot;

        /* Check if the system is neutralizable
         * is (qdelta == p_q*p_num + n_q*n_num) solvable for p_num and n_num? */
        int gcd = gmx_greatest_common_divisor(n_q, p_q);
        if ((qdelta % gcd) != 0)
        {
            gmx_fatal(FARGS, "Can't neutralize this system using -nq %d and"
                      " -pq %d.\n", n_q, p_q);
        }

        while (qdelta != 0)
        {
            while (qdelta < 0)
            {
                p_num++;
                qdelta += p_q;
            }
            while (qdelta > 0)
            {
                n_num++;
                qdelta += n_q;
            }
        }
    }

    if ((p_num == 0) && (n_num == 0))
    {
        fprintf(stderr, "No ions to add, will just copy input configuration.\n");
    }
    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, ePBC, box);

        if (seed == 0)
        {
            rng = gmx_rng_init(gmx_rng_make_seed());
        }
        else
        {
            rng = gmx_rng_init(seed);
        }
        /* Now loop over the ions that have to be placed */
        while (p_num-- > 0)
        {
            insert_ion(nsa, &nw, bSet, repl, index, x, &pbc,
                       1, p_q, p_name, &atoms, rmin, rng);
        }
        while (n_num-- > 0)
        {
            insert_ion(nsa, &nw, bSet, repl, index, x, &pbc,
                       -1, n_q, n_name, &atoms, rmin, rng);
        }
        gmx_rng_destroy(rng);
        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), *top.name, &atoms, x, NULL, ePBC, box);

    return 0;
}
예제 #9
0
// Colvars Initialization
void colvarproxy_gromacs::init(t_inputrec *gmx_inp, gmx_int64_t step) {
  // Initialize colvars.
  first_timestep = true;
  total_force_requested = false;

  // User-scripted forces are not available in GROMACS
  force_script_defined = false;
  have_scripts = false;

  // GROMACS random number generation.
  // Seed with the mdp parameter ld_seed, the Langevin dynamics seed.
  rando = gmx_rng_init(gmx_inp->ld_seed);

  // For expediency, we are using a kludgy input/output structure
  //
  // gmx_inp->userint1 is the colvars state:
  // 0, no colvars
  // 1, colvars without restart
  // 2, colvars with restart (from colvars.state.restart)
  //
  // gmx_inp->userint2 is the config file index
  // the colvars config file is assumed to be called colvars${userint2}.colvars
  // the output files will have the prefix colvars${userint2}
  //
  // gmx_inp->userint3 is the input file index
  // the input state file is assumed to have the prefix colvars${userint3}

  switch(gmx_inp->userint1) {
  case 0:
    gmx_fatal(FARGS,"colvars_potential called for userint1=0\n");
    break;
  case 1:
    colvars_restart = false;
    break;
  case 2:
    colvars_restart = true;
    break;
  default:
    gmx_fatal(FARGS,"userint1 must be 1 (colvars on) or 2 (restarted colvars), not %d\n", gmx_inp->userint1);
    break;
  }
  // Right now the input/output prefixes almost hardcoded (expect for an integer)
  char prefix[256];
  snprintf(prefix,256,"colvars%d",gmx_inp->userint2);
  config_file = std::string(prefix).append(".colvars");
  // Output
  output_prefix_str = std::string(prefix);
  restart_output_prefix_str = std::string(prefix).append(".restart");
  // State file
  if (colvars_restart) {
    char input_state_prefix[256];
    snprintf(input_state_prefix,256,"colvars%d",gmx_inp->userint3);
    input_prefix_str = std::string(input_state_prefix);
  }

  // Get some parameters from GROMACS
  restart_frequency_s = gmx_inp->nstxout;
  timestep = gmx_inp->delta_t;

  // initiate module: this object will be the communication proxy
  colvars = new colvarmodule (this);
  cvm::log("Using GROMACS interface, version "+
	   cvm::to_str(COLVARPROXY_VERSION)+".\n");
  colvars->read_config_file(config_file.c_str());
  colvars->setup_input();
  colvars->setup_output();

  if (step != 0) {
    cvm::log("Initializing step number to "+cvm::to_str(step)+".\n");
    colvars->it = colvars->it_restart = step;
  }

  if (cvm::debug()) {
    cvm::log ("colvars_atoms = "+cvm::to_str (colvars_atoms)+"\n");
    cvm::log ("colvars_atoms_ncopies = "+cvm::to_str (colvars_atoms_ncopies)+"\n");
    cvm::log ("positions = "+cvm::to_str (positions)+"\n");
    cvm::log ("total_forces = "+cvm::to_str (total_forces)+"\n");
    cvm::log ("applied_forces = "+cvm::to_str (applied_forces)+"\n");
    cvm::log (cvm::line_marker);
  }

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

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

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

    rng=gmx_rng_init(seed);

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

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

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
        t0 = MPI_Wtime();
#endif
#endif
    
    if (MASTER(cr)){
                         
        fprintf(stderr, "Calculating reciprocal error part 1 ...");
        
    }

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

                tmp1=eps_poly3(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=info->nkx[0];
                tmp2=iprod(gridp,info->recipbox[XX]);
                
                tmp=tmp1*tmp2;
                
                tmp1=eps_poly3(ny,info->nky[0],info->pme_order[0]);
                tmp1*=info->nky[0];
                tmp2=iprod(gridp,info->recipbox[YY]);
                
                tmp+=tmp1*tmp2;
                
                tmp1=eps_poly3(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=info->nkz[0];
                tmp2=iprod(gridp,info->recipbox[ZZ]);
                
                tmp+=tmp1*tmp2;
                
                tmp*=4.0 * M_PI;
                
                tmp1=eps_poly4(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[XX]);
                tmp1*=info->nkx[0] * info->nkx[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(ny,info->nky[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[YY]);
                tmp1*=info->nky[0] * info->nky[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[ZZ]);
                tmp1*=info->nkz[0] * info->nkz[0];
                
                tmp+=tmp1;
                
                e_rec2+= 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr ;
                
            }
        }
        if (MASTER(cr))
            fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core));
        
    }

    if (MASTER(cr))
        fprintf(stderr, "\n");
    
    /* Use just a fraction of all charges to estimate the self energy error term? */
    bFraction =  (info->fracself > 0.0) && (info->fracself < 1.0);

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

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

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

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

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

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

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

        /* for(nx=startlocal; nx<=stoplocal; nx++)*/
        for(nx=-info->nkx[0]/2; nx<info->nkx[0]/2+1; nx++) 
        {   
            svmul(nx,info->recipbox[XX],gridpx);
            for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++)
            {
                svmul(ny,info->recipbox[YY],tmpvec);
                rvec_add(gridpx,tmpvec,gridpxy);
                for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++)
                {
                    
                    if (  0 == nx && 0 == ny && 0 == nz)
                        continue;
                    
                    svmul(nz,info->recipbox[ZZ],tmpvec);
                    rvec_add(gridpxy,tmpvec,gridp);
                    tmp=norm2(gridp);
                    coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                    coeff/= tmp ;
                    e_rec3x+=coeff*eps_self(nx,info->nkx[0],info->recipbox[XX],info->pme_order[0],x[ci]);
                    e_rec3y+=coeff*eps_self(ny,info->nky[0],info->recipbox[YY],info->pme_order[0],x[ci]);
                    e_rec3z+=coeff*eps_self(nz,info->nkz[0],info->recipbox[ZZ],info->pme_order[0],x[ci]);

                }
            }
        }

        clear_rvec(tmpvec2);

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

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

        }
    }

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

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
    {
        t1= MPI_Wtime() - t0;
        fprintf(fp_out, "Recip. err. est. took   : %lf s\n", t1);
    }
#endif
#endif
   
#ifdef DEBUG
    if (PAR(cr))
    {
        fprintf(stderr, "Node %3d: nx=[%3d...%3d]  e_rec3=%e\n", 
                cr->nodeid, startlocal, stoplocal, e_rec3);
    }
#endif

    if (PAR(cr))
    {
        gmx_sum(1,&e_rec1,cr);
        gmx_sum(1,&e_rec2,cr);
        gmx_sum(1,&e_rec3,cr);
    }
    
    /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ;
       e_rec2*=  q2_all / M_PI / M_PI / info->volume / info->volume / nr ;
       e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ; 
     */
    e_rec=sqrt(e_rec1+e_rec2+e_rec3);
    
    
    return ONE_4PI_EPS0 * e_rec;
}
예제 #11
0
gmx_repl_ex_t init_replica_exchange(FILE *fplog,
                                    const gmx_multisim_t *ms,
                                    const t_state *state,
                                    const t_inputrec *ir,
                                    int nst, int nex, int init_seed)
{
    real                temp, pres;
    int                 i, j, k;
    struct gmx_repl_ex *re;
    gmx_bool            bTemp;
    gmx_bool            bLambda = FALSE;

    fprintf(fplog, "\nInitializing Replica Exchange\n");

    if (ms == NULL || ms->nsim == 1)
    {
        gmx_fatal(FARGS, "Nothing to exchange with only one replica, maybe you forgot to set the -multi option of mdrun?");
    }
    if (!EI_DYNAMICS(ir->eI))
    {
        gmx_fatal(FARGS, "Replica exchange is only supported by dynamical simulations");
        /* Note that PAR(cr) is defined by cr->nnodes > 1, which is
         * distinct from MULTISIM(cr). A multi-simulation only runs
         * with real MPI parallelism, but this does not imply PAR(cr)
         * is true!
         *
         * Since we are using a dynamical integrator, the only
         * decomposition is DD, so PAR(cr) and DOMAINDECOMP(cr) are
         * synonymous. The only way for cr->nnodes > 1 to be true is
         * if we are using DD. */
    }

    snew(re, 1);

    re->repl     = ms->sim;
    re->nrepl    = ms->nsim;
    snew(re->q, ereENDSINGLE);

    fprintf(fplog, "Repl  There are %d replicas:\n", re->nrepl);

    check_multi_int(fplog, ms, state->natoms, "the number of atoms", FALSE);
    check_multi_int(fplog, ms, ir->eI, "the integrator", FALSE);
    check_multi_int64(fplog, ms, ir->init_step+ir->nsteps, "init_step+nsteps", FALSE);
    check_multi_int64(fplog, ms, (ir->init_step+nst-1)/nst,
                      "first exchange step: init_step/-replex", FALSE);
    check_multi_int(fplog, ms, ir->etc, "the temperature coupling", FALSE);
    check_multi_int(fplog, ms, ir->opts.ngtc,
                    "the number of temperature coupling groups", FALSE);
    check_multi_int(fplog, ms, ir->epc, "the pressure coupling", FALSE);
    check_multi_int(fplog, ms, ir->efep, "free energy", FALSE);
    check_multi_int(fplog, ms, ir->fepvals->n_lambda, "number of lambda states", FALSE);

    re->temp = ir->opts.ref_t[0];
    for (i = 1; (i < ir->opts.ngtc); i++)
    {
        if (ir->opts.ref_t[i] != re->temp)
        {
            fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
            fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
        }
    }

    re->type = -1;
    bTemp    = repl_quantity(ms, re, ereTEMP, re->temp);
    if (ir->efep != efepNO)
    {
        bLambda = repl_quantity(ms, re, ereLAMBDA, (real)ir->fepvals->init_fep_state);
    }
    if (re->type == -1)  /* nothing was assigned */
    {
        gmx_fatal(FARGS, "The properties of the %d systems are all the same, there is nothing to exchange", re->nrepl);
    }
    if (bLambda && bTemp)
    {
        re->type = ereTL;
    }

    if (bTemp)
    {
        please_cite(fplog, "Sugita1999a");
        if (ir->epc != epcNO)
        {
            re->bNPT = TRUE;
            fprintf(fplog, "Repl  Using Constant Pressure REMD.\n");
            please_cite(fplog, "Okabe2001a");
        }
        if (ir->etc == etcBERENDSEN)
        {
            gmx_fatal(FARGS, "REMD with the %s thermostat does not produce correct potential energy distributions, consider using the %s thermostat instead",
                      ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE));
        }
    }
    if (bLambda)
    {
        if (ir->fepvals->delta_lambda != 0)   /* check this? */
        {
            gmx_fatal(FARGS, "delta_lambda is not zero");
        }
    }
    if (re->bNPT)
    {
        snew(re->pres, re->nrepl);
        if (ir->epct == epctSURFACETENSION)
        {
            pres = ir->ref_p[ZZ][ZZ];
        }
        else
        {
            pres = 0;
            j    = 0;
            for (i = 0; i < DIM; i++)
            {
                if (ir->compress[i][i] != 0)
                {
                    pres += ir->ref_p[i][i];
                    j++;
                }
            }
            pres /= j;
        }
        re->pres[re->repl] = pres;
        gmx_sum_sim(re->nrepl, re->pres, ms);
    }

    /* Make an index for increasing replica order */
    /* only makes sense if one or the other is varying, not both!
       if both are varying, we trust the order the person gave. */
    snew(re->ind, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        re->ind[i] = i;
    }

    if (re->type < ereENDSINGLE)
    {

        for (i = 0; i < re->nrepl; i++)
        {
            for (j = i+1; j < re->nrepl; j++)
            {
                if (re->q[re->type][re->ind[j]] < re->q[re->type][re->ind[i]])
                {
                    k          = re->ind[i];
                    re->ind[i] = re->ind[j];
                    re->ind[j] = k;
                }
                else if (re->q[re->type][re->ind[j]] == re->q[re->type][re->ind[i]])
                {
                    gmx_fatal(FARGS, "Two replicas have identical %ss", erename[re->type]);
                }
            }
        }
    }

    /* keep track of all the swaps, starting with the initial placement. */
    snew(re->allswaps, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        re->allswaps[i] = re->ind[i];
    }

    switch (re->type)
    {
        case ereTEMP:
            fprintf(fplog, "\nReplica exchange in temperature\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5.1f", re->q[re->type][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            break;
        case ereLAMBDA:
            fprintf(fplog, "\nReplica exchange in lambda\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %3d", (int)re->q[re->type][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            break;
        case ereTL:
            fprintf(fplog, "\nReplica exchange in temperature and lambda state\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5.1f", re->q[ereTEMP][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5d", (int)re->q[ereLAMBDA][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            break;
        default:
            gmx_incons("Unknown replica exchange quantity");
    }
    if (re->bNPT)
    {
        fprintf(fplog, "\nRepl  p");
        for (i = 0; i < re->nrepl; i++)
        {
            fprintf(fplog, " %5.2f", re->pres[re->ind[i]]);
        }

        for (i = 0; i < re->nrepl; i++)
        {
            if ((i > 0) && (re->pres[re->ind[i]] < re->pres[re->ind[i-1]]))
            {
                fprintf(fplog, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
                fprintf(stderr, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
            }
        }
    }
    re->nst = nst;
    if (init_seed == -1)
    {
        if (MASTERSIM(ms))
        {
            re->seed = (int)gmx_rng_make_seed();
        }
        else
        {
            re->seed = 0;
        }
        gmx_sumi_sim(1, &(re->seed), ms);
    }
    else
    {
        re->seed = init_seed;
    }
    fprintf(fplog, "\nReplica exchange interval: %d\n", re->nst);
    fprintf(fplog, "\nReplica random seed: %d\n", re->seed);
    re->rng = gmx_rng_init(re->seed);

    re->nattempt[0] = 0;
    re->nattempt[1] = 0;

    snew(re->prob_sum, re->nrepl);
    snew(re->nexchange, re->nrepl);
    snew(re->nmoves, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->nmoves[i], re->nrepl);
    }
    fprintf(fplog, "Replica exchange information below: x=exchange, pr=probability\n");

    /* generate space for the helper functions so we don't have to snew each time */

    snew(re->destinations, re->nrepl);
    snew(re->incycle, re->nrepl);
    snew(re->tmpswap, re->nrepl);
    snew(re->cyclic, re->nrepl);
    snew(re->order, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->cyclic[i], re->nrepl);
        snew(re->order[i], re->nrepl);
    }
    /* allocate space for the functions storing the data for the replicas */
    /* not all of these arrays needed in all cases, but they don't take
       up much space, since the max size is nrepl**2 */
    snew(re->prob, re->nrepl);
    snew(re->bEx, re->nrepl);
    snew(re->beta, re->nrepl);
    snew(re->Vol, re->nrepl);
    snew(re->Epot, re->nrepl);
    snew(re->de, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->de[i], re->nrepl);
    }
    re->nex = nex;
    return re;
}
예제 #12
0
gmx_radial_distribution_histogram_t *calc_radial_distribution_histogram (
        gmx_sans_t  *gsans,
        rvec        *x,
        matrix       box,
        atom_id     *index,
        int          isize,
        double       binwidth,
        gmx_bool     bMC,
        gmx_bool     bNORM,
        real         mcover,
        unsigned int seed)
{
    gmx_radial_distribution_histogram_t    *pr = NULL;
    rvec              dist;
    double            rmax;
    int               i, j;
#ifdef GMX_OPENMP
    double          **tgr;
    int               tid;
    int               nthreads;
    gmx_rng_t        *trng = NULL;
#endif
    gmx_large_int_t   mc  = 0, max;
    gmx_rng_t         rng = NULL;

    /* allocate memory for pr */
    snew(pr, 1);
    /* set some fields */
    pr->binwidth = binwidth;

    /*
     * create max dist rvec
     * dist = box[xx] + box[yy] + box[zz]
     */
    rvec_add(box[XX], box[YY], dist);
    rvec_add(box[ZZ], dist, dist);

    rmax = norm(dist);

    pr->grn = (int)floor(rmax/pr->binwidth)+1;
    rmax    = pr->grn*pr->binwidth;

    snew(pr->gr, pr->grn);

    if (bMC)
    {
        /* Special case for setting automaticaly number of mc iterations to 1% of total number of direct iterations */
        if (mcover == -1)
        {
            max = (gmx_large_int_t)floor(0.5*0.01*isize*(isize-1));
        }
        else
        {
            max = (gmx_large_int_t)floor(0.5*mcover*isize*(isize-1));
        }
        rng = gmx_rng_init(seed);
#ifdef GMX_OPENMP
        nthreads = gmx_omp_get_max_threads();
        snew(tgr, nthreads);
        snew(trng, nthreads);
        for (i = 0; i < nthreads; i++)
        {
            snew(tgr[i], pr->grn);
            trng[i] = gmx_rng_init(gmx_rng_uniform_uint32(rng));
        }
        #pragma omp parallel shared(tgr,trng,mc) private(tid,i,j)
        {
            tid = gmx_omp_get_thread_num();
            /* now starting parallel threads */
            #pragma omp for
            for (mc = 0; mc < max; mc++)
            {
                i = (int)floor(gmx_rng_uniform_real(trng[tid])*isize);
                j = (int)floor(gmx_rng_uniform_real(trng[tid])*isize);
                if (i != j)
                {
                    tgr[tid][(int)floor(sqrt(distance2(x[index[i]], x[index[j]]))/binwidth)] += gsans->slength[index[i]]*gsans->slength[index[j]];
                }
            }
        }
        /* collecting data from threads */
        for (i = 0; i < pr->grn; i++)
        {
            for (j = 0; j < nthreads; j++)
            {
                pr->gr[i] += tgr[j][i];
            }
        }
        /* freeing memory for tgr and destroying trng */
        for (i = 0; i < nthreads; i++)
        {
            sfree(tgr[i]);
            gmx_rng_destroy(trng[i]);
        }
        sfree(tgr);
        sfree(trng);
#else
        for (mc = 0; mc < max; mc++)
        {
            i = (int)floor(gmx_rng_uniform_real(rng)*isize);
            j = (int)floor(gmx_rng_uniform_real(rng)*isize);
            if (i != j)
            {
                pr->gr[(int)floor(sqrt(distance2(x[index[i]], x[index[j]]))/binwidth)] += gsans->slength[index[i]]*gsans->slength[index[j]];
            }
        }
#endif
        gmx_rng_destroy(rng);
    }
    else
    {
#ifdef GMX_OPENMP
        nthreads = gmx_omp_get_max_threads();
        /* Allocating memory for tgr arrays */
        snew(tgr, nthreads);
        for (i = 0; i < nthreads; i++)
        {
            snew(tgr[i], pr->grn);
        }
        #pragma omp parallel shared(tgr) private(tid,i,j)
        {
            tid = gmx_omp_get_thread_num();
            /* starting parallel threads */
            #pragma omp for
            for (i = 0; i < isize; i++)
            {
                for (j = 0; j < i; j++)
                {
                    tgr[tid][(int)floor(sqrt(distance2(x[index[i]], x[index[j]]))/binwidth)] += gsans->slength[index[i]]*gsans->slength[index[j]];
                }
            }
        }
        /* collecating data for pr->gr */
        for (i = 0; i < pr->grn; i++)
        {
            for (j = 0; j < nthreads; j++)
            {
                pr->gr[i] += tgr[j][i];
            }
        }
        /* freeing memory for tgr */
        for (i = 0; i < nthreads; i++)
        {
            sfree(tgr[i]);
        }
        sfree(tgr);
#else
        for (i = 0; i < isize; i++)
        {
            for (j = 0; j < i; j++)
            {
                pr->gr[(int)floor(sqrt(distance2(x[index[i]], x[index[j]]))/binwidth)] += gsans->slength[index[i]]*gsans->slength[index[j]];
            }
        }
#endif
    }

    /* normalize if needed */
    if (bNORM)
    {
        normalize_probability(pr->grn, pr->gr);
    }

    snew(pr->r, pr->grn);
    for (i = 0; i < pr->grn; i++)
    {
        pr->r[i] = (pr->binwidth*i+pr->binwidth*0.5);
    }

    return (gmx_radial_distribution_histogram_t *) pr;
}
예제 #13
0
int gmx_nmens(int argc, char *argv[])
{
    const char *desc[] = {
        "[THISMODULE] generates an ensemble around an average structure",
        "in a subspace that is defined by a set of normal modes (eigenvectors).",
        "The eigenvectors are assumed to be mass-weighted.",
        "The position along each eigenvector is randomly taken from a Gaussian",
        "distribution with variance kT/eigenvalue.[PAR]",
        "By default the starting eigenvector is set to 7, since the first six",
        "normal modes are the translational and rotational degrees of freedom."
    };
    static int  nstruct = 100, first = 7, last = -1, seed = -1;
    static real temp    = 300.0;
    t_pargs     pa[]    = {
        { "-temp",  FALSE, etREAL, {&temp},
          "Temperature in Kelvin" },
        { "-seed", FALSE, etINT, {&seed},
          "Random seed, -1 generates a seed from time and pid" },
        { "-num", FALSE, etINT, {&nstruct},
          "Number of structures to generate" },
        { "-first", FALSE, etINT, {&first},
          "First eigenvector to use (-1 is select)" },
        { "-last",  FALSE, etINT, {&last},
          "Last eigenvector to use (-1 is till the last)" }
    };
#define NPA asize(pa)

    t_trxstatus        *out;
    int                 status, trjout;
    t_topology          top;
    int                 ePBC;
    t_atoms            *atoms;
    rvec               *xtop, *xref, *xav, *xout1, *xout2;
    gmx_bool            bDMR, bDMA, bFit;
    int                 nvec, *eignr = NULL;
    rvec              **eigvec = NULL;
    matrix              box;
    real               *eigval, totmass, *invsqrtm, t, disp;
    int                 natoms, neigval;
    char               *grpname, title[STRLEN];
    const char         *indexfile;
    int                 i, j, d, s, v;
    int                 nout, *iout, noutvec, *outvec;
    atom_id            *index;
    real                rfac, invfr, rhalf, jr;
    int          *      eigvalnr;
    output_env_t        oenv;
    gmx_rng_t           rng;
    unsigned long       jran;
    const unsigned long im = 0xffff;
    const unsigned long ia = 1093;
    const unsigned long ic = 18257;


    t_filenm fnm[] = {
        { efTRN, "-v",    "eigenvec",    ffREAD  },
        { efXVG, "-e",    "eigenval",    ffREAD  },
        { efTPS, NULL,    NULL,          ffREAD },
        { efNDX, NULL,    NULL,          ffOPTRD },
        { efTRO, "-o",    "ensemble",    ffWRITE }
    };
#define NFILE asize(fnm)

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

    indexfile = ftp2fn_null(efNDX, NFILE, fnm);

    read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit,
                      &xref, &bDMR, &xav, &bDMA, &nvec, &eignr, &eigvec, &eigval);

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, box, bDMA);
    atoms = &top.atoms;

    printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n", natoms);
    get_index(atoms, indexfile, 1, &i, &index, &grpname);
    if (i != natoms)
    {
        gmx_fatal(FARGS, "you selected a group with %d elements instead of %d",
                  i, natoms);
    }
    printf("\n");

    snew(invsqrtm, natoms);
    if (bDMA)
    {
        for (i = 0; (i < natoms); i++)
        {
            invsqrtm[i] = gmx_invsqrt(atoms->atom[index[i]].m);
        }
    }
    else
    {
        for (i = 0; (i < natoms); i++)
        {
            invsqrtm[i] = 1.0;
        }
    }

    if (last == -1)
    {
        last = natoms*DIM;
    }
    if (first > -1)
    {
        /* make an index from first to last */
        nout = last-first+1;
        snew(iout, nout);
        for (i = 0; i < nout; i++)
        {
            iout[i] = first-1+i;
        }
    }
    else
    {
        printf("Select eigenvectors for output, end your selection with 0\n");
        nout = -1;
        iout = NULL;
        do
        {
            nout++;
            srenew(iout, nout+1);
            if (1 != scanf("%d", &iout[nout]))
            {
                gmx_fatal(FARGS, "Error reading user input");
            }
            iout[nout]--;
        }
        while (iout[nout] >= 0);
        printf("\n");
    }

    /* make an index of the eigenvectors which are present */
    snew(outvec, nout);
    noutvec = 0;
    for (i = 0; i < nout; i++)
    {
        j = 0;
        while ((j < nvec) && (eignr[j] != iout[i]))
        {
            j++;
        }
        if ((j < nvec) && (eignr[j] == iout[i]))
        {
            outvec[noutvec] = j;
            iout[noutvec]   = iout[i];
            noutvec++;
        }
    }

    fprintf(stderr, "%d eigenvectors selected for output\n", noutvec);

    if (seed == -1)
    {
        seed = (int)gmx_rng_make_seed();
        rng  = gmx_rng_init(seed);
    }
    else
    {
        rng = gmx_rng_init(seed);
    }
    fprintf(stderr, "Using seed %d and a temperature of %g K\n", seed, temp);

    snew(xout1, natoms);
    snew(xout2, atoms->nr);
    out  = open_trx(ftp2fn(efTRO, NFILE, fnm), "w");
    jran = (unsigned long)((real)im*gmx_rng_uniform_real(rng));
    gmx_rng_destroy(rng);
    for (s = 0; s < nstruct; s++)
    {
        for (i = 0; i < natoms; i++)
        {
            copy_rvec(xav[i], xout1[i]);
        }
        for (j = 0; j < noutvec; j++)
        {
            v = outvec[j];
            /* (r-0.5) n times:  var_n = n * var_1 = n/12
               n=4:  var_n = 1/3, so multiply with 3 */

            rfac  = sqrt(3.0 * BOLTZ*temp/eigval[iout[j]]);
            rhalf = 2.0*rfac;
            rfac  = rfac/(real)im;

            jran = (jran*ia+ic) & im;
            jr   = (real)jran;
            jran = (jran*ia+ic) & im;
            jr  += (real)jran;
            jran = (jran*ia+ic) & im;
            jr  += (real)jran;
            jran = (jran*ia+ic) & im;
            jr  += (real)jran;
            disp = rfac * jr - rhalf;

            for (i = 0; i < natoms; i++)
            {
                for (d = 0; d < DIM; d++)
                {
                    xout1[i][d] += disp*eigvec[v][i][d]*invsqrtm[i];
                }
            }
        }
        for (i = 0; i < natoms; i++)
        {
            copy_rvec(xout1[i], xout2[index[i]]);
        }
        t = s+1;
        write_trx(out, natoms, index, atoms, 0, t, box, xout2, NULL, NULL);
        fprintf(stderr, "\rGenerated %d structures", s+1);
    }
    fprintf(stderr, "\n");
    close_trx(out);

    return 0;
}
예제 #14
0
static void insert_mols(int nmol_insrt, int ntry, int seed,
                        t_atoms *atoms, rvec **x, real **exclusionDistances,
                        t_atoms *atoms_insrt, rvec *x_insrt, real *exclusionDistances_insrt,
                        int ePBC, matrix box,
                        const char* posfn, const rvec deltaR, int enum_rot)
{
    t_pbc            pbc;
    rvec            *x_n;
    int              mol;
    int              trial;
    double         **rpos;

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

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

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

    snew(x_n, atoms_insrt->nr);

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

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

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

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

    sfree(x_n);
}
예제 #15
0
/* Estimate the reciprocal space part error of the SPME Ewald sum. */
static real estimate_reciprocal(
        t_inputinfo *info, 
        rvec x[],           /* array of particles */
        real q[],           /* array of charges */
        int nr,             /* number of charges = size of the charge array */
        FILE *fp_out,
        t_commrec *cr)
{
    real e_rec=0;   /* reciprocal error estimate */
    real e_rec1=0;  /* Error estimate term 1*/
    real e_rec2=0;  /* Error estimate term 2*/
    real e_rec3=0;  /* Error estimate term 3 */
    real e_rec3x=0; /* part of Error estimate term 3 in x */
    real e_rec3y=0; /* part of Error estimate term 3 in y */
    real e_rec3z=0; /* part of Error estimate term 3 in z */
    int i,ci;
    int nx,ny,nz;   /* grid coordinates */
    real q2_all=0;  /* sum of squared charges */
    rvec gridpx;    /* reciprocal grid point in x direction*/
    rvec gridpxy;   /* reciprocal grid point in x and y direction*/
    rvec gridp;     /* complete reciprocal grid point in 3 directions*/
    rvec tmpvec;    /* template to create points from basis vectors */
    rvec tmpvec2;   /* template to create points from basis vectors */
    real coeff=0;   /* variable to compute coefficients of the error estimate */
    real coeff2=0;   /* variable to compute coefficients of the error estimate */
    real tmp=0;     /* variables to compute different factors from vectors */
    real tmp1=0;
    real tmp2=0;
    real xtmp=0;
    real ytmp=0;
    real ztmp=0;
    double ewald_error;
    
    /* Random number generator */
    
    gmx_rng_t rng=NULL;
    /*rng=gmx_rng_init(gmx_rng_make_seed());  */

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

/* #define TAKETIME */
#ifdef TAKETIME
    double t0=0.0;
    double t1=0.0;
    double t2=0.0;
#endif

    rng=gmx_rng_init(cr->nodeid);

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

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

#ifdef TAKETIME
    if (MASTER(cr))
        t0 = MPI_Wtime();
#endif
    
    if (MASTER(cr)){
                         
        fprintf(stderr, "Calculating reciprocal error part 1 ...");
        
    }

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

                tmp1=eps_poly3(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=info->nkx[0];
                tmp2=iprod(gridp,info->recipbox[XX]);
                
                tmp=tmp1*tmp2;
                
                tmp1=eps_poly3(ny,info->nky[0],info->pme_order[0]);
                tmp1*=info->nky[0];
                tmp2=iprod(gridp,info->recipbox[YY]);
                
                tmp+=tmp1*tmp2;
                
                tmp1=eps_poly3(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=info->nkz[0];
                tmp2=iprod(gridp,info->recipbox[ZZ]);
                
                tmp+=tmp1*tmp2;
                
                tmp*=4.0 * M_PI;
                
                tmp1=eps_poly4(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[XX]);
                tmp1*=info->nkx[0] * info->nkx[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(ny,info->nky[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[YY]);
                tmp1*=info->nky[0] * info->nky[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[ZZ]);
                tmp1*=info->nkz[0] * info->nkz[0];
                
                tmp+=tmp1;
                
                e_rec2+= 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr ;
                
            }
        }
        if (MASTER(cr))
            fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core));
        
    }

/* 
#ifdef GMX_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
*/

    if (MASTER(cr))
        fprintf(stderr, "\n");
    if (info->fracself>0)
    {
        nrsamples=ceil(info->fracself*nr);
    }
    else
    {
        nrsamples=nr;
    }
    
    
    xtot=nrsamples;


    startglobal=0;
    stopglobal=nr;

    if(PAR(cr))
    {
        x_per_core=ceil(xtot/cr->nnodes);
        startlocal=startglobal+x_per_core*cr->nodeid;
        stoplocal=startglobal+x_per_core*(cr->nodeid+1);
        if (stoplocal>stopglobal)
            stoplocal=stopglobal;
    }
    else
    {
        startlocal=startglobal;
        stoplocal=stopglobal;
        x_per_core=xtot;
    }



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

        if (info->fracself<0) {
            ci=i;
        }else {
            ci=floor(gmx_rng_uniform_real(rng) * nr );
            if (ci==nr)
            {
                ci=nr-1;
            }
        }

        /* for(nx=startlocal; nx<=stoplocal; nx++)*/
        for(nx=-info->nkx[0]/2; nx<info->nkx[0]/2+1; nx++) 
        {   
            svmul(nx,info->recipbox[XX],gridpx);
            for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++)
            {
                svmul(ny,info->recipbox[YY],tmpvec);
                rvec_add(gridpx,tmpvec,gridpxy);
                for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++)
                {
                    
                    if (  0 == nx && 0 == ny && 0 == nz)
                        continue;
                    
                    svmul(nz,info->recipbox[ZZ],tmpvec);
                    rvec_add(gridpxy,tmpvec,gridp);
                    tmp=norm2(gridp);
                    coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                    coeff/= tmp ;
                    e_rec3x+=coeff*eps_self(nx,info->nkx[0],info->recipbox[XX],info->pme_order[0],x[ci]);
                    e_rec3y+=coeff*eps_self(ny,info->nky[0],info->recipbox[YY],info->pme_order[0],x[ci]);
                    e_rec3z+=coeff*eps_self(nz,info->nkz[0],info->recipbox[ZZ],info->pme_order[0],x[ci]);

                }
            }
        }

        clear_rvec(tmpvec2);

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

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

        }
       
    }

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


#ifdef TAKETIME
    if (MASTER(cr))
    {
        t1= MPI_Wtime() - t0;
        fprintf(fp_out, "Recip. err. est. took   : %lf s\n", t1);
    }
#endif
   
#ifdef DEBUG
    if (PAR(cr))
    {
        fprintf(stderr, "Node %3d: nx=[%3d...%3d]  e_rec3=%e\n", 
                cr->nodeid, startlocal, stoplocal, e_rec3);
    }
#endif
   

/*
#ifdef GMX_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
  */ 

#ifdef TAKETIME
    if (MASTER(cr))
    {
        t2= MPI_Wtime() - t0;
        fprintf(fp_out, "barrier   : %lf s\n", t2-t1);
    }
#endif

    if (PAR(cr))
    {
        gmx_sum(1,&e_rec1,cr);
        gmx_sum(1,&e_rec2,cr);
        gmx_sum(1,&e_rec3,cr);
    }
    
#ifdef TAKETIME
    if (MASTER(cr))
        fprintf(fp_out, "final reduce : %lf s\n", MPI_Wtime() - t0-t2);
#endif
    /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ;
       e_rec2*=  q2_all / M_PI / M_PI / info->volume / info->volume / nr ;
       e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ; 
     */
    e_rec=sqrt(e_rec1+e_rec2+e_rec3);
    
    
    return ONE_4PI_EPS0 * e_rec;
}
예제 #16
0
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);
    }
}
예제 #17
0
int gmx_genconf(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] multiplies a given coordinate file by simply stacking them",
        "on top of each other, like a small child playing with wooden blocks.",
        "The program makes a grid of [IT]user-defined[it]",
        "proportions ([TT]-nbox[tt]), ",
        "and interspaces the grid point with an extra space [TT]-dist[tt].[PAR]",
        "When option [TT]-rot[tt] is used the program does not check for overlap",
        "between molecules on grid points. It is recommended to make the box in",
        "the input file at least as big as the coordinates + ",
        "van der Waals radius.[PAR]",
        "If the optional trajectory file is given, conformations are not",
        "generated, but read from this file and translated appropriately to",
        "build the grid."

    };
    const char       *bugs[] = {
        "The program should allow for random displacement of lattice points."
    };

    int               vol;
    t_atoms          *atoms;      /* list with all atoms */
    rvec             *x, *xx, *v; /* coordinates? */
    real              t;
    vec4             *xrot, *vrot;
    int               ePBC;
    matrix            box, boxx; /* box length matrix */
    rvec              shift;
    int               natoms;    /* number of atoms in one molecule  */
    int               nres;      /* number of molecules? */
    int               i, j, k, l, m, ndx, nrdx, nx, ny, nz;
    t_trxstatus      *status;
    gmx_bool          bTRX;
    gmx_output_env_t *oenv;
    gmx_rng_t         rng;

    t_filenm          fnm[] = {
        { efSTX, "-f", "conf", ffREAD  },
        { efSTO, "-o", "out",  ffWRITE },
        { efTRX, "-trj", NULL,  ffOPTRD }
    };
#define NFILE asize(fnm)
    static rvec       nrbox    = {1, 1, 1};
    static int        seed     = 0;  /* seed for random number generator */
    static int        nmolat   = 3;
    static int        nblock   = 1;
    static gmx_bool   bShuffle = FALSE;
    static gmx_bool   bSort    = FALSE;
    static gmx_bool   bRandom  = FALSE;           /* False: no random rotations */
    static gmx_bool   bRenum   = TRUE;            /* renumber residues */
    static rvec       dist     = {0, 0, 0};       /* space added between molecules ? */
    static rvec       max_rot  = {180, 180, 180}; /* maximum rotation */
    t_pargs           pa[]     = {
        { "-nbox",   FALSE, etRVEC, {nrbox},   "Number of boxes" },
        { "-dist",   FALSE, etRVEC, {dist},    "Distance between boxes" },
        { "-seed",   FALSE, etINT,  {&seed},
          "Random generator seed, if 0 generated from the time" },
        { "-rot",    FALSE, etBOOL, {&bRandom}, "Randomly rotate conformations" },
        { "-shuffle", FALSE, etBOOL, {&bShuffle}, "Random shuffling of molecules" },
        { "-sort",   FALSE, etBOOL, {&bSort},   "Sort molecules on X coord" },
        { "-block",  FALSE, etINT,  {&nblock},
          "Divide the box in blocks on this number of cpus" },
        { "-nmolat", FALSE, etINT,  {&nmolat},
          "Number of atoms per molecule, assumed to start from 0. "
          "If you set this wrong, it will screw up your system!" },
        { "-maxrot", FALSE, etRVEC, {max_rot}, "Maximum random rotation" },
        { "-renumber", FALSE, etBOOL, {&bRenum},  "Renumber residues" }
    };

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

    if (seed == 0)
    {
        rng = gmx_rng_init(gmx_rng_make_seed());
    }
    else
    {
        rng = gmx_rng_init(seed);
    }

    bTRX = ftp2bSet(efTRX, NFILE, fnm);
    nx   = (int)(nrbox[XX]+0.5);
    ny   = (int)(nrbox[YY]+0.5);
    nz   = (int)(nrbox[ZZ]+0.5);

    if ((nx <= 0) || (ny <= 0) || (nz <= 0))
    {
        gmx_fatal(FARGS, "Number of boxes (-nbox) should be larger than zero");
    }
    if ((nmolat <= 0) && bShuffle)
    {
        gmx_fatal(FARGS, "Can not shuffle if the molecules only have %d atoms",
                  nmolat);
    }

    vol = nx*ny*nz; /* calculate volume in grid points (= nr. molecules) */

    t_topology *top;
    snew(top, 1);
    atoms = &top->atoms;
    read_tps_conf(opt2fn("-f", NFILE, fnm), top, &ePBC, &x, &v, box, FALSE);
    natoms = atoms->nr;
    nres   = atoms->nres;          /* nr of residues in one element? */
    /* make space for all the atoms */
    add_t_atoms(atoms, natoms*(vol-1), nres*(vol-1));
    srenew(x, natoms*vol);         /* get space for coordinates of all atoms */
    srenew(v, natoms*vol);         /* velocities. not really needed? */
    snew(xrot, natoms);            /* get space for rotation matrix? */
    snew(vrot, natoms);

    if (bTRX)
    {
        if (!read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &xx, boxx))
        {
            gmx_fatal(FARGS, "No atoms in trajectory %s", ftp2fn(efTRX, NFILE, fnm));
        }
    }
    else
    {
        snew(xx, natoms);
        for (i = 0; i < natoms; i++)
        {
            copy_rvec(x[i], xx[i]);
        }
    }


    for (k = 0; (k < nz); k++)     /* loop over all gridpositions    */
    {
        shift[ZZ] = k*(dist[ZZ]+box[ZZ][ZZ]);

        for (j = 0; (j < ny); j++)
        {
            shift[YY] = j*(dist[YY]+box[YY][YY])+k*box[ZZ][YY];

            for (i = 0; (i < nx); i++)
            {
                shift[XX] = i*(dist[XX]+box[XX][XX])+j*box[YY][XX]+k*box[ZZ][XX];

                ndx  = (i*ny*nz+j*nz+k)*natoms;
                nrdx = (i*ny*nz+j*nz+k)*nres;

                /* Random rotation on input coords */
                if (bRandom)
                {
                    rand_rot(natoms, xx, v, xrot, vrot, rng, max_rot);
                }

                for (l = 0; (l < natoms); l++)
                {
                    for (m = 0; (m < DIM); m++)
                    {
                        if (bRandom)
                        {
                            x[ndx+l][m] = xrot[l][m];
                            v[ndx+l][m] = vrot[l][m];
                        }
                        else
                        {
                            x[ndx+l][m] = xx[l][m];
                            v[ndx+l][m] = v[l][m];
                        }
                    }
                    if (ePBC == epbcSCREW && i % 2 == 1)
                    {
                        /* Rotate around x axis */
                        for (m = YY; m <= ZZ; m++)
                        {
                            x[ndx+l][m] = box[YY][m] + box[ZZ][m] - x[ndx+l][m];
                            v[ndx+l][m] = -v[ndx+l][m];
                        }
                    }
                    for (m = 0; (m < DIM); m++)
                    {
                        x[ndx+l][m] += shift[m];
                    }
                    atoms->atom[ndx+l].resind = nrdx + atoms->atom[l].resind;
                    atoms->atomname[ndx+l]    = atoms->atomname[l];
                }

                for (l = 0; (l < nres); l++)
                {
                    atoms->resinfo[nrdx+l] = atoms->resinfo[l];
                    if (bRenum)
                    {
                        atoms->resinfo[nrdx+l].nr += nrdx;
                    }
                }
                if (bTRX)
                {
                    if (!read_next_x(oenv, status, &t, xx, boxx) &&
                        ((i+1)*(j+1)*(k+1) < vol))
                    {
                        gmx_fatal(FARGS, "Not enough frames in trajectory");
                    }
                }
            }
        }
    }
    if (bTRX)
    {
        close_trj(status);
    }

    /* make box bigger */
    for (m = 0; (m < DIM); m++)
    {
        box[m][m] += dist[m];
    }
    svmul(nx, box[XX], box[XX]);
    svmul(ny, box[YY], box[YY]);
    svmul(nz, box[ZZ], box[ZZ]);
    if (ePBC == epbcSCREW && nx % 2 == 0)
    {
        /* With an even number of boxes in x we can forgot about the screw */
        ePBC = epbcXYZ;
    }

    /* move_x(natoms*vol,x,box); */          /* put atoms in box? */

    atoms->nr   *= vol;
    atoms->nres *= vol;

    /*depending on how you look at it, this is either a nasty hack or the way it should work*/
    if (bRenum)
    {
        for (i = 0; i < atoms->nres; i++)
        {
            atoms->resinfo[i].nr = i+1;
        }
    }


    if (bShuffle)
    {
        randwater(0, atoms->nr/nmolat, nmolat, x, v, rng);
    }
    else if (bSort)
    {
        sortwater(0, atoms->nr/nmolat, nmolat, x, v);
    }
    else if (opt2parg_bSet("-block", asize(pa), pa))
    {
        mkcompact(0, atoms->nr/nmolat, nmolat, x, v, nblock, box);
    }
    gmx_rng_destroy(rng);

    write_sto_conf(opt2fn("-o", NFILE, fnm), *top->name, atoms, x, v, ePBC, box);

    return 0;
}
예제 #18
0
파일: tpi.c 프로젝트: TTarenzi/MMCG-HAdResS
double do_tpi(FILE *fplog,t_commrec *cr,
              int nfile, const t_filenm fnm[],
              const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
              int nstglobalcomm,
              gmx_vsite_t *vsite,gmx_constr_t constr,
              int stepout,
              t_inputrec *inputrec,
              gmx_mtop_t *top_global,t_fcdata *fcd,
              t_state *state,
              t_mdatoms *mdatoms,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,
              t_forcerec *fr,
              int repl_ex_nst,int repl_ex_seed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
              unsigned long Flags,
              gmx_runtime_t *runtime)
{
  const char *TPI="Test Particle Insertion"; 
  gmx_localtop_t *top;
  gmx_groups_t *groups;
  gmx_enerdata_t *enerd;
  rvec   *f;
  real   lambda,t,temp,beta,drmax,epot;
  double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
  t_trxstatus   *status;
  t_trxframe rerun_fr;
  gmx_bool   bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
  tensor force_vir,shake_vir,vir,pres;
  int    cg_tp,a_tp0,a_tp1,ngid,gid_tp,nener,e;
  rvec   *x_mol;
  rvec   mu_tot,x_init,dx,x_tp;
  int    nnodes,frame,nsteps,step;
  int    i,start,end;
  gmx_rng_t tpi_rand;
  FILE   *fp_tpi=NULL;
  char   *ptr,*dump_pdb,**leg,str[STRLEN],str2[STRLEN];
  double dbl,dump_ener;
  gmx_bool   bCavity;
  int    nat_cavity=0,d;
  real   *mass_cavity=NULL,mass_tot;
  int    nbin;
  double invbinw,*bin,refvolshift,logV,bUlogV;
  real dvdl,prescorr,enercorr,dvdlcorr;
  gmx_bool bEnergyOutOfBounds;
  const char *tpid_leg[2]={"direct","reweighted"};

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

  nnodes = cr->nnodes;

  top = gmx_mtop_generate_local_top(top_global,inputrec);

  groups = &top_global->groups;

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

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

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

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

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

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

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

  /* Print to log file  */
  runtime_start(runtime);
  print_date_and_time(fplog,cr->nodeid,
                      "Started Test Particle Insertion",runtime); 
  wallcycle_start(wcycle,ewcRUN);

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

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

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

  if (fplog) {
    fprintf(fplog,"\nWill insert %d atoms %s partial charges\n",
	    a_tp1-a_tp0,bCharge ? "with" : "without");
    
    fprintf(fplog,"\nWill insert %d times in each frame of %s\n",
	    nsteps,opt2fn("-rerun",nfile,fnm));
  }
  
    if (!bCavity)
    {
        if (inputrec->nstlist > 1)
        {
            if (drmax==0 && a_tp1-a_tp0==1)
            {
                gmx_fatal(FARGS,"Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense",inputrec->nstlist,drmax);
            }
            if (fplog)
            {
                fprintf(fplog,"Will use the same neighborlist for %d insertions in a sphere of radius %f\n",inputrec->nstlist,drmax);
            }
        }
    }
    else
    {
        if (fplog)
        {
            fprintf(fplog,"Will insert randomly in a sphere of radius %f around the center of the cavity\n",drmax);
        }
    }

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

  /* Initialize random generator */
  tpi_rand = gmx_rng_init(inputrec->ld_seed);

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

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

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

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

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

#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
    /* Make sure we don't detect SSE overflow generated before this point */
    gmx_mm_check_and_reset_overflow();
#endif

    while (bNotLastFrame)
    {
        lambda = rerun_fr.lambda;
        t = rerun_fr.time;
        
        sum_embU = 0;
        for(e=0; e<nener; e++)
        {
            sum_UgembU[e] = 0;
        }
        
        /* Copy the coordinates from the input trajectory */
        for(i=0; i<rerun_fr.natoms; i++)
        {
            copy_rvec(rerun_fr.x[i],state->x[i]);
        }
        
        V = det(rerun_fr.box);
        logV = log(V);
        
        bStateChanged = TRUE;
        bNS = TRUE;
        for(step=0; step<nsteps; step++)
        {
            /* In parallel all nodes generate all random configurations.
             * In that way the result is identical to a single cpu tpi run.
             */
            if (!bCavity)
            {
                /* Random insertion in the whole volume */
                bNS = (step % inputrec->nstlist == 0);
                if (bNS)
                {
                    /* Generate a random position in the box */
                    x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX];
                    x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY];
                    x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ];
                }
                if (inputrec->nstlist == 1)
                {
                    copy_rvec(x_init,x_tp);
                }
                else
                {
                    /* Generate coordinates within |dx|=drmax of x_init */
                    do
                    {
                        dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                        dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                        dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    }
                    while (norm2(dx) > drmax*drmax);
                    rvec_add(x_init,dx,x_tp);
                }
            }
            else
            {
                /* Random insertion around a cavity location
                 * given by the last coordinate of the trajectory.
                 */
                if (step == 0)
                {
                    if (nat_cavity == 1)
                    {
                        /* Copy the location of the cavity */
                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1],x_init);
                    }
                    else
                    {
                        /* Determine the center of mass of the last molecule */
                        clear_rvec(x_init);
                        mass_tot = 0;
                        for(i=0; i<nat_cavity; i++)
                        {
                            for(d=0; d<DIM; d++)
                            {
                                x_init[d] +=
                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
                            }
                            mass_tot += mass_cavity[i];
                        }
                        for(d=0; d<DIM; d++)
                        {
                            x_init[d] /= mass_tot;
                        }
                    }
                }
                /* Generate coordinates within |dx|=drmax of x_init */
                do
                {
                    dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                }
                while (norm2(dx) > drmax*drmax);
                rvec_add(x_init,dx,x_tp);
            }
            
            if (a_tp1 - a_tp0 == 1)
            {
                /* Insert a single atom, just copy the insertion location */
	copy_rvec(x_tp,state->x[a_tp0]);
            }
            else
            {
                /* Copy the coordinates from the top file */
                for(i=a_tp0; i<a_tp1; i++)
                {
                    copy_rvec(x_mol[i-a_tp0],state->x[i]);
                }
                /* Rotate the molecule randomly */
                rotate_conf(a_tp1-a_tp0,state->x+a_tp0,NULL,
                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
                            2*M_PI*gmx_rng_uniform_real(tpi_rand));
                /* Shift to the insertion location */
                for(i=a_tp0; i<a_tp1; i++)
                {
                    rvec_inc(state->x[i],x_tp);
                }
            }
            
            /* Check if this insertion belongs to this node */
            bOurStep = TRUE;
            if (PAR(cr))
            {
                switch (inputrec->eI)
                {
                case eiTPI:
                    bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid);
                    break;
                case eiTPIC:
                    bOurStep = (step % nnodes == cr->nodeid);
                    break;
                default:
                    gmx_fatal(FARGS,"Unknown integrator %s",ei_names[inputrec->eI]);
                }
            }
            if (bOurStep)
            {
                /* Clear some matrix variables  */
                clear_mat(force_vir); 
                clear_mat(shake_vir);
                clear_mat(vir);
                clear_mat(pres);
                
                /* Set the charge group center of mass of the test particle */
                copy_rvec(x_init,fr->cg_cm[top->cgs.nr-1]);
                
                /* Calc energy (no forces) on new positions.
                 * Since we only need the intermolecular energy
                 * and the RF exclusion terms of the inserted molecule occur
                 * within a single charge group we can pass NULL for the graph.
                 * This also avoids shifts that would move charge groups
                 * out of the box.
                 *
                 * Some checks above ensure than we can not have
                 * twin-range interactions together with nstlist > 1,
                 * therefore we do not need to remember the LR energies.
                 */
                /* Make do_force do a single node force calculation */
                cr->nnodes = 1;
                do_force(fplog,cr,inputrec,
                         step,nrnb,wcycle,top,top_global,&top_global->groups,
                         rerun_fr.box,state->x,&state->hist,
                         f,force_vir,mdatoms,enerd,fcd,
                         lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
                         GMX_FORCE_NONBONDED |
                         (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) |
                         (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); 
                cr->nnodes = nnodes;
                bStateChanged = FALSE;
                bNS = FALSE;
                
                /* Calculate long range corrections to pressure and energy */
                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box,
                              lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr);
                /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
                enerd->term[F_DISPCORR] = enercorr;
                enerd->term[F_EPOT] += enercorr;
                enerd->term[F_PRES] += prescorr;
                enerd->term[F_DVDL] += dvdlcorr;

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

                if(fr->adress_do_drift ||fr->adress_icor == eAdressICThermoForce ){
                    sum_UgembU[e++] += enerd->term[F_ADR_DELTU]*embU;
                }

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

                if (dump_pdb && epot <= dump_ener)
                {
                    sprintf(str,"t%g_step%d.pdb",t,step);
                    sprintf(str2,"t: %f step %d ener: %f",t,step,epot);
                    write_sto_conf_mtop(str,str2,top_global,state->x,state->v,
                                        inputrec->ePBC,state->box);
                }
            }
        }
        
        if (PAR(cr))
        {
            /* When running in parallel sum the energies over the processes */
            gmx_sumd(1,    &sum_embU, cr);
            gmx_sumd(nener,sum_UgembU,cr);
        }

        frame++;
        V_all += V;
        VembU_all += V*sum_embU/nsteps;
        
        if (fp_tpi)
        {
            if (bVerbose || frame%10==0 || frame<10)
            {
                fprintf(stderr,"mu %10.3e <mu> %10.3e\n",
                        -log(sum_embU/nsteps)/beta,-log(VembU_all/V_all)/beta);
            }
            
            fprintf(fp_tpi,"%10.3f %12.5e %12.5e %12.5e %12.5e",
                    t,
                    VembU_all==0 ? 20/beta : -log(VembU_all/V_all)/beta,
                    sum_embU==0  ? 20/beta : -log(sum_embU/nsteps)/beta,
                    sum_embU/nsteps,V);
            for(e=0; e<nener; e++)
            {
                fprintf(fp_tpi," %12.5e",sum_UgembU[e]/nsteps);
            }
            fprintf(fp_tpi,"\n");
            fflush(fp_tpi);
        }
        
        bNotLastFrame = read_next_frame(oenv, status,&rerun_fr);
    } /* End of the loop  */
    runtime_end(runtime);

    close_trj(status);

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

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

    sfree(sum_UgembU);

    runtime->nsteps_done = frame*inputrec->nsteps;

    return 0;
}