/*! * \param[in] top Topology data structure. * \param[in,out] out Pointer to output data structure. * \param[in,out] data Should point to \c t_methoddata_pos. * \returns 0 for success. */ static int init_output_pos(t_topology *top, gmx_ana_selvalue_t *out, void *data) { t_methoddata_pos *d = (t_methoddata_pos *)data; gmx_ana_poscalc_init_pos(d->pc, out->u.p); gmx_ana_pos_set_evalgrp(out->u.p, &d->g); return 0; }
/*! * \param[in] top Topology data structure. * \param[in,out] out Pointer to output data structure. * \param[in,out] data Should point to \c t_methoddata_permute. */ static void init_output_permute(t_topology *top, gmx_ana_selvalue_t *out, void *data) { t_methoddata_permute *d = (t_methoddata_permute *)data; int i, j, b; gmx_ana_pos_copy(out->u.p, &d->p, true); gmx_ana_pos_set_evalgrp(out->u.p, &d->g); d->g.isize = 0; gmx_ana_pos_empty_init(out->u.p); for (i = 0; i < d->p.nr; i += d->n) { for (j = 0; j < d->n; ++j) { b = i + d->rperm[j]; gmx_ana_pos_append_init(out->u.p, &d->g, &d->p, b); } } }
/*! * \param[in] pc Position calculation data structure. * \param[out] p Output positions. * * Calls to gmx_ana_poscalc_update() using \p pc should use only positions * initialized with this function. * The \c p->g pointer is initialized to point to an internal group that * contains the maximum index group set with gmx_ana_poscalc_set_maxindex(). */ void gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p) { gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top_, pc->itype); /* Only do the static optimization when there is no completion */ if (!(pc->flags & POS_DYNAMIC) && pc->b.nra == pc->gmax.isize) { gmx_ana_indexmap_set_static(&p->m, &pc->b); } gmx_ana_pos_reserve(p, p->m.nr, 0); if (pc->flags & POS_VELOCITIES) { gmx_ana_pos_reserve_velocities(p); } if (pc->flags & POS_FORCES) { gmx_ana_pos_reserve_forces(p); } gmx_ana_pos_set_nr(p, p->m.nr); gmx_ana_pos_set_evalgrp(p, &pc->gmax); }
/*! * \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; } } }