Move gmx_ana_pos_t::g into gmx_ana_indexmap_t.
authorTeemu Murtola <teemu.murtola@gmail.com>
Tue, 27 Aug 2013 16:14:38 +0000 (19:14 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Sun, 8 Sep 2013 18:47:13 +0000 (20:47 +0200)
Instead of storing a gmx_ana_index_t structure by reference in the
positions, embed this information in the index mapping structure, as
that is really what it is required for.  This localizes the
responsibility of maintaining that state better, and allows removing
code that was there just to provide such an artificial group structure.
The logic still remains mostly the same: the array of atoms is still
stored by reference instead of copying where possible.

This also makes it simpler to handle cases where the output atoms from
the mapping would actually not equal the input group (e.g., that they
would need to be in a different order).

Prerequisite for #1221.

Change-Id: I9e3e0455d1129fd6c3dd8056b2f088114764f331

15 files changed:
src/gromacs/selection/compiler.cpp
src/gromacs/selection/indexutil.cpp
src/gromacs/selection/indexutil.h
src/gromacs/selection/poscalc.cpp
src/gromacs/selection/position.cpp
src/gromacs/selection/position.h
src/gromacs/selection/selection.cpp
src/gromacs/selection/selection.h
src/gromacs/selection/sm_distance.cpp
src/gromacs/selection/sm_insolidangle.cpp
src/gromacs/selection/sm_merge.cpp
src/gromacs/selection/sm_permute.cpp
src/gromacs/selection/sm_position.cpp
src/gromacs/selection/sm_simple.cpp
src/gromacs/selection/tests/poscalc.cpp

index 60a87a179579ab6568dd1ee9490d4d3c8a8f2b24..a903f995c70956ed7b44154f7af6fcb3b41a43f0 100644 (file)
@@ -2407,7 +2407,7 @@ init_root_item(const SelectionTreeElementPointer &root,
         /* For selections, store the maximum group for
          * gmx_ana_selcollection_evaluate_fin() as the value of the root
          * element (unused otherwise). */
-        if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
+        if (expr->type != SEL_SUBEXPR && expr->v.u.p->m.mapb.a != NULL)
         {
             SelectionTreeElementPointer child = expr;
 
@@ -2427,10 +2427,12 @@ init_root_item(const SelectionTreeElementPointer &root,
             }
             if (child->child->flags & SEL_DYNAMIC)
             {
+                gmx_ana_index_t g;
+                gmx_ana_index_set(&g, expr->v.u.p->m.mapb.nra, expr->v.u.p->m.mapb.a, 0);
                 _gmx_selelem_set_vtype(root, GROUP_VALUE);
                 root->flags  |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
                 _gmx_selvalue_reserve(&root->v, 1);
-                gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, true);
+                gmx_ana_index_copy(root->v.u.g, &g, true);
             }
         }
     }
index ad640ae8173150bd91a0925c9076153f7bd74973..2506c49b18c91d3ff79e68036110d94d5f3df7c2 100644 (file)
@@ -1030,6 +1030,9 @@ gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m)
     m->mapb.nr           = 0;
     m->mapb.index        = NULL;
     m->mapb.nalloc_index = 0;
+    m->mapb.nra          = 0;
+    m->mapb.a            = NULL;
+    m->mapb.nalloc_a     = 0;
     m->orgid             = NULL;
     m->b.nr              = 0;
     m->b.index           = NULL;
@@ -1119,7 +1122,9 @@ gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
         m->refid[i] = i;
         m->mapid[i] = m->orgid[i];
     }
-    m->mapb.nr = m->nr;
+    m->mapb.nr  = m->nr;
+    m->mapb.nra = m->b.nra;
+    m->mapb.a   = m->b.a;
     std::memcpy(m->mapb.index, m->b.index, (m->nr+1)*sizeof(*(m->mapb.index)));
     m->bStatic    = true;
     m->bMapStatic = true;
