Esempio n. 1
0
static void make_cyl_refgrps(t_commrec *cr, struct pull_t *pull, t_mdatoms *md,
                             t_pbc *pbc, double t, rvec *x)
{
    /* The size and stride per coord for the reduction buffer */
    const int       stride = 9;
    int             c, i, ii, m, start, end;
    rvec            g_x, dx, dir;
    double          inv_cyl_r2;
    pull_comm_t    *comm;
    gmx_ga2la_t    *ga2la = NULL;

    comm = &pull->comm;

    if (comm->dbuf_cyl == NULL)
    {
        snew(comm->dbuf_cyl, pull->ncoord*stride);
    }

    if (cr && DOMAINDECOMP(cr))
    {
        ga2la = cr->dd->ga2la;
    }

    start = 0;
    end   = md->homenr;

    inv_cyl_r2 = 1.0/gmx::square(pull->params.cylinder_r);

    /* loop over all groups to make a reference group for each*/
    for (c = 0; c < pull->ncoord; c++)
    {
        pull_coord_work_t *pcrd;
        double             sum_a, wmass, wwmass;
        dvec               radf_fac0, radf_fac1;

        pcrd   = &pull->coord[c];

        sum_a  = 0;
        wmass  = 0;
        wwmass = 0;
        clear_dvec(radf_fac0);
        clear_dvec(radf_fac1);

        if (pcrd->params.eGeom == epullgCYL)
        {
            pull_group_work_t *pref, *pgrp, *pdyna;

            /* pref will be the same group for all pull coordinates */
            pref  = &pull->group[pcrd->params.group[0]];
            pgrp  = &pull->group[pcrd->params.group[1]];
            pdyna = &pull->dyna[c];
            copy_rvec(pcrd->vec, dir);
            pdyna->nat_loc = 0;

            /* We calculate distances with respect to the reference location
             * of this cylinder group (g_x), which we already have now since
             * we reduced the other group COM over the ranks. This resolves
             * any PBC issues and we don't need to use a PBC-atom here.
             */
            if (pcrd->params.rate != 0)
            {
                /* With rate=0, value_ref is set initially */
                pcrd->value_ref = pcrd->params.init + pcrd->params.rate*t;
            }
            for (m = 0; m < DIM; m++)
            {
                g_x[m] = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref;
            }

            /* loop over all atoms in the main ref group */
            for (i = 0; i < pref->params.nat; i++)
            {
                ii = pref->params.ind[i];
                if (ga2la)
                {
                    if (!ga2la_get_home(ga2la, pref->params.ind[i], &ii))
                    {
                        ii = -1;
                    }
                }
                if (ii >= start && ii < end)
                {
                    double dr2, dr2_rel, inp;
                    dvec   dr;

                    pbc_dx_aiuc(pbc, x[ii], g_x, dx);
                    inp = iprod(dir, dx);
                    dr2 = 0;
                    for (m = 0; m < DIM; m++)
                    {
                        /* Determine the radial components */
                        dr[m] = dx[m] - inp*dir[m];
                        dr2  += dr[m]*dr[m];
                    }
                    dr2_rel = dr2*inv_cyl_r2;

                    if (dr2_rel < 1)
                    {
                        double mass, weight, dweight_r;
                        dvec   mdw;

                        /* add to index, to sum of COM, to weight array */
                        if (pdyna->nat_loc >= pdyna->nalloc_loc)
                        {
                            pdyna->nalloc_loc = over_alloc_large(pdyna->nat_loc+1);
                            srenew(pdyna->ind_loc,    pdyna->nalloc_loc);
                            srenew(pdyna->weight_loc, pdyna->nalloc_loc);
                            srenew(pdyna->mdw,        pdyna->nalloc_loc);
                            srenew(pdyna->dv,         pdyna->nalloc_loc);
                        }
                        pdyna->ind_loc[pdyna->nat_loc] = ii;

                        mass      = md->massT[ii];
                        /* The radial weight function is 1-2x^2+x^4,
                         * where x=r/cylinder_r. Since this function depends
                         * on the radial component, we also get radial forces
                         * on both groups.
                         */
                        weight    = 1 + (-2 + dr2_rel)*dr2_rel;
                        dweight_r = (-4 + 4*dr2_rel)*inv_cyl_r2;
                        pdyna->weight_loc[pdyna->nat_loc] = weight;
                        sum_a    += mass*weight*inp;
                        wmass    += mass*weight;
                        wwmass   += mass*weight*weight;
                        dsvmul(mass*dweight_r, dr, mdw);
                        copy_dvec(mdw, pdyna->mdw[pdyna->nat_loc]);
                        /* Currently we only have the axial component of the
                         * distance (inp) up to an unkown offset. We add this
                         * offset after the reduction needs to determine the
                         * COM of the cylinder group.
                         */
                        pdyna->dv[pdyna->nat_loc] = inp;
                        for (m = 0; m < DIM; m++)
                        {
                            radf_fac0[m] += mdw[m];
                            radf_fac1[m] += mdw[m]*inp;
                        }
                        pdyna->nat_loc++;
                    }
                }
            }
        }
        comm->dbuf_cyl[c*stride+0] = wmass;
        comm->dbuf_cyl[c*stride+1] = wwmass;
        comm->dbuf_cyl[c*stride+2] = sum_a;
        comm->dbuf_cyl[c*stride+3] = radf_fac0[XX];
        comm->dbuf_cyl[c*stride+4] = radf_fac0[YY];
        comm->dbuf_cyl[c*stride+5] = radf_fac0[ZZ];
        comm->dbuf_cyl[c*stride+6] = radf_fac1[XX];
        comm->dbuf_cyl[c*stride+7] = radf_fac1[YY];
        comm->dbuf_cyl[c*stride+8] = radf_fac1[ZZ];
    }

    if (cr != NULL && PAR(cr))
    {
        /* Sum the contributions over the ranks */
        pull_reduce_double(cr, comm, pull->ncoord*stride, comm->dbuf_cyl);
    }

    for (c = 0; c < pull->ncoord; c++)
    {
        pull_coord_work_t *pcrd;

        pcrd  = &pull->coord[c];

        if (pcrd->params.eGeom == epullgCYL)
        {
            pull_group_work_t *pdyna, *pgrp;
            double             wmass, wwmass, dist;

            pdyna = &pull->dyna[c];
            pgrp  = &pull->group[pcrd->params.group[1]];

            wmass          = comm->dbuf_cyl[c*stride+0];
            wwmass         = comm->dbuf_cyl[c*stride+1];
            pdyna->mwscale = 1.0/wmass;
            /* Cylinder pulling can't be used with constraints, but we set
             * wscale and invtm anyhow, in case someone would like to use them.
             */
            pdyna->wscale  = wmass/wwmass;
            pdyna->invtm   = wwmass/(wmass*wmass);

            /* We store the deviation of the COM from the reference location
             * used above, since we need it when we apply the radial forces
             * to the atoms in the cylinder group.
             */
            pcrd->cyl_dev  = 0;
            for (m = 0; m < DIM; m++)
            {
                g_x[m]         = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref;
                dist           = -pcrd->vec[m]*comm->dbuf_cyl[c*stride+2]*pdyna->mwscale;
                pdyna->x[m]    = g_x[m] - dist;
                pcrd->cyl_dev += dist;
            }
            /* Now we know the exact COM of the cylinder reference group,
             * we can determine the radial force factor (ffrad) that when
             * multiplied with the axial pull force will give the radial
             * force on the pulled (non-cylinder) group.
             */
            for (m = 0; m < DIM; m++)
            {
                pcrd->ffrad[m] = (comm->dbuf_cyl[c*stride+6+m] +
                                  comm->dbuf_cyl[c*stride+3+m]*pcrd->cyl_dev)/wmass;
            }

            if (debug)
            {
                fprintf(debug, "Pull cylinder group %d:%8.3f%8.3f%8.3f m:%8.3f\n",
                        c, pdyna->x[0], pdyna->x[1],
                        pdyna->x[2], 1.0/pdyna->invtm);
                fprintf(debug, "ffrad %8.3f %8.3f %8.3f\n",
                        pcrd->ffrad[XX], pcrd->ffrad[YY], pcrd->ffrad[ZZ]);
            }
        }
    }
}
Esempio n. 2
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 gmx_unused bCompact,
              int gmx_unused nstglobalcomm,
              gmx_vsite_t gmx_unused *vsite, gmx_constr_t gmx_unused constr,
              int gmx_unused 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 gmx_unused ed,
              t_forcerec *fr,
              int gmx_unused repl_ex_nst, int gmx_unused repl_ex_nex, int gmx_unused repl_ex_seed,
              gmx_membed_t gmx_unused membed,
              real gmx_unused cpt_period, real gmx_unused max_hours,
              const char gmx_unused *deviceOptions,
              int gmx_unused imdport,
              unsigned long gmx_unused Flags,
              gmx_walltime_accounting_t walltime_accounting)
{
    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;
    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;
    gmx_int64_t     frame_step_prev, frame_step;
    gmx_int64_t     nsteps, stepblocksize = 0, step;
    gmx_int64_t     rnd_count_stride, rnd_count;
    gmx_int64_t     seed;
    double          rnd[4];
    int             i, start, end;
    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, top_global->natoms, mdatoms);
    update_mdatoms(mdatoms, inputrec->fepvals->init_lambda);

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

    /* Print to log file  */
    walltime_accounting_start(walltime_accounting);
    wallcycle_start(wcycle, ewcRUN);
    print_start(fplog, cr, walltime_accounting, "Test Particle Insertion");

    /* 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",
                (int)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);

    /* Copy the random seed set by the user */
    seed = inputrec->ld_seed;
    /* We use the frame step number as one random counter.
     * The second counter use the insertion (step) count. But we
     * need multiple random numbers per insertion. This number is
     * not fixed, since we generate random locations in a sphere
     * by putting locations in a cube and some of these fail.
     * A count of 20 is already extremely unlikely, so 10000 is
     * a safe margin for random numbers per insertion.
     */
    rnd_count_stride = 10000;

    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);

    /* Avoid frame step numbers <= -1 */
    frame_step_prev = -1;

    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));

    switch (inputrec->eI)
    {
        case eiTPI:
            stepblocksize = inputrec->nstlist;
            break;
        case eiTPIC:
            stepblocksize = 1;
            break;
        default:
            gmx_fatal(FARGS, "Unknown integrator %s", ei_names[inputrec->eI]);
    }

#ifdef GMX_SIMD
    /* Make sure we don't detect SIMD overflow generated before this point */
    gmx_simd_check_and_reset_overflow();
