Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
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;
}