示例#1
0
void calc_disres_R_6(int nfa, const t_iatom forceatoms[], const t_iparams ip[],
                     const rvec x[], const t_pbc *pbc,
                     t_fcdata *fcd, history_t *hist)
{
    int             ai, aj;
    int             fa, res, pair;
    int             type, npair, np;
    rvec            dx;
    real           *rt, *rm3tav, *Rtl_6, *Rt_6, *Rtav_6;
    real            rt_1, rt_3, rt2;
    t_disresdata   *dd;
    real            ETerm, ETerm1, cf1 = 0, cf2 = 0, invn = 0;
    gmx_bool        bTav;

    dd           = &(fcd->disres);
    bTav         = (dd->dr_tau != 0);
    ETerm        = dd->ETerm;
    ETerm1       = dd->ETerm1;
    rt           = dd->rt;
    rm3tav       = dd->rm3tav;
    Rtl_6        = dd->Rtl_6;
    Rt_6         = dd->Rt_6;
    Rtav_6       = dd->Rtav_6;

    if (bTav)
    {
        /* scaling factor to smoothly turn on the restraint forces *
         * when using time averaging                               */
        dd->exp_min_t_tau = hist->disre_initf*ETerm;

        cf1 = dd->exp_min_t_tau;
        cf2 = 1.0/(1.0 - dd->exp_min_t_tau);
    }

    if (dd->nsystems > 1)
    {
        invn = 1.0/dd->nsystems;
    }

    /* 'loop' over all atom pairs (pair_nr=fa/3) involved in restraints, *
     * the total number of atoms pairs is nfa/3                          */
    res = 0;
    fa  = 0;
    while (fa < nfa)
    {
        type  = forceatoms[fa];
        npair = ip[type].disres.npair;

        Rtav_6[res] = 0.0;
        Rt_6[res]   = 0.0;

        /* Loop over the atom pairs of 'this' restraint */
        np = 0;
        while (fa < nfa && np < npair)
        {
            pair = fa/3;
            ai   = forceatoms[fa+1];
            aj   = forceatoms[fa+2];

            if (pbc)
            {
                pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
            }
            else
            {
                rvec_sub(x[ai], x[aj], dx);
            }
            rt2  = iprod(dx, dx);
            rt_1 = gmx::invsqrt(rt2);
            rt_3 = rt_1*rt_1*rt_1;

            rt[pair]         = std::sqrt(rt2);
            if (bTav)
            {
                /* Here we update rm3tav in t_fcdata using the data
                 * in history_t.
                 * Thus the results stay correct when this routine
                 * is called multiple times.
                 */
                rm3tav[pair] = cf2*((ETerm - cf1)*hist->disre_rm3tav[pair] +
                                    ETerm1*rt_3);
            }
            else
            {
                rm3tav[pair] = rt_3;
            }

            Rt_6[res]       += rt_3*rt_3;
            Rtav_6[res]     += rm3tav[pair]*rm3tav[pair];

            fa += 3;
            np++;
        }
        if (dd->nsystems > 1)
        {
            Rtl_6[res]   = Rt_6[res];
            Rt_6[res]   *= invn;
            Rtav_6[res] *= invn;
        }

        res++;
    }
}
示例#2
0
real ta_disres(int nfa, const t_iatom forceatoms[], const t_iparams ip[],
               const rvec x[], rvec4 f[], rvec fshift[],
               const t_pbc *pbc, const t_graph *g,
               real gmx_unused lambda, real gmx_unused *dvdlambda,
               const t_mdatoms gmx_unused *md, t_fcdata *fcd,
               int gmx_unused *global_atom_index)
{
    const real      seven_three = 7.0/3.0;

    int             ai, aj;
    int             fa, res, npair, p, pair, ki = CENTRAL, m;
    int             type;
    rvec            dx;
    real            weight_rt_1;
    real            smooth_fc, Rt, Rtav, rt2, *Rtl_6, *Rt_6, *Rtav_6;
    real            k0, f_scal = 0, fmax_scal, fk_scal, fij;
    real            tav_viol, instant_viol, mixed_viol, violtot, vtot;
    real            tav_viol_Rtav7, instant_viol_Rtav7;
    real            up1, up2, low;
    gmx_bool        bConservative, bMixed, bViolation;
    ivec            dt;
    t_disresdata   *dd;
    int             dr_weighting;
    gmx_bool        dr_bMixed;

    dd           = &(fcd->disres);
    dr_weighting = dd->dr_weighting;
    dr_bMixed    = dd->dr_bMixed;
    Rtl_6        = dd->Rtl_6;
    Rt_6         = dd->Rt_6;
    Rtav_6       = dd->Rtav_6;

    tav_viol = instant_viol = mixed_viol = tav_viol_Rtav7 = instant_viol_Rtav7 = 0;

    smooth_fc = dd->dr_fc;
    if (dd->dr_tau != 0)
    {
        /* scaling factor to smoothly turn on the restraint forces *
         * when using time averaging                               */
        smooth_fc *= (1.0 - dd->exp_min_t_tau);
    }

    violtot = 0;
    vtot    = 0;

    /* 'loop' over all atom pairs (pair_nr=fa/3) involved in restraints, *
     * the total number of atoms pairs is nfa/3                          */
    res  = 0;
    fa   = 0;
    while (fa < nfa)
    {
        type  = forceatoms[fa];
        /* Take action depending on restraint, calculate scalar force */
        npair = ip[type].disres.npair;
        up1   = ip[type].disres.up1;
        up2   = ip[type].disres.up2;
        low   = ip[type].disres.low;
        k0    = smooth_fc*ip[type].disres.kfac;

        /* save some flops when there is only one pair */
        if (ip[type].disres.type != 2)
        {
            bConservative = (dr_weighting == edrwConservative) && (npair > 1);
            bMixed        = dr_bMixed;
            Rt            = gmx::invsixthroot(Rt_6[res]);
            Rtav          = gmx::invsixthroot(Rtav_6[res]);
        }
        else
        {
            /* When rtype=2 use instantaneous not ensemble avereged distance */
            bConservative = (npair > 1);
            bMixed        = FALSE;
            Rt            = gmx::invsixthroot(Rtl_6[res]);
            Rtav          = Rt;
        }

        if (Rtav > up1)
        {
            bViolation = TRUE;
            tav_viol   = Rtav - up1;
        }
        else if (Rtav < low)
        {
            bViolation = TRUE;
            tav_viol   = Rtav - low;
        }
        else
        {
            bViolation = FALSE;
        }

        if (bViolation)
        {
            /* NOTE:
             * there is no real potential when time averaging is applied
             */
            vtot += 0.5*k0*gmx::square(tav_viol);
            if (1/vtot == 0)
            {
                printf("vtot is inf: %f\n", vtot);
            }
            if (!bMixed)
            {
                f_scal   = -k0*tav_viol;
                violtot += fabs(tav_viol);
            }
            else
            {
                if (Rt > up1)
                {
                    if (tav_viol > 0)
                    {
                        instant_viol = Rt - up1;
                    }
                    else
                    {
                        bViolation = FALSE;
                    }
                }
                else if (Rt < low)
                {
                    if (tav_viol < 0)
                    {
                        instant_viol = Rt - low;
                    }
                    else
                    {
                        bViolation = FALSE;
                    }
                }
                else
                {
                    bViolation = FALSE;
                }
                if (bViolation)
                {
                    mixed_viol = std::sqrt(tav_viol*instant_viol);
                    f_scal     = -k0*mixed_viol;
                    violtot   += mixed_viol;
                }
            }
        }

        if (bViolation)
        {
            fmax_scal = -k0*(up2-up1);
            /* Correct the force for the number of restraints */
            if (bConservative)
            {
                f_scal  = std::max(f_scal, fmax_scal);
                if (!bMixed)
                {
                    f_scal *= Rtav/Rtav_6[res];
                }
                else
                {
                    f_scal            /= 2*mixed_viol;
                    tav_viol_Rtav7     = tav_viol*Rtav/Rtav_6[res];
                    instant_viol_Rtav7 = instant_viol*Rt/Rt_6[res];
                }
            }
            else
            {
                f_scal /= npair;
                f_scal  = std::max(f_scal, fmax_scal);
            }

            /* Exert the force ... */

            /* Loop over the atom pairs of 'this' restraint */
            for (p = 0; p < npair; p++)
            {
                pair = fa/3;
                ai   = forceatoms[fa+1];
                aj   = forceatoms[fa+2];

                if (pbc)
                {
                    ki = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
                }
                else
                {
                    rvec_sub(x[ai], x[aj], dx);
                }
                rt2 = iprod(dx, dx);

                weight_rt_1 = gmx::invsqrt(rt2);

                if (bConservative)
                {
                    if (!dr_bMixed)
                    {
                        weight_rt_1 *= std::pow(dd->rm3tav[pair], seven_three);
                    }
                    else
                    {
                        weight_rt_1 *= tav_viol_Rtav7*std::pow(dd->rm3tav[pair], seven_three)+
                            instant_viol_Rtav7/(dd->rt[pair]*gmx::power6(dd->rt[pair]));
                    }
                }

                fk_scal  = f_scal*weight_rt_1;

                if (g)
                {
                    ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
                    ki = IVEC2IS(dt);
                }

                for (m = 0; m < DIM; m++)
                {
                    fij            = fk_scal*dx[m];

                    f[ai][m]           += fij;
                    f[aj][m]           -= fij;
                    fshift[ki][m]      += fij;
                    fshift[CENTRAL][m] -= fij;
                }
                fa += 3;
            }
        }
        else
        {
            /* No violation so force and potential contributions */
            fa += 3*npair;
        }
        res++;
    }

    dd->sumviol = violtot;

    /* Return energy */
    return vtot;
}
示例#3
0
int gmx_rotacf(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] calculates the rotational correlation function",
        "for molecules. Atom triplets (i,j,k) must be given in the index",
        "file, defining two vectors ij and jk. The rotational ACF",
        "is calculated as the autocorrelation function of the vector",
        "n = ij x jk, i.e. the cross product of the two vectors.",
        "Since three atoms span a plane, the order of the three atoms",
        "does not matter. Optionally, by invoking the [TT]-d[tt] switch, you can",
        "calculate the rotational correlation function for linear molecules",
        "by specifying atom pairs (i,j) in the index file.",
        "[PAR]",
        "EXAMPLES[PAR]",
        "[TT]gmx rotacf -P 1 -nparm 2 -fft -n index -o rotacf-x-P1",
        "-fa expfit-x-P1 -beginfit 2.5 -endfit 20.0[tt][PAR]",
        "This will calculate the rotational correlation function using a first",
        "order Legendre polynomial of the angle of a vector defined by the index",
        "file. The correlation function will be fitted from 2.5 ps until 20.0 ps",
        "to a two-parameter exponential."
    };
    static gmx_bool bVec    = FALSE, bAver = TRUE;

    t_pargs         pa[] = {
        { "-d",   FALSE, etBOOL, {&bVec},
          "Use index doublets (vectors) for correlation function instead of triplets (planes)" },
        { "-aver", FALSE, etBOOL, {&bAver},
          "Average over molecules" }
    };

    t_trxstatus    *status;
    int             isize;
    atom_id        *index;
    char           *grpname;
    rvec           *x, *x_s;
    matrix          box;
    real          **c1;
    rvec            xij, xjk, n;
    int             i, m, teller, n_alloc, natoms, nvec, ai, aj, ak;
    unsigned long   mode;
    real            t, t0, t1, dt;
    gmx_rmpbc_t     gpbc = NULL;
    t_topology     *top;
    int             ePBC;
    t_filenm        fnm[] = {
        { efTRX, "-f", NULL,  ffREAD  },
        { efTPR, NULL, NULL,  ffREAD },
        { efNDX, NULL, NULL,  ffREAD  },
        { efXVG, "-o", "rotacf",  ffWRITE }
    };