@@ -1144,16 +1149,18 @@ void
 gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b)
 {
     sfree(m->mapid);
-    m->mapid = m->orgid;
-    sfree(m->b.index);
-    m->b.nalloc_index = 0;
-    m->b.index        = b->index;
     sfree(m->mapb.index);
-    m->mapb.nalloc_index = 0;
-    m->mapb.index        = m->b.index;
+    sfree(m->b.index);
     sfree(m->b.a);
-    m->b.nalloc_a = 0;
-    m->b.a        = b->a;
+    m->mapb.nalloc_index = 0;
+    m->mapb.nalloc_a     = 0;
+    m->b.nalloc_index    = 0;
+    m->b.nalloc_a        = 0;
+    m->mapid             = m->orgid;
+    m->mapb.index        = b->index;
+    m->mapb.a            = b->a;
+    m->b.index           = b->index;
+    m->b.a               = b->a;
 }
 
 /*!
@@ -1180,6 +1187,20 @@ gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, bool bF
     }
     dest->nr         = src->nr;
     dest->mapb.nr    = src->mapb.nr;
+    dest->mapb.nra   = src->mapb.nra;
+    if (src->mapb.nalloc_a > 0)
+    {
+        if (bFirst)
+        {
+            snew(dest->mapb.a, src->mapb.nalloc_a);
+            dest->mapb.nalloc_a = src->mapb.nalloc_a;
+        }
+        std::memcpy(dest->mapb.a, src->mapb.a, dest->mapb.nra*sizeof(*dest->mapb.a));
+    }
+    else
+    {
+        dest->mapb.a = src->mapb.a;
+    }
     std::memcpy(dest->refid,      src->refid,      dest->nr*sizeof(*dest->refid));
     std::memcpy(dest->mapid,      src->mapid,      dest->nr*sizeof(*dest->mapid));
     std::memcpy(dest->mapb.index, src->mapb.index, (dest->mapb.nr+1)*sizeof(*dest->mapb.index));
@@ -1187,6 +1208,30 @@ gmx_ana_indexmap_copy(gmx_ana_indexmap_t *dest, gmx_ana_indexmap_t *src, bool bF
     dest->bMapStatic = src->bMapStatic;
 }
 
+/*! \brief
+ * Helper function to set the source atoms in an index map.
+ *
+ * \param[in,out] m     Mapping structure.
+ * \param[in]     isize Number of atoms in the \p index array.
+ * \param[in]     index List of atoms.
+ */
+static void
+set_atoms(gmx_ana_indexmap_t *m, int isize, int *index)
+{
+    m->mapb.nra = isize;
+    if (m->mapb.nalloc_a == 0)
+    {
+        m->mapb.a = index;
+    }
+    else
+    {
+        for (int i = 0; i < isize; ++i)
+        {
+            m->mapb.a[i] = index[i];
+        }
+    }
+}
+
 /*!
  * \param[in,out] m         Mapping structure.
  * \param[in]     g         Current index group.
@@ -1209,6 +1254,15 @@ gmx_ana_indexmap_update(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
     {
         return;
     }
+    // TODO: This could also be optimized away under some bStatic conditions.
+    if (bMaskOnly)
+    {
+        set_atoms(m, m->b.nra, m->b.a);
+    }
+    else
+    {
+        set_atoms(m, g->isize, g->index);
+    }
     if (m->type == INDEX_ALL)
     {
         if (m->b.nr > 0)
@@ -1326,6 +1380,10 @@ gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m)
     {
         sfree(m->mapb.index);
     }
+    if (m->mapb.nalloc_a > 0)
+    {
+        sfree(m->mapb.a);
+    }
     sfree(m->orgid);
     if (m->b.nalloc_index > 0)
     {
index da31448525535e98285e0f67c79a180b03aaf9b0..a8d454c8a924dbb26b5488b9201073b703fa0004 100644 (file)
@@ -139,8 +139,9 @@ typedef struct gmx_ana_indexmap_t
      * Mapped block structure.
      *
      * A block structure that corresponds to the current index group.
+     * \c mapb.nra and \c mapb.a correspond to the last mapped index group.
      */
-    t_block             mapb;
+    t_blocka            mapb;
 
     /*! \brief
      * Arbitrary ID numbers for the blocks.
index d07eb7ce2ae86587903b65539f73a62b92202a22..bbdbdbf15e9312d988a2e3eb4e855ceecd71dc67 100644 (file)
@@ -1053,7 +1053,6 @@ gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p)
         gmx_ana_pos_reserve_forces(p);
     }
     gmx_ana_pos_set_nr(p, p->m.nr);
-    gmx_ana_pos_set_evalgrp(p, &pc->gmax);
 }
 
 /*!
@@ -1153,7 +1152,6 @@ gmx_ana_poscalc_update(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p,
     /* Update the index map */
     if (pc->flags & POS_DYNAMIC)
     {
-        gmx_ana_pos_set_evalgrp(p, g);
         gmx_ana_indexmap_update(&p->m, g, false);
         p->nr = p->m.nr;
     }
index 3c34d77a805adf9a4024c5d86abcfa425b54551a..e6754a447219a202f271a70e054313064cb295a0 100644 (file)
@@ -62,7 +62,6 @@ gmx_ana_pos_clear(gmx_ana_pos_t *pos)
     pos->v  = NULL;
     pos->f  = NULL;
     gmx_ana_indexmap_clear(&pos->m);
