Exemple #1
0
int gmx_dos(int argc, char *argv[])
{
    const char         *desc[] = {
        "[TT]g_dos[tt] computes the Density of States from a simulations.",
        "In order for this to be meaningful the velocities must be saved",
        "in the trajecotry with sufficiently high frequency such as to cover",
        "all vibrations. For flexible systems that would be around a few fs",
        "between saving. Properties based on the DoS are printed on the",
        "standard output."
    };
    const char         *bugs[] = {
        "This program needs a lot of memory: total usage equals the number of atoms times 3 times number of frames times 4 (or 8 when run in double precision)."
    };
    FILE               *fp, *fplog;
    t_topology          top;
    int                 ePBC = -1;
    t_trxframe          fr;
    matrix              box;
    int                 gnx;
    char                title[256];
    real                t0, t1, m;
    t_trxstatus        *status;
    int                 nV, nframes, n_alloc, i, j, k, l, fftcode, Nmol, Natom;
    double              rho, dt, V2sum, Vsum, V, tmass, dostot, dos2, dosabs;
    real              **c1, **dos, mi, beta, bfac, *nu, *tt, stddev, c1j;
    output_env_t        oenv;
    gmx_fft_t           fft;
    double              cP, S, A, E, DiffCoeff, Delta, f, y, z, sigHS, Shs, Sig, DoS0, recip_fac;
    double              wCdiff, wSdiff, wAdiff, wEdiff;

    static     gmx_bool bVerbose = TRUE, bAbsolute = FALSE, bNormalize = FALSE;
    static     gmx_bool bRecip   = FALSE, bDump = FALSE;
    static     real     Temp     = 298.15, toler = 1e-6;
    t_pargs             pa[]     = {
        { "-v", FALSE, etBOOL, {&bVerbose},
          "Be loud and noisy." },
        { "-recip", FALSE, etBOOL, {&bRecip},
          "Use cm^-1 on X-axis instead of 1/ps for DoS plots." },
        { "-abs", FALSE, etBOOL, {&bAbsolute},
          "Use the absolute value of the Fourier transform of the VACF as the Density of States. Default is to use the real component only" },
        { "-normdos", FALSE, etBOOL, {&bNormalize},
          "Normalize the DoS such that it adds up to 3N. This is a hack that should not be necessary." },
        { "-T", FALSE, etREAL, {&Temp},
          "Temperature in the simulation" },
        { "-toler", FALSE, etREAL, {&toler},
          "[HIDDEN]Tolerance when computing the fluidicity using bisection algorithm" },
        { "-dump", FALSE, etBOOL, {&bDump},
          "[HIDDEN]Dump the y/fy plot corresponding to Fig. 2 inLin2003a and the and the weighting functions corresponding to Fig. 1 in Berens1983a." }
    };

    t_filenm            fnm[] = {
        { efTRN, "-f",    NULL,    ffREAD  },
        { efTPX, "-s",    NULL,    ffREAD  },
        { efNDX, NULL,    NULL,    ffOPTRD },
        { efXVG, "-vacf", "vacf",  ffWRITE },
        { efXVG, "-mvacf", "mvacf", ffWRITE },
        { efXVG, "-dos",  "dos",   ffWRITE },
        { efLOG, "-g",    "dos",   ffWRITE },
    };
#define NFILE asize(fnm)
    int                 npargs;
    t_pargs            *ppa;
    const char         *DoSlegend[] = {
        "DoS(v)", "DoS(v)[Solid]", "DoS(v)[Diff]"
    };

    CopyRight(stderr, argv[0]);
    npargs = asize(pa);
    ppa    = add_acf_pargs(&npargs, pa);
    parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
                      NFILE, fnm, npargs, ppa, asize(desc), desc,
                      asize(bugs), bugs, &oenv);

    beta = 1/(Temp*BOLTZ);
    if (bDump)
    {
        printf("Dumping reference figures. Thanks for your patience.\n");
        dump_fy(oenv, toler);
        dump_w(oenv, beta);
        exit(0);
    }

    fplog = gmx_fio_fopen(ftp2fn(efLOG, NFILE, fnm), "w");
    fprintf(fplog, "Doing density of states analysis based on trajectory.\n");
    please_cite(fplog, "Pascal2011a");
    please_cite(fplog, "Caleman2011b");

    read_tps_conf(ftp2fn(efTPX, NFILE, fnm), title, &top, &ePBC, NULL, NULL, box,
                  TRUE);
    V     = det(box);
    tmass = 0;
    for (i = 0; (i < top.atoms.nr); i++)
    {
        tmass += top.atoms.atom[i].m;
    }

    Natom = top.atoms.nr;
    Nmol  = top.mols.nr;
    gnx   = Natom*DIM;

    /* Correlation stuff */
    snew(c1, gnx);
    for (i = 0; (i < gnx); i++)
    {
        c1[i] = NULL;
    }

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

    n_alloc = 0;
    nframes = 0;
    Vsum    = V2sum = 0;
    nV      = 0;
    do
    {
        if (fr.bBox)
        {
            V      = det(fr.box);
            V2sum += V*V;
            Vsum  += V;
            nV++;
        }
        if (nframes >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; i < gnx; i++)
            {
                srenew(c1[i], n_alloc);
            }
        }
        for (i = 0; i < gnx; i += DIM)
        {
            c1[i+XX][nframes] = fr.v[i/DIM][XX];
            c1[i+YY][nframes] = fr.v[i/DIM][YY];
            c1[i+ZZ][nframes] = fr.v[i/DIM][ZZ];
        }

        t1 = fr.time;

        nframes++;
    }
    while (read_next_frame(oenv, status, &fr));

    close_trj(status);

    dt = (t1-t0)/(nframes-1);
    if (nV > 0)
    {
        V = Vsum/nV;
    }
    if (bVerbose)
    {
        printf("Going to do %d fourier transforms of length %d. Hang on.\n",
               gnx, nframes);
    }
    low_do_autocorr(NULL, oenv, NULL, nframes, gnx, nframes, c1, dt, eacNormal, 0, FALSE,
                    FALSE, FALSE, -1, -1, 0, 0);
    snew(dos, DOS_NR);
    for (j = 0; (j < DOS_NR); j++)
    {
        snew(dos[j], nframes+4);
    }

    if (bVerbose)
    {
        printf("Going to merge the ACFs into the mass-weighted and plain ACF\n");
    }
    for (i = 0; (i < gnx); i += DIM)
    {
        mi = top.atoms.atom[i/DIM].m;
        for (j = 0; (j < nframes/2); j++)
        {
            c1j            = (c1[i+XX][j] + c1[i+YY][j] + c1[i+ZZ][j]);
            dos[VACF][j]  += c1j/Natom;
            dos[MVACF][j] += mi*c1j;
        }
    }
    fp = xvgropen(opt2fn("-vacf", NFILE, fnm), "Velocity ACF",
                  "Time (ps)", "C(t)", oenv);
    snew(tt, nframes/2);
    for (j = 0; (j < nframes/2); j++)
    {
        tt[j] = j*dt;
        fprintf(fp, "%10g  %10g\n", tt[j], dos[VACF][j]);
    }
    xvgrclose(fp);
    fp = xvgropen(opt2fn("-mvacf", NFILE, fnm), "Mass-weighted velocity ACF",
                  "Time (ps)", "C(t)", oenv);
    for (j = 0; (j < nframes/2); j++)
    {
        fprintf(fp, "%10g  %10g\n", tt[j], dos[MVACF][j]);
    }
    xvgrclose(fp);

    if ((fftcode = gmx_fft_init_1d_real(&fft, nframes/2,
                                        GMX_FFT_FLAG_NONE)) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_init_1d_real returned %d", fftcode);
    }
    if ((fftcode = gmx_fft_1d_real(fft, GMX_FFT_REAL_TO_COMPLEX,
                                   (void *)dos[MVACF], (void *)dos[DOS])) != 0)
    {
        gmx_fatal(FARGS, "gmx_fft_1d_real returned %d", fftcode);
    }

    /* First compute the DoS */
    /* Magic factor of 8 included now. */
    bfac = 8*dt*beta/2;
    dos2 = 0;
    snew(nu, nframes/4);
    for (j = 0; (j < nframes/4); j++)
    {
        nu[j] = 2*j/(t1-t0);
        dos2 += sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1]);
        if (bAbsolute)
        {
            dos[DOS][j] = bfac*sqrt(sqr(dos[DOS][2*j]) + sqr(dos[DOS][2*j+1]));
        }
        else
        {
            dos[DOS][j] = bfac*dos[DOS][2*j];
        }
    }
    /* Normalize it */
    dostot = evaluate_integral(nframes/4, nu, dos[DOS], NULL, nframes/4, &stddev);
    if (bNormalize)
    {
        for (j = 0; (j < nframes/4); j++)
        {
            dos[DOS][j] *= 3*Natom/dostot;
        }
    }

    /* Now analyze it */
    DoS0 = dos[DOS][0];

    /* Note this eqn. is incorrect in Pascal2011a! */
    Delta = ((2*DoS0/(9*Natom))*sqrt(M_PI*BOLTZ*Temp*Natom/tmass)*
             pow((Natom/V), 1.0/3.0)*pow(6/M_PI, 2.0/3.0));
    f     = calc_fluidicity(Delta, toler);
    y     = calc_y(f, Delta, toler);
    z     = calc_compress(y);
    Sig   = BOLTZ*(5.0/2.0+log(2*M_PI*BOLTZ*Temp/(sqr(PLANCK))*V/(f*Natom)));
    Shs   = Sig+calc_Shs(f, y);
    rho   = (tmass*AMU)/(V*NANO*NANO*NANO);
    sigHS = pow(6*y*V/(M_PI*Natom), 1.0/3.0);

    fprintf(fplog, "System = \"%s\"\n", title);
    fprintf(fplog, "Nmol = %d\n", Nmol);
    fprintf(fplog, "Natom = %d\n", Natom);
    fprintf(fplog, "dt = %g ps\n", dt);
    fprintf(fplog, "tmass = %g amu\n", tmass);
    fprintf(fplog, "V = %g nm^3\n", V);
    fprintf(fplog, "rho = %g g/l\n", rho);
    fprintf(fplog, "T = %g K\n", Temp);
    fprintf(fplog, "beta = %g mol/kJ\n", beta);

    fprintf(fplog, "\nDoS parameters\n");
    fprintf(fplog, "Delta = %g\n", Delta);
    fprintf(fplog, "fluidicity = %g\n", f);
    fprintf(fplog, "hard sphere packing fraction = %g\n", y);
    fprintf(fplog, "hard sphere compressibility = %g\n", z);
    fprintf(fplog, "ideal gas entropy = %g\n", Sig);
    fprintf(fplog, "hard sphere entropy = %g\n", Shs);
    fprintf(fplog, "sigma_HS = %g nm\n", sigHS);
    fprintf(fplog, "DoS0 = %g\n", DoS0);
    fprintf(fplog, "Dos2 = %g\n", dos2);
    fprintf(fplog, "DoSTot = %g\n", dostot);

    /* Now compute solid (2) and diffusive (3) components */
    fp = xvgropen(opt2fn("-dos", NFILE, fnm), "Density of states",
                  bRecip ? "E (cm\\S-1\\N)" : "\\f{12}n\\f{4} (1/ps)",
                  "\\f{4}S(\\f{12}n\\f{4})", oenv);
    xvgr_legend(fp, asize(DoSlegend), DoSlegend, oenv);
    recip_fac = bRecip ? (1e7/SPEED_OF_LIGHT) : 1.0;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_DIFF][j]  = DoS0/(1+sqr(DoS0*M_PI*nu[j]/(6*f*Natom)));
        dos[DOS_SOLID][j] = dos[DOS][j]-dos[DOS_DIFF][j];
        fprintf(fp, "%10g  %10g  %10g  %10g\n",
                recip_fac*nu[j],
                dos[DOS][j]/recip_fac,
                dos[DOS_SOLID][j]/recip_fac,
                dos[DOS_DIFF][j]/recip_fac);
    }
    xvgrclose(fp);

    /* Finally analyze the results! */
    wCdiff = 0.5;
    wSdiff = Shs/(3*BOLTZ); /* Is this correct? */
    wEdiff = 0.5;
    wAdiff = wEdiff-wSdiff;
    for (j = 0; (j < nframes/4); j++)
    {
        dos[DOS_CP][j] = (dos[DOS_DIFF][j]*wCdiff +
                          dos[DOS_SOLID][j]*wCsolid(nu[j], beta));
        dos[DOS_S][j]  = (dos[DOS_DIFF][j]*wSdiff +
                          dos[DOS_SOLID][j]*wSsolid(nu[j], beta));
        dos[DOS_A][j]  = (dos[DOS_DIFF][j]*wAdiff +
                          dos[DOS_SOLID][j]*wAsolid(nu[j], beta));
        dos[DOS_E][j]  = (dos[DOS_DIFF][j]*wEdiff +
                          dos[DOS_SOLID][j]*wEsolid(nu[j], beta));
    }
    DiffCoeff = evaluate_integral(nframes/2, tt, dos[VACF], NULL, nframes/2, &stddev);
    DiffCoeff = 1000*DiffCoeff/3.0;
    fprintf(fplog, "Diffusion coefficient from VACF %g 10^-5 cm^2/s\n",
            DiffCoeff);
    fprintf(fplog, "Diffusion coefficient from DoS %g 10^-5 cm^2/s\n",
            1000*DoS0/(12*tmass*beta));

    cP = BOLTZ * evaluate_integral(nframes/4, nu, dos[DOS_CP], NULL,
                                   nframes/4, &stddev);
    fprintf(fplog, "Heat capacity %g J/mol K\n", 1000*cP/Nmol);

    /*
       S  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_S],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Entropy %g J/mol K\n",1000*S/Nmol);
       A  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_A],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Helmholtz energy %g kJ/mol\n",A/Nmol);
       E  = BOLTZ * evaluate_integral(nframes/4,nu,dos[DOS_E],NULL,
                                   nframes/4,&stddev);
       fprintf(fplog,"Internal energy %g kJ/mol\n",E/Nmol);
     */
    fprintf(fplog, "\nArrivederci!\n");
    gmx_fio_fclose(fplog);

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy");

    thanx(stderr);

    return 0;
}
int gmx_pme_error(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] estimates the error of the electrostatic forces",
        "if using the sPME algorithm. The flag [TT]-tune[tt] will determine",
        "the splitting parameter such that the error is equally",
        "distributed over the real and reciprocal space part.",
        "The part of the error that stems from self interaction of the particles "
        "is computationally demanding. However, a good a approximation is to",
        "just use a fraction of the particles for this term which can be",
        "indicated by the flag [TT]-self[tt].[PAR]",
    };

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


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

    output_env_t    oenv = NULL;

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


