Prepare SelectionCollection for parallel analysis
authorKevin Boyd <kevin44boyd@gmail.com>
Mon, 12 Apr 2021 08:52:57 +0000 (08:52 +0000)
committerPaul Bauer <paul.bauer.q@gmail.com>
Mon, 12 Apr 2021 08:52:57 +0000 (08:52 +0000)
src/gromacs/selection/selection.h
src/gromacs/selection/selectioncollection.cpp
src/gromacs/selection/selectioncollection.h
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWithIndexPostCompilation.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPostCompilation.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPreCompilation.xml [new file with mode: 0644]
src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionsAreIndependent.xml [new file with mode: 0644]
src/gromacs/selection/tests/selectioncollection.cpp

index 7119ea3fffc42c2c8caf81e1e0db003796b5bde4..8d950d5a6244091e439dfbb5e86ca0b247dddb10 100644 (file)
@@ -124,6 +124,8 @@ public:
     bool hasFlag(SelectionFlag flag) const { return flags_.test(flag); }
     //! Sets the flags for this selection.
     void setFlags(SelectionFlags flags) { flags_ = flags; }
+    //! Returns the current flags.
+    SelectionFlags flags() const { return flags_; }
 
     //! \copydoc Selection::initCoveredFraction()
     bool initCoveredFraction(e_coverfrac_t type);
index 0ed46f789232755a27b6713d3b3019b2ef11d484..ed13f9c69fea8bbc2bb0318ce1934148bd8ac466 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -48,6 +48,7 @@
 #include <cstdio>
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -57,7 +58,6 @@
 #include "gromacs/options/ioptionscontainer.h"
 #include "gromacs/selection/selection.h"
 #include "gromacs/selection/selhelp.h"
-#include "gromacs/topology/mtop_util.h"
 #include "gromacs/topology/topology.h"
 #include "gromacs/trajectory/trajectoryframe.h"
 #include "gromacs/utility/exceptions.h"
@@ -530,8 +530,55 @@ SelectionCollection::Impl::requiredTopologyPropertiesForPositionType(const std::
 SelectionCollection::SelectionCollection() : impl_(new Impl) {}
 
 
-SelectionCollection::~SelectionCollection() {}
+SelectionCollection::~SelectionCollection() = default;
 
+SelectionCollection::SelectionCollection(const SelectionCollection& rhs) :
+    impl_(std::make_unique<Impl>())
+{
+    setReferencePosType(rhs.impl_->rpost_.empty() ? PositionCalculationCollection::typeEnumValues[0]
+                                                  : rhs.impl_->rpost_.c_str());
+    setOutputPosType(rhs.impl_->spost_.empty() ? PositionCalculationCollection::typeEnumValues[0]
+                                               : rhs.impl_->spost_.c_str());
+    setDebugLevel(static_cast<int>(rhs.impl_->debugLevel_));
+
+    for (size_t i = 0; i < rhs.impl_->sc_.sel.size(); i++)
+    {
+        const auto& selectionOption = rhs.impl_->sc_.sel[i];
+        parseFromString(selectionOption->selectionText());
+        impl_->sc_.sel[i]->setFlags(selectionOption->flags());
+    }
+
+    // Topology has been initialized in rhs if top is non-null or natoms is set.
+    // Note this needs to be set after selections are parsed to register topology requirements properly.
+    if (rhs.impl_->sc_.top != nullptr || rhs.impl_->sc_.gall.isize > 0)
+    {
+        setTopology(rhs.impl_->sc_.top, rhs.impl_->sc_.gall.isize);
+        gmx_ana_index_copy(&impl_->sc_.gall, &rhs.impl_->sc_.gall, /*balloc=*/false);
+    }
+
+    if (rhs.impl_->grps_ != nullptr)
+    {
+        setIndexGroups(rhs.impl_->grps_);
+    }
+
+    // Only compile the selection if rhs is compiled.
+    if (rhs.impl_->sc_.mempool != nullptr)
+    {
+        compile();
+    }
+}
+
+SelectionCollection& SelectionCollection::operator=(SelectionCollection rhs)
+{
+    rhs.swap(*this);
+    return *this;
+}
+
+void SelectionCollection::swap(SelectionCollection& rhs)
+{
+    using std::swap;
+    swap(impl_, rhs.impl_);
+}
 
 void SelectionCollection::initOptions(IOptionsContainer* options, SelectionTypeOption selectionTypeOption)
 {
@@ -594,7 +641,7 @@ void SelectionCollection::setDebugLevel(int debugLevel)
 }
 
 
-void SelectionCollection::setTopology(gmx_mtop_t* top, int natoms)
+void SelectionCollection::setTopology(const gmx_mtop_t* top, int natoms)
 {
     GMX_RELEASE_ASSERT(natoms > 0 || top != nullptr,
                        "The number of atoms must be given if there is no topology");
@@ -877,6 +924,20 @@ void SelectionCollection::evaluateFinal(int nframes)
     evaluator.evaluateFinal(this, nframes);
 }
 
+std::optional<Selection> SelectionCollection::selection(std::string_view selName) const
+{
+    const auto& selections = impl_->sc_.sel;
+    if (const auto foundIter = std::find_if(
+                selections.cbegin(),
+                selections.cend(),
+                [selName](const auto& selection) { return selection->name() == selName; });
+        foundIter != selections.end())
+    {
+        return Selection(foundIter->get());
+    }
+    return std::nullopt;
+}
+
 
 void SelectionCollection::printTree(FILE* fp, bool bValues) const
 {
@@ -904,4 +965,9 @@ void SelectionCollection::printXvgrInfo(FILE* out) const
     std::fprintf(out, "#\n");
 }
 
+void swap(SelectionCollection& lhs, SelectionCollection& rhs)
+{
+    lhs.swap(rhs);
+}
+
 } // namespace gmx
