/*! * \param[in,out] dest Destination positions. * \param[in] src Source positions. * \param[in] bFirst If true, memory is allocated for \p dest and a full * copy is made; otherwise, only variable parts are copied, and no memory * is allocated. * * \p dest should have been initialized somehow (calloc() is enough). */ void gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, bool bFirst) { if (bFirst) { gmx_ana_pos_reserve(dest, src->count(), 0); if (src->v) { gmx_ana_pos_reserve_velocities(dest); } if (src->f) { gmx_ana_pos_reserve_forces(dest); } } memcpy(dest->x, src->x, src->count()*sizeof(*dest->x)); if (dest->v) { GMX_ASSERT(src->v, "src velocities should be non-null if dest velocities are allocated"); memcpy(dest->v, src->v, src->count()*sizeof(*dest->v)); } if (dest->f) { GMX_ASSERT(src->f, "src forces should be non-null if dest forces are allocated"); memcpy(dest->f, src->f, src->count()*sizeof(*dest->f)); } gmx_ana_indexmap_copy(&dest->m, &src->m, bFirst); }
/*! * \param[in,out] dest Destination positions. * \param[in] src Source positions. * \param[in] bFirst If true, memory is allocated for \p dest and a full * copy is made; otherwise, only variable parts are copied, and no memory * is allocated. * * \p dest should have been initialized somehow (calloc() is enough). */ void gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, bool bFirst) { if (bFirst) { gmx_ana_pos_reserve(dest, src->nr, 0); if (src->v) { gmx_ana_pos_reserve_velocities(dest); } if (src->f) { gmx_ana_pos_reserve_forces(dest); } } dest->nr = src->nr; memcpy(dest->x, src->x, dest->nr*sizeof(*dest->x)); if (dest->v) { memcpy(dest->v, src->v, dest->nr*sizeof(*dest->v)); } if (dest->f) { memcpy(dest->f, src->f, dest->nr*sizeof(*dest->f)); } gmx_ana_indexmap_copy(&dest->m, &src->m, bFirst); dest->g = src->g; }
/*! * \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) { e_index_t ptype; ptype = index_type_for_poscalc(pc->type); gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, ptype); gmx_ana_pos_reserve(p, p->m.nr, 0); p->g = &pc->gmax; }
/*! * \param[in,out] pos Position data structure. * \param[in] n Maximum number of positions. * \param[in] isize Maximum number of atoms. * \param[in] bVelocities Whether to reserve space for velocities. * \param[in] bForces Whether to reserve space for forces. * * Ensures that enough memory is allocated in \p pos to calculate \p n * positions from \p isize atoms. * * This method needs to be called instead of gmx_ana_pos_reserve() if the * intent is to use gmx_ana_pos_append_init()/gmx_ana_pos_append(). */ void gmx_ana_pos_reserve_for_append(gmx_ana_pos_t *pos, int n, int isize, bool bVelocities, bool bForces) { gmx_ana_pos_reserve(pos, n, isize); snew(pos->m.mapb.a, isize); pos->m.mapb.nalloc_a = isize; if (bVelocities) { gmx_ana_pos_reserve_velocities(pos); } if (bForces) { gmx_ana_pos_reserve_forces(pos); } }
/*! * \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.mapb.nr, 0); if (pc->flags & POS_VELOCITIES) { gmx_ana_pos_reserve_velocities(p); } if (pc->flags & POS_FORCES) { gmx_ana_pos_reserve_forces(p); } }
/*! \brief * Parses the values for a parameter that takes a variable number of values. * * \param[in] nval Number of values in \p values. * \param[in] values Pointer to the list of values. * \param param Parameter to parse. * \param root Selection element to which child expressions are added. * \returns TRUE if the values were parsed successfully, FALSE otherwise. * * For integer ranges, the sequence of numbers from the first to second value * is stored, each as a separate value. */ static gmx_bool parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param, t_selelem *root) { t_selexpr_value *value; int i, j; param->flags &= ~SPAR_DYNAMIC; /* Update nval if there are integer ranges. */ if (param->val.type == INT_VALUE) { value = values; while (value) { if (value->type == INT_VALUE && !value->bExpr) { nval += abs(value->u.i.i2 - value->u.i.i1); } value = value->next; } } /* Check that the value type is actually implemented */ if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE && param->val.type != STR_VALUE && param->val.type != POS_VALUE) { gmx_bug("internal error"); return FALSE; } /* Reserve appropriate amount of memory */ if (param->val.type == POS_VALUE) { gmx_ana_pos_reserve(param->val.u.p, nval, 0); gmx_ana_pos_set_nr(param->val.u.p, nval); gmx_ana_indexmap_init(¶m->val.u.p->m, NULL, NULL, INDEX_UNKNOWN); } else { _gmx_selvalue_reserve(¶m->val, nval); } value = values; i = 0; while (value) { if (value->bExpr) { _gmx_selparser_error("expressions not supported within value lists"); return FALSE; } if (value->type != param->val.type) { gmx_bug("internal error"); return FALSE; } switch (param->val.type) { case INT_VALUE: if (value->u.i.i1 <= value->u.i.i2) { for (j = value->u.i.i1; j <= value->u.i.i2; ++j) { param->val.u.i[i++] = j; } } else { for (j = value->u.i.i1; j >= value->u.i.i2; --j) { param->val.u.i[i++] = j; } } break; case REAL_VALUE: if (value->u.r.r1 != value->u.r.r2) { _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name); return FALSE; } param->val.u.r[i++] = value->u.r.r1; break; case STR_VALUE: param->val.u.s[i++] = strdup(value->u.s); break; case POS_VALUE: copy_rvec(value->u.x, param->val.u.p->x[i++]); break; default: /* Should not be reached */ gmx_bug("internal error"); return FALSE; } value = value->next; } param->val.nr = i; if (param->nvalptr) { *param->nvalptr = param->val.nr; } param->nvalptr = NULL; /* Create a dummy child element to store the string values. * This element is responsible for freeing the values, but carries no * other function. */ if (param->val.type == STR_VALUE) { t_selelem *child; child = _gmx_selelem_create(SEL_CONST); _gmx_selelem_set_vtype(child, STR_VALUE); child->name = param->name; child->flags &= ~SEL_ALLOCVAL; child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA; child->v.nr = param->val.nr; _gmx_selvalue_setstore(&child->v, param->val.u.s); /* Because the child is not group-valued, the u union is not used * for anything, so we can abuse it by storing the parameter value * as place_child() expects, but this is really ugly... */ child->u.param = param; place_child(root, child, param); } return TRUE; }