コード例 #1
0
ファイル: evaluate.cpp プロジェクト: daniellandau/gromacs
/*!
 * \param[in] data Data for the current frame.
 * \param[in] sel Selection element being evaluated.
 * \param[in] g   Group for which \p sel should be evaluated.
 * \returns   0 on success, a non-zero error code on error.
 *
 * Short-circuiting evaluation of logical OR expressions.
 *
 * Starts by evaluating the first child element in the group \p g.
 * For each subsequent child, finds the part of \p g that is not
 * included the value of any previous child, and evaluates the child
 * in that group until the last child is evaluated or all of \p g
 * is included in some child value.
 * The value of \p sel is set to the union of all the (evaluated)
 * child values.
 *
 * If the first child does not have an evaluation function, its value is
 * used without evaluation.
 * This happens if the first child is a constant expression, the selection
 * has been compiled, and the evaluation group is the same for each frame.
 * In this case, the compiler has taken care of that the child value is a
 * subset of \p g, making it unnecessary to evaluate it.
 *
 * This function is used as gmx::SelectionTreeElement::evaluate for
 * \ref SEL_BOOLEAN elements with \ref BOOL_OR.
 */
void
_gmx_sel_evaluate_or(gmx_sel_evaluate_t                     *data,
                     const gmx::SelectionTreeElementPointer &sel,
                     gmx_ana_index_t                        *g)
{
    gmx_ana_index_t             tmp, tmp2;

    SelectionTreeElementPointer child = sel->child;
    if (child->evaluate)
    {
        MempoolSelelemReserver reserver(child, g->isize);
        child->evaluate(data, child, g);
        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
    }
    else
    {
        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
    }
    child = child->next;
    while (child && tmp.isize > 0)
    {
        {
            MempoolSelelemReserver reserver(child, tmp.isize);
            child->evaluate(data, child, &tmp);
            gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
        }
        sel->v.u.g->isize += tmp.isize;
        tmp.isize          = tmp2.isize;
        tmp.index          = tmp2.index;
        child              = child->next;
    }
    gmx_ana_index_sort(sel->v.u.g);
}
コード例 #2
0
ファイル: evaluate.cpp プロジェクト: daniellandau/gromacs
/*!
 * \param[in] data Data for the current frame.
 * \param[in] sel Selection element being evaluated.
 * \param[in] g   Group for which \p sel should be evaluated.
 * \returns   0 on success, a non-zero error code on error.
 *
 * Short-circuiting evaluation of logical AND expressions.
 *
 * Starts by evaluating the first child element in the group \p g.
 * The each following child element is evaluated in the intersection
 * of all the previous values until all children have been evaluated
 * or the intersection becomes empty.
 * The value of \p sel is set to the intersection of all the (evaluated)
 * child values.
 *
 * If the first child does not have an evaluation function, it is skipped
 * and the evaluation is started at the second child.
 * This happens if the first child is a constant expression and during
 * compilation it was detected that the evaluation group is always a subset
 * of the constant group
 * (currently, the compiler never detects this).
 *
 * This function is used as gmx::SelectionTreeElement::evaluate for
 * \ref SEL_BOOLEAN elements with \ref BOOL_AND.
 */
