Beispiel #1
0
int n_bonded_dx(const gmx_mtop_t *mtop, gmx_bool bExcl)
{
    int                  mb, nmol, ftype, ndxb, ndx_excl;
    int                  ndx;
    const gmx_moltype_t *molt;

    /* Count the number of pbc_rvec_sub calls required for bonded interactions.
     * This number is also roughly proportional to the computational cost.
     */
    ndx      = 0;
    ndx_excl = 0;
#if defined _ICC && __ICC == 1400 || defined __ICL && __ICL == 1400
#pragma novector /* Work-around for incorrect vectorization */
#endif
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molt = &mtop->moltype[mtop->molblock[mb].type];
        nmol = mtop->molblock[mb].nmol;
        for (ftype = 0; ftype < F_NRE; ftype++)
        {
            if (interaction_function[ftype].flags & IF_BOND)
            {
                switch (ftype)
                {
                case F_POSRES:
                case F_FBPOSRES:
                    ndxb = 1;
                    break;
                case F_CONNBONDS:
                    ndxb = 0;
                    break;
                default:
                    ndxb      = NRAL(ftype) - 1;
                    break;
                }
                ndx += nmol*ndxb*molt->ilist[ftype].nr/(1 + NRAL(ftype));
            }
        }
        if (bExcl)
        {
            ndx_excl += nmol*(molt->excls.nra - molt->atoms.nr)/2;
        }
        else
        {
            ndx_excl = 0;
        }
    }

    if (debug)
    {
        fprintf(debug, "ndx bonded %d exclusions %d\n", ndx, ndx_excl);
    }

    ndx += ndx_excl;

    return ndx;
}
Beispiel #2
0
static void enter_function(t_params *p, t_functype ftype, int comb, real reppow,
                           gmx_ffparams_t *ffparams, t_ilist *il,
                           int *maxtypes,
                           gmx_bool bNB, gmx_bool bAppend)
{
    int     k, type, nr, nral, delta, start;

    start = ffparams->ntypes;
    nr    = p->nr;

    for (k = 0; k < nr; k++)
    {
        if (*maxtypes <= ffparams->ntypes)
        {
            *maxtypes += 1000;
            srenew(ffparams->functype, *maxtypes);
            srenew(ffparams->iparams, *maxtypes);
            if (debug)
            {
                fprintf(debug, "%s, line %d: srenewed idef->functype and idef->iparams to %d\n",
                        __FILE__, __LINE__, *maxtypes);
            }
        }
        type = enter_params(ffparams, ftype, p->param[k].c, comb, reppow, start, bAppend);
        /* Type==-1 is used as a signal that this interaction is all-zero and should not be added. */
        if (!bNB && type >= 0)
        {
            nral  = NRAL(ftype);
            delta = nr*(nral+1);
            srenew(il->iatoms, il->nr+delta);
            append_interaction(il, type, nral, p->param[k].a);
        }
    }
}
Beispiel #3
0
static void cppar(t_param p[], int np, t_params plist[], int ftype)
{
    int       i, j, nral, nrfp;
    t_params *ps;

    ps   = &plist[ftype];
    nral = NRAL(ftype);
    nrfp = NRFP(ftype);

    /* Keep old stuff */
    pr_alloc(np, ps);
    for (i = 0; (i < np); i++)
    {
        for (j = 0; (j < nral); j++)
        {
            ps->param[ps->nr].a[j] = p[i].a[j];
        }
        for (j = 0; (j < nrfp); j++)
        {
            ps->param[ps->nr].c[j] = p[i].c[j];
        }
        for (j = 0; (j < MAXSLEN); j++)
        {
            ps->param[ps->nr].s[j] = p[i].s[j];
        }
        ps->nr++;
    }
}
Beispiel #4
0
static int vsite_bond_nrcheck(int ftype)
{
  int nrcheck;
  
  if ((interaction_function[ftype].flags & (IF_BTYPE | IF_CONSTRAINT | IF_ATYPE)) || (ftype == F_IDIHS))
    nrcheck = NRAL(ftype);
  else
    nrcheck = 0;
  
  return nrcheck;
}
Beispiel #5
0
int gmx_mtop_ftype_count(const gmx_mtop_t *mtop,int ftype)
{
    gmx_mtop_ilistloop_t iloop;
    t_ilist *il;
    int n,nmol;

    n = 0;

    iloop = gmx_mtop_ilistloop_init(mtop);
    while (gmx_mtop_ilistloop_next(iloop,&il,&nmol))
    {
        n += nmol*il[ftype].nr/(1+NRAL(ftype));
    }

    return n;
}
Beispiel #6
0
gmx_bool inter_charge_group_constraints(const gmx_mtop_t *mtop)
{
    const gmx_moltype_t *molt;
    const t_block       *cgs;
    const t_ilist       *il;
    int                  mb;
    int                  nat, *at2cg, cg, a, ftype, i;
    gmx_bool             bInterCG;

    bInterCG = FALSE;
    for (mb = 0; mb < mtop->nmolblock && !bInterCG; mb++)
    {
        molt = &mtop->moltype[mtop->molblock[mb].type];

        if (molt->ilist[F_CONSTR].nr   > 0 ||
            molt->ilist[F_CONSTRNC].nr > 0 ||
            molt->ilist[F_SETTLE].nr > 0)
        {
            cgs  = &molt->cgs;
            snew(at2cg, molt->atoms.nr);
            for (cg = 0; cg < cgs->nr; cg++)
            {
                for (a = cgs->index[cg]; a < cgs->index[cg+1]; a++)
                {
                    at2cg[a] = cg;
                }
            }

            for (ftype = F_CONSTR; ftype <= F_CONSTRNC; ftype++)
            {
                il = &molt->ilist[ftype];
                for (i = 0; i < il->nr && !bInterCG; i += 1+NRAL(ftype))
                {
                    if (at2cg[il->iatoms[i+1]] != at2cg[il->iatoms[i+2]])
                    {
                        bInterCG = TRUE;
                    }
                }
            }

            sfree(at2cg);
        }
    }

    return bInterCG;
}
Beispiel #7
0
static at2vsitecon_t *make_at2vsitecon(int natoms,t_params plist[])
{
  gmx_bool *bVSI;
  int  ftype,i,j,ai,aj,nr;
  at2vsitecon_t *at2vc;

  snew(at2vc,natoms);

  snew(bVSI,natoms);
  for(ftype=0; (ftype<F_NRE); ftype++) {
    if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) {
      for(i=0; (i<plist[ftype].nr); i++) {
	for(j=0; j<NRAL(ftype); j++)
	  bVSI[plist[ftype].param[i].a[j]] = TRUE;
      }
    }
  }
  
  for(ftype=0; (ftype<F_NRE); ftype++) {
    if (interaction_function[ftype].flags & IF_CONSTRAINT) {
      for(i=0; (i<plist[ftype].nr); i++) {
	ai = plist[ftype].param[i].AI;
	aj = plist[ftype].param[i].AJ;
	if (bVSI[ai] && bVSI[aj]) {
	  /* Store forward direction */
	  nr = at2vc[ai].nr;
	  if (nr % 10 == 0)
	    srenew(at2vc[ai].aj,nr+10);
	  at2vc[ai].aj[nr] = aj;
	  at2vc[ai].nr++;
	  /* Store backward direction */
	  nr = at2vc[aj].nr;
	  if (nr % 10 == 0)
	    srenew(at2vc[aj].aj,nr+10);
	  at2vc[aj].aj[nr] = ai;
	  at2vc[aj].nr++;
	}
      }
    }
  }
  sfree(bVSI);

  return at2vc;
}
Beispiel #8
0
static at2vsitebond_t *make_at2vsitebond(int natoms,t_params plist[])
{
  gmx_bool *bVSI;
  int  ftype,i,j,nrcheck,nr;
  t_iatom *aa;
  at2vsitebond_t *at2vb;

  snew(at2vb,natoms);

  snew(bVSI,natoms);
  for(ftype=0; (ftype<F_NRE); ftype++) {
    if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) {
      for(i=0; (i<plist[ftype].nr); i++) {
	for(j=0; j<NRAL(ftype); j++)
	  bVSI[plist[ftype].param[i].a[j]] = TRUE;
      }
    }
  }
  
  for(ftype=0; (ftype<F_NRE); ftype++) {
    nrcheck = vsite_bond_nrcheck(ftype);
    if (nrcheck > 0) {
      for(i=0; (i<plist[ftype].nr); i++) {
	aa = plist[ftype].param[i].a;
	for(j=0; j<nrcheck; j++) {
	  if (bVSI[aa[j]]) {
	    nr = at2vb[aa[j]].nr;
	    if (nr % 10 == 0)
	      srenew(at2vb[aa[j]].vsbp,nr+10);
	    at2vb[aa[j]].vsbp[nr].ftype = ftype;
	    at2vb[aa[j]].vsbp[nr].param = &plist[ftype].param[i];
	    at2vb[aa[j]].nr++;
	  }
	}
      }
    }
  }
  sfree(bVSI);

  return at2vb;
}
Beispiel #9
0
static void enter_function(t_params *p, t_functype ftype, int comb, real reppow,
                           gmx_ffparams_t *ffparams, InteractionList *il,
                           bool bNB, bool bAppend)
{
    int     k, type, nr, nral, start;

    start = ffparams->numTypes();
    nr    = p->nr;

    for (k = 0; k < nr; k++)
    {
        type = enter_params(ffparams, ftype, p->param[k].c, comb, reppow, start, bAppend);
        /* Type==-1 is used as a signal that this interaction is all-zero and should not be added. */
        if (!bNB && type >= 0)
        {
            assert(il);
            nral  = NRAL(ftype);
            append_interaction(il, type, nral, p->param[k].a);
        }
    }
}
Beispiel #10
0
static int *make_at2settle(int natoms, const t_ilist *ilist)
{
    int *at2s;
    int  a, stride, s;

    snew(at2s, natoms);
    /* Set all to no settle */
    for (a = 0; a < natoms; a++)
    {
        at2s[a] = -1;
    }

    stride = 1 + NRAL(F_SETTLE);

    for (s = 0; s < ilist->nr; s += stride)
    {
        at2s[ilist->iatoms[s+1]] = s/stride;
        at2s[ilist->iatoms[s+2]] = s/stride;
        at2s[ilist->iatoms[s+3]] = s/stride;
    }

    return at2s;
}
Beispiel #11
0
static void ilistcat(int ftype,t_ilist *dest,t_ilist *src,int copies, 
                     int dnum,int snum)
{
    int nral,c,i,a;

    nral = NRAL(ftype);

    dest->nalloc = dest->nr + copies*src->nr;
    srenew(dest->iatoms,dest->nalloc);

    for(c=0; c<copies; c++)
    {
        for(i=0; i<src->nr; )
        {
            dest->iatoms[dest->nr++] = src->iatoms[i++];
            for(a=0; a<nral; a++)
            {
                dest->iatoms[dest->nr++] = dnum + src->iatoms[i++];
            }
        }
        dnum += snum;
    }
}
Beispiel #12
0
//! Divides bonded interactions over threads
static void divide_bondeds_over_threads(t_idef *idef,
                                        int     nthread,
                                        int     max_nthread_uniform,
                                        bool   *haveBondeds)
{
    ilist_data_t ild[F_NRE];
    int          ntype;
    int          f;

    assert(nthread > 0);

    idef->nthreads = nthread;

    if (F_NRE*(nthread + 1) > idef->il_thread_division_nalloc)
    {
        idef->il_thread_division_nalloc = F_NRE*(nthread + 1);
        snew(idef->il_thread_division, idef->il_thread_division_nalloc);
    }

    *haveBondeds = false;
    ntype        = 0;
    for (f = 0; f < F_NRE; f++)
    {
        if (!ftype_is_bonded_potential(f))
        {
            continue;
        }

        if (idef->il[f].nr > 0)
        {
            *haveBondeds = true;
        }

        if (idef->il[f].nr == 0)
        {
            /* No interactions, avoid all the integer math below */
            int t;
            for (t = 0; t <= nthread; t++)
            {
                idef->il_thread_division[f*(nthread + 1) + t] = 0;
            }
        }
        else if (nthread <= max_nthread_uniform || f == F_DISRES)
        {
            /* On up to 4 threads, load balancing the bonded work
             * is more important than minimizing the reduction cost.
             */
            int nat1, t;

            /* nat1 = 1 + #atoms(ftype) which is the stride use for iatoms */
            nat1 = 1 + NRAL(f);

            for (t = 0; t <= nthread; t++)
            {
                int nr_t;

                /* Divide equally over the threads */
                nr_t = (((idef->il[f].nr/nat1)*t)/nthread)*nat1;

                if (f == F_DISRES)
                {
                    /* Ensure that distance restraint pairs with the same label
                     * end up on the same thread.
                     */
                    while (nr_t > 0 && nr_t < idef->il[f].nr &&
                           idef->iparams[idef->il[f].iatoms[nr_t]].disres.label ==
                           idef->iparams[idef->il[f].iatoms[nr_t-nat1]].disres.label)
                    {
                        nr_t += nat1;
                    }
                }

                idef->il_thread_division[f*(nthread + 1) + t] = nr_t;
            }
        }
        else
        {
            /* Add this ftype to the list to be distributed */
            int nat;

            nat              = NRAL(f);
            ild[ntype].ftype = f;
            ild[ntype].il    = &idef->il[f];
            ild[ntype].nat   = nat;

            /* The first index for the thread division is always 0 */
            idef->il_thread_division[f*(nthread + 1)] = 0;

            ntype++;
        }
    }

    if (ntype > 0)
    {
        divide_bondeds_by_locality(ntype, ild, nthread, idef);
    }

    if (debug)
    {
        int f;

        fprintf(debug, "Division of bondeds over threads:\n");
        for (f = 0; f < F_NRE; f++)
        {
            if (ftype_is_bonded_potential(f) && idef->il[f].nr > 0)
            {
                int t;

                fprintf(debug, "%16s", interaction_function[f].name);
                for (t = 0; t < nthread; t++)
                {
                    fprintf(debug, " %4d",
                            (idef->il_thread_division[f*(nthread + 1) + t + 1] -
                             idef->il_thread_division[f*(nthread + 1) + t])/
                            (1 + NRAL(f)));
                }
                fprintf(debug, "\n");
            }
        }
    }
}
Beispiel #13
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, a1, a2, a3, a;
    const t_atoms                 *atoms;
    const t_ilist                 *il;
    const t_iparams               *ip;
    atom_nonbonded_kinetic_prop_t *prop;
    real                          *vsite_m;
    int                            n_nonlin_vsite_mol;

    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.
         * For virtual sites we need the masses and geometry of
         * the constructing atoms to determine their velocity distribution.
         */
        snew(prop, 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))
            {
                ip         = &mtop->ffparams.iparams[il->iatoms[i]];
                a1         = il->iatoms[i+1];
                a2         = il->iatoms[i+2];
                if (atoms->atom[a2].m > prop[a1].con_mass)
                {
                    prop[a1].con_mass = atoms->atom[a2].m;
                    prop[a1].con_len  = ip->constr.dA;
                }
                if (atoms->atom[a1].m > prop[a2].con_mass)
                {
                    prop[a2].con_mass = atoms->atom[a1].m;
                    prop[a2].con_len  = ip->constr.dA;
                }
            }
        }

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

        for (i = 0; i < il->nr; i += 1+NRAL(F_SETTLE))
        {
            ip         = &mtop->ffparams.iparams[il->iatoms[i]];
            a1         = il->iatoms[i+1];
            a2         = il->iatoms[i+2];
            a3         = il->iatoms[i+3];
            /* Usually the mass of a1 (usually oxygen) is larger than a2/a3.
             * If this is not the case, we overestimate the displacement,
             * which leads to a larger buffer (ok since this is an exotic case).
             */
            prop[a1].con_mass = atoms->atom[a2].m;
            prop[a1].con_len  = ip->settle.doh;

            prop[a2].con_mass = atoms->atom[a1].m;
            prop[a2].con_len  = ip->settle.doh;

            prop[a3].con_mass = atoms->atom[a1].m;
            prop[a3].con_len  = ip->settle.doh;
        }

        get_vsite_masses(&mtop->moltype[mtop->molblock[mb].type],
                         &mtop->ffparams,
                         vsite_m,
                         &n_nonlin_vsite_mol);
        if (n_nonlin_vsite != NULL)
        {
            *n_nonlin_vsite += nmol*n_nonlin_vsite_mol;
        }

        for (a = 0; a < atoms->nr; a++)
        {
            if (atoms->atom[a].ptype == eptVSite)
            {
                prop[a].mass = vsite_m[a];
            }
            else
            {
                prop[a].mass = atoms->atom[a].m;
            }
            prop[a].type     = atoms->atom[a].type;
            prop[a].q        = atoms->atom[a].q;
            /* We consider an atom constrained, #DOF=2, when it is
             * connected with constraints to (at least one) atom with
             * a mass of more than 0.4x its own mass. This is not a critical
             * parameter, since with roughly equal masses the unconstrained
             * and constrained displacement will not differ much (and both
             * overestimate the displacement).
             */
            prop[a].bConstr = (prop[a].con_mass > 0.4*prop[a].mass);

            add_at(&att, &natt, &prop[a], nmol);
        }

        sfree(vsite_m);
        sfree(prop);
    }

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

    *att_p  = att;
    *natt_p = natt;
}
Beispiel #14
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]);
                }
            }
        }
    }
}
Beispiel #15
0
void count_bonded_distances(gmx_mtop_t *mtop, const t_inputrec *ir,
                            double *ndistance_c, double *ndistance_simd)
{
    gmx_bool       bExcl;
    int            nst_ener_or_vir;
    double         nonsimd_step_frac;
    int            mb, nmol, ftype;
    gmx_moltype_t *molt;
    double         ndtot_c, ndtot_simd;
#ifdef GMX_SIMD_HAVE_REAL
    gmx_bool       bSimdBondeds = TRUE;
#else
    gmx_bool       bSimdBondeds = FALSE;
#endif

    bExcl = (ir->cutoff_scheme == ecutsGROUP && IR_EXCL_FORCES(*ir)
             && !EEL_FULL(ir->coulombtype));

    if (bSimdBondeds)
    {
        /* We only have SIMD versions of these bondeds without energy and
         * without shift-forces, we take that into account here.
         */
        if (ir->nstcalcenergy > 0)
        {
            nonsimd_step_frac = 1.0/ir->nstcalcenergy;
        }
        else
        {
            nonsimd_step_frac = 0;
        }
        if (ir->epc != epcNO && 1.0/ir->nstpcouple > nonsimd_step_frac)
        {
            nonsimd_step_frac = 1.0/ir->nstpcouple;
        }
    }
    else
    {
        nonsimd_step_frac = 1;
    }

    /* Count the number of pbc_rvec_sub calls required for bonded interactions.
     * This number is also roughly proportional to the computational cost.
     */
    ndtot_c    = 0;
    ndtot_simd = 0;
#if defined _ICC && __ICC == 1400 || defined __ICL && __ICL == 1400
#pragma novector /* Work-around for incorrect vectorization */
#endif
    for (mb = 0; mb < mtop->nmolblock; mb++)
    {
        molt = &mtop->moltype[mtop->molblock[mb].type];
        nmol = mtop->molblock[mb].nmol;
        for (ftype = 0; ftype < F_NRE; ftype++)
        {
            int nbonds;

            if (interaction_function[ftype].flags & IF_BOND)
            {
                double nd_c, nd_simd;

                nd_c    = 0;
                nd_simd = 0;
                /* For all interactions, except for the three exceptions
                 * in the switch below, #distances = #atoms - 1.
                 */
                switch (ftype)
                {
                    case F_POSRES:
                    case F_FBPOSRES:
                        nd_c    = 1;
                        break;
                    case F_CONNBONDS:
                        break;
                    /* These bonded potentially use SIMD */
                    case F_ANGLES:
                    case F_PDIHS:
                    case F_RBDIHS:
                        nd_c    =      nonsimd_step_frac *(NRAL(ftype) - 1);
                        nd_simd = (1 - nonsimd_step_frac)*(NRAL(ftype) - 1);
                        break;
                    default:
                        nd_c    = NRAL(ftype) - 1;
                        break;
                }
                nbonds      = nmol*molt->ilist[ftype].nr/(1 + NRAL(ftype));
                ndtot_c    += nbonds*nd_c;
                ndtot_simd += nbonds*nd_simd;
            }
        }
        if (bExcl)
        {
            ndtot_c += nmol*(molt->excls.nra - molt->atoms.nr)/2;
        }
    }

    if (debug)
    {
        fprintf(debug, "nr. of distance calculations in bondeds: C %.1f SIMD %.1f\n", ndtot_c, ndtot_simd);
    }

    if (ndistance_c    != NULL)
    {
        *ndistance_c    = ndtot_c;
    }
    if (ndistance_simd != NULL)
    {
        *ndistance_simd = ndtot_simd;
    }
}
void print_bt(FILE *out, directive d, gpp_atomtype_t at,
              int ftype, int fsubtype, t_params plist[],
              gmx_bool bFullDih)
{
    /* This dihp is a DIRTY patch because the dih-types do not use
     * all four atoms to determine the type.
     */
    const int    dihp[2][2] = { { 1, 2 }, { 0, 3 } };
    t_params    *bt;
    int          i, j, f, nral, nrfp;
    gmx_bool     bDih = FALSE, bSwapParity;

    bt = &(plist[ftype]);

    if (!bt->nr)
    {
        return;
    }

    f = 0;
    switch (ftype)
    {
        case F_G96ANGLES:
            f = 1;
            break;
        case F_G96BONDS:
            f = 1;
            break;
        case F_MORSE:
            f = 2;
            break;
        case F_CUBICBONDS:
            f = 3;
            break;
        case F_CONNBONDS:
            f = 4;
            break;
        case F_HARMONIC:
            f = 5;
            break;
        case F_CROSS_BOND_ANGLES:
            f = 2;
            break;
        case F_CROSS_BOND_BONDS:
            f = 3;
            break;
        case F_UREY_BRADLEY:
            f = 4;
            break;
        case F_PDIHS:
        case F_RBDIHS:
        case F_FOURDIHS:
            bDih = TRUE;
            break;
        case F_IDIHS:
            f    = 1;
            bDih = TRUE;
            break;
        case F_CONSTRNC:
            f = 1;
            break;
        case F_VSITE3FD:
            f = 1;
            break;
        case F_VSITE3FAD:
            f = 2;
            break;
        case F_VSITE3OUT:
            f = 3;
            break;
        case F_VSITE4FDN:
            f = 1;
            break;
        case F_CMAP:
            f = 1;
            break;

        default:
            bDih = FALSE;
    }
    if (bFullDih)
    {
        bDih = FALSE;
    }
    if (fsubtype)
    {
        f = fsubtype-1;
    }

    nral = NRAL(ftype);
    nrfp = NRFP(ftype);

    /* header */
    fprintf(out, "[ %s ]\n", dir2str(d));
    fprintf(out, "; ");
    if (!bDih)
    {
        fprintf (out, "%3s  %4s", "ai", "aj");
        for (j = 2; (j < nral); j++)
        {
            fprintf (out, "  %3c%c", 'a', 'i'+j);
        }
    }
    else
    {
        for (j = 0; (j < 2); j++)
        {
            fprintf (out, "%3c%c", 'a', 'i'+dihp[f][j]);
        }
    }

    fprintf (out, " funct");
    for (j = 0; (j < nrfp); j++)
    {
        fprintf (out, " %12c%1d", 'c', j);
    }
    fprintf (out, "\n");

    /* print bondtypes */
    for (i = 0; (i < bt->nr); i++)
    {
        bSwapParity = (bt->param[i].C0 == NOTSET) && (bt->param[i].C1 == -1);
        if (!bDih)
        {
            for (j = 0; (j < nral); j++)
            {
                fprintf (out, "%5s ", get_atomtype_name(bt->param[i].a[j], at));
            }
        }
        else
        {
            for (j = 0; (j < 2); j++)
            {
                fprintf (out, "%5s ", get_atomtype_name(bt->param[i].a[dihp[f][j]], at));
            }
        }
        fprintf (out, "%5d ", bSwapParity ? -f-1 : f+1);

        if (bt->param[i].s[0])
        {
            fprintf(out, "   %s", bt->param[i].s);
        }
        else
        {
            for (j = 0; (j < nrfp && (bt->param[i].c[j] != NOTSET)); j++)
            {
                fprintf (out, "%13.6e ", bt->param[i].c[j]);
            }
        }

        fprintf (out, "\n");
    }
    fprintf (out, "\n");
    fflush (out);
}
Beispiel #17
0
static void clean_vsite_angles(t_params *plist, t_pindex pindex[], 
			       int cftype, int vsite_type[],
			       at2vsitecon_t *at2vc)
{
  int      i,j,parnr,k,l,m,n,nvsite,kept_i,vsnral,vsitetype;
  atom_id  atom,constr,at1,at2;
  atom_id  vsiteatoms[MAXATOMLIST];
  gmx_bool     bKeep,bUsed,bPresent,bAll3FAD,bFirstTwo;
  t_params *ps;
  
  ps = &(plist[cftype]);
  vsnral=0;
  kept_i=0;
  for(i=0; (i<ps->nr); i++) { /* for all angles in the plist */
    bKeep=FALSE;
    bAll3FAD=TRUE;
    /* check if all virtual sites are constructed from the same atoms */
    nvsite=0;
    for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */
      atom = ps->param[i].a[k];
      if (vsite_type[atom]!=NOTSET) {
	nvsite++;
	bAll3FAD = bAll3FAD && (pindex[atom].ftype == F_VSITE3FAD);
	if (nvsite==1) {
	  /* store construction atoms of first vsite */
	  vsnral=NRAL(pindex[atom].ftype)-1;
	  for(m=0; (m<vsnral); m++)
	    vsiteatoms[m]=
	      plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
	} else 
	  /* check if this vsite is constructed from the same atoms */
	  if (vsnral == NRAL(pindex[atom].ftype)-1 )
	    for(m=0; (m<vsnral) && !bKeep; m++) {
	      bPresent=FALSE;
	      constr=
		plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
	      for(n=0; (n<vsnral) && !bPresent; n++)
		if (constr == vsiteatoms[n])
		  bPresent=TRUE;
	      if (!bPresent)
		bKeep=TRUE;
	    }
	  else
	    bKeep=TRUE;
      }
    }
    
    /* keep all angles with no virtual sites in them or 
       with virtual sites with more than 3 constr. atoms */
    if ( nvsite == 0 && vsnral > 3 )
      bKeep=TRUE;
    
    /* check if all non-vsite atoms are used in construction: */
    bFirstTwo=TRUE;
    for(k=0; (k<3) && !bKeep; k++) { /* for all atoms in the angle */
      atom = ps->param[i].a[k];
      if (vsite_type[atom]==NOTSET) {
	bUsed=FALSE;
	for(m=0; (m<vsnral) && !bUsed; m++)
	  if (atom == vsiteatoms[m]) {
	    bUsed=TRUE;
	    bFirstTwo = bFirstTwo && m<2;
	  }
	if (!bUsed)
	  bKeep=TRUE;
      }
    }
    
    if ( ! ( bAll3FAD && bFirstTwo ) )
      /* check if all constructing atoms are constrained together */
      for (m=0; m<vsnral && !bKeep; m++) { /* all constr. atoms */
	at1 = vsiteatoms[m];
	at2 = vsiteatoms[(m+1) % vsnral];
	bPresent=FALSE;
	for(j=0; j<at2vc[at1].nr; j++) {
	  if (at2vc[at1].aj[j] == at2)
	    bPresent = TRUE;
	}
	if (!bPresent)
	  bKeep=TRUE;
      }
    
    if ( bKeep ) {
      /* now copy the angle to the new array */
      memcpy(&(ps->param[kept_i]),
	     &(ps->param[i]),(size_t)sizeof(ps->param[0]));
      kept_i++;
    }
  }
  
  if (ps->nr != kept_i)
    fprintf(stderr,"Removed   %4d %15ss with virtual sites, %5d left\n",
	    ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
  ps->nr=kept_i;
}
Beispiel #18
0
int dd_make_local_constraints(gmx_domdec_t *dd,int at_start,
                              const gmx_mtop_t *mtop,
                              const int *cginfo,
                              gmx_constr_t constr,int nrec,
                              t_ilist *il_local)
{
    gmx_domdec_constraints_t *dc;
    t_ilist *ilc_local,*ils_local;
    ind_req_t *ireq;
    const t_blocka *at2con_mt;
    const int **at2settle_mt;
    gmx_hash_t ga2la_specat;
    int at_end,i,j;
    t_iatom *iap;
    
    dc = dd->constraints;
    
    ilc_local = &il_local[F_CONSTR];
    ils_local = &il_local[F_SETTLE];

    dc->ncon      = 0;
    ilc_local->nr = 0;
    if (dd->constraint_comm)
    {
        at2con_mt = atom2constraints_moltype(constr);
        ireq = &dd->constraint_comm->ireq[0];
        ireq->n = 0;
    }
    else
    {
        at2con_mt = NULL;
        ireq = NULL;
    }

    if (dd->bInterCGsettles)
    {
        at2settle_mt = atom2settle_moltype(constr);
        ils_local->nr = 0;
    }
    else
    {
        /* Settle works inside charge groups, we assigned them already */
        at2settle_mt = NULL;
    }

    if (at2settle_mt == NULL)
    {
        atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec,
                             ilc_local,ireq);
    }
    else
    {
        int t0_set;
        int thread;

        /* Do the constraints, if present, on the first thread.
         * Do the settles on all other threads.
         */
        t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0);