#endif

    while (bNotLastFrame)
    {
        frame_step      = rerun_fr.step;
        if (frame_step <= frame_step_prev)
        {
            /* We don't have step number in the trajectory file,
             * or we have constant or decreasing step numbers.
             * Ensure we have increasing step numbers, since we use
             * the step numbers as a counter for random numbers.
             */
            frame_step  = frame_step_prev + 1;
        }
        frame_step_prev = frame_step;

        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]);
        }
        copy_mat(rerun_fr.box, state->box);

        V    = det(state->box);
        logV = log(V);

        bStateChanged = TRUE;
        bNS           = TRUE;

        step = cr->nodeid*stepblocksize;
        while (step < nsteps)
        {
            /* Initialize the second counter for random numbers using
             * the insertion step index. This ensures that we get
             * the same random numbers independently of how many
             * MPI ranks we use. Also for the same seed, we get
             * the same initial random sequence for different nsteps.
             */
            rnd_count = step*rnd_count_stride;

            if (!bCavity)
            {
                /* Random insertion in the whole volume */
                bNS = (step % inputrec->nstlist == 0);
                if (bNS)
                {
                    /* Generate a random position in the box */
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                    for (d = 0; d < DIM; d++)
                    {
                        x_init[d] = rnd[d]*state->box[d][d];
                    }
                }
                if (inputrec->nstlist == 1)
                {
                    copy_rvec(x_init, x_tp);
                }
                else
                {
                    /* Generate coordinates within |dx|=drmax of x_init */
                    do
                    {
                        gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                        gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                        for (d = 0; d < DIM; d++)
                        {
                            dx[d] = (2*rnd[d] - 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
                {
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                    gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                    for (d = 0; d < DIM; d++)
                    {
                        dx[d] = (2*rnd[d] - 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 */
                gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd);
                gmx_rng_cycle_2uniform(frame_step, rnd_count++, seed, RND_SEED_TPI, rnd+2);
                rotate_conf(a_tp1-a_tp0, state->x+a_tp0, NULL,
                            2*M_PI*rnd[0],
                            2*M_PI*rnd[1],
                            2*M_PI*rnd[2]);
                /* Shift to the insertion location */
                for (i = a_tp0; i < a_tp1; i++)
                {
                    rvec_inc(state->x[i], x_tp);
                }
            }

            /* 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->groups,
                     state->box, state->x, &state->hist,
                     f, force_vir, mdatoms, enerd, fcd,
                     state->lambda,
                     NULL, fr, NULL, mu_tot, t, NULL, NULL, FALSE,
                     GMX_FORCE_NONBONDED | GMX_FORCE_ENERGY |
                     (bNS ? GMX_FORCE_DYNAMICBOX | GMX_FORCE_NS | GMX_FORCE_DO_LR : 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, state->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_VDW] += dvdlcorr;

            epot               = enerd->term[F_EPOT];
            bEnergyOutOfBounds = FALSE;
#ifdef GMX_SIMD_X86_SSE2_OR_HIGHER
            /* 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, (int)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 (debug)
            {
                fprintf(debug, "TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
                        (int)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, (int)step);
                sprintf(str2, "t: %f step %d ener: %f", t, (int)step, epot);
                write_sto_conf_mtop(str, str2, top_global, state->x, state->v,
                                    inputrec->ePBC, state->box);
            }

            step++;
            if ((step/stepblocksize) % cr->nnodes != cr->nodeid)
            {
                /* Skip all steps assigned to the other MPI ranks */
                step += (cr->nnodes - 1)*stepblocksize;
            }
        }

        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  */
    walltime_accounting_end(walltime_accounting);

    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);

    walltime_accounting_set_nsteps_done(walltime_accounting, frame*inputrec->nsteps);

    return 0;
}
Esempio n. 3
0
int write_trxframe_indexed(t_trxstatus *status, const t_trxframe *fr, int nind,
                           const int *ind, gmx_conect gc)
{
    char  title[STRLEN];
    rvec *xout = NULL, *vout = NULL, *fout = NULL;
    int   i, ftp = -1;
    real  prec;

    if (fr->bPrec)
    {
        prec = fr->prec;
    }
    else
    {
        prec = 1000.0;
    }

    if (status->tng)
    {
        ftp = efTNG;
    }
    else if (status->fio)
    {
        ftp = gmx_fio_getftp(status->fio);
    }
    else
    {
        gmx_incons("No input file available");
    }

    switch (ftp)
    {
        case efTRR:
        case efTNG:
            break;
        default:
            if (!fr->bX)
            {
                gmx_fatal(FARGS, "Need coordinates to write a %s trajectory",
                          ftp2ext(ftp));
            }
            break;
    }

    switch (ftp)
    {
        case efTRR:
        case efTNG:
            if (fr->bV)
            {
                snew(vout, nind);
                for (i = 0; i < nind; i++)
                {
                    copy_rvec(fr->v[ind[i]], vout[i]);
                }
            }
            if (fr->bF)
            {
                snew(fout, nind);
                for (i = 0; i < nind; i++)
                {
                    copy_rvec(fr->f[ind[i]], fout[i]);
                }
            }
        /* no break */
        case efXTC:
            if (fr->bX)
            {
                snew(xout, nind);
                for (i = 0; i < nind; i++)
                {
                    copy_rvec(fr->x[ind[i]], xout[i]);
                }
            }
            break;
        default:
            break;
    }

    switch (ftp)
    {
        case efTNG:
            gmx_write_tng_from_trxframe(status->tng, fr, nind);
            break;
        case efXTC:
            write_xtc(status->fio, nind, fr->step, fr->time, fr->box, xout, prec);
            break;
        case efTRR:
            gmx_trr_write_frame(status->fio, nframes_read(status),
                                fr->time, fr->step, fr->box, nind, xout, vout, fout);
            break;
        case efGRO:
        case efPDB:
        case efBRK:
        case efENT:
            if (!fr->bAtoms)
            {
                gmx_fatal(FARGS, "Can not write a %s file without atom names",
                          ftp2ext(ftp));
            }
            sprintf(title, "frame t= %.3f", fr->time);
            if (ftp == efGRO)
            {
                write_hconf_indexed_p(gmx_fio_getfp(status->fio), title, fr->atoms, nind, ind,
                                      fr->x, fr->bV ? fr->v : NULL, fr->box);
            }
            else
            {
                write_pdbfile_indexed(gmx_fio_getfp(status->fio), title, fr->atoms,
                                      fr->x, -1, fr->box, ' ', fr->step, nind, ind, gc, TRUE);
            }
            break;
        case efG96:
            write_g96_conf(gmx_fio_getfp(status->fio), fr, nind, ind);
            break;
        default:
            gmx_fatal(FARGS, "Sorry, write_trxframe_indexed can not write %s",
                      ftp2ext(ftp));
            break;
    }

    switch (ftp)
    {
        case efTRR:
        case efTNG:
            if (vout)
            {
                sfree(vout);
            }
            if (fout)
            {
                sfree(fout);
            }
        /* no break */
        case efXTC:
            sfree(xout);
            break;
        default:
            break;
    }

    return 0;
}
Esempio n. 4
0
static void mk_diamond(t_atoms *a,rvec x[],real odist,t_symtab *symtab,
		       gmx_bool bPBC,matrix box)
{
  
  int   i,ib,j,k,l,m,nrm=0;
  t_bbb *bbb;
  gmx_bool  *bRemove;
  rvec  dx;
  
  do {
    nrm = 0;
    bbb = mk_bonds(a->nr,x,odist,bPBC,box);
    
    for(i=0; (i<a->nr); i++) {
      if (bbb[i].n < 2) {
	for(k=0; (k<bbb[i].n); k++) {
	  ib = bbb[i].aa[k];
	  for(j=0; (j<bbb[ib].n); j++)
	    if (bbb[ib].aa[j] == i)
	      break;
	  if (j == bbb[ib].n)
	    gmx_fatal(FARGS,"Bond inconsistency (%d not in list of %d)!\n",i,ib);
	  for( ; (j<bbb[ib].n-1); j++)
	    bbb[ib].aa[j] = bbb[ib].aa[j+1];
	  bbb[ib].n--;
	  nrm++;
	}
	bbb[i].n = 0;
      }
    }
  
    for(i=j=0; (i<a->nr); i++) {
      if (bbb[i].n >= 2) {
	copy_rvec(x[i],x[j]);
	j++;
      }
    }
    fprintf(stderr,"Kicking out %d carbon atoms (out of %d)\n",
	    a->nr-j,a->nr);
    a->nr = j;
    sfree(bbb);
  } while (nrm > 0);
  /* Rename atoms */
  bbb = mk_bonds(a->nr,x,odist,bPBC,box);
  for(i=0; (i<a->nr); i++) {
    switch (bbb[i].n) {
    case 4:
      a->atomname[i] = put_symtab(symtab,"C");
      break;
    case 3:
      a->atomname[i] = put_symtab(symtab,"CH1");
      break;
    case 2:
      a->atomname[i] = put_symtab(symtab,"CH2");
      break;
    default:
      gmx_fatal(FARGS,"This atom (%d) has %d bonds only",i,bbb[i].n);
    }
  }
  sfree(bbb);
}
int gmx_bundle(int argc,char *argv[])
{
  static char *desc[] = {
    "g_bundle analyzes bundles of axes. The axes can be for instance",
    "helix axes. The program reads two index groups and divides both",
    "of them in [TT]-na[tt] parts. The centers of mass of these parts",
    "define the tops and bottoms of the axes.",
    "Several quantities are written to file:",
    "the axis length, the distance and the z-shift of the axis mid-points",
    "with respect to the average center of all axes, the total tilt,",
    "the radial tilt and the lateral tilt with respect to the average axis.",
    "[PAR]",
    "With options [TT]-ok[tt], [TT]-okr[tt] and [TT]-okl[tt] the total,",
    "radial and lateral kinks of the axes are plotted. An extra index",
    "group of kink atoms is required, which is also divided into [TT]-na[tt]",
    "parts. The kink angle is defined as the angle between the kink-top and",
    "the bottom-kink vectors.",
    "[PAR]",
    "With option [TT]-oa[tt] the top, mid (or kink when [TT]-ok[tt] is set)",
    "and bottom points of each axis",
    "are written to a pdb file each frame. The residue numbers correspond",
    "to the axis numbers. When viewing this file with [TT]rasmol[tt], use the",
    "command line option [TT]-nmrpdb[tt], and type [TT]set axis true[tt] to",
    "display the reference axis."
  };
  static int  n=0;
  static bool bZ=FALSE;
  t_pargs pa[] = {
    { "-na", FALSE, etINT, {&n},
	"Number of axes" },
    { "-z", FALSE, etBOOL, {&bZ},
	"Use the Z-axis as reference iso the average axis" }
  };
  FILE       *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl;
  FILE       *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL;
  int        status,fpdb;
  t_topology top;
  int        ePBC;
  rvec       *xtop;
  matrix     box;
  t_trxframe fr;
  t_atoms    outatoms;
  real       t,comp;
  int        natoms;
  char       *grpname[MAX_ENDS],title[256],*anm="CA",*rnm="GLY";
  int        i,j,gnx[MAX_ENDS];
  atom_id    *index[MAX_ENDS];
  t_bundle   bun;
  bool       bKink;
  rvec       va,vb,vc,vr,vl;
#define NLEG asize(leg) 
  t_filenm fnm[] = { 
    { efTRX, "-f", NULL, ffREAD }, 
    { efTPS, NULL, NULL, ffREAD }, 
    { efNDX, NULL, NULL, ffOPTRD },
    { efXVG, "-ol", "bun_len", ffWRITE },
    { efXVG, "-od", "bun_dist", ffWRITE },
    { efXVG, "-oz", "bun_z", ffWRITE },
    { efXVG, "-ot", "bun_tilt", ffWRITE },
    { efXVG, "-otr", "bun_tiltr", ffWRITE },
    { efXVG, "-otl", "bun_tiltl", ffWRITE },
    { efXVG, "-ok", "bun_kink", ffOPTWR },
    { efXVG, "-okr", "bun_kinkr", ffOPTWR },
    { efXVG, "-okl", "bun_kinkl", ffOPTWR },
    { efPDB, "-oa", "axes", ffOPTWR }
  }; 
#define NFILE asize(fnm) 

  CopyRight(stderr,argv[0]); 
  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL); 

  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,TRUE);

  bKink = opt2bSet("-ok",NFILE,fnm) || opt2bSet("-okr",NFILE,fnm) 
    || opt2bSet("-okl",NFILE,fnm);
  if (bKink)
    bun.nend = 3;
  else
    bun.nend = 2;
  
  fprintf(stderr,"Select a group of top and a group of bottom ");
  if (bKink)
    fprintf(stderr,"and a group of kink ");
  fprintf(stderr,"atoms\n");
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),bun.nend,
	    gnx,index,grpname);

  if (n<=0 || gnx[0] % n || gnx[1] % n || (bKink && gnx[2] % n))
    gmx_fatal(FARGS,
		"The size of one of your index groups is not a multiple of n");
  bun.n = n;
  snew(bun.end[0],n);
  snew(bun.end[1],n);
  if (bKink)
    snew(bun.end[2],n);
  snew(bun.mid,n);
  snew(bun.dir,n);
  snew(bun.len,n);

  flen   = xvgropen(opt2fn("-ol",NFILE,fnm),"Axis lengths",
		    xvgr_tlabel(),"(nm)");
  fdist  = xvgropen(opt2fn("-od",NFILE,fnm),"Distance of axis centers",
		    xvgr_tlabel(),"(nm)");
  fz     = xvgropen(opt2fn("-oz",NFILE,fnm),"Z-shift of axis centers",
		    xvgr_tlabel(),"(nm)");
  ftilt  = xvgropen(opt2fn("-ot",NFILE,fnm),"Axis tilts",
		    xvgr_tlabel(),"(degrees)");
  ftiltr = xvgropen(opt2fn("-otr",NFILE,fnm),"Radial axis tilts",
		    xvgr_tlabel(),"(degrees)");
  ftiltl = xvgropen(opt2fn("-otl",NFILE,fnm),"Lateral axis tilts",
		    xvgr_tlabel(),"(degrees)");
  
  if (bKink) {
    fkink  = xvgropen(opt2fn("-ok",NFILE,fnm),"Kink angles",
		      xvgr_tlabel(),"(degrees)");
    fkinkr = xvgropen(opt2fn("-okr",NFILE,fnm),"Radial kink angles",
		      xvgr_tlabel(),"(degrees)");
    if (bPrintXvgrCodes())
      fprintf(fkinkr,"@ subtitle \"+ = ) (   - = ( )\"\n");
    fkinkl = xvgropen(opt2fn("-okl",NFILE,fnm),"Lateral kink angles",
		      xvgr_tlabel(),"(degrees)");
  }

  if (opt2bSet("-oa",NFILE,fnm)) {
    init_t_atoms(&outatoms,3*n,FALSE);
    outatoms.nr = 3*n;
    for(i=0; i<3*n; i++) {
      outatoms.atomname[i] = &anm;
      outatoms.atom[i].resnr = i/3;
      outatoms.resname[i/3] = &rnm;
    }
    fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
  } else
    fpdb = -1;
  
  read_first_frame(&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X); 
  
  do {
    rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
    calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
    t = convert_time(fr.time);
    fprintf(flen," %10g",t);
    fprintf(fdist," %10g",t);
    fprintf(fz," %10g",t);
    fprintf(ftilt," %10g",t);
    fprintf(ftiltr," %10g",t);
    fprintf(ftiltl," %10g",t);
    if (bKink) {
      fprintf(fkink," %10g",t);
      fprintf(fkinkr," %10g",t);
      fprintf(fkinkl," %10g",t);
    }

    for(i=0; i<bun.n; i++) {
      fprintf(flen," %6g",bun.len[i]);
      fprintf(fdist," %6g",norm(bun.mid[i]));
      fprintf(fz," %6g",bun.mid[i][ZZ]);
      fprintf(ftilt," %6g",RAD2DEG*acos(bun.dir[i][ZZ]));
      comp = bun.mid[i][XX]*bun.dir[i][XX]+bun.mid[i][YY]*bun.dir[i][YY];
      fprintf(ftiltr," %6g",RAD2DEG*
	      asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
      comp = bun.mid[i][YY]*bun.dir[i][XX]-bun.mid[i][XX]*bun.dir[i][YY];
      fprintf(ftiltl," %6g",RAD2DEG*
	      asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ]))));
      if (bKink) {
	rvec_sub(bun.end[0][i],bun.end[2][i],va);
	rvec_sub(bun.end[2][i],bun.end[1][i],vb);
	unitv_no_table(va,va);
	unitv_no_table(vb,vb);
	fprintf(fkink," %6g",RAD2DEG*acos(iprod(va,vb)));
	cprod(va,vb,vc);
	copy_rvec(bun.mid[i],vr);
	vr[ZZ] = 0;
	unitv_no_table(vr,vr);
	fprintf(fkinkr," %6g",RAD2DEG*asin(iprod(vc,vr)));
	vl[XX] = vr[YY];
	vl[YY] = -vr[XX];
	vl[ZZ] = 0;
	fprintf(fkinkl," %6g",RAD2DEG*asin(iprod(vc,vl)));
      }
    }
    fprintf(flen,"\n");
    fprintf(fdist,"\n");
    fprintf(fz,"\n");
    fprintf(ftilt,"\n");
    fprintf(ftiltr,"\n");
    fprintf(ftiltl,"\n");
    if (bKink) {
      fprintf(fkink,"\n");
      fprintf(fkinkr,"\n");
      fprintf(fkinkl,"\n");
    }
    if (fpdb >= 0)
      dump_axes(fpdb,&fr,&outatoms,&bun);
  } while(read_next_frame(status,&fr));

  close_trx(status);
  
  if (fpdb >= 0)
    close_trx(fpdb);
  fclose(flen);
  fclose(fdist);
  fclose(fz);
  fclose(ftilt);
  fclose(ftiltr);
  fclose(ftiltl);
  if (bKink) {
    fclose(fkink);
    fclose(fkinkr);
    fclose(fkinkl);
  }
  
  thanx(stderr);
  
  return 0;
}
Esempio n. 6
0
void read_eigenvectors(const char *file, int *natoms, gmx_bool *bFit,
                       rvec **xref, gmx_bool *bDMR,
                       rvec **xav, gmx_bool *bDMA,
                       int *nvec, int **eignr,
                       rvec ***eigvec, real **eigval)
{
    gmx_trr_header_t   head;
    int                i, snew_size;
    struct t_fileio   *status;
    rvec              *x;
    matrix             box;
    gmx_bool           bOK;

    *bDMR = FALSE;

    /* read (reference (t=-1) and) average (t=0) structure */
    status = gmx_trr_open(file, "r");
    gmx_trr_read_frame_header(status, &head, &bOK);
    *natoms = head.natoms;
    snew(*xav, *natoms);
    gmx_trr_read_frame_data(status, &head, box, *xav, NULL, NULL);

    if ((head.t >= -1.1) && (head.t <= -0.9))
    {
        snew(*xref, *natoms);
        for (i = 0; i < *natoms; i++)
        {
            copy_rvec((*xav)[i], (*xref)[i]);
        }
        *bDMR = (head.lambda > 0.5);
        *bFit = (head.lambda > -0.5);
        if (*bFit)
        {
            fprintf(stderr, "Read %smass weighted reference structure with %d atoms from %s\n", *bDMR ? "" : "non ", *natoms, file);
        }
        else
        {
            fprintf(stderr, "Eigenvectors in %s were determined without fitting\n", file);
            sfree(*xref);
            *xref = NULL;
        }
        gmx_trr_read_frame_header(status, &head, &bOK);
        gmx_trr_read_frame_data(status, &head, box, *xav, NULL, NULL);
    }
    else
    {
        *bFit = TRUE;
        *xref = NULL;
    }
    *bDMA = (head.lambda > 0.5);
    if ((head.t <= -0.01) || (head.t >= 0.01))
    {
        fprintf(stderr, "WARNING: %s does not start with t=0, which should be the "
                "average structure. This might not be a eigenvector file. "
                "Some things might go wrong.\n",
                file);
    }
    else
    {
        fprintf(stderr,
                "Read %smass weighted average/minimum structure with %d atoms from %s\n",
                *bDMA ? "" : "non ", *natoms, file);
    }

    snew(x, *natoms);
    snew_size = 10;
    snew(*eignr, snew_size);
    snew(*eigval, snew_size);
    snew(*eigvec, snew_size);

    *nvec = 0;
    while (gmx_trr_read_frame_header(status, &head, &bOK))
    {
        gmx_trr_read_frame_data(status, &head, box, x, NULL, NULL);
        if (*nvec >= snew_size)
        {
            snew_size += 10;
            srenew(*eignr, snew_size);
            srenew(*eigval, snew_size);
            srenew(*eigvec, snew_size);
        }
        i                = head.step;
        (*eigval)[*nvec] = head.t;
        (*eignr)[*nvec]  = i-1;
        snew((*eigvec)[*nvec], *natoms);
        for (i = 0; i < *natoms; i++)
        {
            copy_rvec(x[i], (*eigvec)[*nvec][i]);
        }
        (*nvec)++;
    }
    sfree(x);
    gmx_trr_close(status);
    fprintf(stderr, "Read %d eigenvectors (for %d atoms)\n\n", *nvec, *natoms);
}
Esempio n. 7
0
void calc_running_com(t_pull *pull) {
  int i,j,n;
  rvec ave;
  real tm;
  
  /* for group i, we have nhist[i] points of history. The maximum nr of points
     is pull->reflag. The array comhist[i][0..nhist[i]-1] has the positions
     of the center of mass over the last nhist[i] steps. x_unc[i] has the
     new ones. Remove the oldest one from the list, add the new one, calculate
     the average, put that in x_unc instead and return. We just move all coms
     1 down in the list and add the latest one to the top. 
   */
  
  if (pull->bCyl) {
    /* act on dyna groups */
    for (i=0;i<pull->pull.n;i++) {
      clear_rvec(ave);
      for (j=0;j<(pull->reflag-1);j++) {
	copy_rvec(pull->dyna.comhist[i][j+1],pull->dyna.comhist[i][j]);
	rvec_add(ave,pull->dyna.comhist[i][j],ave);
      }
      copy_rvec(pull->dyna.x_unc[i],pull->dyna.comhist[i][j]);
      rvec_add(ave,pull->dyna.x_unc[i],ave);
      svmul(1.0/pull->reflag,ave,ave); 

      /* now ave has the running com for group i, copy it to x_unc[i] */
      copy_rvec(ave,pull->dyna.x_unc[i]);

#ifdef DEBUG
      if (pull->bVerbose) 
	for (n=0;n<pull->reflag;n++) 
	  fprintf(stderr,"Comhist %d, grp %d: %8.3f%8.3f%8.3f\n",n,i,
		  pull->dyna.comhist[i][n][XX],
		  pull->dyna.comhist[i][n][YY],
  		  pull->dyna.comhist[i][n][ZZ]);
#endif
    }
  } else {
    /* act on ref group */
    clear_rvec(ave);
    
    for (j=0;j<(pull->reflag-1);j++) {
      copy_rvec(pull->ref.comhist[0][j+1],pull->ref.comhist[0][j]);
      rvec_add(ave,pull->ref.comhist[0][j],ave);
    }
    
    copy_rvec(pull->ref.x_unc[0],pull->ref.comhist[0][j]);
    rvec_add(ave,pull->ref.x_unc[0],ave);
    svmul(1.0/pull->reflag,ave,ave); 
    /* now ave has the running com for group i, copy it to x_unc[0] */
    copy_rvec(ave,pull->ref.x_unc[0]);

#ifdef DEBUG
    if (pull->bVerbose) 
      for (i=0;i<pull->reflag;i++) 
	fprintf(stderr,"Comhist %d: %8.3f%8.3f%8.3f\n",i,
		pull->ref.comhist[0][i][XX],
		pull->ref.comhist[0][i][YY],
		pull->ref.comhist[0][i][ZZ]);
#endif
  }
}
Esempio n. 8
0
static void dd_pmeredist_pos_coeffs(struct gmx_pme_t *pme,
                                    int n, gmx_bool bX, rvec *x, real *data,
                                    pme_atomcomm_t *atc)
{
    int *commnode, *buf_index;
    int  nnodes_comm, i, nsend, local_pos, buf_pos, node, scount, rcount;

    commnode  = atc->node_dest;
    buf_index = atc->buf_index;

    nnodes_comm = min(2*atc->maxshift, atc->nslab-1);

    nsend = 0;
    for (i = 0; i < nnodes_comm; i++)
    {
        buf_index[commnode[i]] = nsend;
        nsend                 += atc->count[commnode[i]];
    }
    if (bX)
    {
        if (atc->count[atc->nodeid] + nsend != n)
        {
            gmx_fatal(FARGS, "%d particles communicated to PME rank %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n"
                      "This usually means that your system is not well equilibrated.",
                      n - (atc->count[atc->nodeid] + nsend),
                      pme->nodeid, 'x'+atc->dimind);
        }

        if (nsend > pme->buf_nalloc)
        {
            pme->buf_nalloc = over_alloc_dd(nsend);
            srenew(pme->bufv, pme->buf_nalloc);
            srenew(pme->bufr, pme->buf_nalloc);
        }

        atc->n = atc->count[atc->nodeid];
        for (i = 0; i < nnodes_comm; i++)
        {
            scount = atc->count[commnode[i]];
            /* Communicate the count */
            if (debug)
            {
                fprintf(debug, "dimind %d PME rank %d send to rank %d: %d\n",
                        atc->dimind, atc->nodeid, commnode[i], scount);
            }
            pme_dd_sendrecv(atc, FALSE, i,
                            &scount, sizeof(int),
                            &atc->rcount[i], sizeof(int));
            atc->n += atc->rcount[i];
        }

        pme_realloc_atomcomm_things(atc);
    }

    local_pos = 0;
    for (i = 0; i < n; i++)
    {
        node = atc->pd[i];
        if (node == atc->nodeid)
        {
            /* Copy direct to the receive buffer */
            if (bX)
            {
                copy_rvec(x[i], atc->x[local_pos]);
            }
            atc->coefficient[local_pos] = data[i];
            local_pos++;
        }
        else
        {
            /* Copy to the send buffer */
            if (bX)
            {
                copy_rvec(x[i], pme->bufv[buf_index[node]]);
            }
            pme->bufr[buf_index[node]] = data[i];
            buf_index[node]++;
        }
    }

    buf_pos = 0;
    for (i = 0; i < nnodes_comm; i++)
    {
        scount = atc->count[commnode[i]];
        rcount = atc->rcount[i];
        if (scount > 0 || rcount > 0)
        {
            if (bX)
            {
                /* Communicate the coordinates */
                pme_dd_sendrecv(atc, FALSE, i,
                                pme->bufv[buf_pos], scount*sizeof(rvec),
                                atc->x[local_pos], rcount*sizeof(rvec));
            }
            /* Communicate the coefficients */
            pme_dd_sendrecv(atc, FALSE, i,
                            pme->bufr+buf_pos, scount*sizeof(real),
                            atc->coefficient+local_pos, rcount*sizeof(real));
            buf_pos   += scount;
            local_pos += atc->rcount[i];
        }
    }
}
Esempio n. 9
0
void dd_pmeredist_f(struct gmx_pme_t *pme, pme_atomcomm_t *atc,
                    int n, rvec *f,
                    gmx_bool bAddF)
{
    int *commnode, *buf_index;
    int  nnodes_comm, local_pos, buf_pos, i, scount, rcount, node;

    commnode  = atc->node_dest;
    buf_index = atc->buf_index;

    nnodes_comm = min(2*atc->maxshift, atc->nslab-1);

    local_pos = atc->count[atc->nodeid];
    buf_pos   = 0;
    for (i = 0; i < nnodes_comm; i++)
    {
        scount = atc->rcount[i];
        rcount = atc->count[commnode[i]];
        if (scount > 0 || rcount > 0)
        {
            /* Communicate the forces */
            pme_dd_sendrecv(atc, TRUE, i,
                            atc->f[local_pos], scount*sizeof(rvec),
                            pme->bufv[buf_pos], rcount*sizeof(rvec));
            local_pos += scount;
        }
        buf_index[commnode[i]] = buf_pos;
        buf_pos               += rcount;
    }

    local_pos = 0;
    if (bAddF)
    {
        for (i = 0; i < n; i++)
        {
            node = atc->pd[i];
            if (node == atc->nodeid)
            {
                /* Add from the local force array */
                rvec_inc(f[i], atc->f[local_pos]);
                local_pos++;
            }
            else
            {
                /* Add from the receive buffer */
                rvec_inc(f[i], pme->bufv[buf_index[node]]);
                buf_index[node]++;
            }
        }
    }
    else
    {
        for (i = 0; i < n; i++)
        {
            node = atc->pd[i];
            if (node == atc->nodeid)
            {
                /* Copy from the local force array */
                copy_rvec(atc->f[local_pos], f[i]);
                local_pos++;
            }
            else
            {
                /* Copy from the receive buffer */
                copy_rvec(pme->bufv[buf_index[node]], f[i]);
                buf_index[node]++;
            }
        }
    }
}
Esempio n. 10
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;
    matrix            box;
    t_trxstatus      *status;
    int               natoms;
    real              theta1, theta2, theta3;

    int               i, j, teller = 0;
    int               iCA, iSC;
    int              *ind_CA;
    int              *ind_SC;
    char             *gn_CA;
    char             *gn_SC;
    rvec              v1, v2;
    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             *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;
    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;

    gmx_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 * std::acos( tmp );
            radius[i] = std::sqrt( norm(diff13[i])*norm(diff24[i]) ) / (2.0* (1.0-tmp) );
            rise[i]   = std::abs(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*std::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]);
            }
        }
        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]);

                    /* 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.
                     */

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

                    tilt     = std::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);
    xvgrclose(fptilt);
    xvgrclose(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;
}
Esempio n. 11
0
int gmx_traj(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] plots coordinates, velocities, forces and/or the box.",
        "With [TT]-com[tt] the coordinates, velocities and forces are",
        "calculated for the center of mass of each group.",
        "When [TT]-mol[tt] is set, the numbers in the index file are",
        "interpreted as molecule numbers and the same procedure as with",
        "[TT]-com[tt] is used for each molecule.[PAR]",
        "Option [TT]-ot[tt] plots the temperature of each group,",
        "provided velocities are present in the trajectory file.",
        "No corrections are made for constrained degrees of freedom!",
        "This implies [TT]-com[tt].[PAR]",
        "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and",
        "rotational kinetic energy of each group,",
        "provided velocities are present in the trajectory file.",
        "This implies [TT]-com[tt].[PAR]",
        "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities",
        "and average forces as temperature factors to a [REF].pdb[ref] file with",
        "the average coordinates or the coordinates at [TT]-ctime[tt].",
        "The temperature factors are scaled such that the maximum is 10.",
        "The scaling can be changed with the option [TT]-scale[tt].",
        "To get the velocities or forces of one",
        "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of",
        "desired frame. When averaging over frames you might need to use",
        "the [TT]-nojump[tt] option to obtain the correct average coordinates.",
        "If you select either of these option the average force and velocity",
        "for each atom are written to an [REF].xvg[ref] file as well",
        "(specified with [TT]-av[tt] or [TT]-af[tt]).[PAR]",
        "Option [TT]-vd[tt] computes a velocity distribution, i.e. the",
        "norm of the vector is plotted. In addition in the same graph",
        "the kinetic energy distribution is given."
    };
    static gmx_bool   bMol    = FALSE, bCom = FALSE, bPBC = TRUE, bNoJump = FALSE;
    static gmx_bool   bX      = TRUE, bY = TRUE, bZ = TRUE, bNorm = FALSE, bFP = FALSE;
    static int        ngroups = 1;
    static real       ctime   = -1, scale = 0, binwidth = 1;
    t_pargs           pa[]    = {
        { "-com", FALSE, etBOOL, {&bCom},
          "Plot data for the com of each group" },
        { "-pbc", FALSE, etBOOL, {&bPBC},
          "Make molecules whole for COM" },
        { "-mol", FALSE, etBOOL, {&bMol},
          "Index contains molecule numbers iso atom numbers" },
        { "-nojump", FALSE, etBOOL, {&bNoJump},
          "Remove jumps of atoms across the box" },
        { "-x", FALSE, etBOOL, {&bX},
          "Plot X-component" },
        { "-y", FALSE, etBOOL, {&bY},
          "Plot Y-component" },
        { "-z", FALSE, etBOOL, {&bZ},
          "Plot Z-component" },
        { "-ng",       FALSE, etINT, {&ngroups},
          "Number of groups to consider" },
        { "-len", FALSE, etBOOL, {&bNorm},
          "Plot vector length" },
        { "-fp", FALSE, etBOOL, {&bFP},
          "Full precision output" },
        { "-bin", FALSE, etREAL, {&binwidth},
          "Binwidth for velocity histogram (nm/ps)" },
        { "-ctime", FALSE, etREAL, {&ctime},
          "Use frame at this time for x in [TT]-cv[tt] and [TT]-cf[tt] instead of the average x" },
        { "-scale", FALSE, etREAL, {&scale},
          "Scale factor for [REF].pdb[ref] output, 0 is autoscale" }
    };
    FILE             *outx   = NULL, *outv = NULL, *outf = NULL, *outb = NULL, *outt = NULL;
    FILE             *outekt = NULL, *outekr = NULL;
    t_topology        top;
    int               ePBC;
    real             *mass, time;
    const char       *indexfn;
    t_trxframe        fr, frout;
    int               flags, nvhisto = 0, *vhisto = NULL;
    rvec             *xtop, *xp = NULL;
    rvec             *sumx = NULL, *sumv = NULL, *sumf = NULL;
    matrix            topbox;
    t_trxstatus      *status;
    t_trxstatus      *status_out = NULL;
    gmx_rmpbc_t       gpbc       = NULL;
    int               i, j;
    int               nr_xfr, nr_vfr, nr_ffr;
    char            **grpname;
    int              *isize0, *isize;
    int             **index0, **index;
    int              *atndx;
    t_block          *mols;
    gmx_bool          bTop, bOX, bOXT, bOV, bOF, bOB, bOT, bEKT, bEKR, bCV, bCF;
    gmx_bool          bDim[4], bDum[4], bVD;
    char              sffmt[STRLEN], sffmt6[STRLEN];
    const char       *box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" };
    gmx_output_env_t *oenv;

    t_filenm          fnm[] = {
        { efTRX, "-f", NULL, ffREAD },
        { efTPS, NULL, NULL, ffREAD },
        { efNDX, NULL, NULL, ffOPTRD },
        { efXVG, "-ox",  "coord",     ffOPTWR },
        { efTRX, "-oxt", "coord",     ffOPTWR },
        { efXVG, "-ov",  "veloc",     ffOPTWR },
        { efXVG, "-of",  "force",     ffOPTWR },
        { efXVG, "-ob",  "box",       ffOPTWR },
        { efXVG, "-ot",  "temp",      ffOPTWR },
        { efXVG, "-ekt", "ektrans",   ffOPTWR },
        { efXVG, "-ekr", "ekrot",     ffOPTWR },
        { efXVG, "-vd",  "veldist",   ffOPTWR },
        { efPDB, "-cv",  "veloc",     ffOPTWR },
        { efPDB, "-cf",  "force",     ffOPTWR },
        { efXVG, "-av",  "all_veloc", ffOPTWR },
        { efXVG, "-af",  "all_force", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    if (bMol)
    {
        fprintf(stderr, "Interpreting indexfile entries as molecules.\n"
                "Using center of mass.\n");
    }

    bOX  = opt2bSet("-ox", NFILE, fnm);
    bOXT = opt2bSet("-oxt", NFILE, fnm);
    bOV  = opt2bSet("-ov", NFILE, fnm);
    bOF  = opt2bSet("-of", NFILE, fnm);
    bOB  = opt2bSet("-ob", NFILE, fnm);
    bOT  = opt2bSet("-ot", NFILE, fnm);
    bEKT = opt2bSet("-ekt", NFILE, fnm);
    bEKR = opt2bSet("-ekr", NFILE, fnm);
    bCV  = opt2bSet("-cv", NFILE, fnm) || opt2bSet("-av", NFILE, fnm);
    bCF  = opt2bSet("-cf", NFILE, fnm) || opt2bSet("-af", NFILE, fnm);
    bVD  = opt2bSet("-vd", NFILE, fnm) || opt2parg_bSet("-bin", asize(pa), pa);
    if (bMol || bOT || bEKT || bEKR)
    {
        bCom = TRUE;
    }

    bDim[XX]  = bX;
    bDim[YY]  = bY;
    bDim[ZZ]  = bZ;
    bDim[DIM] = bNorm;

    if (bFP)
    {
        sprintf(sffmt, "\t%s", gmx_real_fullprecision_pfmt);
    }
    else
    {
        sprintf(sffmt, "\t%%g");
    }
    sprintf(sffmt6, "%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt);

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC,
                         &xtop, NULL, topbox,
                         bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR));
    sfree(xtop);
    if ((bMol || bCV || bCF) && !bTop)
    {
        gmx_fatal(FARGS, "Need a run input file for option -mol, -cv or -cf");
    }

    if (bMol)
    {
        indexfn = ftp2fn(efNDX, NFILE, fnm);
    }
    else
    {
        indexfn = ftp2fn_null(efNDX, NFILE, fnm);
    }

    if (!(bCom && !bMol))
    {
        ngroups = 1;
    }
    snew(grpname, ngroups);
    snew(isize0, ngroups);
    snew(index0, ngroups);
    get_index(&(top.atoms), indexfn, ngroups, isize0, index0, grpname);

    if (bMol)
    {
        mols    = &(top.mols);
        atndx   = mols->index;
        ngroups = isize0[0];
        snew(isize, ngroups);
        snew(index, ngroups);
        for (i = 0; i < ngroups; i++)
        {
            if (index0[0][i] < 0 || index0[0][i] >= mols->nr)
            {
                gmx_fatal(FARGS, "Molecule index (%d) is out of range (%d-%d)",
                          index0[0][i]+1, 1, mols->nr);
            }
            isize[i] = atndx[index0[0][i]+1] - atndx[index0[0][i]];
            snew(index[i], isize[i]);
            for (j = 0; j < isize[i]; j++)
            {
                index[i][j] = atndx[index0[0][i]] + j;
            }
        }
    }
    else
    {
        isize = isize0;
        index = index0;
    }
    if (bCom)
    {
        snew(mass, top.atoms.nr);
        for (i = 0; i < top.atoms.nr; i++)
        {
            mass[i] = top.atoms.atom[i].m;
        }
    }
    else
    {
        mass = NULL;
    }

    flags = 0;
    if (bOX)
    {
        flags = flags | TRX_READ_X;
        outx  = xvgropen(opt2fn("-ox", NFILE, fnm),
                         bCom ? "Center of mass" : "Coordinate",
                         output_env_get_xvgr_tlabel(oenv), "Coordinate (nm)", oenv);
        make_legend(outx, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOXT)
    {
        flags      = flags | TRX_READ_X;
        status_out = open_trx(opt2fn("-oxt", NFILE, fnm), "w");
    }
    if (bOV)
    {
        flags = flags | TRX_READ_V;
        outv  = xvgropen(opt2fn("-ov", NFILE, fnm),
                         bCom ? "Center of mass velocity" : "Velocity",
                         output_env_get_xvgr_tlabel(oenv), "Velocity (nm/ps)", oenv);
        make_legend(outv, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOF)
    {
        flags = flags | TRX_READ_F;
        outf  = xvgropen(opt2fn("-of", NFILE, fnm), "Force",
                         output_env_get_xvgr_tlabel(oenv), "Force (kJ mol\\S-1\\N nm\\S-1\\N)",
                         oenv);
        make_legend(outf, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv);
    }
    if (bOB)
    {
        outb = xvgropen(opt2fn("-ob", NFILE, fnm), "Box vector elements",
                        output_env_get_xvgr_tlabel(oenv), "(nm)", oenv);

        xvgr_legend(outb, 6, box_leg, oenv);
    }
    if (bOT)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_V;
        outt      = xvgropen(opt2fn("-ot", NFILE, fnm), "Temperature",
                             output_env_get_xvgr_tlabel(oenv), "(K)", oenv);
        make_legend(outt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bEKT)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_V;
        outekt    = xvgropen(opt2fn("-ekt", NFILE, fnm), "Center of mass translation",
                             output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv);
        make_legend(outekt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bEKR)
    {
        bDum[XX]  = FALSE;
        bDum[YY]  = FALSE;
        bDum[ZZ]  = FALSE;
        bDum[DIM] = TRUE;
        flags     = flags | TRX_READ_X | TRX_READ_V;
        outekr    = xvgropen(opt2fn("-ekr", NFILE, fnm), "Center of mass rotation",
                             output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv);
        make_legend(outekr, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv);
    }
    if (bVD)
    {
        flags = flags | TRX_READ_V;
    }
    if (bCV)
    {
        flags = flags | TRX_READ_X | TRX_READ_V;
    }
    if (bCF)
    {
        flags = flags | TRX_READ_X | TRX_READ_F;
    }
    if ((flags == 0) && !bOB)
    {
        fprintf(stderr, "Please select one or more output file options\n");
        exit(0);
    }

    read_first_frame(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &fr, flags);


    if ((bOV || bOF) && fn2ftp(ftp2fn(efTRX, NFILE, fnm)) == efXTC)
    {
        gmx_fatal(FARGS, "Cannot extract velocities or forces since your input XTC file does not contain them.");
    }

    if (bCV || bCF)
    {
        snew(sumx, fr.natoms);
    }
    if (bCV)
    {
        snew(sumv, fr.natoms);
    }
    if (bCF)
    {
        snew(sumf, fr.natoms);
    }
    nr_xfr = 0;
    nr_vfr = 0;
    nr_ffr = 0;

    if (bCom && bPBC)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);
    }

    do
    {
        time = output_env_conv_time(oenv, fr.time);

        if (fr.bX && bNoJump && fr.bBox)
        {
            if (xp)
            {
                remove_jump(fr.box, fr.natoms, xp, fr.x);
            }
            else
            {
                snew(xp, fr.natoms);
            }
            for (i = 0; i < fr.natoms; i++)
            {
                copy_rvec(fr.x[i], xp[i]);
            }
        }

        if (fr.bX && bCom && bPBC)
        {
            gmx_rmpbc_trxfr(gpbc, &fr);
        }

        if (bVD && fr.bV)
        {
            update_histo(isize[0], index[0], fr.v, &nvhisto, &vhisto, binwidth);
        }

        if (bOX && fr.bX)
        {
            print_data(outx, time, fr.x, mass, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOXT && fr.bX)
        {
            frout = fr;
            if (!frout.bAtoms)
            {
                frout.atoms  = &top.atoms;
                frout.bAtoms = TRUE;
            }
            write_trx_x(status_out, &frout, mass, bCom, ngroups, isize, index);
        }
        if (bOV && fr.bV)
        {
            print_data(outv, time, fr.v, mass, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOF && fr.bF)
        {
            print_data(outf, time, fr.f, NULL, bCom, ngroups, isize, index, bDim, sffmt);
        }
        if (bOB && fr.bBox)
        {
            fprintf(outb, "\t%g", fr.time);
            fprintf(outb, sffmt6,
                    fr.box[XX][XX], fr.box[YY][YY], fr.box[ZZ][ZZ],
                    fr.box[YY][XX], fr.box[ZZ][XX], fr.box[ZZ][YY]);
            fprintf(outb, "\n");
        }
        if (bOT && fr.bV)
        {
            fprintf(outt, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outt, sffmt, temp(fr.v, mass, isize[i], index[i]));
            }
            fprintf(outt, "\n");
        }
        if (bEKT && fr.bV)
        {
            fprintf(outekt, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outekt, sffmt, ektrans(fr.v, mass, isize[i], index[i]));
            }
            fprintf(outekt, "\n");
        }
        if (bEKR && fr.bX && fr.bV)
        {
            fprintf(outekr, " %g", time);
            for (i = 0; i < ngroups; i++)
            {
                fprintf(outekr, sffmt, ekrot(fr.x, fr.v, mass, isize[i], index[i]));
            }
            fprintf(outekr, "\n");
        }
        if ((bCV || bCF) && fr.bX &&
            (ctime < 0 || (fr.time >= ctime*0.999999 &&
                           fr.time <= ctime*1.000001)))
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumx[i], fr.x[i]);
            }
            nr_xfr++;
        }
        if (bCV && fr.bV)
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumv[i], fr.v[i]);
            }
            nr_vfr++;
        }
        if (bCF && fr.bF)
        {
            for (i = 0; i < fr.natoms; i++)
            {
                rvec_inc(sumf[i], fr.f[i]);
            }
            nr_ffr++;
        }

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

    if (gpbc != NULL)
    {
        gmx_rmpbc_done(gpbc);
    }

    /* clean up a bit */
    close_trj(status);

    if (bOX)
    {
        xvgrclose(outx);
    }
    if (bOXT)
    {
        close_trx(status_out);
    }
    if (bOV)
    {
        xvgrclose(outv);
    }
    if (bOF)
    {
        xvgrclose(outf);
    }
    if (bOB)
    {
        xvgrclose(outb);
    }
    if (bOT)
    {
        xvgrclose(outt);
    }
    if (bEKT)
    {
        xvgrclose(outekt);
    }
    if (bEKR)
    {
        xvgrclose(outekr);
    }

    if (bVD)
    {
        print_histo(opt2fn("-vd", NFILE, fnm), nvhisto, vhisto, binwidth, oenv);
    }

    if (bCV || bCF)
    {
        if (nr_xfr > 1)
        {
            if (ePBC != epbcNONE && !bNoJump)
            {
                fprintf(stderr, "\nWARNING: More than one frame was used for option -cv or -cf\n"
                        "If atoms jump across the box you should use the -nojump or -ctime option\n\n");
            }
            for (i = 0; i < isize[0]; i++)
            {
                svmul(1.0/nr_xfr, sumx[index[0][i]], sumx[index[0][i]]);
            }
        }
        else if (nr_xfr == 0)
        {
            fprintf(stderr, "\nWARNING: No coordinate frames found for option -cv or -cf\n\n");
        }
    }
    if (bCV)
    {
        write_pdb_bfac(opt2fn("-cv", NFILE, fnm),
                       opt2fn("-av", NFILE, fnm), "average velocity", &(top.atoms),
                       ePBC, topbox, isize[0], index[0], nr_xfr, sumx,
                       nr_vfr, sumv, bDim, scale, oenv);
    }
    if (bCF)
    {
        write_pdb_bfac(opt2fn("-cf", NFILE, fnm),
                       opt2fn("-af", NFILE, fnm), "average force", &(top.atoms),
                       ePBC, topbox, isize[0], index[0], nr_xfr, sumx,
                       nr_ffr, sumf, bDim, scale, oenv);
    }

    /* view it */
    view_all(oenv, NFILE, fnm);

    return 0;
}
Esempio n. 12
0
void connelly_plot(const char *fn,int ndots,real dots[],rvec x[],t_atoms *atoms,
		   t_symtab *symtab,int ePBC,matrix box,gmx_bool bSave)
{
  static const char *atomnm="DOT";
  static const char *resnm ="DOT";
  static const char *title ="Connely Dot Surface Generated by g_sas";

  int  i,i0,r0,ii0,k;
  rvec *xnew;
  t_atoms aaa;

  if (bSave) {  
    i0 = atoms->nr;
    r0 = atoms->nres;
    srenew(atoms->atom,atoms->nr+ndots);
    srenew(atoms->atomname,atoms->nr+ndots);
    srenew(atoms->resinfo,r0+1);
    atoms->atom[i0].resind = r0;
    t_atoms_set_resinfo(atoms,i0,symtab,resnm,r0+1,' ',0,' ');
    srenew(atoms->pdbinfo,atoms->nr+ndots);
    snew(xnew,atoms->nr+ndots);
    for(i=0; (i<atoms->nr); i++)
      copy_rvec(x[i],xnew[i]);
    for(i=k=0; (i<ndots); i++) {
      ii0 = i0+i;
      atoms->atomname[ii0] = put_symtab(symtab,atomnm);
      atoms->pdbinfo[ii0].type = epdbATOM;
      atoms->pdbinfo[ii0].atomnr= ii0;
      atoms->atom[ii0].resind = r0;
      xnew[ii0][XX] = dots[k++];
      xnew[ii0][YY] = dots[k++];
      xnew[ii0][ZZ] = dots[k++];
      atoms->pdbinfo[ii0].bfac  = 0.0;
      atoms->pdbinfo[ii0].occup = 0.0;
    }
    atoms->nr   = i0+ndots;
    atoms->nres = r0+1;
    write_sto_conf(fn,title,atoms,xnew,NULL,ePBC,box);
    atoms->nres = r0;
    atoms->nr   = i0;
  }
  else {
    init_t_atoms(&aaa,ndots,TRUE);
    aaa.atom[0].resind = 0;
    t_atoms_set_resinfo(&aaa,0,symtab,resnm,1,' ',0,' ');
    snew(xnew,ndots);
    for(i=k=0; (i<ndots); i++) {
      ii0 = i;
      aaa.atomname[ii0] = put_symtab(symtab,atomnm);
      aaa.pdbinfo[ii0].type = epdbATOM;
      aaa.pdbinfo[ii0].atomnr= ii0;
      aaa.atom[ii0].resind = 0;
      xnew[ii0][XX] = dots[k++];
      xnew[ii0][YY] = dots[k++];
      xnew[ii0][ZZ] = dots[k++];
      aaa.pdbinfo[ii0].bfac  = 0.0;
      aaa.pdbinfo[ii0].occup = 0.0;
    }
    aaa.nr = ndots;
    write_sto_conf(fn,title,&aaa,xnew,NULL,ePBC,box);
    do_conect(fn,ndots,xnew);
    free_t_atoms(&aaa,FALSE);
  }
  sfree(xnew);
}
Esempio n. 13
0
void sgangle_plot_single(const char *fn,const char *afile,const char *dfile, 
			 const char *d1file, const char *d2file,
			 atom_id index1[], int gnx1, char *grpn1,
			 atom_id index2[], int gnx2, char *grpn2,
			 t_topology *top,int ePBC, const output_env_t oenv)
{
  FILE         
    *sg_angle,           /* xvgr file with angles */
    *sg_distance = NULL, /* xvgr file with distances */
    *sg_distance1 = NULL,/* xvgr file with distance between plane and atom */
    *sg_distance2 = NULL;/* xvgr file with distance between plane and atom2 */
  real         
    t,                   /* time */
    angle,               /* cosine of angle between two groups */
    distance,            /* distance between two groups. */
    distance1,           /* distance between plane and one of two atoms */
    distance2;           /* same for second of two atoms */
  t_trxstatus *status;
  int        natoms,teller=0;
  int        i;
  rvec       *x0;   /* coordinates, and coordinates corrected for pb */
  rvec       *xzero;
  matrix     box;        
  char       buf[256];   /* for xvgr title */
  gmx_rmpbc_t  gpbc=NULL;
  

  if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
    gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
  
  sprintf(buf,"Angle between %s and %s",grpn1,grpn2);
  sg_angle = xvgropen(afile,buf,"Time (ps)","Cos(angle) ",oenv);
  
  if (dfile) {
    sprintf(buf,"Distance between %s and %s",grpn1,grpn2);
    sg_distance = xvgropen(dfile,buf,"Time (ps)","Distance (nm)",oenv);
  }
  
  if (d1file) {
    sprintf(buf,"Distance between plane and first atom of vector");
    sg_distance1 = xvgropen(d1file,buf,"Time (ps)","Distance (nm)",oenv);
  }
  
  if (d2file) {
    sprintf(buf,"Distance between plane and second atom of vector");
    sg_distance2 = xvgropen(d2file,buf,"Time (ps","Distance (nm)",oenv);
  }
  
  snew(xzero,natoms);
  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);

  do {
    teller++;
    
    gmx_rmpbc(gpbc,natoms,box,x0);
    if (teller==1) {
      for(i=0;i<natoms;i++)
	copy_rvec(x0[i],xzero[i]);
    }
    
    
    calc_angle_single(ePBC,box,
		      xzero,x0,index1,index2,gnx1,gnx2,&angle,
		      &distance,&distance1,&distance2);
    
    fprintf(sg_angle,"%12g  %12g  %12g\n",t,angle,acos(angle)*180.0/M_PI);
    if (dfile)
      fprintf(sg_distance,"%12g  %12g\n",t,distance);
    if (d1file)
      fprintf(sg_distance1,"%12g  %12g\n",t,distance1);
    if (d2file)
      fprintf(sg_distance2,"%12g  %12g\n",t,distance1);
    
  } while (read_next_x(oenv,status,&t,natoms,x0,box));
  gmx_rmpbc_done(gpbc);
  
  fprintf(stderr,"\n");
  close_trj(status);
  ffclose(sg_angle);
  if (dfile)
    ffclose(sg_distance);
  if (d1file)
    ffclose(sg_distance1);
  if (d2file)
    ffclose(sg_distance2);
  
  sfree(x0);
}
Esempio n. 14
0
/* calculates center of mass of selection index from all coordinates x */
void pull_calc_coms(t_commrec *cr,
                    struct pull_t *pull, t_mdatoms *md, t_pbc *pbc, double t,
                    rvec x[], rvec *xp)
{
    int          g;
    real         twopi_box = 0;
    pull_comm_t *comm;

    comm = &pull->comm;

    if (comm->rbuf == NULL)
    {
        snew(comm->rbuf, pull->ngroup);
    }
    if (comm->dbuf == NULL)
    {
        snew(comm->dbuf, 3*pull->ngroup);
    }

    if (pull->bRefAt && pull->bSetPBCatoms)
    {
        pull_set_pbcatoms(cr, pull, x, comm->rbuf);

        if (cr != NULL && DOMAINDECOMP(cr))
        {
            /* We can keep these PBC reference coordinates fixed for nstlist
             * steps, since atoms won't jump over PBC.
             * This avoids a global reduction at the next nstlist-1 steps.
             * Note that the exact values of the pbc reference coordinates
             * are irrelevant, as long all atoms in the group are within
             * half a box distance of the reference coordinate.
             */
            pull->bSetPBCatoms = FALSE;
        }
    }

    if (pull->cosdim >= 0)
    {
        int m;

        assert(pull->npbcdim <= DIM);

        for (m = pull->cosdim+1; m < pull->npbcdim; m++)
        {
            if (pbc->box[m][pull->cosdim] != 0)
            {
                gmx_fatal(FARGS, "Can not do cosine weighting for trilinic dimensions");
            }
        }
        twopi_box = 2.0*M_PI/pbc->box[pull->cosdim][pull->cosdim];
    }

    for (g = 0; g < pull->ngroup; g++)
    {
        pull_group_work_t *pgrp;

        pgrp = &pull->group[g];

        if (pgrp->bCalcCOM)
        {
            if (pgrp->epgrppbc != epgrppbcCOS)
            {
                dvec   com, comp;
                double wmass, wwmass;
                rvec   x_pbc = { 0, 0, 0 };
                int    i;

                clear_dvec(com);
                clear_dvec(comp);
                wmass  = 0;
                wwmass = 0;

                if (pgrp->epgrppbc == epgrppbcREFAT)
                {
                    /* Set the pbc atom */
                    copy_rvec(comm->rbuf[g], x_pbc);
                }

                for (i = 0; i < pgrp->nat_loc; i++)
                {
                    int  ii, m;
                    real mass, wm;

                    ii   = pgrp->ind_loc[i];
                    mass = md->massT[ii];
                    if (pgrp->weight_loc == NULL)
                    {
                        wm     = mass;
                        wmass += wm;
                    }
                    else
                    {
                        real w;

                        w       = pgrp->weight_loc[i];
                        wm      = w*mass;
                        wmass  += wm;
                        wwmass += wm*w;
                    }
                    if (pgrp->epgrppbc == epgrppbcNONE)
                    {
                        /* Plain COM: sum the coordinates */
                        for (m = 0; m < DIM; m++)
                        {
                            com[m]    += wm*x[ii][m];
                        }
                        if (xp)
                        {
                            for (m = 0; m < DIM; m++)
                            {
                                comp[m] += wm*xp[ii][m];
                            }
                        }
                    }
                    else
                    {
                        rvec dx;

                        /* Sum the difference with the reference atom */
                        pbc_dx(pbc, x[ii], x_pbc, dx);
                        for (m = 0; m < DIM; m++)
                        {
                            com[m]    += wm*dx[m];
                        }
                        if (xp)
                        {
                            /* For xp add the difference between xp and x to dx,
                             * such that we use the same periodic image,
                             * also when xp has a large displacement.
                             */
                            for (m = 0; m < DIM; m++)
                            {
                                comp[m] += wm*(dx[m] + xp[ii][m] - x[ii][m]);
                            }
                        }
                    }
                }

                /* We do this check after the loop above to avoid more nesting.
                 * If we have a single-atom group the mass is irrelevant, so
                 * we can remove the mass factor to avoid division by zero.
                 * Note that with constraint pulling the mass does matter, but
                 * in that case a check group mass != 0 has been done before.
                 */
                if (pgrp->params.nat == 1 && pgrp->nat_loc == 1 && wmass == 0)
                {
                    int m;

                    /* Copy the single atom coordinate */
                    for (m = 0; m < DIM; m++)
                    {
                        com[m] = x[pgrp->ind_loc[0]][m];
                    }
                    /* Set all mass factors to 1 to get the correct COM */
                    wmass  = 1;
                    wwmass = 1;
                }

                if (pgrp->weight_loc == NULL)
                {
                    wwmass = wmass;
                }

                /* Copy local sums to a buffer for global summing */
                copy_dvec(com,  comm->dbuf[g*3]);
                copy_dvec(comp, comm->dbuf[g*3 + 1]);
                comm->dbuf[g*3 + 2][0] = wmass;
                comm->dbuf[g*3 + 2][1] = wwmass;
                comm->dbuf[g*3 + 2][2] = 0;
            }
            else
            {
                /* Cosine weighting geometry */
                double cm, sm, cmp, smp, ccm, csm, ssm, csw, snw;
                int    i;

                cm  = 0;
                sm  = 0;
                cmp = 0;
                smp = 0;
                ccm = 0;
                csm = 0;
                ssm = 0;

                for (i = 0; i < pgrp->nat_loc; i++)
                {
                    int  ii;
                    real mass;

                    ii   = pgrp->ind_loc[i];
                    mass = md->massT[ii];
                    /* Determine cos and sin sums */
                    csw  = cos(x[ii][pull->cosdim]*twopi_box);
                    snw  = sin(x[ii][pull->cosdim]*twopi_box);
                    cm  += csw*mass;
                    sm  += snw*mass;
                    ccm += csw*csw*mass;
                    csm += csw*snw*mass;
                    ssm += snw*snw*mass;

                    if (xp)
                    {
                        csw  = cos(xp[ii][pull->cosdim]*twopi_box);
                        snw  = sin(xp[ii][pull->cosdim]*twopi_box);
                        cmp += csw*mass;
                        smp += snw*mass;
                    }
                }

                /* Copy local sums to a buffer for global summing */
                comm->dbuf[g*3  ][0] = cm;
                comm->dbuf[g*3  ][1] = sm;
                comm->dbuf[g*3  ][2] = 0;
                comm->dbuf[g*3+1][0] = ccm;
                comm->dbuf[g*3+1][1] = csm;
                comm->dbuf[g*3+1][2] = ssm;
                comm->dbuf[g*3+2][0] = cmp;
                comm->dbuf[g*3+2][1] = smp;
                comm->dbuf[g*3+2][2] = 0;
            }
        }
    }

    pull_reduce_double(cr, comm, pull->ngroup*3*DIM, comm->dbuf[0]);

    for (g = 0; g < pull->ngroup; g++)
    {
        pull_group_work_t *pgrp;

        pgrp = &pull->group[g];
        if (pgrp->params.nat > 0 && pgrp->bCalcCOM)
        {
            if (pgrp->epgrppbc != epgrppbcCOS)
            {
                double wmass, wwmass;
                int    m;

                /* Determine the inverse mass */
                wmass             = comm->dbuf[g*3+2][0];
                wwmass            = comm->dbuf[g*3+2][1];
                pgrp->mwscale     = 1.0/wmass;
                /* invtm==0 signals a frozen group, so then we should keep it zero */
                if (pgrp->invtm != 0)
                {
                    pgrp->wscale  = wmass/wwmass;
                    pgrp->invtm   = wwmass/(wmass*wmass);
                }
                /* Divide by the total mass */
                for (m = 0; m < DIM; m++)
                {
                    pgrp->x[m]      = comm->dbuf[g*3  ][m]*pgrp->mwscale;
                    if (xp)
                    {
                        pgrp->xp[m] = comm->dbuf[g*3+1][m]*pgrp->mwscale;
                    }
                    if (pgrp->epgrppbc == epgrppbcREFAT)
                    {
                        pgrp->x[m]      += comm->rbuf[g][m];
                        if (xp)
                        {
                            pgrp->xp[m] += comm->rbuf[g][m];
                        }
                    }
                }
            }
            else
            {
                /* Cosine weighting geometry */
                double csw, snw, wmass, wwmass;
                int    i, ii;

                /* Determine the optimal location of the cosine weight */
                csw                   = comm->dbuf[g*3][0];
                snw                   = comm->dbuf[g*3][1];
                pgrp->x[pull->cosdim] = atan2_0_2pi(snw, csw)/twopi_box;
                /* Set the weights for the local atoms */
                wmass  = sqrt(csw*csw + snw*snw);
                wwmass = (comm->dbuf[g*3+1][0]*csw*csw +
                          comm->dbuf[g*3+1][1]*csw*snw +
                          comm->dbuf[g*3+1][2]*snw*snw)/(wmass*wmass);

                pgrp->mwscale = 1.0/wmass;
                pgrp->wscale  = wmass/wwmass;
                pgrp->invtm   = wwmass/(wmass*wmass);
                /* Set the weights for the local atoms */
                csw *= pgrp->invtm;
                snw *= pgrp->invtm;
                for (i = 0; i < pgrp->nat_loc; i++)
                {
                    ii                  = pgrp->ind_loc[i];
                    pgrp->weight_loc[i] = csw*cos(twopi_box*x[ii][pull->cosdim]) +
                        snw*sin(twopi_box*x[ii][pull->cosdim]);
                }
                if (xp)
                {
                    csw                    = comm->dbuf[g*3+2][0];
                    snw                    = comm->dbuf[g*3+2][1];
                    pgrp->xp[pull->cosdim] = atan2_0_2pi(snw, csw)/twopi_box;
                }
            }
            if (debug)
            {
                fprintf(debug, "Pull group %d wmass %f invtm %f\n",
                        g, 1.0/pgrp->mwscale, pgrp->invtm);
            }
        }
    }

    if (pull->bCylinder)
    {
        /* Calculate the COMs for the cyclinder reference groups */
        make_cyl_refgrps(cr, pull, md, pbc, t, x);
    }
}
Esempio n. 15
0
void calc_h_pos(int nht, rvec xa[], rvec xh[], int *l)
{
#define alfaH   (acos(-1/3.0)) /* 109.47 degrees */
#define alfaHpl (2*M_PI/3)     /* 120 degrees */
#define distH   0.1

#define alfaCOM (DEG2RAD*117)
#define alfaCO  (DEG2RAD*121)
#define alfaCOA (DEG2RAD*115)

#define distO   0.123
#define distOA  0.125
#define distOM  0.136

    rvec sa, sb, sij;
    real s6, rij, ra, rb, xd;
    int  d;

    s6 = 0.5*sqrt(3.e0);

    /* common work for constructing one, two or three dihedral hydrogens */
    switch (nht)
    {
        case 2:
        case 3:
        case 4:
        case 8:
        case 9:
            rij = 0.e0;
            for (d = 0; (d < DIM); d++)
            {
                xd     = xAJ[d];
                sij[d] = xAI[d]-xd;
                sb[d]  = xd-xAK[d];
                rij   += sqr(sij[d]);
            }
            rij    = sqrt(rij);
            sa[XX] = sij[YY]*sb[ZZ]-sij[ZZ]*sb[YY];
            sa[YY] = sij[ZZ]*sb[XX]-sij[XX]*sb[ZZ];
            sa[ZZ] = sij[XX]*sb[YY]-sij[YY]*sb[XX];
            ra     = 0.e0;
            for (d = 0; (d < DIM); d++)
            {
                sij[d] = sij[d]/rij;
                ra    += sqr(sa[d]);
            }
            ra = sqrt(ra);
            for (d = 0; (d < DIM); d++)
            {
                sa[d] = sa[d]/ra;
            }

            sb[XX] = sa[YY]*sij[ZZ]-sa[ZZ]*sij[YY];
            sb[YY] = sa[ZZ]*sij[XX]-sa[XX]*sij[ZZ];
            sb[ZZ] = sa[XX]*sij[YY]-sa[YY]*sij[XX];
            break;
    } /* end switch */

    switch (nht)
    {
        case 1: /* construct one planar hydrogen (peptide,rings) */
            rij = 0.e0;
            rb  = 0.e0;
            for (d = 0; (d < DIM); d++)
            {
                sij[d] = xAI[d]-xAJ[d];
                sb[d]  = xAI[d]-xAK[d];
                rij   += sqr(sij[d]);
                rb    += sqr(sb[d]);
            }
            rij = sqrt(rij);
            rb  = sqrt(rb);
            ra  = 0.e0;
            for (d = 0; (d < DIM); d++)
            {
                sa[d] = sij[d]/rij+sb[d]/rb;
                ra   += sqr(sa[d]);
            }
            ra = sqrt(ra);
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]+distH*sa[d]/ra;
            }
            break;
        case 2: /* one single hydrogen, e.g. hydroxyl */
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]+distH*sin(alfaH)*sb[d]-distH*cos(alfaH)*sij[d];
            }
            break;
        case 3: /* two planar hydrogens, e.g. -NH2 */
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]-distH*sin(alfaHpl)*sb[d]-distH*cos(alfaHpl)*sij[d];
                xH2[d] = xAI[d]+distH*sin(alfaHpl)*sb[d]-distH*cos(alfaHpl)*sij[d];
            }
            break;
        case 4: /* two or three tetrahedral hydrogens, e.g. -CH3 */
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]+distH*sin(alfaH)*sb[d]-distH*cos(alfaH)*sij[d];
                xH2[d] = ( xAI[d]
                           - distH*sin(alfaH)*0.5*sb[d]
                           + distH*sin(alfaH)*s6*sa[d]
                           - distH*cos(alfaH)*sij[d] );
                if (xH3[XX] != NOTSET && xH3[YY] != NOTSET && xH3[ZZ] != NOTSET)
                {
                    xH3[d] = ( xAI[d]
                               - distH*sin(alfaH)*0.5*sb[d]
                               - distH*sin(alfaH)*s6*sa[d]
                               - distH*cos(alfaH)*sij[d] );
                }
            }
            break;
        case 5: /* one tetrahedral hydrogen, e.g. C3CH */
        {
            real center;
            rvec dxc;

            for (d = 0; (d < DIM); d++)
            {
                center = (xAJ[d]+xAK[d]+xAL[d])/3.0;
                dxc[d] = xAI[d]-center;
            }
            center = norm(dxc);
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]+dxc[d]*distH/center;
            }
            break;
        }
        case 6: /* two tetrahedral hydrogens, e.g. C-CH2-C */
        {
            rvec rBB, rCC1, rCC2, rNN;
            real bb, nn;

            for (d = 0; (d < DIM); d++)
            {
                rBB[d] = xAI[d]-0.5*(xAJ[d]+xAK[d]);
            }
            bb = norm(rBB);

            rvec_sub(xAI, xAJ, rCC1);
            rvec_sub(xAI, xAK, rCC2);
            cprod(rCC1, rCC2, rNN);
            nn = norm(rNN);

            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]+distH*(cos(alfaH/2.0)*rBB[d]/bb+
                                       sin(alfaH/2.0)*rNN[d]/nn);
                xH2[d] = xAI[d]+distH*(cos(alfaH/2.0)*rBB[d]/bb-
                                       sin(alfaH/2.0)*rNN[d]/nn);
            }
            break;
        }
        case 7: /* two water hydrogens */
            gen_waterhydrogen(2, xa, xh, l);
            break;
        case 10: /* three water hydrogens */
            gen_waterhydrogen(3, xa, xh, l);
            break;
        case 11: /* four water hydrogens */
            gen_waterhydrogen(4, xa, xh, l);
            break;
        case 8: /* two carboxyl oxygens, -COO- */
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]-distOM*sin(alfaCOM)*sb[d]-distOM*cos(alfaCOM)*sij[d];
                xH2[d] = xAI[d]+distOM*sin(alfaCOM)*sb[d]-distOM*cos(alfaCOM)*sij[d];
            }
            break;
        case 9:          /* carboxyl oxygens and hydrogen, -COOH */
        {
            rvec xa2[4]; /* i,j,k,l   */

            /* first add two oxygens */
            for (d = 0; (d < DIM); d++)
            {
                xH1[d] = xAI[d]-distO *sin(alfaCO )*sb[d]-distO *cos(alfaCO )*sij[d];
                xH2[d] = xAI[d]+distOA*sin(alfaCOA)*sb[d]-distOA*cos(alfaCOA)*sij[d];
            }

            /* now use rule 2 to add hydrogen to 2nd oxygen */
            copy_rvec(xH2, xa2[0]); /* new i = n' */
            copy_rvec(xAI, xa2[1]); /* new j = i  */
            copy_rvec(xAJ, xa2[2]); /* new k = j  */
            copy_rvec(xAK, xa2[3]); /* new l = k, not used */
            calc_h_pos(2, xa2, (xh+2), l);

            break;
        }
        default:
            gmx_fatal(FARGS, "Invalid argument (%d) for nht in routine genh\n", nht);
    } /* end switch */
}
Esempio n. 16
0
static void dielectric(FILE *fmj, FILE *fmd, FILE *outf, FILE *fcur, FILE *mcor,
                       FILE *fmjdsp, gmx_bool bNoJump, gmx_bool bACF, gmx_bool bINT,
                       int ePBC, t_topology top, t_trxframe fr, real temp,
                       real bfit, real efit, real bvit, real evit,
                       t_trxstatus *status, int isize, int nmols, int nshift,
                       int *index0, int indexm[], real mass2[],
                       real qmol[], real eps_rf, const gmx_output_env_t *oenv)
{
    int       i, j;
    int       valloc, nalloc, nfr, nvfr;
    int       vshfr;
    real     *xshfr       = NULL;
    int      *vfr         = NULL;
    real      refr        = 0.0;
    real     *cacf        = NULL;
    real     *time        = NULL;
    real     *djc         = NULL;
    real      corint      = 0.0;
    real      prefactorav = 0.0;
    real      prefactor   = 0.0;
    real      volume;
    real      volume_av = 0.0;
    real      dk_s, dk_d, dk_f;
    real      mj    = 0.0;
    real      mj2   = 0.0;
    real      mjd   = 0.0;
    real      mjdav = 0.0;
    real      md2   = 0.0;
    real      mdav2 = 0.0;
    real      sgk;
    rvec      mja_tmp;
    rvec      mjd_tmp;
    rvec      mdvec;
    rvec     *mu    = NULL;
    rvec     *xp    = NULL;
    rvec     *v0    = NULL;
    rvec     *mjdsp = NULL;
    real     *dsp2  = NULL;
    real      t0;
    real      rtmp;

    rvec      tmp;
    rvec     *mtrans = NULL;

    /*
     * Variables for the least-squares fit for Einstein-Helfand and Green-Kubo
     */

    int          bi, ei, ie, ii;
    real         rest  = 0.0;
    real         sigma = 0.0;
    real         malt  = 0.0;
    real         err   = 0.0;
    real        *xfit;
    real        *yfit;
    gmx_rmpbc_t  gpbc = NULL;

    /*
     * indices for EH
     */

    ei = 0;
    bi = 0;

    /*
     * indices for GK
     */

    ii  = 0;
    ie  = 0;
    t0  = 0;
    sgk = 0.0;


    /* This is the main loop over frames */


    nfr = 0;


    nvfr   = 0;
    vshfr  = 0;
    nalloc = 0;
    valloc = 0;

    clear_rvec(mja_tmp);
    clear_rvec(mjd_tmp);
    clear_rvec(mdvec);
    clear_rvec(tmp);
    gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms);

    do
    {

        refr = (nfr+1);

        if (nfr >= nalloc)
        {
            nalloc += 100;
            srenew(time, nalloc);
            srenew(mu, nalloc);
            srenew(mjdsp, nalloc);
            srenew(dsp2, nalloc);
            srenew(mtrans, nalloc);
            srenew(xshfr, nalloc);

            for (i = nfr; i < nalloc; i++)
            {
                clear_rvec(mjdsp[i]);
                clear_rvec(mu[i]);
                clear_rvec(mtrans[i]);
                dsp2[i]  = 0.0;
                xshfr[i] = 0.0;
            }
        }
        GMX_RELEASE_ASSERT(time != NULL, "Memory not allocated correctly - time array is NULL");

        if (nfr == 0)
        {
            t0 = fr.time;

        }

        time[nfr] = fr.time-t0;

        if (time[nfr] <= bfit)
        {
            bi = nfr;
        }
        if (time[nfr] <= efit)
        {
            ei = nfr;
        }

        if (bNoJump)
        {

            if (xp)
            {
                remove_jump(fr.box, fr.natoms, xp, fr.x);
            }
            else
            {
                snew(xp, fr.natoms);
            }

            for (i = 0; i < fr.natoms; i++)
            {
                copy_rvec(fr.x[i], xp[i]);
            }

        }

        gmx_rmpbc_trxfr(gpbc, &fr);

        calc_mj(top, ePBC, fr.box, bNoJump, nmols, indexm, fr.x, mtrans[nfr], mass2, qmol);

        for (i = 0; i < isize; i++)
        {
            j = index0[i];
            svmul(top.atoms.atom[j].q, fr.x[j], fr.x[j]);
            rvec_inc(mu[nfr], fr.x[j]);
        }

        /*if(mod(nfr,nshift)==0){*/
        if (nfr%nshift == 0)
        {
            for (j = nfr; j >= 0; j--)
            {
                rvec_sub(mtrans[nfr], mtrans[j], tmp);
                dsp2[nfr-j]  += norm2(tmp);
                xshfr[nfr-j] += 1.0;
            }
        }

        if (fr.bV)
        {
            if (nvfr >= valloc)
            {
                valloc += 100;
                srenew(vfr, valloc);
                if (bINT)
                {
                    srenew(djc, valloc);
                }
                srenew(v0, valloc);
                if (bACF)
                {
                    srenew(cacf, valloc);
                }
            }
            if (time[nfr] <= bvit)
            {
                ii = nvfr;
            }
            if (time[nfr] <= evit)
            {
                ie = nvfr;
            }
            vfr[nvfr] = nfr;
            clear_rvec(v0[nvfr]);
            if (bACF)
            {
                cacf[nvfr] = 0.0;
            }
            if (bINT)
            {
                djc[nvfr] = 0.0;
            }
            for (i = 0; i < isize; i++)
            {
                j = index0[i];
                svmul(mass2[j], fr.v[j], fr.v[j]);
                svmul(qmol[j], fr.v[j], fr.v[j]);
                rvec_inc(v0[nvfr], fr.v[j]);
            }

            fprintf(fcur, "%.3f\t%.6f\t%.6f\t%.6f\n", time[nfr], v0[nfr][XX], v0[nfr][YY], v0[nfr][ZZ]);
            if (bACF || bINT)
            {
                /*if(mod(nvfr,nshift)==0){*/
                if (nvfr%nshift == 0)
                {
                    for (j = nvfr; j >= 0; j--)
                    {
                        if (bACF)
                        {
                            cacf[nvfr-j] += iprod(v0[nvfr], v0[j]);
                        }
                        if (bINT)
                        {
                            djc[nvfr-j] += iprod(mu[vfr[j]], v0[nvfr]);
                        }
                    }
                    vshfr++;
                }
            }
            nvfr++;
        }

        volume     = det(fr.box);
        volume_av += volume;

        rvec_inc(mja_tmp, mtrans[nfr]);
        mjd += iprod(mu[nfr], mtrans[nfr]);
        rvec_inc(mdvec, mu[nfr]);

        mj2 += iprod(mtrans[nfr], mtrans[nfr]);
        md2 += iprod(mu[nfr], mu[nfr]);

        fprintf(fmj, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n", time[nfr], mtrans[nfr][XX], mtrans[nfr][YY], mtrans[nfr][ZZ], mj2/refr, norm(mja_tmp)/refr);
        fprintf(fmd, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n",    \
                time[nfr], mu[nfr][XX], mu[nfr][YY], mu[nfr][ZZ], md2/refr, norm(mdvec)/refr);

        nfr++;

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

    gmx_rmpbc_done(gpbc);

    volume_av /= refr;

    prefactor  = 1.0;
    prefactor /= 3.0*EPSILON0*volume_av*BOLTZ*temp;


    prefactorav  = E_CHARGE*E_CHARGE;
    prefactorav /= volume_av*BOLTZMANN*temp*NANO*6.0;

    fprintf(stderr, "Prefactor fit E-H: 1 / 6.0*V*k_B*T: %g\n", prefactorav);

    calc_mjdsp(fmjdsp, prefactorav, dsp2, time, nfr, xshfr);

    /*
     * Now we can average and calculate the correlation functions
     */


    mj2 /= refr;
    mjd /= refr;
    md2 /= refr;

    svmul(1.0/refr, mdvec, mdvec);
    svmul(1.0/refr, mja_tmp, mja_tmp);

    mdav2 = norm2(mdvec);
    mj    = norm2(mja_tmp);
    mjdav = iprod(mdvec, mja_tmp);


    printf("\n\nAverage translational dipole moment M_J [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mja_tmp[XX], mja_tmp[YY], mja_tmp[ZZ], mj2);
    printf("\n\nAverage molecular dipole moment M_D [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mdvec[XX], mdvec[YY], mdvec[ZZ], md2);

    if (v0 != NULL)
    {
        if (bINT)
        {

            printf("\nCalculating M_D - current correlation integral ... \n");
            corint = calc_cacf(mcor, prefactorav/EPSI0, djc, time, nvfr, vfr, ie, nshift);

        }

        if (bACF)
        {

            printf("\nCalculating current autocorrelation ... \n");
            sgk = calc_cacf(outf, prefactorav/PICO, cacf, time, nvfr, vfr, ie, nshift);

            if (ie > ii)
            {

                snew(xfit, ie-ii+1);
                snew(yfit, ie-ii+1);

                for (i = ii; i <= ie; i++)
                {

                    xfit[i-ii] = std::log(time[vfr[i]]);
                    rtmp       = std::abs(cacf[i]);
                    yfit[i-ii] = std::log(rtmp);

                }

                lsq_y_ax_b(ie-ii, xfit, yfit, &sigma, &malt, &err, &rest);

                malt = std::exp(malt);

                sigma += 1.0;

                malt *= prefactorav*2.0e12/sigma;

                sfree(xfit);
                sfree(yfit);

            }
        }
    }


    /* Calculation of the dielectric constant */

    fprintf(stderr, "\n********************************************\n");
    dk_s = calceps(prefactor, md2, mj2, mjd, eps_rf, FALSE);
    fprintf(stderr, "\nAbsolute values:\n epsilon=%f\n", dk_s);
    fprintf(stderr, " <M_D^2> , <M_J^2>, <(M_J*M_D)^2>:  (%f, %f, %f)\n\n", md2, mj2, mjd);
    fprintf(stderr, "********************************************\n");


    dk_f = calceps(prefactor, md2-mdav2, mj2-mj, mjd-mjdav, eps_rf, FALSE);
    fprintf(stderr, "\n\nFluctuations:\n epsilon=%f\n\n", dk_f);
    fprintf(stderr, "\n deltaM_D , deltaM_J, deltaM_JD:  (%f, %f, %f)\n", md2-mdav2, mj2-mj, mjd-mjdav);
    fprintf(stderr, "\n********************************************\n");
    if (bINT)
    {
        dk_d = calceps(prefactor, md2-mdav2, mj2-mj, corint, eps_rf, TRUE);
        fprintf(stderr, "\nStatic dielectric constant using integral and fluctuations: %f\n", dk_d);
        fprintf(stderr, "\n < M_JM_D > via integral:  %.3f\n", -1.0*corint);
    }

    fprintf(stderr, "\n***************************************************");
    fprintf(stderr, "\n\nAverage volume V=%f nm^3 at T=%f K\n", volume_av, temp);
    fprintf(stderr, "and corresponding refactor 1.0 / 3.0*V*k_B*T*EPSILON_0: %f \n", prefactor);



    if (bACF && (ii < nvfr))
    {
        fprintf(stderr, "Integral and integrated fit to the current acf yields at t=%f:\n", time[vfr[ii]]);
        fprintf(stderr, "sigma=%8.3f (pure integral: %.3f)\n", sgk-malt*std::pow(time[vfr[ii]], sigma), sgk);
    }

    if (ei > bi)
    {
        fprintf(stderr, "\nStart fit at %f ps (%f).\n", time[bi], bfit);
        fprintf(stderr, "End fit at %f ps (%f).\n\n", time[ei], efit);

        snew(xfit, ei-bi+1);
        snew(yfit, ei-bi+1);

        for (i = bi; i <= ei; i++)
        {
            xfit[i-bi] = time[i];
            yfit[i-bi] = dsp2[i];
        }

        lsq_y_ax_b(ei-bi, xfit, yfit, &sigma, &malt, &err, &rest);

        sigma *= 1e12;
        dk_d   = calceps(prefactor, md2, 0.5*malt/prefactorav, corint, eps_rf, TRUE);

        fprintf(stderr, "Einstein-Helfand fit to the MSD of the translational dipole moment yields:\n\n");
        fprintf(stderr, "sigma=%.4f\n", sigma);
        fprintf(stderr, "translational fraction of M^2: %.4f\n", 0.5*malt/prefactorav);
        fprintf(stderr, "Dielectric constant using EH: %.4f\n", dk_d);

        sfree(xfit);
        sfree(yfit);
    }
    else
    {
        fprintf(stderr, "Too few points for a fit.\n");
    }


    if (v0 != NULL)
    {
        sfree(v0);
    }
    if (bACF)
    {
        sfree(cacf);
    }
    if (bINT)
    {
        sfree(djc);
    }

    sfree(time);


    sfree(mjdsp);
    sfree(mu);
}
Esempio n. 17
0
void fill_grid(gmx_domdec_zones_t *dd_zones,
               t_grid *grid, int ncg_tot,
               int cg0, int cg1, rvec cg_cm[])
{
    int       *cell_index;
    int        nry, nrz;
    rvec       n_box, offset;
    int        zone, ccg0, ccg1, cg, d, not_used;
    ivec       shift0, useall, b0, b1, ind;
    gmx_bool   bUse;

    if (cg0 == -1)
    {
        /* We have already filled the grid up to grid->ncg,
         * continue from there.
         */
        cg0 = grid->nr;
    }

    set_grid_ncg(grid, ncg_tot);

    cell_index = grid->cell_index;

    /* Initiate cell borders */
    nry = grid->n[YY];
    nrz = grid->n[ZZ];
    for (d = 0; d < DIM; d++)
    {
        if (grid->cell_size[d] > 0)
        {
            n_box[d] = 1/grid->cell_size[d];
        }
        else
        {
            n_box[d] = 0;
        }
    }
    copy_rvec(grid->cell_offset, offset);

    if (debug)
    {
        fprintf(debug, "Filling grid from %d to %d\n", cg0, cg1);
    }

    if (dd_zones == nullptr)
    {
        for (cg = cg0; cg < cg1; cg++)
        {
            for (d = 0; d < DIM; d++)
            {
                ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d])*n_box[d]);
                /* With pbc we should be done here.
                 * Without pbc cg's outside the grid
                 * should be assigned to the closest grid cell.
                 */
                if (ind[d] < 0)
                {
                    ind[d] = 0;
                }
                else if (ind[d] >= grid->n[d])
                {
                    ind[d] = grid->n[d] - 1;
                }
            }
            cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
        }
    }
    else
    {
        for (zone = 0; zone < dd_zones->n; zone++)
        {
            ccg0 = dd_zones->cg_range[zone];
            ccg1 = dd_zones->cg_range[zone+1];
            if (ccg1 <= cg0 || ccg0 >= cg1)
            {
                continue;
            }

            /* Determine the ns grid cell limits for this DD zone */
            for (d = 0; d < DIM; d++)
            {
                shift0[d] = dd_zones->shift[zone][d];
                useall[d] = static_cast<int>(shift0[d] == 0 || d >= grid->npbcdim);
                /* Check if we need to do normal or optimized grid assignments.
                 * Normal is required for dims without DD or triclinic dims.
                 * DD edge cell on dims without pbc will be automatically
                 * be correct, since the shift=0 zones with have b0 and b1
                 * set to the grid boundaries and there are no shift=1 zones.
                 */
                if (grid->ncpddc[d] == 0)
                {
                    b0[d] = 0;
                    b1[d] = grid->n[d];
                }
                else
                {
                    if (shift0[d] == 0)
                    {
                        b0[d] = 0;
                        b1[d] = grid->ncpddc[d];
                    }
                    else
                    {
                        /* shift = 1 */
                        b0[d] = grid->ncpddc[d];
                        b1[d] = grid->n[d];
                    }
                }
            }

            not_used = ci_not_used(grid->n);

            /* Put all the charge groups of this DD zone on the grid */
            for (cg = ccg0; cg < ccg1; cg++)
            {
                if (cell_index[cg] == -1)
                {
                    /* This cg has moved to another node */
                    cell_index[cg] = NSGRID_SIGNAL_MOVED_FAC*grid->ncells;
                    continue;
                }

                bUse = TRUE;
                for (d = 0; d < DIM; d++)
                {
                    ind[d] = static_cast<int>((cg_cm[cg][d] - offset[d])*n_box[d]);
                    /* Here we have to correct for rounding problems,
                     * as this cg_cm to cell index operation is not necessarily
                     * binary identical to the operation for the DD zone assignment
                     * and therefore a cg could end up in an unused grid cell.
                     * For dimensions without pbc we need to check
                     * for cells on the edge if charge groups are beyond
                     * the grid and if so, store them in the closest cell.
                     */
                    if (ind[d] < b0[d])
                    {
                        ind[d] = b0[d];
                    }
                    else if (ind[d] >= b1[d])
                    {
                        if (useall[d])
                        {
                            ind[d] = b1[d] - 1;
                        }
                        else
                        {
                            /* Charge groups in this DD zone further away than the cut-off
                             * in direction do not participate in non-bonded interactions.
                             */
                            bUse = FALSE;
                        }
                    }
                }
                if (cg > grid->nr_alloc)
                {
                    fprintf(stderr, "WARNING: nra_alloc %d cg0 %d cg1 %d cg %d\n",
                            grid->nr_alloc, cg0, cg1, cg);
                }
                if (bUse)
                {
                    cell_index[cg] = xyz2ci(nry, nrz, ind[XX], ind[YY], ind[ZZ]);
                }
                else
                {
                    cell_index[cg] = not_used;
                }
            }
        }
    }

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

    snew(xt, atoms->nr);

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

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

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

        /* Copy the new positions back */
        for (i = index[0]; i < atoms->nr; i++)
        {
            copy_rvec(xt[i], x[i]);
        }
        sfree(xt);
    }
}
static void get_refx(output_env_t oenv, const char *trxfn, int nfitdim, int skip,
                     int gnx, int *index,
                     gmx_bool bMW, t_topology *top, int ePBC, rvec *x_ref)
{
    int          natoms, nfr_all, nfr, i, j, a, r, c, min_fr;
    t_trxstatus *status;
    real        *ti, min_t;
    double       tot_mass, msd, *srmsd, min_srmsd, srmsd_tot;
    rvec        *x, **xi;
    real         xf;
    matrix       box, R;
    real        *w_rls;
    gmx_rmpbc_t  gpbc = NULL;


    nfr_all = 0;
    nfr     = 0;
    snew(ti, 100);
    snew(xi, 100);
    natoms = read_first_x(oenv, &status, trxfn, &ti[nfr], &x, box);

    snew(w_rls, gnx);
    tot_mass = 0;
    for (a = 0; a < gnx; a++)
    {
        if (index[a] >= natoms)
        {
            gmx_fatal(FARGS, "Atom index (%d) is larger than the number of atoms in the trajecory (%d)", index[a]+1, natoms);
        }
        w_rls[a]  = (bMW ? top->atoms.atom[index[a]].m : 1.0);
        tot_mass += w_rls[a];
    }
    gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);

    do
    {
        if (nfr_all % skip == 0)
        {
            gmx_rmpbc(gpbc, natoms, box, x);
            snew(xi[nfr], gnx);
            for (i = 0; i < gnx; i++)
            {
                copy_rvec(x[index[i]], xi[nfr][i]);
            }
            reset_x(gnx, NULL, gnx, NULL, xi[nfr], w_rls);
            nfr++;
            if (nfr % 100 == 0)
            {
                srenew(ti, nfr+100);
                srenew(xi, nfr+100);
            }
        }
        nfr_all++;
    }
    while (read_next_x(oenv, status, &ti[nfr], x, box));
    close_trj(status);
    sfree(x);

    gmx_rmpbc_done(gpbc);

    snew(srmsd, nfr);
    for (i = 0; i < nfr; i++)
    {
        printf("\rProcessing frame %d of %d", i, nfr);
        for (j = i+1; j < nfr; j++)
        {
            calc_fit_R(nfitdim, gnx, w_rls, xi[i], xi[j], R);

            msd = 0;
            for (a = 0; a < gnx; a++)
            {
                for (r = 0; r < DIM; r++)
                {
                    xf = 0;
                    for (c = 0; c < DIM; c++)
                    {
                        xf += R[r][c]*xi[j][a][c];
                    }
                    msd += w_rls[a]*sqr(xi[i][a][r] - xf);
                }
            }
            msd      /= tot_mass;
            srmsd[i] += sqrt(msd);
            srmsd[j] += sqrt(msd);
        }
        sfree(xi[i]);
    }
    printf("\n");
    sfree(w_rls);

    min_srmsd = GMX_REAL_MAX;
    min_fr    = -1;
    min_t     = -1;
    srmsd_tot = 0;
    for (i = 0; i < nfr; i++)
    {
        srmsd[i] /= (nfr - 1);
        if (srmsd[i] < min_srmsd)
        {
            min_srmsd = srmsd[i];
            min_fr    = i;
            min_t     = ti[i];
        }
        srmsd_tot += srmsd[i];
    }
    sfree(srmsd);

    printf("Average RMSD between all structures: %.3f\n", srmsd_tot/nfr);
    printf("Structure with lowest RMSD to all others: time %g, av. RMSD %.3f\n",
           min_t, min_srmsd);

    for (a = 0; a < gnx; a++)
    {
        copy_rvec(xi[min_fr][a], x_ref[index[a]]);
    }

    sfree(xi);
}
Esempio n. 20
0
int gmx_covar(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] calculates and diagonalizes the (mass-weighted)",
        "covariance matrix.",
        "All structures are fitted to the structure in the structure file.",
        "When this is not a run input file periodicity will not be taken into",
        "account. When the fit and analysis groups are identical and the analysis",
        "is non mass-weighted, the fit will also be non mass-weighted.",
        "[PAR]",
        "The eigenvectors are written to a trajectory file ([TT]-v[tt]).",
        "When the same atoms are used for the fit and the covariance analysis,",
        "the reference structure for the fit is written first with t=-1.",
        "The average (or reference when [TT]-ref[tt] is used) structure is",
        "written with t=0, the eigenvectors",
        "are written as frames with the eigenvector number as timestamp.",
        "[PAR]",
        "The eigenvectors can be analyzed with [gmx-anaeig].",
        "[PAR]",
        "Option [TT]-ascii[tt] writes the whole covariance matrix to",
        "an ASCII file. The order of the elements is: x1x1, x1y1, x1z1, x1x2, ...",
        "[PAR]",
        "Option [TT]-xpm[tt] writes the whole covariance matrix to an [REF].xpm[ref] file.",
        "[PAR]",
        "Option [TT]-xpma[tt] writes the atomic covariance matrix to an [REF].xpm[ref] file,",
        "i.e. for each atom pair the sum of the xx, yy and zz covariances is",
        "written.",
        "[PAR]",
        "Note that the diagonalization of a matrix requires memory and time",
        "that will increase at least as fast as than the square of the number",
        "of atoms involved. It is easy to run out of memory, in which",
        "case this tool will probably exit with a 'Segmentation fault'. You",
        "should consider carefully whether a reduced set of atoms will meet",
        "your needs for lower costs."
    };
    static gmx_bool bFit = TRUE, bRef = FALSE, bM = FALSE, bPBC = TRUE;
    static int      end  = -1;
    t_pargs         pa[] = {
        {   "-fit",  FALSE, etBOOL, {&bFit},
            "Fit to a reference structure"
        },
        {   "-ref",  FALSE, etBOOL, {&bRef},
            "Use the deviation from the conformation in the structure file instead of from the average"
        },
        {   "-mwa",  FALSE, etBOOL, {&bM},
            "Mass-weighted covariance analysis"
        },
        {   "-last",  FALSE, etINT, {&end},
            "Last eigenvector to write away (-1 is till the last)"
        },
        {   "-pbc",  FALSE,  etBOOL, {&bPBC},
            "Apply corrections for periodic boundary conditions"
        }
    };
    FILE           *out = NULL; /* initialization makes all compilers happy */
    t_trxstatus    *status;
    t_topology      top;
    int             ePBC;
    t_atoms        *atoms;
    rvec           *x, *xread, *xref, *xav, *xproj;
    matrix          box, zerobox;
    real           *sqrtm, *mat, *eigenvalues, sum, trace, inv_nframes;
    real            t, tstart, tend, **mat2;
    real            xj, *w_rls = NULL;
    real            min, max, *axis;
    int             natoms, nat, nframes0, nframes, nlevels;
    gmx_int64_t     ndim, i, j, k, l;
    int             WriteXref;
    const char     *fitfile, *trxfile, *ndxfile;
    const char     *eigvalfile, *eigvecfile, *averfile, *logfile;
    const char     *asciifile, *xpmfile, *xpmafile;
    char            str[STRLEN], *fitname, *ananame;
    int             d, dj, nfit;
    atom_id        *index, *ifit;
    gmx_bool        bDiffMass1, bDiffMass2;
    char            timebuf[STRLEN];
    t_rgb           rlo, rmi, rhi;
    real           *eigenvectors;
    output_env_t    oenv;
    gmx_rmpbc_t     gpbc = NULL;

    t_filenm        fnm[] = {
        { efTRX, "-f",  NULL, ffREAD },
        { efTPS, NULL,  NULL, ffREAD },
        { efNDX, NULL,  NULL, ffOPTRD },
        { efXVG, NULL,  "eigenval", ffWRITE },
        { efTRN, "-v",  "eigenvec", ffWRITE },
        { efSTO, "-av", "average.pdb", ffWRITE },
        { efLOG, NULL,  "covar", ffWRITE },
        { efDAT, "-ascii", "covar", ffOPTWR },
        { efXPM, "-xpm", "covar", ffOPTWR },
        { efXPM, "-xpma", "covara", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    clear_mat(zerobox);

    fitfile    = ftp2fn(efTPS, NFILE, fnm);
    trxfile    = ftp2fn(efTRX, NFILE, fnm);
    ndxfile    = ftp2fn_null(efNDX, NFILE, fnm);
    eigvalfile = ftp2fn(efXVG, NFILE, fnm);
    eigvecfile = ftp2fn(efTRN, NFILE, fnm);
    averfile   = ftp2fn(efSTO, NFILE, fnm);
    logfile    = ftp2fn(efLOG, NFILE, fnm);
    asciifile  = opt2fn_null("-ascii", NFILE, fnm);
    xpmfile    = opt2fn_null("-xpm", NFILE, fnm);
    xpmafile   = opt2fn_null("-xpma", NFILE, fnm);

    read_tps_conf(fitfile, str, &top, &ePBC, &xref, NULL, box, TRUE);
    atoms = &top.atoms;

    if (bFit)
    {
        printf("\nChoose a group for the least squares fit\n");
        get_index(atoms, ndxfile, 1, &nfit, &ifit, &fitname);
        if (nfit < 3)
        {
            gmx_fatal(FARGS, "Need >= 3 points to fit!\n");
        }
    }
    else
    {
        nfit = 0;
    }
    printf("\nChoose a group for the covariance analysis\n");
    get_index(atoms, ndxfile, 1, &natoms, &index, &ananame);

    bDiffMass1 = FALSE;
    if (bFit)
    {
        snew(w_rls, atoms->nr);
        for (i = 0; (i < nfit); i++)
        {
            w_rls[ifit[i]] = atoms->atom[ifit[i]].m;
            if (i)
            {
                bDiffMass1 = bDiffMass1 || (w_rls[ifit[i]] != w_rls[ifit[i-1]]);
            }
        }
    }
    bDiffMass2 = FALSE;
    snew(sqrtm, natoms);
    for (i = 0; (i < natoms); i++)
    {
        if (bM)
        {
            sqrtm[i] = std::sqrt(atoms->atom[index[i]].m);
            if (i)
            {
                bDiffMass2 = bDiffMass2 || (sqrtm[i] != sqrtm[i-1]);
            }
        }
        else
        {
            sqrtm[i] = 1.0;
        }
    }

    if (bFit && bDiffMass1 && !bDiffMass2)
    {
        bDiffMass1 = natoms != nfit;
        for (i = 0; (i < natoms) && !bDiffMass1; i++)
        {
            bDiffMass1 = index[i] != ifit[i];
        }
        if (!bDiffMass1)
        {
            fprintf(stderr, "\n"
                    "Note: the fit and analysis group are identical,\n"
                    "      while the fit is mass weighted and the analysis is not.\n"
                    "      Making the fit non mass weighted.\n\n");
            for (i = 0; (i < nfit); i++)
            {
                w_rls[ifit[i]] = 1.0;
            }
        }
    }

    /* Prepare reference frame */
    if (bPBC)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, atoms->nr);
        gmx_rmpbc(gpbc, atoms->nr, box, xref);
    }
    if (bFit)
    {
        reset_x(nfit, ifit, atoms->nr, NULL, xref, w_rls);
    }

    snew(x, natoms);
    snew(xav, natoms);
    ndim = natoms*DIM;
    if (std::sqrt(static_cast<real>(GMX_INT64_MAX)) < static_cast<real>(ndim))
    {
        gmx_fatal(FARGS, "Number of degrees of freedoms to large for matrix.\n");
    }
    snew(mat, ndim*ndim);

    fprintf(stderr, "Calculating the average structure ...\n");
    nframes0 = 0;
    nat      = read_first_x(oenv, &status, trxfile, &t, &xread, box);
    if (nat != atoms->nr)
    {
        fprintf(stderr, "\nWARNING: number of atoms in tpx (%d) and trajectory (%d) do not match\n", natoms, nat);
    }
    do
    {
        nframes0++;
        /* calculate x: a fitted struture of the selected atoms */
        if (bPBC)
        {
            gmx_rmpbc(gpbc, nat, box, xread);
        }
        if (bFit)
        {
            reset_x(nfit, ifit, nat, NULL, xread, w_rls);
            do_fit(nat, w_rls, xref, xread);
        }
        for (i = 0; i < natoms; i++)
        {
            rvec_inc(xav[i], xread[index[i]]);
        }
    }
    while (read_next_x(oenv, status, &t, xread, box));
    close_trj(status);

    inv_nframes = 1.0/nframes0;
    for (i = 0; i < natoms; i++)
    {
        for (d = 0; d < DIM; d++)
        {
            xav[i][d]         *= inv_nframes;
            xread[index[i]][d] = xav[i][d];
        }
    }
    write_sto_conf_indexed(opt2fn("-av", NFILE, fnm), "Average structure",
                           atoms, xread, NULL, epbcNONE, zerobox, natoms, index);
    sfree(xread);

    fprintf(stderr, "Constructing covariance matrix (%dx%d) ...\n", static_cast<int>(ndim), static_cast<int>(ndim));
    nframes = 0;
    nat     = read_first_x(oenv, &status, trxfile, &t, &xread, box);
    tstart  = t;
    do
    {
        nframes++;
        tend = t;
        /* calculate x: a (fitted) structure of the selected atoms */
        if (bPBC)
        {
            gmx_rmpbc(gpbc, nat, box, xread);
        }
        if (bFit)
        {
            reset_x(nfit, ifit, nat, NULL, xread, w_rls);
            do_fit(nat, w_rls, xref, xread);
        }
        if (bRef)
        {
            for (i = 0; i < natoms; i++)
            {
                rvec_sub(xread[index[i]], xref[index[i]], x[i]);
            }
        }
        else
        {
            for (i = 0; i < natoms; i++)
            {
                rvec_sub(xread[index[i]], xav[i], x[i]);
            }
        }

        for (j = 0; j < natoms; j++)
        {
            for (dj = 0; dj < DIM; dj++)
            {
                k  = ndim*(DIM*j+dj);
                xj = x[j][dj];
                for (i = j; i < natoms; i++)
                {
                    l = k+DIM*i;
                    for (d = 0; d < DIM; d++)
                    {
                        mat[l+d] += x[i][d]*xj;
                    }
                }
            }
        }
    }
    while (read_next_x(oenv, status, &t, xread, box) &&
            (bRef || nframes < nframes0));
    close_trj(status);
    gmx_rmpbc_done(gpbc);

    fprintf(stderr, "Read %d frames\n", nframes);

    if (bRef)
    {
        /* copy the reference structure to the ouput array x */
        snew(xproj, natoms);
        for (i = 0; i < natoms; i++)
        {
            copy_rvec(xref[index[i]], xproj[i]);
        }
    }
    else
    {
        xproj = xav;
    }

    /* correct the covariance matrix for the mass */
    inv_nframes = 1.0/nframes;
    for (j = 0; j < natoms; j++)
    {
        for (dj = 0; dj < DIM; dj++)
        {
            for (i = j; i < natoms; i++)
            {
                k = ndim*(DIM*j+dj)+DIM*i;
                for (d = 0; d < DIM; d++)
                {
                    mat[k+d] = mat[k+d]*inv_nframes*sqrtm[i]*sqrtm[j];
                }
            }
        }
    }

    /* symmetrize the matrix */
    for (j = 0; j < ndim; j++)
    {
        for (i = j; i < ndim; i++)
        {
            mat[ndim*i+j] = mat[ndim*j+i];
        }
    }

    trace = 0;
    for (i = 0; i < ndim; i++)
    {
        trace += mat[i*ndim+i];
    }
    fprintf(stderr, "\nTrace of the covariance matrix: %g (%snm^2)\n",
            trace, bM ? "u " : "");

    if (asciifile)
    {
        out = gmx_ffopen(asciifile, "w");
        for (j = 0; j < ndim; j++)
        {
            for (i = 0; i < ndim; i += 3)
            {
                fprintf(out, "%g %g %g\n",
                        mat[ndim*j+i], mat[ndim*j+i+1], mat[ndim*j+i+2]);
            }
        }
        gmx_ffclose(out);
    }

    if (xpmfile)
    {
        min = 0;
        max = 0;
        snew(mat2, ndim);
        for (j = 0; j < ndim; j++)
        {
            mat2[j] = &(mat[ndim*j]);
            for (i = 0; i <= j; i++)
            {
                if (mat2[j][i] < min)
                {
                    min = mat2[j][i];
                }
                if (mat2[j][j] > max)
                {
                    max = mat2[j][i];
                }
            }
        }
        snew(axis, ndim);
        for (i = 0; i < ndim; i++)
        {
            axis[i] = i+1;
        }
        rlo.r   = 0;
        rlo.g = 0;
        rlo.b = 1;
        rmi.r   = 1;
        rmi.g = 1;
        rmi.b = 1;
        rhi.r   = 1;
        rhi.g = 0;
        rhi.b = 0;
        out     = gmx_ffopen(xpmfile, "w");
        nlevels = 80;
        write_xpm3(out, 0, "Covariance", bM ? "u nm^2" : "nm^2",
                   "dim", "dim", ndim, ndim, axis, axis,
                   mat2, min, 0.0, max, rlo, rmi, rhi, &nlevels);
        gmx_ffclose(out);
        sfree(axis);
        sfree(mat2);
    }

    if (xpmafile)
    {
        min = 0;
        max = 0;
        snew(mat2, ndim/DIM);
        for (i = 0; i < ndim/DIM; i++)
        {
            snew(mat2[i], ndim/DIM);
        }
        for (j = 0; j < ndim/DIM; j++)
        {
            for (i = 0; i <= j; i++)
            {
                mat2[j][i] = 0;
                for (d = 0; d < DIM; d++)
                {
                    mat2[j][i] += mat[ndim*(DIM*j+d)+DIM*i+d];
                }
                if (mat2[j][i] < min)
                {
                    min = mat2[j][i];
                }
                if (mat2[j][j] > max)
                {
                    max = mat2[j][i];
                }
                mat2[i][j] = mat2[j][i];
            }
        }
        snew(axis, ndim/DIM);
        for (i = 0; i < ndim/DIM; i++)
        {
            axis[i] = i+1;
        }
        rlo.r   = 0;
        rlo.g = 0;
        rlo.b = 1;
        rmi.r   = 1;
        rmi.g = 1;
        rmi.b = 1;
        rhi.r   = 1;
        rhi.g = 0;
        rhi.b = 0;
        out     = gmx_ffopen(xpmafile, "w");
        nlevels = 80;
        write_xpm3(out, 0, "Covariance", bM ? "u nm^2" : "nm^2",
                   "atom", "atom", ndim/DIM, ndim/DIM, axis, axis,
                   mat2, min, 0.0, max, rlo, rmi, rhi, &nlevels);
        gmx_ffclose(out);
        sfree(axis);
        for (i = 0; i < ndim/DIM; i++)
        {
            sfree(mat2[i]);
        }
        sfree(mat2);
    }


    /* call diagonalization routine */

    snew(eigenvalues, ndim);
    snew(eigenvectors, ndim*ndim);

    std::memcpy(eigenvectors, mat, ndim*ndim*sizeof(real));
    fprintf(stderr, "\nDiagonalizing ...\n");
    fflush(stderr);
    eigensolver(eigenvectors, ndim, 0, ndim, eigenvalues, mat);
    sfree(eigenvectors);

    /* now write the output */

    sum = 0;
    for (i = 0; i < ndim; i++)
    {
        sum += eigenvalues[i];
    }
    fprintf(stderr, "\nSum of the eigenvalues: %g (%snm^2)\n",
            sum, bM ? "u " : "");
    if (std::abs(trace-sum) > 0.01*trace)
    {
        fprintf(stderr, "\nWARNING: eigenvalue sum deviates from the trace of the covariance matrix\n");
    }

    /* Set 'end', the maximum eigenvector and -value index used for output */
    if (end == -1)
    {
        if (nframes-1 < ndim)
        {
            end = nframes-1;
            fprintf(stderr, "\nWARNING: there are fewer frames in your trajectory than there are\n");
            fprintf(stderr, "degrees of freedom in your system. Only generating the first\n");
            fprintf(stderr, "%d out of %d eigenvectors and eigenvalues.\n", end, static_cast<int>(ndim));
        }
        else
        {
            end = ndim;
        }
    }

    fprintf(stderr, "\nWriting eigenvalues to %s\n", eigvalfile);

    sprintf(str, "(%snm\\S2\\N)", bM ? "u " : "");
    out = xvgropen(eigvalfile,
                   "Eigenvalues of the covariance matrix",
                   "Eigenvector index", str, oenv);
    for (i = 0; (i < end); i++)
    {
        fprintf (out, "%10d %g\n", static_cast<int>(i+1), eigenvalues[ndim-1-i]);
    }
    xvgrclose(out);

    if (bFit)
    {
        /* misuse lambda: 0/1 mass weighted analysis no/yes */
        if (nfit == natoms)
        {
            WriteXref = eWXR_YES;
            for (i = 0; i < nfit; i++)
            {
                copy_rvec(xref[ifit[i]], x[i]);
            }
        }
        else
        {
            WriteXref = eWXR_NO;
        }
    }
    else
    {
        /* misuse lambda: -1 for no fit */
        WriteXref = eWXR_NOFIT;
    }

    write_eigenvectors(eigvecfile, natoms, mat, TRUE, 1, end,
                       WriteXref, x, bDiffMass1, xproj, bM, eigenvalues);

    out = gmx_ffopen(logfile, "w");

    gmx_format_current_time(timebuf, STRLEN);
    fprintf(out, "Covariance analysis log, written %s\n", timebuf);

    fprintf(out, "Program: %s\n", argv[0]);
    gmx_getcwd(str, STRLEN);

    fprintf(out, "Working directory: %s\n\n", str);

    fprintf(out, "Read %d frames from %s (time %g to %g %s)\n", nframes, trxfile,
            output_env_conv_time(oenv, tstart), output_env_conv_time(oenv, tend), output_env_get_time_unit(oenv));
    if (bFit)
    {
        fprintf(out, "Read reference structure for fit from %s\n", fitfile);
    }
    if (ndxfile)
    {
        fprintf(out, "Read index groups from %s\n", ndxfile);
    }
    fprintf(out, "\n");

    fprintf(out, "Analysis group is '%s' (%d atoms)\n", ananame, natoms);
    if (bFit)
    {
        fprintf(out, "Fit group is '%s' (%d atoms)\n", fitname, nfit);
    }
    else
    {
        fprintf(out, "No fit was used\n");
    }
    fprintf(out, "Analysis is %smass weighted\n", bDiffMass2 ? "" : "non-");
    if (bFit)
    {
        fprintf(out, "Fit is %smass weighted\n", bDiffMass1 ? "" : "non-");
    }
    fprintf(out, "Diagonalized the %dx%d covariance matrix\n", static_cast<int>(ndim), static_cast<int>(ndim));
    fprintf(out, "Trace of the covariance matrix before diagonalizing: %g\n",
            trace);
    fprintf(out, "Trace of the covariance matrix after diagonalizing: %g\n\n",
            sum);

    fprintf(out, "Wrote %d eigenvalues to %s\n", static_cast<int>(end), eigvalfile);
    if (WriteXref == eWXR_YES)
    {
        fprintf(out, "Wrote reference structure to %s\n", eigvecfile);
    }
    fprintf(out, "Wrote average structure to %s and %s\n", averfile, eigvecfile);
    fprintf(out, "Wrote eigenvectors %d to %d to %s\n", 1, end, eigvecfile);

    gmx_ffclose(out);

    fprintf(stderr, "Wrote the log to %s\n", logfile);

    return 0;
}
Esempio n. 21
0
void shift_x(const t_graph *g, matrix box, const rvec x[], rvec x_s[])
{
    ivec    *is;
    int      g0, g1;
    int      j, tx, ty, tz;

    GCHECK(g);
    g0 = g->at_start;
    g1 = g->at_end;
    is = g->ishift;

    for (j = g->at0; j < g0; j++)
    {
        copy_rvec(x[j], x_s[j]);
    }

    if (g->bScrewPBC)
    {
        for (j = g0; (j < g1); j++)
        {
            tx = is[j][XX];
            ty = is[j][YY];
            tz = is[j][ZZ];

            if ((tx > 0 && tx % 2 == 1) ||
                (tx < 0 && -tx %2 == 1))
            {
                x_s[j][XX] = x[j][XX] + tx*box[XX][XX];
                x_s[j][YY] = box[YY][YY] + box[ZZ][YY] - x[j][YY];
                x_s[j][ZZ] = box[ZZ][ZZ]               - x[j][ZZ];
            }
            else
            {
                x_s[j][XX] = x[j][XX];
            }
            x_s[j][YY] = x[j][YY] + ty*box[YY][YY] + tz*box[ZZ][YY];
            x_s[j][ZZ] = x[j][ZZ] + tz*box[ZZ][ZZ];
        }
    }
    else if (TRICLINIC(box))
    {
        for (j = g0; (j < g1); j++)
        {
            tx = is[j][XX];
            ty = is[j][YY];
            tz = is[j][ZZ];

            x_s[j][XX] = x[j][XX]+tx*box[XX][XX]+ty*box[YY][XX]+tz*box[ZZ][XX];
            x_s[j][YY] = x[j][YY]+ty*box[YY][YY]+tz*box[ZZ][YY];
            x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
        }
    }
    else
    {
        for (j = g0; (j < g1); j++)
        {
            tx = is[j][XX];
            ty = is[j][YY];
            tz = is[j][ZZ];

            x_s[j][XX] = x[j][XX]+tx*box[XX][XX];
            x_s[j][YY] = x[j][YY]+ty*box[YY][YY];
            x_s[j][ZZ] = x[j][ZZ]+tz*box[ZZ][ZZ];
        }
    }

    for (j = g1; j < g->at1; j++)
    {
        copy_rvec(x[j], x_s[j]);
    }
}
Esempio n. 22
0
int gmx_trjorder(int argc, char *argv[])
{
    const char     *desc[] = {
        "[THISMODULE] orders molecules according to the smallest distance",
        "to atoms in a reference group",
        "or on z-coordinate (with option [TT]-z[tt]).",
        "With distance ordering, it will ask for a group of reference",
        "atoms and a group of molecules. For each frame of the trajectory",
        "the selected molecules will be reordered according to the shortest",
        "distance between atom number [TT]-da[tt] in the molecule and all the",
        "atoms in the reference group. The center of mass of the molecules can",
        "be used instead of a reference atom by setting [TT]-da[tt] to 0.",
        "All atoms in the trajectory are written",
        "to the output trajectory.[PAR]",
        "[THISMODULE] can be useful for e.g. analyzing the n waters closest to a",
        "protein.",
        "In that case the reference group would be the protein and the group",
        "of molecules would consist of all the water atoms. When an index group",
        "of the first n waters is made, the ordered trajectory can be used",
        "with any GROMACS program to analyze the n closest waters.",
        "[PAR]",
        "If the output file is a [REF].pdb[ref] file, the distance to the reference target",
        "will be stored in the B-factor field in order to color with e.g. Rasmol.",
        "[PAR]",
        "With option [TT]-nshell[tt] the number of molecules within a shell",
        "of radius [TT]-r[tt] around the reference group are printed."
    };
    static int      na   = 3, ref_a = 1;
    static real     rcut = 0;
    static gmx_bool bCOM = FALSE, bZ = FALSE;
    t_pargs         pa[] = {
        { "-na", FALSE, etINT,  {&na},
          "Number of atoms in a molecule" },
        { "-da", FALSE, etINT,  {&ref_a},
          "Atom used for the distance calculation, 0 is COM" },
        { "-com", FALSE, etBOOL, {&bCOM},
          "Use the distance to the center of mass of the reference group" },
        { "-r",  FALSE, etREAL, {&rcut},
          "Cutoff used for the distance calculation when computing the number of molecules in a shell around e.g. a protein" },
        { "-z", FALSE, etBOOL, {&bZ},
          "Order molecules on z-coordinate" }
    };
    FILE           *fp;
    t_trxstatus    *out;
    t_trxstatus    *status;
    gmx_bool        bNShell, bPDBout;
    t_topology      top;
    int             ePBC;
    rvec           *x, *xsol, xcom, dx;
    matrix          box;
    t_pbc           pbc;
    gmx_rmpbc_t     gpbc;
    real            t, totmass, mass, rcut2 = 0, n2;
    int             natoms, nwat, ncut;
    char          **grpname, title[256];
    int             i, j, d, *isize, isize_ref = 0, isize_sol;
    atom_id         sa, sr, *swi, **index, *ind_ref = NULL, *ind_sol;
    output_env_t    oenv;
    t_filenm        fnm[] = {
        { efTRX, "-f", NULL, ffREAD  },
        { efTPS, NULL, NULL, ffREAD  },
        { efNDX, NULL, NULL, ffOPTRD },
        { efTRO, "-o", "ordered", ffOPTWR },
        { efXVG, "-nshell", "nshell", ffOPTWR }
    };
#define NFILE asize(fnm)

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

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x, NULL, box, TRUE);
    sfree(x);

    /* get index groups */
    printf("Select %sa group of molecules to be ordered:\n",
           bZ ? "" : "a group of reference atoms and ");
    snew(grpname, 2);
    snew(index, 2);
    snew(isize, 2);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), bZ ? 1 : 2,
              isize, index, grpname);

    if (!bZ)
    {
        isize_ref = isize[0];
        isize_sol = isize[1];
        ind_ref   = index[0];
        ind_sol   = index[1];
    }
    else
    {
        isize_sol = isize[0];
        ind_sol   = index[0];
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    if (natoms > top.atoms.nr)
    {
        gmx_fatal(FARGS, "Number of atoms in the run input file is larger than in the trjactory");
    }
    for (i = 0; (i < 2); i++)
    {
        for (j = 0; (j < isize[i]); j++)
        {
            if (index[i][j] > natoms)
            {
                gmx_fatal(FARGS, "An atom number in group %s is larger than the number of atoms in the trajectory");
            }
        }
    }

    if ((isize_sol % na) != 0)
    {
        gmx_fatal(FARGS, "Number of atoms in the molecule group (%d) is not a multiple of na (%d)",
                  isize[1], na);
    }

    nwat = isize_sol/na;
    if (ref_a > na)
    {
        gmx_fatal(FARGS, "The reference atom can not be larger than the number of atoms in a molecule");
    }
    ref_a--;
    snew(xsol, nwat);
    snew(order, nwat);
    snew(swi, natoms);
    for (i = 0; (i < natoms); i++)
    {
        swi[i] = i;
    }

    out     = NULL;
    fp      = NULL;
    bNShell = ((opt2bSet("-nshell", NFILE, fnm)) ||
               (opt2parg_bSet("-r", asize(pa), pa)));
    bPDBout = FALSE;
    if (bNShell)
    {
        rcut2   = rcut*rcut;
        fp      = xvgropen(opt2fn("-nshell", NFILE, fnm), "Number of molecules",
                           "Time (ps)", "N", oenv);
        printf("Will compute the number of molecules within a radius of %g\n",
               rcut);
    }
    if (!bNShell || opt2bSet("-o", NFILE, fnm))
    {
        bPDBout = (fn2ftp(opt2fn("-o", NFILE, fnm)) == efPDB);
        if (bPDBout && !top.atoms.pdbinfo)
        {
            fprintf(stderr, "Creating pdbfino records\n");
            snew(top.atoms.pdbinfo, top.atoms.nr);
        }
        out = open_trx(opt2fn("-o", NFILE, fnm), "w");
    }
    gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    do
    {
        gmx_rmpbc(gpbc, natoms, box, x);
        set_pbc(&pbc, ePBC, box);

        if (ref_a == -1)
        {
            /* Calculate the COM of all solvent molecules */
            for (i = 0; i < nwat; i++)
            {
                totmass = 0;
                clear_rvec(xsol[i]);
                for (j = 0; j < na; j++)
                {
                    sa       = ind_sol[i*na+j];
                    mass     = top.atoms.atom[sa].m;
                    totmass += mass;
                    for (d = 0; d < DIM; d++)
                    {
                        xsol[i][d] += mass*x[sa][d];
                    }
                }
                svmul(1.0/totmass, xsol[i], xsol[i]);
            }
        }
        else
        {
            /* Copy the reference atom of all solvent molecules */
            for (i = 0; i < nwat; i++)
            {
                copy_rvec(x[ind_sol[i*na+ref_a]], xsol[i]);
            }
        }

        if (bZ)
        {
            for (i = 0; (i < nwat); i++)
            {
                sa           = ind_sol[na*i];
                order[i].i   = sa;
                order[i].d2  = xsol[i][ZZ];
            }
        }
        else if (bCOM)
        {
            totmass = 0;
            clear_rvec(xcom);
            for (i = 0; i < isize_ref; i++)
            {
                mass     = top.atoms.atom[ind_ref[i]].m;
                totmass += mass;
                for (j = 0; j < DIM; j++)
                {
                    xcom[j] += mass*x[ind_ref[i]][j];
                }
            }
            svmul(1/totmass, xcom, xcom);
            for (i = 0; (i < nwat); i++)
            {
                sa = ind_sol[na*i];
                pbc_dx(&pbc, xcom, xsol[i], dx);
                order[i].i   = sa;
                order[i].d2  = norm2(dx);
            }
        }
        else
        {
            /* Set distance to first atom */
            for (i = 0; (i < nwat); i++)
            {
                sa = ind_sol[na*i];
                pbc_dx(&pbc, x[ind_ref[0]], xsol[i], dx);
                order[i].i   = sa;
                order[i].d2  = norm2(dx);
            }
            for (j = 1; (j < isize_ref); j++)
            {
                sr = ind_ref[j];
                for (i = 0; (i < nwat); i++)
                {
                    pbc_dx(&pbc, x[sr], xsol[i], dx);
                    n2 = norm2(dx);
                    if (n2 < order[i].d2)
                    {
                        order[i].d2  = n2;
                    }
                }
            }
        }

        if (bNShell)
        {
            ncut = 0;
            for (i = 0; (i < nwat); i++)
            {
                if (order[i].d2 <= rcut2)
                {
                    ncut++;
                }
            }
            fprintf(fp, "%10.3f  %8d\n", t, ncut);
        }
        if (out)
        {
            qsort(order, nwat, sizeof(*order), ocomp);
            for (i = 0; (i < nwat); i++)
            {
                for (j = 0; (j < na); j++)
                {
                    swi[ind_sol[na*i]+j] = order[i].i+j;
                }
            }

            /* Store the distance as the B-factor */
            if (bPDBout)
            {
                for (i = 0; (i < nwat); i++)
                {
                    for (j = 0; (j < na); j++)
                    {
                        top.atoms.pdbinfo[order[i].i+j].bfac = std::sqrt(order[i].d2);
                    }
                }
            }
            write_trx(out, natoms, swi, &top.atoms, 0, t, box, x, NULL, NULL);
        }
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trj(status);
    if (out)
    {
        close_trx(out);
    }
    if (fp)
    {
        xvgrclose(fp);
    }
    gmx_rmpbc_done(gpbc);

    return 0;
}
Esempio n. 23
0
void put_charge_groups_in_box(FILE *fplog,int cg0,int cg1,
                              int ePBC,matrix box,t_block *cgs,
                              rvec pos[],rvec cg_cm[])

{ 
    int  npbcdim,icg,k,k0,k1,d,e;
    rvec cg;
    real nrcg,inv_ncg;
    atom_id *cgindex;
    gmx_bool bTric;

    if (ePBC == epbcNONE) 
        gmx_incons("Calling put_charge_groups_in_box for a system without PBC");

#ifdef DEBUG
    fprintf(fplog,"Putting cgs %d to %d in box\n",cg0,cg1);
#endif
    cgindex = cgs->index;

    if (ePBC == epbcXY)
        npbcdim = 2;
    else
        npbcdim = 3;

    bTric = TRICLINIC(box);

    for(icg=cg0; (icg<cg1); icg++) {
        /* First compute the center of geometry for this charge group */
        k0      = cgindex[icg];
        k1      = cgindex[icg+1];
        nrcg    = k1-k0;

        if (nrcg == 1) {
            copy_rvec(pos[k0],cg_cm[icg]);
        } else {
            inv_ncg = 1.0/nrcg;

            clear_rvec(cg);
            for(k=k0; (k<k1); k++)  {
                for(d=0; d<DIM; d++)
                    cg[d] += pos[k][d];
            }
            for(d=0; d<DIM; d++)
                cg_cm[icg][d] = inv_ncg*cg[d];
        }
        /* Now check pbc for this cg */
        if (bTric) {
            for(d=npbcdim-1; d>=0; d--) {
                while(cg_cm[icg][d] < 0) {
                    for(e=d; e>=0; e--) {
                        cg_cm[icg][e] += box[d][e];
                        for(k=k0; (k<k1); k++) 
                            pos[k][e] += box[d][e];
                    }
                }
                while(cg_cm[icg][d] >= box[d][d]) {
                    for(e=d; e>=0; e--) {
                        cg_cm[icg][e] -= box[d][e];
                        for(k=k0; (k<k1); k++) 
                            pos[k][e] -= box[d][e];
                    }
                }
            }
        } else {
            for(d=0; d<npbcdim; d++) {
                while(cg_cm[icg][d] < 0) {
                    cg_cm[icg][d] += box[d][d];
                    for(k=k0; (k<k1); k++) 
                        pos[k][d] += box[d][d];
                }
                while(cg_cm[icg][d] >= box[d][d]) {
                    cg_cm[icg][d] -= box[d][d];
                    for(k=k0; (k<k1); k++) 
                        pos[k][d] -= box[d][d];
                }
            }
        }
#ifdef DEBUG_PBC
        for(d=0; (d<npbcdim); d++) {
            if ((cg_cm[icg][d] < 0) || (cg_cm[icg][d] >= box[d][d]))
                gmx_fatal(FARGS,"cg_cm[%d] = %15f  %15f  %15f\n"
                          "box = %15f  %15f  %15f\n",
                          icg,cg_cm[icg][XX],cg_cm[icg][YY],cg_cm[icg][ZZ],
                          box[XX][XX],box[YY][YY],box[ZZ][ZZ]);
        }
#endif
    }
}
Esempio n. 24
0
int gmx_confrms(int argc, char *argv[])
{
    const char     *desc[] = {
        "[TT]g_confrms[tt] computes the root mean square deviation (RMSD) of two",
        "structures after least-squares fitting the second structure on the first one.",
        "The two structures do NOT need to have the same number of atoms,",
        "only the two index groups used for the fit need to be identical.",
        "With [TT]-name[tt] only matching atom names from the selected groups",
        "will be used for the fit and RMSD calculation. This can be useful ",
        "when comparing mutants of a protein.",
        "[PAR]",
        "The superimposed structures are written to file. In a [TT].pdb[tt] file",
        "the two structures will be written as separate models",
        "(use [TT]rasmol -nmrpdb[tt]). Also in a [TT].pdb[tt] file, B-factors",
        "calculated from the atomic MSD values can be written with [TT]-bfac[tt].",
    };
    static gmx_bool bOne  = FALSE, bRmpbc = FALSE, bMW = TRUE, bName = FALSE,
                    bBfac = FALSE, bFit = TRUE, bLabel = FALSE;

    t_pargs  pa[] = {
        { "-one", FALSE, etBOOL, {&bOne},   "Only write the fitted structure to file" },
        { "-mw",  FALSE, etBOOL, {&bMW},    "Mass-weighted fitting and RMSD" },
        { "-pbc", FALSE, etBOOL, {&bRmpbc}, "Try to make molecules whole again" },
        { "-fit", FALSE, etBOOL, {&bFit},
          "Do least squares superposition of the target structure to the reference" },
        { "-name", FALSE, etBOOL, {&bName},
          "Only compare matching atom names" },
        { "-label", FALSE, etBOOL, {&bLabel},
          "Added chain labels A for first and B for second structure"},
        { "-bfac", FALSE, etBOOL, {&bBfac},
          "Output B-factors from atomic MSD values" }
    };
    t_filenm fnm[] = {
        { efTPS, "-f1",  "conf1.gro", ffREAD  },
        { efSTX, "-f2",  "conf2",     ffREAD  },
        { efSTO, "-o",   "fit.pdb",   ffWRITE },
        { efNDX, "-n1", "fit1.ndx",  ffOPTRD },
        { efNDX, "-n2", "fit2.ndx",  ffOPTRD },
        { efNDX, "-no", "match.ndx", ffOPTWR }
    };
#define NFILE asize(fnm)

    /* the two structure files */
    const char  *conf1file, *conf2file, *matchndxfile, *outfile;
    FILE        *fp;
    char         title1[STRLEN], title2[STRLEN], *name1, *name2;
    t_topology  *top1, *top2;
    int          ePBC1, ePBC2;
    t_atoms     *atoms1, *atoms2;
    int          warn = 0;
    atom_id      at;
    real        *w_rls, mass, totmass;
    rvec        *x1, *v1, *x2, *v2, *fit_x;
    matrix       box1, box2;

    output_env_t oenv;

    /* counters */
    int     i, j, m;

    /* center of mass calculation */
    real    tmas1, tmas2;
    rvec    xcm1, xcm2;

    /* variables for fit */
    char    *groupnames1, *groupnames2;
    int      isize1, isize2;
    atom_id *index1, *index2;
    real     rms, msd, minmsd, maxmsd;
    real    *msds;


    parse_common_args(&argc, argv, PCA_BE_NICE | PCA_CAN_VIEW,
                      NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);
    matchndxfile = opt2fn_null("-no", NFILE, fnm);
    conf1file    = ftp2fn(efTPS, NFILE, fnm);
    conf2file    = ftp2fn(efSTX, NFILE, fnm);

    /* reading reference structure from first structure file */
    fprintf(stderr, "\nReading first structure file\n");
    snew(top1, 1);
    read_tps_conf(conf1file, title1, top1, &ePBC1, &x1, &v1, box1, TRUE);
    atoms1 = &(top1->atoms);
    fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
            title1, atoms1->nr, atoms1->nres);

    if (bRmpbc)
    {
        rm_gropbc(atoms1, x1, box1);
    }

    fprintf(stderr, "Select group from first structure\n");
    get_index(atoms1, opt2fn_null("-n1", NFILE, fnm),
              1, &isize1, &index1, &groupnames1);
    printf("\n");

    if (bFit && (isize1 < 3))
    {
        gmx_fatal(FARGS, "Need >= 3 points to fit!\n");
    }

    /* reading second structure file */
    fprintf(stderr, "\nReading second structure file\n");
    snew(top2, 1);
    read_tps_conf(conf2file, title2, top2, &ePBC2, &x2, &v2, box2, TRUE);
    atoms2 = &(top2->atoms);
    fprintf(stderr, "%s\nContaining %d atoms in %d residues\n",
            title2, atoms2->nr, atoms2->nres);

    if (bRmpbc)
    {
        rm_gropbc(atoms2, x2, box2);
    }

    fprintf(stderr, "Select group from second structure\n");
    get_index(atoms2, opt2fn_null("-n2", NFILE, fnm),
              1, &isize2, &index2, &groupnames2);

    if (bName)
    {
        find_matching_names(&isize1, index1, atoms1, &isize2, index2, atoms2);
        if (matchndxfile)
        {
            fp = ffopen(matchndxfile, "w");
            fprintf(fp, "; Matching atoms between %s from %s and %s from %s\n",
                    groupnames1, conf1file, groupnames2, conf2file);
            fprintf(fp, "[ Match_%s_%s ]\n", conf1file, groupnames1);
            for (i = 0; i < isize1; i++)
            {
                fprintf(fp, "%4u%s", index1[i]+1, (i%15 == 14 || i == isize1-1) ? "\n" : " ");
            }
            fprintf(fp, "[ Match_%s_%s ]\n", conf2file, groupnames2);
            for (i = 0; i < isize2; i++)
            {
                fprintf(fp, "%4u%s", index2[i]+1, (i%15 == 14 || i == isize2-1) ? "\n" : " ");
            }
        }
    }

    /* check isizes, must be equal */
    if (isize2 != isize1)
    {
        gmx_fatal(FARGS, "You selected groups with differen number of atoms.\n");
    }

    for (i = 0; i < isize1; i++)
    {
        name1 = *atoms1->atomname[index1[i]];
        name2 = *atoms2->atomname[index2[i]];
        if (strcmp(name1, name2))
        {
            if (warn < 20)
            {
                fprintf(stderr,
                        "Warning: atomnames at index %d don't match: %u %s, %u %s\n",
                        i+1, index1[i]+1, name1, index2[i]+1, name2);
            }
            warn++;
        }
        if (!bMW)
        {
            atoms1->atom[index1[i]].m = 1;
            atoms2->atom[index2[i]].m = 1;
        }
    }
    if (warn)
    {
        fprintf(stderr, "%d atomname%s did not match\n", warn, (warn == 1) ? "" : "s");
    }

    if (bFit)
    {
        /* calculate and remove center of mass of structures */
        calc_rm_cm(isize1, index1, atoms1, x1, xcm1);
        calc_rm_cm(isize2, index2, atoms2, x2, xcm2);

        snew(w_rls, atoms2->nr);
        snew(fit_x, atoms2->nr);
        for (at = 0; (at < isize1); at++)
        {
            w_rls[index2[at]] = atoms1->atom[index1[at]].m;
            copy_rvec(x1[index1[at]], fit_x[index2[at]]);
        }

        /* do the least squares fit to the reference structure */
        do_fit(atoms2->nr, w_rls, fit_x, x2);

        sfree(fit_x);
        sfree(w_rls);
        w_rls = NULL;
    }
    else
    {
        clear_rvec(xcm1);
        clear_rvec(xcm2);
        w_rls = NULL;
    }

    /* calculate the rms deviation */
    rms     = 0;
    totmass = 0;
    maxmsd  = -1e18;
    minmsd  =  1e18;
    snew(msds, isize1);
    for (at = 0; at < isize1; at++)
    {
        mass = atoms1->atom[index1[at]].m;
        for (m = 0; m < DIM; m++)
        {
            msd       = sqr(x1[index1[at]][m] - x2[index2[at]][m]);
            rms      += msd*mass;
            msds[at] += msd;
        }
        maxmsd   = max(maxmsd, msds[at]);
        minmsd   = min(minmsd, msds[at]);
        totmass += mass;
    }
    rms = sqrt(rms/totmass);

    printf("Root mean square deviation after lsq fit = %g nm\n", rms);
    if (bBfac)
    {
        printf("Atomic MSD's range from %g to %g nm^2\n", minmsd, maxmsd);
    }

    if (bFit)
    {
        /* reset coordinates of reference and fitted structure */
        for (i = 0; i < atoms1->nr; i++)
        {
            for (m = 0; m < DIM; m++)
            {
                x1[i][m] += xcm1[m];
            }
        }
        for (i = 0; i < atoms2->nr; i++)
        {
            for (m = 0; m < DIM; m++)
            {
                x2[i][m] += xcm1[m];
            }
        }
    }

    outfile = ftp2fn(efSTO, NFILE, fnm);
    switch (fn2ftp(outfile))
    {
        case efPDB:
        case efBRK:
        case efENT:
            if (bBfac || bLabel)
            {
                srenew(atoms1->pdbinfo, atoms1->nr);
                srenew(atoms1->atom, atoms1->nr); /* Why renew atom? */

                /* Avoid segfaults when writing the pdb-file */
                for (i = 0; i < atoms1->nr; i++)
                {
                    atoms1->pdbinfo[i].type         = eptAtom;
                    atoms1->pdbinfo[i].occup        = 1.00;
                    atoms1->pdbinfo[i].bAnisotropic = FALSE;
                    if (bBfac)
                    {
                        atoms1->pdbinfo[i].bfac = 0;
                    }
                    if (bLabel)
                    {
                        atoms1->resinfo[atoms1->atom[i].resind].chainid = 'A';
                    }
                }

                for (i = 0; i < isize1; i++)
                {
                    /* atoms1->pdbinfo[index1[i]].type = eptAtom; */
/*  atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE; */
                    if (bBfac)
                    {
                        atoms1->pdbinfo[index1[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
                    }
/*  if (bLabel) */
/*    atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A'; */
                }
                srenew(atoms2->pdbinfo, atoms2->nr);
                srenew(atoms2->atom, atoms2->nr); /* Why renew atom? */

                for (i = 0; i < atoms2->nr; i++)
                {
                    atoms2->pdbinfo[i].type         = eptAtom;
                    atoms2->pdbinfo[i].occup        = 1.00;
                    atoms2->pdbinfo[i].bAnisotropic = FALSE;
                    if (bBfac)
                    {
                        atoms2->pdbinfo[i].bfac = 0;
                    }
                    if (bLabel)
                    {
                        atoms2->resinfo[atoms1->atom[i].resind].chainid = 'B';
                    }
                }

                for (i = 0; i < isize2; i++)
                {
                    /* atoms2->pdbinfo[index2[i]].type = eptAtom; */
/*  atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE; */
                    if (bBfac)
                    {
                        atoms2->pdbinfo[index2[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
                    }
/*  if (bLabel) */
/*    atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B'; */
                }
            }
            fp = ffopen(outfile, "w");
            if (!bOne)
            {
                write_pdbfile(fp, title1, atoms1, x1, ePBC1, box1, ' ', 1, NULL, TRUE);
            }
            write_pdbfile(fp, title2, atoms2, x2, ePBC2, box2, ' ', bOne ? -1 : 2, NULL, TRUE);
            ffclose(fp);
            break;
        case efGRO:
            if (bBfac)
            {
                fprintf(stderr, "WARNING: cannot write B-factor values to gro file\n");
            }
            fp = ffopen(outfile, "w");
            if (!bOne)
            {
                write_hconf_p(fp, title1, atoms1, 3, x1, v1, box1);
            }
            write_hconf_p(fp, title2, atoms2, 3, x2, v2, box2);
            ffclose(fp);
            break;
        default:
            if (bBfac)
            {
                fprintf(stderr, "WARNING: cannot write B-factor values to %s file\n",
                        ftp2ext(fn2ftp(outfile)));
            }
            if (!bOne)
            {
                fprintf(stderr,
                        "WARNING: cannot write the reference structure to %s file\n",
                        ftp2ext(fn2ftp(outfile)));
            }
            write_sto_conf(outfile, title2, atoms2, x2, v2, ePBC2, box2);
            break;
    }

    view_all(oenv, NFILE, fnm);

    thanx(stderr);

    return 0;
}
Esempio n. 25
0
int gmx_gyrate(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] computes the radius of gyration of a molecule",
        "and the radii of gyration about the [IT]x[it]-, [IT]y[it]- and [IT]z[it]-axes,",
        "as a function of time. The atoms are explicitly mass weighted.[PAR]",
        "The axis components corresponds to the mass-weighted root-mean-square",
        "of the radii components orthogonal to each axis, for example:[PAR]",
        "Rg(x) = sqrt((sum_i m_i (R_i(y)^2 + R_i(z)^2))/(sum_i m_i)).[PAR]",
        "With the [TT]-nmol[tt] option the radius of gyration will be calculated",
        "for multiple molecules by splitting the analysis group in equally",
        "sized parts.[PAR]",
        "With the option [TT]-nz[tt] 2D radii of gyration in the [IT]x-y[it] plane",
        "of slices along the [IT]z[it]-axis are calculated."
    };
    static int        nmol = 1, nz = 0;
    static gmx_bool   bQ   = FALSE, bRot = FALSE, bMOI = FALSE;
    t_pargs           pa[] = {
        { "-nmol", FALSE, etINT, {&nmol},
          "The number of molecules to analyze" },
        { "-q", FALSE, etBOOL, {&bQ},
          "Use absolute value of the charge of an atom as weighting factor instead of mass" },
        { "-p", FALSE, etBOOL, {&bRot},
          "Calculate the radii of gyration about the principal axes." },
        { "-moi", FALSE, etBOOL, {&bMOI},
          "Calculate the moments of inertia (defined by the principal axes)." },
        { "-nz", FALSE, etINT, {&nz},
          "Calculate the 2D radii of gyration of this number of slices along the z-axis" },
    };
    FILE             *out;
    t_trxstatus      *status;
    t_topology        top;
    int               ePBC;
    rvec             *x, *x_s;
    rvec              xcm, gvec, gvec1;
    matrix            box, trans;
    gmx_bool          bACF;
    real            **moi_trans = nullptr;
    int               max_moi   = 0, delta_moi = 100;
    rvec              d, d1; /* eigenvalues of inertia tensor */
    real              t, t0, tm, gyro;
    int               natoms;
    char             *grpname;
    int               j, m, gnx, nam, mol;
    int              *index;
    gmx_output_env_t *oenv;
    gmx_rmpbc_t       gpbc   = nullptr;
    const char       *leg[]  = { "Rg", "Rg\\sX\\N", "Rg\\sY\\N", "Rg\\sZ\\N" };
    const char       *legI[] = { "Itot", "I1", "I2", "I3" };
#define NLEG asize(leg)
    t_filenm          fnm[] = {
        { efTRX, "-f",   nullptr,       ffREAD },
        { efTPS, nullptr,   nullptr,       ffREAD },
        { efNDX, nullptr,   nullptr,       ffOPTRD },
        { efXVG, nullptr,   "gyrate",   ffWRITE },
        { efXVG, "-acf", "moi-acf",  ffOPTWR },
    };
#define NFILE asize(fnm)
    int               npargs;
    t_pargs          *ppa;

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

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
                           NFILE, fnm, npargs, ppa, asize(desc), desc, 0, nullptr, &oenv))
    {
        sfree(ppa);
        return 0;
    }
    bACF = opt2bSet("-acf", NFILE, fnm);
    if (bACF && nmol != 1)
    {
        gmx_fatal(FARGS, "Can only do acf with nmol=1");
    }
    bRot = bRot || bMOI || bACF;
    /*
       if (nz > 0)
       bMOI = TRUE;
     */
    if (bRot)
    {
        printf("Will rotate system along principal axes\n");
        snew(moi_trans, DIM);
    }
    if (bMOI)
    {
        printf("Will print moments of inertia\n");
        bQ = FALSE;
    }
    if (bQ)
    {
        printf("Will print radius normalised by charge\n");
    }

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

    if (nmol > gnx || gnx % nmol != 0)
    {
        gmx_fatal(FARGS, "The number of atoms in the group (%d) is not a multiple of nmol (%d)", gnx, nmol);
    }
    nam = gnx/nmol;

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

    j  = 0;
    t0 = t;
    if (bQ)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of Charge (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    else if (bMOI)
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Moments of inertia (total and around axes)", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv);
    }
    else
    {
        out = xvgropen(ftp2fn(efXVG, NFILE, fnm),
                       "Radius of gyration (total and around axes)", "Time (ps)", "Rg (nm)", oenv);
    }
    if (bMOI)
    {
        xvgr_legend(out, NLEG, legI, oenv);
    }
    else
    {
        if (bRot)
        {
            if (output_env_get_print_xvgr_codes(oenv))
            {
                fprintf(out, "@ subtitle \"Axes are principal component axes\"\n");
            }
        }
        xvgr_legend(out, NLEG, leg, oenv);
    }
    if (nz == 0)
    {
        gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    }
    do
    {
        if (nz == 0)
        {
            gmx_rmpbc_copy(gpbc, natoms, box, x, x_s);
        }
        gyro = 0;
        clear_rvec(gvec);
        clear_rvec(gvec1);
        clear_rvec(d);
        clear_rvec(d1);
        for (mol = 0; mol < nmol; mol++)
        {
            tm    = sub_xcm(nz == 0 ? x_s : x, nam, index+mol*nam, top.atoms.atom, xcm, bQ);
            if (nz == 0)
            {
                gyro += calc_gyro(x_s, nam, index+mol*nam, top.atoms.atom,
                                  tm, gvec1, d1, bQ, bRot, bMOI, trans);
            }
            else
            {
                calc_gyro_z(x, box, nam, index+mol*nam, top.atoms.atom, nz, t, out);
            }
            rvec_inc(gvec, gvec1);
            rvec_inc(d, d1);
        }
        if (nmol > 0)
        {
            gyro /= nmol;
            svmul(1.0/nmol, gvec, gvec);
            svmul(1.0/nmol, d, d);
        }

        if (nz == 0)
        {
            if (bRot)
            {
                if (j >= max_moi)
                {
                    max_moi += delta_moi;
                    for (m = 0; (m < DIM); m++)
                    {
                        srenew(moi_trans[m], max_moi*DIM);
                    }
                }
                for (m = 0; (m < DIM); m++)
                {
                    copy_rvec(trans[m], moi_trans[m]+DIM*j);
                }
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, d[XX], d[YY], d[ZZ]);
            }
            else
            {
                fprintf(out, "%10g  %10g  %10g  %10g  %10g\n",
                        t, gyro, gvec[XX], gvec[YY], gvec[ZZ]);
            }
        }
        j++;
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trx(status);
    if (nz == 0)
    {
        gmx_rmpbc_done(gpbc);
    }

    xvgrclose(out);

    if (bACF)
    {
        int mode = eacVector;

        do_autocorr(opt2fn("-acf", NFILE, fnm), oenv,
                    "Moment of inertia vector ACF",
                    j, 3, moi_trans, (t-t0)/j, mode, FALSE);
        do_view(oenv, opt2fn("-acf", NFILE, fnm), "-nxy");
    }

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

    return 0;
}
Esempio n. 26
0
int gmx_genconf(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] multiplies a given coordinate file by simply stacking them",
        "on top of each other, like a small child playing with wooden blocks.",
        "The program makes a grid of [IT]user-defined[it]",
        "proportions ([TT]-nbox[tt]), ",
        "and interspaces the grid point with an extra space [TT]-dist[tt].[PAR]",
        "When option [TT]-rot[tt] is used the program does not check for overlap",
        "between molecules on grid points. It is recommended to make the box in",
        "the input file at least as big as the coordinates + ",
        "van der Waals radius.[PAR]",
        "If the optional trajectory file is given, conformations are not",
        "generated, but read from this file and translated appropriately to",
        "build the grid."

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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


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

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

    return 0;
}
Esempio n. 27
0
int gmx_vanhove(int argc,char *argv[])
{
  const char *desc[] = {
    "g_vanhove computes the Van Hove correlation function.",
    "The Van Hove G(r,t) is the probability that a particle that is at r0",
    "at time zero can be found at position r0+r at time t.",
    "g_vanhove determines G not for a vector r, but for the length of r.",
    "Thus it gives the probability that a particle moves a distance of r",
    "in time t.",
    "Jumps across the periodic boundaries are removed.",
    "Corrections are made for scaling due to isotropic",
    "or anisotropic pressure coupling.",
    "[PAR]",
    "With option [TT]-om[tt] the whole matrix can be written as a function",
    "of t and r or as a function of sqrt(t) and r (option [TT]-sqrt[tt]).",
    "[PAR]",
    "With option [TT]-or[tt] the Van Hove function is plotted for one",
    "or more values of t. Option [TT]-nr[tt] sets the number of times,",
    "option [TT]-fr[tt] the number spacing between the times.",
    "The binwidth is set with option [TT]-rbin[tt]. The number of bins",
    "is determined automatically.",
    "[PAR]",
    "With option [TT]-ot[tt] the integral up to a certain distance",
    "(option [TT]-rt[tt]) is plotted as a function of time.",
    "[PAR]",
    "For all frames that are read the coordinates of the selected particles",
    "are stored in memory. Therefore the program may use a lot of memory.",
    "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.",
    "This is because the calculation scales as the number of frames times",
    "[TT]-fm[tt] or [TT]-ft[tt].",
    "Note that with the [TT]-dt[tt] option the memory usage and calculation",
    "time can be reduced."
  };
  static int fmmax=0,ftmax=0,nlev=81,nr=1,fshift=0;
  static real sbin=0,rmax=2,rbin=0.01,mmax=0,rint=0;
  t_pargs pa[] = {
    { "-sqrt",    FALSE, etREAL,{&sbin},
      "Use sqrt(t) on the matrix axis which binspacing # in sqrt(ps)" },
    { "-fm",      FALSE, etINT, {&fmmax},
      "Number of frames in the matrix, 0 is plot all" },
    { "-rmax",    FALSE, etREAL, {&rmax},
      "Maximum r in the matrix (nm)" },
    { "-rbin",    FALSE, etREAL, {&rbin},
      "Binwidth in the matrix and for -or (nm)" },
    { "-mmax",    FALSE, etREAL, {&mmax},
      "Maximum density in the matrix, 0 is calculate (1/nm)" },
    { "-nlevels" ,FALSE, etINT,  {&nlev}, 
      "Number of levels in the matrix" },
    { "-nr",      FALSE, etINT, {&nr},
      "Number of curves for the -or output" },
    { "-fr",      FALSE, etINT, {&fshift},
      "Frame spacing for the -or output" },
    { "-rt",      FALSE, etREAL, {&rint},
      "Integration limit for the -ot output (nm)" },
    { "-ft",      FALSE, etINT, {&ftmax},
      "Number of frames in the -ot output, 0 is plot all" }
  };
#define NPA asize(pa)

  t_filenm fnm[] = { 
    { efTRX, NULL, NULL,  ffREAD },
    { efTPS, NULL, NULL,  ffREAD }, 
    { efNDX, NULL, NULL,  ffOPTRD },
    { efXPM, "-om", "vanhove", ffOPTWR },
    { efXVG, "-or", "vanhove_r", ffOPTWR },
    { efXVG, "-ot", "vanhove_t", ffOPTWR }
  };
#define NFILE asize(fnm)

  output_env_t oenv;
  const char *matfile,*otfile,*orfile;
  char     title[256];
  t_topology top;
  int      ePBC;
  matrix   boxtop,box,*sbox,avbox,corr;
  rvec     *xtop,*x,**sx;
  int      isize,nalloc,nallocn,natom;
  t_trxstatus *status;
  atom_id  *index;
  char     *grpname;
  int      nfr,f,ff,i,m,mat_nx=0,nbin=0,bin,mbin,fbin;
  real     *time,t,invbin=0,rmax2=0,rint2=0,d2;
  real     invsbin=0,matmax,normfac,dt,*tickx,*ticky;
  char     buf[STRLEN],**legend;
  real     **mat=NULL;
  int      *pt=NULL,**pr=NULL,*mcount=NULL,*tcount=NULL,*rcount=NULL;
  FILE     *fp;
  t_rgb    rlo={1,1,1}, rhi={0,0,0};

  CopyRight(stderr,argv[0]);

  parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
  
  matfile = opt2fn_null("-om",NFILE,fnm);
  if (opt2parg_bSet("-fr",NPA,pa))
    orfile  = opt2fn("-or",NFILE,fnm);
  else
    orfile  = opt2fn_null("-or",NFILE,fnm);
  if (opt2parg_bSet("-rt",NPA,pa))
    otfile  = opt2fn("-ot",NFILE,fnm);
  else
    otfile  = opt2fn_null("-ot",NFILE,fnm);
  
  if (!matfile && !otfile && !orfile) {
    fprintf(stderr,
	    "For output set one (or more) of the output file options\n");
    exit(0);
  }
  
  read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,boxtop,
		FALSE); 
  get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
  
  nalloc = 0;
  time = NULL;
  sbox = NULL;
  sx   = NULL;
  clear_mat(avbox);

  natom=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
  nfr = 0;
  do {
    if (nfr >= nalloc) {
      nalloc += 100;
      srenew(time,nalloc);
      srenew(sbox,nalloc);
      srenew(sx,nalloc);
    }
    
    time[nfr] = t;
    copy_mat(box,sbox[nfr]);
    /* This assumes that the off-diagonal box elements
     * are not affected by jumps across the periodic boundaries.
     */
    m_add(avbox,box,avbox);
    snew(sx[nfr],isize);
    for(i=0; i<isize; i++)
     copy_rvec(x[index[i]],sx[nfr][i]);
    
    nfr++;
  } while (read_next_x(oenv,status,&t,natom,x,box));

  /* clean up */
  sfree(x);
  close_trj(status);
  
  fprintf(stderr,"Read %d frames\n",nfr);

  dt = (time[nfr-1] - time[0])/(nfr - 1);
  /* Some ugly rounding to get nice nice times in the output */
  dt = (int)(10000.0*dt + 0.5)/10000.0;

  invbin = 1.0/rbin;

  if (matfile) {
    if (fmmax <= 0 || fmmax >= nfr)
      fmmax = nfr - 1;
    snew(mcount,fmmax);
    nbin = (int)(rmax*invbin + 0.5);
    if (sbin == 0) {
      mat_nx = fmmax + 1;
    } else {
      invsbin = 1.0/sbin;
      mat_nx = sqrt(fmmax*dt)*invsbin + 1;
    }
    snew(mat,mat_nx);
    for(f=0; f<mat_nx; f++)
      snew(mat[f],nbin);
    rmax2 = sqr(nbin*rbin);
    /* Initialize time zero */
    mat[0][0] = nfr*isize;
    mcount[0] += nfr;
  } else {
    fmmax = 0;
  }
  
  if (orfile) {
    snew(pr,nr);
    nalloc = 0;
    snew(rcount,nr);
  }
  
  if (otfile) {
    if (ftmax <= 0)
      ftmax = nfr - 1;
    snew(tcount,ftmax);
    snew(pt,nfr);
    rint2 = rint*rint;
    /* Initialize time zero */
    pt[0] = nfr*isize;
    tcount[0] += nfr;
  } else {
    ftmax = 0;
  }

  msmul(avbox,1.0/nfr,avbox);
  for(f=0; f<nfr; f++) {
    if (f % 100 == 0)
      fprintf(stderr,"\rProcessing frame %d",f);
    /* Scale all the configuration to the average box */
    m_inv_ur0(sbox[f],corr);
    mmul_ur0(avbox,corr,corr);
    for(i=0; i<isize; i++) {
      mvmul_ur0(corr,sx[f][i],sx[f][i]);
      if (f > 0) {
	/* Correct for periodic jumps */
	for(m=DIM-1; m>=0; m--) {
	  while(sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m])
	    rvec_dec(sx[f][i],avbox[m]);
	  while(sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m])
	    rvec_inc(sx[f][i],avbox[m]);
	}
      }
    }
    for(ff=0; ff<f; ff++) {
      fbin = f - ff;
      if (fbin <= fmmax || fbin <= ftmax) {
	if (sbin == 0)
	  mbin = fbin;
	else
	  mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5);
	for(i=0; i<isize; i++) {
	  d2 = distance2(sx[f][i],sx[ff][i]);
	  if (mbin < mat_nx && d2 < rmax2) {
	    bin = (int)(sqrt(d2)*invbin + 0.5);
	    if (bin < nbin) {
	      mat[mbin][bin] += 1;
	    }
	  }
	  if (fbin <= ftmax && d2 <= rint2)
	    pt[fbin]++;
	}
	if (matfile)
	  mcount[mbin]++;
	if (otfile)
	  tcount[fbin]++;
      }
    }
    if (orfile) {
      for(fbin=0; fbin<nr; fbin++) {
	ff = f - (fbin + 1)*fshift;
	if (ff >= 0) {
	  for(i=0; i<isize; i++) {
	    d2 = distance2(sx[f][i],sx[ff][i]);
	    bin = (int)(sqrt(d2)*invbin);
	    if (bin >= nalloc) {
	      nallocn = 10*(bin/10) + 11;
	      for(m=0; m<nr; m++) {
		srenew(pr[m],nallocn);
		for(i=nalloc; i<nallocn; i++)
		  pr[m][i] = 0;
	      }
	      nalloc = nallocn;
	    }
	    pr[fbin][bin]++;
	  }
	  rcount[fbin]++;
	}
      }
    }
  }
  fprintf(stderr,"\n");
  
  if (matfile) {
    matmax = 0;
    for(f=0; f<mat_nx; f++) {
      normfac = 1.0/(mcount[f]*isize*rbin);
      for(i=0; i<nbin; i++) {
	mat[f][i] *= normfac;
	if (mat[f][i] > matmax && (f!=0 || i!=0))
	  matmax = mat[f][i];
      }
    }
    fprintf(stdout,"Value at (0,0): %.3f, maximum of the rest %.3f\n",
	    mat[0][0],matmax);
    if (mmax > 0)
      matmax = mmax;
    snew(tickx,mat_nx);
    for(f=0; f<mat_nx; f++) {
      if (sbin == 0)
	tickx[f] = f*dt;
      else
	tickx[f] = f*sbin;
    }
    snew(ticky,nbin+1);
    for(i=0; i<=nbin; i++)
      ticky[i] = i*rbin;
    fp = ffopen(matfile,"w");
    write_xpm(fp,MAT_SPATIAL_Y,"Van Hove function","G (1/nm)",
	      sbin==0 ? "time (ps)" : "sqrt(time) (ps^1/2)","r (nm)",
	      mat_nx,nbin,tickx,ticky,mat,0,matmax,rlo,rhi,&nlev);     
    ffclose(fp);
  }
  
  if (orfile) {
    fp = xvgropen(orfile,"Van Hove function","r (nm)","G (nm\\S-1\\N)",oenv);
    fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname);
    snew(legend,nr);
    for(fbin=0; fbin<nr; fbin++) {
      sprintf(buf,"%g ps",(fbin + 1)*fshift*dt);
      legend[fbin] = strdup(buf);
    }
    xvgr_legend(fp,nr,(const char**)legend,oenv);
    for(i=0; i<nalloc; i++) {
      fprintf(fp,"%g",i*rbin);
      for(fbin=0; fbin<nr; fbin++)
	fprintf(fp," %g",
		(real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i==0 ? 0.5 : 1)));
      fprintf(fp,"\n");
    }
    ffclose(fp);
  }
  
  if (otfile) {
    sprintf(buf,"Probability of moving less than %g nm",rint);
    fp = xvgropen(otfile,buf,"t (ps)","",oenv);
    fprintf(fp,"@ subtitle \"for particles in group %s\"\n",grpname);
    for(f=0; f<=ftmax; f++)
      fprintf(fp,"%g %g\n",f*dt,(real)pt[f]/(tcount[f]*isize));
    ffclose(fp);
  }

  do_view(oenv, matfile,NULL);
  do_view(oenv, orfile,NULL);
  do_view(oenv, otfile,NULL);

  thanx(stderr);
  
  return 0;
}
Esempio n. 28
0
static void shell_pos_sd(FILE *log,rvec xcur[],rvec xnew[],rvec f[],
			 int ns,t_shell s[],int count)
{
    const real step_scale_min = 0.8,
        step_scale_increment = 0.2,
        step_scale_max = 1.2,
        step_scale_multiple = (step_scale_max - step_scale_min) / step_scale_increment;
  int  i,shell,d;
  real dx,df,k_est;
#ifdef PRINT_STEP  
  real step_min,step_max;

  step_min = 1e30;
  step_max = 0;
#endif
  for(i=0; (i<ns); i++) {
    shell = s[i].shell;
    if (count == 1) {
      for(d=0; d<DIM; d++) {
	s[i].step[d] = s[i].k_1;
#ifdef PRINT_STEP
	step_min = min(step_min,s[i].step[d]);
	step_max = max(step_max,s[i].step[d]);
#endif
      }
    } else {
      for(d=0; d<DIM; d++) {
	dx = xcur[shell][d] - s[i].xold[d];
	df =    f[shell][d] - s[i].fold[d];
    /* -dx/df gets used to generate an interpolated value, but would
     * cause a NaN if df were binary-equal to zero. Values close to
     * zero won't cause problems (because of the min() and max()), so
     * just testing for binary inequality is OK. */
    if (0.0 != df)
    {
        k_est = -dx/df;
        /* Scale the step size by a factor interpolated from
         * step_scale_min to step_scale_max, as k_est goes from 0 to
         * step_scale_multiple * s[i].step[d] */
        s[i].step[d] =
            step_scale_min * s[i].step[d] +
            step_scale_increment * min(step_scale_multiple * s[i].step[d], max(k_est, 0));
    }
    else
    {
        /* Here 0 == df */
        if (gmx_numzero(dx)) /* 0 == dx */
        {
            /* Likely this will never happen, but if it does just
             * don't scale the step. */
        }
        else /* 0 != dx */
        {
            s[i].step[d] *= step_scale_max;
        }
    }
#ifdef PRINT_STEP
	step_min = min(step_min,s[i].step[d]);
	step_max = max(step_max,s[i].step[d]);
#endif
      }
    }
    copy_rvec(xcur[shell],s[i].xold);
    copy_rvec(f[shell],   s[i].fold);

    do_1pos3(xnew[shell],xcur[shell],f[shell],s[i].step);

    if (gmx_debug_at) {
      fprintf(debug,"shell[%d] = %d\n",i,shell);
      pr_rvec(debug,0,"fshell",f[shell],DIM,TRUE);
      pr_rvec(debug,0,"xold",xcur[shell],DIM,TRUE);
      pr_rvec(debug,0,"step",s[i].step,DIM,TRUE);
      pr_rvec(debug,0,"xnew",xnew[shell],DIM,TRUE);
    }
  }
#ifdef PRINT_STEP
  printf("step %.3e %.3e\n",step_min,step_max);
#endif
}
Esempio n. 29
0
static void rot_conf(t_atoms *atoms, rvec x[], rvec v[], real trans, real angle,
                     rvec head, rvec tail, matrix box, int isize, atom_id index[],
                     rvec xout[], rvec vout[])
{
    rvec     arrow, center, xcm;
    real     theta, phi, arrow_len;
    mat4     Rx, Ry, Rz, Rinvy, Rinvz, Mtot, Tcm, Tinvcm, Tx;
    mat4     temp1, temp2, temp3, temp4, temp21, temp43;
    vec4     xv;
    int      i, j, ai;

    rvec_sub(tail, head, arrow);
    arrow_len = norm(arrow);
    if (debug)
    {
        fprintf(debug, "Arrow vector:   %10.4f  %10.4f  %10.4f\n",
                arrow[XX], arrow[YY], arrow[ZZ]);
        fprintf(debug, "Effective translation %g nm\n", trans);
    }
    if (arrow_len == 0.0)
    {
        gmx_fatal(FARGS, "Arrow vector not given");
    }

    /* Copy all aoms to output */
    for (i = 0; (i < atoms->nr); i++)
    {
        copy_rvec(x[i], xout[i]);
        copy_rvec(v[i], vout[i]);
    }

    /* Compute center of mass and move atoms there */
    clear_rvec(xcm);
    for (i = 0; (i < isize); i++)
    {
        rvec_inc(xcm, x[index[i]]);
    }
    for (i = 0; (i < DIM); i++)
    {
        xcm[i] /= isize;
    }
    if (debug)
    {
        fprintf(debug, "Center of mass: %10.4f  %10.4f  %10.4f\n",
                xcm[XX], xcm[YY], xcm[ZZ]);
    }
    for (i = 0; (i < isize); i++)
    {
        rvec_sub(x[index[i]], xcm, xout[index[i]]);
    }

    /* Compute theta and phi that describe the arrow */
    theta = acos(arrow[ZZ]/arrow_len);
    phi   = atan2(arrow[YY]/arrow_len, arrow[XX]/arrow_len);
    if (debug)
    {
        fprintf(debug, "Phi = %.1f, Theta = %.1f\n", RAD2DEG*phi, RAD2DEG*theta);
    }

    /* Now the total rotation matrix: */
    /* Rotate a couple of times */
    rotate(ZZ, -phi, Rz);
    rotate(YY, M_PI/2-theta, Ry);
    rotate(XX, angle*DEG2RAD, Rx);
    Rx[WW][XX] = trans;
    rotate(YY, theta-M_PI/2, Rinvy);
    rotate(ZZ, phi, Rinvz);

    mult_matrix(temp1, Ry, Rz);
    mult_matrix(temp2, Rinvy, Rx);
    mult_matrix(temp3, temp2, temp1);
    mult_matrix(Mtot, Rinvz, temp3);

    print_m4(debug, "Rz", Rz);
    print_m4(debug, "Ry", Ry);
    print_m4(debug, "Rx", Rx);
    print_m4(debug, "Rinvy", Rinvy);
    print_m4(debug, "Rinvz", Rinvz);
    print_m4(debug, "Mtot", Mtot);

    for (i = 0; (i < isize); i++)
    {
        ai = index[i];
        m4_op(Mtot, xout[ai], xv);
        rvec_add(xv, xcm, xout[ai]);
        m4_op(Mtot, v[ai], xv);
        copy_rvec(xv, vout[ai]);
    }
}
Esempio n. 30
0
int gmx_make_edi(int argc, char *argv[])
{

    static const char *desc[] = {
        "[THISMODULE] generates an essential dynamics (ED) sampling input file to be used with [TT]mdrun[tt]",
        "based on eigenvectors of a covariance matrix ([gmx-covar]) or from a",
        "normal modes analysis ([gmx-nmeig]).",
        "ED sampling can be used to manipulate the position along collective coordinates",
        "(eigenvectors) of (biological) macromolecules during a simulation. Particularly,",
        "it may be used to enhance the sampling efficiency of MD simulations by stimulating",
        "the system to explore new regions along these collective coordinates. A number",
        "of different algorithms are implemented to drive the system along the eigenvectors",
        "([TT]-linfix[tt], [TT]-linacc[tt], [TT]-radfix[tt], [TT]-radacc[tt], [TT]-radcon[tt]),",
        "to keep the position along a certain (set of) coordinate(s) fixed ([TT]-linfix[tt]),",
        "or to only monitor the projections of the positions onto",
        "these coordinates ([TT]-mon[tt]).[PAR]",
        "References:[BR]",
        "A. Amadei, A.B.M. Linssen, B.L. de Groot, D.M.F. van Aalten and ",
        "H.J.C. Berendsen; An efficient method for sampling the essential subspace ",
        "of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[BR]",
        "B.L. de Groot, A. Amadei, D.M.F. van Aalten and H.J.C. Berendsen; ",
        "Towards an exhaustive sampling of the configurational spaces of the ",
        "two forms of the peptide hormone guanylin,",
        "J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[BR]",
        "B.L. de Groot, A.Amadei, R.M. Scheek, N.A.J. van Nuland and H.J.C. Berendsen; ",
        "An extended sampling of the configurational space of HPr from E. coli",
        "Proteins: Struct. Funct. Gen. 26: 314-322 (1996)",
        "[PAR]You will be prompted for one or more index groups that correspond to the eigenvectors,",
        "reference structure, target positions, etc.[PAR]",

        "[TT]-mon[tt]: monitor projections of the coordinates onto selected eigenvectors.[PAR]",
        "[TT]-linfix[tt]: perform fixed-step linear expansion along selected eigenvectors.[PAR]",
        "[TT]-linacc[tt]: perform acceptance linear expansion along selected eigenvectors.",
        "(steps in the desired directions will be accepted, others will be rejected).[PAR]",
        "[TT]-radfix[tt]: perform fixed-step radius expansion along selected eigenvectors.[PAR]",
        "[TT]-radacc[tt]: perform acceptance radius expansion along selected eigenvectors.",
        "(steps in the desired direction will be accepted, others will be rejected).",
        "[BB]Note:[bb] by default the starting MD structure will be taken as origin of the first",
        "expansion cycle for radius expansion. If [TT]-ori[tt] is specified, you will be able",
        "to read in a structure file that defines an external origin.[PAR]",
        "[TT]-radcon[tt]: perform acceptance radius contraction along selected eigenvectors",
        "towards a target structure specified with [TT]-tar[tt].[PAR]",
        "NOTE: each eigenvector can be selected only once. [PAR]",
        "[TT]-outfrq[tt]: frequency (in steps) of writing out projections etc. to [TT].xvg[tt] file[PAR]",
        "[TT]-slope[tt]: minimal slope in acceptance radius expansion. A new expansion",
        "cycle will be started if the spontaneous increase of the radius (in nm/step)",
        "is less than the value specified.[PAR]",
        "[TT]-maxedsteps[tt]: maximum number of steps per cycle in radius expansion",
        "before a new cycle is started.[PAR]",
        "Note on the parallel implementation: since ED sampling is a 'global' thing",
        "(collective coordinates etc.), at least on the 'protein' side, ED sampling",
        "is not very parallel-friendly from an implementation point of view. Because",
        "parallel ED requires some extra communication, expect the performance to be",
        "lower as in a free MD simulation, especially on a large number of nodes and/or",
        "when the ED group contains a lot of atoms. [PAR]",
        "Please also note that if your ED group contains more than a single protein,",
        "then the [TT].tpr[tt] file must contain the correct PBC representation of the ED group.",
        "Take a look on the initial RMSD from the reference structure, which is printed",
        "out at the start of the simulation; if this is much higher than expected, one",
        "of the ED molecules might be shifted by a box vector. [PAR]",
        "All ED-related output of [TT]mdrun[tt] (specify with [TT]-eo[tt]) is written to a [TT].xvg[tt] file",
        "as a function of time in intervals of OUTFRQ steps.[PAR]",
        "[BB]Note[bb] that you can impose multiple ED constraints and flooding potentials in",
        "a single simulation (on different molecules) if several [TT].edi[tt] files were concatenated",
        "first. The constraints are applied in the order they appear in the [TT].edi[tt] file. ",
        "Depending on what was specified in the [TT].edi[tt] input file, the output file contains for each ED dataset[PAR]",
        "[TT]*[tt] the RMSD of the fitted molecule to the reference structure (for atoms involved in fitting prior to calculating the ED constraints)[BR]",
        "[TT]*[tt] projections of the positions onto selected eigenvectors[BR]",
        "[PAR][PAR]",
        "FLOODING:[PAR]",
        "with [TT]-flood[tt], you can specify which eigenvectors are used to compute a flooding potential,",
        "which will lead to extra forces expelling the structure out of the region described",
        "by the covariance matrix. If you switch -restrain the potential is inverted and the structure",
        "is kept in that region.",
        "[PAR]",
        "The origin is normally the average structure stored in the [TT]eigvec.trr[tt] file.",
        "It can be changed with [TT]-ori[tt] to an arbitrary position in configuration space.",
        "With [TT]-tau[tt], [TT]-deltaF0[tt], and [TT]-Eflnull[tt] you control the flooding behaviour.",
        "Efl is the flooding strength, it is updated according to the rule of adaptive flooding.",
        "Tau is the time constant of adaptive flooding, high [GRK]tau[grk] means slow adaption (i.e. growth). ",
        "DeltaF0 is the flooding strength you want to reach after tau ps of simulation.",
        "To use constant Efl set [TT]-tau[tt] to zero.",
        "[PAR]",
        "[TT]-alpha[tt] is a fudge parameter to control the width of the flooding potential. A value of 2 has been found",
        "to give good results for most standard cases in flooding of proteins.",
        "[GRK]alpha[grk] basically accounts for incomplete sampling, if you sampled further the width of the ensemble would",
        "increase, this is mimicked by [GRK]alpha[grk] > 1.",
        "For restraining, [GRK]alpha[grk] < 1 can give you smaller width in the restraining potential.",
        "[PAR]",
        "RESTART and FLOODING:",
        "If you want to restart a crashed flooding simulation please find the values deltaF and Efl in",
        "the output file and manually put them into the [TT].edi[tt] file under DELTA_F0 and EFL_NULL."
    };

    /* Save all the params in this struct and then save it in an edi file.
     * ignoring fields nmass,massnrs,mass,tmass,nfit,fitnrs,edo
     */
    static t_edipar edi_params;

    enum  {
        evStepNr = evRADFIX + 1
    };
    static const char* evSelections[evNr]      = {NULL, NULL, NULL, NULL, NULL, NULL};
    static const char* evOptions[evNr]         = {"-linfix", "-linacc", "-flood", "-radfix", "-radacc", "-radcon", "-mon"};
    static const char* evParams[evStepNr]      = {NULL, NULL};
    static const char* evStepOptions[evStepNr] = {"-linstep", "-accdir", "-not_used", "-radstep"};
    static const char* ConstForceStr;
    static real      * evStepList[evStepNr];
    static real        radstep  = 0.0;
    static real        deltaF0  = 150;
    static real        deltaF   = 0;
    static real        tau      = .1;
    static real        constEfl = 0.0;
    static real        alpha    = 1;
    static int         eqSteps  = 0;
    static int       * listen[evNr];
    static real        T         = 300.0;
    const real         kB        = 2.5 / 300.0; /* k_boltzmann in MD units */
    static gmx_bool    bRestrain = FALSE;
    static gmx_bool    bHesse    = FALSE;
    static gmx_bool    bHarmonic = FALSE;
    t_pargs            pa[]      = {
        { "-mon", FALSE, etSTR, {&evSelections[evMON]},
          "Indices of eigenvectors for projections of x (e.g. 1,2-5,9) or 1-100:10 means 1 11 21 31 ... 91" },
        { "-linfix", FALSE, etSTR, {&evSelections[0]},
          "Indices of eigenvectors for fixed increment linear sampling" },
        { "-linacc", FALSE, etSTR, {&evSelections[1]},
          "Indices of eigenvectors for acceptance linear sampling" },
        { "-radfix", FALSE, etSTR, {&evSelections[3]},
          "Indices of eigenvectors for fixed increment radius expansion" },
        { "-radacc", FALSE, etSTR, {&evSelections[4]},
          "Indices of eigenvectors for acceptance radius expansion" },
        { "-radcon", FALSE, etSTR, {&evSelections[5]},
          "Indices of eigenvectors for acceptance radius contraction" },
        { "-flood",  FALSE, etSTR, {&evSelections[2]},
          "Indices of eigenvectors for flooding"},
        { "-outfrq", FALSE, etINT, {&edi_params.outfrq},
          "Freqency (in steps) of writing output in [TT].xvg[tt] file" },
        { "-slope", FALSE, etREAL, { &edi_params.slope},
          "Minimal slope in acceptance radius expansion"},
        { "-linstep", FALSE, etSTR, {&evParams[0]},
          "Stepsizes (nm/step) for fixed increment linear sampling (put in quotes! \"1.0 2.3 5.1 -3.1\")"},
        { "-accdir", FALSE, etSTR, {&evParams[1]},
          "Directions for acceptance linear sampling - only sign counts! (put in quotes! \"-1 +1 -1.1\")"},
        { "-radstep", FALSE, etREAL, {&radstep},
          "Stepsize (nm/step) for fixed increment radius expansion"},
        { "-maxedsteps", FALSE, etINT, {&edi_params.maxedsteps},
          "Maximum number of steps per cycle" },
        { "-eqsteps", FALSE, etINT, {&eqSteps},
          "Number of steps to run without any perturbations "},
        { "-deltaF0", FALSE, etREAL, {&deltaF0},
          "Target destabilization energy for flooding"},
        { "-deltaF", FALSE, etREAL, {&deltaF},
          "Start deltaF with this parameter - default 0, nonzero values only needed for restart"},
        { "-tau", FALSE, etREAL, {&tau},
          "Coupling constant for adaption of flooding strength according to deltaF0, 0 = infinity i.e. constant flooding strength"},
        { "-Eflnull", FALSE, etREAL, {&constEfl},
          "The starting value of the flooding strength. The flooding strength is updated "
          "according to the adaptive flooding scheme. For a constant flooding strength use [TT]-tau[tt] 0. "},
        { "-T", FALSE, etREAL, {&T},
          "T is temperature, the value is needed if you want to do flooding "},
        { "-alpha", FALSE, etREAL, {&alpha},
          "Scale width of gaussian flooding potential with alpha^2 "},
        { "-restrain", FALSE, etBOOL, {&bRestrain},
          "Use the flooding potential with inverted sign -> effects as quasiharmonic restraining potential"},
        { "-hessian", FALSE, etBOOL, {&bHesse},
          "The eigenvectors and eigenvalues are from a Hessian matrix"},
        { "-harmonic", FALSE, etBOOL, {&bHarmonic},
          "The eigenvalues are interpreted as spring constant"},
        { "-constF", FALSE, etSTR, {&ConstForceStr},
          "Constant force flooding: manually set the forces for the eigenvectors selected with -flood "
          "(put in quotes! \"1.0 2.3 5.1 -3.1\"). No other flooding parameters are needed when specifying the forces directly."}
    };
#define NPA asize(pa)

    rvec        *xref1;
    int          nvec1, *eignr1 = NULL;
    rvec        *xav1, **eigvec1 = NULL;
    t_atoms     *atoms = NULL;
    int          nav; /* Number of atoms in the average structure */
    char        *grpname;
    const char  *indexfile;
    int          i;
    atom_id     *index, *ifit;
    int          nfit;           /* Number of atoms in the reference/fit structure */
    int          ev_class;       /* parameter _class i.e. evMON, evRADFIX etc. */
    int          nvecs;
    real        *eigval1 = NULL; /* in V3.3 this is parameter of read_eigenvectors */

    const char  *EdiFile;
    const char  *TargetFile;
    const char  *OriginFile;
    const char  *EigvecFile;

    output_env_t oenv;

    /*to read topology file*/
    t_topology  top;
    int         ePBC;
    char        title[STRLEN];
    matrix      topbox;
    rvec       *xtop;
    gmx_bool    bTop, bFit1;

    t_filenm    fnm[] = {
        { efTRN, "-f",    "eigenvec",    ffREAD  },
        { efXVG, "-eig",  "eigenval",    ffOPTRD },
        { efTPS, NULL,    NULL,          ffREAD },
        { efNDX, NULL,    NULL,  ffOPTRD },
        { efSTX, "-tar", "target", ffOPTRD},
        { efSTX, "-ori", "origin", ffOPTRD},
        { efEDI, "-o", "sam", ffWRITE }
    };
#define NFILE asize(fnm)
    edi_params.outfrq = 100; edi_params.slope = 0.0; edi_params.maxedsteps = 0;
    if (!parse_common_args(&argc, argv, 0,
                           NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv))
    {
        return 0;
    }

    indexfile       = ftp2fn_null(efNDX, NFILE, fnm);
    EdiFile         = ftp2fn(efEDI, NFILE, fnm);
    TargetFile      = opt2fn_null("-tar", NFILE, fnm);
    OriginFile      = opt2fn_null("-ori", NFILE, fnm);


    for (ev_class = 0; ev_class < evNr; ++ev_class)
    {
        if (opt2parg_bSet(evOptions[ev_class], NPA, pa))
        {
            /*get list of eigenvectors*/
            nvecs = sscan_list(&(listen[ev_class]), opt2parg_str(evOptions[ev_class], NPA, pa), evOptions[ev_class]);
            if (ev_class < evStepNr-2)
            {
                /*if apropriate get list of stepsizes for these eigenvectors*/
                if (opt2parg_bSet(evStepOptions[ev_class], NPA, pa))
                {
                    evStepList[ev_class] =
                        scan_vecparams(opt2parg_str(evStepOptions[ev_class], NPA, pa), evStepOptions[ev_class], nvecs);
                }
                else   /*if list is not given fill with zeros */
                {
                    snew(evStepList[ev_class], nvecs);
                    for (i = 0; i < nvecs; i++)
                    {
                        evStepList[ev_class][i] = 0.0;
                    }
                }
            }
            else if (ev_class == evRADFIX)
            {
                snew(evStepList[ev_class], nvecs);
                for (i = 0; i < nvecs; i++)
                {
                    evStepList[ev_class][i] = radstep;
                }
            }
            else if (ev_class == evFLOOD)
            {
                snew(evStepList[ev_class], nvecs);

                /* Are we doing constant force flooding? In that case, we read in
                 * the fproj values from the command line */
                if (opt2parg_bSet("-constF", NPA, pa))
                {
                    evStepList[ev_class] = scan_vecparams(opt2parg_str("-constF", NPA, pa), "-constF", nvecs);
                }
            }
            else
            {
            };   /*to avoid ambiguity   */
        }
        else     /* if there are no eigenvectors for this option set list to zero */
        {
            listen[ev_class] = NULL;
            snew(listen[ev_class], 1);
            listen[ev_class][0] = 0;
        }
    }

    /* print the interpreted list of eigenvectors - to give some feedback*/
    for (ev_class = 0; ev_class < evNr; ++ev_class)
    {
        printf("Eigenvector list %7s consists of the indices: ", evOptions[ev_class]);
        i = 0;
        while (listen[ev_class][i])
        {
            printf("%d ", listen[ev_class][i++]);
        }
        printf("\n");
    }

    EigvecFile = NULL;
    EigvecFile = opt2fn("-f", NFILE, fnm);

    /*read eigenvectors from eigvec.trr*/
    read_eigenvectors(EigvecFile, &nav, &bFit1,
                      &xref1, &edi_params.fitmas, &xav1, &edi_params.pcamas, &nvec1, &eignr1, &eigvec1, &eigval1);

    bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm),
                         title, &top, &ePBC, &xtop, NULL, topbox, 0);
    atoms = &top.atoms;


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


    if (xref1 == NULL)
    {
        if (bFit1)
        {
            /* if g_covar used different coordinate groups to fit and to do the PCA */
            printf("\nNote: the structure in %s should be the same\n"
                   "      as the one used for the fit in g_covar\n", ftp2fn(efTPS, NFILE, fnm));
            printf("\nSelect the index group that was used for the least squares fit in g_covar\n");
        }
        else
        {
            printf("\nNote: Apparently no fitting was done in g_covar.\n"
                   "      However, you need to select a reference group for fitting in mdrun\n");
        }
        get_index(atoms, indexfile, 1, &nfit, &ifit, &grpname);
        snew(xref1, nfit);
        for (i = 0; i < nfit; i++)
        {
            copy_rvec(xtop[ifit[i]], xref1[i]);
        }
    }
    else
    {
        nfit = nav;
        ifit = index;
    }

    if (opt2parg_bSet("-constF", NPA, pa))
    {
        /* Constant force flooding is special: Most of the normal flooding
         * options are not needed. */
        edi_params.flood.bConstForce = TRUE;
    }
    else
    {
        /* For normal flooding read eigenvalues and store them in evSteplist[evFLOOD] */

        if (listen[evFLOOD][0] != 0)
        {
            read_eigenvalues(listen[evFLOOD], opt2fn("-eig", NFILE, fnm), evStepList[evFLOOD], bHesse, kB*T);
        }

        edi_params.flood.tau       = tau;
        edi_params.flood.deltaF0   = deltaF0;
        edi_params.flood.deltaF    = deltaF;
        edi_params.presteps        = eqSteps;
        edi_params.flood.kT        = kB*T;
        edi_params.flood.bHarmonic = bHarmonic;
        if (bRestrain)
        {
            /* Trick: invert sign of Efl and alpha2 then this will give the same sign in the exponential and inverted sign outside */
            edi_params.flood.constEfl = -constEfl;
            edi_params.flood.alpha2   = -sqr(alpha);
        }
        else
        {
            edi_params.flood.constEfl = constEfl;
            edi_params.flood.alpha2   = sqr(alpha);
        }
    }

    edi_params.ned = nav;

    /*number of system atoms  */
    edi_params.nini = atoms->nr;


    /*store reference and average structure in edi_params*/
    make_t_edx(&edi_params.sref, nfit, xref1, ifit );
    make_t_edx(&edi_params.sav, nav, xav1, index);


    /* Store target positions in edi_params */
    if (opt2bSet("-tar", NFILE, fnm))
    {
        if (0 != listen[evFLOOD][0])
        {
            fprintf(stderr, "\nNote: Providing a TARGET structure has no effect when using flooding.\n"
                    "      You may want to use -ori to define the flooding potential center.\n\n");
        }
        get_structure(atoms, indexfile, TargetFile, &edi_params.star, nfit, ifit, nav, index);
    }
    else
    {
        make_t_edx(&edi_params.star, 0, NULL, index);
    }

    /* Store origin positions */
    if (opt2bSet("-ori", NFILE, fnm))
    {
        get_structure(atoms, indexfile, OriginFile, &edi_params.sori, nfit, ifit, nav, index);
    }
    else
    {
        make_t_edx(&edi_params.sori, 0, NULL, index);
    }

    /* Write edi-file */
    write_the_whole_thing(gmx_ffopen(EdiFile, "w"), &edi_params, eigvec1, nvec1, listen, evStepList);

    return 0;
}