-    pos->g        = NULL;
     pos->nalloc_x = 0;
 }
 
@@ -138,6 +137,36 @@ gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos)
     }
 }
 
+/*!
+ * \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[out]    pos  Position data structure to initialize.
  * \param[in]     x    Position vector to use.
@@ -228,7 +257,6 @@ gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, bool bFirst)
         memcpy(dest->f, src->f, dest->nr*sizeof(*dest->f));
     }
     gmx_ana_indexmap_copy(&dest->m, &src->m, bFirst);
-    dest->g = src->g;
 }
 
 /*!
@@ -241,21 +269,6 @@ gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int nr)
     pos->nr = nr;
 }
 
-/*!
- * \param[in,out] pos  Position data structure.
- * \param         g    Evaluation group.
- *
- * The old group, if any, is discarded.
- * Note that only a pointer to \p g is stored; it is the responsibility of
- * the caller to ensure that \p g is not freed while it can be accessed
- * through \p pos.
- */
-void
-gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g)
-{
-    pos->g = g;
-}
-
 /*!
  * \param[in,out] pos   Position data structure.
  *
@@ -264,11 +277,12 @@ gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g)
 void
 gmx_ana_pos_empty_init(gmx_ana_pos_t *pos)
 {
-    pos->nr        = 0;
-    pos->m.nr      = 0;
-    pos->m.mapb.nr = 0;
-    pos->m.b.nr    = 0;
-    pos->m.b.nra   = 0;
+    pos->nr         = 0;
+    pos->m.nr       = 0;
+    pos->m.mapb.nr  = 0;
+    pos->m.mapb.nra = 0;
+    pos->m.b.nr     = 0;
+    pos->m.b.nra    = 0;
     /* This should not really be necessary, but do it for safety... */
     pos->m.mapb.index[0] = 0;
     pos->m.b.index[0]    = 0;
@@ -286,9 +300,10 @@ gmx_ana_pos_empty_init(gmx_ana_pos_t *pos)
 void
 gmx_ana_pos_empty(gmx_ana_pos_t *pos)
 {
-    pos->nr        = 0;
-    pos->m.nr      = 0;
-    pos->m.mapb.nr = 0;
+    pos->nr         = 0;
+    pos->m.nr       = 0;
+    pos->m.mapb.nr  = 0;
+    pos->m.mapb.nra = 0;
     /* This should not really be necessary, but do it for safety... */
     pos->m.mapb.index[0] = 0;
     /* We set the flags to true, although really in the empty state they
@@ -301,13 +316,11 @@ gmx_ana_pos_empty(gmx_ana_pos_t *pos)
 
 /*!
  * \param[in,out] dest  Data structure to which the new position is appended.
- * \param[in,out] g     Data structure to which the new atoms are appended.
  * \param[in]     src   Data structure from which the position is copied.
  * \param[in]     i     Index in \p from to copy.
  */
 void
-gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                        gmx_ana_pos_t *src, int i)
+gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, int i)
 {
     int  j, k;
 
@@ -340,11 +353,11 @@ gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
     dest->m.orgid[j] = src->m.orgid[i];
     for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
     {
-        g->index[g->isize++]         = src->g->index[k];
-        dest->m.b.a[dest->m.b.nra++] = src->m.b.a[k];
+        dest->m.mapb.a[dest->m.mapb.nra++] = src->m.mapb.a[k];
+        dest->m.b.a[dest->m.b.nra++]       = src->m.b.a[k];
     }
-    dest->m.mapb.index[j+1] = g->isize;
-    dest->m.b.index[j+1]    = g->isize;
+    dest->m.mapb.index[j+1] = dest->m.mapb.nra;
+    dest->m.b.index[j+1]    = dest->m.mapb.nra;
     dest->nr++;
     dest->m.nr      = dest->nr;
     dest->m.mapb.nr = dest->nr;
@@ -352,76 +365,66 @@ gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
 }
 
 /*!
- * \param[in,out] dest  Data structure to which the new position is appended
- *      (can be NULL, in which case only \p g is updated).
- * \param[in,out] g     Data structure to which the new atoms are appended.
+ * \param[in,out] dest  Data structure to which the new position is appended.
  * \param[in]     src   Data structure from which the position is copied.
  * \param[in]     i     Index in \p src to copy.
  * \param[in]     refid Reference ID in \p out
  *   (all negative values are treated as -1).
- *
- * If \p dest is NULL, the value of \p refid is not used.
  */
 void
-gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                   gmx_ana_pos_t *src, int i, int refid)
+gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, int i, int refid)
 {
-    int  j, k;
-
-    for (k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
+    for (int k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
     {
-        g->index[g->isize++] = src->g->index[k];
+        dest->m.mapb.a[dest->m.mapb.nra++] = src->m.mapb.a[k];
     }
-    if (dest)
+    const int j = dest->nr;
+    if (dest->v)
     {
-        j = dest->nr;
-        if (dest->v)
+        if (src->v)
         {
-            if (src->v)
-            {
-                copy_rvec(src->v[i], dest->v[j]);
-            }
-            else
-            {
-                clear_rvec(dest->v[j]);
-            }
+            copy_rvec(src->v[i], dest->v[j]);
         }
-        if (dest->f)
+        else
         {
-            if (src->f)
-            {
-                copy_rvec(src->f[i], dest->f[j]);
-            }
-            else
-            {
-                clear_rvec(dest->f[j]);
-            }
+            clear_rvec(dest->v[j]);
         }
-        copy_rvec(src->x[i], dest->x[j]);
-        if (refid < 0)
+    }
+    if (dest->f)
+    {
+        if (src->f)
         {
-            dest->m.refid[j] = -1;
-            dest->m.bStatic  = false;
-            /* If we are using masks, there is no need to alter the
-             * mapid field. */
+            copy_rvec(src->f[i], dest->f[j]);
         }
         else
         {
-            if (refid != j)
-            {
-                dest->m.bStatic    = false;
-                dest->m.bMapStatic = false;
-            }
-            dest->m.refid[j] = refid;
-            /* Use the original IDs from the output structure to correctly
-             * handle user customization. */
-            dest->m.mapid[j] = dest->m.orgid[refid];
+            clear_rvec(dest->f[j]);
+        }
+    }
+    copy_rvec(src->x[i], dest->x[j]);
+    if (refid < 0)
+    {
+        dest->m.refid[j] = -1;
+        dest->m.bStatic  = false;
+        /* If we are using masks, there is no need to alter the
+         * mapid field. */
+    }
+    else
+    {
+        if (refid != j)
+        {
+            dest->m.bStatic    = false;
+            dest->m.bMapStatic = false;
         }
-        dest->m.mapb.index[j+1] = g->isize;
-        dest->nr++;
-        dest->m.nr      = dest->nr;
-        dest->m.mapb.nr = dest->nr;
+        dest->m.refid[j] = refid;
+        /* Use the original IDs from the output structure to correctly
+         * handle user customization. */
+        dest->m.mapid[j] = dest->m.orgid[refid];
     }
+    dest->m.mapb.index[j+1] = dest->m.mapb.nra;
+    dest->nr++;
+    dest->m.nr      = dest->nr;
+    dest->m.mapb.nr = dest->nr;
 }
 
 /*!
@@ -440,3 +443,17 @@ gmx_ana_pos_append_finish(gmx_ana_pos_t *pos)
         pos->m.bMapStatic = false;
     }
 }
+
+/*!
+ * \param[in,out] g     Data structure to which the new atoms are appended.
+ * \param[in]     src   Data structure from which the position is copied.
+ * \param[in]     i     Index in \p src to copy.
+ */
+void
+gmx_ana_pos_add_to_group(gmx_ana_index_t *g, gmx_ana_pos_t *src, int i)
+{
+    for (int k = src->m.mapb.index[i]; k < src->m.mapb.index[i+1]; ++k)
+    {
+        g->index[g->isize++] = src->m.mapb.a[k];
+    }
+}
index 4f2b688a74d84e81bd31a14393627b12eafdfb6d..37397008a1e86af987f5267f14c22083736d06fa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -72,10 +72,6 @@ typedef struct gmx_ana_pos_t
      * \see gmx_ana_indexmap_t
      */
     gmx_ana_indexmap_t  m;
-    /*! \brief
-     * Pointer to the current evaluation group.
-     */
-    gmx_ana_index_t    *g;
     /*! \brief
      * Number of elements allocated for \c x.
      */
@@ -94,6 +90,10 @@ gmx_ana_pos_reserve_velocities(gmx_ana_pos_t *pos);
 /** Request memory allocation for forces. */
 void
 gmx_ana_pos_reserve_forces(gmx_ana_pos_t *pos);
+/** Reserves memory for use with gmx_ana_pos_append_init(). */
+void
+gmx_ana_pos_reserve_for_append(gmx_ana_pos_t *pos, int n, int isize,
+                               bool bVelocities, bool bForces);
 /** Initializes a \c gmx_ana_pos_t to represent a constant position. */
 void
 gmx_ana_pos_init_const(gmx_ana_pos_t *pos, const rvec x);
@@ -110,9 +110,6 @@ gmx_ana_pos_copy(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, bool bFirst);
 /** Sets the number of positions in a position structure. */
 void
 gmx_ana_pos_set_nr(gmx_ana_pos_t *pos, int n);
-/** Sets the evaluation group of a position data structure. */
-void
-gmx_ana_pos_set_evalgrp(gmx_ana_pos_t *pos, gmx_ana_index_t *g);
 /** Empties a position data structure with full initialization. */
 void
 gmx_ana_pos_empty_init(gmx_ana_pos_t *pos);
@@ -122,14 +119,15 @@ gmx_ana_pos_empty(gmx_ana_pos_t *pos);
 /** Appends a position to a preallocated data structure with full
  * initialization. */
 void
-gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                        gmx_ana_pos_t *src, int i);
+gmx_ana_pos_append_init(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, int i);
 /** Appends a position to a preallocated data structure. */
 void
-gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_index_t *g,
-                   gmx_ana_pos_t *src, int i, int refid);
+gmx_ana_pos_append(gmx_ana_pos_t *dest, gmx_ana_pos_t *src, int i, int refid);
 /** Updates position data structure state after appends. */
 void
 gmx_ana_pos_append_finish(gmx_ana_pos_t *pos);