index 7e3c13560759a437706366f6fb82ad243f7ceb13..e02ed9f32ac35a191de09c5224d85f0c1255bb6f 100644 (file)
@@ -47,6 +47,7 @@
 #include <cstdio>
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -61,7 +62,6 @@ namespace gmx
 {
 
 class IOptionsContainer;
-class SelectionCompiler;
 class SelectionEvaluator;
 class TextInputStream;
 class TextOutputStream;
@@ -81,6 +81,11 @@ struct SelectionTopologyProperties;
  * setOutputPosType().  See these methods for more details on the
  * initialization options.
  *
+ * SelectionCollections can be copied. Copies retain the same pointers to external indices (if set)
+ * and the topology (if set), and are compiled if the copied collection is compiled. Selection
+ * objects created from a given SelectionCollection are tied only to the original collection, so
+ * a copy of a SelectionCollection will not update pre-existing Selections on evaluate() calls.
+ *
  * After setting the default values, one or more selections can be parsed with
  * one or more calls to parseInteractive(), parseFromStdin(), parseFromFile(), and/or
  * parseFromString().  After all selections are parsed, the topology must be
@@ -138,6 +143,10 @@ public:
     SelectionCollection();
     ~SelectionCollection();
 
+    SelectionCollection(const SelectionCollection& rhs);
+    SelectionCollection& operator=(SelectionCollection rhs);
+    void                 swap(SelectionCollection& rhs);
+
     /*! \brief
      * Initializes options for setting global properties on the collection.
      *
@@ -246,7 +255,7 @@ public:
      * Does not throw currently, but this is subject to change when more
      * underlying code is converted to C++.
      */
-    void setTopology(gmx_mtop_t* top, int natoms);
+    void setTopology(const gmx_mtop_t* top, int natoms);
     /*! \brief
      * Sets the external index groups to use for the selections.
      *
@@ -388,7 +397,13 @@ public:
      * Does not throw.
      */
     void evaluateFinal(int nframes);
-
+    /*! \brief
+     * Retrieves a Selection handle for the selection with the given name
+     *
+     * @param selName name of the selection to return
+     * @return The selection with the given name, or nullopt if no such selection exists.
+     */
+    [[nodiscard]] std::optional<Selection> selection(std::string_view selName) const;
     /*! \brief
      * Prints a human-readable version of the internal selection element
      * tree.
@@ -422,6 +437,8 @@ private:
     friend class SelectionEvaluator;
 };
 
+void swap(SelectionCollection& lhs, SelectionCollection& rhs);
+
 } // namespace gmx
 
 #endif
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWithIndexPostCompilation.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWithIndexPostCompilation.xml
new file mode 100644 (file)
index 0000000..8cae2e6
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <ParsedSelections Name="Parsed">
+    <ParsedSelection Name="Selection1">
+      <String Name="Input">group "GrpA"</String>
+      <String Name="Name">GrpA</String>
+      <String Name="Text">group "GrpA"</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection2">
+      <String Name="Input">GrpB</String>
+      <String Name="Name">GrpB</String>
+      <String Name="Text">GrpB</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection3">
+      <String Name="Input">1</String>
+      <String Name="Name">GrpB</String>
+      <String Name="Text">1</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection4">
+      <String Name="Input">group "GrpB" and resname RB</String>
+      <String Name="Name">group "GrpB" and resname RB</String>
+      <String Name="Text">group "GrpB" and resname RB</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection5">
+      <String Name="Input">group "GrpA" permute 5 3 2 1 4</String>
+      <String Name="Name">group "GrpA" permute 5 3 2 1 4</String>
+      <String Name="Text">group "GrpA" permute 5 3 2 1 4</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection6">
+      <String Name="Input">group "GrpA" plus group "GrpB"</String>
+      <String Name="Name">group "GrpA" plus group "GrpB"</String>
+      <String Name="Text">group "GrpA" plus group "GrpB"</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection7">
+      <String Name="Input">res_cog of group "GrpA"</String>
+      <String Name="Name">res_cog of group "GrpA"</String>
+      <String Name="Text">res_cog of group "GrpA"</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+  </ParsedSelections>
+  <CompiledSelections Name="Compiled">
+    <Selection Name="Selection1">
+      <String Name="Name">GrpA</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">5</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <String Name="Name">GrpB</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">5</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <String Name="Name">GrpB</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">5</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <String Name="Name">group "GrpB" and resname RB</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">3</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <String Name="Name">group "GrpA" permute 5 3 2 1 4</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">5</Int>
+        <Int>3</Int>
+        <Int>2</Int>
+        <Int>1</Int>
+        <Int>4</Int>
+        <Int>0</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection6">
+      <String Name="Name">group "GrpA" plus group "GrpB"</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">10</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection7">
+      <String Name="Name">res_cog of group "GrpA"</String>
+      <Sequence Name="Atoms">
+        <Int Name="Length">5</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+      </Sequence>
+    </Selection>
+  </CompiledSelections>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPostCompilation.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPostCompilation.xml
new file mode 100644 (file)
index 0000000..3c59289
--- /dev/null
@@ -0,0 +1,397 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <ParsedSelections Name="Parsed">
+    <ParsedSelection Name="Selection1">
+      <String Name="Input">x &gt; 2</String>
+      <String Name="Text">x &gt; 2</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection2">
+      <String Name="Input">2 &lt; x</String>
+      <String Name="Text">2 &lt; x</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection3">
+      <String Name="Input">y &gt; resnr</String>
+      <String Name="Text">y &gt; resnr</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection4">
+      <String Name="Input">resnr &lt; 2.5</String>
+      <String Name="Text">resnr &lt; 2.5</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection5">
+      <String Name="Input">2.5 &gt; resnr</String>
+      <String Name="Text">2.5 &gt; resnr</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+  </ParsedSelections>
+  <CompiledSelections Name="Compiled">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+  </CompiledSelections>
+  <EvaluatedSelections Name="Frame1">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">4</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>7</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">4</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+  </EvaluatedSelections>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPreCompilation.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionWorksPreCompilation.xml
new file mode 100644 (file)
index 0000000..3c59289
--- /dev/null
@@ -0,0 +1,397 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <ParsedSelections Name="Parsed">
+    <ParsedSelection Name="Selection1">
+      <String Name="Input">x &gt; 2</String>
+      <String Name="Text">x &gt; 2</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection2">
+      <String Name="Input">2 &lt; x</String>
+      <String Name="Text">2 &lt; x</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection3">
+      <String Name="Input">y &gt; resnr</String>
+      <String Name="Text">y &gt; resnr</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection4">
+      <String Name="Input">resnr &lt; 2.5</String>
+      <String Name="Text">resnr &lt; 2.5</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection5">
+      <String Name="Input">2.5 &gt; resnr</String>
+      <String Name="Text">2.5 &gt; resnr</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+  </ParsedSelections>
+  <CompiledSelections Name="Compiled">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+  </CompiledSelections>
+  <EvaluatedSelections Name="Frame1">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">4</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>7</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">4</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+  </EvaluatedSelections>
+</ReferenceData>
diff --git a/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionsAreIndependent.xml b/src/gromacs/selection/tests/refdata/SelectionCollectionDataTest_CopiedSelectionsAreIndependent.xml
new file mode 100644 (file)
index 0000000..3c59289
--- /dev/null
@@ -0,0 +1,397 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <ParsedSelections Name="Parsed">
+    <ParsedSelection Name="Selection1">
+      <String Name="Input">x &gt; 2</String>
+      <String Name="Text">x &gt; 2</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection2">
+      <String Name="Input">2 &lt; x</String>
+      <String Name="Text">2 &lt; x</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection3">
+      <String Name="Input">y &gt; resnr</String>
+      <String Name="Text">y &gt; resnr</String>
+      <Bool Name="Dynamic">true</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection4">
+      <String Name="Input">resnr &lt; 2.5</String>
+      <String Name="Text">resnr &lt; 2.5</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+    <ParsedSelection Name="Selection5">
+      <String Name="Input">2.5 &gt; resnr</String>
+      <String Name="Text">2.5 &gt; resnr</String>
+      <Bool Name="Dynamic">false</Bool>
+    </ParsedSelection>
+  </ParsedSelections>
+  <CompiledSelections Name="Compiled">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">15</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+        <Int>6</Int>
+        <Int>7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+    </Selection>
+  </CompiledSelections>
+  <EvaluatedSelections Name="Frame1">
+    <Selection Name="Selection1">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection2">
+      <Sequence Name="Atoms">
+        <Int Name="Length">7</Int>
+        <Int>8</Int>
+        <Int>9</Int>
+        <Int>10</Int>
+        <Int>11</Int>
+        <Int>12</Int>
+        <Int>13</Int>
+        <Int>14</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">7</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">3</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">4</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection3">
+      <Sequence Name="Atoms">
+        <Int Name="Length">4</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>7</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">4</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection4">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+    <Selection Name="Selection5">
+      <Sequence Name="Atoms">
+        <Int Name="Length">6</Int>
+        <Int>0</Int>
+        <Int>1</Int>
+        <Int>2</Int>
+        <Int>3</Int>
+        <Int>4</Int>
+        <Int>5</Int>
+      </Sequence>
+      <Sequence Name="Positions">
+        <Int Name="Length">6</Int>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">3</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">1</Real>
+            <Real Name="Y">4</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">1</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+        <Position>
+          <Vector Name="Coordinates">
+            <Real Name="X">2</Real>
+            <Real Name="Y">2</Real>
+            <Real Name="Z">0</Real>
+          </Vector>
+        </Position>
+      </Sequence>
+    </Selection>
+  </EvaluatedSelections>
+</ReferenceData>
index a7a54235b0b8c0540d424a63112d52c08fc1d28a..7b835c0481285364cf115603283779d975717fb1 100644 (file)
@@ -2,7 +2,7 @@
  * This file is part of the GROMACS molecular simulation package.
  *
  * Copyright (c) 2010-2018, The GROMACS development team.
- * Copyright (c) 2019,2020, by the GROMACS development team, led by
+ * Copyright (c) 2019,2020,2021, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -138,7 +138,6 @@ void SelectionCollectionTest::loadIndexGroups(const char* filename)
     sc_.setIndexGroups(grps_);
 }
 
-
 /********************************************************************
  * Test fixture for interactive SelectionCollection tests
  */
@@ -200,12 +199,13 @@ public:
     void runTest(int natoms, const gmx::ArrayRef<const char* const>& selections);
     void runTest(const char* filename, const gmx::ArrayRef<const char* const>& selections);
 
+    void checkCompiled();
+
 private:
     static void checkSelection(gmx::test::TestReferenceChecker* checker,
                                const gmx::Selection&            sel,
                                TestFlags                        flags);
 
-    void checkCompiled();
 
     gmx::test::TestReferenceData    data_;
     gmx::test::TestReferenceChecker checker_;
@@ -636,6 +636,47 @@ TEST_F(SelectionCollectionTest, HandlesFramesWithTooSmallAtomSubsets4)
 
 // TODO: Tests for more evaluation errors
 
+
+/********************************************************************
+ * Tests for retrieving selections.
+ */
+TEST_F(SelectionCollectionTest, RetrieveValidSelection)
+{
+    ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
+    const std::optional<gmx::Selection> retrievedSel = sc_.selection(sel_[0].name());
+    ASSERT_TRUE(retrievedSel.has_value());
+    EXPECT_STREQ(sel_[0].name(), retrievedSel->name());
+}
+
+TEST_F(SelectionCollectionTest, RetrieveInvalidSelection)
+{
+    ASSERT_FALSE(sc_.selection("some invalid key").has_value());
+}
+
+/********************************************************************
+ * Tests for assignment/copying.
+ */
+TEST_F(SelectionCollectionTest, CanCopyEmptyCollection)
+{
+    EXPECT_NO_THROW_GMX(gmx::SelectionCollection sc2(sc_));
+}
+
+TEST_F(SelectionCollectionTest, CopiedSelectionListsAreHandledSeparately)
+{
+    ASSERT_NO_THROW_GMX(sel_ = sc_.parseFromString("atomnr 1 to 10; none"));
+    EXPECT_FALSE(sc_.requiredTopologyProperties().hasAny());
+    ASSERT_NO_FATAL_FAILURE(setAtomCount(10));
+    ASSERT_EQ(2U, sel_.size());
+    gmx::SelectionCollection sc2(sc_);
+    ASSERT_NO_THROW_GMX(sel_[1].setEvaluateVelocities(true));
+    ASSERT_NO_THROW_GMX(sel_[1].setEvaluateForces(true));
+    ASSERT_NO_THROW_GMX(sc2.compile());
+    // These would only be populated if sc_.compile() was called
+    EXPECT_FALSE(sel_[1].hasVelocities());
+    EXPECT_FALSE(sel_[1].hasForces());
+}
+
+
 /********************************************************************
  * Tests for interactive selection input
  */
@@ -1398,5 +1439,121 @@ TEST_F(SelectionCollectionDataTest, HandlesVariablesWithMixedEvaluationGroups2)
     runTest("simple.gro", selections);
 }
 
