diff --git a/src/lagrangian/basic/particle/particle.H b/src/lagrangian/basic/particle/particle.H
index f48c0c405a0f46279a1750b09e1d00d557966ad0..ae2edec37b8c522277cd7641e341ef3841c63024 100644
--- a/src/lagrangian/basic/particle/particle.H
+++ b/src/lagrangian/basic/particle/particle.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017, 2020 OpenFOAM Foundation
-    Copyright (C) 2017-2020 OpenCFD Ltd.
+    Copyright (C) 2017-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -295,6 +295,17 @@ protected:
 
     // Patch interactions
 
+        //- Read particle from stream. Optionally (for old format) return
+        //  read position. Used by construct-from-Istream
+        void readData
+        (
+            Istream& is,
+            point& position,
+            const bool readFields,
+            const bool newFormat,
+            const bool doLocate
+        );
+
         //- Overridable function to handle the particle hitting a patch.
         //  Executed before other patch-hitting functions.
         template<class TrackCloudType>
@@ -399,8 +410,9 @@ public:
         (
             const polyMesh& mesh,
             Istream&,
-            bool readFields = true,
-            bool newFormat = true
+            const bool readFields = true,
+            const bool newFormat = true,
+            const bool doLocate = true
         );
 
         //- Construct as a copy
diff --git a/src/lagrangian/basic/particle/particleIO.C b/src/lagrangian/basic/particle/particleIO.C
index bf8e9ac30aff634fccac2b67d94b1dd6c05afafc..afaaa8c78f6b7d8c5254613ceba34c02926d2cde 100644
--- a/src/lagrangian/basic/particle/particleIO.C
+++ b/src/lagrangian/basic/particle/particleIO.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2019 OpenCFD Ltd.
+    Copyright (C) 2016-2019,2022 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -50,8 +50,9 @@ Foam::particle::particle
 (
     const polyMesh& mesh,
     Istream& is,
-    bool readFields,
-    bool newFormat
+    const bool readFields,
+    const bool newFormat,
+    const bool doLocate
 )
 :
     mesh_(mesh),
@@ -63,6 +64,22 @@ Foam::particle::particle
     stepFraction_(0.0),
     origProc_(Pstream::myProcNo()),
     origId_(-1)