void
_gmx_sel_evaluate_and(gmx_sel_evaluate_t                     *data,
                      const gmx::SelectionTreeElementPointer &sel,
                      gmx_ana_index_t                        *g)
{
    SelectionTreeElementPointer child = sel->child;
    /* Skip the first child if it does not have an evaluation function. */
    if (!child->evaluate)
    {
        child = child->next;
    }
    /* Evaluate the first child */
    {
        MempoolSelelemReserver reserver(child, g->isize);
        child->evaluate(data, child, g);
        gmx_ana_index_copy(sel->v.u.g, child->v.u.g, false);
    }
    child = child->next;
    while (child && sel->v.u.g->isize > 0)
    {
        MempoolSelelemReserver reserver(child, sel->v.u.g->isize);
        child->evaluate(data, child, sel->v.u.g);
        gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
        child = child->next;
    }
}
コード例 #3
0
void
SelectionCollection::setIndexGroups(gmx_ana_indexgrps_t *grps)
{
    GMX_RELEASE_ASSERT(grps == NULL || !impl_->bExternalGroupsSet_,
                       "Can only set external groups once or clear them afterwards");
    impl_->grps_               = grps;
    impl_->bExternalGroupsSet_ = true;

    ExceptionInitializer        errors("Invalid index group reference(s)");
    SelectionTreeElementPointer root = impl_->sc_.root;
    while (root)
    {
        impl_->resolveExternalGroups(root, &errors);
        root->checkUnsortedAtoms(true, &errors);
        root = root->next;
    }
    if (errors.hasNestedExceptions())
    {
        GMX_THROW(InconsistentInputError(errors));
    }
    for (size_t i = 0; i < impl_->sc_.sel.size(); ++i)
    {
        impl_->sc_.sel[i]->refreshName();
    }
}
コード例 #4
0
/*!
 * \param[in]  name     Name of the variable.
 * \param[in]  expr     The selection element that evaluates the variable.
 * \param      scanner  Scanner data structure.
 * \returns    The created root selection element.
 *
 * This function handles the creation of root gmx::SelectionTreeElement objects
 * for variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
 * element are both created.
 */
SelectionTreeElementPointer
_gmx_sel_assign_variable(const char                             *name,
                         const gmx::SelectionTreeElementPointer &expr,
                         yyscan_t                                scanner)
{
    gmx_ana_selcollection_t     *sc      = _gmx_sel_lexer_selcollection(scanner);
    const char                  *pselstr = _gmx_sel_lexer_pselstr(scanner);
    SelectionTreeElementPointer  root;

    _gmx_selelem_update_flags(expr);
    /* Check if this is a constant non-group value */
    if (expr->type == SEL_CONST && expr->v.type != GROUP_VALUE)
    {
        /* If so, just assign the constant value to the variable */
        sc->symtab->addVariable(name, expr);
    }
    /* Check if we are assigning a variable to another variable */
    else if (expr->type == SEL_SUBEXPRREF)
    {
        /* If so, make a simple alias */
        sc->symtab->addVariable(name, expr->child);
    }
    else
    {
        /* Create the root element */
        root.reset(new SelectionTreeElement(SEL_ROOT));
        root->setName(name);
        /* Create the subexpression element */
        root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
        root->child->setName(name);
        _gmx_selelem_set_vtype(root->child, expr->v.type);
        root->child->child  = expr;
        /* Update flags */
        _gmx_selelem_update_flags(root);
        gmx::ExceptionInitializer errors("Invalid index group reference(s)");
        root->checkUnsortedAtoms(true, &errors);
        if (errors.hasNestedExceptions())
        {
            GMX_THROW(gmx::InconsistentInputError(errors));
        }
        /* Add the variable to the symbol table */
        sc->symtab->addVariable(name, root->child);
    }
    srenew(sc->varstrs, sc->nvars + 1);
    sc->varstrs[sc->nvars] = strdup(pselstr);
    ++sc->nvars;
    if (_gmx_sel_is_lexer_interactive(scanner))
    {
        fprintf(stderr, "Variable '%s' parsed\n", pselstr);
    }
    return root;
}
コード例 #5
0
ファイル: parsetree.cpp プロジェクト: alwanderer/gromacs
/*!
 * \param[in]  name     Name of the variable.
 * \param[in]  expr     The selection element that evaluates the variable.
 * \param      scanner  Scanner data structure.
 * \returns    The created root selection element.
 *
 * This function handles the creation of root gmx::SelectionTreeElement objects
 * for variable assignments. A \ref SEL_ROOT element and a \ref SEL_SUBEXPR
 * element are both created.
 */