+void
+/** Appends atoms from a position into a preallocated index group. */
+gmx_ana_pos_add_to_group(gmx_ana_index_t *g, gmx_ana_pos_t *src, int i);
 
 #endif
index ea476706647ade23ae96ae20b22d1d1afbb6bb39..c3c61bd5c5b80b4b63bb7155f6edb00ea7811dcb 100644 (file)
@@ -159,7 +159,7 @@ void computeMassesAndCharges(const t_topology *top, const gmx_ana_pos_t &pos,
         real charge = 0.0;
         for (int i = pos.m.mapb.index[b]; i < pos.m.mapb.index[b+1]; ++i)
         {
-            int index = pos.g->index[i];
+            const int index = pos.m.mapb.a[i];
             mass   += top->atoms.atom[index].m;
             charge += top->atoms.atom[index].q;
         }
@@ -234,8 +234,8 @@ SelectionData::restoreOriginalPositions(const t_topology *top)
     if (isDynamic())
     {
         gmx_ana_pos_t &p = rawPositions_;
-        gmx_ana_index_copy(p.g, rootElement().v.u.g, false);
-        gmx_ana_indexmap_update(&p.m, p.g, hasFlag(gmx::efSelection_DynamicMask));
+        gmx_ana_indexmap_update(&p.m, rootElement().v.u.g,
+                                hasFlag(gmx::efSelection_DynamicMask));
         p.nr = p.m.nr;
         refreshMassesAndCharges(top);
     }
@@ -273,7 +273,9 @@ Selection::printDebugInfo(FILE *fp, int nmaxind) const
     fprintf(fp, "  ");
     printInfo(fp);
     fprintf(fp, "    Group ");
-    gmx_ana_index_dump(fp, p.g, nmaxind);
+    gmx_ana_index_t g;
+    gmx_ana_index_set(&g, p.m.mapb.nra, p.m.mapb.a, 0);
+    gmx_ana_index_dump(fp, &g, nmaxind);
 
     fprintf(fp, "    Block (size=%d):", p.m.mapb.nr);
     if (!p.m.mapb.index)
index 861f407633135c11cd760302f8ed1a7e617b600a..d681c50d4843e9b2f46acae044522b2121baf6a7 100644 (file)
@@ -312,17 +312,13 @@ class Selection
         //! Total number of atoms in the selection.
         int atomCount() const
         {
-            return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
+            return data().rawPositions_.m.mapb.nra;
         }
         //! Returns atom indices of all atoms in the selection.
         ConstArrayRef<int> atomIndices() const
         {
-            if (data().rawPositions_.g == NULL)
-            {
-                return ConstArrayRef<int>();
-            }
-            return ConstArrayRef<int>(data().rawPositions_.g->index,
-                                      data().rawPositions_.g->isize);
+            return ConstArrayRef<int>(sel_->rawPositions_.m.mapb.a,
+                                      sel_->rawPositions_.m.mapb.nra);
         }
         //! Number of positions in the selection.
         int posCount() const { return data().posCount(); }
@@ -636,13 +632,13 @@ class SelectionPosition
         //! Return atom indices that make up this position.
         ConstArrayRef<int> atomIndices() const
         {
-            if (sel_->rawPositions_.g == NULL)
+            const int *atoms = sel_->rawPositions_.m.mapb.a;
+            if (atoms == NULL)
             {
                 return ConstArrayRef<int>();
             }
-            int first = sel_->rawPositions_.m.mapb.index[i_];
-            return ConstArrayRef<int>(&sel_->rawPositions_.g->index[first],
-                                      atomCount());
+            const int first = sel_->rawPositions_.m.mapb.index[i_];
+            return ConstArrayRef<int>(&atoms[first], atomCount());
         }
         /*! \brief
          * Returns whether this position is selected in the current frame.
index 6e9d8d276a78fa704c4c9cea9342d740473c62aa..44bda5be25b84f829049901dbced13f45325f31d 100644 (file)
@@ -268,7 +268,7 @@ evaluate_distance(t_topology *top, t_trxframe *fr, t_pbc *pbc,
 {
     t_methoddata_distance *d = (t_methoddata_distance *)data;
 
-    out->nr = pos->g->isize;
+    out->nr = pos->m.mapb.nra;
     for (int b = 0; b < pos->nr; ++b)
     {
         real dist = d->nbsearch.minimumDistance(pos->x[b]);
@@ -297,7 +297,7 @@ evaluate_within(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     {
         if (d->nbsearch.isWithin(pos->x[b]))
         {
-            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
+            gmx_ana_pos_add_to_group(out->u.g, pos, b);
         }
     }
 }
index 80eedd164ef53ff995c11c53c8977bd316cdb575..16ae2a5f3df47003a722ffa4f9ca29815f757811 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -487,7 +487,7 @@ evaluate_insolidangle(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     {
         if (accept_insolidangle(pos->x[b], pbc, data))
         {
-            gmx_ana_pos_append(NULL, out->u.g, pos, b, 0);
+            gmx_ana_pos_add_to_group(out->u.g, pos, b);
         }
     }
 }
index 803ee1eac7ed70bbb915687da188457719c3e7bd..61bcb085ffabf0656d48caec6f9d8bcd5dc2c4a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -56,8 +56,6 @@ typedef struct
     gmx_ana_pos_t    p1;
     /** Other input positions. */
     gmx_ana_pos_t    p2;
-    /** Group to store the output atom indices. */
-    gmx_ana_index_t  g;
     /** Stride for merging (\c stride values from \c p1 for each in \c p2). */
     int              stride;
 } t_methoddata_merge;