+{
+    point position;
+    readData(is, position, readFields, newFormat, doLocate);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::particle::readData
+(
+    Istream& is,
+    point& position,
+    const bool readFields,
+    const bool newFormat,
+    const bool doLocate
+)
 {
     if (newFormat)
     {
@@ -178,14 +195,20 @@ Foam::particle::particle
             origId_ = p.origId;
         }
 
-        locate
-        (
-            p.position,
-            nullptr,
-            p.celli,
-            false,
-            "Particle initialised with a location outside of the mesh."
-        );
+        // Preserve read position
+        position = p.position;
+
+        if (doLocate)
+        {
+            locate
+            (
+                p.position,
+                nullptr,
+                p.celli,
+                false,
+                "Particle initialised with a location outside of the mesh."
+            );
+        }
     }
 
     // Check state of Istream
diff --git a/src/parallel/reconstruct/reconstruct/Make/files b/src/parallel/reconstruct/reconstruct/Make/files
index 784519c5c6a01bb8e8aad978ede0ee3d75f75e7a..2dbe299bfde830a7d02ff979232eebb23ee912d5 100644
--- a/src/parallel/reconstruct/reconstruct/Make/files
+++ b/src/parallel/reconstruct/reconstruct/Make/files
@@ -1,6 +1,7 @@
 processorMeshes.C
 fvFieldReconstructor.C
 pointFieldReconstructor.C
+passivePositionParticleCloud.C
 lagrangianReconstructor.C
 
 LIB = $(FOAM_LIBBIN)/libreconstruct
diff --git a/src/parallel/reconstruct/reconstruct/lagrangianReconstructor.C b/src/parallel/reconstruct/reconstruct/lagrangianReconstructor.C
index f7a578f4cb327ed93453ef35ce94f464b80b0944..285d9364cfcd1e00daea4fdcab9a1834dad91c08 100644
--- a/src/parallel/reconstruct/reconstruct/lagrangianReconstructor.C
+++ b/src/parallel/reconstruct/reconstruct/lagrangianReconstructor.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2018 OpenCFD Ltd.
+    Copyright (C) 2018,2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,8 +27,7 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "lagrangianReconstructor.H"
-#include "labelIOList.H"
-#include "passiveParticleCloud.H"
+#include "passivePositionParticleCloud.H"
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
@@ -54,11 +53,11 @@ Foam::label Foam::lagrangianReconstructor::reconstructPositions
     const word& cloudName
 ) const
 {
-    passiveParticleCloud lagrangianPositions
+    passivePositionParticleCloud lagrangianPositions
     (
         mesh_,
         cloudName,
-        IDLList<passiveParticle>()
+        IDLList<passivePositionParticle>()
     );
 
     forAll(procMeshes_, meshi)
@@ -66,38 +65,73 @@ Foam::label Foam::lagrangianReconstructor::reconstructPositions
         const labelList& cellMap = cellProcAddressing_[meshi];
         const labelList& faceMap = faceProcAddressing_[meshi];
 
-        Cloud<passiveParticle> lpi(procMeshes_[meshi], cloudName, false);
+        // Use a special particle that does not try to find the particle on
+        // the mesh. This is to be able to handle particles originating
+        // from a different processor. This can happen with some
+        // functionObjects - e.g. extractEulerianParticles.
+        // These particles should be
+        // - written in the old format
+        passivePositionParticleCloud lpi(procMeshes_[meshi], cloudName, false);
 
         forAllConstIters(lpi, iter)
         {
-            const passiveParticle& ppi = *iter;
+            const passivePositionParticle& ppi = *iter;
 
-            const label mappedCell = cellMap[ppi.cell()];
+            const label mappedCell =
+            (
+                (ppi.cell() >= 0)
+              ? cellMap[ppi.cell()]
+              : -1
+            );
 
             // Inverting sign if necessary and subtracting 1 from
             // faceProcAddressing
-            const label mappedTetFace = mag(faceMap[ppi.tetFace()]) - 1;
-
-            lagrangianPositions.append
+            const label mappedTetFace =
             (
-                new passiveParticle
-                (
-                    mesh_,
-                    ppi.coordinates(),
-                    mappedCell,
-                    mappedTetFace,
-                    ppi.procTetPt(mesh_, mappedCell, mappedTetFace)
-                )
+                (ppi.tetFace() >= 0)
+              ? mag(faceMap[ppi.tetFace()]) - 1
+              : -1
             );
+
+            if ((ppi.cell() >= 0) && (ppi.tetFace() >= 0))
+            {
+                // cell,face succesfully mapped. Coordinates inside the cell
+                // should be same
+                lagrangianPositions.append
+                (
+                    new passivePositionParticle
+                    (
+                        mesh_,
+                        ppi.coordinates(),
+                        mappedCell,
+                        mappedTetFace,
+                        ppi.procTetPt(mesh_, mappedCell, mappedTetFace)
+                    )
+                );
+            }
+            else
+            {
+                // No valid coordinates. Use built-in locating from cell -1
+                lagrangianPositions.append
+                (
+                    new passivePositionParticle
+                    (
+                        mesh_,
+                        ppi.location(),
+                        mappedCell
+                    )
+                );
+            }
         }
     }
 