SelectionTreeElementPointer
_gmx_sel_assign_variable(const char                        *name,
                         const SelectionTreeElementPointer &expr,
                         yyscan_t                           scanner)
{
    gmx_ana_selcollection_t     *sc      = _gmx_sel_lexer_selcollection(scanner);
    const char                  *pselstr = _gmx_sel_lexer_pselstr(scanner);
    SelectionTreeElementPointer  root;

    gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
    char  buf[1024];
    sprintf(buf, "In selection '%s'", pselstr);
    gmx::MessageStringContext  context(errors, buf);

    _gmx_selelem_update_flags(expr, scanner);
    /* Check if this is a constant non-group value */
    if (expr->type == SEL_CONST && expr->v.type != GROUP_VALUE)
    {
        /* If so, just assign the constant value to the variable */
        sc->symtab->addVariable(name, expr);
        goto finish;
    }
    /* Check if we are assigning a variable to another variable */
    if (expr->type == SEL_SUBEXPRREF)
    {
        /* If so, make a simple alias */
        sc->symtab->addVariable(name, expr->child);
        goto finish;
    }
    /* Create the root element */
    root.reset(new SelectionTreeElement(SEL_ROOT));
    root->setName(name);
    /* Create the subexpression element */
    root->child.reset(new SelectionTreeElement(SEL_SUBEXPR));
    root->child->setName(name);
    _gmx_selelem_set_vtype(root->child, expr->v.type);
    root->child->child  = expr;
    /* Update flags */
    _gmx_selelem_update_flags(root, scanner);
    /* Add the variable to the symbol table */
    sc->symtab->addVariable(name, root->child);
finish:
    srenew(sc->varstrs, sc->nvars + 1);
    sc->varstrs[sc->nvars] = strdup(pselstr);
    ++sc->nvars;
    if (_gmx_sel_is_lexer_interactive(scanner))
    {
        fprintf(stderr, "Variable '%s' parsed\n", pselstr);
    }
    return root;
}
コード例 #6
0
ファイル: params.cpp プロジェクト: MelroLeandro/gromacs
/*! \brief
 * Adds a new subexpression reference to a selection element.
 *
 * \param[in,out] root  Root element to which the subexpression is added.
 * \param[in]     param Parameter for which this expression is a value.
 * \param[in]     expr  Expression to add.
 * \param[in]     scanner Scanner data structure.
 * \returns       The created child element.
 *
 * Creates a new \ref SEL_SUBEXPRREF element and adds it into the child
 * list of \p root.
 * If \p expr is already a \ref SEL_SUBEXPRREF, it is used as it is.
 * \ref SEL_ALLOCVAL is cleared for the returned element.
 */
static SelectionTreeElementPointer
add_child(const SelectionTreeElementPointer &root, gmx_ana_selparam_t *param,
          const SelectionTreeElementPointer &expr, void *scanner)
{
    GMX_RELEASE_ASSERT(root->type == SEL_EXPRESSION || root->type == SEL_MODIFIER,
                       "Unsupported root element for selection parameter parser");
    SelectionTreeElementPointer child;
    /* Create a subexpression reference element if necessary */
    if (expr->type == SEL_SUBEXPRREF)
    {
        child = expr;
    }
    else
    {
        // TODO: Initialize such that it includes the parameter.
        child.reset(new SelectionTreeElement(SEL_SUBEXPRREF, expr->location()));
        _gmx_selelem_set_vtype(child, expr->v.type);
        child->child  = expr;
    }
    /* Setup the child element */
    child->flags  &= ~SEL_ALLOCVAL;
    child->u.param = param;
    if (child->v.type != param->val.type)
    {
        // TODO: It would be nice to say what is the expected type.
        std::string text(_gmx_sel_lexer_get_text(scanner, expr->location()));
        std::string message
            = formatString("Expression '%s' is not valid in this context "
                           "(produces the wrong type of values)",
                           text.c_str());
        GMX_THROW(InvalidInputError(message));
    }
    _gmx_selelem_update_flags(child);
    if ((child->flags & SEL_DYNAMIC) && !(param->flags & SPAR_DYNAMIC))
    {
        std::string text(_gmx_sel_lexer_get_text(scanner, expr->location()));
        std::string message
            = formatString("Expression '%s' is dynamic, which is not "
                           "valid in this context",
                           text.c_str());
        GMX_THROW(InvalidInputError(message));
    }
    if (!(child->flags & SEL_DYNAMIC))
    {
        param->flags &= ~SPAR_DYNAMIC;
    }
    /* Put the child element in the correct place */
    place_child(root, child, param);
    return child;
}
コード例 #7
0
ファイル: evaluate.cpp プロジェクト: daniellandau/gromacs
/*!
 * \param[in] data Data for the current frame.
 * \param[in] sel  Selection element being evaluated.
 * \param[in] g    Group for which \p sel should be evaluated.
 * \returns   0 on success, a non-zero error code on error.
 *
 * Evaluates each child of \p sel in \p g.
 */