#define NFILE asize(fnm)

    cr = init_commrec();
#ifdef GMX_LIB_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif

    PCA_Flags  = PCA_NOEXIT_ON_ARGS;
    PCA_Flags |= (MASTER(cr) ? 0 : PCA_QUIET);

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

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

    info.n_entries = 1;

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

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

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

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

    /* Estimate (S)PME force error */

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

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

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

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

    return 0;
}
Exemple #3
0
int main(){

    Mecanismo P = Mecanismo(2);

    cube I1__; I1__.zeros(3,3,2);
    I1__.slice(0) << 0 << 0                       << 0          << endr
                  << 0 << 107.307e-6 + 146.869e-6 << 0          << endr
                  << 0 << 0                       << 107.307e-6 + 146.869e-6 << endr;

    I1__.slice(1) << 0 << 0        << 0        << endr
                  << 0 << 438.0e-6 << 0        << endr
                  << 0 << 0        << 438.0e-6 << endr;

    cube I2__; I2__.zeros(3,3,2);
    I2__.slice(0) << 0 << 0                        << 0          << endr
                  << 0 << 107.307e-6 + 188.738e-6  << 0          << endr
                  << 0 << 0                        << 107.307e-6 + 188.738e-6  << endr;

    I2__.slice(1) << 0 << 0          << 0          << endr
                  << 0 << 301.679e-6 << 0          << endr
                  << 0 << 0          << 301.679e-6 << endr;

    Serial RR1 = Serial(2, {0.12, 0.16}, {0.06, 0.078},{0.062, 0.124}, I1__ , {0, 0, 9.8}, &fDH_RR);
    Serial RR2 = Serial(2, {0.12, 0.16}, {0.06, 0.058},{0.062, 0.097}, I2__ , {0, 0, 9.8}, &fDH_RR);
    Serial **RR_ = new Serial* [2];
    RR_[0] = &RR1;
    RR_[1] = &RR2;

    //Matrizes que descrevem a arquitetura do mecanismo
    double l0 = 0.05;
    mat D_ = join_vert((mat)eye(2,2),2);
    mat E_ = join_diag( Roty(0)(span(0,1),span(0,2)), Roty(PI)(span(0,1),span(0,2)) );
    mat F_ = zeros(4,4);
    vec f_ = {l0,0,-l0,0};

    Parallel Robot = Parallel(2, &P, RR_, 2, {2,4}, D_, E_, F_, f_);
    Reference RefObj = Reference(0.12, {0.08, 0.16}, {-0.08, 0.4});

    //Plotar área de trabalho
    uint nx = 96.0;
    uint ny = 56.0;
    double lx = 0.24;
    double ly = 0.28;
    double xi = -lx;
    double xf = lx;
    double yi = 0.0;
    double yf = ly;
    double dx = (xf-xi)/(nx-1);
    double dy = (yf-yi)/(ny-1);
    double dl = 0.5*(dx+dy);
    
    Mat<int> M; M.zeros(nx,ny);
    field<mat> fZ_(nx,ny);
    field<mat> fMh_(nx,ny);
    field<vec> fgh_(nx,ny);
    field<vec> fa1_(nx,ny);
    field<vec> fa2_(nx,ny);
    field<vec> fa12_(nx,ny);
    for(uint i=0; i<nx; i++){
        for(uint j=0; j<ny; j++){
            fZ_(i,j).zeros(2,2);
            fMh_(i,j).zeros(2,2);
            fgh_(i,j).zeros(2);
            fa1_(i,j).zeros(2);
            fa2_(i,j).zeros(2);
            fa12_(i,j).zeros(2);
        }
    }
    vec v1_ = {1,0};
    vec v2_ = {0,1};
    vec v12_ = {1,1};
    double r = 0.07;
    double x0 = 0.0;
    double y0 = 0.17;

    uint rows = nx;
    uint cols = ny;

    vec q0_ = {0.823167, 1.81774, 0.823167, 1.81774};

    GNR2 gnr2 = GNR2("RK6", &Robot, 1e-6, 30);
    //gnr2.Doit(q0_, {0.05,0.08});
    //cout << gnr2.convergiu << endl;
    //cout << gnr2.x_ << endl;
    //cout << gnr2.res_ << endl;
    //cout << gnr2.n << endl;

    double x;
    double y;
    mat A2_;
    for(uint i=0; i<rows; i++){
        for(uint j=0; j<cols; j++){
            x = xi + i*dx;
            y = yi + j*dy;
            gnr2.Doit(q0_, {x, y});
            if(gnr2.convergiu){
                q0_ = gnr2.x_;
                A2_ = join_horiz(Robot.Ah_, join_horiz(Robot.Ao_.col(1), Robot.Ao_.col(3)) );
                if(abs(det(Robot.Ao_)) < 1.6*1e-6 || abs(det(A2_)) < 1e-11 ) M(i,j) = 2;
                else{ 
                	M(i,j) = 1;
                	Robot.Doit(Robot.q0_, join_vert(v1_, -solve(Robot.Ao_, Robot.Ah_*v1_)) );
                	fZ_(i,j) = Robot.Z_;
                    fMh_(i,j) = Robot.dy->Mh_;
                    fgh_(i,j) = Robot.dy->gh_;
                    fa1_(i,j) = Robot.dy->vh_;
                    Robot.Doit(Robot.q0_, Robot.C_*v2_);
                    fa2_(i,j) = Robot.dy->vh_;
                    Robot.Doit(Robot.q0_, Robot.C_*v12_);
                    fa12_(i,j) = Robot.dy->vh_ - fa1_(i,j) - fa2_(i,j);
                }
            }
            gnr2.convergiu = false;
            if( ((x - x0)*(x - x0) + (y - y0)*(y - y0) <= (r+dl)*(r+dl) ) && ((x - x0)*(x - x0) + (y - y0)*(y - y0) >= (r-dl)*(r-dl) ) && (M(i,j) != 2) )
                M(i,j) = 3;
        }
    }

    for(uint i=0; i<rows; i++){
        for(uint j=0; j<cols; j++){
            cout << M(i,j) << ";" ;
            if(j==cols-1) cout << endl;
        }
    }


    fZ_.save("fZ_field");
    fMh_.save("fMh_field");
    fgh_.save("fgh_field");
    fa1_.save("fa1_field");
    fa2_.save("fa2_field");
    fa12_.save("fa12_field");


    return 0;
}
Exemple #4
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, title[STRLEN];
    gmx_bool          *bSet;
    int                i, nw, nwa, nsa, nsalt, iqtot;
    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), title, &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 = gmx_nint(qtot);


    if (conc > 0)
    {
        /* Compute number of ions to be added */
        vol   = det(box);
        nsalt = gmx_nint(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;
}
void calc_dispcorr(FILE *fplog,t_inputrec *ir,t_forcerec *fr,int step,
		   int natoms,matrix box,real lambda,
		   tensor pres,tensor virial,real ener[])
{
  static bool bFirst=TRUE;
  bool bCorrAll,bCorrPres;
  real dvdlambda,invvol,dens,ninter,avcsix,avctwelve,enerdiff,svir=0,spres=0;
  int  m;

  ener[F_DISPCORR] = 0.0;

  if (ir->eDispCorr != edispcNO) {
    bCorrAll  = (ir->eDispCorr == edispcAllEner ||
		 ir->eDispCorr == edispcAllEnerPres);
    bCorrPres = (ir->eDispCorr == edispcEnerPres ||
		 ir->eDispCorr == edispcAllEnerPres);

    if (bFirst)
      calc_enervirdiff(fplog,ir->eDispCorr,fr);
    
    invvol = 1/det(box);
    if (fr->n_tpi) {
      /* Only correct for the interactions with the inserted molecule */
      dens = (natoms - fr->n_tpi)*invvol;
      ninter = fr->n_tpi;
    } else {
      dens = natoms*invvol;
      ninter = 0.5*natoms;
    }

    if (ir->efep == efepNO) {
      avcsix    = fr->avcsix[0];
      avctwelve = fr->avctwelve[0];
    } else {
      avcsix    = (1 - lambda)*fr->avcsix[0]    + lambda*fr->avcsix[1];
      avctwelve = (1 - lambda)*fr->avctwelve[0] + lambda*fr->avctwelve[1];
    }
    
    enerdiff = ninter*(dens*fr->enerdiffsix - fr->enershiftsix);
    ener[F_DISPCORR] += avcsix*enerdiff;
    dvdlambda = 0.0;
    if (ir->efep != efepNO)
      dvdlambda += (fr->avcsix[1] - fr->avcsix[0])*enerdiff;

    if (bCorrAll) {
      enerdiff = ninter*(dens*fr->enerdifftwelve - fr->enershifttwelve);
      ener[F_DISPCORR] += avctwelve*enerdiff;
      if (fr->efep != efepNO)
	dvdlambda += (fr->avctwelve[1] - fr->avctwelve[0])*enerdiff;
    }

    if (bCorrPres) {
      svir = ninter*dens*avcsix*fr->virdiffsix/3.0;
      if (ir->eDispCorr == edispcAllEnerPres)
	svir += ninter*dens*avctwelve*fr->virdifftwelve/3.0;
      
      /* The factor 2 is because of the Gromacs virial definition */
      spres = -2.0*invvol*svir*PRESFAC;
      
      for(m=0; m<DIM; m++) {
	virial[m][m] += svir;
	pres[m][m] += spres;
      }
      ener[F_PRES] += spres;
    }
    
    if (bFirst && fplog) {
      if (bCorrAll)
	fprintf(fplog,"Long Range LJ corr.: <C6> %10.4e, <C12> %10.4e\n",
		avcsix,avctwelve);
      else
	fprintf(fplog,"Long Range LJ corr.: <C6> %10.4e\n",avcsix);
      
      if (bCorrPres)
	fprintf(fplog,
		"Long Range LJ corr.: Epot %10g, Pres: %10g, Vir: %10g\n",
                ener[F_DISPCORR],spres,svir);
      else
	fprintf(fplog,"Long Range LJ corr.: Epot %10g\n",ener[F_DISPCORR]);
    }
    bFirst = FALSE;

    if (fr->bSepDVDL && do_per_step(step,ir->nstlog))
      fprintf(fplog,sepdvdlformat,"Dispersion correction",
	      ener[F_DISPCORR],dvdlambda);
    
    ener[F_EPOT] += ener[F_DISPCORR];
    if (fr->efep != efepNO)
      ener[F_DVDL] += dvdlambda;
  }
}
Exemple #6
0
void check_cm_grp(FILE *fp,t_vcm *vcm,t_inputrec *ir,real Temp_Max)
{
  int    m,g;
  real   ekcm,ekrot,tm,tm_1,Temp_cm;
  rvec   jcm;
  tensor Icm,Tcm;
    
  /* First analyse the total results */
  if (vcm->mode != ecmNO) {
    for(g=0; (g<vcm->nr); g++) {
      tm = vcm->group_mass[g];
      if (tm != 0) {
	tm_1 = 1.0/tm;
	svmul(tm_1,vcm->group_p[g],vcm->group_v[g]);
      }
      /* Else it's zero anyway! */
    }
    if (vcm->mode == ecmANGULAR) {
      for(g=0; (g<vcm->nr); g++) {
	tm = vcm->group_mass[g];
	if (tm != 0) {
	  tm_1 = 1.0/tm;
	  
	  /* Compute center of mass for this group */
	  for(m=0; (m<DIM); m++)
	    vcm->group_x[g][m] *= tm_1;
	  
	  /* Subtract the center of mass contribution to the 
	   * angular momentum 
	   */
 	  cprod(vcm->group_x[g],vcm->group_v[g],jcm);
	  for(m=0; (m<DIM); m++)
	    vcm->group_j[g][m] -= tm*jcm[m];
	  
	  /* Subtract the center of mass contribution from the inertia 
	   * tensor (this is not as trivial as it seems, but due to
	   * some cancellation we can still do it, even in parallel).
	   */
	  clear_mat(Icm);
	  update_tensor(vcm->group_x[g],tm,Icm);
	  m_sub(vcm->group_i[g],Icm,vcm->group_i[g]);
	  
	  /* Compute angular velocity, using matrix operation 
	   * Since J = I w
	   * we have
	   * w = I^-1 J
	   */
	  get_minv(vcm->group_i[g],Icm);
	  mvmul(Icm,vcm->group_j[g],vcm->group_w[g]);
	}
	/* Else it's zero anyway! */
      }
    }
  }
  for(g=0; (g<vcm->nr); g++) {
    ekcm    = 0;
    if (vcm->group_mass[g] != 0 && vcm->group_ndf[g] > 0) {
      for(m=0; m<vcm->ndim; m++) 
	ekcm += sqr(vcm->group_v[g][m]);
      ekcm *= 0.5*vcm->group_mass[g];
      Temp_cm = 2*ekcm/vcm->group_ndf[g];
      
      if ((Temp_cm > Temp_Max) && fp)
	fprintf(fp,"Large VCM(group %s): %12.5f, %12.5f, %12.5f, Temp-cm: %12.5e\n",
		vcm->group_name[g],vcm->group_v[g][XX],
		vcm->group_v[g][YY],vcm->group_v[g][ZZ],Temp_cm);
      
      if (vcm->mode == ecmANGULAR) {
	ekrot = 0.5*iprod(vcm->group_j[g],vcm->group_w[g]);
	if ((ekrot > 1) && fp && !EI_RANDOM(ir->eI)) {
          /* if we have an integrator that may not conserve momenta, skip */
	  tm    = vcm->group_mass[g];
	  fprintf(fp,"Group %s with mass %12.5e, Ekrot %12.5e Det(I) = %12.5e\n",
		  vcm->group_name[g],tm,ekrot,det(vcm->group_i[g]));
	  fprintf(fp,"  COM: %12.5f  %12.5f  %12.5f\n",
		  vcm->group_x[g][XX],vcm->group_x[g][YY],vcm->group_x[g][ZZ]);
	  fprintf(fp,"  P:   %12.5f  %12.5f  %12.5f\n",
		  vcm->group_p[g][XX],vcm->group_p[g][YY],vcm->group_p[g][ZZ]);
	  fprintf(fp,"  V:   %12.5f  %12.5f  %12.5f\n",
		  vcm->group_v[g][XX],vcm->group_v[g][YY],vcm->group_v[g][ZZ]);
	  fprintf(fp,"  J:   %12.5f  %12.5f  %12.5f\n",
		  vcm->group_j[g][XX],vcm->group_j[g][YY],vcm->group_j[g][ZZ]);
	  fprintf(fp,"  w:   %12.5f  %12.5f  %12.5f\n",
		vcm->group_w[g][XX],vcm->group_w[g][YY],vcm->group_w[g][ZZ]);
	  pr_rvecs(fp,0,"Inertia tensor",vcm->group_i[g],DIM);
	}
      }
    }
  }
}
Exemple #7
0
bool line_check_equivalent(line l1, line l2) {
    return fabs(det(l1.a, l1.b, l2.a, l2.b)) < eps &&
            fabs(det(l1.a, l1.c, l2.a, l2.c)) < eps &&
            fabs(det(l1.b, l1.c, l2.b, l2.c)) < eps;
}
position_tracker::Position getClosestRightLineProjection()
{

   //WHAT IF THERE IS NO LINE TO THE RIGHT OF THE ROBOT???

   double min_dist = 100000000;
   position_tracker::Position *tmp_pos = new position_tracker::Position();
   tmp_pos->x = -1;
   tmp_pos->y = -1;
   tmp_pos->theta = -1;

   list<Edge *>::iterator i;   
   for(i = map4.begin(); i != map4.end(); ++i) //for each edge in the map
   {
      Edge *e = *i;
      double D[2][2] = {{(e->Bx - e->Ax), (e->By - e->Ay)}, {(cur_pos.x - e->Ax), (cur_pos.y - e->Ay)}};

/*      cout << "cur_pos.x = " << cur_pos.x << endl;
      cout << "cur_pos.y = " << cur_pos.y << endl;
      cout << "cur_pos.theta = " << cur_pos.theta << endl;
      cout << "e->Ax = " << e->Ax << endl;
      cout << "e->Ay = " << e->Ay << endl;
      cout << "e->Bx = " << e->Bx << endl;
      cout << "e->By = " << e->By << endl;
      cout << "e->theta = " << e->theta << endl;
      cout << "det(D) = " << det(D) << endl;*/

      //keep only the lines to the right of the current robot pos
      if((det(D) > 0  && fabs(det(D)) > 0.0001 && (cur_pos.theta > e->theta - PI/2 && cur_pos.theta < e->theta + PI/2)) || (det(D) < 0  && fabs(det(D)) > 0.0001 && (cur_pos.theta < e->theta - PI/2 || cur_pos.theta > e->theta + PI/2)))
      {
          //find the projection of the current point to the last identified left line
          double A[2][2] = {{(e->Bx - e->Ax), (e->By - e->Ay)}, {(e->Ay - e->By), (e->Bx - e->Ax)}};
          double X[2] = {0, 0};
          double B[2] = {cur_pos.x*(e->Bx - e->Ax) + cur_pos.y*(e->By - e->Ay), e->Ay*(e->Bx - e->Ax) - e->Ax*(e->By - e->Ay)};
          solve(A, B, X);

          //discard line segment if the projection falls outside its boundaries
          if(e->theta < 0.1 ) //horizontal line
          {
              if(X[0] > e->Bx || X[0] < e->Ax)
                 continue;
          }
		  else{ //vertical line
              if(X[1] > e->By || X[1] < e->Ay)
                 continue; 
          }

          cout << "line to the RIGHT of the robot" << endl;

          //calculate the distance between the projection and the current robot location
          double sdist = pow(cur_pos.x - X[0], 2) + pow(cur_pos.y - X[1], 2);

          //keep the projection with the min distance from the current pos
          if(sdist < min_dist)
          {
              min_dist = sdist;
              tmp_pos->x = X[0] + (0.05/sdist)*(cur_pos.x - X[0]); //X[0];
              tmp_pos->y = X[1] + (0.05/sdist)*(cur_pos.y - X[1]); //X[1];


			  double angle1 = e->theta;
			  double angle2 = e->theta + PI;
              if(angle1 > PI)
                   angle1 = -2*PI + angle1;
              else if(angle1 < -PI)
                   angle1 = 2*PI + angle1;

              if(angle2 > PI)
                   angle2 = -2*PI + angle2;
              else if(angle2 < -PI)
                   angle2 = 2*PI + angle2;

              double diff1 = angle1 - cur_pos.theta;
              double diff2 = angle2 - cur_pos.theta;

              if(fabs(diff1) < fabs(diff2))
                   tmp_pos->theta = angle1; 
              else
                   tmp_pos->theta = angle2; 

      cout << "angle1 = " << angle1 << endl;
      cout << "angle2 = " << angle2 << endl;
      cout << "tmp_pos->theta = " << tmp_pos->theta << endl;

      cout << "cur_pos.x = " << cur_pos.x << endl;
      cout << "cur_pos.y = " << cur_pos.y << endl;
      cout << "cur_pos.theta = " << cur_pos.theta << endl;
      cout << "e->Ax = " << e->Ax << endl;
      cout << "e->Ay = " << e->Ay << endl;
      cout << "e->Bx = " << e->Bx << endl;
      cout << "e->By = " << e->By << endl;
      cout << "e->theta = " << e->theta << endl;
      cout << "det(D) = " << det(D) << endl;

          }
      }
   }

   return *tmp_pos;

}
void trotter_update(t_inputrec *ir,gmx_large_int_t step, gmx_ekindata_t *ekind, 
                    gmx_enerdata_t *enerd, t_state *state, 
                    tensor vir, t_mdatoms *md, 
                    t_extmass *MassQ, int **trotter_seqlist, int trotter_seqno) 
{
    
    int n,i,j,d,ntgrp,ngtc,gc=0;
    t_grp_tcstat *tcstat;
    t_grpopts *opts;
    gmx_large_int_t step_eff;
    real ecorr,pcorr,dvdlcorr;
    real bmass,qmass,reft,kT,dt,nd;
    tensor dumpres,dumvir;
    double *scalefac,dtc;
    int *trotter_seq;
    rvec sumv,consk;
    gmx_bool bCouple;

    if (trotter_seqno <= ettTSEQ2)
    {
        step_eff = step-1;  /* the velocity verlet calls are actually out of order -- the first half step
                               is actually the last half step from the previous step.  Thus the first half step
                               actually corresponds to the n-1 step*/
                               
    } else {
        step_eff = step;
    }

    bCouple = (ir->nsttcouple == 1 ||
               do_per_step(step_eff+ir->nsttcouple,ir->nsttcouple));

    trotter_seq = trotter_seqlist[trotter_seqno];

    /* signal we are returning if nothing is going to be done in this routine */
    if ((trotter_seq[0] == etrtSKIPALL)  || !(bCouple))
    {
        return;
    }

    dtc = ir->nsttcouple*ir->delta_t;
    opts = &(ir->opts); /* just for ease of referencing */
    ngtc = opts->ngtc;
    snew(scalefac,opts->ngtc);
    for (i=0;i<ngtc;i++) 
    {
        scalefac[i] = 1;
    }
    /* execute the series of trotter updates specified in the trotterpart array */
    
    for (i=0;i<NTROTTERPARTS;i++){
        /* allow for doubled intgrators by doubling dt instead of making 2 calls */
        if ((trotter_seq[i] == etrtBAROV2) || (trotter_seq[i] == etrtBARONHC2) || (trotter_seq[i] == etrtNHC2))
        {
            dt = 2 * dtc;
        }
        else 
        {
            dt = dtc;
        }

        switch (trotter_seq[i])
        {
        case etrtBAROV:
        case etrtBAROV2:
            boxv_trotter(ir,&(state->veta),dt,state->box,ekind,vir,
                         enerd->term[F_PDISPCORR],enerd->term[F_DISPCORR],MassQ);
            break;
        case etrtBARONHC:
        case etrtBARONHC2:
            NHC_trotter(opts,state->nnhpres,ekind,dt,state->nhpres_xi,
                        state->nhpres_vxi,NULL,&(state->veta),MassQ,FALSE);      
            break;
        case etrtNHC:
        case etrtNHC2:
            NHC_trotter(opts,opts->ngtc,ekind,dt,state->nosehoover_xi,
                        state->nosehoover_vxi,scalefac,NULL,MassQ,(ir->eI==eiVV));
            /* need to rescale the kinetic energies and velocities here.  Could 
               scale the velocities later, but we need them scaled in order to 
               produce the correct outputs, so we'll scale them here. */
            
            for (i=0; i<ngtc;i++) 
            {
                tcstat = &ekind->tcstat[i];
                tcstat->vscale_nhc = scalefac[i]; 
                tcstat->ekinscaleh_nhc *= (scalefac[i]*scalefac[i]); 
                tcstat->ekinscalef_nhc *= (scalefac[i]*scalefac[i]); 
            }
            /* now that we've scaled the groupwise velocities, we can add them up to get the total */
            /* but do we actually need the total? */
            
            /* modify the velocities as well */
            for (n=md->start;n<md->start+md->homenr;n++) 
            {
                if (md->cTC) 
                { 
                    gc = md->cTC[n];
                }
                for (d=0;d<DIM;d++) 
                {
                    state->v[n][d] *= scalefac[gc];
                }
                
                if (debug) 
                {
                    for (d=0;d<DIM;d++) 
                    {
                        sumv[d] += (state->v[n][d])/md->invmass[n];
                    }
                }
            }          
            break;
        default:
            break;
        }
    }
    /* check for conserved momentum -- worth looking at this again eventually, but not working right now.*/  
#if 0
    if (debug) 
    {
        if (bFirstHalf) 
        {
            for (d=0;d<DIM;d++) 
            {
                consk[d] = sumv[d]*exp((1 + 1.0/opts->nrdf[0])*((1.0/DIM)*log(det(state->box)/state->vol0)) + state->nosehoover_xi[0]); 
            }
            fprintf(debug,"Conserved kappa: %15.8f %15.8f %15.8f\n",consk[0],consk[1],consk[2]);    
        }
    }
#endif
    sfree(scalefac);
}
gmx_bool replica_exchange(FILE *fplog, const t_commrec *cr, struct gmx_repl_ex *re,
                          t_state *state, gmx_enerdata_t *enerd,
                          t_state *state_local, gmx_int64_t step, real time)
{
    int i, j;
    int replica_id = 0;
    int exchange_partner;
    int maxswap = 0;
    /* Number of rounds of exchanges needed to deal with any multiple
     * exchanges. */
    /* Where each replica ends up after the exchange attempt(s). */
    /* The order in which multiple exchanges will occur. */
    gmx_bool bThisReplicaExchanged = FALSE;

    if (MASTER(cr))
    {
        replica_id  = re->repl;
        test_for_replica_exchange(fplog, cr->ms, re, enerd, det(state_local->box), step, time);
        prepare_to_do_exchange(fplog, re, replica_id, &maxswap, &bThisReplicaExchanged);
    }
    /* Do intra-simulation broadcast so all processors belonging to
     * each simulation know whether they need to participate in
     * collecting the state. Otherwise, they might as well get on with
     * the next thing to do. */
    if (DOMAINDECOMP(cr))
    {
#ifdef GMX_MPI
        MPI_Bcast(&bThisReplicaExchanged, sizeof(gmx_bool), MPI_BYTE, MASTERRANK(cr),
                  cr->mpi_comm_mygroup);
#endif
    }

    if (bThisReplicaExchanged)
    {
        /* Exchange the states */
        /* Collect the global state on the master node */
        if (DOMAINDECOMP(cr))
        {
            dd_collect_state(cr->dd, state_local, state);
        }
        else
        {
            copy_state_nonatomdata(state_local, state);
        }

        if (MASTER(cr))
        {
            /* There will be only one swap cycle with standard replica
             * exchange, but there may be multiple swap cycles if we
             * allow multiple swaps. */

            for (j = 0; j < maxswap; j++)
            {
                exchange_partner = re->order[replica_id][j];

                if (exchange_partner != replica_id)
                {
                    /* Exchange the global states between the master nodes */
                    if (debug)
                    {
                        fprintf(debug, "Exchanging %d with %d\n", replica_id, exchange_partner);
                    }
                    exchange_state(cr->ms, exchange_partner, state);
                }
            }
            /* For temperature-type replica exchange, we need to scale
             * the velocities. */
            if (re->type == ereTEMP || re->type == ereTL)
            {
                scale_velocities(state, sqrt(re->q[ereTEMP][replica_id]/re->q[ereTEMP][re->destinations[replica_id]]));
            }

        }

        /* With domain decomposition the global state is distributed later */
        if (!DOMAINDECOMP(cr))
        {
            /* Copy the global state to the local state data structure */
            copy_state_nonatomdata(state, state_local);
        }
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    thanx(stderr);

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

    return 0;
}
Exemple #12
0
ll det (const pii & a,const pii & b,const pii & c){
 return det((b-a),(c-a));
}
Exemple #13
0
int gmx_genbox(int argc, char *argv[])
{
    const char *desc[] = {
        "[TT]genbox[tt] can do one of 4 things:[PAR]",

        "1) Generate a box of solvent. Specify [TT]-cs[tt] and [TT]-box[tt]. Or specify [TT]-cs[tt] and",
        "[TT]-cp[tt] with a structure file with a box, but without atoms.[PAR]",

        "2) Solvate a solute configuration, e.g. a protein, in a bath of solvent ",
        "molecules. Specify [TT]-cp[tt] (solute) and [TT]-cs[tt] (solvent). ",
        "The box specified in the solute coordinate file ([TT]-cp[tt]) is used,",
        "unless [TT]-box[tt] is set.",
        "If you want the solute to be centered in the box,",
        "the program [TT]editconf[tt] has sophisticated options",
        "to change the box dimensions and center the solute.",
        "Solvent molecules are removed from the box where the ",
        "distance between any atom of the solute molecule(s) and any atom of ",
        "the solvent molecule is less than the sum of the van der Waals radii of ",
        "both atoms. A database ([TT]vdwradii.dat[tt]) of van der Waals radii is ",
        "read by the program, and atoms not in the database are ",
        "assigned a default distance [TT]-vdwd[tt].",
        "Note that this option will also influence the distances between",
        "solvent molecules if they contain atoms that are not in the database.",
        "[PAR]",

        "3) Insert a number ([TT]-nmol[tt]) of extra molecules ([TT]-ci[tt]) ",
        "at random positions.",
        "The program iterates until [TT]nmol[tt] molecules",
        "have been inserted in the box. To test whether an insertion is ",
        "successful the same van der Waals criterium is used as for removal of ",
        "solvent molecules. When no appropriately-sized ",
        "holes (holes that can hold an extra molecule) are available, the ",
        "program tries for [TT]-nmol[tt] * [TT]-try[tt] times before giving up. ",
        "Increase [TT]-try[tt] if you have several small holes to fill.",
        "Option [TT]-rot[tt] defines if the molecules are randomly oriented.",
        "[PAR]",

        "4) Insert a number of molecules ([TT]-ci[tt]) at positions defined in",
        "positions.dat ([TT]-ip[tt]). positions.dat should have 3 columns (x/y/z),",
        "that give the displacements compared to the input molecule position ([TT]-ci[tt]).",
        "Hence, if positions.dat should contain the absolut positions, the molecule ",
        "must be centered to 0/0/0 before using genbox (use, e.g., editconf -center).",
        "Comments in positions.dat starting with # are ignored. Option [TT]-dr[tt]",
        "defines the maximally allowed displacements during insertial trials.",
        "[TT]-try[tt] and [TT]-rot[tt] work as in mode (3) (see above)",
        "[PAR]",

        "If you need to do more than one of the above operations, it can be",
        "best to call [TT]genbox[tt] separately for each operation, so that",
        "you are sure of the order in which the operations occur.[PAR]",

        "The default solvent is Simple Point Charge water (SPC), with coordinates ",
        "from [TT]$GMXLIB/spc216.gro[tt]. These coordinates can also be used",
        "for other 3-site water models, since a short equibilibration will remove",
        "the small differences between the models.",
        "Other solvents are also supported, as well as mixed solvents. The",
        "only restriction to solvent types is that a solvent molecule consists",
        "of exactly one residue. The residue information in the coordinate",
        "files is used, and should therefore be more or less consistent.",
        "In practice this means that two subsequent solvent molecules in the ",
        "solvent coordinate file should have different residue number.",
        "The box of solute is built by stacking the coordinates read from",
        "the coordinate file. This means that these coordinates should be ",
        "equlibrated in periodic boundary conditions to ensure a good",
        "alignment of molecules on the stacking interfaces.",
        "The [TT]-maxsol[tt] option simply adds only the first [TT]-maxsol[tt]",
        "solvent molecules and leaves out the rest that would have fitted",
        "into the box. This can create a void that can cause problems later.",
        "Choose your volume wisely.[PAR]",

        "The program can optionally rotate the solute molecule to align the",
        "longest molecule axis along a box edge. This way the amount of solvent",
        "molecules necessary is reduced.",
        "It should be kept in mind that this only works for",
        "short simulations, as e.g. an alpha-helical peptide in solution can ",
        "rotate over 90 degrees, within 500 ps. In general it is therefore ",
        "better to make a more or less cubic box.[PAR]",

        "Setting [TT]-shell[tt] larger than zero will place a layer of water of",
        "the specified thickness (nm) around the solute. Hint: it is a good",
        "idea to put the protein in the center of a box first (using [TT]editconf[tt]).",
        "[PAR]",

        "Finally, [TT]genbox[tt] will optionally remove lines from your topology file in ",
        "which a number of solvent molecules is already added, and adds a ",
        "line with the total number of solvent molecules in your coordinate file."
    };

    const char *bugs[] = {
        "Molecules must be whole in the initial configurations.",
        "Many repeated neighbor searchings with -ci blows up the allocated memory. "
        "Option -allpair avoids this using all-to-all distance checks (slow for large systems)"
    };

    /* parameter data */
    gmx_bool       bSol, bProt, bBox;
    const char    *conf_prot, *confout;
    int            bInsert;
    real          *r;
    char          *title_ins;
    gmx_atomprop_t aps;

    /* protein configuration data */
    char    *title = NULL;
    t_atoms  atoms;
    rvec    *x, *v = NULL;
    int      ePBC = -1;
    matrix   box;

    /* other data types */
    int      atoms_added, residues_added;

    t_filenm fnm[] = {
        { efSTX, "-cp", "protein", ffOPTRD },
        { efSTX, "-cs", "spc216",  ffLIBOPTRD},
        { efSTX, "-ci", "insert",  ffOPTRD},
        { efDAT, "-ip", "positions",  ffOPTRD},
        { efSTO, NULL,  NULL,      ffWRITE},
        { efTOP, NULL,  NULL,      ffOPTRW},
    };
#define NFILE asize(fnm)

    static int      nmol_ins   = 0, nmol_try = 10, seed = 1997, enum_rot;
    static real     r_distance = 0.105, r_shell = 0, r_scale = 0.57;
    static rvec     new_box    = {0.0, 0.0, 0.0}, deltaR = {0.0, 0.0, 0.0};
    static gmx_bool bReadV     = FALSE, bCheckAllPairDist = FALSE;
    static int      max_sol    = 0;
    output_env_t    oenv;
    const char     *enum_rot_string[] = {NULL, "xyz", "z", "none", NULL};
    t_pargs         pa[]              = {
        { "-box",    FALSE, etRVEC, {new_box},
          "Box size" },
        { "-nmol",   FALSE, etINT, {&nmol_ins},
          "Number of extra molecules to insert" },
        { "-try",    FALSE, etINT, {&nmol_try},
          "Try inserting [TT]-nmol[tt] times [TT]-try[tt] times" },
        { "-seed",   FALSE, etINT, {&seed},
          "Random generator seed"},
        { "-vdwd",   FALSE, etREAL, {&r_distance},
          "Default van der Waals distance"},
        { "-vdwscale", FALSE, etREAL, {&r_scale},
          "HIDDENScale factor to multiply Van der Waals radii from the database in share/gromacs/top/vdwradii.dat. The default value of 0.57 yields density close to 1000 g/l for proteins in water." },
        { "-shell",  FALSE, etREAL, {&r_shell},
          "Thickness of optional water layer around solute" },
        { "-maxsol", FALSE, etINT,  {&max_sol},
          "Maximum number of solvent molecules to add if they fit in the box. If zero (default) this is ignored" },
        { "-vel",    FALSE, etBOOL, {&bReadV},
          "Keep velocities from input solute and solvent" },
        { "-dr",    FALSE, etRVEC, {deltaR},
          "Allowed displacement in x/y/z from positions in [TT]-ip[tt] file" },
        { "-rot", FALSE,  etENUM, {enum_rot_string},
          "rotate inserted molecules randomly" },
        { "-allpair",    FALSE, etBOOL, {&bCheckAllPairDist},
          "Avoid momory leaks during neighbor searching with option -ci. May be slow for large systems." },
    };

    parse_common_args(&argc, argv, PCA_BE_NICE, NFILE, fnm, asize(pa), pa,
                      asize(desc), desc, asize(bugs), bugs, &oenv);

    bInsert   = opt2bSet("-ci", NFILE, fnm) && ((nmol_ins > 0) || opt2bSet("-ip", NFILE, fnm));
    bSol      = opt2bSet("-cs", NFILE, fnm);
    bProt     = opt2bSet("-cp", NFILE, fnm);
    bBox      = opt2parg_bSet("-box", asize(pa), pa);
    enum_rot  = nenum(enum_rot_string);

    /* check input */
    if (bInsert && (nmol_ins <= 0 && !opt2bSet("-ip", NFILE, fnm)))
    {
        gmx_fatal(FARGS, "When specifying inserted molecules (-ci), "
                  "-nmol must be larger than 0 or positions must be given with -ip");
    }
    if (!bProt && !bBox)
    {
        gmx_fatal(FARGS, "When no solute (-cp) is specified, "
                  "a box size (-box) must be specified");
    }

    aps = gmx_atomprop_init();

    if (bProt)
    {
        /*generate a solute configuration */
        conf_prot = opt2fn("-cp", NFILE, fnm);
        title     = read_prot(conf_prot, &atoms, &x, bReadV ? &v : NULL, &r, &ePBC, box,
                              aps, r_distance, r_scale);
        if (bReadV && !v)
        {
            fprintf(stderr, "Note: no velocities found\n");
        }
        if (atoms.nr == 0)
        {
            fprintf(stderr, "Note: no atoms in %s\n", conf_prot);
            bProt = FALSE;
        }
    }
    if (!bProt)
    {
        atoms.nr       = 0;
        atoms.nres     = 0;
        atoms.resinfo  = NULL;
        atoms.atomname = NULL;
        atoms.atom     = NULL;
        atoms.pdbinfo  = NULL;
        x              = NULL;
        r              = NULL;
    }
    if (bBox)
    {
        ePBC = epbcXYZ;
        clear_mat(box);
        box[XX][XX] = new_box[XX];
        box[YY][YY] = new_box[YY];
        box[ZZ][ZZ] = new_box[ZZ];
    }
    if (det(box) == 0)
    {
        gmx_fatal(FARGS, "Undefined solute box.\nCreate one with editconf "
                  "or give explicit -box command line option");
    }

    /* add nmol_ins molecules of atoms_ins
       in random orientation at random place */
    if (bInsert)
    {
        title_ins = insert_mols(opt2fn("-ci", NFILE, fnm), nmol_ins, nmol_try, seed,
                                &atoms, &x, &r, ePBC, box, aps, 
                                r_distance, r_scale, r_shell,
                                oenv, opt2fn_null("-ip", NFILE, fnm), deltaR, enum_rot,
                                bCheckAllPairDist);
    }
    else
    {
        title_ins = strdup("Generated by genbox");
    }

    /* add solvent */
    if (bSol)
    {
        add_solv(opt2fn("-cs", NFILE, fnm), &atoms, &x, v ? &v : NULL, &r, ePBC, box,
                 aps, r_distance, r_scale, &atoms_added, &residues_added, r_shell, max_sol,
                 oenv);
    }

    /* write new configuration 1 to file confout */
    confout = ftp2fn(efSTO, NFILE, fnm);
    fprintf(stderr, "Writing generated configuration to %s\n", confout);
    if (bProt)
    {
        write_sto_conf(confout, title, &atoms, x, v, ePBC, box);
        /* print box sizes and box type to stderr */
        fprintf(stderr, "%s\n", title);
    }
    else
    {
        write_sto_conf(confout, title_ins, &atoms, x, v, ePBC, box);
    }

    sfree(title_ins);

    /* print size of generated configuration */
    fprintf(stderr, "\nOutput configuration contains %d atoms in %d residues\n",
            atoms.nr, atoms.nres);
    update_top(&atoms, box, NFILE, fnm, aps);

    gmx_atomprop_destroy(aps);

    thanx(stderr);

    return 0;
}
Exemple #14
0
int main()
{
//#ifdef _DEBUG
//	int iOrg = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);	
//	_CrtSetDbgFlag(iOrg | _CRTDBG_LEAK_CHECK_DF);
//#endif
	
	cout << "tmat demo program" << endl;

	// build two 16 element double arrays
	double aa[] = { 1, 2, 3, 4,
				    4, 1, 2, 3,
					3, 4, 1, 2,
					2, 3, 4, 1 };

	double bb[] = { 3, 4, 5, 6,
		            6, 3, 4, 5,
					5, 6, 3, 4,
					4, 5, 6, 3 };

	// instantiate arrays as 4 x 4 matrices
	tmat<double> A(4,4,aa); cout << A << endl;
	tmat<double> B(4,4,bb); cout << B << endl;

	// check determinants
	cout << "det(A) = " << det(A) << endl;
	cout << "det(B) = " << det(B) << endl << endl;

	// exercise the matrix operators
	tmat<double> C;
	C = A + B; cout << "A + B =" << endl << C << endl;
	C = A - B; cout << "A - B =" << endl << C << endl;
	C = A * B; cout << "A * B =" << endl << C << endl;

	// exercise unary operators
	C = transpose(A); cout << "transpose(A) =" << endl << C << endl;
	C = inv(A); cout << "inv(A) =" << endl << C << endl;

	// check error flag
	C = hconcat(A, B); cout << "A | B =" << endl << C << endl;
	C = vconcat(A, B); cout << "A , B =" << endl << C << endl;
//	C = A + C; // error here
	delrow(C,5);cout << "A , B row=" << endl << C << endl;

	// string matrices
	tmat<string> S(3,3);  
	S(1,1) = "an";  S(1,2) = "to";  S(1,3) = "if";
	S(2,1) = "or";	S(2,2) = "no";	S(2,3) = "on";
	S(3,1) = "be";	S(3,2) = "am";  S(3,3) = "as";
	cout << S << endl;

	S = transpose(S); cout << S << endl;

	// integer matrices
	tmat<int> H(3,3);
	H(1,1) = 1;  H(1,2) = 0; H(1,3) = 1;
	H(2,1) = 0;  H(2,2) = 1; H(2,3) = 1;
	H(3,1) = 1;  H(3,2) = 0; H(3,3) = 0;
	cout << H << endl;

	H = bin_add(H, transpose(H));  cout << H << endl;
		


	cout << "end program" << endl;

	return 0;

}// main()
Exemple #15
0
double cross(struct Point* a, struct Point* b, struct Point* c) {
	return det(b->x - a->x, b->y - a->y, c->x - a->x, c->y - a->y);
}
real NPT_energy(t_inputrec *ir, t_state *state, t_extmass *MassQ)
{
    int  i,j,nd,ndj,bmass,qmass,ngtcall;
    real ener_npt,reft,eta,kT,tau;
    double *ivxi, *ixi;
    double *iQinv;
    real vol,dbaro,W,Q;
    int nh = state->nhchainlength;

    ener_npt = 0;
    
    /* now we compute the contribution of the pressure to the conserved quantity*/
    
    if (ir->epc==epcMTTK) 
    {
        /* find the volume, and the kinetic energy of the volume */
        
        switch (ir->epct) {
            
        case epctISOTROPIC:
            /* contribution from the pressure momenenta */
            ener_npt += 0.5*sqr(state->veta)/MassQ->Winv;
            
            /* contribution from the PV term */
            vol = det(state->box);
            ener_npt += vol*trace(ir->ref_p)/(DIM*PRESFAC);

            break;
        case epctANISOTROPIC:
            
            break;
            
        case epctSURFACETENSION:
            
            break;
        case epctSEMIISOTROPIC:
            
            break;
        default:
            break;
        }
    }
    
    if (IR_NPT_TROTTER(ir)) 
    {
        /* add the energy from the barostat thermostat chain */
        for (i=0;i<state->nnhpres;i++) {

            /* note -- assumes only one degree of freedom that is thermostatted in barostat */
            ivxi = &state->nhpres_vxi[i*nh];
            ixi = &state->nhpres_xi[i*nh];
            iQinv = &(MassQ->QPinv[i*nh]);
            reft = max(ir->opts.ref_t[0],0); /* using 'System' temperature */
            kT = BOLTZ * reft;
        
            for (j=0;j<nh;j++) 
            {
                if (iQinv[j] > 0)
                {
                    ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
                    /* contribution from the thermal variable of the NH chain */
                    ener_npt += ixi[j]*kT;
                }
                if (debug) 
                {
                    fprintf(debug,"P-T-group: %10d Chain %4d ThermV: %15.8f ThermX: %15.8f",i,j,ivxi[j],ixi[j]);
                }
            }
        }
    }
        
    if (ir->etc) 
    {
        for(i=0; i<ir->opts.ngtc; i++) 
        {
            ixi = &state->nosehoover_xi[i*nh];
            ivxi = &state->nosehoover_vxi[i*nh];
            iQinv = &(MassQ->Qinv[i*nh]);
            
            nd = ir->opts.nrdf[i];
            reft = max(ir->opts.ref_t[i],0);
            kT = BOLTZ * reft;
            
            if (nd > 0) 
            {
                if (IR_NVT_TROTTER(ir))
                {
                    /* contribution from the thermal momenta of the NH chain */
                    for (j=0;j<nh;j++) 
                    {
                        if (iQinv[j] > 0) {
                            ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
                            /* contribution from the thermal variable of the NH chain */
                            if (j==0) {
                                ndj = nd;
                            } 
                            else 
                            {
                                ndj = 1;
                            } 
                            ener_npt += ndj*ixi[j]*kT;
                        }
                    }
                }
                else  /* Other non Trotter temperature NH control  -- no chains yet. */
                { 
                    ener_npt += 0.5*BOLTZ*nd*sqr(ivxi[0])/iQinv[0];
                    ener_npt += nd*ixi[0]*kT;
                }
            }
        }
    }
    return ener_npt;
}
      virtual double metric(stk::mesh::Entity& element, bool& valid)
      {
        valid = true;
        JacobianUtil jacA, jacW;

        int spatialDim = m_eMesh->get_spatial_dim();
        double A_ = 0.0, W_ = 0.0; // current and reference detJ
        jacA(A_, *m_eMesh, element, m_coord_field_current, m_topology_data);
        jacW(W_, *m_eMesh, element, m_coord_field_original, m_topology_data);
        double val=0.0, val_shape=0.0;
        MsqMatrix<3,3> Ident; 
        identity(Ident);

        MsqMatrix<3,3> WI, T;

        for (int i=0; i < jacA.m_num_nodes; i++)
          {
            double detAi = jacA.m_detJ[i];
            if (detAi < 0)
              {
                valid = false;
              }
            MsqMatrix<3,3>& W = jacW.m_J[i];
            MsqMatrix<3,3>& A = jacA.m_J[i];

            // frob2 = h^2 + h^2 + 1
            // frob21 = 2 h^2
            // f = h sqrt(2)
            // det = h*h
            // met = f*f / (det*2) - 1
            // frob3 = 3 h^2
            // f = h sqrt(3)
            // det = h*h*h
            // met = f*f*f/(3^3/2 *det) - 1 = f*f*f/(3*sqrt(3)*det) - 1
            double shape_metric = 0.0;
            if (std::fabs(detAi) > 1.e-15)
              {
                inverse(W, WI);
                product(A, WI, T);
                double d = det(T);
                double f = my_sqr_Frobenius(T);
                if (spatialDim==2)
                  {
                    // all our jacobians are 3D, with a 1 in the 3,3 slot for 2d, so we subtract it here
                    f = f - 1.0;
                    f = std::sqrt(f);
                    double fac = 2.0;
                    double den = fac * d;
                    shape_metric = (f*f)/den - 1.0;
                  }
                else
                  {
                    f = std::sqrt(f);
                    double fac = 3.0*std::sqrt(3.0);
                    double den = fac * d;
                    shape_metric = (f*f*f)/den - 1.0;
                  }
                //shape_metric = std::fabs(shape_metric);
                //shape_metric = f/std::pow(den,1./3.) - 1.0;
              }
            val_shape += shape_metric;
            //val_shape += std::fabs(shape_metric);
            //val_shape += shape_metric*shape_metric;
          }
        val = val_shape;
        //val = val_shape*val_shape;
        return val;
      }
Exemple #18
0
static void pp_group_load(const gmx_mtop_t *mtop, const t_inputrec *ir,
                          matrix box,
                          int *nq_tot, int *nlj_tot,
                          double *cost_pp,
                          gmx_bool *bChargePerturbed, gmx_bool *bTypePerturbed)
{
    t_atom        *atom;
    int            mb, nmol, atnr, cg, a, a0, ncqlj, ncq, nclj;
    gmx_bool       bBHAM, bLJcut, bWater, bQ, bLJ;
    int            nw, nqlj, nq, nlj;
    float          fq, fqlj, flj, fqljw, fqw;
    t_iparams     *iparams;
    gmx_moltype_t *molt;

    bBHAM = (mtop->ffparams.functype[0] == F_BHAM);

    bLJcut = ((ir->vdwtype == evdwCUT) && !bBHAM);

    /* Computational cost of bonded, non-bonded and PME calculations.
     * This will be machine dependent.
     * The numbers here are accurate for Intel Core2 and AMD Athlon 64
     * in single precision. In double precision PME mesh is slightly cheaper,
     * although not so much that the numbers need to be adjusted.
     */
    fq    = C_GR_FQ;
    fqlj  = (bLJcut ? C_GR_QLJ_CUT : C_GR_QLJ_TAB);
    flj   = (bLJcut ? C_GR_LJ_CUT  : C_GR_LJ_TAB);
    /* Cost of 1 water with one Q/LJ atom */
    fqljw = (bLJcut ? C_GR_QLJW_CUT : C_GR_QLJW_TAB);
    /* Cost of 1 water with one Q atom or with 1/3 water (LJ negligible) */
    fqw   = C_GR_QW;

    iparams           = mtop->ffparams.iparams;
    atnr              = mtop->ffparams.atnr;
    nw                = 0;
    nqlj              = 0;
    nq                = 0;
    nlj               = 0;
    *bChargePerturbed = FALSE;
    *bTypePerturbed   = FALSE;
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molt = &mtop->moltype[mtop->molblock[mb].type];
        atom = molt->atoms.atom;
        nmol = mtop->molblock[mb].nmol;
        a    = 0;
        for (cg = 0; cg < molt->cgs.nr; cg++)
        {
            bWater = !bBHAM;
            ncqlj  = 0;
            ncq    = 0;
            nclj   = 0;
            a0     = a;
            while (a < molt->cgs.index[cg+1])
            {
                bQ  = (atom[a].q != 0 || atom[a].qB != 0);
                bLJ = (iparams[(atnr+1)*atom[a].type].lj.c6  != 0 ||
                       iparams[(atnr+1)*atom[a].type].lj.c12 != 0);
                if (atom[a].q != atom[a].qB)
                {
                    *bChargePerturbed = TRUE;
                }
                if (atom[a].type != atom[a].typeB)
                {
                    *bTypePerturbed = TRUE;
                }
                /* This if this atom fits into water optimization */
                if (!((a == a0   &&  bQ &&  bLJ) ||
                        (a == a0+1 &&  bQ && !bLJ) ||
                        (a == a0+2 &&  bQ && !bLJ && atom[a].q == atom[a-1].q) ||
                        (a == a0+3 && !bQ &&  bLJ)))
                {
                    bWater = FALSE;
                }
                if (bQ && bLJ)
                {
                    ncqlj++;
                }
                else
                {
                    if (bQ)
                    {
                        ncq++;
                    }
                    if (bLJ)
                    {
                        nclj++;
                    }
                }
                a++;
            }
            if (bWater)
            {
                nw   += nmol;
            }
            else
            {
                nqlj += nmol*ncqlj;
                nq   += nmol*ncq;
                nlj  += nmol*nclj;
            }
        }
    }

    *nq_tot  = nq  + nqlj + nw*3;
    *nlj_tot = nlj + nqlj + nw;

    if (debug)
    {
        fprintf(debug, "nw %d nqlj %d nq %d nlj %d\n", nw, nqlj, nq, nlj);
    }

    /* For the PP non-bonded cost it is (unrealistically) assumed
     * that all atoms are distributed homogeneously in space.
     * Factor 3 is used because a water molecule has 3 atoms
     * (and TIP4P effectively has 3 interactions with (water) atoms)).
     */
    *cost_pp = 0.5*(fqljw*nw*nqlj +
                    fqw  *nw*(3*nw + nq) +
                    fqlj *nqlj*nqlj +
                    fq   *nq*(3*nw + nqlj + nq) +
                    flj  *nlj*(nw + nqlj + nlj))
               *4/3*M_PI*ir->rlist*ir->rlist*ir->rlist/det(box);
}
Exemple #19
0
bool line_check_parallel(line l1, line l2) {
    return fabs(det(l1.a, l1.b, l2.a, l2.b)) < eps;
}
Exemple #20
0
static void pp_verlet_load(const gmx_mtop_t *mtop, const t_inputrec *ir,
                           matrix box,
                           int *nq_tot, int *nlj_tot,
                           double *cost_pp,
                           gmx_bool *bChargePerturbed, gmx_bool *bTypePerturbed)
{
    t_atom        *atom;
    int            mb, nmol, atnr, a, nqlj, nq, nlj;
    gmx_bool       bQRF;
    t_iparams     *iparams;
    gmx_moltype_t *molt;
    real           r_eff;
    double         c_qlj, c_q, c_lj;
    double         nat;
    /* Conversion factor for reference vs SIMD kernel performance.
     * The factor is about right for SSE2/4, but should be 2 higher for AVX256.
     */
#ifdef GMX_DOUBLE
    const real     nbnxn_refkernel_fac = 4.0;
#else
    const real     nbnxn_refkernel_fac = 8.0;
#endif

    bQRF = (EEL_RF(ir->coulombtype) || ir->coulombtype == eelCUT);

    iparams           = mtop->ffparams.iparams;
    atnr              = mtop->ffparams.atnr;
    nqlj              = 0;
    nq                = 0;
    *bChargePerturbed = FALSE;
    *bTypePerturbed   = FALSE;
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molt = &mtop->moltype[mtop->molblock[mb].type];
        atom = molt->atoms.atom;
        nmol = mtop->molblock[mb].nmol;
        for (a = 0; a < molt->atoms.nr; a++)
        {
            if (atom[a].q != 0 || atom[a].qB != 0)
            {
                if (iparams[(atnr+1)*atom[a].type].lj.c6  != 0 ||
                        iparams[(atnr+1)*atom[a].type].lj.c12 != 0)
                {
                    nqlj += nmol;
                }
                else
                {
                    nq += nmol;
                }
            }
            if (atom[a].q != atom[a].qB)
            {
                *bChargePerturbed = TRUE;
            }
            if (atom[a].type != atom[a].typeB)
            {
                *bTypePerturbed = TRUE;
            }
        }
    }

    nlj = mtop->natoms - nqlj - nq;

    *nq_tot  = nqlj + nq;
    *nlj_tot = nqlj + nlj;

    /* Effective cut-off for cluster pair list of 4x4 atoms */
    r_eff = ir->rlist + nbnxn_get_rlist_effective_inc(NBNXN_CPU_CLUSTER_I_SIZE, mtop->natoms/det(box));

    if (debug)
    {
        fprintf(debug, "nqlj %d nq %d nlj %d rlist %.3f r_eff %.3f\n",
                nqlj, nq, nlj, ir->rlist, r_eff);
    }

    /* Determine the cost per pair interaction */
    c_qlj = (bQRF ? C_VT_QRF_LJ : C_VT_QEXP_LJ);
    c_q   = (bQRF ? C_VT_QRF    : C_VT_QEXP);
    c_lj  = C_VT_LJ;
    if (ir->vdw_modifier == eintmodPOTSWITCH || EVDW_PME(ir->vdwtype))
    {
        c_qlj += C_VT_LJEXP_ADD;
        c_lj  += C_VT_LJEXP_ADD;
    }
    if (EVDW_PME(ir->vdwtype) && ir->ljpme_combination_rule == eljpmeLB)
    {
        /* We don't have LJ-PME LB comb. rule kernels, we use slow kernels */
        c_qlj *= nbnxn_refkernel_fac;
        c_q   *= nbnxn_refkernel_fac;
        c_lj  *= nbnxn_refkernel_fac;
    }

    /* For the PP non-bonded cost it is (unrealistically) assumed
     * that all atoms are distributed homogeneously in space.
     */
    /* Convert mtop->natoms to double to avoid int overflow */
    nat      = mtop->natoms;
    *cost_pp = 0.5*nat*(nqlj*c_qlj + nq*c_q + nlj*c_lj)
               *4/3*M_PI*r_eff*r_eff*r_eff/det(box);
}
static void do_rdf(char *fnNDX,char *fnTPS,char *fnTRX,
		   char *fnRDF,char *fnCNRDF, char *fnHQ,
		   bool bCM,char **rdft,bool bXY,bool bPBC,bool bNormalize,
		   real cutoff,real binwidth,real fade,int ng)
{
  FILE       *fp;
  int        status;
  char       outf1[STRLEN],outf2[STRLEN];
  char       title[STRLEN],gtitle[STRLEN];
  int        g,natoms,i,j,k,nbin,j0,j1,n,nframes;
  int        **count;
  char       **grpname;
  int        *isize,isize_cm=0,nrdf=0,max_i,isize0,isize_g;
  atom_id    **index,*index_cm=NULL;
#if (defined SIZEOF_LONG_LONG_INT) && (SIZEOF_LONG_LONG_INT >= 8)    
  long long int *sum;
#else
  double     *sum;
#endif
  real       t,rmax2,cut2,r,r2,invhbinw,normfac;
  real       segvol,spherevol,prev_spherevol,**rdf;
  rvec       *x,dx,*x0=NULL,*x_i1,xi;
  real       *inv_segvol,invvol,invvol_sum,rho;
  bool       *bExcl,bTop,bNonSelfExcl;
  matrix     box,box_pbc;
  int        **npairs;
  atom_id    ix,jx,***pairs;
  t_topology *top=NULL;
  int        ePBC=-1;
  t_block    *mols=NULL;
  t_blocka   *excl;
  t_atom     *atom=NULL;
  t_pbc      pbc;

  int        *is=NULL,**coi=NULL,cur,mol,i1,res,a;

  excl=NULL;
  
  if (fnTPS) {
    snew(top,1);
    bTop=read_tps_conf(fnTPS,title,top,&ePBC,&x,NULL,box,TRUE);
    if (bTop && !bCM)
      /* get exclusions from topology */
      excl = &(top->excls);
  }
  snew(grpname,ng+1);
  snew(isize,ng+1);
  snew(index,ng+1);
  fprintf(stderr,"\nSelect a reference group and %d group%s\n",
	  ng,ng==1?"":"s");
  if (fnTPS) {
    get_index(&(top->atoms),fnNDX,ng+1,isize,index,grpname);
    atom = top->atoms.atom;
  } else {
    rd_index(fnNDX,ng+1,isize,index,grpname);
  }

  if (rdft[0][0] != 'a') {
    /* Split up all the groups in molecules or residues */
    switch (rdft[0][0]) {
    case 'm':
      mols = &top->mols;
      break;
    case 'r':
      atom = top->atoms.atom;
      break;
    default:
      gmx_fatal(FARGS,"Unknown rdf option '%s'",rdft[0]);
    }
    snew(is,ng+1);
    snew(coi,ng+1);
    for(g=(bCM ? 1 : 0); g<ng+1; g++) {
      snew(coi[g],isize[g]+1);
      is[g] = 0;
      cur = -1;
      mol = 0;
      for(i=0; i<isize[g]; i++) {
	a = index[g][i];
	if (rdft[0][0] == 'm') {
	  /* Check if the molecule number has changed */
	  i1 = mols->index[mol+1];
	  while(a >= i1) {
	    mol++;
	    i1 = mols->index[mol+1];
	  }
	  if (mol != cur) {
	    coi[g][is[g]++] = i;
	    cur = mol;
	  }
	} else if (rdft[0][0] == 'r') {
	  /* Check if the residue number has changed */
	  res = atom[a].resnr;
	  if (res != cur) {
	    coi[g][is[g]++] = i;
	    cur = res;
	  }
	}
      }
      coi[g][is[g]] = i;
      srenew(coi[g],is[g]+1);
      printf("Group '%s' of %d atoms consists of %d %s\n",
	     grpname[g],isize[g],is[g],
	     (rdft[0][0]=='m' ? "molecules" : "residues"));
    }
  } else if (bCM) {
    snew(is,1);
    snew(coi,1);
  }
  
  if (bCM) {
    is[0] = 1;
    snew(coi[0],is[0]+1);
    coi[0][0] = 0;
    coi[0][1] = isize[0];
    isize0 = is[0];
    snew(x0,isize0);
  } else if (rdft[0][0] != 'a') {
    isize0 = is[0];
    snew(x0,isize0);
  } else {
    isize0 = isize[0];
  }
  
  natoms=read_first_x(&status,fnTRX,&t,&x,box);
  if ( !natoms )
    gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
  if (fnTPS)
    /* check with topology */
    if ( natoms > top->atoms.nr ) 
      gmx_fatal(FARGS,"Trajectory (%d atoms) does not match topology (%d atoms)",
		  natoms,top->atoms.nr);
  /* check with index groups */
  for (i=0; i<ng+1; i++)
    for (j=0; j<isize[i]; j++)
      if ( index[i][j] >= natoms )
	gmx_fatal(FARGS,"Atom index (%d) in index group %s (%d atoms) larger "
		  "than number of atoms in trajectory (%d atoms)",
		  index[i][j],grpname[i],isize[i],natoms);
  
  /* initialize some handy things */
  copy_mat(box,box_pbc);
  if (bXY) {
    check_box_c(box);
    /* Make sure the z-height does not influence the cut-off */
    box_pbc[ZZ][ZZ] = 2*max(box[XX][XX],box[YY][YY]);
  }
  if (bPBC)
    rmax2   = 0.99*0.99*max_cutoff2(bXY ? epbcXY : epbcXYZ,box_pbc);
  else
    rmax2   = sqr(3*max(box[XX][XX],max(box[YY][YY],box[ZZ][ZZ])));
  if (debug)
    fprintf(debug,"rmax2 = %g\n",rmax2);

  /* We use the double amount of bins, so we can correctly
   * write the rdf and rdf_cn output at i*binwidth values.
   */
  nbin     = (int)(sqrt(rmax2) * 2 / binwidth);
  invhbinw = 2.0 / binwidth;
  cut2   = sqr(cutoff);

  snew(count,ng);
  snew(pairs,ng);
  snew(npairs,ng);

  snew(bExcl,natoms);
  max_i = 0;
  for(g=0; g<ng; g++) {
    if (isize[g+1] > max_i)
      max_i = isize[g+1];

    /* this is THE array */
    snew(count[g],nbin+1);
  
    /* make pairlist array for groups and exclusions */
    snew(pairs[g],isize[0]);
    snew(npairs[g],isize[0]);
    for(i=0; i<isize[0]; i++) {
      /* We can only have exclusions with atomic rdfs */
      if (!(bCM || rdft[0][0] != 'a')) {
	ix = index[0][i];
	for(j=0; j < natoms; j++)
	  bExcl[j] = FALSE;
	/* exclusions? */
	if (excl)
	  for( j = excl->index[ix]; j < excl->index[ix+1]; j++)
	    bExcl[excl->a[j]]=TRUE;
	k = 0;
	snew(pairs[g][i], isize[g+1]);
	bNonSelfExcl = FALSE;
	for(j=0; j<isize[g+1]; j++) {
	  jx = index[g+1][j];
	  if (!bExcl[jx])
	    pairs[g][i][k++]=jx;
	  else if (ix != jx)
	    /* Check if we have exclusions other than self exclusions */
	    bNonSelfExcl = TRUE;
	}
	if (bNonSelfExcl) {
	  npairs[g][i]=k;
	  srenew(pairs[g][i],npairs[g][i]);
	} else {
	  /* Save a LOT of memory and some cpu cycles */
	  npairs[g][i]=-1;
	  sfree(pairs[g][i]);
	}
      } else {
	npairs[g][i]=-1;
      }
    }
  }
  sfree(bExcl);

  snew(x_i1,max_i);
  nframes = 0;
  invvol_sum = 0;
  do {
    /* Must init pbc every step because of pressure coupling */
    copy_mat(box,box_pbc);
    if (bPBC) {
      if (top != NULL)
	rm_pbc(&top->idef,ePBC,natoms,box,x,x);
      if (bXY) {
	check_box_c(box);
	clear_rvec(box_pbc[ZZ]);
      }
      set_pbc(&pbc,ePBC,box_pbc);

      if (bXY)
	/* Set z-size to 1 so we get the surface iso the volume */
	box_pbc[ZZ][ZZ] = 1;
    }
    invvol = 1/det(box_pbc);
    invvol_sum += invvol;

    if (bCM) {
      /* Calculate center of mass of the whole group */
      calc_comg(is[0],coi[0],index[0],TRUE           ,atom,x,x0);
    } else if (rdft[0][0] != 'a') {
      calc_comg(is[0],coi[0],index[0],rdft[0][6]=='m',atom,x,x0);
    }

    for(g=0; g<ng; g++) {
      if (rdft[0][0] == 'a') {
	/* Copy the indexed coordinates to a continuous array */
	for(i=0; i<isize[g+1]; i++)
	  copy_rvec(x[index[g+1][i]],x_i1[i]);
      } else {
	/* Calculate the COMs/COGs and store in x_i1 */
	calc_comg(is[g+1],coi[g+1],index[g+1],rdft[0][6]=='m',atom,x,x_i1);
      }
    
      for(i=0; i<isize0; i++) {
	if (bCM || rdft[0][0] != 'a') {
	  copy_rvec(x0[i],xi);
	} else {
	  copy_rvec(x[index[0][i]],xi);
	}
	if (rdft[0][0] == 'a' && npairs[g][i] >= 0) {
	  /* Expensive loop, because of indexing */
	  for(j=0; j<npairs[g][i]; j++) {
	    jx=pairs[g][i][j];
	    if (bPBC)
	      pbc_dx(&pbc,xi,x[jx],dx);
	    else
	      rvec_sub(xi,x[jx],dx);
	      
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	} else {
	  /* Cheaper loop, no exclusions */
	  if (rdft[0][0] == 'a')
	    isize_g = isize[g+1];
	  else
	    isize_g = is[g+1];
	  for(j=0; j<isize_g; j++) {
	    if (bPBC)
	      pbc_dx(&pbc,xi,x_i1[j],dx);
	    else
	      rvec_sub(xi,x_i1[j],dx);
	    if (bXY)
	      r2 = dx[XX]*dx[XX] + dx[YY]*dx[YY];
	    else 
	      r2=iprod(dx,dx);
	    if (r2>cut2 && r2<=rmax2)
	      count[g][(int)(sqrt(r2)*invhbinw)]++;
	  }
	}
      }
    }
    nframes++;
  } while (read_next_x(status,&t,natoms,x,box));
  fprintf(stderr,"\n");
  
  close_trj(status);
  
  sfree(x);
  
  /* Average volume */
  invvol = invvol_sum/nframes;

  /* Calculate volume of sphere segments or length of circle segments */
  snew(inv_segvol,(nbin+1)/2);
  prev_spherevol=0;
  for(i=0; (i<(nbin+1)/2); i++) {
    r = (i + 0.5)*binwidth;
    if (bXY) {
      spherevol=M_PI*r*r;
    } else {
      spherevol=(4.0/3.0)*M_PI*r*r*r;
    }
    segvol=spherevol-prev_spherevol;
    inv_segvol[i]=1.0/segvol;
    prev_spherevol=spherevol;
  }
  
  snew(rdf,ng);
  for(g=0; g<ng; g++) {
    /* We have to normalize by dividing by the number of frames */
    if (rdft[0][0] == 'a')
      normfac = 1.0/(nframes*invvol*isize0*isize[g+1]);
    else
      normfac = 1.0/(nframes*invvol*isize0*is[g+1]);
      
    /* Do the normalization */
    nrdf = max((nbin+1)/2,1+2*fade/binwidth);
    snew(rdf[g],nrdf);
    for(i=0; i<(nbin+1)/2; i++) {
      r = i*binwidth;
      if (i == 0)
	j = count[g][0];
      else
	j = count[g][i*2-1] + count[g][i*2];
      if ((fade > 0) && (r >= fade))
	rdf[g][i] = 1 + (j*inv_segvol[i]*normfac-1)*exp(-16*sqr(r/fade-1));
      else {
	if (bNormalize)
	  rdf[g][i] = j*inv_segvol[i]*normfac;
	else
	  rdf[g][i] = j/(binwidth*isize0*nframes);
      }
    }
    for( ; (i<nrdf); i++)
      rdf[g][i] = 1.0;
  }

  if (rdft[0][0] == 'a') {
    sprintf(gtitle,"Radial distribution");
  } else {
    sprintf(gtitle,"Radial distribution of %s %s",
	    rdft[0][0]=='m' ? "molecule" : "residue",
	    rdft[0][6]=='m' ? "COM" : "COG");
  }
  fp=xvgropen(fnRDF,gtitle,"r","");
  if (ng==1) {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"%s%s - %s\"\n",
	      grpname[0],bCM ? " COM" : "",grpname[1]);
  }
  else {
    if (bPrintXvgrCodes())
      fprintf(fp,"@ subtitle \"reference %s%s\"\n",
	      grpname[0],bCM ? " COM" : "");
    xvgr_legend(fp,ng,grpname+1);
  }
  for(i=0; (i<nrdf); i++) {
    fprintf(fp,"%10g",i*binwidth);
    for(g=0; g<ng; g++)
      fprintf(fp," %10g",rdf[g][i]);
    fprintf(fp,"\n");
  }
  ffclose(fp);
  
  do_view(fnRDF,NULL);

  /* h(Q) function: fourier transform of rdf */  
  if (fnHQ) {
    int nhq = 401;
    real *hq,*integrand,Q;
    
    /* Get a better number density later! */
    rho = isize[1]*invvol;
    snew(hq,nhq);
    snew(integrand,nrdf);
    for(i=0; (i<nhq); i++) {
      Q = i*0.5;
      integrand[0] = 0;
      for(j=1; (j<nrdf); j++) {
	r = j*binwidth;
	integrand[j]  = (Q == 0) ? 1.0 : sin(Q*r)/(Q*r);
	integrand[j] *= 4.0*M_PI*rho*r*r*(rdf[0][j]-1.0);
      }
      hq[i] = print_and_integrate(debug,nrdf,binwidth,integrand,NULL,0);
    }
    fp=xvgropen(fnHQ,"h(Q)","Q(/nm)","h(Q)");
    for(i=0; (i<nhq); i++) 
      fprintf(fp,"%10g %10g\n",i*0.5,hq[i]);
    ffclose(fp);
    do_view(fnHQ,NULL);
    sfree(hq);
    sfree(integrand);
  }
  
  if (fnCNRDF) {  
    normfac = 1.0/(isize0*nframes);
    fp=xvgropen(fnCNRDF,"Cumulative Number RDF","r","number");
    if (ng==1) {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"%s-%s\"\n",grpname[0],grpname[1]);
    }
    else {
      if (bPrintXvgrCodes())
	fprintf(fp,"@ subtitle \"reference %s\"\n",grpname[0]);
      xvgr_legend(fp,ng,grpname+1);
    }
    snew(sum,ng);
    for(i=0; (i<=nbin/2); i++) {
      fprintf(fp,"%10g",i*binwidth);
      for(g=0; g<ng; g++) {
	fprintf(fp," %10g",(real)((double)sum[g]*normfac));
	if (i*2+1 < nbin)
	  sum[g] += count[g][i*2] + count[g][i*2+1];
      }
      fprintf(fp,"\n");
    }
    ffclose(fp);
    sfree(sum);
    
    do_view(fnCNRDF,NULL);
  }

  for(g=0; g<ng; g++)
    sfree(rdf[g]);
  sfree(rdf);
}
Exemple #22
0
static void update_top(t_atoms *atoms,matrix box,int NFILE,t_filenm fnm[],
		       gmx_atomprop_t aps)
{
#define TEMP_FILENM "temp.top"
  FILE   *fpin,*fpout;
  char   buf[STRLEN],buf2[STRLEN],*temp,*topinout;
  int    line;
  bool   bSystem,bMolecules,bSkip;
  int    i,nsol=0;
  double mtot;
  real   vol,mm;
  
  for(i=0; (i<atoms->nres); i++) {
    /* calculate number of SOLvent molecules */
    if ( (strcmp(*atoms->resinfo[i].name,"SOL")==0) ||
	 (strcmp(*atoms->resinfo[i].name,"WAT")==0) ||
	 (strcmp(*atoms->resinfo[i].name,"HOH")==0) )
      nsol++;
  }
  mtot = 0;
  for(i=0; (i<atoms->nr); i++) {
    gmx_atomprop_query(aps,epropMass,
		       *atoms->resinfo[atoms->atom[i].resind].name,
		       *atoms->atomname[i],&mm);
    mtot += mm;
  }
  
  vol=det(box);
  
  fprintf(stderr,"Volume                 :  %10g (nm^3)\n",vol);
  fprintf(stderr,"Density                :  %10g (g/l)\n",
	  (mtot*1e24)/(AVOGADRO*vol));
  fprintf(stderr,"Number of SOL molecules:  %5d   \n\n",nsol);
  
  /* open topology file and append sol molecules */
  topinout  = ftp2fn(efTOP,NFILE,fnm);
  if ( ftp2bSet(efTOP,NFILE,fnm) ) {
    fprintf(stderr,"Processing topology\n");
    fpin = ffopen(topinout,"r");
    fpout= ffopen(TEMP_FILENM,"w");
    line=0;
    bSystem = bMolecules = FALSE;
    while (fgets(buf, STRLEN, fpin)) {
      bSkip=FALSE;
      line++;
      strcpy(buf2,buf);
      if ((temp=strchr(buf2,'\n')) != NULL)
	temp[0]='\0';
      ltrim(buf2);
      if (buf2[0]=='[') {
	buf2[0]=' ';
	if ((temp=strchr(buf2,'\n')) != NULL)
	  temp[0]='\0';
	rtrim(buf2);
	if (buf2[strlen(buf2)-1]==']') {
	  buf2[strlen(buf2)-1]='\0';
	  ltrim(buf2);
	  rtrim(buf2);
	  bSystem=(strcasecmp(buf2,"system")==0);
	  bMolecules=(strcasecmp(buf2,"molecules")==0);
	}
      } else if (bSystem && nsol && (buf[0]!=';') ) {
	/* if sol present, append "in water" to system name */
	rtrim(buf2);
	if (buf2[0] && (!strstr(buf2," water")) ) {
	  sprintf(buf,"%s in water\n",buf2);
	  bSystem = FALSE;
	}
      } else if (bMolecules) {
	/* check if this is a line with solvent molecules */
	sscanf(buf,"%s",buf2);
	if (strcmp(buf2,"SOL")==0) {
	  sscanf(buf,"%*s %d",&i);
	  nsol-=i;
	  if (nsol<0) {
	    bSkip=TRUE;
	    nsol+=i;
	  }
	}
      }
      if (bSkip) {
	if ((temp=strchr(buf,'\n')) != NULL)
	  temp[0]='\0';
	fprintf(stdout,"Removing line #%d '%s' from topology file (%s)\n",
		line,buf,topinout);
      } else
	fprintf(fpout,"%s",buf);
    }
    fclose(fpin);
    if ( nsol ) {
      fprintf(stdout,"Adding line for %d solvent molecules to "
	      "topology file (%s)\n",nsol,topinout);
      fprintf(fpout,"%-15s %5d\n","SOL",nsol);
    }
    fclose(fpout);
    /* use ffopen to generate backup of topinout */
    fpout=ffopen(topinout,"w");
    fclose(fpout);
    rename(TEMP_FILENM,topinout);
  }
#undef TEMP_FILENM
}
	const staticMat2 inverse(const staticMat2& A)
	{
		point2 row0 = A.is_trans() ? point2(A(1,1), -A(1,0)): point2( A(1,1), -A(0,1) );
		point2 row1 = A.is_trans() ? point2(-A(0,1), A(0,0)): point2( -A(1,0), A(0,0) );
		return staticMat2(row0, row1)/det(A);
	}// inverse of a 2x2 matrix by Kramer's formula.