@@ -198,11 +196,6 @@ init_merge(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
     {
         GMX_THROW(gmx::InconsistentInputError("The number of positions to be merged are not compatible"));
     }
-    /* We access the m.b.nra field instead of g->isize in the position
-     * data structures to handle cases where g is NULL
-     * (this occurs with constant positions. */
-    gmx_ana_index_reserve(&d->g, d->p1.m.b.nra + d->p2.m.b.nra);
-    d->g.isize = d->p1.m.b.nra + d->p2.m.b.nra;
 }
 
 /*! \brief
@@ -226,18 +219,10 @@ init_output_common(t_topology *top, gmx_ana_selvalue_t *out, void *data)
     {
         out->u.p->m.type = d->p1.m.type;
     }
-    gmx_ana_pos_reserve(out->u.p, d->p1.nr + d->p2.nr, d->g.isize);
-    if (d->p1.v)
-    {
-        gmx_ana_pos_reserve_velocities(out->u.p);
-    }
-    if (d->p1.f)
-    {
-        gmx_ana_pos_reserve_forces(out->u.p);
-    }
-    gmx_ana_pos_set_evalgrp(out->u.p, &d->g);
+    gmx_ana_pos_reserve_for_append(out->u.p, d->p1.nr + d->p2.nr,
+                                   d->p1.m.b.nra + d->p2.m.b.nra,
+                                   d->p1.v != NULL, d->p1.f != NULL);
     gmx_ana_pos_empty_init(out->u.p);
-    d->g.isize = 0;
 }
 
 /*!
@@ -256,9 +241,9 @@ init_output_merge(t_topology *top, gmx_ana_selvalue_t *out, void *data)
     {
         for (j = 0; j < d->stride; ++j)
         {
-            gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, d->stride*i+j);
+            gmx_ana_pos_append_init(out->u.p, &d->p1, d->stride * i + j);
         }
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
+        gmx_ana_pos_append_init(out->u.p, &d->p2, i);
     }
 }
 
@@ -276,11 +261,11 @@ init_output_plus(t_topology *top, gmx_ana_selvalue_t *out, void *data)
     init_output_common(top, out, data);
     for (i = 0; i < d->p1.nr; ++i)
     {
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p1, i);
+        gmx_ana_pos_append_init(out->u.p, &d->p1, i);
     }
     for (i = 0; i < d->p2.nr; ++i)
     {
-        gmx_ana_pos_append_init(out->u.p, &d->g, &d->p2, i);
+        gmx_ana_pos_append_init(out->u.p, &d->p2, i);
     }
 }
 
@@ -294,7 +279,6 @@ free_data_merge(void *data)
 {
     t_methoddata_merge *d = (t_methoddata_merge *)data;
 
-    gmx_ana_index_deinit(&d->g);
     sfree(d);
 }
 
@@ -318,7 +302,6 @@ evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     {
         GMX_THROW(gmx::InconsistentInputError("The number of positions to be merged are not compatible"));
     }
-    d->g.isize = 0;
     gmx_ana_pos_empty(out->u.p);
     for (i = 0; i < d->p2.nr; ++i)
     {
@@ -329,10 +312,10 @@ evaluate_merge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
             {
                 refid = (d->stride+1) * (refid / d->stride) + (refid % d->stride);
             }
-            gmx_ana_pos_append(out->u.p, &d->g, &d->p1, d->stride*i+j, refid);
+            gmx_ana_pos_append(out->u.p, &d->p1, d->stride*i+j, refid);
         }
-        refid = (d->stride+1)*d->p2.m.refid[i]+d->stride;
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
+        refid = (d->stride+1)*d->p2.m.refid[i] + d->stride;
+        gmx_ana_pos_append(out->u.p, &d->p2, i, refid);
     }
     gmx_ana_pos_append_finish(out->u.p);
 }
@@ -353,12 +336,11 @@ evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     int                 i;
     int                 refid;
 
-    d->g.isize = 0;
     gmx_ana_pos_empty(out->u.p);
     for (i = 0; i < d->p1.nr; ++i)
     {
         refid = d->p1.m.refid[i];
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p1, i, refid);
+        gmx_ana_pos_append(out->u.p, &d->p1, i, refid);
     }
     for (i = 0; i < d->p2.nr; ++i)
     {
@@ -367,7 +349,7 @@ evaluate_plus(t_topology *top, t_trxframe *fr, t_pbc *pbc,
         {
             refid += d->p1.m.b.nr;
         }
-        gmx_ana_pos_append(out->u.p, &d->g, &d->p2, i, refid);
+        gmx_ana_pos_append(out->u.p, &d->p2, i, refid);
     }
     gmx_ana_pos_append_finish(out->u.p);
 }
index 894bbf3616113cb665c15f50fa31f7441fe59d8e..da741d26bd2c84ab669bed3daed15bac7c971eab 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -55,8 +55,6 @@ typedef struct
 {
     /** Positions to permute. */
     gmx_ana_pos_t    p;
