From 8e79bf1b8273a2875477cd1afce7516af3c2d5c7 Mon Sep 17 00:00:00 2001
From: andy <andy>
Date: Wed, 14 Aug 2013 15:54:40 +0100
Subject: [PATCH] ENH: Added initial support for particle tracking across AMI
 patches

---
 src/lagrangian/basic/Cloud/Cloud.C            |  18 ++-
 src/lagrangian/basic/particle/particle.H      |   9 ++
 .../basic/particle/particleTemplates.C        |  84 +++++++++++++-
 .../AMIInterpolation/AMIInterpolation.C       | 108 ++++++++++++++++++
 .../AMIInterpolation/AMIInterpolation.H       |  25 ++++
 .../cyclicAMIPolyPatch/cyclicAMIPolyPatch.C   |  32 ++++++
 .../cyclicAMIPolyPatch/cyclicAMIPolyPatch.H   |   9 ++
 7 files changed, 278 insertions(+), 7 deletions(-)

diff --git a/src/lagrangian/basic/Cloud/Cloud.C b/src/lagrangian/basic/Cloud/Cloud.C
index d85ef08dcaf..c0e43c16868 100644
--- a/src/lagrangian/basic/Cloud/Cloud.C
+++ b/src/lagrangian/basic/Cloud/Cloud.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2012 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -44,16 +44,22 @@ void Foam::Cloud<ParticleType>::checkPatches() const
     {
         if (isA<cyclicAMIPolyPatch>(pbm[patchI]))
         {
-            ok = false;
-            break;
+            const cyclicAMIPolyPatch& cami =
+                refCast<const cyclicAMIPolyPatch>(pbm[patchI]);
+
+            if (cami.owner())
+            {
+                ok = ok && (cami.AMI().singlePatchProc() != -1);
+            }
         }
     }
 
     if (!ok)
     {
-        WarningIn("void Foam::Cloud<ParticleType>::initCloud(const bool)")
-            << "Particle tracking across AMI patches is not currently "
-            << "supported" << endl;
+        FatalErrorIn("void Foam::Cloud<ParticleType>::initCloud(const bool)")
+            << "Particle tracking across AMI patches is only currently "
+            << "supported for cases where the AMI patches reside on a "
+            << "single processor" << abort(FatalError);
     }
 }
 
diff --git a/src/lagrangian/basic/particle/particle.H b/src/lagrangian/basic/particle/particle.H
index cf293c5691c..15742cacc94 100644
--- a/src/lagrangian/basic/particle/particle.H
+++ b/src/lagrangian/basic/particle/particle.H
@@ -257,6 +257,15 @@ protected:
         template<class TrackData>
         void hitCyclicPatch(const cyclicPolyPatch&, TrackData& td);
 
+        //- Overridable function to handle the particle hitting a cyclicAMIPatch
+        template<class TrackData>
+        void hitCyclicAMIPatch
+        (
+            const cyclicAMIPolyPatch&,
+            TrackData& td,
+            const vector& direction
+        );
+
         //- Overridable function to handle the particle hitting a
         //  processorPatch
         template<class TrackData>
diff --git a/src/lagrangian/basic/particle/particleTemplates.C b/src/lagrangian/basic/particle/particleTemplates.C
index caa82196ab6..cdc12634bd3 100644
--- a/src/lagrangian/basic/particle/particleTemplates.C
+++ b/src/lagrangian/basic/particle/particleTemplates.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
+    \\  /    A nd           | Copyright (C) 2011-2013 OpenFOAM Foundation
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -26,6 +26,7 @@ License
 #include "IOPosition.H"
 
 #include "cyclicPolyPatch.H"
+#include "cyclicAMIPolyPatch.H"
 #include "processorPolyPatch.H"
 #include "symmetryPolyPatch.H"
 #include "wallPolyPatch.H"
@@ -598,6 +599,15 @@ Foam::scalar Foam::particle::trackToFace
                     static_cast<const cyclicPolyPatch&>(patch), td
                 );
             }