Exemple #24
0
int gmx_genbox(int argc,char *argv[])
{
  const char *desc[] = {
    "Genbox can do one of 3 things:[PAR]",
    
    "1) Generate a box of solvent. Specify -cs and -box. Or specify -cs and",
    "-cp with a structure file with a box, but without atoms.[PAR]",
    
    "2) Solvate a solute configuration, eg. a protein, in a bath of solvent ",
    "molecules. Specify [TT]-cp[tt] (solute) and [TT]-cs[tt] (solvent). ",
    "The box specified in the solute coordinate file ([TT]-cp[tt]) is used,",
    "unless [TT]-box[tt] is set.",
    "If you want the solute to be centered in the box,",
    "the program [TT]editconf[tt] has sophisticated options",
    "to change the box dimensions and center the solute.",
    "Solvent molecules are removed from the box where the ",
    "distance between any atom of the solute molecule(s) and any atom of ",
    "the solvent molecule is less than the sum of the VanderWaals radii of ",
    "both atoms. A database ([TT]vdwradii.dat[tt]) of VanderWaals radii is ",
    "read by the program, atoms not in the database are ",
    "assigned a default distance [TT]-vdwd[tt].",
    "Note that this option will also influence the distances between",
    "solvent molecules if they contain atoms that are not in the database.",
    "[PAR]",
    
    "3) Insert a number ([TT]-nmol[tt]) of extra molecules ([TT]-ci[tt]) ",
    "at random positions.",
    "The program iterates until [TT]nmol[tt] molecules",
    "have been inserted in the box. To test whether an insertion is ",
    "successful the same VanderWaals criterium is used as for removal of ",
    "solvent molecules. When no appropriately ",
    "sized holes (holes that can hold an extra molecule) are available the ",
    "program tries for [TT]-nmol[tt] * [TT]-try[tt] times before giving up. ",
    "Increase -try if you have several small holes to fill.[PAR]",
    
    "The default solvent is Simple Point Charge water (SPC), with coordinates ",
    "from [TT]$GMXLIB/spc216.gro[tt]. These coordinates can also be used",
    "for other 3-site water models, since a short equibilibration will remove",
    "the small differences between the models.",
    "Other solvents are also supported, as well as mixed solvents. The",
    "only restriction to solvent types is that a solvent molecule consists",
    "of exactly one residue. The residue information in the coordinate",
    "files is used, and should therefore be more or less consistent.",
    "In practice this means that two subsequent solvent molecules in the ",
    "solvent coordinate file should have different residue number.",
    "The box of solute is built by stacking the coordinates read from",
    "the coordinate file. This means that these coordinates should be ",
    "equlibrated in periodic boundary conditions to ensure a good",
    "alignment of molecules on the stacking interfaces.",
    "The [TT]-maxsol[tt] option simply adds only the first [TT]-maxsol[tt]",
    "solvent molecules and leaves out the rest would have fit into the box.",
    "[PAR]",
    
    "The program can optionally rotate the solute molecule to align the",
    "longest molecule axis along a box edge. This way the amount of solvent",
    "molecules necessary is reduced.",
    "It should be kept in mind that this only works for",
    "short simulations, as eg. an alpha-helical peptide in solution can ",
    "rotate over 90 degrees, within 500 ps. In general it is therefore ",
    "better to make a more or less cubic box.[PAR]",
    
    "Setting -shell larger than zero will place a layer of water of",
    "the specified thickness (nm) around the solute. Hint: it is a good",
    "idea to put the protein in the center of a box first (using editconf).",
    "[PAR]",
    
    "Finally, genbox will optionally remove lines from your topology file in ",
    "which a number of solvent molecules is already added, and adds a ",
    "line with the total number of solvent molecules in your coordinate file."
  };

  const char *bugs[] = {
    "Molecules must be whole in the initial configurations.",
  };
  
  /* parameter data */
  bool bSol,bProt,bBox;
  char *conf_prot,*confout;
  int  bInsert;
  real *r;
  char *title_ins;
  gmx_atomprop_t aps;
  
  /* protein configuration data */
  char    *title=NULL;
  t_atoms atoms;
  rvec    *x,*v=NULL;
  int     ePBC=-1;
  matrix  box;
  t_pbc   pbc;
    
  /* other data types */
  int  atoms_added,residues_added;
  
  t_filenm fnm[] = {
    { efSTX, "-cp", "protein", ffOPTRD },
    { efSTX, "-cs", "spc216",  ffLIBOPTRD},
    { efSTX, "-ci", "insert",  ffOPTRD},
    { efSTO, NULL,  NULL,      ffWRITE},
    { efTOP, NULL,  NULL,      ffOPTRW},
  };
#define NFILE asize(fnm)
  
  static int nmol_ins=0,nmol_try=10,seed=1997;
  static real r_distance=0.105,r_shell=0;
  static rvec new_box={0.0,0.0,0.0};
  static bool bReadV=FALSE;
  static int  max_sol = 0;
  t_pargs pa[] = {
    { "-box",    FALSE, etRVEC, {new_box},   
      "box size" },
    { "-nmol",   FALSE, etINT , {&nmol_ins},  
      "no of extra molecules to insert" },
    { "-try",    FALSE, etINT , {&nmol_try},  
      "try inserting -nmol*-try times" },
    { "-seed",   FALSE, etINT , {&seed},      
      "random generator seed"},
    { "-vdwd",   FALSE, etREAL, {&r_distance},
      "default vdwaals distance"},
    { "-shell",  FALSE, etREAL, {&r_shell},
      "thickness of optional water layer around solute" },
    { "-maxsol", FALSE, etINT,  {&max_sol},
      "maximum number of solvent molecules to add if they fit in the box. If zero (default) this is ignored" },
    { "-vel",    FALSE, etBOOL, {&bReadV},
      "keep velocities from input solute and solvent" }
  };

  CopyRight(stderr,argv[0]);
  parse_common_args(&argc,argv, PCA_BE_NICE,NFILE,fnm,asize(pa),pa,
		    asize(desc),desc,asize(bugs),bugs);
  
  bInsert   = opt2bSet("-ci",NFILE,fnm) && (nmol_ins > 0);
  bSol      = opt2bSet("-cs",NFILE,fnm);
  bProt     = opt2bSet("-cp",NFILE,fnm);
  bBox      = opt2parg_bSet("-box",asize(pa),pa);
     
  /* check input */
  if (bInsert && nmol_ins<=0)
    gmx_fatal(FARGS,"When specifying inserted molecules (-ci), "
		"-nmol must be larger than 0");
  if (!bProt && !bBox)
    gmx_fatal(FARGS,"When no solute (-cp) is specified, "
		"a box size (-box) must be specified");

  aps = gmx_atomprop_init();
  
  if (bProt) {
    /*generate a solute configuration */
    conf_prot = opt2fn("-cp",NFILE,fnm);
    title = read_prot(conf_prot,&atoms,&x,bReadV?&v:NULL,&r,&ePBC,box,
		      aps,r_distance);
    if (bReadV && !v)
      fprintf(stderr,"Note: no velocities found\n");
    if (atoms.nr == 0) {
      fprintf(stderr,"Note: no atoms in %s\n",conf_prot);
      bProt = FALSE;
    }
  } 
  if (!bProt) {
    atoms.nr=0;
    atoms.nres=0;
    atoms.resinfo=NULL;
    atoms.atomname=NULL;
    atoms.atom=NULL;
    atoms.pdbinfo=NULL;
    x=NULL;
    r=NULL;
  }
  if (bBox) {
    ePBC = epbcXYZ;
    clear_mat(box);
    box[XX][XX]=new_box[XX];
    box[YY][YY]=new_box[YY];
    box[ZZ][ZZ]=new_box[ZZ];
  }
  if (det(box) == 0) 
    gmx_fatal(FARGS,"Undefined solute box.\nCreate one with editconf "
		"or give explicit -box command line option");
  
  /* add nmol_ins molecules of atoms_ins 
     in random orientation at random place */
  if (bInsert) 
    title_ins = insert_mols(opt2fn("-ci",NFILE,fnm),nmol_ins,nmol_try,seed,
			    &atoms,&x,&r,ePBC,box,aps,r_distance,r_shell);
  else
    title_ins = strdup("Generated by genbox");
  
  /* add solvent */
  if (bSol)
    add_solv(opt2fn("-cs",NFILE,fnm),&atoms,&x,v?&v:NULL,&r,ePBC,box,
	     aps,r_distance,&atoms_added,&residues_added,r_shell,max_sol);
	     
  /* write new configuration 1 to file confout */
  confout = ftp2fn(efSTO,NFILE,fnm);
  fprintf(stderr,"Writing generated configuration to %s\n",confout);
  if (bProt) {
    write_sto_conf(confout,title,&atoms,x,v,ePBC,box);
    /* print box sizes and box type to stderr */
    fprintf(stderr,"%s\n",title);  
  } else 
    write_sto_conf(confout,title_ins,&atoms,x,v,ePBC,box);
  
  /* print size of generated configuration */
  fprintf(stderr,"\nOutput configuration contains %d atoms in %d residues\n",
	  atoms.nr,atoms.nres);
  update_top(&atoms,box,NFILE,fnm,aps);
	  
  gmx_atomprop_destroy(aps);
  
  thanx(stderr);
  
  return 0;
}
Exemple #25
0
double Vect2::det(const Vect2& v) const {
	return det(v.x,v.y);
}
Exemple #26
0
int gmx_genion(int argc, char *argv[])
{
  const char *desc[] = {
    "[TT]genion[tt] replaces solvent molecules by monoatomic ions at",
    "the position of the first atoms with the most favorable electrostatic",
    "potential or at random. The potential is calculated on all atoms, using",
    "normal GROMACS particle-based methods (in contrast to other methods",
    "based on solving the Poisson-Boltzmann equation).",
    "The potential is recalculated after every ion insertion.",
    "If specified in the run input file, a reaction field, shift function",
    "or user function can be used. For the user function a table file",
    "can be specified with the option [TT]-table[tt].",
    "The group of solvent molecules should be continuous and all molecules",
    "should have the same number of atoms.",
    "The user should add the ion molecules to the topology file 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]",
    "With the option [TT]-pot[tt] the potential can be written as B-factors",
    "in a [TT].pdb[tt] file (for visualisation using e.g. Rasmol).",
    "The unit of the potential is 1000 kJ/(mol e), the scaling be changed",
    "with the [TT]-scale[tt] option.[PAR]",
    "For larger ions, e.g. sulfate we recommended using [TT]genbox[tt]."
  };
  const char *bugs[] = {
    "Calculation of the potential is not reliable, therefore the [TT]-random[tt] option is now turned on by default.",
    "If you specify a salt concentration existing ions are not taken into account. In effect you therefore specify the amount of salt to be added."
  };
  static int  p_num=0,n_num=0,p_q=1,n_q=-1;
  static const char *p_name="NA",*n_name="CL";
  static real rmin=0.6,scale=0.001,conc=0;
  static int  seed=1993;
  static gmx_bool bRandom=TRUE,bNeutral=FALSE;
  static t_pargs pa[] = {
    { "-np",    FALSE, etINT,  {&p_num}, "Number of positive ions"       },
    { "-pname", FALSE, etSTR,  {&p_name},"Name of the positive ion"      },
    { "-pq",    FALSE, etINT,  {&p_q},   "Charge of the positive ion"    },
    { "-nn",    FALSE, etINT,  {&n_num}, "Number of negative ions"       },
    { "-nname", FALSE, etSTR,  {&n_name},"Name of the negative ion"      },
    { "-nq",    FALSE, etINT,  {&n_q},   "Charge of the negative ion"    },
    { "-rmin",  FALSE, etREAL, {&rmin},  "Minimum distance between ions" },
    { "-random",FALSE,etBOOL, {&bRandom},"Use random placement of ions instead of based on potential. The rmin option should still work" },
    { "-seed",  FALSE, etINT,  {&seed},  "Seed for random number generator" },
    { "-scale", FALSE, etREAL, {&scale}, "Scaling factor for the potential for [TT]-pot[tt]" },
    { "-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 [TT].tpr[tt] 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. In combination with the concentration option a neutral system at a given salt concentration will be generated." }
  };
  gmx_mtop_t  *mtop;
  gmx_localtop_t *top;
  t_inputrec  inputrec;
  t_commrec   *cr;
  t_mdatoms   *mdatoms;
  gmx_enerdata_t enerd;
  t_graph     *graph;
  t_forcerec  *fr;
  rvec        *x,*v;
  real        *pot,vol,qtot;
  matrix      box;
  t_atoms     atoms;
  t_pbc       pbc;
  int         *repl;
  atom_id     *index;
  char        *grpname;
  gmx_bool        *bSet,bPDB;
  int         i,nw,nwa,nsa,nsalt,iqtot;
  FILE        *fplog;
  output_env_t oenv;
  t_filenm fnm[] = {
    { efTPX, NULL,  NULL,      ffREAD  },
    { efXVG, "-table","table", ffOPTRD },
    { efNDX, NULL,  NULL,      ffOPTRD },
    { efSTO, "-o",  NULL,      ffWRITE },
    { efLOG, "-g",  "genion",  ffWRITE },
    { efPDB, "-pot", "pot",    ffOPTWR },
    { efTOP, "-p",  "topol",   ffOPTRW }
  };
#define NFILE asize(fnm)
  
  parse_common_args(&argc,argv,PCA_BE_NICE,NFILE,fnm,asize(pa),pa,
                    asize(desc),desc, asize(bugs),bugs,&oenv);
  bPDB = ftp2bSet(efPDB,NFILE,fnm);
  if (bRandom && bPDB) {
    fprintf(stderr,"Not computing potential with random option!\n");
    bPDB = FALSE;
  }
    
  /* Check input for something sensible */
  if ((p_num<0) || (n_num<0))
    gmx_fatal(FARGS,"Negative number of ions to add?");

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

  atoms = gmx_mtop_global_atoms(mtop);

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

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

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

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

  gmx_log_close(fplog);
  
  return 0;
}
bool AffineTransform::isInvertible() const
{
    return det() != 0.0;
}
void Foam::threePhaseInterfaceProperties::correctContactAngle
(
    surfaceVectorField::GeometricBoundaryField& nHatb
) const
{
    const volScalarField::GeometricBoundaryField& alpha1 =
        mixture_.alpha1().boundaryField();
    const volScalarField::GeometricBoundaryField& alpha2 =
        mixture_.alpha2().boundaryField();
    const volScalarField::GeometricBoundaryField& alpha3 =
        mixture_.alpha3().boundaryField();
    const volVectorField::GeometricBoundaryField& U =
        mixture_.U().boundaryField();

    const fvMesh& mesh = mixture_.U().mesh();
    const fvBoundaryMesh& boundary = mesh.boundary();

    forAll(boundary, patchi)
    {
        if (isA<alphaContactAngleFvPatchScalarField>(alpha1[patchi]))
        {
            const alphaContactAngleFvPatchScalarField& a2cap =
                refCast<const alphaContactAngleFvPatchScalarField>
                (alpha2[patchi]);

            const alphaContactAngleFvPatchScalarField& a3cap =
                refCast<const alphaContactAngleFvPatchScalarField>
                (alpha3[patchi]);

            scalarField twoPhaseAlpha2(max(a2cap, scalar(0)));
            scalarField twoPhaseAlpha3(max(a3cap, scalar(0)));

            scalarField sumTwoPhaseAlpha
            (
                twoPhaseAlpha2 + twoPhaseAlpha3 + SMALL
            );

            twoPhaseAlpha2 /= sumTwoPhaseAlpha;
            twoPhaseAlpha3 /= sumTwoPhaseAlpha;

            fvsPatchVectorField& nHatp = nHatb[patchi];

            scalarField theta
            (
                convertToRad
              * (
                   twoPhaseAlpha2*(180 - a2cap.theta(U[patchi], nHatp))
                 + twoPhaseAlpha3*(180 - a3cap.theta(U[patchi], nHatp))
                )
            );

            vectorField nf(boundary[patchi].nf());

            // Reset nHatPatch to correspond to the contact angle

            scalarField a12(nHatp & nf);

            scalarField b1(cos(theta));

            scalarField b2(nHatp.size());

            forAll(b2, facei)
            {
                b2[facei] = cos(acos(a12[facei]) - theta[facei]);
            }

            scalarField det(1.0 - a12*a12);

            scalarField a((b1 - a12*b2)/det);
            scalarField b((b2 - a12*b1)/det);

            nHatp = a*nf + b*nHatp;

            nHatp /= (mag(nHatp) + deltaN_.value());
        }
    }
Exemple #29
0
	KdTree::ObstacleTreeNode *KdTree::buildObstacleTreeRecursive(const std::vector<Obstacle *> &obstacles)
	{
		if (obstacles.empty()) {
			return NULL;
		}
		else {
			ObstacleTreeNode *const node = new ObstacleTreeNode;

			size_t optimalSplit = 0;
			size_t minLeft = obstacles.size();
			size_t minRight = obstacles.size();

			for (size_t i = 0; i < obstacles.size(); ++i) {
				size_t leftSize = 0;
				size_t rightSize = 0;

				const Obstacle *const obstacleI1 = obstacles[i];
				const Obstacle *const obstacleI2 = obstacleI1->nextObstacle_;

				/* Compute optimal split node. */
				for (size_t j = 0; j < obstacles.size(); ++j) {
					if (i == j) {
						continue;
					}

					const Obstacle *const obstacleJ1 = obstacles[j];
					const Obstacle *const obstacleJ2 = obstacleJ1->nextObstacle_;

					const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
					const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);

					if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
						++leftSize;
					}
					else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
						++rightSize;
					}
					else {
						++leftSize;
						++rightSize;
					}

					if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) >= std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
						break;
					}
				}

				if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) < std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
					minLeft = leftSize;
					minRight = rightSize;
					optimalSplit = i;
				}
			}

			/* Build split node. */
			std::vector<Obstacle *> leftObstacles(minLeft);
			std::vector<Obstacle *> rightObstacles(minRight);

			size_t leftCounter = 0;
			size_t rightCounter = 0;
			const size_t i = optimalSplit;

			const Obstacle *const obstacleI1 = obstacles[i];
			const Obstacle *const obstacleI2 = obstacleI1->nextObstacle_;

			for (size_t j = 0; j < obstacles.size(); ++j) {
				if (i == j) {
					continue;
				}

				Obstacle *const obstacleJ1 = obstacles[j];
				Obstacle *const obstacleJ2 = obstacleJ1->nextObstacle_;

				const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
				const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);

				if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
					leftObstacles[leftCounter++] = obstacles[j];
				}
				else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
					rightObstacles[rightCounter++] = obstacles[j];
				}
				else {
					/* Split obstacle j. */
					const float t = det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleI1->point_) / det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleJ2->point_);

					const Vector2 splitpoint = obstacleJ1->point_ + t * (obstacleJ2->point_ - obstacleJ1->point_);

					Obstacle *const newObstacle = new Obstacle();
					newObstacle->point_ = splitpoint;
					newObstacle->prevObstacle_ = obstacleJ1;
					newObstacle->nextObstacle_ = obstacleJ2;
					newObstacle->isConvex_ = true;
					newObstacle->unitDir_ = obstacleJ1->unitDir_;

					newObstacle->id_ = sim_->obstacles_.size();

					sim_->obstacles_.push_back(newObstacle);

					obstacleJ1->nextObstacle_ = newObstacle;
					obstacleJ2->prevObstacle_ = newObstacle;

					if (j1LeftOfI > 0.0f) {
						leftObstacles[leftCounter++] = obstacleJ1;
						rightObstacles[rightCounter++] = newObstacle;
					}
					else {
						rightObstacles[rightCounter++] = obstacleJ1;
						leftObstacles[leftCounter++] = newObstacle;
					}
				}
			}

			node->obstacle = obstacleI1;
			node->left = buildObstacleTreeRecursive(leftObstacles);
			node->right = buildObstacleTreeRecursive(rightObstacles);
			return node;
		}
	}
Exemple #30
0
double do_tpi(FILE *fplog,t_commrec *cr,
              int nfile, const t_filenm fnm[],
              const output_env_t oenv, gmx_bool bVerbose,gmx_bool 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;
}