-    /** Group to receive the output permutation. */
-    gmx_ana_index_t  g;
     /** Number of elements in the permutation. */
     int              n;
     /** Array describing the permutation. */
@@ -153,7 +151,6 @@ init_permute(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
     t_methoddata_permute *d = (t_methoddata_permute *)data;
     int                   i;
 
-    gmx_ana_index_reserve(&d->g, d->p.g->isize);
     d->n    = param[1].val.nr;
     d->perm = param[1].val.u.i;
     if (d->p.nr % d->n != 0)
@@ -192,16 +189,16 @@ 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;
+    out->u.p->m.type = d->p.m.type;
+    gmx_ana_pos_reserve_for_append(out->u.p, d->p.nr, d->p.m.b.nra,
+                                   d->p.v != NULL, d->p.f != NULL);
     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);
+            gmx_ana_pos_append_init(out->u.p, &d->p, b);
         }
     }
 }
@@ -216,7 +213,6 @@ free_data_permute(void *data)
 {
     t_methoddata_permute *d = (t_methoddata_permute *)data;
 
-    gmx_ana_index_deinit(&d->g);
     sfree(d->rperm);
     sfree(d);
 }
@@ -246,7 +242,6 @@ evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
         GMX_THROW(gmx::InconsistentInputError(
                           gmx::formatString("The number of positions to be permuted is not divisible by %d", d->n)));
     }
-    d->g.isize = 0;
     gmx_ana_pos_empty(out->u.p);
     for (i = 0; i < d->p.nr; i += d->n)
     {
@@ -259,7 +254,7 @@ evaluate_permute(t_topology *top, t_trxframe *fr, t_pbc *pbc,
                 /* De-permute the reference ID */
                 refid = refid - (refid % d->n) + d->perm[refid % d->n];
             }
-            gmx_ana_pos_append(out->u.p, &d->g, p, b, refid);
+            gmx_ana_pos_append(out->u.p, p, b, refid);
         }
     }
     gmx_ana_pos_append_finish(out->u.p);
