/*! * See sel_updatefunc() for description of the parameters. * \p data should point to a \c t_methoddata_pos. * * Calculates the positions using \c t_methoddata_pos::pc for the index group * in \c t_methoddata_pos::g and stores the results in \p out->u.p. */ static void evaluate_pos(t_topology * /* top */, t_trxframe *fr, t_pbc *pbc, gmx_ana_index_t * /* g */, gmx_ana_selvalue_t *out, void *data) { t_methoddata_pos *d = (t_methoddata_pos *)data; gmx_ana_poscalc_update(d->pc, out->u.p, &d->g, fr, pbc); }
/*! * See sel_updatefunc() for description of the parameters. * \p data should point to a \c t_methoddata_pos. * * Calculates the positions using \c t_methoddata_pos::pc for the index group * in \c t_methoddata_pos::g and stores the results in \p out->u.p. */ static int evaluate_pos(t_topology *top, t_trxframe *fr, t_pbc *pbc, gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data) { t_methoddata_pos *d = (t_methoddata_pos *)data; gmx_ana_poscalc_update(d->pc, out->u.p, &d->g, fr, pbc); return 0; }
/*! * \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 all child selections (using _gmx_sel_evaluate_method_params()) * to evaluate any parameter values. * If this is the first time this expression is evaluated for * the frame, sel_framefunc() callback is called if one is provided. * If a reference position calculation has been initialized for this element, * the positions are also updated, and sel_updatefunc_pos() is used to * evaluate the value. Otherwise, sel_updatefunc() is used. * * This function is used as \c t_selelem::evaluate for \ref SEL_EXPRESSION * elements. */ void _gmx_sel_evaluate_method(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g) { _gmx_sel_evaluate_method_params(data, sel, g); if (sel->flags & SEL_INITFRAME) { sel->flags &= ~SEL_INITFRAME; sel->u.expr.method->init_frame(data->top, data->fr, data->pbc, sel->u.expr.mdata); } if (sel->u.expr.pc) { gmx_ana_poscalc_update(sel->u.expr.pc, sel->u.expr.pos, g, data->fr, data->pbc); sel->u.expr.method->pupdate(data->top, data->fr, data->pbc, sel->u.expr.pos, &sel->v, sel->u.expr.mdata); } else { sel->u.expr.method->update(data->top, data->fr, data->pbc, g, &sel->v, sel->u.expr.mdata); } }
/*! * \param[in] pc Position calculation data. * \param[in,out] p Output positions, initialized previously with * gmx_ana_poscalc_init_pos() using \p pc. * \param[in] g Index group to use for the update. * \param[in] x Current positions of the atoms. * \param[in] pbc PBC data, or NULL if no PBC should be used. * * gmx_ana_poscalc_init_frame() should be called for each frame before calling * this function. */ void gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p, gmx_ana_index_t *g, rvec x[], t_pbc *pbc) { int i, j, bi, bj; if (pc->bEval == TRUE && !(pc->flags & POS_MASKONLY)) { return; } if (pc->sbase) { gmx_ana_poscalc_update(pc->sbase, NULL, NULL, x, pbc); } if (!p) { p = pc->p; } if (!g) { g = &pc->gmax; } p->g = g; /* Update the index map */ if (pc->flags & POS_DYNAMIC) { gmx_ana_indexmap_update(&p->m, g, FALSE); p->nr = p->m.nr; } else if (pc->flags & POS_MASKONLY) { gmx_ana_indexmap_update(&p->m, g, TRUE); if (pc->bEval) return; } if (!(pc->flags & POS_DYNAMIC)) { pc->bEval = TRUE; } /* Evaluate the positions */ if (pc->sbase) { /* TODO: It might be faster to evaluate the positions within this * loop instead of in the beginning. */ if (pc->flags & POS_DYNAMIC) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[p->m.refid[bi]]; copy_rvec(pc->sbase->p->x[bj], p->x[bi]); } } else { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[bi]; copy_rvec(pc->sbase->p->x[bj], p->x[bi]); } } } else /* pc->sbase is NULL */ { if (pc->flags & POS_DYNAMIC) { pc->b.nr = p->m.mapb.nr; pc->b.index = p->m.mapb.index; pc->b.nra = g->isize; pc->b.a = g->index; } /* Here, we assume that the topology has been properly initialized, * and do not check the return values of gmx_calc_comg*(). */ switch (pc->type) { case POS_ATOM: for (i = 0; i < pc->b.nra; ++i) { copy_rvec(x[pc->b.a[i]], p->x[i]); } break; case POS_ALL: gmx_calc_comg(pc->coll->top, x, pc->b.nra, pc->b.a, pc->flags & POS_MASS, p->x[0]); break; case POS_ALL_PBC: gmx_calc_comg_pbc(pc->coll->top, x, pbc, pc->b.nra, pc->b.a, pc->flags & POS_MASS, p->x[0]); break; default: gmx_calc_comg_blocka(pc->coll->top, x, &pc->b, pc->flags & POS_MASS, p->x); break; } } }
/*! * \param[in] pc Position calculation data. * \param[in,out] p Output positions, initialized previously with * gmx_ana_poscalc_init_pos() using \p pc. * \param[in] g Index group to use for the update. * \param[in] fr Current frame. * \param[in] pbc PBC data, or NULL if no PBC should be used. * * gmx_ana_poscalc_init_frame() should be called for each frame before calling * this function. */ void gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p, gmx_ana_index_t *g, t_trxframe *fr, t_pbc *pbc) { int i, bi, bj; if (pc->bEval == true && !(pc->flags & POS_MASKONLY)) { return; } if (pc->sbase) { gmx_ana_poscalc_update(pc->sbase, NULL, NULL, fr, pbc); } if (!p) { p = pc->p; } if (!g) { g = &pc->gmax; } gmx_ana_pos_set_evalgrp(p, g); /* Update the index map */ if (pc->flags & POS_DYNAMIC) { gmx_ana_indexmap_update(&p->m, g, false); p->nr = p->m.nr; } else if (pc->flags & POS_MASKONLY) { gmx_ana_indexmap_update(&p->m, g, true); if (pc->bEval) { return; } } if (!(pc->flags & POS_DYNAMIC)) { pc->bEval = true; } /* Evaluate the positions */ if (pc->sbase) { /* TODO: It might be faster to evaluate the positions within this * loop instead of in the beginning. */ if (pc->flags & POS_DYNAMIC) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[p->m.refid[bi]]; copy_rvec(pc->sbase->p->x[bj], p->x[bi]); } if (p->v) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[p->m.refid[bi]]; copy_rvec(pc->sbase->p->v[bj], p->v[bi]); } } if (p->f) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[p->m.refid[bi]]; copy_rvec(pc->sbase->p->f[bj], p->f[bi]); } } } else { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[bi]; copy_rvec(pc->sbase->p->x[bj], p->x[bi]); } if (p->v) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[bi]; copy_rvec(pc->sbase->p->v[bj], p->v[bi]); } } if (p->f) { for (bi = 0; bi < p->nr; ++bi) { bj = pc->baseid[bi]; copy_rvec(pc->sbase->p->f[bj], p->f[bi]); } } } } else /* pc->sbase is NULL */ { if (pc->flags & POS_DYNAMIC) { pc->b.nr = p->m.mapb.nr; pc->b.index = p->m.mapb.index; pc->b.nra = g->isize; pc->b.a = g->index; } if (p->v && !fr->bV) { for (i = 0; i < pc->b.nra; ++i) { clear_rvec(p->v[i]); } } if (p->f && !fr->bF) { for (i = 0; i < pc->b.nra; ++i) { clear_rvec(p->f[i]); } } /* Here, we assume that the topology has been properly initialized, * and do not check the return values of gmx_calc_comg*(). */ t_topology *top = pc->coll->top_; bool bMass = pc->flags & POS_MASS; switch (pc->type) { case POS_ATOM: for (i = 0; i < pc->b.nra; ++i) { copy_rvec(fr->x[pc->b.a[i]], p->x[i]); } if (p->v && fr->bV) { for (i = 0; i < pc->b.nra; ++i) { copy_rvec(fr->v[pc->b.a[i]], p->v[i]); } } if (p->f && fr->bF) { for (i = 0; i < pc->b.nra; ++i) { copy_rvec(fr->f[pc->b.a[i]], p->f[i]); } } break; case POS_ALL: gmx_calc_comg(top, fr->x, pc->b.nra, pc->b.a, bMass, p->x[0]); if (p->v && fr->bV) { gmx_calc_comg(top, fr->v, pc->b.nra, pc->b.a, bMass, p->v[0]); } if (p->f && fr->bF) { gmx_calc_comg_f(top, fr->f, pc->b.nra, pc->b.a, bMass, p->f[0]); } break; case POS_ALL_PBC: gmx_calc_comg_pbc(top, fr->x, pbc, pc->b.nra, pc->b.a, bMass, p->x[0]); if (p->v && fr->bV) { gmx_calc_comg(top, fr->v, pc->b.nra, pc->b.a, bMass, p->v[0]); } if (p->f && fr->bF) { gmx_calc_comg_f(top, fr->f, pc->b.nra, pc->b.a, bMass, p->f[0]); } break; default: gmx_calc_comg_blocka(top, fr->x, &pc->b, bMass, p->x); if (p->v && fr->bV) { gmx_calc_comg_blocka(top, fr->v, &pc->b, bMass, p->v); } if (p->f && fr->bF) { gmx_calc_comg_blocka(top, fr->f, &pc->b, bMass, p->f); } break; } } }