+            else if (isA<cyclicAMIPolyPatch>(patch))
+            {
+                p.hitCyclicAMIPatch
+                (
+                    static_cast<const cyclicAMIPolyPatch&>(patch),
+                    td,
+                    endPosition - position_
+                );
+            }
             else if (isA<processorPolyPatch>(patch))
             {
                 p.hitProcessorPatch
@@ -1010,6 +1020,78 @@ void Foam::particle::hitCyclicPatch
 }
 
 
+template<class TrackData>
+void Foam::particle::hitCyclicAMIPatch
+(
+    const cyclicAMIPolyPatch& cpp,
+    TrackData& td,
+    const vector& direction
+)
+{
+    const cyclicAMIPolyPatch& receiveCpp = cpp.neighbPatch();
+
+    // patch face index on sending side
+    label patchFaceI = faceI_ - cpp.start();
+
+    // patch face index on receiving side - also updates position
+    patchFaceI = cpp.pointFace(patchFaceI, direction, position_);
+
+    if (patchFaceI < 0)
+    {
+        FatalErrorIn
+        (
+            "template<class TrackData>"
+            "void Foam::particle::hitCyclicAMIPatch"
+            "("
+                "const cyclicAMIPolyPatch&, "
+                "TrackData&, "
+                "const vector&"
+            ")"
+        )
+            << "Particle lost across " << cyclicAMIPolyPatch::typeName
+            << " patches " << cpp.name() << " and " << receiveCpp.name()
+            << " at position " << position_ << abort(FatalError);
+    }
+
+    // convert face index into global numbering
+    faceI_ = patchFaceI + receiveCpp.start();
+
+    cellI_ = mesh_.faceOwner()[faceI_];
+
+    tetFaceI_ = faceI_;
+
+    // See note in correctAfterParallelTransfer for tetPtI_ addressing.
+    tetPtI_ = mesh_.faces()[tetFaceI_].size() - 1 - tetPtI_;
+
+    // Now the particle is on the receiving side
+
+    // Have patch transform the position
+    receiveCpp.transformPosition(position_, patchFaceI);
+
+    // Transform the properties
+    if (!receiveCpp.parallel())
+    {
+        const tensor& T =
+        (
+            receiveCpp.forwardT().size() == 1
+          ? receiveCpp.forwardT()[0]
+          : receiveCpp.forwardT()[patchFaceI]
+        );
+        transformProperties(T);
+    }
+    else if (receiveCpp.separated())
+    {
+        const vector& s =
+        (
+            (receiveCpp.separation().size() == 1)
+          ? receiveCpp.separation()[0]
+          : receiveCpp.separation()[patchFaceI]
+        );
+        transformProperties(-s);
+    }
+}
+
+
 template<class TrackData>
 void Foam::particle::hitProcessorPatch(const processorPolyPatch&, TrackData&)
 {}
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
index 10ec0bf5d01..897e7ec42d1 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.C
@@ -1248,6 +1248,114 @@ Foam::AMIInterpolation<SourcePatch, TargetPatch>::interpolateToTarget
 }
 
 