void
_gmx_sel_evaluate_children(gmx_sel_evaluate_t                     *data,
                           const gmx::SelectionTreeElementPointer &sel,
                           gmx_ana_index_t                        *g)
{
    SelectionTreeElementPointer child = sel->child;
    while (child)
    {
        if (child->evaluate)
        {
            child->evaluate(data, child, g);
        }
        child = child->next;
    }
}
コード例 #8
0
ファイル: params.cpp プロジェクト: MelroLeandro/gromacs
/*! \brief
 * Initializes the storage of an expression value.
 *
 * \param[in,out] sel   Selection element that evaluates the value.
 * \param[in]     param Parameter to receive the value.
 * \param[in]     i     The value of \p sel evaluates the value \p i for
 *   \p param.
 * \param[in]     scanner Scanner data structure.
 *
 * Initializes the data pointer of \p sel such that the result is stored
 * as the value \p i of \p param.
 * This function is used internally by parse_values_std().
 */
static void
set_expr_value_store(const SelectionTreeElementPointer &sel,
                     gmx_ana_selparam_t *param, int i, void *scanner)
{
    if (sel->v.type != GROUP_VALUE && !(sel->flags & SEL_SINGLEVAL))
    {
        std::string text(_gmx_sel_lexer_get_text(scanner, sel->location()));
        std::string message
            = formatString("Expression '%s' is invalid in this context",
                           text.c_str());
        GMX_THROW(InvalidInputError(message));
    }
    switch (sel->v.type)
    {
        case INT_VALUE:   sel->v.u.i = &param->val.u.i[i]; break;
        case REAL_VALUE:  sel->v.u.r = &param->val.u.r[i]; break;
        case STR_VALUE:   sel->v.u.s = &param->val.u.s[i]; break;
        case POS_VALUE:   sel->v.u.p = &param->val.u.p[i]; break;
        case GROUP_VALUE: sel->v.u.g = &param->val.u.g[i]; break;
        default: /* Error */
            GMX_THROW(InternalError("Invalid value type"));
    }
    sel->v.nr     = 1;
    sel->v.nalloc = -1;
}
コード例 #9
0
void SelectionCollection::Impl::resolveExternalGroups(
        const SelectionTreeElementPointer &root,
        ExceptionInitializer              *errors)
{

    if (root->type == SEL_GROUPREF)
    {
        try
        {
            root->resolveIndexGroupReference(grps_, sc_.gall.isize);
        }
        catch (const UserInputError &)
        {
            errors->addCurrentExceptionAsNested();
        }
    }

    SelectionTreeElementPointer child = root->child;
    while (child)
    {
        resolveExternalGroups(child, errors);
        root->flags |= (child->flags & SEL_UNSORTED);
        child        = child->next;
    }
}
コード例 #10
0
/*!
 * \param[in,out] sel  Value of the variable.
 * \returns       The created selection element that references \p sel.
 *
 * The reference count of \p sel is updated, but no other modifications are
 * made.
 */
