Exemplo n.º 1
0
static void get_vsite_masses(const gmx_moltype_t  *moltype,
                             const gmx_ffparams_t *ffparams,
                             real                 *vsite_m,
                             int                  *n_nonlin_vsite)
{
    int            ft, i;
    const t_ilist *il;

    *n_nonlin_vsite = 0;

    /* Check for virtual sites, determine mass from constructing atoms */
    for (ft = 0; ft < F_NRE; ft++)
    {
        if (IS_VSITE(ft))
        {
            il = &moltype->ilist[ft];

            for (i = 0; i < il->nr; i += 1+NRAL(ft))
            {
                const t_iparams *ip;
                real             cam[5] = {0}, inv_mass, coeff, m_aj;
                int              a1, j, aj;

                ip = &ffparams->iparams[il->iatoms[i]];

                a1 = il->iatoms[i+1];

                if (ft != F_VSITEN)
                {
                    for (j = 1; j < NRAL(ft); j++)
                    {
                        cam[j] = moltype->atoms.atom[il->iatoms[i+1+j]].m;
                        if (cam[j] == 0)
                        {
                            cam[j] = vsite_m[il->iatoms[i+1+j]];
                        }
                        if (cam[j] == 0)
                        {
                            gmx_fatal(FARGS, "In molecule type '%s' %s construction involves atom %d, which is a virtual site of equal or high complexity. This is not supported.",
                                      *moltype->name,
                                      interaction_function[ft].longname,
                                      il->iatoms[i+1+j]+1);
                        }
                    }
                }

                switch (ft)
                {
                    case F_VSITE2:
                        /* Exact */
                        vsite_m[a1] = (cam[1]*cam[2])/(cam[2]*sqr(1-ip->vsite.a) + cam[1]*sqr(ip->vsite.a));
                        break;
                    case F_VSITE3:
                        /* Exact */
                        vsite_m[a1] = (cam[1]*cam[2]*cam[3])/(cam[2]*cam[3]*sqr(1-ip->vsite.a-ip->vsite.b) + cam[1]*cam[3]*sqr(ip->vsite.a) + cam[1]*cam[2]*sqr(ip->vsite.b));
                        break;
                    case F_VSITEN:
                        /* Exact */
                        inv_mass = 0;
                        for (j = 0; j < 3*ffparams->iparams[il->iatoms[i]].vsiten.n; j += 3)
                        {
                            aj    = il->iatoms[i+j+2];
                            coeff = ffparams->iparams[il->iatoms[i+j]].vsiten.a;
                            if (moltype->atoms.atom[aj].ptype == eptVSite)
                            {
                                m_aj = vsite_m[aj];
                            }
                            else
                            {
                                m_aj = moltype->atoms.atom[aj].m;
                            }
                            if (m_aj <= 0)
                            {
                                gmx_incons("The mass of a vsiten constructing atom is <= 0");
                            }
                            inv_mass += coeff*coeff/m_aj;
                        }
                        vsite_m[a1] = 1/inv_mass;
                        /* Correct for loop increment of i */
                        i += j - 1 - NRAL(ft);
                        break;
                    default:
                        /* Use the mass of the lightest constructing atom.
                         * This is an approximation.
                         * If the distance of the virtual site to the
                         * constructing atom is less than all distances
                         * between constructing atoms, this is a safe
                         * over-estimate of the displacement of the vsite.
                         * This condition holds for all H mass replacement
                         * vsite constructions, except for SP2/3 groups.
                         * In SP3 groups one H will have a F_VSITE3
                         * construction, so even there the total drift
                         * estimate shouldn't be far off.
                         */
                        assert(j >= 1);
                        vsite_m[a1] = cam[1];
                        for (j = 2; j < NRAL(ft); j++)
                        {
                            vsite_m[a1] = min(vsite_m[a1], cam[j]);
                        }
                        (*n_nonlin_vsite)++;
                        break;
                }
                if (gmx_debug_at)
                {
                    fprintf(debug, "atom %4d %-20s mass %6.3f\n",
                            a1, interaction_function[ft].longname, vsite_m[a1]);
                }
            }
        }
    }
}
Exemplo n.º 2
0
static void get_verlet_buffer_atomtypes(const gmx_mtop_t      *mtop,
                                        verletbuf_atomtype_t **att_p,
                                        int                   *natt_p,
                                        int                   *n_nonlin_vsite)
{
    verletbuf_atomtype_t *att;
    int                   natt;
    int                   mb, nmol, ft, i, j, a1, a2, a3, a;
    const t_atoms        *atoms;
    const t_ilist        *il;
    const t_atom         *at;
    const t_iparams      *ip;
    real                 *con_m, *vsite_m, cam[5];

    att  = NULL;
    natt = 0;

    if (n_nonlin_vsite != NULL)
    {
        *n_nonlin_vsite = 0;
    }

    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        nmol = mtop->molblock[mb].nmol;

        atoms = &mtop->moltype[mtop->molblock[mb].type].atoms;

        /* Check for constraints, as they affect the kinetic energy */
        snew(con_m, atoms->nr);
        snew(vsite_m, atoms->nr);

        for (ft = F_CONSTR; ft <= F_CONSTRNC; ft++)
        {
            il = &mtop->moltype[mtop->molblock[mb].type].ilist[ft];

            for (i = 0; i < il->nr; i += 1+NRAL(ft))
            {
                a1         = il->iatoms[i+1];
                a2         = il->iatoms[i+2];
                con_m[a1] += atoms->atom[a2].m;
                con_m[a2] += atoms->atom[a1].m;
            }
        }

        il = &mtop->moltype[mtop->molblock[mb].type].ilist[F_SETTLE];

        for (i = 0; i < il->nr; i += 1+NRAL(F_SETTLE))
        {
            a1         = il->iatoms[i+1];
            a2         = il->iatoms[i+2];
            a3         = il->iatoms[i+3];
            con_m[a1] += atoms->atom[a2].m + atoms->atom[a3].m;
            con_m[a2] += atoms->atom[a1].m + atoms->atom[a3].m;
            con_m[a3] += atoms->atom[a1].m + atoms->atom[a2].m;
        }

        /* Check for virtual sites, determine mass from constructing atoms */
        for (ft = 0; ft < F_NRE; ft++)
        {
            if (IS_VSITE(ft))
            {
                il = &mtop->moltype[mtop->molblock[mb].type].ilist[ft];

                for (i = 0; i < il->nr; i += 1+NRAL(ft))
                {
                    ip = &mtop->ffparams.iparams[il->iatoms[i]];

                    a1 = il->iatoms[i+1];

                    for (j = 1; j < NRAL(ft); j++)
                    {
                        cam[j] = atoms->atom[il->iatoms[i+1+j]].m;
                        if (cam[j] == 0)
                        {
                            cam[j] = vsite_m[il->iatoms[i+1+j]];
                        }
                        if (cam[j] == 0)
                        {
                            gmx_fatal(FARGS, "In molecule type '%s' %s construction involves atom %d, which is a virtual site of equal or high complexity. This is not supported.",
                                      *mtop->moltype[mtop->molblock[mb].type].name,
                                      interaction_function[ft].longname,
                                      il->iatoms[i+1+j]+1);
                        }
                    }

                    switch (ft)
                    {
                        case F_VSITE2:
                            /* Exact except for ignoring constraints */
                            vsite_m[a1] = (cam[2]*sqr(1-ip->vsite.a) + cam[1]*sqr(ip->vsite.a))/(cam[1]*cam[2]);
                            break;
                        case F_VSITE3:
                            /* Exact except for ignoring constraints */
                            vsite_m[a1] = (cam[2]*cam[3]*sqr(1-ip->vsite.a-ip->vsite.b) + cam[1]*cam[3]*sqr(ip->vsite.a) + cam[1]*cam[2]*sqr(ip->vsite.b))/(cam[1]*cam[2]*cam[3]);
                            break;
                        default:
                            /* Use the mass of the lightest constructing atom.
                             * This is an approximation.
                             * If the distance of the virtual site to the
                             * constructing atom is less than all distances
                             * between constructing atoms, this is a safe
                             * over-estimate of the displacement of the vsite.
                             * This condition holds for all H mass replacement
                             * replacement vsite constructions, except for SP2/3
                             * groups. In SP3 groups one H will have a F_VSITE3
                             * construction, so even there the total drift
                             * estimation shouldn't be far off.
                             */
                            assert(j >= 1);
                            vsite_m[a1] = cam[1];
                            for (j = 2; j < NRAL(ft); j++)
                            {
                                vsite_m[a1] = min(vsite_m[a1], cam[j]);
                            }
                            if (n_nonlin_vsite != NULL)
                            {
                                *n_nonlin_vsite += nmol;
                            }
                            break;
                    }
                }
            }
        }

        for (a = 0; a < atoms->nr; a++)
        {
            at = &atoms->atom[a];
            /* We consider an atom constrained, #DOF=2, when it is
             * connected with constraints to one or more atoms with
             * total mass larger than 1.5 that of the atom itself.
             */
            add_at(&att, &natt,
                   at->m, at->type, at->q, con_m[a] > 1.5*at->m, nmol);
        }

        sfree(vsite_m);
        sfree(con_m);
    }

    if (gmx_debug_at)
    {
        for (a = 0; a < natt; a++)
        {
            fprintf(debug, "type %d: m %5.2f t %d q %6.3f con %d n %d\n",
                    a, att[a].mass, att[a].type, att[a].q, att[a].con, att[a].n);
        }
    }

    *att_p  = att;
    *natt_p = natt;
}