index 0669a01527410b30f3f0a37b0369f0882e8e85d8..13f6b3be7652bfa8d10791cd5cc18cba8c7bce76 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -320,7 +320,6 @@ 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);
 }
 
 /*!
index 97c20e2d9b4c6ccf3c60c8d8d277532986603140..f510e1ed90bf227bacc349612d20e70520c7f443 100644 (file)
@@ -837,8 +837,6 @@ evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
 /*! \brief
  * Internal utility function for position keyword evaluation.
  *
- * \param[in]  fr   Current frame.
- * \param[in]  g    Index group for which the coordinates should be evaluated.
  * \param[out] out  Output array.
  * \param[in]  pos  Position data to use instead of atomic coordinates
  *   (can be NULL).
@@ -848,33 +846,19 @@ evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
  * evaluate_z() to do the actual evaluation.
  */
 static void
-evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
-               gmx_ana_pos_t *pos, int d)
+evaluate_coord(real out[], gmx_ana_pos_t *pos, int d)
 {
-    int  b, i;
-    real v;
-
-    if (pos)
-    {
-        for (b = 0; b < pos->nr; ++b)
-        {
-            v = pos->x[b][d];
-            for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
-            {
-                out[i] = v;
-            }
-        }
-    }
-    else
+    for (int b = 0; b < pos->nr; ++b)
     {
-        // TODO: This loop is never reached in the current code.
-        // It would be useful to change the code such that it is, mostly for
-        // memory efficiency reasons.
-        for (i = 0; i < g->isize; ++i)
+        const real v = pos->x[b][d];
+        for (int i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
         {
-            out[i] = fr->x[g->index[i]][d];
+            out[i] = v;
         }
     }
+    // TODO: Make this more efficient by directly extracting the coordinates
+    // from the frame coordinates for atomic positions instead of going through
+    // a position calculation.
 }
 
 /*!
@@ -884,11 +868,11 @@ evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
  * Returns the \p x coordinate for each atom in \p out->u.r.
  */
 static void
-evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+evaluate_x(t_topology * /*top*/, t_trxframe * /*fr*/, t_pbc * /*pbc*/,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
 {
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, XX);
+    out->nr = pos->m.mapb.nra;
+    evaluate_coord(out->u.r, pos, XX);
 }
 
 /*!
@@ -898,11 +882,11 @@ evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
  * Returns the \p y coordinate for each atom in \p out->u.r.
  */
 static void
-evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+evaluate_y(t_topology * /*top*/, t_trxframe * /*fr*/, t_pbc * /*pbc*/,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
 {
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, YY);
+    out->nr = pos->m.mapb.nra;
+    evaluate_coord(out->u.r, pos, YY);
 }
 
 /*!
@@ -912,9 +896,9 @@ evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
  * Returns the \p z coordinate for each atom in \p out->u.r.
  */
 static void
-evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
+evaluate_z(t_topology * /*top*/, t_trxframe * /*fr*/, t_pbc * /*pbc*/,
+           gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
 {
-    out->nr = pos->g->isize;
-    evaluate_coord(fr, pos->g, out->u.r, pos, ZZ);
+    out->nr = pos->m.mapb.nra;
+    evaluate_coord(out->u.r, pos, ZZ);
 }
index 50f3325a76c5a9f8d95689fb73f8233da4a29410..cd74475a564b850499d9c227debf283e8c1e9815 100644 (file)
@@ -234,8 +234,6 @@ void PositionCalculationTest::updateAndCheck(
         gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p, int count, const int atoms[],
         gmx::test::TestReferenceChecker *checker, const char *name)
 {
-    // TODO: The group reference may get stored in p and stays there after this
-    // function returns.
     gmx_ana_index_t g;
     g.isize = count;
     g.index = const_cast<int *>(atoms);
@@ -315,7 +313,6 @@ void PositionCalculationTest::checkPositions(
 {
     EXPECT_EQ(p->nr, p->m.nr);
     EXPECT_EQ(p->nr, p->m.mapb.nr);
-    ASSERT_TRUE(p->g != NULL);
     gmx::test::TestReferenceChecker compound(
             checker->checkCompound("Positions", name));
     compound.checkInteger(p->nr, "Count");
@@ -334,13 +331,9 @@ void PositionCalculationTest::checkPositions(
     {
         gmx::test::TestReferenceChecker posCompound(
                 compound.checkCompound("Position", NULL));
-        // Always true; should satisfy clang.
-        if (p->g != NULL)
-        {
-            posCompound.checkSequence(&p->g->index[p->m.mapb.index[i]],
-                                      &p->g->index[p->m.mapb.index[i+1]],
-                                      "Atoms");
-        }
+        posCompound.checkSequence(&p->m.mapb.a[p->m.mapb.index[i]],
+                                  &p->m.mapb.a[p->m.mapb.index[i+1]],
+                                  "Atoms");
         posCompound.checkInteger(p->m.refid[i], "RefId");
         if (bCoordinates)
         {