+/*******************************************************************
+ * Tests for copy validation.
+ *
+ * These tests ensure that copies of a SelectionCollection behave as the original while being
+ * independently evaluated.
+ */
+TEST_F(SelectionCollectionDataTest, CopiedSelectionWorksPreCompilation)
+{
+    static const char* const selections[] = {
+        "x > 2", "2 < x", "y > resnr", "resnr < 2.5", "2.5 > resnr"
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    std::vector<std::string> selNames;
+    for (const auto& sel : sel_)
+    {
+        selNames.emplace_back(sel.name());
+    }
+    // Swap copied selection with original and update selections, to reuse the testing machinery.
+    gmx::SelectionCollection sc2(sc_);
+    sc_ = sc2;
+    std::vector<gmx::Selection> sel2;
+    for (const std::string_view selName : selNames)
+    {
+        std::optional<gmx::Selection> maybeSel = sc_.selection(selName);
+        ASSERT_TRUE(maybeSel.has_value());
+        sel2.push_back(*maybeSel);
+    }
+    sel_ = std::move(sel2);
+
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+    ASSERT_NO_FATAL_FAILURE(runEvaluate());
+    ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
+}
+
+TEST_F(SelectionCollectionDataTest, CopiedSelectionWorksPostCompilation)
+{
+    static const char* const selections[] = {
+        "x > 2", "2 < x", "y > resnr", "resnr < 2.5", "2.5 > resnr"
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+    // Note the copy is made post-compilation.
+    std::vector<std::string> selNames;
+    for (const auto& sel : sel_)
+    {
+        selNames.emplace_back(sel.name());
+    }
+    gmx::SelectionCollection sc2(sc_);
+    sc_ = sc2;
+    std::vector<gmx::Selection> sel2;
+    for (const std::string_view selName : selNames)
+    {
+        std::optional<gmx::Selection> maybeSel = sc_.selection(selName);
+        ASSERT_TRUE(maybeSel.has_value());
+        sel2.push_back(*maybeSel);
+    }
+    sel_ = std::move(sel2);
+
+    ASSERT_NO_FATAL_FAILURE(runEvaluate());
+    ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
+}
+
+TEST_F(SelectionCollectionDataTest, CopiedSelectionsAreIndependent)
+{
+    static const char* const selections[] = {
+        "x > 2", "2 < x", "y > resnr", "resnr < 2.5", "2.5 > resnr"
+    };
+    setFlags(TestFlags() | efTestEvaluation | efTestPositionCoordinates);
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+    // Check that copy evaluation does not conflict with original.
+    gmx::SelectionCollection sc2(sc_);
+    ASSERT_NO_THROW_GMX(sc2.evaluate(topManager_.frame(), nullptr));
+
+    ASSERT_NO_FATAL_FAILURE(runEvaluate());
+    ASSERT_NO_FATAL_FAILURE(runEvaluateFinal());
+}
+
+TEST_F(SelectionCollectionDataTest, CopiedSelectionWithIndexPostCompilation)
+{
+    static const char* const selections[] = { "group \"GrpA\"",
+                                              "GrpB",
+                                              "1",
+                                              "group \"GrpB\" and resname RB",
+                                              "group \"GrpA\" permute 5 3 2 1 4",
+                                              "group \"GrpA\" plus group \"GrpB\"",
+                                              "res_cog of group \"GrpA\"" };
+    setFlags(TestFlags() | efTestSelectionNames);
+    ASSERT_NO_THROW_GMX(loadIndexGroups("simple.ndx"));
+    ASSERT_NO_FATAL_FAILURE(runParser(selections));
+    ASSERT_NO_FATAL_FAILURE(loadTopology("simple.gro"));
+    ASSERT_NO_FATAL_FAILURE(runCompiler());
+    std::vector<std::string> selNames;
+    for (const auto& sel : sel_)
+    {
+        selNames.emplace_back(sel.name());
+    }
+    gmx::SelectionCollection sc2(sc_);
+    sc_ = sc2;
+    std::vector<gmx::Selection> sel2;
+    for (const std::string_view selName : selNames)
+    {
+        std::optional<gmx::Selection> maybeSel = sc_.selection(selName);
+        ASSERT_TRUE(maybeSel.has_value());
+        sel2.push_back(*maybeSel);
+    }
+    sel_ = std::move(sel2);
+    checkCompiled();
+}
 
 } // namespace