SelectionTreeElementPointer
_gmx_sel_init_variable_ref(const gmx::SelectionTreeElementPointer &sel)
{
    SelectionTreeElementPointer ref;

    if (sel->v.type == POS_VALUE && sel->type == SEL_CONST)
    {
        ref = sel;
    }
    else
    {
        ref.reset(new SelectionTreeElement(SEL_SUBEXPRREF));
        _gmx_selelem_set_vtype(ref, sel->v.type);
        ref->setName(sel->name());
        ref->child = sel;
    }
    return ref;
}
コード例 #11
0
ファイル: evaluate.cpp プロジェクト: daniellandau/gromacs
/*!
 * \param[in,out] coll  The selection collection to evaluate.
 * \param[in] fr  Frame for which the evaluation should be carried out.
 * \param[in] pbc PBC data, or NULL if no PBC should be used.
 * \returns   0 on successful evaluation, a non-zero error code on error.
 *
 * This functions sets the global variables for topology, frame and PBC,
 * clears some information in the selection to initialize the evaluation
 * for a new frame, and evaluates \p sel and all the selections pointed by
 * the \p next pointers of \p sel.
 *
 * This is the only function that user code should call if they want to
 * evaluate a selection for a new frame.
 */
void
SelectionEvaluator::evaluate(SelectionCollection *coll,
                             t_trxframe *fr, t_pbc *pbc)
{
    gmx_ana_selcollection_t *sc = &coll->impl_->sc_;
    gmx_sel_evaluate_t       data;

    _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
    init_frame_eval(sc->root);
    SelectionTreeElementPointer sel = sc->root;
    while (sel)
    {
        /* Clear the evaluation group of subexpressions */
        if (sel->child && sel->child->type == SEL_SUBEXPR
            && sel->child->evaluate != NULL)
        {
            sel->child->u.cgrp.isize = 0;
            /* Not strictly necessary, because the value will be overwritten
             * during first evaluation of the subexpression anyways, but we
             * clear the group for clarity. Note that this is _not_ done during
             * compilation because of some additional complexities involved
             * (see compiler.cpp), so it should not be relied upon in
             * _gmx_sel_evaluate_subexpr(). */
            if (sel->child->v.type == GROUP_VALUE)
            {
                sel->child->v.u.g->isize = 0;
            }
        }
        if (sel->evaluate)
        {
            sel->evaluate(&data, sel, NULL);
        }
        sel = sel->next;
    }
    /* Update selection information */
    SelectionDataList::const_iterator isel;
    for (isel = sc->sel.begin(); isel != sc->sel.end(); ++isel)
    {
        internal::SelectionData &sel = **isel;
        sel.refreshMassesAndCharges(sc->top);
        sel.updateCoveredFractionForFrame();
    }
}
コード例 #12
0
ファイル: parsetree.cpp プロジェクト: alwanderer/gromacs
/*!
 * \param[in,out] sel    Selection element to initialize.
 * \param[in]     method Selection method to set.
 * \param[in]     scanner Scanner data structure.
 *
 * Makes a copy of \p method and stores it in \p sel->u.expr.method,
 * and calls _gmx_selelem_init_method_params();
 */
void
_gmx_selelem_set_method(const SelectionTreeElementPointer &sel,
                        gmx_ana_selmethod_t               *method,
                        yyscan_t                           scanner)
{
    _gmx_selelem_set_vtype(sel, method->type);
    sel->setName(method->name);
    snew(sel->u.expr.method, 1);
    memcpy(sel->u.expr.method, method, sizeof(gmx_ana_selmethod_t));
    _gmx_selelem_init_method_params(sel, scanner);
}
コード例 #13
0
ファイル: evaluate.cpp プロジェクト: daniellandau/gromacs
/*!
 * \param[in] data Data for the current frame.
 * \param[in] sel Selection element being evaluated.
 * \param[in] g   Group for which \p sel should be evaluated.
 * \returns   0 on success, a non-zero error code on error.
 *
 * Evaluates each child of a \ref SEL_EXPRESSION element.
 * The value of \p sel is not touched.
 *
 * This function is not used as gmx::SelectionTreeElement::evaluate,
 * but is used internally.
 */
