コード例 #1
0
static void predict_shells(FILE *fplog, rvec x[], rvec v[], real dt,
                           int ns, t_shell s[],
                           real mass[], gmx_mtop_t *mtop, gmx_bool bInit)
{
    int                   i, m, s1, n1, n2, n3;
    real                  dt_1, dt_2, dt_3, fudge, tm, m1, m2, m3;
    rvec                 *ptr;
    gmx_mtop_atomlookup_t alook = NULL;
    t_atom               *atom;

    if (mass == NULL)
    {
        alook = gmx_mtop_atomlookup_init(mtop);
    }

    /* We introduce a fudge factor for performance reasons: with this choice
     * the initial force on the shells is about a factor of two lower than
     * without
     */
    fudge = 1.0;

    if (bInit)
    {
        if (fplog)
        {
            fprintf(fplog, "RELAX: Using prediction for initial shell placement\n");
        }
        ptr  = x;
        dt_1 = 1;
    }
    else
    {
        ptr  = v;
        dt_1 = fudge*dt;
    }

    for (i = 0; (i < ns); i++)
    {
        s1 = s[i].shell;
        if (bInit)
        {
            clear_rvec(x[s1]);
        }
        switch (s[i].nnucl)
        {
            case 1:
                n1 = s[i].nucl1;
                for (m = 0; (m < DIM); m++)
                {
                    x[s1][m] += ptr[n1][m]*dt_1;
                }
                break;
            case 2:
                n1 = s[i].nucl1;
                n2 = s[i].nucl2;
                if (mass)
                {
                    m1 = mass[n1];
                    m2 = mass[n2];
                }
                else
                {
                    /* Not the correct masses with FE, but it is just a prediction... */
                    m1 = atom[n1].m;
                    m2 = atom[n2].m;
                }
                tm = dt_1/(m1+m2);
                for (m = 0; (m < DIM); m++)
                {
                    x[s1][m] += (m1*ptr[n1][m]+m2*ptr[n2][m])*tm;
                }
                break;
            case 3:
                n1 = s[i].nucl1;
                n2 = s[i].nucl2;
                n3 = s[i].nucl3;
                if (mass)
                {
                    m1 = mass[n1];
                    m2 = mass[n2];
                    m3 = mass[n3];
                }
                else
                {
                    /* Not the correct masses with FE, but it is just a prediction... */
                    gmx_mtop_atomnr_to_atom(alook, n1, &atom);
                    m1 = atom->m;
                    gmx_mtop_atomnr_to_atom(alook, n2, &atom);
                    m2 = atom->m;
                    gmx_mtop_atomnr_to_atom(alook, n3, &atom);
                    m3 = atom->m;
                }
                tm = dt_1/(m1+m2+m3);
                for (m = 0; (m < DIM); m++)
                {
                    x[s1][m] += (m1*ptr[n1][m]+m2*ptr[n2][m]+m3*ptr[n3][m])*tm;
                }
                break;
            default:
                gmx_fatal(FARGS, "Shell %d has %d nuclei!", i, s[i].nnucl);
        }
    }

    if (mass == NULL)
    {
        gmx_mtop_atomlookup_destroy(alook);
    }
}
コード例 #2
0
ファイル: mdatoms.cpp プロジェクト: tanigawa/gromacs
void atoms2md(const gmx_mtop_t *mtop, const t_inputrec *ir,
              int nindex, const int *index,
              int homenr,
              t_mdatoms *md)
{
    gmx_bool              bLJPME;
    gmx_mtop_atomlookup_t alook;
    int                   i;
    const t_grpopts      *opts;
    const gmx_groups_t   *groups;
    int                   nthreads gmx_unused;
    const real            oneOverSix = 1.0 / 6.0;

    bLJPME = EVDW_PME(ir->vdwtype);

    opts = &ir->opts;

    groups = &mtop->groups;

    /* Index==NULL indicates no DD (unless we have a DD node with no
     * atoms), so also check for homenr. This should be
     * signaled properly with an extra parameter or nindex==-1.
     */
    if (index == NULL && (homenr > 0))
    {
        md->nr = mtop->natoms;
    }
    else
    {
        md->nr = nindex;
    }

    if (md->nr > md->nalloc)
    {
        md->nalloc = over_alloc_dd(md->nr);

        if (md->nMassPerturbed)
        {
            srenew(md->massA, md->nalloc);
            srenew(md->massB, md->nalloc);
        }
        srenew(md->massT, md->nalloc);
        srenew(md->invmass, md->nalloc);
        srenew(md->chargeA, md->nalloc);
        srenew(md->typeA, md->nalloc);
        if (md->nPerturbed)
        {
            srenew(md->chargeB, md->nalloc);
            srenew(md->typeB, md->nalloc);
        }
        if (bLJPME)
        {
            srenew(md->sqrt_c6A, md->nalloc);
            srenew(md->sigmaA, md->nalloc);
            srenew(md->sigma3A, md->nalloc);
            if (md->nPerturbed)
            {
                srenew(md->sqrt_c6B, md->nalloc);
                srenew(md->sigmaB, md->nalloc);
                srenew(md->sigma3B, md->nalloc);
            }
        }
        srenew(md->ptype, md->nalloc);
        if (opts->ngtc > 1)
        {
            srenew(md->cTC, md->nalloc);
            /* We always copy cTC with domain decomposition */
        }
        srenew(md->cENER, md->nalloc);
        if (opts->ngacc > 1)
        {
            srenew(md->cACC, md->nalloc);
        }
        if (opts->nFreeze &&
            (opts->ngfrz > 1 ||
             opts->nFreeze[0][XX] || opts->nFreeze[0][YY] || opts->nFreeze[0][ZZ]))
        {
            srenew(md->cFREEZE, md->nalloc);
        }
        if (md->bVCMgrps)
        {
            srenew(md->cVCM, md->nalloc);
        }
        if (md->bOrires)
        {
            srenew(md->cORF, md->nalloc);
        }
        if (md->nPerturbed)
        {
            srenew(md->bPerturbed, md->nalloc);
        }

        /* Note that these user t_mdatoms array pointers are NULL
         * when there is only one group present.
         * Therefore, when adding code, the user should use something like:
         * gprnrU1 = (md->cU1==NULL ? 0 : md->cU1[localatindex])
         */
        if (mtop->groups.grpnr[egcUser1] != NULL)
        {
            srenew(md->cU1, md->nalloc);
        }
        if (mtop->groups.grpnr[egcUser2] != NULL)
        {
            srenew(md->cU2, md->nalloc);
        }

        if (ir->bQMMM)
        {
            srenew(md->bQM, md->nalloc);
        }
        if (ir->bAdress)
        {
            srenew(md->wf, md->nalloc);
            srenew(md->tf_table_index, md->nalloc);
        }
    }

    alook = gmx_mtop_atomlookup_init(mtop);

    // cppcheck-suppress unreadVariable
    nthreads = gmx_omp_nthreads_get(emntDefault);
#pragma omp parallel for num_threads(nthreads) schedule(static)
    for (i = 0; i < md->nr; i++)
    {
        try
        {
            int      g, ag;
            real     mA, mB, fac;
            real     c6, c12;
            t_atom  *atom;

            if (index == NULL)
            {
                ag = i;
            }
            else
            {
                ag   = index[i];
            }
            gmx_mtop_atomnr_to_atom(alook, ag, &atom);

            if (md->cFREEZE)
            {
                md->cFREEZE[i] = ggrpnr(groups, egcFREEZE, ag);
            }
            if (EI_ENERGY_MINIMIZATION(ir->eI))
            {
                /* Displacement is proportional to F, masses used for constraints */
                mA = 1.0;
                mB = 1.0;
            }
            else if (ir->eI == eiBD)
            {
                /* With BD the physical masses are irrelevant.
                 * To keep the code simple we use most of the normal MD code path
                 * for BD. Thus for constraining the masses should be proportional
                 * to the friction coefficient. We set the absolute value such that
                 * m/2<(dx/dt)^2> = m/2*2kT/fric*dt = kT/2 => m=fric*dt/2
                 * Then if we set the (meaningless) velocity to v=dx/dt, we get the
                 * correct kinetic energy and temperature using the usual code path.
                 * Thus with BD v*dt will give the displacement and the reported
                 * temperature can signal bad integration (too large time step).
                 */
                if (ir->bd_fric > 0)
                {
                    mA = 0.5*ir->bd_fric*ir->delta_t;
                    mB = 0.5*ir->bd_fric*ir->delta_t;
                }
                else
                {
                    /* The friction coefficient is mass/tau_t */
                    fac = ir->delta_t/opts->tau_t[md->cTC ? groups->grpnr[egcTC][ag] : 0];
                    mA  = 0.5*atom->m*fac;
                    mB  = 0.5*atom->mB*fac;
                }
            }
            else
            {
                mA = atom->m;
                mB = atom->mB;
            }
            if (md->nMassPerturbed)
            {
                md->massA[i]  = mA;
                md->massB[i]  = mB;
            }
            md->massT[i]    = mA;
            if (mA == 0.0)
            {
                md->invmass[i]    = 0;
            }
            else if (md->cFREEZE)
            {
                g = md->cFREEZE[i];
                if (opts->nFreeze[g][XX] && opts->nFreeze[g][YY] && opts->nFreeze[g][ZZ])
                {
                    /* Set the mass of completely frozen particles to ALMOST_ZERO iso 0
                     * to avoid div by zero in lincs or shake.
                     * Note that constraints can still move a partially frozen particle.
                     */
                    md->invmass[i]  = ALMOST_ZERO;
                }
                else
                {
                    md->invmass[i]  = 1.0/mA;
                }
            }
            else
            {
                md->invmass[i]    = 1.0/mA;
            }
            md->chargeA[i]      = atom->q;
            md->typeA[i]        = atom->type;
            if (bLJPME)
            {
                c6                = mtop->ffparams.iparams[atom->type*(mtop->ffparams.atnr+1)].lj.c6;
                c12               = mtop->ffparams.iparams[atom->type*(mtop->ffparams.atnr+1)].lj.c12;
                md->sqrt_c6A[i]   = sqrt(c6);
                if (c6 == 0.0 || c12 == 0)
                {
                    md->sigmaA[i] = 1.0;
                }
                else
                {
                    md->sigmaA[i] = pow(c12/c6, oneOverSix);
                }
                md->sigma3A[i]    = 1/(md->sigmaA[i]*md->sigmaA[i]*md->sigmaA[i]);
            }
            if (md->nPerturbed)
            {
                md->bPerturbed[i] = PERTURBED(*atom);
                md->chargeB[i]    = atom->qB;
                md->typeB[i]      = atom->typeB;
                if (bLJPME)
                {
                    c6                = mtop->ffparams.iparams[atom->typeB*(mtop->ffparams.atnr+1)].lj.c6;
                    c12               = mtop->ffparams.iparams[atom->typeB*(mtop->ffparams.atnr+1)].lj.c12;
                    md->sqrt_c6B[i]   = sqrt(c6);
                    if (c6 == 0.0 || c12 == 0)
                    {
                        md->sigmaB[i] = 1.0;
                    }
                    else
                    {
                        md->sigmaB[i] = pow(c12/c6, oneOverSix);
                    }
                    md->sigma3B[i]    = 1/(md->sigmaB[i]*md->sigmaB[i]*md->sigmaB[i]);
                }
            }
            md->ptype[i]    = atom->ptype;
            if (md->cTC)
            {
                md->cTC[i]    = groups->grpnr[egcTC][ag];
            }
            md->cENER[i]    =
                (groups->grpnr[egcENER] ? groups->grpnr[egcENER][ag] : 0);
            if (md->cACC)
            {
                md->cACC[i]   = groups->grpnr[egcACC][ag];
            }
            if (md->cVCM)
            {
                md->cVCM[i]       = groups->grpnr[egcVCM][ag];
            }
            if (md->cORF)
            {
                md->cORF[i]       = groups->grpnr[egcORFIT][ag];
            }

            if (md->cU1)
            {
                md->cU1[i]        = groups->grpnr[egcUser1][ag];
            }
            if (md->cU2)
            {
                md->cU2[i]        = groups->grpnr[egcUser2][ag];
            }

            if (ir->bQMMM)
            {
                if (groups->grpnr[egcQMMM] == 0 ||
                    groups->grpnr[egcQMMM][ag] < groups->grps[egcQMMM].nr-1)
                {
                    md->bQM[i]      = TRUE;
                }
                else
                {
                    md->bQM[i]      = FALSE;
                }
            }
            /* Initialize AdResS weighting functions to adressw */
            if (ir->bAdress)
            {
                md->wf[i]           = 1.0;
                /* if no tf table groups specified, use default table */
                md->tf_table_index[i] = DEFAULT_TF_TABLE;
                if (ir->adress->n_tf_grps > 0)
                {
                    /* if tf table groups specified, tf is only applied to thoose energy groups*/
                    md->tf_table_index[i] = NO_TF_TABLE;
                    /* check wether atom is in one of the relevant energy groups and assign a table index */
                    for (g = 0; g < ir->adress->n_tf_grps; g++)
                    {
                        if (md->cENER[i] == ir->adress->tf_table_index[g])
                        {
                            md->tf_table_index[i] = g;
                        }
                    }
                }
            }
        }
        GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
    }

    gmx_mtop_atomlookup_destroy(alook);

    md->homenr = homenr;
    md->lambda = 0;
}
コード例 #3
0
ファイル: gmx_clustsize.cpp プロジェクト: mpharrigan/gromacs
static void clust_size(const char *ndx, const char *trx, const char *xpm,
                       const char *xpmw, const char *ncl, const char *acl,
                       const char *mcl, const char *histo, const char *tempf,
                       const char *mcn, gmx_bool bMol, gmx_bool bPBC, const char *tpr,
                       real cut, int nskip, int nlevels,
                       t_rgb rmid, t_rgb rhi, int ndf,
                       const output_env_t oenv)
{
    FILE                 *fp, *gp, *hp, *tp;
    atom_id              *index = NULL;
    int                   nindex, natoms;
    t_trxstatus          *status;
    rvec                 *x = NULL, *v = NULL, dx;
    t_pbc                 pbc;
    char                 *gname;
    char                  timebuf[32];
    gmx_bool              bSame, bTPRwarn = TRUE;
    /* Topology stuff */
    t_trxframe            fr;
    t_tpxheader           tpxh;
    gmx_mtop_t           *mtop = NULL;
    int                   ePBC = -1;
    t_block              *mols = NULL;
    gmx_mtop_atomlookup_t alook;
    t_atom               *atom;
    int                   version, generation, ii, jj;
    real                  temp, tfac;
    /* Cluster size distribution (matrix) */
    real                **cs_dist = NULL;
    real                  tf, dx2, cut2, *t_x = NULL, *t_y, cmid, cmax, cav, ekin;
    int                   i, j, k, ai, aj, ci, cj, nframe, nclust, n_x, max_size = 0;
    int                  *clust_index, *clust_size, max_clust_size, max_clust_ind, nav, nhisto;
    t_rgb                 rlo = { 1.0, 1.0, 1.0 };

    clear_trxframe(&fr, TRUE);
    sprintf(timebuf, "Time (%s)", output_env_get_time_unit(oenv));
    tf     = output_env_get_time_factor(oenv);
    fp     = xvgropen(ncl, "Number of clusters", timebuf, "N", oenv);
    gp     = xvgropen(acl, "Average cluster size", timebuf, "#molecules", oenv);
    hp     = xvgropen(mcl, "Max cluster size", timebuf, "#molecules", oenv);
    tp     = xvgropen(tempf, "Temperature of largest cluster", timebuf, "T (K)",
                      oenv);

    if (!read_first_frame(oenv, &status, trx, &fr, TRX_NEED_X | TRX_READ_V))
    {
        gmx_file(trx);
    }

    natoms = fr.natoms;
    x      = fr.x;

    if (tpr)
    {
        snew(mtop, 1);
        read_tpxheader(tpr, &tpxh, TRUE, &version, &generation);
        if (tpxh.natoms != natoms)
        {
            gmx_fatal(FARGS, "tpr (%d atoms) and trajectory (%d atoms) do not match!",
                      tpxh.natoms, natoms);
        }
        ePBC = read_tpx(tpr, NULL, NULL, &natoms, NULL, NULL, mtop);
    }
    if (ndf <= -1)
    {
        tfac = 1;
    }
    else
    {
        tfac = ndf/(3.0*natoms);
    }

    if (bMol)
    {
        if (ndx)
        {
            printf("Using molecules rather than atoms. Not reading index file %s\n",
                   ndx);
        }
        GMX_RELEASE_ASSERT(mtop != NULL, "Trying to access mtop->mols from NULL mtop pointer");
        mols = &(mtop->mols);

        /* Make dummy index */
        nindex = mols->nr;
        snew(index, nindex);
        for (i = 0; (i < nindex); i++)
        {
            index[i] = i;
        }
        gname = gmx_strdup("mols");
    }
    else
    {
        rd_index(ndx, 1, &nindex, &index, &gname);
    }

    alook = gmx_mtop_atomlookup_init(mtop);

    snew(clust_index, nindex);
    snew(clust_size, nindex);
    cut2   = cut*cut;
    nframe = 0;
    n_x    = 0;
    snew(t_y, nindex);
    for (i = 0; (i < nindex); i++)
    {
        t_y[i] = i+1;
    }
    max_clust_size = 1;
    max_clust_ind  = -1;
    do
    {
        if ((nskip == 0) || ((nskip > 0) && ((nframe % nskip) == 0)))
        {
            if (bPBC)
            {
                set_pbc(&pbc, ePBC, fr.box);
            }
            max_clust_size = 1;
            max_clust_ind  = -1;

            /* Put all atoms/molecules in their own cluster, with size 1 */
            for (i = 0; (i < nindex); i++)
            {
                /* Cluster index is indexed with atom index number */
                clust_index[i] = i;
                /* Cluster size is indexed with cluster number */
                clust_size[i]  = 1;
            }

            /* Loop over atoms */
            for (i = 0; (i < nindex); i++)
            {
                ai = index[i];
                ci = clust_index[i];

                /* Loop over atoms (only half a matrix) */
                for (j = i+1; (j < nindex); j++)
                {
                    cj = clust_index[j];

                    /* If they are not in the same cluster already */
                    if (ci != cj)
                    {
                        aj = index[j];

                        /* Compute distance */
                        if (bMol)
                        {
                            GMX_RELEASE_ASSERT(mols != NULL, "Cannot access index[] from NULL mols pointer");
                            bSame = FALSE;
                            for (ii = mols->index[ai]; !bSame && (ii < mols->index[ai+1]); ii++)
                            {
                                for (jj = mols->index[aj]; !bSame && (jj < mols->index[aj+1]); jj++)
                                {
                                    if (bPBC)
                                    {
                                        pbc_dx(&pbc, x[ii], x[jj], dx);
                                    }
                                    else
                                    {
                                        rvec_sub(x[ii], x[jj], dx);
                                    }
                                    dx2   = iprod(dx, dx);
                                    bSame = (dx2 < cut2);
                                }
                            }
                        }
                        else
                        {
                            if (bPBC)
                            {
                                pbc_dx(&pbc, x[ai], x[aj], dx);
                            }
                            else
                            {
                                rvec_sub(x[ai], x[aj], dx);
                            }
                            dx2   = iprod(dx, dx);
                            bSame = (dx2 < cut2);
                        }
                        /* If distance less than cut-off */
                        if (bSame)
                        {
                            /* Merge clusters: check for all atoms whether they are in
                             * cluster cj and if so, put them in ci
                             */
                            for (k = 0; (k < nindex); k++)
                            {
                                if (clust_index[k] == cj)
                                {
                                    if (clust_size[cj] <= 0)
                                    {
                                        gmx_fatal(FARGS, "negative cluster size %d for element %d",
                                                  clust_size[cj], cj);
                                    }
                                    clust_size[cj]--;
                                    clust_index[k] = ci;
                                    clust_size[ci]++;
                                }
                            }
                        }
                    }
                }
            }
            n_x++;
            srenew(t_x, n_x);
            t_x[n_x-1] = fr.time*tf;
            srenew(cs_dist, n_x);
            snew(cs_dist[n_x-1], nindex);
            nclust = 0;
            cav    = 0;
            nav    = 0;
            for (i = 0; (i < nindex); i++)
            {
                ci = clust_size[i];
                if (ci > max_clust_size)
                {
                    max_clust_size = ci;
                    max_clust_ind  = i;
                }
                if (ci > 0)
                {
                    nclust++;
                    cs_dist[n_x-1][ci-1] += 1.0;
                    max_size              = std::max(max_size, ci);
                    if (ci > 1)
                    {
                        cav += ci;
                        nav++;
                    }
                }
            }
            fprintf(fp, "%14.6e  %10d\n", fr.time, nclust);
            if (nav > 0)
            {
                fprintf(gp, "%14.6e  %10.3f\n", fr.time, cav/nav);
            }
            fprintf(hp, "%14.6e  %10d\n", fr.time, max_clust_size);
        }
        /* Analyse velocities, if present */
        if (fr.bV)
        {
            if (!tpr)
            {
                if (bTPRwarn)
                {
                    printf("You need a [REF].tpr[ref] file to analyse temperatures\n");
                    bTPRwarn = FALSE;
                }
            }
            else
            {
                v = fr.v;
                /* Loop over clusters and for each cluster compute 1/2 m v^2 */
                if (max_clust_ind >= 0)
                {
                    ekin = 0;
                    for (i = 0; (i < nindex); i++)
                    {
                        if (clust_index[i] == max_clust_ind)
                        {
                            ai    = index[i];
                            gmx_mtop_atomnr_to_atom(alook, ai, &atom);
                            ekin += 0.5*atom->m*iprod(v[ai], v[ai]);
                        }
                    }
                    temp = (ekin*2.0)/(3.0*tfac*max_clust_size*BOLTZ);
                    fprintf(tp, "%10.3f  %10.3f\n", fr.time, temp);
                }
            }
        }
        nframe++;
    }
    while (read_next_frame(oenv, status, &fr));
    close_trx(status);
    xvgrclose(fp);
    xvgrclose(gp);
    xvgrclose(hp);
    xvgrclose(tp);

    gmx_mtop_atomlookup_destroy(alook);

    if (max_clust_ind >= 0)
    {
        fp = gmx_ffopen(mcn, "w");
        fprintf(fp, "[ max_clust ]\n");
        for (i = 0; (i < nindex); i++)
        {
            if (clust_index[i] == max_clust_ind)
            {
                if (bMol)
                {
                    GMX_RELEASE_ASSERT(mols != NULL, "Cannot access index[] from NULL mols pointer");
                    for (j = mols->index[i]; (j < mols->index[i+1]); j++)
                    {
                        fprintf(fp, "%d\n", j+1);
                    }
                }
                else
                {
                    fprintf(fp, "%d\n", index[i]+1);
                }
            }
        }
        gmx_ffclose(fp);
    }

    /* Print the real distribution cluster-size/numer, averaged over the trajectory. */
    fp     = xvgropen(histo, "Cluster size distribution", "Cluster size", "()", oenv);
    nhisto = 0;
    fprintf(fp, "%5d  %8.3f\n", 0, 0.0);
    for (j = 0; (j < max_size); j++)
    {
        real nelem = 0;
        for (i = 0; (i < n_x); i++)
        {
            nelem += cs_dist[i][j];
        }
        fprintf(fp, "%5d  %8.3f\n", j+1, nelem/n_x);
        nhisto += static_cast<int>((j+1)*nelem/n_x);
    }
    fprintf(fp, "%5d  %8.3f\n", j+1, 0.0);
    xvgrclose(fp);

    fprintf(stderr, "Total number of atoms in clusters =  %d\n", nhisto);

    /* Look for the smallest entry that is not zero
     * This will make that zero is white, and not zero is coloured.
     */
    cmid = 100.0;
    cmax = 0.0;
    for (i = 0; (i < n_x); i++)
    {
        for (j = 0; (j < max_size); j++)
        {
            if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid))
            {
                cmid = cs_dist[i][j];
            }
            cmax = std::max(cs_dist[i][j], cmax);
        }
    }
    fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size);
    cmid = 1;
    fp   = gmx_ffopen(xpm, "w");
    write_xpm3(fp, 0, "Cluster size distribution", "# clusters", timebuf, "Size",
               n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax,
               rlo, rmid, rhi, &nlevels);
    gmx_ffclose(fp);
    cmid = 100.0;
    cmax = 0.0;
    for (i = 0; (i < n_x); i++)
    {
        for (j = 0; (j < max_size); j++)
        {
            cs_dist[i][j] *= (j+1);
            if ((cs_dist[i][j] > 0) && (cs_dist[i][j] < cmid))
            {
                cmid = cs_dist[i][j];
            }
            cmax = std::max(cs_dist[i][j], cmax);
        }
    }
    fprintf(stderr, "cmid: %g, cmax: %g, max_size: %d\n", cmid, cmax, max_size);
    fp = gmx_ffopen(xpmw, "w");
    write_xpm3(fp, 0, "Weighted cluster size distribution", "Fraction", timebuf,
               "Size", n_x, max_size, t_x, t_y, cs_dist, 0, cmid, cmax,
               rlo, rmid, rhi, &nlevels);
    gmx_ffclose(fp);

    sfree(clust_index);
    sfree(clust_size);
    sfree(index);
}
コード例 #4
0
/*! \brief Looks up constraint for the local atoms */
static void atoms_to_constraints(gmx_domdec_t *dd,
                                 const gmx_mtop_t *mtop,
                                 const int *cginfo,
                                 const t_blocka *at2con_mt, int nrec,
                                 t_ilist *ilc_local,
                                 ind_req_t *ireq)
{
    const t_blocka             *at2con;
    gmx_ga2la_t                *ga2la;
    gmx_mtop_atomlookup_t       alook;
    int                         ncon1;
    gmx_molblock_t             *molb;
    t_iatom                    *ia1, *ia2, *iap;
    int                         nhome, cg, a, a_gl, a_mol, a_loc, b_lo, offset, mb, molnr, b_mol, i, con, con_offset;
    gmx_domdec_constraints_t   *dc;
    gmx_domdec_specat_comm_t   *dcc;

    dc  = dd->constraints;
    dcc = dd->constraint_comm;

    ga2la  = dd->ga2la;

    alook = gmx_mtop_atomlookup_init(mtop);

    nhome = 0;
    for (cg = 0; cg < dd->ncg_home; cg++)
    {
        if (GET_CGINFO_CONSTR(cginfo[cg]))
        {
            for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++)
            {
                a_gl = dd->gatindex[a];

                gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol);
                molb = &mtop->molblock[mb];

                ncon1 = mtop->moltype[molb->type].ilist[F_CONSTR].nr/NRAL(F_SETTLE);

                ia1 = mtop->moltype[molb->type].ilist[F_CONSTR].iatoms;
                ia2 = mtop->moltype[molb->type].ilist[F_CONSTRNC].iatoms;

                /* Calculate the global constraint number offset for the molecule.
                 * This is only required for the global index to make sure
                 * that we use each constraint only once.
                 */
                con_offset =
                    dc->molb_con_offset[mb] + molnr*dc->molb_ncon_mol[mb];

                /* The global atom number offset for this molecule */
                offset = a_gl - a_mol;
                at2con = &at2con_mt[molb->type];
                for (i = at2con->index[a_mol]; i < at2con->index[a_mol+1]; i++)
                {
                    con = at2con->a[i];
                    iap = constr_iatomptr(ncon1, ia1, ia2, con);
                    if (a_mol == iap[1])
                    {
                        b_mol = iap[2];
                    }
                    else
                    {
                        b_mol = iap[1];
                    }
                    if (ga2la_get_home(ga2la, offset+b_mol, &a_loc))
                    {
                        /* Add this fully home constraint at the first atom */
                        if (a_mol < b_mol)
                        {
                            if (dc->ncon+1 > dc->con_nalloc)
                            {
                                dc->con_nalloc = over_alloc_large(dc->ncon+1);
                                srenew(dc->con_gl, dc->con_nalloc);
                                srenew(dc->con_nlocat, dc->con_nalloc);
                            }
                            dc->con_gl[dc->ncon]     = con_offset + con;
                            dc->con_nlocat[dc->ncon] = 2;
                            if (ilc_local->nr + 3 > ilc_local->nalloc)
                            {
                                ilc_local->nalloc = over_alloc_dd(ilc_local->nr + 3);
                                srenew(ilc_local->iatoms, ilc_local->nalloc);
                            }
                            b_lo = a_loc;
                            ilc_local->iatoms[ilc_local->nr++] = iap[0];
                            ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? a    : b_lo);
                            ilc_local->iatoms[ilc_local->nr++] = (a_gl == iap[1] ? b_lo : a   );
                            dc->ncon++;
                            nhome++;
                        }
                    }
                    else
                    {
                        /* We need the nrec constraints coupled to this constraint,
                         * so we need to walk out of the home cell by nrec+1 atoms,
                         * since already atom bg is not locally present.
                         * Therefore we call walk_out with nrec recursions to go
                         * after this first call.
                         */
                        walk_out(con, con_offset, b_mol, offset, nrec,
                                 ncon1, ia1, ia2, at2con,
                                 dd->ga2la, TRUE, dc, dcc, ilc_local, ireq);
                    }
                }
            }
        }
    }

    gmx_mtop_atomlookup_destroy(alook);

    if (debug)
    {
        fprintf(debug,
                "Constraints: home %3d border %3d atoms: %3d\n",
                nhome, dc->ncon-nhome,
                dd->constraint_comm ? ireq->n : 0);
    }
}
コード例 #5
0
/*! \brief Looks up SETTLE constraints for a range of charge-groups */
static void atoms_to_settles(gmx_domdec_t *dd,
                             const gmx_mtop_t *mtop,
                             const int *cginfo,
                             const int **at2settle_mt,
                             int cg_start, int cg_end,
                             t_ilist *ils_local,
                             ind_req_t *ireq)
{
    gmx_ga2la_t            *ga2la;
    gmx_mtop_atomlookup_t   alook;
    int                     settle;
    int                     nral, sa;
    int                     cg, a, a_gl, a_glsa, a_gls[3], a_locs[3];
    int                     mb, molnr, a_mol, offset;
    const gmx_molblock_t   *molb;
    const t_iatom          *ia1;
    gmx_bool                a_home[3];
    int                     nlocal;
    gmx_bool                bAssign;

    ga2la  = dd->ga2la;

    alook = gmx_mtop_atomlookup_settle_init(mtop);

    nral = NRAL(F_SETTLE);

    for (cg = cg_start; cg < cg_end; cg++)
    {
        if (GET_CGINFO_SETTLE(cginfo[cg]))
        {
            for (a = dd->cgindex[cg]; a < dd->cgindex[cg+1]; a++)
            {
                a_gl = dd->gatindex[a];

                gmx_mtop_atomnr_to_molblock_ind(alook, a_gl, &mb, &molnr, &a_mol);
                molb = &mtop->molblock[mb];

                settle = at2settle_mt[molb->type][a_mol];

                if (settle >= 0)
                {
                    offset = a_gl - a_mol;

                    ia1 = mtop->moltype[molb->type].ilist[F_SETTLE].iatoms;

                    bAssign = FALSE;
                    nlocal  = 0;
                    for (sa = 0; sa < nral; sa++)
                    {
                        a_glsa     = offset + ia1[settle*(1+nral)+1+sa];
                        a_gls[sa]  = a_glsa;
                        a_home[sa] = ga2la_get_home(ga2la, a_glsa, &a_locs[sa]);
                        if (a_home[sa])
                        {
                            if (nlocal == 0 && a_gl == a_glsa)
                            {
                                bAssign = TRUE;
                            }
                            nlocal++;
                        }
                    }

                    if (bAssign)
                    {
                        if (ils_local->nr+1+nral > ils_local->nalloc)
                        {
                            ils_local->nalloc = over_alloc_dd(ils_local->nr+1+nral);
                            srenew(ils_local->iatoms, ils_local->nalloc);
                        }

                        ils_local->iatoms[ils_local->nr++] = ia1[settle*4];

                        for (sa = 0; sa < nral; sa++)
                        {
                            if (ga2la_get_home(ga2la, a_gls[sa], &a_locs[sa]))
                            {
                                ils_local->iatoms[ils_local->nr++] = a_locs[sa];
                            }
                            else
                            {
                                ils_local->iatoms[ils_local->nr++] = -a_gls[sa] - 1;
                                /* Add this non-home atom to the list */
                                if (ireq->n+1 > ireq->nalloc)
                                {
                                    ireq->nalloc = over_alloc_large(ireq->n+1);
                                    srenew(ireq->ind, ireq->nalloc);
                                }
                                ireq->ind[ireq->n++] = a_gls[sa];
                                /* A check on double atom requests is
                                 * not required for settle.
                                 */
                            }
                        }
                    }
                }
            }
        }
    }

    gmx_mtop_atomlookup_destroy(alook);
}
コード例 #6
0
ファイル: pull.c プロジェクト: exianshine/gromacs
static void init_pull_group_index(FILE *fplog, t_commrec *cr,
                                  int start, int end,
                                  int g, t_pull_group *pg, ivec pulldims,
                                  gmx_mtop_t *mtop, t_inputrec *ir, real lambda)
{
    int                   i, ii, d, nfrozen, ndim;
    real                  m, w, mbd;
    double                tmass, wmass, wwmass;
    gmx_bool              bDomDec;
    gmx_ga2la_t           ga2la = NULL;
    gmx_groups_t         *groups;
    gmx_mtop_atomlookup_t alook;
    t_atom               *atom;

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

    if (EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
    {
        /* There are no masses in the integrator.
         * But we still want to have the correct mass-weighted COMs.
         * So we store the real masses in the weights.
         * We do not set nweight, so these weights do not end up in the tpx file.
         */
        if (pg->nweight == 0)
        {
            snew(pg->weight, pg->nat);
        }
    }

    if (cr && PAR(cr))
    {
        pg->nat_loc    = 0;
        pg->nalloc_loc = 0;
        pg->ind_loc    = NULL;
        pg->weight_loc = NULL;
    }
    else
    {
        pg->nat_loc = pg->nat;
        pg->ind_loc = pg->ind;
        if (pg->epgrppbc == epgrppbcCOS)
        {
            snew(pg->weight_loc, pg->nat);
        }
        else
        {
            pg->weight_loc = pg->weight;
        }
    }

    groups = &mtop->groups;

    alook = gmx_mtop_atomlookup_init(mtop);

    nfrozen = 0;
    tmass   = 0;
    wmass   = 0;
    wwmass  = 0;
    for (i = 0; i < pg->nat; i++)
    {
        ii = pg->ind[i];
        gmx_mtop_atomnr_to_atom(alook, ii, &atom);
        if (cr && PAR(cr) && !bDomDec && ii >= start && ii < end)
        {
            pg->ind_loc[pg->nat_loc++] = ii;
        }
        if (ir->opts.nFreeze)
        {
            for (d = 0; d < DIM; d++)
            {
                if (pulldims[d] && ir->opts.nFreeze[ggrpnr(groups, egcFREEZE, ii)][d])
                {
                    nfrozen++;
                }
            }
        }
        if (ir->efep == efepNO)
        {
            m = atom->m;
        }
        else
        {
            m = (1 - lambda)*atom->m + lambda*atom->mB;
        }
        if (pg->nweight > 0)
        {
            w = pg->weight[i];
        }
        else
        {
            w = 1;
        }
        if (EI_ENERGY_MINIMIZATION(ir->eI))
        {
            /* Move the mass to the weight */
            w            *= m;
            m             = 1;
            pg->weight[i] = w;
        }
        else if (ir->eI == eiBD)
        {
            if (ir->bd_fric)
            {
                mbd = ir->bd_fric*ir->delta_t;
            }
            else
            {
                if (groups->grpnr[egcTC] == NULL)
                {
                    mbd = ir->delta_t/ir->opts.tau_t[0];
                }
                else
                {
                    mbd = ir->delta_t/ir->opts.tau_t[groups->grpnr[egcTC][ii]];
                }
            }
            w            *= m/mbd;
            m             = mbd;
            pg->weight[i] = w;
        }
        tmass  += m;
        wmass  += m*w;
        wwmass += m*w*w;
    }

    gmx_mtop_atomlookup_destroy(alook);

    if (wmass == 0)
    {
        gmx_fatal(FARGS, "The total%s mass of pull group %d is zero",
                  pg->weight ? " weighted" : "", g);
    }
    if (fplog)
    {
        fprintf(fplog,
                "Pull group %d: %5d atoms, mass %9.3f", g, pg->nat, tmass);
        if (pg->weight || EI_ENERGY_MINIMIZATION(ir->eI) || ir->eI == eiBD)
        {
            fprintf(fplog, ", weighted mass %9.3f", wmass*wmass/wwmass);
        }
        if (pg->epgrppbc == epgrppbcCOS)
        {
            fprintf(fplog, ", cosine weighting will be used");
        }
        fprintf(fplog, "\n");
    }

    if (nfrozen == 0)
    {
        /* A value > 0 signals not frozen, it is updated later */
        pg->invtm  = 1.0;
    }
    else
    {
        ndim = 0;
        for (d = 0; d < DIM; d++)
        {
            ndim += pulldims[d]*pg->nat;
        }
        if (fplog && nfrozen > 0 && nfrozen < ndim)
        {
            fprintf(fplog,
                    "\nWARNING: In pull group %d some, but not all of the degrees of freedom\n"
                    "         that are subject to pulling are frozen.\n"
                    "         For pulling the whole group will be frozen.\n\n",
                    g);
        }
        pg->invtm  = 0.0;
        pg->wscale = 1.0;
    }
}
コード例 #7
0
ファイル: qmmm.cpp プロジェクト: wangxubo0201/gromacs
void init_QMMMrec(t_commrec  *cr,
                  gmx_mtop_t *mtop,
                  t_inputrec *ir,
                  t_forcerec *fr)
{
    /* we put the atomsnumbers of atoms that belong to the QMMM group in
     * an array that will be copied later to QMMMrec->indexQM[..]. Also
     * it will be used to create an QMMMrec->bQMMM index array that
     * simply contains true/false for QM and MM (the other) atoms.
     */

    gmx_groups_t            *groups;
    int                     *qm_arr = NULL, vsite, ai, aj;
    int                      qm_max = 0, qm_nr = 0, i, j, jmax, k, l, nrvsite2 = 0;
    t_QMMMrec               *qr;
    t_MMrec                 *mm;
    t_iatom                 *iatoms;
    real                     c12au, c6au;
    gmx_mtop_atomloop_all_t  aloop;
    t_atom                  *atom;
    gmx_mtop_ilistloop_all_t iloop;
    int                      a_offset;
    t_ilist                 *ilist_mol;
    gmx_mtop_atomlookup_t    alook;

    c6au  = (HARTREE2KJ*AVOGADRO*gmx::power6(BOHR2NM));
    c12au = (HARTREE2KJ*AVOGADRO*gmx::power12(BOHR2NM));
    /* issue a fatal if the user wants to run with more than one node */
    if (PAR(cr))
    {
        gmx_fatal(FARGS, "QM/MM does not work in parallel, use a single rank instead\n");
    }

    /* Make a local copy of the QMMMrec */
    qr = fr->qr;

    /* bQMMM[..] is an array containing TRUE/FALSE for atoms that are
     * QM/not QM. We first set all elemenst at false. Afterwards we use
     * the qm_arr (=MMrec->indexQM) to changes the elements
     * corresponding to the QM atoms at TRUE.  */

    qr->QMMMscheme     = ir->QMMMscheme;

    /* we take the possibility into account that a user has
     * defined more than one QM group:
     */
    /* an ugly work-around in case there is only one group In this case
     * the whole system is treated as QM. Otherwise the second group is
     * always the rest of the total system and is treated as MM.
     */

    /* small problem if there is only QM.... so no MM */

    jmax = ir->opts.ngQM;

    if (qr->QMMMscheme == eQMMMschemeoniom)
    {
        qr->nrQMlayers = jmax;
    }
    else
    {
        qr->nrQMlayers = 1;
    }

    groups = &mtop->groups;

    /* there are jmax groups of QM atoms. In case of multiple QM groups
     * I assume that the users wants to do ONIOM. However, maybe it
     * should also be possible to define more than one QM subsystem with
     * independent neighbourlists. I have to think about
     * that.. 11-11-2003
     */
    snew(qr->qm, jmax);
    for (j = 0; j < jmax; j++)
    {
        /* new layer */
        aloop = gmx_mtop_atomloop_all_init(mtop);
        while (gmx_mtop_atomloop_all_next(aloop, &i, &atom))
        {
            if (qm_nr >= qm_max)
            {
                qm_max += 1000;
                srenew(qm_arr, qm_max);
            }
            if (ggrpnr(groups, egcQMMM, i) == j)
            {
                /* hack for tip4p */
                qm_arr[qm_nr++] = i;
            }
        }
        if (qr->QMMMscheme == eQMMMschemeoniom)
        {
            /* add the atoms to the bQMMM array
             */

            /* I assume that users specify the QM groups from small to
             * big(ger) in the mdp file
             */
            qr->qm[j] = mk_QMrec();
            /* we need to throw out link atoms that in the previous layer
             * existed to separate this QMlayer from the previous
             * QMlayer. We use the iatoms array in the idef for that
             * purpose. If all atoms defining the current Link Atom (Dummy2)
             * are part of the current QM layer it needs to be removed from
             * qm_arr[].  */

            iloop = gmx_mtop_ilistloop_all_init(mtop);
            while (gmx_mtop_ilistloop_all_next(iloop, &ilist_mol, &a_offset))
            {
                nrvsite2 = ilist_mol[F_VSITE2].nr;
                iatoms   = ilist_mol[F_VSITE2].iatoms;

                for (k = 0; k < nrvsite2; k += 4)
                {
                    vsite = a_offset + iatoms[k+1]; /* the vsite         */
                    ai    = a_offset + iatoms[k+2]; /* constructing atom */
                    aj    = a_offset + iatoms[k+3]; /* constructing atom */
                    if (ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, ai)
                            &&
                            ggrpnr(groups, egcQMMM, vsite) == ggrpnr(groups, egcQMMM, aj))
                    {
                        /* this dummy link atom needs to be removed from the qm_arr
                         * before making the QMrec of this layer!
                         */
                        for (i = 0; i < qm_nr; i++)
                        {
                            if (qm_arr[i] == vsite)
                            {
                                /* drop the element */
                                for (l = i; l < qm_nr; l++)
                                {
                                    qm_arr[l] = qm_arr[l+1];
                                }
                                qm_nr--;
                            }
                        }
                    }
                }
            }

            /* store QM atoms in this layer in the QMrec and initialise layer
             */
            init_QMrec(j, qr->qm[j], qm_nr, qm_arr, mtop, ir);

            /* we now store the LJ C6 and C12 parameters in QM rec in case
             * we need to do an optimization
             */
            if (qr->qm[j]->bOPT || qr->qm[j]->bTS)
            {
                for (i = 0; i < qm_nr; i++)
                {
                    /* nbfp now includes the 6.0/12.0 derivative prefactors */
                    qr->qm[j]->c6[i]  =  C6(fr->nbfp, mtop->ffparams.atnr, atom->type, atom->type)/c6au/6.0;
                    qr->qm[j]->c12[i] = C12(fr->nbfp, mtop->ffparams.atnr, atom->type, atom->type)/c12au/12.0;
                }
            }
            /* now we check for frontier QM atoms. These occur in pairs that
             * construct the vsite
             */
            iloop = gmx_mtop_ilistloop_all_init(mtop);
            while (gmx_mtop_ilistloop_all_next(iloop, &ilist_mol, &a_offset))
            {
                nrvsite2 = ilist_mol[F_VSITE2].nr;
                iatoms   = ilist_mol[F_VSITE2].iatoms;

                for (k = 0; k < nrvsite2; k += 4)
                {
                    vsite = a_offset + iatoms[k+1]; /* the vsite         */
                    ai    = a_offset + iatoms[k+2]; /* constructing atom */
                    aj    = a_offset + iatoms[k+3]; /* constructing atom */
                    if (ggrpnr(groups, egcQMMM, ai) < (groups->grps[egcQMMM].nr-1) &&
                            (ggrpnr(groups, egcQMMM, aj) >= (groups->grps[egcQMMM].nr-1)))
                    {
                        /* mark ai as frontier atom */
                        for (i = 0; i < qm_nr; i++)
                        {
                            if ( (qm_arr[i] == ai) || (qm_arr[i] == vsite) )
                            {
                                qr->qm[j]->frontatoms[i] = TRUE;
                            }
                        }
                    }
                    else if (ggrpnr(groups, egcQMMM, aj) < (groups->grps[egcQMMM].nr-1) &&
                             (ggrpnr(groups, egcQMMM, ai) >= (groups->grps[egcQMMM].nr-1)))
                    {
                        /* mark aj as frontier atom */
                        for (i = 0; i < qm_nr; i++)
                        {
                            if ( (qm_arr[i] == aj) || (qm_arr[i] == vsite))
                            {
                                qr->qm[j]->frontatoms[i] = TRUE;
                            }
                        }
                    }
                }
            }
        }
    }
    if (qr->QMMMscheme != eQMMMschemeoniom)
    {

        /* standard QMMM, all layers are merged together so there is one QM
         * subsystem and one MM subsystem.
         * Also we set the charges to zero in the md->charge arrays to prevent
         * the innerloops from doubly counting the electostatic QM MM interaction
         */

        alook = gmx_mtop_atomlookup_init(mtop);

        for (k = 0; k < qm_nr; k++)
        {
            gmx_mtop_atomnr_to_atom(alook, qm_arr[k], &atom);
            atom->q  = 0.0;
            atom->qB = 0.0;
        }
        qr->qm[0] = mk_QMrec();
        /* store QM atoms in the QMrec and initialise
         */
        init_QMrec(0, qr->qm[0], qm_nr, qm_arr, mtop, ir);
        if (qr->qm[0]->bOPT || qr->qm[0]->bTS)
        {
            for (i = 0; i < qm_nr; i++)
            {
                gmx_mtop_atomnr_to_atom(alook, qm_arr[i], &atom);
                /* nbfp now includes the 6.0/12.0 derivative prefactors */
                qr->qm[0]->c6[i]  =  C6(fr->nbfp, mtop->ffparams.atnr, atom->type, atom->type)/c6au/6.0;
                qr->qm[0]->c12[i] = C12(fr->nbfp, mtop->ffparams.atnr, atom->type, atom->type)/c12au/12.0;
            }
        }

        /* find frontier atoms and mark them true in the frontieratoms array.
         */
        for (i = 0; i < qm_nr; i++)
        {
            gmx_mtop_atomnr_to_ilist(alook, qm_arr[i], &ilist_mol, &a_offset);
            nrvsite2 = ilist_mol[F_VSITE2].nr;
            iatoms   = ilist_mol[F_VSITE2].iatoms;

            for (k = 0; k < nrvsite2; k += 4)
            {
                vsite = a_offset + iatoms[k+1]; /* the vsite         */
                ai    = a_offset + iatoms[k+2]; /* constructing atom */
                aj    = a_offset + iatoms[k+3]; /* constructing atom */
                if (ggrpnr(groups, egcQMMM, ai) < (groups->grps[egcQMMM].nr-1) &&
                        (ggrpnr(groups, egcQMMM, aj) >= (groups->grps[egcQMMM].nr-1)))
                {
                    /* mark ai as frontier atom */
                    if ( (qm_arr[i] == ai) || (qm_arr[i] == vsite) )
                    {
                        qr->qm[0]->frontatoms[i] = TRUE;
                    }
                }
                else if (ggrpnr(groups, egcQMMM, aj) < (groups->grps[egcQMMM].nr-1) &&
                         (ggrpnr(groups, egcQMMM, ai) >= (groups->grps[egcQMMM].nr-1)))
                {
                    /* mark aj as frontier atom */
                    if ( (qm_arr[i] == aj) || (qm_arr[i] == vsite) )
                    {
                        qr->qm[0]->frontatoms[i] = TRUE;
                    }
                }
            }
        }

        gmx_mtop_atomlookup_destroy(alook);

        /* MM rec creation */
        mm               = mk_MMrec();
        mm->scalefactor  = ir->scalefactor;
        mm->nrMMatoms    = (mtop->natoms)-(qr->qm[0]->nrQMatoms); /* rest of the atoms */
        qr->mm           = mm;
    }
    else /* ONIOM */
    {   /* MM rec creation */
        mm               = mk_MMrec();
        mm->scalefactor  = ir->scalefactor;
        mm->nrMMatoms    = 0;
        qr->mm           = mm;
    }

    /* these variables get updated in the update QMMMrec */

    if (qr->nrQMlayers == 1)
    {
        /* with only one layer there is only one initialisation
         * needed. Multilayer is a bit more complicated as it requires
         * re-initialisation at every step of the simulation. This is due
         * to the use of COMMON blocks in the fortran QM subroutines.
         */
        if (qr->qm[0]->QMmethod < eQMmethodRHF)
        {
#if GMX_QMMM_MOPAC
            /* semi-empiprical 1-layer ONIOM calculation requested (mopac93) */
            init_mopac(qr->qm[0]);
#else
            gmx_fatal(FARGS, "Semi-empirical QM only supported with Mopac.");
#endif
        }
        else
        {
            /* ab initio calculation requested (gamess/gaussian/ORCA) */
#if GMX_QMMM_GAMESS
            init_gamess(cr, qr->qm[0], qr->mm);
#elif GMX_QMMM_GAUSSIAN
            init_gaussian(qr->qm[0]);
#elif GMX_QMMM_ORCA
            init_orca(qr->qm[0]);
#else
            gmx_fatal(FARGS, "Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
#endif
        }
    }
} /* init_QMMMrec */
コード例 #8
0
ファイル: qmmm.cpp プロジェクト: wangxubo0201/gromacs
static void init_QMrec(int grpnr, t_QMrec *qm, int nr, int *atomarray,
                       gmx_mtop_t *mtop, t_inputrec *ir)
{
    /* fills the t_QMrec struct of QM group grpnr
     */
    int                   i;
    gmx_mtop_atomlookup_t alook;
    t_atom               *atom;


    qm->nrQMatoms = nr;
    snew(qm->xQM, nr);
    snew(qm->indexQM, nr);
    snew(qm->shiftQM, nr); /* the shifts */
    for (i = 0; i < nr; i++)
    {
        qm->indexQM[i] = atomarray[i];
    }

    alook = gmx_mtop_atomlookup_init(mtop);

    snew(qm->atomicnumberQM, nr);
    for (i = 0; i < qm->nrQMatoms; i++)
    {
        gmx_mtop_atomnr_to_atom(alook, qm->indexQM[i], &atom);
        qm->nelectrons       += mtop->atomtypes.atomnumber[atom->type];
        qm->atomicnumberQM[i] = mtop->atomtypes.atomnumber[atom->type];
    }

    gmx_mtop_atomlookup_destroy(alook);

    qm->QMcharge       = ir->opts.QMcharge[grpnr];
    qm->multiplicity   = ir->opts.QMmult[grpnr];
    qm->nelectrons    -= ir->opts.QMcharge[grpnr];

    qm->QMmethod       = ir->opts.QMmethod[grpnr];
    qm->QMbasis        = ir->opts.QMbasis[grpnr];
    /* trajectory surface hopping setup (Gaussian only) */
    qm->bSH            = ir->opts.bSH[grpnr];
    qm->CASorbitals    = ir->opts.CASorbitals[grpnr];
    qm->CASelectrons   = ir->opts.CASelectrons[grpnr];
    qm->SAsteps        = ir->opts.SAsteps[grpnr];
    qm->SAon           = ir->opts.SAon[grpnr];
    qm->SAoff          = ir->opts.SAoff[grpnr];
    /* hack to prevent gaussian from reinitializing all the time */
    qm->nQMcpus        = 0; /* number of CPU's to be used by g01, is set
                             * upon initializing gaussian
                             * (init_gaussian()
                             */
    /* print the current layer to allow users to check their input */
    fprintf(stderr, "Layer %d\nnr of QM atoms %d\n", grpnr, nr);
    fprintf(stderr, "QMlevel: %s/%s\n\n",
            eQMmethod_names[qm->QMmethod], eQMbasis_names[qm->QMbasis]);

    /* frontier atoms */
    snew(qm->frontatoms, nr);
    /* Lennard-Jones coefficients */
    snew(qm->c6, nr);
    snew(qm->c12, nr);
    /* do we optimize the QM separately using the algorithms of the QM program??
     */
    qm->bTS      = ir->opts.bTS[grpnr];
    qm->bOPT     = ir->opts.bOPT[grpnr];

} /* init_QMrec */