Reinstantiate unsorted index group check
[alexxy/gromacs.git] / src / gromacs / selection / selelem.cpp
index e80e4f75c8d241d946505ec85d6e5901a2666206..a10d5a5802af892480c4664f5984b2e459165660 100644 (file)
@@ -53,6 +53,7 @@
 #include "keywords.h"
 #include "mempool.h"
 #include "selelem.h"
+#include "selmethod.h"
 
 /*!
  * \param[in] sel Selection for which the string is requested
@@ -328,6 +329,43 @@ void SelectionTreeElement::fillNameIfMissing(const char *selectionText)
     }
 }
 
+void SelectionTreeElement::checkUnsortedAtoms(
+        bool bUnsortedAllowed, ExceptionInitializer *errors) const
+{
+    const bool bUnsortedSupported
+        = (type == SEL_CONST && v.type == GROUP_VALUE)
+            || type == SEL_ROOT || type == SEL_SUBEXPR || type == SEL_SUBEXPRREF
+            // TODO: Consolidate.
+            || type == SEL_MODIFIER
+            || (type == SEL_EXPRESSION && (u.expr.method->flags & SMETH_ALLOW_UNSORTED));
+
+    // TODO: For some complicated selections, this may result in the same
+    // index group reference being flagged as an error multiple times for the
+    // same selection.
+    SelectionTreeElementPointer child = this->child;
+    while (child)
+    {
+        child->checkUnsortedAtoms(bUnsortedAllowed && bUnsortedSupported,
+                                  errors);
+        child = child->next;
+    }
+
+    // The logic here is simplified by the fact that only constant groups can
+    // currently be the root cause of SEL_UNSORTED being set, so only those
+    // need to be considered in triggering the error.
+    if (!bUnsortedAllowed && (flags & SEL_UNSORTED)
+        && type == SEL_CONST && v.type == GROUP_VALUE)
+    {
+        std::string message = formatString(
+                    "Group '%s' cannot be used in selections except "
+                    "as a full value of the selection, "
+                    "because atom indices in it are not sorted and/or "
+                    "it contains duplicate atoms.",
+                    name().c_str());
+        errors->addNested(InconsistentInputError(message));
+    }
+}
+
 void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
 {
     GMX_RELEASE_ASSERT(type == SEL_GROUPREF,
@@ -366,16 +404,6 @@ void SelectionTreeElement::resolveIndexGroupReference(gmx_ana_indexgrps_t *grps)
     if (!gmx_ana_index_check_sorted(&foundGroup))
     {
         flags |= SEL_UNSORTED;
-        // TODO: Add this test elsewhere, where it does not break valid use cases.
-#if 0
-        gmx_ana_index_deinit(&foundGroup);
-        std::string message = formatString(
-                    "Group '%s' ('%s') cannot be used in selections, "
-                    "because atom indices in it are not sorted and/or "
-                    "it contains duplicate atoms.",
-                    foundName.c_str(), name().c_str());
-        GMX_THROW(InconsistentInputError(message));
-#endif
     }
 
     sfree(u.gref.name);