Beispiel #1
0
/*!
 * \param[in] top   Not used.
 * \param[in] npar  Not used (should be 2).
 * \param[in] param Method parameters (should point to \ref smparams_permute).
 * \param[in] data  Should point to a \p t_methoddata_permute.
 * \returns   0 if the input permutation is valid, -1 on error.
 */
static void
init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
{
    t_methoddata_permute *d = (t_methoddata_permute *)data;
    int                   i;

    gmx_ana_index_reserve(&d->g, d->p.g->isize);
    d->n    = param[1].val.nr;
    d->perm = param[1].val.u.i;
    if (d->p.nr % d->n != 0)
    {
        GMX_THROW(gmx::InconsistentInputError(
                          gmx::formatString("The number of positions to be permuted is not divisible by %d", d->n)));
    }
    snew(d->rperm, d->n);
    for (i = 0; i < d->n; ++i)
    {
        d->rperm[i] = -1;
    }
    for (i = 0; i < d->n; ++i)
    {
        d->perm[i]--;
        if (d->perm[i] < 0 || d->perm[i] >= d->n)
        {
            GMX_THROW(gmx::InvalidInputError("Invalid permutation"));
        }
        if (d->rperm[d->perm[i]] >= 0)
        {
            GMX_THROW(gmx::InvalidInputError("Invalid permutation"));
        }
        d->rperm[d->perm[i]] = i;
    }
}
Beispiel #2
0
/*!
 * \param[in] top   Not used.
 * \param[in] npar  Not used (should be 2).
 * \param[in] param Method parameters (should point to \ref smparams_permute).
 * \param[in] data  Should point to a \p t_methoddata_permute.
 * \returns   0 if the input permutation is valid, -1 on error.
 */
static int
init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
{
    t_methoddata_permute *d = (t_methoddata_permute *)data;
    int                   i;

    gmx_ana_index_reserve(&d->g, d->p.g->isize);
    d->n    = param[1].val.nr;
    d->perm = param[1].val.u.i;
    if (d->p.nr % d->n != 0)
    {
        fprintf(stderr, "error: the number of positions to be permuted is not divisible by %d\n",
                d->n);
        return -1;
    }
    snew(d->rperm, d->n);
    for (i = 0; i < d->n; ++i)
    {
        d->rperm[i] = -1;
    }
    for (i = 0; i < d->n; ++i)
    {
        d->perm[i]--;
        if (d->perm[i] < 0 || d->perm[i] >= d->n)
        {
            fprintf(stderr, "invalid permutation");
            return -1;
        }
        if (d->rperm[d->perm[i]] >= 0)
        {
            fprintf(stderr, "invalid permutation");
            return -1;
        }
        d->rperm[d->perm[i]] = i;
    }
    return 0;
}
Beispiel #3
0
/*! \brief
 * Setups the static base calculation for a position calculation.
 *
 * \param[in,out] pc   Position calculation to setup the base for.
 */
