diff --git a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.C b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.C
index 570cf5b9d08033e6734dbeca63beee460427d693..6bcbf3102437277ce14e7d3f76dcebc90255b338 100644
--- a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.C
+++ b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.C
@@ -288,6 +288,19 @@ void Foam::globalIndexAndTransform::determineTransforms()
     }
 
     Pstream::scatter(transforms_);
+
+    if (transforms_.size() > 3)
+    {
+        WarningIn
+        (
+            "void globalIndexAndTransform::determineTransforms()"
+        )   << "More than three independent basic "
+            << "transforms detected:" << nl
+            << transforms_ << nl
+            << "This is not a space filling tiling and will probably"
+            << " give problems for e.g. lagrangian tracking or interpolation"
+            << endl;
+    }
 }
 
 
diff --git a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.H b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.H
index d142e542447326547309afec05ed4f087bf13429..9e2c6ddc3dbe9a028409e69bbce51a254c37bbd2 100644
--- a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.H
+++ b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransform.H
@@ -120,6 +120,12 @@ class globalIndexAndTransform
             bool checkBothSigns
         ) const;
 
+        //- Decode transform index. Hardcoded to 3 independent transforms max.
+        inline static FixedList<label, 3> decodeTransformIndex
+        (
+            const label transformIndex
+        );
+
         //- Disallow default bitwise copy construct
         globalIndexAndTransform(const globalIndexAndTransform&);
 
@@ -159,6 +165,20 @@ public:
             const bool isSendingSide = true
         ) const;
 
+        //- Combine two transformIndices
+        static inline label mergeTransformIndex
+        (
+            const label transformIndex0,
+            const label transformIndex1
+        );
+
+        //- Combine two transformIndices
+        static inline label minimumTransformIndex
+        (
+            const label transformIndex0,
+            const label transformIndex1
+        );
+
         //- Encode index and bare index as components on own processor
         inline static labelPair encode
         (
diff --git a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransformI.H b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransformI.H
index 81ff5ed755ff2e18900c4b7c84f8fb9c39b28b4c..19ecfee68c1d3440030ad291e1b2bebab4f69c8f 100644
--- a/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransformI.H
+++ b/src/OpenFOAM/primitives/globalIndexAndTransform/globalIndexAndTransformI.H
@@ -75,6 +75,38 @@ Foam::label Foam::globalIndexAndTransform::encodeTransformIndex
 }
 
 