void
_gmx_sel_evaluate_method_params(gmx_sel_evaluate_t                     *data,
                                const gmx::SelectionTreeElementPointer &sel,
                                gmx_ana_index_t                        *g)
{
    SelectionTreeElementPointer child = sel->child;
    while (child)
    {
        if (child->evaluate && !(child->flags & SEL_EVALFRAME))
        {
            if (child->flags & SEL_ATOMVAL)
            {
                child->evaluate(data, child, g);
            }
            else
            {
                child->flags |= SEL_EVALFRAME;
                child->evaluate(data, child, NULL);
            }
        }
        child = child->next;
    }
}
コード例 #14
0
ファイル: selelem.cpp プロジェクト: losalamos/gromacs-kokkos
void SelectionTreeElement::checkUnsortedAtoms(
    bool bUnsortedAllowed, ExceptionInitializer *errors) const
{
    const bool bUnsortedSupported
        = (type == SEL_CONST && v.type == GROUP_VALUE)
          || type == SEL_ROOT || type == SEL_SUBEXPR || type == SEL_SUBEXPRREF
          // TODO: Consolidate.
          || type == SEL_MODIFIER
          || (type == SEL_EXPRESSION && (u.expr.method->flags & SMETH_ALLOW_UNSORTED));

    // TODO: For some complicated selections, this may result in the same
    // index group reference being flagged as an error multiple times for the
    // same selection.
    SelectionTreeElementPointer child = this->child;
    while (child)
    {
        child->checkUnsortedAtoms(bUnsortedAllowed && bUnsortedSupported,
                                  errors);
        child = child->next;
    }

    // The logic here is simplified by the fact that only constant groups can
    // currently be the root cause of SEL_UNSORTED being set, so only those
    // need to be considered in triggering the error.
    if (!bUnsortedAllowed && (flags & SEL_UNSORTED)
            && type == SEL_CONST && v.type == GROUP_VALUE)
    {
        std::string message = formatString(
                                  "Group '%s' cannot be used in selections except "
                                  "as a full value of the selection, "
                                  "because atom indices in it are not sorted and/or "
                                  "it contains duplicate atoms.",
                                  name().c_str());
        errors->addNested(InconsistentInputError(message));
    }
}
コード例 #15
0
ファイル: parsetree.cpp プロジェクト: alwanderer/gromacs
/*!
 * \param         sel   Selection to append (can be NULL, in which
 *   case nothing is done).
 * \param         last  Last selection, or NULL if not present or not known.
 * \param         scanner  Scanner data structure.
 * \returns       The last selection after the append.
 *
 * Appends \p sel after the last root element, and returns either \p sel
 * (if it was non-NULL) or the last element (if \p sel was NULL).
 */
SelectionTreeElementPointer
_gmx_sel_append_selection(const SelectionTreeElementPointer &sel,
                          SelectionTreeElementPointer        last,
                          yyscan_t                           scanner)
{
    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);

    /* Append sel after last, or the last element of sc if last is NULL */
    if (last)
    {
        last->next = sel;
    }
    else
    {
        if (sc->root)
        {
            last = sc->root;
            while (last->next)
            {
                last = last->next;
            }
            last->next = sel;
        }
        else
        {
            sc->root = sel;
        }
    }
    /* Initialize a selection object if necessary */
    if (sel)
    {
        last = sel;
        /* Add the new selection to the collection if it is not a variable. */
        if (sel->child->type != SEL_SUBEXPR)
        {
            gmx::SelectionDataPointer selPtr(
                    new gmx::internal::SelectionData(
                            sel.get(), _gmx_sel_lexer_pselstr(scanner)));
            sc->sel.push_back(gmx::move(selPtr));
        }
    }
    /* Clear the selection string now that we've saved it */
    _gmx_sel_lexer_clear_pselstr(scanner);
    return last;
}