static void
setup_base(gmx_ana_poscalc_t *pc)
{
    gmx_ana_poscalc_t *base, *pbase, *next;
    gmx_ana_index_t    gp, g;

    /* Exit immediately if pc should not have a base. */
    if (!can_use_base(pc))
    {
        return;
    }

    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
    gmx_ana_index_clear(&g);
    gmx_ana_index_reserve(&g, pc->b.nra);
    pbase = pc;
    base = pc->coll->first;
    while (base)
    {
        /* Save the next calculation so that we can safely delete base */
        next = base->next;
        /* Skip pc, calculations that already have a base (we should match the
         * base instead), as well as calculations that should not have a base.
         * If the above conditions are met, check whether we should do a
         * merge.
         */
        if (base != pc && !base->sbase && can_use_base(base)
            && should_merge(pbase, base, &gp, &g))
        {
            /* Check whether this is the first base found */
            if (pbase == pc)
            {
                /* Create a real base if one is not present */
                if (!base->p)
                {
                    pbase = create_simple_base(base);
                }
                else
                {
                    pbase = base;
                }
                /* Make it a base for pc as well */
                merge_to_base(pbase, pc);
                pc->sbase = pbase;
                pbase->refcount++;
            }
            else /* This was not the first base */
            {
                if (!base->p)
                {
                    /* If it is not a real base, just make the new base as
                     * the base for it as well. */
                    merge_to_base(pbase, base);
                    base->sbase = pbase;
                    pbase->refcount++;
                }
                else
                {
                    /* If base is a real base, merge it with the new base
                     * and delete it. */
                    merge_bases(pbase, base);
                }
            }
            gmx_ana_index_set(&gp, pbase->b.nra, pbase->b.a, NULL, 0);
            gmx_ana_index_reserve(&g, pc->b.nra);
        }
        /* Proceed to the next unchecked calculation */
        base = next;
    }

    gmx_ana_index_deinit(&g);

    /* If no base was found, create one if one is required */
    if (!pc->sbase && (pc->flags & POS_DYNAMIC)
        && (pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
    {
        create_simple_base(pc);
    }
}
Beispiel #4
0
/*! \brief
 * Merges a calculation into another calculation such that the new calculation
 * can be used as a base.
 *
 * \param[in,out] base Base calculation to merge to.
 * \param[in,out] pc   Position calculation to merge to \p base.
 *
 * After the call, \p base can be used as a base for \p pc (or any calculation
 * that used it as a base).
 * It is assumed that any overlap between \p base and \p pc is in complete
 * blocks, i.e., that the merge is possible.
 */
static void
merge_to_base(gmx_ana_poscalc_t *base, gmx_ana_poscalc_t *pc)
{
    gmx_ana_index_t  gp, gb, g;
    int              isize, bnr;
    int              i, j, bi, bj, bo;

    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
    gmx_ana_index_set(&gb, base->b.nra, base->b.a, NULL, 0);
    isize = gmx_ana_index_difference_size(&gp, &gb);
    if (isize > 0)
    {
        gmx_ana_index_clear(&g);
        gmx_ana_index_reserve(&g, base->b.nra + isize);
        /* Find the new blocks */
        gmx_ana_index_difference(&g, &gp, &gb);
        /* Count the blocks in g */
        i = bi = bnr = 0;
        while (i < g.isize)
        {
            while (pc->b.a[pc->b.index[bi]] != g.index[i])
            {
                ++bi;
            }
            i += pc->b.index[bi+1] - pc->b.index[bi];
            ++bnr;
            ++bi;
        }
        /* Merge the atoms into a temporary structure */
        gmx_ana_index_merge(&g, &gb, &g);
        /* Merge the blocks */
        srenew(base->b.index, base->b.nr + bnr + 1);
        i  = g.isize - 1;
        bi = base->b.nr - 1;
        bj = pc->b.nr - 1;
        bo = base->b.nr + bnr - 1;
        base->b.index[bo+1] = i + 1;
        while (bo >= 0)
        {
            if (bi < 0 || base->b.a[base->b.index[bi+1]-1] != g.index[i])
            {
                i -= pc->b.index[bj+1] - pc->b.index[bj];
                --bj;
            }
            else
            {
                if (bj >= 0 && pc->b.a[pc->b.index[bj+1]-1] == g.index[i])
                {
                    --bj;
                }
                i -= base->b.index[bi+1] - base->b.index[bi];
                --bi;
            }
            base->b.index[bo] = i + 1;
            --bo;
        }
        base->b.nr           += bnr;
        base->b.nalloc_index += bnr;
        sfree(base->b.a);
        base->b.nra      = g.isize;
        base->b.a        = g.index;
        base->b.nalloc_a = g.isize;
        /* Refresh the gmax field */
        gmx_ana_index_set(&base->gmax, base->b.nra, base->b.a, NULL, 0);
    }
}