+template<class SourcePatch, class TargetPatch>
+Foam::label Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcPointFace
+(
+    const SourcePatch& srcPatch,
+    const TargetPatch& tgtPatch,
+    const vector& n,
+    const label tgtFaceI,
+    point& tgtPoint
+)
+const
+{
+    const pointField& srcPoints = srcPatch.points();
+
+    // source face addresses that intersect target face tgtFaceI
+    const labelList& addr = tgtAddress_[tgtFaceI];
+
+    forAll(addr, i)
+    {
+        label srcFaceI = addr[i];
+        const face& f = srcPatch[tgtFaceI];
+
+        pointHit ray = f.ray(tgtPoint, n, srcPoints);
+
+        if (ray.hit())
+        {
+            tgtPoint = ray.rawPoint();
+
+            return srcFaceI;
+        }
+    }
+
+    // no hit registered - try with face normal instead of input normal
+    forAll(addr, i)
+    {
+        label srcFaceI = addr[i];
+        const face& f = srcPatch[tgtFaceI];
+
+        vector nFace(-srcPatch.faceNormals()[srcFaceI]);
+        nFace += tgtPatch.faceNormals()[tgtFaceI];
+
+        pointHit ray = f.ray(tgtPoint, nFace, srcPoints);
+
+        if (ray.hit())
+        {
+            tgtPoint = ray.rawPoint();
+
+            return srcFaceI;
+        }
+    }
+
+    return -1;
+}
+
+
+template<class SourcePatch, class TargetPatch>
+Foam::label Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtPointFace
+(
+    const SourcePatch& srcPatch,
+    const TargetPatch& tgtPatch,
+    const vector& n,
+    const label srcFaceI,
+    point& srcPoint
+)
+const
+{
+    const pointField& tgtPoints = tgtPatch.points();
+
+    // target face addresses that intersect source face srcFaceI
+    const labelList& addr = srcAddress_[srcFaceI];
+
+    forAll(addr, i)
+    {
+        label tgtFaceI = addr[i];
+        const face& f = tgtPatch[tgtFaceI];
+
+        pointHit ray = f.ray(srcPoint, n, tgtPoints);
+
+        if (ray.hit())
+        {
+            srcPoint = ray.rawPoint();
+
+            return tgtFaceI;
+        }
+    }
+
+    // no hit registered - try with face normal instead of input normal
+    forAll(addr, i)
+    {
+        label tgtFaceI = addr[i];
+        const face& f = tgtPatch[tgtFaceI];
+
+        vector nFace(-srcPatch.faceNormals()[srcFaceI]);
+        nFace += tgtPatch.faceNormals()[tgtFaceI];
+
+        pointHit ray = f.ray(srcPoint, n, tgtPoints);
+
+        if (ray.hit())
+        {
+            srcPoint = ray.rawPoint();
+
+            return tgtFaceI;
+        }
+    }
+
+    return -1;
+}
+
+
 template<class SourcePatch, class TargetPatch>
 void Foam::AMIInterpolation<SourcePatch, TargetPatch>::writeFaceConnectivity
 (
diff --git a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
index 3aea35473fa..cc30379df1c 100644
--- a/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
+++ b/src/meshTools/AMIInterpolation/AMIInterpolation/AMIInterpolation.H
@@ -454,6 +454,31 @@ public:
             ) const;
 
 
+        // Point intersections
+
+            //- Return source patch face index of point on target patch face
+            label srcPointFace
+            (
+                const SourcePatch& srcPatch,
+                const TargetPatch& tgtPatch,
+                const vector& n,
+                const label tgtFaceI,
+                point& tgtPoint
+            )
+            const;
+
+            //- Return target patch face index of point on source patch face
+            label tgtPointFace
+            (
+                const SourcePatch& srcPatch,
+                const TargetPatch& tgtPatch,
+                const vector& n,
+                const label srcFaceI,
+                point& srcPoint
+            )
+            const;
+
+
         // Checks
 
             //- Write face connectivity as OBJ file
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
index f43f91ff465..14e1c7ddf47 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
+++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.C
@@ -797,6 +797,38 @@ bool Foam::cyclicAMIPolyPatch::order
 }
 
 
+Foam::label Foam::cyclicAMIPolyPatch::pointFace
+(
+    const label faceI,
+    const vector& n,
+    point& p
+) const
+{
+    if (owner())
+    {
+        return AMI().tgtPointFace
+        (
+            *this,
+            neighbPatch(),
+            n,
+            faceI,
+            p
+        );
+    }
+    else
+    {
+        return neighbPatch().AMI().srcPointFace
+        (
+            neighbPatch(),
+            *this,
+            n,
+            faceI,
+            p
+        );
+    }
+}
+
+
 void Foam::cyclicAMIPolyPatch::write(Ostream& os) const
 {
     coupledPolyPatch::write(os);
diff --git a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
index 51a9c1dc0d2..28b0e5e17cb 100644
--- a/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
+++ b/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatch.H
@@ -367,6 +367,15 @@ public:
             labelList& rotation
         ) const;
 
+        //- Return face index on neighbour patch which shares point p
+        //  following trajectory vector n
+        label pointFace
+        (
+            const label faceI,
+            const vector& n,
+            point& p
+        ) const;
+
         //- Write the polyPatch data as a dictionary
         virtual void write(Ostream&) const;
 };
-- 
GitLab