-    IOPosition<Cloud<passiveParticle>>(lagrangianPositions).write();
+
+    IOPosition<passivePositionParticleCloud>(lagrangianPositions).write();
 
     // Force writing of "positions" too, if specified via the InfoSwitch
     if (particle::writeLagrangianPositions)
     {
-        IOPosition<Cloud<passiveParticle>>
+        IOPosition<passivePositionParticleCloud>
         (
             lagrangianPositions,
             cloud::geometryType::POSITIONS
diff --git a/src/parallel/reconstruct/reconstruct/passivePositionParticle.H b/src/parallel/reconstruct/reconstruct/passivePositionParticle.H
new file mode 100644
index 0000000000000000000000000000000000000000..8612c632a223ee03c214d86db48d88c392935a28
--- /dev/null
+++ b/src/parallel/reconstruct/reconstruct/passivePositionParticle.H
@@ -0,0 +1,182 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::passivePositionParticle
+
+Description
+    Copy of base particle but without particle locating and preserving
+    read location.
+
+    Used in reconstructing lagrangian positions generated outside the
+    mesh domain (can happen in extractEulerianParticles functionObject)
+
+SourceFiles
+    passivePositionParticle.H
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef passivePositionParticle_H
+#define passivePositionParticle_H
+
+#include "particle.H"
+#include "IOstream.H"
+#include "autoPtr.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                  Class passivePositionParticle Declaration
+\*---------------------------------------------------------------------------*/
+
+class passivePositionParticle
+:
+    public particle
+{
+    // Private Data
+
+        //- Raw location
+        point location_;
+
+
+public:
+
+    // Constructors
+
+        //- Construct from components
+        passivePositionParticle
+        (
+            const polyMesh& mesh,
+            const barycentric& coordinates,
+            const label celli,
+            const label tetFacei,
+            const label tetPti
+        )
+        :
+            particle(mesh, coordinates, celli, tetFacei, tetPti),
+            location_(position())
+        {}
+
+
+        //- Construct from a position and a cell.
+        //  Searches for the rest of the required topology.
+        passivePositionParticle
+        (
+            const polyMesh& mesh,
+            const vector& position,
+            const label celli = -1
+        )
+        :
+            particle(mesh, position, celli),
+            location_(position)
+        {}
+
+
+        //- Construct from Istream
+        passivePositionParticle
+        (
+            const polyMesh& mesh,
+            Istream& is,
+            const bool readFields = true,
+            const bool newFormat = true
+        )
+        :
+            //particle(mesh, is, readFields, newFormat)
+            particle
+            (
+                mesh,
+                Zero,   // position
+                -1,     // celli
+                -1,     // tetFacei
+                -1,     // tetPti
+                false   // doLocate
+            )
+        {
+            readData
+            (
+                is,
+                location_,
+                readFields,
+                newFormat,
+                false       //doLocate
+            );
+        }
+
+
+        //- Construct as copy
+        passivePositionParticle(const passivePositionParticle& p)
+        :
+            particle(p)
+        {}
+
+
+        //- Construct and return a clone
+        virtual autoPtr<particle> clone() const
+        {
+            return autoPtr<particle>(new passivePositionParticle(*this));
+        }
+
+
+        //- Factory class to read-construct particles (for parallel transfer)
+        class iNew
+        {
+            const polyMesh& mesh_;
+
+        public:
+
+            iNew(const polyMesh& mesh)
+            :
+                mesh_(mesh)
+            {}
+
+            autoPtr<passivePositionParticle> operator()(Istream& is) const
+            {
+                return autoPtr<passivePositionParticle>::New(mesh_, is, true);
+            }
+        };
+
+
+    // Member Functions
+
+            //- Return current particle position
+            inline const point& location() const
+            {
+                return location_;
+            }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.C b/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.C
new file mode 100644
index 0000000000000000000000000000000000000000..4f714ad2878e5ad17971f22841cfb13592865e65
--- /dev/null
+++ b/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.C
@@ -0,0 +1,66 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "passivePositionParticleCloud.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTemplateTypeNameAndDebug(Cloud<passivePositionParticle>, 0);
+}
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::passivePositionParticleCloud::passivePositionParticleCloud
+(
+    const polyMesh& mesh,
+    const word& cloudName,
+    bool readFields
+)
+:
+    Cloud<passivePositionParticle>(mesh, cloudName, false)
+{
+    if (readFields)
+    {
+        passivePositionParticle::readFields(*this);
+    }
+}
+
+
+Foam::passivePositionParticleCloud::passivePositionParticleCloud
+(
+    const polyMesh& mesh,
+    const word& cloudName,
+    const IDLList<passivePositionParticle>& particles
+)
+:
+    Cloud<passivePositionParticle>(mesh, cloudName, particles)
+{}
+
+
+// ************************************************************************* //
diff --git a/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.H b/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.H
new file mode 100644
index 0000000000000000000000000000000000000000..dab774fcfc004dc65b918958eed5e2cf2a757cf6
--- /dev/null
+++ b/src/parallel/reconstruct/reconstruct/passivePositionParticleCloud.H
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | www.openfoam.com
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+    Copyright (C) 2021 OpenCFD Ltd.
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::passivePositionParticleCloud
+
+Description
+    A Cloud of passive particles
+
+SourceFiles
+    passivePositionParticleCloud.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef passivePositionParticleCloud_H
+#define passivePositionParticleCloud_H
+
+#include "Cloud.H"
+#include "passivePositionParticle.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                Class passivePositionParticleCloud Declaration
+\*---------------------------------------------------------------------------*/
+
+class passivePositionParticleCloud
+:
+    public Cloud<passivePositionParticle>
+{
+    // Private Member Functions
+
+        //- No copy construct
+        passivePositionParticleCloud(const passivePositionParticleCloud&) =
+            delete;
+
+        //- No copy assignment
+        void operator=(const passivePositionParticleCloud&) = delete;
+
+
+public:
+
+    // Constructors
+
+        //- Construct given mesh
+        explicit passivePositionParticleCloud
+        (
+            const polyMesh& mesh,
+            const word& cloudName = cloud::defaultName,
+            bool readFields = true
+        );
+
+        //- Construct from mesh, cloud name, and a list of particles
+        passivePositionParticleCloud
+        (
+            const polyMesh& mesh,
+            const word& cloudName,
+            const IDLList<passivePositionParticle>& particles
+        );
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //