Esempio n. 1
0
static void constr_recur(t_blocka *at2con,
                         t_ilist *ilist, t_iparams *iparams, gmx_bool bTopB,
                         int at, int depth, int nc, int *path,
                         real r0, real r1, real *r2max,
                         int *count)
{
    int      ncon1;
    t_iatom *ia1, *ia2;
    int      c, con, a1;
    gmx_bool bUse;
    t_iatom *ia;
    real     len, rn0, rn1;

    (*count)++;

    ncon1 = ilist[F_CONSTR].nr/3;
    ia1   = ilist[F_CONSTR].iatoms;
    ia2   = ilist[F_CONSTRNC].iatoms;

    /* Loop over all constraints connected to this atom */
    for (c = at2con->index[at]; c < at2con->index[at+1]; c++)
    {
        con = at2con->a[c];
        /* Do not walk over already used constraints */
        bUse = TRUE;
        for (a1 = 0; a1 < depth; a1++)
        {
            if (con == path[a1])
            {
                bUse = FALSE;
            }
        }
        if (bUse)
        {
            ia = constr_iatomptr(ncon1, ia1, ia2, con);
            /* Flexible constraints currently have length 0, which is incorrect */
            if (!bTopB)
            {
                len = iparams[ia[0]].constr.dA;
            }
            else
            {
                len = iparams[ia[0]].constr.dB;
            }
            /* In the worst case the bond directions alternate */
            if (nc % 2 == 0)
            {
                rn0 = r0 + len;
                rn1 = r1;
            }
            else
            {
                rn0 = r0;
                rn1 = r1 + len;
            }
            /* Assume angles of 120 degrees between all bonds */
            if (rn0*rn0 + rn1*rn1 + rn0*rn1 > *r2max)
            {
                *r2max = rn0*rn0 + rn1*rn1 + r0*rn1;
                if (debug)
                {
                    fprintf(debug, "Found longer constraint distance: r0 %5.3f r1 %5.3f rmax %5.3f\n", rn0, rn1, sqrt(*r2max));
                    for (a1 = 0; a1 < depth; a1++)
                    {
                        fprintf(debug, " %d %5.3f",
                                path[a1],
                                iparams[constr_iatomptr(ncon1, ia1, ia2, con)[0]].constr.dA);
                    }
                    fprintf(debug, " %d %5.3f\n", con, len);
                }
            }
            /* Limit the number of recursions to 1000*nc,
             * so a call does not take more than a second,
             * even for highly connected systems.
             */
            if (depth + 1 < nc && *count < 1000*nc)
            {
                if (ia[1] == at)
                {
                    a1 = ia[2];
                }
                else
                {
                    a1 = ia[1];
                }
                /* Recursion */
                path[depth] = con;
                constr_recur(at2con, ilist, iparams,
                             bTopB, a1, depth+1, nc, path, rn0, rn1, r2max, count);
                path[depth] = -1;
            }
        }
    }
}
/*! \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);
    }
}
Esempio n. 3
0
static int count_triangle_constraints(t_ilist *ilist,t_blocka *at2con)
{
    int  ncon1,ncon_tot;
    int  c0,a00,a01,n1,c1,a10,a11,ac1,n2,c2,a20,a21;
    int  ncon_triangle;
    gmx_bool bTriangle;
    t_iatom *ia1,*ia2,*iap;
    
    ncon1    = ilist[F_CONSTR].nr/3;
    ncon_tot = ncon1 + ilist[F_CONSTRNC].nr/3;

    ia1 = ilist[F_CONSTR].iatoms;
    ia2 = ilist[F_CONSTRNC].iatoms;
    
    ncon_triangle = 0;
    for(c0=0; c0<ncon_tot; c0++)
    {
        bTriangle = FALSE;
        iap = constr_iatomptr(ncon1,ia1,ia2,c0);
        a00 = iap[1];
        a01 = iap[2];
        for(n1=at2con->index[a01]; n1<at2con->index[a01+1]; n1++)
        {
            c1 = at2con->a[n1];
            if (c1 != c0)
            {
                iap = constr_iatomptr(ncon1,ia1,ia2,c1);
                a10 = iap[1];
                a11 = iap[2];
                if (a10 == a01)
                {
                    ac1 = a11;
                }
                else
                {
                    ac1 = a10;
                }
                for(n2=at2con->index[ac1]; n2<at2con->index[ac1+1]; n2++)
                {
                    c2 = at2con->a[n2];
                    if (c2 != c0 && c2 != c1)
                    {
                        iap = constr_iatomptr(ncon1,ia1,ia2,c2);
                        a20 = iap[1];
                        a21 = iap[2];
                        if (a20 == a00 || a21 == a00)
                        {
                            bTriangle = TRUE;
                        }
                    }
                }
            }
        }
        if (bTriangle)
        {
            ncon_triangle++;
        }
    }
    
    return ncon_triangle;
}
/*! \brief Walks over the constraints out from the local atoms into the non-local atoms and adds them to a list */
static void walk_out(int con, int con_offset, int a, int offset, int nrec,
                     int ncon1, const t_iatom *ia1, const t_iatom *ia2,
                     const t_blocka *at2con,
                     const gmx_ga2la_t *ga2la, gmx_bool bHomeConnect,
                     gmx_domdec_constraints_t *dc,
                     gmx_domdec_specat_comm_t *dcc,
                     t_ilist *il_local,
                     ind_req_t *ireq)
{
    int            a1_gl, a2_gl, a_loc, i, coni, b;
    const t_iatom *iap;

    if (dc->gc_req[con_offset+con] == 0)
    {
        /* Add this non-home constraint to the list */
        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]   = (bHomeConnect ? 1 : 0);
        dc->gc_req[con_offset+con] = 1;
        if (il_local->nr + 3 > il_local->nalloc)
        {
            il_local->nalloc = over_alloc_dd(il_local->nr+3);
            srenew(il_local->iatoms, il_local->nalloc);
        }
        iap = constr_iatomptr(ncon1, ia1, ia2, con);
        il_local->iatoms[il_local->nr++] = iap[0];
        a1_gl = offset + iap[1];
        a2_gl = offset + iap[2];
        /* The following indexing code can probably be optizimed */
        if (ga2la_get_home(ga2la, a1_gl, &a_loc))
        {
            il_local->iatoms[il_local->nr++] = a_loc;
        }
        else
        {
            /* We set this index later */
            il_local->iatoms[il_local->nr++] = -a1_gl - 1;
        }
        if (ga2la_get_home(ga2la, a2_gl, &a_loc))
        {
            il_local->iatoms[il_local->nr++] = a_loc;
        }
        else
        {
            /* We set this index later */
            il_local->iatoms[il_local->nr++] = -a2_gl - 1;
        }
        dc->ncon++;
    }
    /* Check to not ask for the same atom more than once */
    if (gmx_hash_get_minone(dc->ga2la, offset+a) == -1)
    {
        assert(dcc);
        /* 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++] = offset + a;
        /* Temporarily mark with -2, we get the index later */
        gmx_hash_set(dc->ga2la, offset+a, -2);
    }

    if (nrec > 0)
    {
        for (i = at2con->index[a]; i < at2con->index[a+1]; i++)
        {
            coni = at2con->a[i];
            if (coni != con)
            {
                /* Walk further */
                iap = constr_iatomptr(ncon1, ia1, ia2, coni);
                if (a == iap[1])
                {
                    b = iap[2];
                }
                else
                {
                    b = iap[1];
                }
                if (!ga2la_get_home(ga2la, offset+b, &a_loc))
                {
                    walk_out(coni, con_offset, b, offset, nrec-1,
                             ncon1, ia1, ia2, at2con,
                             ga2la, FALSE, dc, dcc, il_local, ireq);
                }
            }
        }
    }
}