#define NFILE asize(fnm)
    int             npargs;
    t_pargs        *ppa;

    output_env_t    oenv;

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

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

    rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);

    if (bVec)
    {
        nvec = isize/2;
    }
    else
    {
        nvec = isize/3;
    }

    if (((isize % 3) != 0) && !bVec)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of 3, "
                  "these can not be atom triplets\n");
    }
    if (((isize % 2) != 0) && bVec)
    {
        gmx_fatal(FARGS, "number of index elements not multiple of 2, "
                  "these can not be atom doublets\n");
    }

    top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);

    snew(c1, nvec);
    for (i = 0; (i < nvec); i++)
    {
        c1[i] = NULL;
    }
    n_alloc = 0;

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

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

    /* Start the loop over frames */
    t1      = t0 = t;
    teller  = 0;
    do
    {
        if (teller >= n_alloc)
        {
            n_alloc += 100;
            for (i = 0; (i < nvec); i++)
            {
                srenew(c1[i], DIM*n_alloc);
            }
        }
        t1 = t;

        /* Remove periodicity */
        gmx_rmpbc_copy(gpbc, natoms, box, x, x_s);

        /* Compute crossproducts for all vectors, if triplets.
         * else, just get the vectors in case of doublets.
         */
        if (bVec == FALSE)
        {
            for (i = 0; (i < nvec); i++)
            {
                ai = index[3*i];
                aj = index[3*i+1];
                ak = index[3*i+2];
                rvec_sub(x_s[ai], x_s[aj], xij);
                rvec_sub(x_s[aj], x_s[ak], xjk);
                cprod(xij, xjk, n);
                for (m = 0; (m < DIM); m++)
                {
                    c1[i][DIM*teller+m] = n[m];
                }
            }
        }
        else
        {
            for (i = 0; (i < nvec); i++)
            {
                ai = index[2*i];
                aj = index[2*i+1];
                rvec_sub(x_s[ai], x_s[aj], n);
                for (m = 0; (m < DIM); m++)
                {
                    c1[i][DIM*teller+m] = n[m];
                }
            }
        }
        /* Increment loop counter */
        teller++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);
    fprintf(stderr, "\nDone with trajectory\n");

    gmx_rmpbc_done(gpbc);


    /* Autocorrelation function */
    if (teller < 2)
    {
        fprintf(stderr, "Not enough frames for correlation function\n");
    }
    else
    {
        dt = (t1 - t0)/(teller-1);

        mode = eacVector;

        do_autocorr(ftp2fn(efXVG, NFILE, fnm), oenv, "Rotational Correlation Function",
                    teller, nvec, c1, dt, mode, bAver);
    }

    do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL);

    return 0;
}
示例#4
0
int gmx_sorient(int argc, char *argv[])
{
    t_topology      top;
    int             ePBC = -1;
    char            title[STRLEN];
    t_trxstatus    *status;
    int             natoms;
    real            t;
    rvec           *xtop, *x;
    matrix          box;

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

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

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

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

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

    two_pi = 2/M_PI;

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

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

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

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

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

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

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

    invrbw = 1/rbinw;

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

    return 0;
}
示例#5
0
文件: orires.c 项目: Chadi-akel/cere
real orires(int nfa,t_iatom forceatoms[],t_iparams ip[],
	    rvec x[],rvec f[],t_forcerec *fr,t_graph *g,
	    matrix box,real lambda,real *dvdlambda,
	    t_mdatoms *md,int ngrp,real egnb[],real egcoul[],
	    t_fcdata *fcd)
{
  atom_id      ai,aj;
  int          fa,d,i,type,ex,power,ki;
  ivec         dt;
  real         r2,invr,invr2,fc,smooth_fc,dev,devins,pfac;
  rvec         r,Sr,fij;
  real         vtot;
  t_oriresdata *od;
  bool         bTAV;

  vtot = 0;
  od = &(fcd->orires);

  if (fabs(od->fc) > GMX_REAL_MIN) {
    bTAV = (fabs(od->edt) > GMX_REAL_MIN);
    
    /* Smoothly switch on the restraining when time averaging is used */
    smooth_fc = od->fc*(1.0 - od->exp_min_t_tau);
    
    d = 0;
    for(fa=0; fa<nfa; fa+=3) {
      type  = forceatoms[fa];
      ai    = forceatoms[fa+1];
      aj    = forceatoms[fa+2];
      rvec_sub(x[ai],x[aj],r);
      r2    = norm2(r);
      invr  = invsqrt(r2);
      invr2 = invr*invr;
      ex    = ip[type].orires.ex;
      power = ip[type].orires.pow;
      fc    = smooth_fc*ip[type].orires.kfac;
      dev   = od->otav[d] - ip[type].orires.obs;
      
      /* NOTE: there is no real potential when time averaging is applied */
      vtot += 0.5*fc*sqr(dev);
      
      if (bTAV) {
	/* Calculate the force as the sqrt of tav times instantaneous */
	devins = od->oins[d] - ip[type].orires.obs;
	if (dev*devins <= 0)
	  dev = 0;
	else {
	  dev = sqrt(dev*devins);
	  if (devins < 0)
	    dev = -dev;
	}
      }
      
      pfac  = fc*ip[type].orires.c*invr2;
      for(i=0; i<power; i++)
	pfac *= invr;
      mvmul(od->S[ex],r,Sr);
      for(i=0; i<DIM; i++)
	fij[i] = -pfac*dev*(4*Sr[i] - 2*(2+power)*invr2*iprod(Sr,r)*r[i]);
      
      ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);
      ki=IVEC2IS(dt);
      
      for(i=0; i<DIM; i++) {
	f[ai][i]               += fij[i];
	f[aj][i]               -= fij[i];
	fr->fshift[ki][i]      += fij[i];
	fr->fshift[CENTRAL][i] -= fij[i];
      }
      d++;
    }
  }
  
  return vtot;
  
  /* Approx. 80*nfa/3 flops */
}
示例#6
0
文件: orires.c 项目: Chadi-akel/cere
real calc_orires_dev(t_commrec *mcr,
		     int nfa,t_iatom forceatoms[],t_iparams ip[],
		     t_mdatoms *md,rvec x[],t_fcdata *fcd)
{
  int          fa,d,i,j,type,ex,nref;
  real         edt,edt1,invn,pfac,r2,invr,corrfac,weight,wsv2,sw,dev;
  tensor       *S,R,TMP;
  rvec5        *Dinsl,*Dins,*Dtav,*rhs;
  real         *mref,***T;
  rvec         *xref,*xtmp,com,r_unrot,r;
  t_oriresdata *od;
  bool         bTAV;
  static real  two_thr=2.0/3.0;

  od = &(fcd->orires);

  bTAV = (fabs(od->edt)>GMX_REAL_MIN);
  edt  = od->edt;
  edt1 = od->edt1;
  S    = od->S;
  Dinsl= od->Dinsl;
  Dins = od->Dins;
  Dtav = od->Dtav;
  T    = od->TMP;
  rhs  = od->tmp;
  nref = od->nref;
  mref = od->mref;
  xref = od->xref;
  xtmp = od->xtmp;
  
  od->exp_min_t_tau *= edt;

  if (mcr)
    invn = 1.0/mcr->nnodes;
  else
    invn = 1.0;

  j=0;
  for(i=0; i<md->nr; i++)
    if (md->cORF[i] == 0) {
      copy_rvec(x[i],xtmp[j]);
      for(d=0; d<DIM; d++)
	com[d] += mref[j]*xref[j][d];
      j++;
    }
  svmul(od->invmref,com,com);
  for(j=0; j<nref; j++)
    rvec_dec(xtmp[j],com);
  /* Calculate the rotation matrix to rotate x to the reference orientation */
  calc_fit_R(nref,mref,xref,xtmp,R);
  copy_mat(R,od->R);

  d = 0;
  for(fa=0; fa<nfa; fa+=3) {
    type = forceatoms[fa];
    rvec_sub(x[forceatoms[fa+1]],x[forceatoms[fa+2]],r_unrot);
    mvmul(R,r_unrot,r);
    r2   = norm2(r);
    invr = invsqrt(r2);
    /* Calculate the prefactor for the D tensor, this includes the factor 3! */
    pfac = ip[type].orires.c*invr*invr*3;
    for(i=0; i<ip[type].orires.pow; i++)
      pfac *= invr;
    Dinsl[d][0] = pfac*(2*r[0]*r[0] + r[1]*r[1] - r2);
    Dinsl[d][1] = pfac*(2*r[0]*r[1]);
    Dinsl[d][2] = pfac*(2*r[0]*r[2]);
    Dinsl[d][3] = pfac*(2*r[1]*r[1] + r[0]*r[0] - r2);
    Dinsl[d][4] = pfac*(2*r[1]*r[2]);

    if (mcr)
      for(i=0; i<5; i++)
	Dins[d][i] = Dinsl[d][i]*invn;
    
    d++;
  }
  
  if (mcr)
    gmx_sum(5*od->nr,Dins[0],mcr);
  
  /* Correction factor to correct for the lack of history for short times */
  corrfac = 1.0/(1.0-od->exp_min_t_tau);
  
  /* Calculate the order tensor S for each experiment via optimization */
  for(ex=0; ex<od->nex; ex++)
    for(i=0; i<5; i++) {
      rhs[ex][i] = 0;
      for(j=0; j<=i; j++)
	T[ex][i][j] = 0;
    }
  d = 0;
  for(fa=0; fa<nfa; fa+=3) {
    if (bTAV)
      for(i=0; i<5; i++)
	Dtav[d][i] = edt*Dtav[d][i] + edt1*Dins[d][i];

    type   = forceatoms[fa];
    ex     = ip[type].orires.ex;
    weight = ip[type].orires.kfac;
    /* Calculate the vector rhs and half the matrix T for the 5 equations */
    for(i=0; i<5; i++) {
      rhs[ex][i] += Dtav[d][i]*ip[type].orires.obs*weight;
      for(j=0; j<=i; j++)
	T[ex][i][j] += Dtav[d][i]*Dtav[d][j]*weight;
    }
    d++;
  }
  /* Now we have all the data we can calculate S */
  for(ex=0; ex<od->nex; ex++) {
    /* Correct corrfac and copy one half of T to the other half */
    for(i=0; i<5; i++) {
      rhs[ex][i]  *= corrfac;
      T[ex][i][i] *= sqr(corrfac);
      for(j=0; j<i; j++) {
	T[ex][i][j] *= sqr(corrfac);
	T[ex][j][i]  = T[ex][i][j];
      }
    }
    m_inv_gen(T[ex],5,T[ex]);
    /* Calculate the orientation tensor S for this experiment */
    S[ex][0][0] = 0;
    S[ex][0][1] = 0;
    S[ex][0][2] = 0;
    S[ex][1][1] = 0;
    S[ex][1][2] = 0;
    for(i=0; i<5; i++) {
      S[ex][0][0] += 1.5*T[ex][0][i]*rhs[ex][i];
      S[ex][0][1] += 1.5*T[ex][1][i]*rhs[ex][i];
      S[ex][0][2] += 1.5*T[ex][2][i]*rhs[ex][i];
      S[ex][1][1] += 1.5*T[ex][3][i]*rhs[ex][i];
      S[ex][1][2] += 1.5*T[ex][4][i]*rhs[ex][i];
    }
    S[ex][1][0] = S[ex][0][1];
    S[ex][2][0] = S[ex][0][2];
    S[ex][2][1] = S[ex][1][2];
    S[ex][2][2] = -S[ex][0][0] - S[ex][1][1];
  }
  
  wsv2 = 0;
  sw   = 0;
  
  d = 0;
  for(fa=0; fa<nfa; fa+=3) {
    type = forceatoms[fa];
    ex = ip[type].orires.ex;

    od->otav[d] = two_thr*
      corrfac*(S[ex][0][0]*Dtav[d][0] + S[ex][0][1]*Dtav[d][1] +
	       S[ex][0][2]*Dtav[d][2] + S[ex][1][1]*Dtav[d][3] +
	       S[ex][1][2]*Dtav[d][4]);
    if (bTAV)
      od->oins[d] = two_thr*(S[ex][0][0]*Dins[d][0] + S[ex][0][1]*Dins[d][1] +
			     S[ex][0][2]*Dins[d][2] + S[ex][1][1]*Dins[d][3] +
			     S[ex][1][2]*Dins[d][4]);
    if (mcr)
      /* When ensemble averaging is used recalculate the local orientation
       * for output to the energy file.
       */
      od->oinsl[d] = two_thr*
	(S[ex][0][0]*Dinsl[d][0] + S[ex][0][1]*Dinsl[d][1] +
	 S[ex][0][2]*Dinsl[d][2] + S[ex][1][1]*Dinsl[d][3] +
	 S[ex][1][2]*Dinsl[d][4]);
    
    dev = od->otav[d] - ip[type].orires.obs;
    
    wsv2 += ip[type].orires.kfac*sqr(dev);
    sw   += ip[type].orires.kfac;
    
    d++;
  }
  od->rmsdev = sqrt(wsv2/sw);
  
  /* Rotate the S matrices back, so we get the correct grad(tr(S D)) */
  for(ex=0; ex<od->nex; ex++) {
    tmmul(R,S[ex],TMP);
    mmul(TMP,R,S[ex]);
  }

  return od->rmsdev;
  
  /* Approx. 120*nfa/3 flops */
}
示例#7
0
real shift_LRcorrection(FILE *fp,int start,int natoms,
			t_commrec *cr,t_forcerec *fr,
			real charge[],t_blocka *excl,rvec x[],
			gmx_bool bOld,matrix box,matrix lr_vir)
{
  static gmx_bool bFirst=TRUE;
  static real Vself;
  int    i,i1,i2,j,k,m,iv,jv;
  int *AA;
  double qq; /* Necessary for precision */
  double isp=0.564189583547756;
  real   qi,dr,dr2,dr_1,dr_3,fscal,Vexcl,qtot=0;
  rvec   df,dx;
  real   r1=fr->rcoulomb_switch;
  real   rc=fr->rcoulomb;
  ivec   shift;     
  
  if (bFirst) {
    qq =0;  
    for(i=start; (i<start+natoms); i++) 
      qq  += charge[i]*charge[i];
    
    /* Obsolete, until we implement dipole and charge corrections.
       qtot=0;
       for(i=0;i<nsb->natoms;i++)
       qtot+=charge[i];
    */
   
    Vself = 0.5*C*ONE_4PI_EPS0*qq;
    if(debug) {
	fprintf(fp,"Long Range corrections for shifted interactions:\n");
	fprintf(fp,"r1 = %g, rc=%g\n",r1,rc);
	fprintf(fp,"start=%d,natoms=%d\n",start,natoms);
	fprintf(fp,"qq = %g, Vself=%g\n",qq,Vself);
    }
    
  }
  AA = excl->a;
  Vexcl = 0;
 
  for(i=start; (i<start+natoms); i++) {
    /* Initiate local variables (for this i-particle) to 0 */
    i1  = excl->index[i];
    i2  = excl->index[i+1];
    qi  = charge[i]*ONE_4PI_EPS0;

    /* Loop over excluded neighbours */
    for(j=i1; (j<i2); j++) {
      k = AA[j];
      /* 
       * First we must test whether k <> i, and then, because the
       * exclusions are all listed twice i->k and k->i we must select
       * just one of the two.
       * As a minor optimization we only compute forces when the charges
       * are non-zero.
       */
      if (k > i) {
	qq = qi*charge[k];
	if (qq != 0.0) {
	  dr2 = 0;
	  rvec_sub(x[i],x[k],dx);
	  for(m=DIM-1; m>=0; m--) {
	    if (dx[m] > 0.5*box[m][m])
	      rvec_dec(dx,box[m]);
	    else if (dx[m] < -0.5*box[m][m])
	      rvec_inc(dx,box[m]);
	    
	    dr2  += dx[m]*dx[m];
	  }
	  dr_1    = gmx_invsqrt(dr2);
	  dr      = 1.0/dr_1;
	  dr_3    = dr_1*dr_1*dr_1;
	  /* Compute exclusion energy and scalar force */

	  Vexcl  += qq*(dr_1-potential(r1,rc,dr));
	  fscal   = qq*(-shiftfunction(r1,rc,dr))*dr_3;
	  
	  if ((fscal != 0) && debug)
	    fprintf(debug,"i: %d, k: %d, dr: %.3f fscal: %.3f\n",i,k,dr,fscal);
	    
	  /* The force vector is obtained by multiplication with the 
	   * distance vector 
	   */
	  svmul(fscal,dx,df);
	  rvec_inc(fr->f_novirsum[k],df);
	  rvec_dec(fr->f_novirsum[i],df);
	  for(iv=0;iv<DIM;iv++)
	      for(jv=0;jv<DIM;jv++)
		  lr_vir[iv][jv]+=0.5*dx[iv]*df[jv];
	}
      }
    }
  }
  if (bFirst && debug)
    fprintf(fp,"Long Range correction: Vexcl=%g\n",Vexcl);
  
  bFirst = FALSE;
  /* Return the correction to the energy */
  return (-(Vself+Vexcl));
}
示例#8
0
int gmx_genpr(int argc, char *argv[])
{
    const char        *desc[] = {
        "[THISMODULE] produces an #include file for a topology containing",
        "a list of atom numbers and three force constants for the",
        "[IT]x[it]-, [IT]y[it]-, and [IT]z[it]-direction based on",
        "the contents of the [TT]-f[tt] file. A single isotropic force constant may",
        "be given on the command line instead of three components.[PAR]",
        "WARNING: Position restraints are interactions within molecules, therefore",
        "they must be included within the correct [TT][ moleculetype ][tt]",
        "block in the topology. The atom indices within the",
        "[TT][ position_restraints ][tt] block must be within the range of the",
        "atom indices for that molecule type. Since the atom numbers in every",
        "moleculetype in the topology start at 1 and the numbers in the input file",
        "for [THISMODULE] number consecutively from 1, [THISMODULE] will only",
        "produce a useful file for the first molecule. You may wish to",
        "edit the resulting index file to remove the lines for later atoms,",
        "or construct a suitable index group to provide",
        "as input to [THISMODULE].[PAR]",
        "The [TT]-of[tt] option produces an index file that can be used for",
        "freezing atoms. In this case, the input file must be a [TT].pdb[tt] file.[PAR]",
        "With the [TT]-disre[tt] option, half a matrix of distance restraints",
        "is generated instead of position restraints. With this matrix, that",
        "one typically would apply to C[GRK]alpha[grk] atoms in a protein, one can",
        "maintain the overall conformation of a protein without tieing it to",
        "a specific position (as with position restraints)."
    };
    static rvec        fc           = {1000.0, 1000.0, 1000.0};
    static real        freeze_level = 0.0;
    static real        disre_dist   = 0.1;
    static real        disre_frac   = 0.0;
    static real        disre_up2    = 1.0;
    static gmx_bool    bDisre       = FALSE;
    static gmx_bool    bConstr      = FALSE;
    static real        cutoff       = -1.0;

    t_pargs            pa[] = {
        { "-fc", FALSE, etRVEC, {fc},
          "Force constants (kJ/mol nm^2)" },
        { "-freeze", FALSE, etREAL, {&freeze_level},
          "If the [TT]-of[tt] option or this one is given an index file will be written containing atom numbers of all atoms that have a B-factor less than the level given here" },
        { "-disre", FALSE, etBOOL, {&bDisre},
          "Generate a distance restraint matrix for all the atoms in index" },
        { "-disre_dist", FALSE, etREAL, {&disre_dist},
          "Distance range around the actual distance for generating distance restraints" },
        { "-disre_frac", FALSE, etREAL, {&disre_frac},
          "Fraction of distance to be used as interval rather than a fixed distance. If the fraction of the distance that you specify here is less than the distance given in the previous option, that one is used instead." },
        { "-disre_up2", FALSE, etREAL, {&disre_up2},
          "Distance between upper bound for distance restraints, and the distance at which the force becomes constant (see manual)" },
        { "-cutoff", FALSE, etREAL, {&cutoff},
          "Only generate distance restraints for atoms pairs within cutoff (nm)" },
        { "-constr", FALSE, etBOOL, {&bConstr},
          "Generate a constraint matrix rather than distance restraints. Constraints of type 2 will be generated that do generate exclusions." }
    };
#define npargs asize(pa)

    output_env_t     oenv;
    t_atoms         *atoms = NULL;
    int              i, j, k;
    FILE            *out;
    int              igrp;
    real             d, dd, lo, hi;
    atom_id         *ind_grp;
    const char      *xfn, *nfn;
    char            *gn_grp;
    char             title[STRLEN];
    matrix           box;
    gmx_bool         bFreeze;
    rvec             dx, *x = NULL, *v = NULL;

    t_filenm         fnm[] = {
        { efSTX, "-f",  NULL,    ffREAD },
        { efNDX, "-n",  NULL,    ffOPTRD },
        { efITP, "-o",  "posre", ffWRITE },
        { efNDX, "-of", "freeze",    ffOPTWR }
    };
#define NFILE asize(fnm)

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

    bFreeze = opt2bSet("-of", NFILE, fnm) || opt2parg_bSet("-freeze", asize(pa), pa);
    bDisre  = bDisre || opt2parg_bSet("-disre_dist", npargs, pa);
    xfn     = opt2fn_null("-f", NFILE, fnm);
    nfn     = opt2fn_null("-n", NFILE, fnm);

    if (( nfn == NULL ) && ( xfn == NULL))
    {
        gmx_fatal(FARGS, "no index file and no structure file supplied");
    }

    if ((disre_frac < 0) || (disre_frac >= 1))
    {
        gmx_fatal(FARGS, "disre_frac should be between 0 and 1");
    }
    if (disre_dist < 0)
    {
        gmx_fatal(FARGS, "disre_dist should be >= 0");
    }

    if (xfn != NULL)
    {
        snew(atoms, 1);
        get_stx_coordnum(xfn, &(atoms->nr));
        init_t_atoms(atoms, atoms->nr, TRUE);
        snew(x, atoms->nr);
        snew(v, atoms->nr);
        fprintf(stderr, "\nReading structure file\n");
        read_stx_conf(xfn, title, atoms, x, v, NULL, box);
    }

    if (bFreeze)
    {
        if (!atoms || !atoms->pdbinfo)
        {
            gmx_fatal(FARGS, "No B-factors in input file %s, use a pdb file next time.",
                      xfn);
        }

        out = opt2FILE("-of", NFILE, fnm, "w");
        fprintf(out, "[ freeze ]\n");
        for (i = 0; (i < atoms->nr); i++)
        {
            if (atoms->pdbinfo[i].bfac <= freeze_level)
            {
                fprintf(out, "%d\n", i+1);
            }
        }
        gmx_ffclose(out);
    }
    else if ((bDisre || bConstr) && x)
    {
        printf("Select group to generate %s matrix from\n",
               bConstr ? "constraint" : "distance restraint");
        get_index(atoms, nfn, 1, &igrp, &ind_grp, &gn_grp);

        out = ftp2FILE(efITP, NFILE, fnm, "w");
        if (bConstr)
        {
            fprintf(out, "; constraints for %s of %s\n\n", gn_grp, title);
            fprintf(out, "[ constraints ]\n");
            fprintf(out, ";%4s %5s %1s %10s\n", "i", "j", "tp", "dist");
        }
        else
        {
            fprintf(out, "; distance restraints for %s of %s\n\n", gn_grp, title);
            fprintf(out, "[ distance_restraints ]\n");
            fprintf(out, ";%4s %5s %1s %5s %10s %10s %10s %10s %10s\n", "i", "j", "?",
                    "label", "funct", "lo", "up1", "up2", "weight");
        }
        for (i = k = 0; i < igrp; i++)
        {
            for (j = i+1; j < igrp; j++, k++)
            {
                rvec_sub(x[ind_grp[i]], x[ind_grp[j]], dx);
                d = norm(dx);
                if (bConstr)
                {
                    fprintf(out, "%5d %5d %1d %10g\n", ind_grp[i]+1, ind_grp[j]+1, 2, d);
                }
                else
                {
                    if (cutoff < 0 || d < cutoff)
                    {
                        if (disre_frac > 0)
                        {
                            dd = min(disre_dist, disre_frac*d);
                        }
                        else
                        {
                            dd = disre_dist;
                        }
                        lo = max(0, d-dd);
                        hi = d+dd;
                        fprintf(out, "%5d %5d %1d %5d %10d %10g %10g %10g %10g\n",
                                ind_grp[i]+1, ind_grp[j]+1, 1, k, 1,
                                lo, hi, hi+disre_up2, 1.0);
                    }
                }
            }
        }
        gmx_ffclose(out);
    }
    else
    {
        printf("Select group to position restrain\n");
        get_index(atoms, nfn, 1, &igrp, &ind_grp, &gn_grp);

        out = ftp2FILE(efITP, NFILE, fnm, "w");
        fprintf(out, "; position restraints for %s of %s\n\n", gn_grp, title);
        fprintf(out, "[ position_restraints ]\n");
        fprintf(out, ";%3s %5s %9s %10s %10s\n", "i", "funct", "fcx", "fcy", "fcz");
        for (i = 0; i < igrp; i++)
        {
            fprintf(out, "%4d %4d %10g %10g %10g\n",
                    ind_grp[i]+1, 1, fc[XX], fc[YY], fc[ZZ]);
        }
        gmx_ffclose(out);
    }
    if (xfn)
    {
        sfree(x);
        sfree(v);
    }

    return 0;
}
示例#9
0
int gmx_helixorient(int argc, char *argv[])
{
    const char      *desc[] = {
        "[THISMODULE] calculates the coordinates and direction of the average",
        "axis inside an alpha helix, and the direction/vectors of both the",
        "C[GRK]alpha[grk] and (optionally) a sidechain atom relative to the axis.[PAR]",
        "As input, you need to specify an index group with C[GRK]alpha[grk] atoms",
        "corresponding to an [GRK]alpha[grk]-helix of continuous residues. Sidechain",
        "directions require a second index group of the same size, containing",
        "the heavy atom in each residue that should represent the sidechain.[PAR]",
        "[BB]Note[bb] that this program does not do any fitting of structures.[PAR]",
        "We need four C[GRK]alpha[grk] coordinates to define the local direction of the helix",
        "axis.[PAR]",
        "The tilt/rotation is calculated from Euler rotations, where we define",
        "the helix axis as the local [IT]x[it]-axis, the residues/C[GRK]alpha[grk] vector as [IT]y[it], and the",
        "[IT]z[it]-axis from their cross product. We use the Euler Y-Z-X rotation, meaning",
        "we first tilt the helix axis (1) around and (2) orthogonal to the residues",
        "vector, and finally apply the (3) rotation around it. For debugging or other",
        "purposes, we also write out the actual Euler rotation angles as [TT]theta[1-3].xvg[tt]"
    };

    t_topology      *top = NULL;
    real             t;
    rvec            *x = NULL, dx;
    matrix           box;
    t_trxstatus     *status;
    int              natoms;
    real             theta1, theta2, theta3;

    int              d, i, j, teller = 0;
    int              iCA, iSC;
    atom_id         *ind_CA;
    atom_id         *ind_SC;
    char            *gn_CA;
    char            *gn_SC;
    rvec             averageaxis;
    rvec             v1, v2, p1, p2, vtmp, vproj;
    rvec            *x_CA, *x_SC;
    rvec            *r12;
    rvec            *r23;
    rvec            *r34;
    rvec            *diff13;
    rvec            *diff24;
    rvec            *helixaxis;
    rvec            *residuehelixaxis;
    rvec            *residueorigin;
    rvec            *residuevector;
    rvec            *sidechainvector;

    rvec             axes_t0[3];
    rvec             axes[3];
    rvec            *residuehelixaxis_t0;
    rvec            *residuevector_t0;
    rvec            *axis3_t0;
    rvec            *residuehelixaxis_tlast;
    rvec            *residuevector_tlast;
    rvec            *axis3_tlast;
    rvec             refaxes[3], newaxes[3];
    rvec             unitaxes[3];
    rvec             rot_refaxes[3], rot_newaxes[3];

    real             tilt, rotation;
    rvec            *axis3;
    real            *twist, *residuetwist;
    real            *radius, *residueradius;
    real            *rise, *residuerise;
    real            *residuebending;

    real             tmp, rotangle;
    real             weight[3];
    t_pbc            pbc;
    matrix           A;

    FILE            *fpaxis, *fpcenter, *fptilt, *fprotation;
    FILE            *fpradius, *fprise, *fptwist;
    FILE            *fptheta1, *fptheta2, *fptheta3;
    FILE            *fpbending;
    int              ePBC;

    output_env_t     oenv;
    gmx_rmpbc_t      gpbc = NULL;

    static  gmx_bool bSC          = FALSE;
    static gmx_bool  bIncremental = FALSE;

    static t_pargs   pa[] = {
        { "-sidechain",      FALSE, etBOOL, {&bSC},
          "Calculate sidechain directions relative to helix axis too." },
        { "-incremental",        FALSE, etBOOL, {&bIncremental},
          "Calculate incremental rather than total rotation/tilt." },
    };
#define NPA asize(pa)

    t_filenm fnm[] = {
        { efTPR, NULL, NULL, ffREAD },
        { efTRX, "-f", NULL, ffREAD },
        { efNDX, NULL, NULL, ffOPTRD },
        { efDAT, "-oaxis",    "helixaxis", ffWRITE },
        { efDAT, "-ocenter",  "center", ffWRITE },
        { efXVG, "-orise",    "rise", ffWRITE },
        { efXVG, "-oradius",  "radius", ffWRITE },
        { efXVG, "-otwist",   "twist", ffWRITE },
        { efXVG, "-obending", "bending", ffWRITE },
        { efXVG, "-otilt",    "tilt", ffWRITE },
        { efXVG, "-orot",     "rotation", ffWRITE }
    };
#define NFILE asize(fnm)

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

    top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC);

    for (i = 0; i < 3; i++)
    {
        weight[i] = 1.0;
    }

    /* read index files */
    printf("Select a group of Calpha atoms corresponding to a single continuous helix:\n");
    get_index(&(top->atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &iCA, &ind_CA, &gn_CA);
    snew(x_CA, iCA);
    snew(x_SC, iCA); /* sic! */

    snew(r12, iCA-3);
    snew(r23, iCA-3);
    snew(r34, iCA-3);
    snew(diff13, iCA-3);
    snew(diff24, iCA-3);
    snew(helixaxis, iCA-3);
    snew(twist, iCA);
    snew(residuetwist, iCA);
    snew(radius, iCA);
    snew(residueradius, iCA);
    snew(rise, iCA);
    snew(residuerise, iCA);
    snew(residueorigin, iCA);
    snew(residuehelixaxis, iCA);
    snew(residuevector, iCA);
    snew(sidechainvector, iCA);
    snew(residuebending, iCA);
    snew(residuehelixaxis_t0, iCA);
    snew(residuevector_t0, iCA);
    snew(axis3_t0, iCA);
    snew(residuehelixaxis_tlast, iCA);
    snew(residuevector_tlast, iCA);
    snew(axis3_tlast, iCA);
    snew(axis3, iCA);

    if (bSC)
    {
        printf("Select a group of atoms defining the sidechain direction (1/residue):\n");
        get_index(&(top->atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &iSC, &ind_SC, &gn_SC);
        if (iSC != iCA)
        {
            gmx_fatal(FARGS, "Number of sidechain atoms (%d) != number of CA atoms (%d)", iSC, iCA);
        }

    }

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

    fpaxis    = gmx_ffopen(opt2fn("-oaxis", NFILE, fnm), "w");
    fpcenter  = gmx_ffopen(opt2fn("-ocenter", NFILE, fnm), "w");
    fprise    = gmx_ffopen(opt2fn("-orise", NFILE, fnm), "w");
    fpradius  = gmx_ffopen(opt2fn("-oradius", NFILE, fnm), "w");
    fptwist   = gmx_ffopen(opt2fn("-otwist", NFILE, fnm), "w");
    fpbending = gmx_ffopen(opt2fn("-obending", NFILE, fnm), "w");

    fptheta1 = gmx_ffopen("theta1.xvg", "w");
    fptheta2 = gmx_ffopen("theta2.xvg", "w");
    fptheta3 = gmx_ffopen("theta3.xvg", "w");

    if (bIncremental)
    {
        fptilt = xvgropen(opt2fn("-otilt", NFILE, fnm),
                          "Incremental local helix tilt", "Time(ps)", "Tilt (degrees)",
                          oenv);
        fprotation = xvgropen(opt2fn("-orot", NFILE, fnm),
                              "Incremental local helix rotation", "Time(ps)",
                              "Rotation (degrees)", oenv);
    }
    else
    {
        fptilt = xvgropen(opt2fn("-otilt", NFILE, fnm),
                          "Cumulative local helix tilt", "Time(ps)", "Tilt (degrees)", oenv);
        fprotation = xvgropen(opt2fn("-orot", NFILE, fnm),
                              "Cumulative local helix rotation", "Time(ps)",
                              "Rotation (degrees)", oenv);
    }

    clear_rvecs(3, unitaxes);
    unitaxes[0][0] = 1;
    unitaxes[1][1] = 1;
    unitaxes[2][2] = 1;

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

    do
    {
        /* initialisation for correct distance calculations */
        set_pbc(&pbc, ePBC, box);
        /* make molecules whole again */
        gmx_rmpbc(gpbc, natoms, box, x);

        /* copy coords to our smaller arrays */
        for (i = 0; i < iCA; i++)
        {
            copy_rvec(x[ind_CA[i]], x_CA[i]);
            if (bSC)
            {
                copy_rvec(x[ind_SC[i]], x_SC[i]);
            }
        }

        for (i = 0; i < iCA-3; i++)
        {
            rvec_sub(x_CA[i+1], x_CA[i], r12[i]);
            rvec_sub(x_CA[i+2], x_CA[i+1], r23[i]);
            rvec_sub(x_CA[i+3], x_CA[i+2], r34[i]);
            rvec_sub(r12[i], r23[i], diff13[i]);
            rvec_sub(r23[i], r34[i], diff24[i]);
            /* calculate helix axis */
            cprod(diff13[i], diff24[i], helixaxis[i]);
            svmul(1.0/norm(helixaxis[i]), helixaxis[i], helixaxis[i]);

            tmp       = cos_angle(diff13[i], diff24[i]);
            twist[i]  = 180.0/M_PI * acos( tmp );
            radius[i] = sqrt( norm(diff13[i])*norm(diff24[i]) ) / (2.0* (1.0-tmp) );
            rise[i]   = fabs(iprod(r23[i], helixaxis[i]));

            svmul(radius[i]/norm(diff13[i]), diff13[i], v1);
            svmul(radius[i]/norm(diff24[i]), diff24[i], v2);

            rvec_sub(x_CA[i+1], v1, residueorigin[i+1]);
            rvec_sub(x_CA[i+2], v2, residueorigin[i+2]);
        }
        residueradius[0] = residuetwist[0] = residuerise[0] = 0;

        residueradius[1] = radius[0];
        residuetwist[1]  = twist[0];
        residuerise[1]   = rise[0];

        residuebending[0] = residuebending[1] = 0;
        for (i = 2; i < iCA-2; i++)
        {
            residueradius[i]  = 0.5*(radius[i-2]+radius[i-1]);
            residuetwist[i]   = 0.5*(twist[i-2]+twist[i-1]);
            residuerise[i]    = 0.5*(rise[i-2]+rise[i-1]);
            residuebending[i] = 180.0/M_PI*acos( cos_angle(helixaxis[i-2], helixaxis[i-1]) );
        }
        residueradius[iCA-2]  = radius[iCA-4];
        residuetwist[iCA-2]   = twist[iCA-4];
        residuerise[iCA-2]    = rise[iCA-4];
        residueradius[iCA-1]  = residuetwist[iCA-1] = residuerise[iCA-1] = 0;
        residuebending[iCA-2] = residuebending[iCA-1] = 0;

        clear_rvec(residueorigin[0]);
        clear_rvec(residueorigin[iCA-1]);

        /* average helix axes to define them on the residues.
         * Just extrapolate second first/list atom.
         */
        copy_rvec(helixaxis[0], residuehelixaxis[0]);
        copy_rvec(helixaxis[0], residuehelixaxis[1]);

        for (i = 2; i < iCA-2; i++)
        {
            rvec_add(helixaxis[i-2], helixaxis[i-1], residuehelixaxis[i]);
            svmul(0.5, residuehelixaxis[i], residuehelixaxis[i]);
        }
        copy_rvec(helixaxis[iCA-4], residuehelixaxis[iCA-2]);
        copy_rvec(helixaxis[iCA-4], residuehelixaxis[iCA-1]);

        /* Normalize the axis */
        for (i = 0; i < iCA; i++)
        {
            svmul(1.0/norm(residuehelixaxis[i]), residuehelixaxis[i], residuehelixaxis[i]);
        }

        /* calculate vector from origin to residue CA */
        fprintf(fpaxis, "%15.12g  ", t);
        fprintf(fpcenter, "%15.12g  ", t);
        fprintf(fprise, "%15.12g  ", t);
        fprintf(fpradius, "%15.12g  ", t);
        fprintf(fptwist, "%15.12g  ", t);
        fprintf(fpbending, "%15.12g  ", t);

        for (i = 0; i < iCA; i++)
        {
            if (i == 0 || i == iCA-1)
            {
                fprintf(fpaxis, "%15.12g %15.12g %15.12g       ", 0.0, 0.0, 0.0);
                fprintf(fpcenter, "%15.12g %15.12g %15.12g       ", 0.0, 0.0, 0.0);
                fprintf(fprise, "%15.12g  ", 0.0);
                fprintf(fpradius, "%15.12g  ", 0.0);
                fprintf(fptwist, "%15.12g  ", 0.0);
                fprintf(fpbending, "%15.12g  ", 0.0);
            }
            else
            {
                rvec_sub( bSC ? x_SC[i] : x_CA[i], residueorigin[i], residuevector[i]);
                svmul(1.0/norm(residuevector[i]), residuevector[i], residuevector[i]);
                cprod(residuehelixaxis[i], residuevector[i], axis3[i]);
                fprintf(fpaxis, "%15.12g %15.12g %15.12g       ", residuehelixaxis[i][0], residuehelixaxis[i][1], residuehelixaxis[i][2]);
                fprintf(fpcenter, "%15.12g %15.12g %15.12g       ", residueorigin[i][0], residueorigin[i][1], residueorigin[i][2]);

                fprintf(fprise, "%15.12g  ", residuerise[i]);
                fprintf(fpradius, "%15.12g  ", residueradius[i]);
                fprintf(fptwist, "%15.12g  ", residuetwist[i]);
                fprintf(fpbending, "%15.12g  ", residuebending[i]);

                /* angle with local vector? */
                /*
                   printf("res[%2d]:  axis: %g %g %g    origin: %g %g %g   vector: %g %g %g   angle: %g\n",i,
                       residuehelixaxis[i][0],
                       residuehelixaxis[i][1],
                       residuehelixaxis[i][2],
                       residueorigin[i][0],
                       residueorigin[i][1],
                       residueorigin[i][2],
                       residuevector[i][0],
                       residuevector[i][1],
                       residuevector[i][2],
                       180.0/M_PI*acos( cos_angle(residuevector[i],residuehelixaxis[i]) ));
                 */
                /*      fprintf(fp,"%15.12g %15.12g %15.12g   %15.12g %15.12g %15.12g\n",
                              residuehelixaxis[i][0],
                              residuehelixaxis[i][1],
                              residuehelixaxis[i][2],
                              residuevector[i][0],
                              residuevector[i][1],
                              residuevector[i][2]);
                 */
            }
        }
        fprintf(fprise, "\n");
        fprintf(fpradius, "\n");
        fprintf(fpaxis, "\n");
        fprintf(fpcenter, "\n");
        fprintf(fptwist, "\n");
        fprintf(fpbending, "\n");

        if (teller == 0)
        {
            for (i = 0; i < iCA; i++)
            {
                copy_rvec(residuehelixaxis[i], residuehelixaxis_t0[i]);
                copy_rvec(residuevector[i], residuevector_t0[i]);
                copy_rvec(axis3[i], axis3_t0[i]);
            }
        }
        else
        {
            fprintf(fptilt, "%15.12g       ", t);
            fprintf(fprotation, "%15.12g       ", t);
            fprintf(fptheta1, "%15.12g      ", t);
            fprintf(fptheta2, "%15.12g      ", t);
            fprintf(fptheta3, "%15.12g      ", t);

            for (i = 0; i < iCA; i++)
            {
                if (i == 0 || i == iCA-1)
                {
                    tilt = rotation = 0;
                }
                else
                {
                    if (!bIncremental)
                    {
                        /* Total rotation & tilt */
                        copy_rvec(residuehelixaxis_t0[i], refaxes[0]);
                        copy_rvec(residuevector_t0[i], refaxes[1]);
                        copy_rvec(axis3_t0[i], refaxes[2]);
                    }
                    else
                    {
                        /* Rotation/tilt since last step */
                        copy_rvec(residuehelixaxis_tlast[i], refaxes[0]);
                        copy_rvec(residuevector_tlast[i], refaxes[1]);
                        copy_rvec(axis3_tlast[i], refaxes[2]);
                    }
                    copy_rvec(residuehelixaxis[i], newaxes[0]);
                    copy_rvec(residuevector[i], newaxes[1]);
                    copy_rvec(axis3[i], newaxes[2]);

                    /*
                       printf("frame %d, i=%d:\n  old: %g %g %g , %g %g %g , %g %g %g\n  new:  %g %g %g , %g %g %g , %g %g %g\n",
                       teller,i,
                       refaxes[0][0],refaxes[0][1],refaxes[0][2],
                               refaxes[1][0],refaxes[1][1],refaxes[1][2],
                               refaxes[2][0],refaxes[2][1],refaxes[2][2],
                               newaxes[0][0],newaxes[0][1],newaxes[0][2],
                               newaxes[1][0],newaxes[1][1],newaxes[1][2],
                               newaxes[2][0],newaxes[2][1],newaxes[2][2]);
                     */

                    /* rotate reference frame onto unit axes */
                    calc_fit_R(3, 3, weight, unitaxes, refaxes, A);
                    for (j = 0; j < 3; j++)
                    {
                        mvmul(A, refaxes[j], rot_refaxes[j]);
                        mvmul(A, newaxes[j], rot_newaxes[j]);
                    }

                    /* Determine local rotation matrix A */
                    calc_fit_R(3, 3, weight, rot_newaxes, rot_refaxes, A);
                    /* Calculate euler angles, from rotation order y-z-x, where
                     * x is helixaxis, y residuevector, and z axis3.
                     *
                     * A contains rotation column vectors.
                     */

                    /*
                       printf("frame %d, i=%d, A: %g %g %g  , %g %g %g , %g %g %g\n",
                       teller,i,A[0][0],A[0][1],A[0][2],A[1][0],A[1][1],A[1][2],A[2][0],A[2][1],A[2][2]);
                     */

                    theta1 = 180.0/M_PI*atan2(A[0][2], A[0][0]);
                    theta2 = 180.0/M_PI*asin(-A[0][1]);
                    theta3 = 180.0/M_PI*atan2(A[2][1], A[1][1]);

                    tilt     = sqrt(theta1*theta1+theta2*theta2);
                    rotation = theta3;
                    fprintf(fptheta1, "%15.12g  ", theta1);
                    fprintf(fptheta2, "%15.12g  ", theta2);
                    fprintf(fptheta3, "%15.12g  ", theta3);

                }
                fprintf(fptilt, "%15.12g  ", tilt);
                fprintf(fprotation, "%15.12g  ", rotation);
            }
            fprintf(fptilt, "\n");
            fprintf(fprotation, "\n");
            fprintf(fptheta1, "\n");
            fprintf(fptheta2, "\n");
            fprintf(fptheta3, "\n");
        }

        for (i = 0; i < iCA; i++)
        {
            copy_rvec(residuehelixaxis[i], residuehelixaxis_tlast[i]);
            copy_rvec(residuevector[i], residuevector_tlast[i]);
            copy_rvec(axis3[i], axis3_tlast[i]);
        }

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

    gmx_rmpbc_done(gpbc);

    gmx_ffclose(fpaxis);
    gmx_ffclose(fpcenter);
    gmx_ffclose(fptilt);
    gmx_ffclose(fprotation);
    gmx_ffclose(fprise);
    gmx_ffclose(fpradius);
    gmx_ffclose(fptwist);
    gmx_ffclose(fpbending);
    gmx_ffclose(fptheta1);
    gmx_ffclose(fptheta2);
    gmx_ffclose(fptheta3);

    close_trj(status);

    return 0;
}