#pragma omp parallel for num_threads(dc->nthread) schedule(static)
        for(thread=0; thread<dc->nthread; thread++)
        {
            if (at2con_mt && thread == 0)
            {
                atoms_to_constraints(dd,mtop,cginfo,at2con_mt,nrec,
                                     ilc_local,ireq);
            }

            if (thread >= t0_set)
            {
                int cg0,cg1;
                t_ilist *ilst;
                ind_req_t *ireqt;

                /* Distribute the settle check+assignments over
                 * dc->nthread or dc->nthread-1 threads.
                 */
                cg0 = (dd->ncg_home*(thread-t0_set  ))/(dc->nthread-t0_set);
                cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set);

                if (thread == t0_set)
                {
                    ilst = ils_local;
                }
                else
                {
                    ilst = &dc->ils[thread];
                }
                ilst->nr = 0;

                ireqt = &dd->constraint_comm->ireq[thread];
                if (thread > 0)
                {
                    ireqt->n = 0;
                }

                atoms_to_settles(dd,mtop,cginfo,at2settle_mt,
                                 cg0,cg1,
                                 ilst,ireqt);
            }
        }

        /* Combine the generate settles and requested indices */
        for(thread=1; thread<dc->nthread; thread++)
        {
            t_ilist *ilst;
            ind_req_t *ireqt;
            int ia;

            if (thread > t0_set)
            {
                ilst = &dc->ils[thread];
                if (ils_local->nr + ilst->nr > ils_local->nalloc)
                {
                    ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr);
                    srenew(ils_local->iatoms,ils_local->nalloc);
                }
                for(ia=0; ia<ilst->nr; ia++)
                {
                    ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia];
                }
                ils_local->nr += ilst->nr;
            }

            ireqt = &dd->constraint_comm->ireq[thread];
            if (ireq->n+ireqt->n > ireq->nalloc)
            {
                ireq->nalloc = over_alloc_large(ireq->n+ireqt->n);
                srenew(ireq->ind,ireq->nalloc);
            }
            for(ia=0; ia<ireqt->n; ia++)
            {
                ireq->ind[ireq->n+ia] = ireqt->ind[ia];
            }
            ireq->n += ireqt->n;
        }

        if (debug)
        {
            fprintf(debug,"Settles: total %3d\n",ils_local->nr/4);
        }
    }

    if (dd->constraint_comm) {
        int nral1;

        at_end =
            setup_specat_communication(dd,ireq,dd->constraint_comm,
                                       dd->constraints->ga2la,
                                       at_start,2,
                                       "constraint"," or lincs-order");
        
        /* Fill in the missing indices */
        ga2la_specat = dd->constraints->ga2la;

        nral1 = 1 + NRAL(F_CONSTR);
        for(i=0; i<ilc_local->nr; i+=nral1)
        {
            iap = ilc_local->iatoms + i;
            for(j=1; j<nral1; j++)
            {
                if (iap[j] < 0)
                {
                    iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1);
                }
            }
        }

        nral1 = 1 + NRAL(F_SETTLE);
        for(i=0; i<ils_local->nr; i+=nral1)
        {
            iap = ils_local->iatoms + i;
            for(j=1; j<nral1; j++)
            {
                if (iap[j] < 0)
                {
                    iap[j] = gmx_hash_get_minone(ga2la_specat,-iap[j]-1);
                }
            }
        }
    }
    else
    {
        at_end = at_start;
    }
    
    return at_end;
}
Beispiel #19
0
void gmx_sort_ilist_fe(t_idef *idef, const real *qA, const real *qB)
{
    int        ftype, nral, i, ic, ib, a;
    t_iparams *iparams;
    t_ilist   *ilist;
    t_iatom   *iatoms;
    gmx_bool   bPert;
    t_iatom   *iabuf;
    int        iabuf_nalloc;

    if (qB == NULL)
    {
        qB = qA;
    }

    iabuf_nalloc = 0;
    iabuf        = NULL;

    iparams = idef->iparams;

    for (ftype = 0; ftype < F_NRE; ftype++)
    {
        if (interaction_function[ftype].flags & IF_BOND)
        {
            ilist  = &idef->il[ftype];
            iatoms = ilist->iatoms;
            nral   = NRAL(ftype);
            ic     = 0;
            ib     = 0;
            i      = 0;
            while (i < ilist->nr)
            {
                /* Check if this interaction is perturbed */
                if (ip_q_pert(ftype, iatoms+i, iparams, qA, qB))
                {
                    /* Copy to the perturbed buffer */
                    if (ib + 1 + nral > iabuf_nalloc)
                    {
                        iabuf_nalloc = over_alloc_large(ib+1+nral);
                        srenew(iabuf, iabuf_nalloc);
                    }
                    for (a = 0; a < 1+nral; a++)
                    {
                        iabuf[ib++] = iatoms[i++];
                    }
                }
                else
                {
                    /* Copy in place */
                    for (a = 0; a < 1+nral; a++)
                    {
                        iatoms[ic++] = iatoms[i++];
                    }
                }
            }
            /* Now we now the number of non-perturbed interactions */
            ilist->nr_nonperturbed = ic;

            /* Copy the buffer with perturbed interactions to the ilist */
            for (a = 0; a < ib; a++)
            {
                iatoms[ic++] = iabuf[a];
            }

            if (debug)
            {
                fprintf(debug, "%s non-pert %d pert %d\n",
                        interaction_function[ftype].longname,
                        ilist->nr_nonperturbed,
                        ilist->nr-ilist->nr_nonperturbed);
            }
        }
    }

    sfree(iabuf);

    idef->ilsort = ilsortFE_SORTED;
}
Beispiel #20
0
void convert_params(int atnr, t_params nbtypes[],
                    t_molinfo *mi, t_molinfo *intermolecular_interactions,
                    int comb, double reppow, real fudgeQQ,
                    gmx_mtop_t *mtop)
{
    int             i;
    unsigned long   flags;
    gmx_ffparams_t *ffp;
    gmx_moltype_t  *molt;
    t_params       *plist;

    ffp           = &mtop->ffparams;
    ffp->atnr     = atnr;
    ffp->functype.clear();
    ffp->iparams.clear();
    ffp->reppow   = reppow;

    enter_function(&(nbtypes[F_LJ]),  static_cast<t_functype>(F_LJ),    comb, reppow, ffp, nullptr,
                   TRUE, TRUE);
    enter_function(&(nbtypes[F_BHAM]), static_cast<t_functype>(F_BHAM),  comb, reppow, ffp, nullptr,
                   TRUE, TRUE);

    for (size_t mt = 0; mt < mtop->moltype.size(); mt++)
    {
        molt = &mtop->moltype[mt];
        for (i = 0; (i < F_NRE); i++)
        {
            molt->ilist[i].iatoms.clear();

            plist = mi[mt].plist;

            flags = interaction_function[i].flags;
            if ((i != F_LJ) && (i != F_BHAM) && ((flags & IF_BOND) ||
                                                 (flags & IF_VSITE) ||
                                                 (flags & IF_CONSTRAINT)))
            {
                enter_function(&(plist[i]), static_cast<t_functype>(i), comb, reppow,
                               ffp, &molt->ilist[i],
                               FALSE, (i == F_POSRES  || i == F_FBPOSRES));
            }
        }
    }

    mtop->bIntermolecularInteractions = FALSE;
    if (intermolecular_interactions != nullptr)
    {
        /* Process the intermolecular interaction list */
        mtop->intermolecular_ilist = gmx::compat::make_unique<InteractionLists>();

        for (i = 0; (i < F_NRE); i++)
        {
            (*mtop->intermolecular_ilist)[i].iatoms.clear();

            plist = intermolecular_interactions->plist;

            if (plist[i].nr > 0)
            {
                flags = interaction_function[i].flags;
                /* For intermolecular interactions we (currently)
                 * only support potentials.
                 * Constraints and virtual sites would be possible,
                 * but require a lot of extra (bug-prone) code.
                 */
                if (!(flags & IF_BOND))
                {
                    gmx_fatal(FARGS, "The intermolecular_interaction section may only contain bonded potentials");
                }
                else if (NRAL(i) == 1) /* e.g. position restraints */
                {
                    gmx_fatal(FARGS, "Single atom interactions don't make sense in the intermolecular_interaction section, you can put them in the moleculetype section");
                }
                else if (flags & IF_CHEMBOND)
                {
                    gmx_fatal(FARGS, "The intermolecular_interaction can not contain chemically bonding interactions");
                }
                else
                {
                    enter_function(&(plist[i]), static_cast<t_functype>(i), comb, reppow,
                                   ffp, &(*mtop->intermolecular_ilist)[i],
                                   FALSE, FALSE);

                    mtop->bIntermolecularInteractions = TRUE;
                }
            }
        }

        if (!mtop->bIntermolecularInteractions)
        {
            mtop->intermolecular_ilist.reset(nullptr);
        }
    }

    ffp->fudgeQQ = fudgeQQ;
}
Beispiel #21
0
static void clean_vsite_dihs(t_params *plist, t_pindex pindex[], 
			   int cftype, int vsite_type[])
{
  int      ftype,i,parnr,k,l,m,n,nvsite,kept_i,vsnral;
  atom_id  atom,constr;
  atom_id  vsiteatoms[3];
  gmx_bool     bKeep,bUsed,bPresent;
  t_params *ps;
  
  ps = &(plist[cftype]);
  
  vsnral=0;
  kept_i=0;
  for(i=0; (i<ps->nr); i++) { /* for all dihedrals in the plist */
    bKeep=FALSE;
    /* check if all virtual sites are constructed from the same atoms */
    nvsite=0;
    for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */
      atom = ps->param[i].a[k];
      if (vsite_type[atom]!=NOTSET) {
	nvsite++;
	if (nvsite==1) {
	  /* store construction atoms of first vsite */
	  vsnral=NRAL(pindex[atom].ftype)-1;
	  for(m=0; (m<vsnral); m++)
	    vsiteatoms[m]=
	      plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
	  if (debug) {
	    fprintf(debug,"dih w. vsite: %u %u %u %u\n",
		    ps->param[i].AI+1,ps->param[i].AJ+1,
		    ps->param[i].AK+1,ps->param[i].AL+1);
	    fprintf(debug,"vsite %u from: %u %u %u\n",
		    atom+1,vsiteatoms[0]+1,vsiteatoms[1]+1,vsiteatoms[2]+1);
	  }
	} else 
	  /* check if this vsite is constructed from the same atoms */
	  if (vsnral == NRAL(pindex[atom].ftype)-1 )
	    for(m=0; (m<vsnral) && !bKeep; m++) {
	      bPresent=FALSE;
	      constr=
		plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
	      for(n=0; (n<vsnral) && !bPresent; n++)
		if (constr == vsiteatoms[n])
		  bPresent=TRUE;
	      if (!bPresent)
		bKeep=TRUE;
	    }
      }
    }
    
    /* keep all dihedrals with no virtual sites in them */
    if (nvsite==0)
      bKeep=TRUE;
    
    /* check if all atoms in dihedral are either virtual sites, or used in 
       construction of virtual sites. If so, keep it, if not throw away: */
    for(k=0; (k<4) && !bKeep; k++) { /* for all atoms in the dihedral */
      atom = ps->param[i].a[k];
      if (vsite_type[atom]==NOTSET) {
	bUsed=FALSE;
	for(m=0; (m<vsnral) && !bUsed; m++)
	  if (atom == vsiteatoms[m])
	    bUsed=TRUE;
	if (!bUsed) {
	  bKeep=TRUE;
	  if (debug) fprintf(debug,"unused atom in dih: %u\n",atom+1);
	}
      }
    }
      
    if ( bKeep ) {
      memcpy(&(ps->param[kept_i]),
	     &(ps->param[i]),(size_t)sizeof(ps->param[0]));
      kept_i++;
    }
  }

  if (ps->nr != kept_i)
    fprintf(stderr,"Removed   %4d %15ss with virtual sites, %5d left\n", 
	    ps->nr-kept_i, interaction_function[cftype].longname, kept_i);
  ps->nr=kept_i;
}
Beispiel #22
0
int set_vsites(gmx_bool bVerbose, t_atoms *atoms, gpp_atomtype_t atype,
		t_params plist[])
{
  int i,j,ftype;
  int nvsite,nrbond,nrang,nridih,nrset;
  gmx_bool bFirst,bSet,bERROR;
  at2vsitebond_t *at2vb;
  t_mybonded *bonds;
  t_mybonded *angles;
  t_mybonded *idihs;
  
  bFirst = TRUE;
  bERROR = TRUE;
  nvsite=0;
  if (debug)
    fprintf(debug, "\nCalculating parameters for virtual sites\n");

  /* Make a reverse list to avoid ninteractions^2 operations */
  at2vb = make_at2vsitebond(atoms->nr,plist);

  for(ftype=0; (ftype<F_NRE); ftype++)
    if ((interaction_function[ftype].flags & IF_VSITE) && ftype != F_VSITEN) {
      nrset=0;
      nvsite+=plist[ftype].nr;
      for(i=0; (i<plist[ftype].nr); i++) {
	/* check if all parameters are set */
	bSet=TRUE;
	for(j=0; j<NRFP(ftype) && bSet; j++)
	  bSet = plist[ftype].param[i].c[j]!=NOTSET;

	if (debug) {
	  fprintf(debug,"bSet=%s ",bool_names[bSet]);
	  print_param(debug,ftype,i,&plist[ftype].param[i]);
	}
	if (!bSet) {
	  if (bVerbose && bFirst) {
	    fprintf(stderr,"Calculating parameters for virtual sites\n");
	    bFirst=FALSE;
	  }
	  
	  nrbond=nrang=nridih=0;
	  bonds = NULL;
	  angles= NULL;
	  idihs = NULL;
	  nrset++;
	  /* now set the vsite parameters: */
	  get_bondeds(NRAL(ftype), plist[ftype].param[i].a, at2vb, plist, 
		      &nrbond, &bonds, &nrang,  &angles, &nridih, &idihs);
	  if (debug) {
	    fprintf(debug, "Found %d bonds, %d angles and %d idihs "
		    "for virtual site %u (%s)\n",nrbond,nrang,nridih,
		    plist[ftype].param[i].AI+1,
		    interaction_function[ftype].longname);
	    print_bad(debug, nrbond, bonds, nrang, angles, nridih, idihs);
	  } /* debug */
	  switch(ftype) {
	  case F_VSITE3: 
	    bERROR = 
	      calc_vsite3_param(atype, &(plist[ftype].param[i]), atoms,
				nrbond, bonds, nrang, angles);
	    break;
	  case F_VSITE3FD:
	    bERROR = 
	      calc_vsite3fd_param(&(plist[ftype].param[i]),
				  nrbond, bonds, nrang, angles);
	    break;
	  case F_VSITE3FAD:
	    bERROR = 
	      calc_vsite3fad_param(&(plist[ftype].param[i]),
				   nrbond, bonds, nrang, angles);
	    break;
	  case F_VSITE3OUT:
	    bERROR = 
	      calc_vsite3out_param(atype, &(plist[ftype].param[i]), atoms,
				   nrbond, bonds, nrang, angles);
	    break;
	  case F_VSITE4FD:
	    bERROR = 
	      calc_vsite4fd_param(&(plist[ftype].param[i]), 
				  nrbond, bonds, nrang, angles);
	    break;
	  case F_VSITE4FDN:
          bERROR = 
	      calc_vsite4fdn_param(&(plist[ftype].param[i]), 
                               nrbond, bonds, nrang, angles);
          break;
	  default:
	    gmx_fatal(FARGS,"Automatic parameter generation not supported "
			"for %s atom %d",
			interaction_function[ftype].longname,
			plist[ftype].param[i].AI+1);
	  } /* switch */
	  if (bERROR)
	    gmx_fatal(FARGS,"Automatic parameter generation not supported "
			"for %s atom %d for this bonding configuration",
			interaction_function[ftype].longname,
			plist[ftype].param[i].AI+1);
	  sfree(bonds);
	  sfree(angles);
	  sfree(idihs);
	} /* if bSet */
      } /* for i */
      if (debug && plist[ftype].nr)
	fprintf(stderr,"Calculated parameters for %d out of %d %s atoms\n",
		nrset,plist[ftype].nr,interaction_function[ftype].longname);
    } /* if IF_VSITE */

  done_at2vsitebond(atoms->nr,at2vb);
  
  return nvsite;
}
/*! \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);
}
Beispiel #24
0
static void clean_vsite_bonds(t_params *plist, t_pindex pindex[], 
			    int cftype, int vsite_type[])
{
  int      ftype,i,j,parnr,k,l,m,n,nvsite,nOut,kept_i,vsnral,vsitetype;
  int      nconverted,nremoved;
  atom_id  atom,oatom,constr,at1,at2;
  atom_id  vsiteatoms[MAXATOMLIST];
  gmx_bool     bKeep,bRemove,bUsed,bPresent,bThisFD,bThisOUT,bAllFD,bFirstTwo;
  t_params *ps;

  if (cftype == F_CONNBONDS)
    return;
  
  ps = &(plist[cftype]);
  vsnral=0;
  kept_i=0;
  nconverted=0;
  nremoved=0;
  nOut=0;
  for(i=0; (i<ps->nr); i++) { /* for all bonds in the plist */
    bKeep=FALSE;
    bRemove=FALSE;
    bAllFD=TRUE;
    /* check if all virtual sites are constructed from the same atoms */
    nvsite=0;
    if(debug) 
      fprintf(debug,"constr %u %u:",ps->param[i].AI+1,ps->param[i].AJ+1);
    for(k=0; (k<2) && !bKeep && !bRemove; k++) { 
      /* for all atoms in the bond */
      atom = ps->param[i].a[k];
      if (vsite_type[atom]!=NOTSET) {
	if(debug) {
	  fprintf(debug," d%d[%d: %d %d %d]",k,atom+1,
		  plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ+1,
		  plist[pindex[atom].ftype].param[pindex[atom].parnr].AK+1,
		  plist[pindex[atom].ftype].param[pindex[atom].parnr].AL+1);
	}
	nvsite++;
	bThisFD = ( (pindex[atom].ftype == F_VSITE3FD ) ||
                (pindex[atom].ftype == F_VSITE3FAD) ||
                (pindex[atom].ftype == F_VSITE4FD ) ||
                (pindex[atom].ftype == F_VSITE4FDN ) );
	bThisOUT= ( (pindex[atom].ftype == F_VSITE3OUT) &&
		    (interaction_function[cftype].flags & IF_CONSTRAINT) );
	bAllFD = bAllFD && bThisFD;
	if (bThisFD || bThisOUT) {
	  if(debug)fprintf(debug," %s",bThisOUT?"out":"fd");
	  oatom = ps->param[i].a[1-k]; /* the other atom */
	  if ( vsite_type[oatom]==NOTSET &&
	       oatom==plist[pindex[atom].ftype].param[pindex[atom].parnr].AJ ){
	    /* if the other atom isn't a vsite, and it is AI */
	    bRemove=TRUE;
	    if (bThisOUT)
	      nOut++;
	    if(debug)fprintf(debug," D-AI");
	  }
	}
	if (!bRemove) {
	  if (nvsite==1) {
	    /* if this is the first vsite we encounter then
	       store construction atoms */
	    vsnral=NRAL(pindex[atom].ftype)-1;
	    for(m=0; (m<vsnral); m++)
	      vsiteatoms[m]=
		plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
	  } else {
	    /* if it is not the first then
	       check if this vsite is constructed from the same atoms */
	    if (vsnral == NRAL(pindex[atom].ftype)-1 )
	      for(m=0; (m<vsnral) && !bKeep; m++) {
		bPresent=FALSE;
		constr=
		  plist[pindex[atom].ftype].param[pindex[atom].parnr].a[m+1];
		for(n=0; (n<vsnral) && !bPresent; n++)
		  if (constr == vsiteatoms[n])
		    bPresent=TRUE;
		if (!bPresent) {
		  bKeep=TRUE;
		  if(debug)fprintf(debug," !present");
		}
	      }
	    else {
	      bKeep=TRUE;
	      if(debug)fprintf(debug," !same#at");
	    }
	  }
	}
      }
    }
    
    if (bRemove) 
      bKeep=FALSE;
    else {
      /* if we have no virtual sites in this bond, keep it */
      if (nvsite==0) {
	if (debug)fprintf(debug," no vsite");
	bKeep=TRUE;
      }
    
      /* check if all non-vsite atoms are used in construction: */
      bFirstTwo=TRUE;
      for(k=0; (k<2) && !bKeep; k++) { /* for all atoms in the bond */
	atom = ps->param[i].a[k];
	if (vsite_type[atom]==NOTSET) {
	  bUsed=FALSE;
	  for(m=0; (m<vsnral) && !bUsed; m++)
	    if (atom == vsiteatoms[m]) {
	      bUsed=TRUE;
	      bFirstTwo = bFirstTwo && m<2;
	    }
	  if (!bUsed) {
	    bKeep=TRUE;
	    if(debug)fprintf(debug," !used");
	  }
	}
      }
      
      if ( ! ( bAllFD && bFirstTwo ) )
	/* check if all constructing atoms are constrained together */
	for (m=0; m<vsnral && !bKeep; m++) { /* all constr. atoms */
	  at1 = vsiteatoms[m];
	  at2 = vsiteatoms[(m+1) % vsnral];
	  bPresent=FALSE;
	  for (ftype=0; ftype<F_NRE; ftype++)
	    if ( interaction_function[ftype].flags & IF_CONSTRAINT )
	      for (j=0; (j<plist[ftype].nr) && !bPresent; j++)
		/* all constraints until one matches */
		bPresent = ( ( (plist[ftype].param[j].AI == at1) &&
			       (plist[ftype].param[j].AJ == at2) ) || 
			     ( (plist[ftype].param[j].AI == at2) &&
			       (plist[ftype].param[j].AJ == at1) ) );
	  if (!bPresent) {
	    bKeep=TRUE;
	    if(debug)fprintf(debug," !bonded");
	  }
	}
    }
    
    if ( bKeep ) {
      if(debug)fprintf(debug," keeping");
      /* now copy the bond to the new array */
      memcpy(&(ps->param[kept_i]),
	     &(ps->param[i]),(size_t)sizeof(ps->param[0]));
      kept_i++;
    } else if (IS_CHEMBOND(cftype)) {
      srenew(plist[F_CONNBONDS].param,plist[F_CONNBONDS].nr+1);
      memcpy(&(plist[F_CONNBONDS].param[plist[F_CONNBONDS].nr]),
	     &(ps->param[i]),(size_t)sizeof(plist[F_CONNBONDS].param[0]));
      plist[F_CONNBONDS].nr++;
      nconverted++;
    } else
      nremoved++;
    if(debug)fprintf(debug,"\n");
  }
  
  if (nremoved)
    fprintf(stderr,"Removed   %4d %15ss with virtual sites, %5d left\n",
	    nremoved, interaction_function[cftype].longname, kept_i);
  if (nconverted)
    fprintf(stderr,"Converted %4d %15ss with virtual sites to connections, %5d left\n",
	    nconverted, interaction_function[cftype].longname, kept_i);
  if (nOut)
    fprintf(stderr,"Warning: removed %d %ss with vsite with %s construction\n"
	    "         This vsite construction does not guarantee constant "
	    "bond-length\n"
	    "         If the constructions were generated by pdb2gmx ignore "
	    "this warning\n",
	    nOut, interaction_function[cftype].longname, 
	    interaction_function[F_VSITE3OUT].longname );
  ps->nr=kept_i;
}
Beispiel #25
0
gmx_bool constrain(FILE *fplog, gmx_bool bLog, gmx_bool bEner,
                   struct gmx_constr *constr,
                   t_idef *idef, t_inputrec *ir, gmx_ekindata_t *ekind,
                   t_commrec *cr,
                   gmx_int64_t step, int delta_step,
                   t_mdatoms *md,
                   rvec *x, rvec *xprime, rvec *min_proj,
                   gmx_bool bMolPBC, matrix box,
                   real lambda, real *dvdlambda,
                   rvec *v, tensor *vir,
                   t_nrnb *nrnb, int econq, gmx_bool bPscal,
                   real veta, real vetanew)
{
    gmx_bool    bOK, bDump;
    int         start, homenr, nrend;
    int         i, j, d;
    int         ncons, settle_error;
    tensor      vir_r_m_dr;
    rvec       *vstor;
    real        invdt, vir_fac, t;
    t_ilist    *settle;
    int         nsettle;
    t_pbc       pbc, *pbc_null;
    char        buf[22];
    t_vetavars  vetavar;
    int         nth, th;

    if (econq == econqForceDispl && !EI_ENERGY_MINIMIZATION(ir->eI))
    {
        gmx_incons("constrain called for forces displacements while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted");
    }

    bOK   = TRUE;
    bDump = FALSE;

    start  = 0;
    homenr = md->homenr;
    nrend  = start+homenr;

    /* set constants for pressure control integration */
    init_vetavars(&vetavar, econq != econqCoord,
                  veta, vetanew, ir, ekind, bPscal);

    if (ir->delta_t == 0)
    {
        invdt = 0;
    }
    else
    {
        invdt  = 1/ir->delta_t;
    }

    if (ir->efep != efepNO && EI_DYNAMICS(ir->eI))
    {
        /* Set the constraint lengths for the step at which this configuration
         * is meant to be. The invmasses should not be changed.
         */
        lambda += delta_step*ir->fepvals->delta_lambda;
    }

    if (vir != NULL)
    {
        clear_mat(vir_r_m_dr);
    }

    where();

    settle  = &idef->il[F_SETTLE];
    nsettle = settle->nr/(1+NRAL(F_SETTLE));

    if (nsettle > 0)
    {
        nth = gmx_omp_nthreads_get(emntSETTLE);
    }
    else
    {
        nth = 1;
    }

    if (nth > 1 && constr->vir_r_m_dr_th == NULL)
    {
        snew(constr->vir_r_m_dr_th, nth);
        snew(constr->settle_error, nth);
    }

    settle_error = -1;

    /* We do not need full pbc when constraints do not cross charge groups,
     * i.e. when dd->constraint_comm==NULL.
     * Note that PBC for constraints is different from PBC for bondeds.
     * For constraints there is both forward and backward communication.
     */
    if (ir->ePBC != epbcNONE &&
        (cr->dd || bMolPBC) && !(cr->dd && cr->dd->constraint_comm == NULL))
    {
        /* With pbc=screw the screw has been changed to a shift
         * by the constraint coordinate communication routine,
         * so that here we can use normal pbc.
         */
        pbc_null = set_pbc_dd(&pbc, ir->ePBC, cr->dd, FALSE, box);
    }
    else
    {
        pbc_null = NULL;
    }

    /* Communicate the coordinates required for the non-local constraints
     * for LINCS and/or SETTLE.
     */
    if (cr->dd)
    {
        dd_move_x_constraints(cr->dd, box, x, xprime, econq == econqCoord);
    }

    if (constr->lincsd != NULL)
    {
        bOK = constrain_lincs(fplog, bLog, bEner, ir, step, constr->lincsd, md, cr,
                              x, xprime, min_proj,
                              box, pbc_null, lambda, dvdlambda,
                              invdt, v, vir != NULL, vir_r_m_dr,
                              econq, nrnb,
                              constr->maxwarn, &constr->warncount_lincs);
        if (!bOK && constr->maxwarn >= 0)
        {
            if (fplog != NULL)
            {
                fprintf(fplog, "Constraint error in algorithm %s at step %s\n",
                        econstr_names[econtLINCS], gmx_step_str(step, buf));
            }
            bDump = TRUE;
        }
    }

    if (constr->nblocks > 0)
    {
        switch (econq)
        {
            case (econqCoord):
                bOK = bshakef(fplog, constr->shaked,
                              md->invmass, constr->nblocks, constr->sblock,
                              idef, ir, x, xprime, nrnb,
                              constr->lagr, lambda, dvdlambda,
                              invdt, v, vir != NULL, vir_r_m_dr,
                              constr->maxwarn >= 0, econq, &vetavar);
                break;
            case (econqVeloc):
                bOK = bshakef(fplog, constr->shaked,
                              md->invmass, constr->nblocks, constr->sblock,
                              idef, ir, x, min_proj, nrnb,
                              constr->lagr, lambda, dvdlambda,
                              invdt, NULL, vir != NULL, vir_r_m_dr,
                              constr->maxwarn >= 0, econq, &vetavar);
                break;
            default:
                gmx_fatal(FARGS, "Internal error, SHAKE called for constraining something else than coordinates");
                break;
        }

        if (!bOK && constr->maxwarn >= 0)
        {
            if (fplog != NULL)
            {
                fprintf(fplog, "Constraint error in algorithm %s at step %s\n",
                        econstr_names[econtSHAKE], gmx_step_str(step, buf));
            }
            bDump = TRUE;
        }
    }

    if (nsettle > 0)
    {
        int calcvir_atom_end;

        if (vir == NULL)
        {
            calcvir_atom_end = 0;
        }
        else
        {
            calcvir_atom_end = md->homenr;
        }

        switch (econq)
        {
            case econqCoord:
#pragma omp parallel for num_threads(nth) schedule(static)
                for (th = 0; th < nth; th++)
                {
                    int start_th, end_th;

                    if (th > 0)
                    {
                        clear_mat(constr->vir_r_m_dr_th[th]);
                    }

                    start_th = (nsettle* th   )/nth;
                    end_th   = (nsettle*(th+1))/nth;
                    if (start_th >= 0 && end_th - start_th > 0)
                    {
                        csettle(constr->settled,
                                end_th-start_th,
                                settle->iatoms+start_th*(1+NRAL(F_SETTLE)),
                                pbc_null,
                                x[0], xprime[0],
                                invdt, v ? v[0] : NULL, calcvir_atom_end,
                                th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th],
                                th == 0 ? &settle_error : &constr->settle_error[th],
                                &vetavar);
                    }
                }
                inc_nrnb(nrnb, eNR_SETTLE, nsettle);
                if (v != NULL)
                {
                    inc_nrnb(nrnb, eNR_CONSTR_V, nsettle*3);
                }
                if (vir != NULL)
                {
                    inc_nrnb(nrnb, eNR_CONSTR_VIR, nsettle*3);
                }
                break;
            case econqVeloc:
            case econqDeriv:
            case econqForce:
            case econqForceDispl:
#pragma omp parallel for num_threads(nth) schedule(static)
                for (th = 0; th < nth; th++)
                {
                    int start_th, end_th;

                    if (th > 0)
                    {
                        clear_mat(constr->vir_r_m_dr_th[th]);
                    }

                    start_th = (nsettle* th   )/nth;
                    end_th   = (nsettle*(th+1))/nth;

                    if (start_th >= 0 && end_th - start_th > 0)
                    {
                        settle_proj(constr->settled, econq,
                                    end_th-start_th,
                                    settle->iatoms+start_th*(1+NRAL(F_SETTLE)),
                                    pbc_null,
                                    x,
                                    xprime, min_proj, calcvir_atom_end,
                                    th == 0 ? vir_r_m_dr : constr->vir_r_m_dr_th[th],
                                    &vetavar);
                    }
                }
                /* This is an overestimate */
                inc_nrnb(nrnb, eNR_SETTLE, nsettle);
                break;
            case econqDeriv_FlexCon:
                /* Nothing to do, since the are no flexible constraints in settles */
                break;
            default:
                gmx_incons("Unknown constraint quantity for settle");
        }
    }

    if (settle->nr > 0)
    {
        /* Combine virial and error info of the other threads */
        for (i = 1; i < nth; i++)
        {
            m_add(vir_r_m_dr, constr->vir_r_m_dr_th[i], vir_r_m_dr);
            settle_error = constr->settle_error[i];
        }

        if (econq == econqCoord && settle_error >= 0)
        {
            bOK = FALSE;
            if (constr->maxwarn >= 0)
            {
                char buf[256];
                sprintf(buf,
                        "\nstep " "%"GMX_PRId64 ": Water molecule starting at atom %d can not be "
                        "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n",
                        step, ddglatnr(cr->dd, settle->iatoms[settle_error*(1+NRAL(F_SETTLE))+1]));
                if (fplog)
                {
                    fprintf(fplog, "%s", buf);
                }
                fprintf(stderr, "%s", buf);
                constr->warncount_settle++;
                if (constr->warncount_settle > constr->maxwarn)
                {
                    too_many_constraint_warnings(-1, constr->warncount_settle);
                }
                bDump = TRUE;
            }
        }
    }

    free_vetavars(&vetavar);

    if (vir != NULL)
    {
        switch (econq)
        {
            case econqCoord:
                vir_fac = 0.5/(ir->delta_t*ir->delta_t);
                break;
            case econqVeloc:
                vir_fac = 0.5/ir->delta_t;
                break;
            case econqForce:
            case econqForceDispl:
                vir_fac = 0.5;
                break;
            default:
                vir_fac = 0;
                gmx_incons("Unsupported constraint quantity for virial");
        }

        if (EI_VV(ir->eI))
        {
            vir_fac *= 2;  /* only constraining over half the distance here */
        }
        for (i = 0; i < DIM; i++)
        {
            for (j = 0; j < DIM; j++)
            {
                (*vir)[i][j] = vir_fac*vir_r_m_dr[i][j];
            }
        }
    }

    if (bDump)
    {
        dump_confs(fplog, step, constr->warn_mtop, start, homenr, cr, x, xprime, box);
    }

    if (econq == econqCoord)
    {
        if (ir->ePull == epullCONSTRAINT)
        {
            if (EI_DYNAMICS(ir->eI))
            {
                t = ir->init_t + (step + delta_step)*ir->delta_t;
            }
            else
            {
                t = ir->init_t;
            }
            set_pbc(&pbc, ir->ePBC, box);
            pull_constraint(ir->pull, md, &pbc, cr, ir->delta_t, t, x, xprime, v, *vir);
        }
        if (constr->ed && delta_step > 0)
        {
            /* apply the essential dynamcs constraints here */
            do_edsam(ir, step, cr, xprime, v, box, constr->ed);
        }
    }

    return bOK;
}
Beispiel #26
0
int dd_make_local_vsites(gmx_domdec_t *dd, int at_start, t_ilist *lil)
{
    gmx_domdec_specat_comm_t *spac;
    ind_req_t                *ireq;
    gmx_hash_t                ga2la_specat;
    int  ftype, nral, i, j, a;
    t_ilist                  *lilf;
    t_iatom                  *iatoms;
    int  at_end;

    spac         = dd->vsite_comm;
    ireq         = &spac->ireq[0];
    ga2la_specat = dd->ga2la_vsite;

    ireq->n = 0;
    /* Loop over all the home vsites */
    for (ftype = 0; ftype < F_NRE; ftype++)
    {
        if (interaction_function[ftype].flags & IF_VSITE)
        {
            nral = NRAL(ftype);
            lilf = &lil[ftype];
            for (i = 0; i < lilf->nr; i += 1+nral)
            {
                iatoms = lilf->iatoms + i;
                /* Check if we have the other atoms */
                for (j = 1; j < 1+nral; j++)
                {
                    if (iatoms[j] < 0)
                    {
                        /* This is not a home atom,
                         * we need to ask our neighbors.
                         */
                        a = -iatoms[j] - 1;
                        /* Check to not ask for the same atom more than once */
                        if (gmx_hash_get_minone(dd->ga2la_vsite, a) == -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;
                            /* Temporarily mark with -2,
                             * we get the index later.
                             */
                            gmx_hash_set(ga2la_specat, a, -2);
                        }
                    }
                }
            }
        }
    }

    at_end = setup_specat_communication(dd, ireq, dd->vsite_comm, ga2la_specat,
                                        at_start, 1, "vsite", "");

    /* Fill in the missing indices */
    for (ftype = 0; ftype < F_NRE; ftype++)
    {
        if (interaction_function[ftype].flags & IF_VSITE)
        {
            nral = NRAL(ftype);
            lilf = &lil[ftype];
            for (i = 0; i < lilf->nr; i += 1+nral)
            {
                iatoms = lilf->iatoms + i;
                for (j = 1; j < 1+nral; j++)
                {
                    if (iatoms[j] < 0)
                    {
                        iatoms[j] = gmx_hash_get_minone(ga2la_specat, -iatoms[j]-1);
                    }
                }
            }
        }
    }

    return at_end;
}
/*! \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);
    }
}
Beispiel #28
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;
}
Beispiel #29
0
void convert_params(int atnr, t_params nbtypes[],
                    t_molinfo *mi, t_molinfo *intermolecular_interactions,
                    int comb, double reppow, real fudgeQQ,
                    gmx_mtop_t *mtop)
{
    int             i, maxtypes, mt;
    unsigned long   flags;
    gmx_ffparams_t *ffp;
    gmx_moltype_t  *molt;
    t_params       *plist;

    maxtypes = 0;

    ffp           = &mtop->ffparams;
    ffp->ntypes   = 0;
    ffp->atnr     = atnr;
    ffp->functype = NULL;
    ffp->iparams  = NULL;
    ffp->reppow   = reppow;

    enter_function(&(nbtypes[F_LJ]),  (t_functype)F_LJ,    comb, reppow, ffp, NULL,
                   &maxtypes, TRUE, TRUE);
    enter_function(&(nbtypes[F_BHAM]), (t_functype)F_BHAM,  comb, reppow, ffp, NULL,
                   &maxtypes, TRUE, TRUE);

    for (mt = 0; mt < mtop->nmoltype; mt++)
    {
        molt = &mtop->moltype[mt];
        for (i = 0; (i < F_NRE); i++)
        {
            molt->ilist[i].nr     = 0;
            molt->ilist[i].iatoms = NULL;

            plist = mi[mt].plist;

            flags = interaction_function[i].flags;
            if ((i != F_LJ) && (i != F_BHAM) && ((flags & IF_BOND) ||
                                                 (flags & IF_VSITE) ||
                                                 (flags & IF_CONSTRAINT)))
            {
                enter_function(&(plist[i]), (t_functype)i, comb, reppow,
                               ffp, &molt->ilist[i],
                               &maxtypes, FALSE, (i == F_POSRES  || i == F_FBPOSRES));
            }
        }
    }

    mtop->bIntermolecularInteractions = FALSE;
    if (intermolecular_interactions != NULL)
    {
        /* Process the intermolecular interaction list */
        snew(mtop->intermolecular_ilist, F_NRE);

        for (i = 0; (i < F_NRE); i++)
        {
            mtop->intermolecular_ilist[i].nr     = 0;
            mtop->intermolecular_ilist[i].iatoms = NULL;

            plist = intermolecular_interactions->plist;

            if (plist[i].nr > 0)
            {
                flags = interaction_function[i].flags;
                /* For intermolecular interactions we (currently)
                 * only support potentials.
                 * Constraints and virtual sites would be possible,
                 * but require a lot of extra (bug-prone) code.
                 */
                if (!(flags & IF_BOND))
                {
                    gmx_fatal(FARGS, "The intermolecular_interaction section may only contain bonded potentials");
                }
                else if (NRAL(i) == 1) /* e.g. position restraints */
                {
                    gmx_fatal(FARGS, "Single atom interactions don't make sense in the intermolecular_interaction section, you can put them in the moleculetype section");
                }
                else if (flags & IF_CHEMBOND)
                {
                    gmx_fatal(FARGS, "The intermolecular_interaction can not contain chemically bonding interactions");
                }
                else
                {
                    enter_function(&(plist[i]), (t_functype)i, comb, reppow,
                                   ffp, &mtop->intermolecular_ilist[i],
                                   &maxtypes, FALSE, FALSE);

                    mtop->bIntermolecularInteractions = TRUE;
                }
            }
        }

        if (!mtop->bIntermolecularInteractions)
        {
            sfree(mtop->intermolecular_ilist);
        }
    }

    if (debug)
    {
        fprintf(debug, "%s, line %d: There are %d functypes in idef\n",
                __FILE__, __LINE__, ffp->ntypes);
    }

    ffp->fudgeQQ = fudgeQQ;
}
int dd_make_local_constraints(gmx_domdec_t *dd, int at_start,
                              const struct gmx_mtop_t *mtop,
                              const int *cginfo,
                              gmx_constr_t constr, int nrec,
                              t_ilist *il_local)
{
    gmx_domdec_constraints_t   *dc;
    t_ilist                    *ilc_local, *ils_local;
    ind_req_t                  *ireq;
    const t_blocka             *at2con_mt;
    const int                 **at2settle_mt;
    gmx_hash_t                 *ga2la_specat;
    int at_end, i, j;
    t_iatom                    *iap;

    // This code should not be called unless this condition is true,
    // because that's the only time init_domdec_constraints is
    // called...
    GMX_RELEASE_ASSERT(dd->bInterCGcons || dd->bInterCGsettles, "dd_make_local_constraints called when there are no local constraints");
    // ... and init_domdec_constraints always sets
    // dd->constraint_comm...
    GMX_RELEASE_ASSERT(dd->constraint_comm, "Invalid use of dd_make_local_constraints before construction of constraint_comm");
    // ... which static analysis needs to be reassured about, because
    // otherwise, when dd->bInterCGsettles is
    // true. dd->constraint_comm is unilaterally dereferenced before
    // the call to atoms_to_settles.

    dc = dd->constraints;

    ilc_local = &il_local[F_CONSTR];
    ils_local = &il_local[F_SETTLE];

    dc->ncon      = 0;
    ilc_local->nr = 0;
    if (dd->constraint_comm)
    {
        at2con_mt = atom2constraints_moltype(constr);
        ireq      = &dd->constraint_comm->ireq[0];
        ireq->n   = 0;
    }
    else
    {
        // Currently unreachable
        at2con_mt = NULL;
        ireq      = NULL;
    }

    if (dd->bInterCGsettles)
    {
        at2settle_mt  = atom2settle_moltype(constr);
        ils_local->nr = 0;
    }
    else
    {
        /* Settle works inside charge groups, we assigned them already */
        at2settle_mt = NULL;
    }

    if (at2settle_mt == NULL)
    {
        atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec,
                             ilc_local, ireq);
    }
    else
    {
        int t0_set;
        int thread;

        /* Do the constraints, if present, on the first thread.
         * Do the settles on all other threads.
         */
        t0_set = ((at2con_mt != NULL && dc->nthread > 1) ? 1 : 0);

#pragma omp parallel for num_threads(dc->nthread) schedule(static)
        for (thread = 0; thread < dc->nthread; thread++)
        {
            try
            {
                if (at2con_mt && thread == 0)
                {
                    atoms_to_constraints(dd, mtop, cginfo, at2con_mt, nrec,
                                         ilc_local, ireq);
                }

                if (thread >= t0_set)
                {
                    int        cg0, cg1;
                    t_ilist   *ilst;
                    ind_req_t *ireqt;

                    /* Distribute the settle check+assignments over
                     * dc->nthread or dc->nthread-1 threads.
                     */
                    cg0 = (dd->ncg_home*(thread-t0_set  ))/(dc->nthread-t0_set);
                    cg1 = (dd->ncg_home*(thread-t0_set+1))/(dc->nthread-t0_set);

                    if (thread == t0_set)
                    {
                        ilst = ils_local;
                    }
                    else
                    {
                        ilst = &dc->ils[thread];
                    }
                    ilst->nr = 0;

                    ireqt = &dd->constraint_comm->ireq[thread];
                    if (thread > 0)
                    {
                        ireqt->n = 0;
                    }

                    atoms_to_settles(dd, mtop, cginfo, at2settle_mt,
                                     cg0, cg1,
                                     ilst, ireqt);
                }
            }
            GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
        }

        /* Combine the generate settles and requested indices */
        for (thread = 1; thread < dc->nthread; thread++)
        {
            t_ilist   *ilst;
            ind_req_t *ireqt;
            int        ia;

            if (thread > t0_set)
            {
                ilst = &dc->ils[thread];
                if (ils_local->nr + ilst->nr > ils_local->nalloc)
                {
                    ils_local->nalloc = over_alloc_large(ils_local->nr + ilst->nr);
                    srenew(ils_local->iatoms, ils_local->nalloc);
                }
                for (ia = 0; ia < ilst->nr; ia++)
                {
                    ils_local->iatoms[ils_local->nr+ia] = ilst->iatoms[ia];
                }
                ils_local->nr += ilst->nr;
            }

            ireqt = &dd->constraint_comm->ireq[thread];
            if (ireq->n+ireqt->n > ireq->nalloc)
            {
                ireq->nalloc = over_alloc_large(ireq->n+ireqt->n);
                srenew(ireq->ind, ireq->nalloc);
            }
            for (ia = 0; ia < ireqt->n; ia++)
            {
                ireq->ind[ireq->n+ia] = ireqt->ind[ia];
            }
            ireq->n += ireqt->n;
        }

        if (debug)
        {
            fprintf(debug, "Settles: total %3d\n", ils_local->nr/4);
        }
    }

    if (dd->constraint_comm)
    {
        int nral1;

        at_end =
            setup_specat_communication(dd, ireq, dd->constraint_comm,
                                       dd->constraints->ga2la,
                                       at_start, 2,
                                       "constraint", " or lincs-order");

        /* Fill in the missing indices */
        ga2la_specat = dd->constraints->ga2la;

        nral1 = 1 + NRAL(F_CONSTR);
        for (i = 0; i < ilc_local->nr; i += nral1)
        {
            iap = ilc_local->iatoms + i;
            for (j = 1; j < nral1; j++)
            {
                if (iap[j] < 0)
                {
                    iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1);
                }
            }
        }

        nral1 = 1 + NRAL(F_SETTLE);
        for (i = 0; i < ils_local->nr; i += nral1)
        {
            iap = ils_local->iatoms + i;
            for (j = 1; j < nral1; j++)
            {
                if (iap[j] < 0)
                {
                    iap[j] = gmx_hash_get_minone(ga2la_specat, -iap[j]-1);
                }
            }
        }
    }
    else
    {
        // Currently unreachable
        at_end = at_start;
    }

    return at_end;
}