+Foam::FixedList<Foam::label, 3>
+Foam::globalIndexAndTransform::decodeTransformIndex
+(
+    const label transformIndex
+)
+{
+    FixedList<label, 3> permutation;
+
+    label t = transformIndex;
+    permutation[0] = (t%3)-1;
+    t /= 3;
+    permutation[1] = (t%3)-1;
+    t /= 3;
+    permutation[2] = (t%3)-1;
+
+#   ifdef FULLDEBUG
+    t /= 3;
+    if (t != 0)
+    {
+        FatalErrorIn
+        (
+            "globalIndexAndTransform::decodeTransformIndex(const label)"
+        )   << "transformIndex : " << transformIndex
+            << " has more than 3 fields."
+            << abort(FatalError);
+    }
+#   endif
+
+    return permutation;
+}
+
+
 Foam::label Foam::globalIndexAndTransform::addToTransformIndex
 (
     const label transformIndex,
@@ -90,17 +122,7 @@ Foam::label Foam::globalIndexAndTransform::addToTransformIndex
 
     if (matchTransI > -1 && matchTransI < 3)
     {
-        label t = transformIndex;
-
-        // Decode permutation as 3 integers
-        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-        // Note: FixedList for speed reasons.
-        FixedList<label, 3> permutation;
-        permutation[0] = (t%3)-1;
-        t /= 3;
-        permutation[1] = (t%3)-1;
-        t /= 3;
-        permutation[2] = (t%3)-1;
+        FixedList<label, 3> permutation = decodeTransformIndex(transformIndex);
 
 
         // Add patch transform
@@ -116,27 +138,37 @@ Foam::label Foam::globalIndexAndTransform::addToTransformIndex
         // If this transform been found already by a patch?
         if (permutation[matchTransI] != 0)
         {
-            // If so, if they have opposite signs, then this is
-            // considered an error.  They are allowed to be the
-            // same sign, but this only results in a single
-            // transform.
-            if (permutation[matchTransI] != sign)
+            if (sign == 0)
+            {
+                // sent from patch without a transformation. Do nothing.
+                FatalErrorIn("globalIndexAndTransform::addToTransformIndex(..)")
+                    << "patch:" << mesh_.boundaryMesh()[patchI].name()
+                    << " transform:" << matchTransI << " sign:" << sign
+                    << "  current transforms:" << permutation
+                    << exit(FatalError);
+            }
+            else if (sign == permutation[matchTransI])
             {
                 FatalErrorIn
                 (
                     "Foam::label "
                     "Foam::globalIndexAndTransform::addToTransformIndex\n"
                     "(\n"
-                        "const label transformIndex,\n"
-                        "const label patchI\n"
+                        "const label,\n"
+                        "const label,\n"
+                        "const bool\n"
                     ") const\n"
                 )   << "More than one patch accessing the same transform "
                     << "but not of the same sign." << endl
                     << "patch:" << mesh_.boundaryMesh()[patchI].name()
                     << " transform:" << matchTransI << " sign:" << sign
-                    << "  cumulative transforms:" << permutation
+                    << "  current transforms:" << permutation
                     << exit(FatalError);
             }
+            else
+            {
+                permutation[matchTransI] = 0;
+            }
         }
         else
         {
@@ -159,6 +191,94 @@ Foam::label Foam::globalIndexAndTransform::addToTransformIndex
 }
 
 
+Foam::label Foam::globalIndexAndTransform::mergeTransformIndex
+(
+    const label transformIndex0,
+    const label transformIndex1
+)
+{
+    FixedList<label, 3> permutation0 = decodeTransformIndex(transformIndex0);
+    FixedList<label, 3> permutation1 = decodeTransformIndex(transformIndex1);
+
+    forAll(permutation0, i)
+    {
+        if (permutation0[i] == 0)
+        {
+            // Take over whatever sign 1 has
+            permutation0[i] = permutation1[i];
+        }
+        else if (permutation1[i] != 0 && permutation0[i] != permutation1[i])
+        {
+            FatalErrorIn
+            (
+                "Foam::label "
+                "Foam::globalIndexAndTransform::addToTransformIndex\n"
+                "(\n"
+                    "const label,\n"
+                    "const label\n"
+                ") const\n"
+            )   << "More than one patch accessing the same transform "
+                << "but not of the same sign." << endl
+                << "Trying to combine two transforms " << transformIndex0
+                << " with signs " << permutation0
+                << " and " << transformIndex1
+                << " with signs " << permutation1
+                << exit(FatalError);
+        }
+    }
+    return
+        (permutation0[2]+1)*9
+      + (permutation0[1]+1)*3
+      + (permutation0[0]+1);
+}
+
+
+Foam::label Foam::globalIndexAndTransform::minimumTransformIndex
+(
+    const label transformIndex0,
+    const label transformIndex1
+)
+{
+    FixedList<label, 3> permutation0 = decodeTransformIndex(transformIndex0);
+    FixedList<label, 3> permutation1 = decodeTransformIndex(transformIndex1);
+
+    forAll(permutation0, i)
+    {
+        if (permutation0[i] == 0)
+        {
+            // 0 wins.
+        }
+        else if (permutation1[i] == 0)
+        {
+            // 0 wins.
+            permutation0[i] = permutation1[i];
+        }
+        else if (permutation0[i] != permutation1[i])
+        {
+            FatalErrorIn
+            (
+                "Foam::label "
+                "Foam::globalIndexAndTransform::minimumTransformIndex\n"
+                "(\n"
+                    "const label,\n"
+                    "const label\n"
+                ") const\n"
+            )   << "More than one patch accessing the same transform "
+                << "but not of the same sign." << endl
+                << "Trying to combine two transforms " << transformIndex0
+                << " with signs " << permutation0
+                << " and " << transformIndex1
+                << " with signs " << permutation1
+                << exit(FatalError);
+        }
+    }
+    return
+        (permutation0[2]+1)*9
+      + (permutation0[1]+1)*3
+      + (permutation0[0]+1);
+}
+
+
 Foam::labelPair Foam::globalIndexAndTransform::encode
 (
     const label index,