예제 #1
0
SelectionCollection::Impl::Impl(gmx_ana_poscalc_coll_t *pcc)
    : _options("selection", "Common selection control"),
      _debugLevel(0), _grps(NULL)
{
    _sc.root      = NULL;
    _sc.nvars     = 0;
    _sc.varstrs   = NULL;
    _sc.top       = NULL;
    gmx_ana_index_clear(&_sc.gall);
    _sc.pcc       = pcc;
    _sc.mempool   = NULL;
    _sc.symtab    = NULL;

    // TODO: This is not exception-safe if any called function throws.
    if (_sc.pcc == NULL)
    {
        int rc = gmx_ana_poscalc_coll_create(&_sc.pcc);
        if (rc != 0)
        {
            // TODO: A more reasonable error
            GMX_THROW(InternalError("Failed to create position calculation collection"));
        }
        _flags.set(Impl::efOwnPositionCollection);
    }
    _gmx_sel_symtab_create(&_sc.symtab);
    gmx_ana_selmethod_register_defaults(_sc.symtab);
}
예제 #2
0
/*!
 * \param[out]  selp    Pointer to receive a pointer to the created selection
 *      element (set to NULL on error).
 * \param[in]   method  Keyword selection method to evaluate.
 * \param[in]   param   Parameter that gives the group to evaluate \p method in.
 * \param[in]   scanner Scanner data structure.
 * \returns     0 on success, non-zero error code on error.
 *
 * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
 * that evaluates the keyword method given by \p method in the group given by
 * \p param.
 */
int
_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
                                t_selexpr_param *param, void *scanner)
{
    t_selelem            *sel;
    t_methoddata_kweval  *data;

    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
    char  buf[1024];
    sprintf(buf, "In evaluation of '%s'", method->name);
    gmx::MessageStringContext   context(errors, buf);

    if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
        || method->outinit || method->pupdate)
    {
        _gmx_selexpr_free_params(param);
        GMX_ERROR(gmx::eeInternalError,
                  "Unsupported keyword method for arbitrary group evaluation");
    }

    *selp = NULL;
    sel = _gmx_selelem_create(SEL_EXPRESSION);
    _gmx_selelem_set_method(sel, method, scanner);

    snew(data, 1);
    data->kwmethod = sel->u.expr.method;
    data->kwmdata  = sel->u.expr.mdata;
    gmx_ana_index_clear(&data->g);

    snew(sel->u.expr.method, 1);
    memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
    sel->u.expr.method->flags       |= SMETH_VARNUMVAL;
    sel->u.expr.method->init_data    = NULL;
    sel->u.expr.method->set_poscoll  = NULL;
    sel->u.expr.method->init         = method->init ? &init_kweval : NULL;
    sel->u.expr.method->outinit      = &init_output_kweval;
    sel->u.expr.method->free         = &free_data_kweval;
    sel->u.expr.method->init_frame   = method->init_frame ? &init_frame_kweval : NULL;
    sel->u.expr.method->update       = &evaluate_kweval;
    sel->u.expr.method->pupdate      = NULL;
    sel->u.expr.method->nparams      = asize(smparams_kweval);
    sel->u.expr.method->param        = smparams_kweval;
    _gmx_selelem_init_method_params(sel, scanner);
    sel->u.expr.mdata = data;

    sel->u.expr.method->param[0].val.u.g = &data->g;

    sfree(param->name);
    param->name = NULL;
    if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
                               sel->u.expr.method->param, sel, scanner))
    {
        _gmx_selelem_free(sel);
        return -1;
    }
    *selp = sel;
    return 0;
}
/*!
 * \param[in] g  Index group structure.
 *
 * The pointer \p g is not freed.
 */
void
gmx_ana_index_deinit(gmx_ana_index_t *g)
{
    if (g->nalloc_index > 0)
    {
        sfree(g->index);
    }
    gmx_ana_index_clear(g);
}
예제 #4
0
SelectionCollection::Impl::Impl()
    : maxAtomIndex_(0), debugLevel_(0), bExternalGroupsSet_(false), grps_(NULL)
{
    sc_.nvars     = 0;
    sc_.varstrs   = NULL;
    sc_.top       = NULL;
    gmx_ana_index_clear(&sc_.gall);
    sc_.mempool   = NULL;
    sc_.symtab.reset(new SelectionParserSymbolTable);
    gmx_ana_selmethod_register_defaults(sc_.symtab.get());
}
예제 #5
0
/*!
 * \param[in,out] val  Value structure to allocate.
 * \param[in]     n    Maximum number of values needed.
 * \returns       Zero on success.
 *
 * Reserves memory for the values within \p val to store at least \p n values,
 * of the type specified in the \p val structure.
 *
 * If the type is \ref POS_VALUE or \ref GROUP_VALUE, memory is reserved for
 * the data structures, but no memory is reserved inside these newly allocated
 * data structures.
 * Similarly, for \ref STR_VALUE values, the pointers are set to NULL.
 * For other values, the memory is uninitialized.
 */
int
_gmx_selvalue_reserve(gmx_ana_selvalue_t *val, int n)
{
    int  i;

    if (val->nalloc == -1)
    {
        return 0;
    }

    if (!val->u.ptr || val->nalloc < n)
    {
        switch (val->type)
        {
            case INT_VALUE:   srenew(val->u.i, n); break;
            case REAL_VALUE:  srenew(val->u.r, n); break;
            case STR_VALUE:
                srenew(val->u.s, n);
                for (i = val->nalloc; i < n; ++i)
                {
                    val->u.s[i] = NULL;
                }
                break;
            case POS_VALUE:
                srenew(val->u.p, n);
                for (i = val->nalloc; i < n; ++i)
                {
                    gmx_ana_pos_clear(&val->u.p[i]);
                }
                break;
            case GROUP_VALUE:
                srenew(val->u.g, n);
                for (i = val->nalloc; i < n; ++i)
                {
                    gmx_ana_index_clear(&val->u.g[i]);
                }
                break;
            case NO_VALUE:    break;
        }
        val->nalloc = n;
    }
    return 0;
}
예제 #6
0
파일: selection.c 프로젝트: aar2163/GROMACS
/*!
 * \param[out] scp Pointer to a newly allocated empty selection collection.
 * \param[in]  pcc Position calculation data structure to use for selection
 *   position evaluation.
 * \returns    0 on success.
 */
int
gmx_ana_selcollection_create(gmx_ana_selcollection_t **scp,
                             gmx_ana_poscalc_coll_t *pcc)
{
    gmx_ana_selcollection_t *sc;
    
    snew(sc, 1);
    sc->rpost     = NULL;
    sc->spost     = NULL;
    sc->selstr    = NULL;
    sc->root      = NULL;
    sc->nr        = 0;
    sc->sel       = NULL;
    sc->top       = NULL;
    gmx_ana_index_clear(&sc->gall);
    sc->pcc       = pcc;
    _gmx_sel_symtab_create(&sc->symtab);
    *scp = sc;
    return 0;
}
예제 #7
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);
    }
}
예제 #8
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);
    }
}