diff --git a/src/parallel/decompose/decompose/fvFieldDecomposer.C b/src/parallel/decompose/decompose/fvFieldDecomposer.C
index 077c177fc13966b6c15969409419fbf2ae2f851b..61ade1be3bc6a567abdbe8e110407d727dfc432e 100644
--- a/src/parallel/decompose/decompose/fvFieldDecomposer.C
+++ b/src/parallel/decompose/decompose/fvFieldDecomposer.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
+    Copyright (C) 2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -48,21 +49,19 @@ Foam::fvFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
 Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
 processorVolPatchFieldDecomposer
 (
-    const fvMesh& mesh,
+    const labelUList& owner,  // == mesh.faceOwner()
+    const labelUList& neigh,  // == mesh.faceNeighbour()
     const labelUList& addressingSlice
 )
 :
     directAddressing_(addressingSlice.size())
 {
-    const labelList& own = mesh.faceOwner();
-    const labelList& neighb = mesh.faceNeighbour();
-
     forAll(directAddressing_, i)
     {
         // Subtract one to align addressing.
         label ai = mag(addressingSlice[i]) - 1;
 
-        if (ai < neighb.size())
+        if (ai < neigh.size())
         {
             // This is a regular face. it has been an internal face
             // of the original mesh and now it has become a face
@@ -72,11 +71,11 @@ processorVolPatchFieldDecomposer
             if (addressingSlice[i] >= 0)
             {
                 // I have the owner so use the neighbour value
-                directAddressing_[i] = neighb[ai];
+                directAddressing_[i] = neigh[ai];
             }
             else
             {
-                directAddressing_[i] = own[ai];
+                directAddressing_[i] = owner[ai];
             }
         }
         else
@@ -87,12 +86,28 @@ processorVolPatchFieldDecomposer
             // up the different (face) list of data), so I will
             // just grab the value from the owner cell
 
-            directAddressing_[i] = own[ai];
+            directAddressing_[i] = owner[ai];
         }
     }
 }
 
 
+Foam::fvFieldDecomposer::processorVolPatchFieldDecomposer::
+processorVolPatchFieldDecomposer
+(
+    const fvMesh& mesh,
+    const labelUList& addressingSlice
+)
+:
+    processorVolPatchFieldDecomposer
+    (
+        mesh.faceOwner(),
+        mesh.faceNeighbour(),
+        addressingSlice
+    )
+{}
+
+
 Foam::fvFieldDecomposer::processorSurfacePatchFieldDecomposer::
 processorSurfacePatchFieldDecomposer
 (
@@ -104,8 +119,8 @@ processorSurfacePatchFieldDecomposer
 {
     forAll(addressing_, i)
     {
-        addressing_[i].setSize(1);
-        weights_[i].setSize(1);
+        addressing_[i].resize(1);
+        weights_[i].resize(1);
 
         addressing_[i][0] = mag(addressingSlice[i]) - 1;
         weights_[i][0] = 1;
@@ -115,32 +130,184 @@ processorSurfacePatchFieldDecomposer
 
 Foam::fvFieldDecomposer::fvFieldDecomposer
 (
-    const fvMesh& completeMesh,
+    const Foam::zero,
     const fvMesh& procMesh,
     const labelList& faceAddressing,
     const labelList& cellAddressing,
     const labelList& boundaryAddressing
 )
 :
-    completeMesh_(completeMesh),
     procMesh_(procMesh),
     faceAddressing_(faceAddressing),
     cellAddressing_(cellAddressing),
     boundaryAddressing_(boundaryAddressing),
-    patchFieldDecomposerPtrs_(procMesh_.boundary().size()),
-    processorVolPatchFieldDecomposerPtrs_(procMesh_.boundary().size()),
-    processorSurfacePatchFieldDecomposerPtrs_(procMesh_.boundary().size()),
-    faceSign_(procMesh_.boundary().size())
+    // Mappers
+    patchFieldDecomposerPtrs_(),
+    processorVolPatchFieldDecomposerPtrs_(),
+    processorSurfacePatchFieldDecomposerPtrs_(),
+    faceSign_()
+{}
+
+
+Foam::fvFieldDecomposer::fvFieldDecomposer
+(
+    const fvMesh& completeMesh,
+    const fvMesh& procMesh,
+    const labelList& faceAddressing,
+    const labelList& cellAddressing,
+    const labelList& boundaryAddressing
+)
+:
+    fvFieldDecomposer
+    (
+        zero{},
+        procMesh,
+        faceAddressing,
+        cellAddressing,
+        boundaryAddressing
+    )
+{
+    reset(completeMesh);
+}
+
+
+Foam::fvFieldDecomposer::fvFieldDecomposer
+(
+    const List<labelRange>& boundaryRanges,
+    const labelUList& faceOwner,
+    const labelUList& faceNeighbour,
+
+    const fvMesh& procMesh,
+    const labelList& faceAddressing,
+    const labelList& cellAddressing,
+    const labelList& boundaryAddressing
+)
+:
+    fvFieldDecomposer
+    (
+        zero{},
+        procMesh,
+        faceAddressing,
+        cellAddressing,
+        boundaryAddressing
+    )
+{
+    reset(boundaryRanges, faceOwner, faceNeighbour);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::fvFieldDecomposer::empty() const
+{
+    return patchFieldDecomposerPtrs_.empty();
+}
+
+
+void Foam::fvFieldDecomposer::clear()
+{
+    patchFieldDecomposerPtrs_.clear();
+    processorVolPatchFieldDecomposerPtrs_.clear();
+    processorSurfacePatchFieldDecomposerPtrs_.clear();
+    faceSign_.clear();
+}
+
+
+void Foam::fvFieldDecomposer::reset
+(
+    const List<labelRange>& boundaryRanges,
+    const labelUList& faceOwner,
+    const labelUList& faceNeighbour
+)
+{
+    clear();
+    const label nMappers = procMesh_.boundary().size();
+    patchFieldDecomposerPtrs_.resize(nMappers);
+    processorVolPatchFieldDecomposerPtrs_.resize(nMappers);
+    processorSurfacePatchFieldDecomposerPtrs_.resize(nMappers);
+    faceSign_.resize(nMappers);
+
+    forAll(boundaryAddressing_, patchi)
+    {
+        const label oldPatchi = boundaryAddressing_[patchi];
+        const fvPatch& fvp = procMesh_.boundary()[patchi];
+        const labelSubList localPatchSlice(fvp.patchSlice(faceAddressing_));
+
+        if
+        (
+            oldPatchi >= 0
+        && !isA<processorLduInterface>(procMesh_.boundary()[patchi])
+        )
+        {
+            patchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new patchFieldDecomposer
+                (
+                    localPatchSlice,
+                    boundaryRanges[oldPatchi].start()
+                )
+            );
+        }
+        else
+        {
+            processorVolPatchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new processorVolPatchFieldDecomposer
+                (
+                    faceOwner,
+                    faceNeighbour,
+                    localPatchSlice
+                )
+            );
+
+            processorSurfacePatchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new processorSurfacePatchFieldDecomposer
+                (
+                    static_cast<const labelUList&>(localPatchSlice)
+                )
+            );
+
+            faceSign_.set
+            (
+                patchi,
+                new scalarField(localPatchSlice.size())
+            );
+
+            {
+                scalarField& s = faceSign_[patchi];
+                forAll(s, i)
+                {
+                    s[i] = sign(localPatchSlice[i]);
+                }
+            }
+        }
+    }
+}
+
+
+void Foam::fvFieldDecomposer::reset(const fvMesh& completeMesh)
 {
+    clear();
+    const label nMappers = procMesh_.boundary().size();
+    patchFieldDecomposerPtrs_.resize(nMappers);
+    processorVolPatchFieldDecomposerPtrs_.resize(nMappers);
+    processorSurfacePatchFieldDecomposerPtrs_.resize(nMappers);
+    faceSign_.resize(nMappers);
+
     forAll(boundaryAddressing_, patchi)
     {
         const label oldPatchi = boundaryAddressing_[patchi];
         const fvPatch& fvp = procMesh_.boundary()[patchi];
+        const labelSubList localPatchSlice(fvp.patchSlice(faceAddressing_));
 
         if
         (
             oldPatchi >= 0
-        && !isA<processorLduInterface>(procMesh.boundary()[patchi])
+        && !isA<processorLduInterface>(procMesh_.boundary()[patchi])
         )
         {
             patchFieldDecomposerPtrs_.set
@@ -148,8 +315,8 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
                 patchi,
                 new patchFieldDecomposer
                 (
-                    fvp.patchSlice(faceAddressing_),
-                    completeMesh_.boundaryMesh()[oldPatchi].start()
+                    localPatchSlice,
+                    completeMesh.boundaryMesh()[oldPatchi].start()
                 )
             );
         }
@@ -160,8 +327,8 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
                 patchi,
                 new processorVolPatchFieldDecomposer
                 (
-                    completeMesh_,
-                    fvp.patchSlice(faceAddressing_)
+                    completeMesh,
+                    localPatchSlice
                 )
             );
 
@@ -170,28 +337,21 @@ Foam::fvFieldDecomposer::fvFieldDecomposer
                 patchi,
                 new processorSurfacePatchFieldDecomposer
                 (
-                    static_cast<const labelUList&>
-                    (
-                        fvp.patchSlice
-                        (
-                            faceAddressing_
-                        )
-                    )
+                    static_cast<const labelUList&>(localPatchSlice)
                 )
             );
 
             faceSign_.set
             (
                 patchi,
-                new scalarField(fvp.patchSlice(faceAddressing_).size())
+                new scalarField(localPatchSlice.size())
             );
 
             {
-                const SubList<label> fa = fvp.patchSlice(faceAddressing_);
                 scalarField& s = faceSign_[patchi];
                 forAll(s, i)
                 {
-                    s[i] = sign(fa[i]);
+                    s[i] = sign(localPatchSlice[i]);
                 }
             }
         }
diff --git a/src/parallel/decompose/decompose/fvFieldDecomposer.H b/src/parallel/decompose/decompose/fvFieldDecomposer.H
index d9358224e6330ebc4c9b594ee99ec1d3896e2923..bfb91e75adc316e505451bcc140df7ea7cf735ac 100644
--- a/src/parallel/decompose/decompose/fvFieldDecomposer.H
+++ b/src/parallel/decompose/decompose/fvFieldDecomposer.H
@@ -115,7 +115,15 @@ public:
 
         public:
 
-            //- Construct given addressing
+            //- Construct addressing from details
+            processorVolPatchFieldDecomposer
+            (
+                const labelUList& faceOwner,
+                const labelUList& faceNeigbour,
+                const labelUList& addressingSlice
+            );
+
+            //- Construct given addressing from complete mesh
             processorVolPatchFieldDecomposer
             (
                 const fvMesh& mesh,
@@ -201,7 +209,7 @@ private:
     // Private Data
 
         //- Reference to complete mesh
-        const fvMesh& completeMesh_;
+        //REMOVED const fvMesh& completeMesh_;
 
         //- Reference to processor mesh
         const fvMesh& procMesh_;
@@ -238,7 +246,17 @@ public:
 
     // Constructors
 
-        //- Construct from components
+        //- Construct without mappers, added later with reset()
+        fvFieldDecomposer
+        (
+            const Foam::zero,
+            const fvMesh& procMesh,
+            const labelList& faceAddressing,
+            const labelList& cellAddressing,
+            const labelList& boundaryAddressing
+        );
+
+        //- Construct from components using information from the complete mesh
         fvFieldDecomposer
         (
             const fvMesh& completeMesh,
@@ -248,6 +266,21 @@ public:
             const labelList& boundaryAddressing
         );
 
+        //- Construct from components without the complete mesh
+        fvFieldDecomposer
+        (
+            // Information about the complete mesh
+            const List<labelRange>& boundaryRanges,
+            const labelUList& faceOwner,
+            const labelUList& faceNeigbour,
+
+            // Addressing for processor mesh
+            const fvMesh& procMesh,
+            const labelList& faceAddressing,
+            const labelList& cellAddressing,
+            const labelList& boundaryAddressing
+        );
+
 
     //- Destructor
     ~fvFieldDecomposer() = default;
@@ -255,6 +288,26 @@ public:
 
     // Member Functions
 
+        //- True if no mappers have been allocated
+        bool empty() const;
+
+        //- Remove all mappers
+        void clear();
+
+        //- Reset mappers using information from the complete mesh
+        void reset(const fvMesh& completeMesh);
+
+        //- Reset mapper using information about the complete mesh
+        void reset
+        (
+            const List<labelRange>& boundaryRanges,
+            const labelUList& faceOwner,
+            const labelUList& faceNeigbour
+        );
+
+
+    // Mapping
+
         //- Decompose internal field
         template<class Type>
         tmp<DimensionedField<Type, volMesh>>
diff --git a/src/parallel/decompose/faDecompose/faFieldDecomposer.C b/src/parallel/decompose/faDecompose/faFieldDecomposer.C
index 122eaa5fb381fc4290d39a0da909b3c7c84504be..f0966dfe47a7565a28b1a56cb6cec35798ead540 100644
--- a/src/parallel/decompose/faDecompose/faFieldDecomposer.C
+++ b/src/parallel/decompose/faDecompose/faFieldDecomposer.C
@@ -53,37 +53,46 @@ Foam::faFieldDecomposer::patchFieldDecomposer::patchFieldDecomposer
 Foam::faFieldDecomposer::processorAreaPatchFieldDecomposer::
 processorAreaPatchFieldDecomposer
 (
-    const faMesh& mesh,
-    const labelUList& addressingSlice
+    const label nTotalFaces,
+    const labelUList& owner,  // == mesh.edgeOwner()
+    const labelUList& neigh,  // == mesh.edgeNeighbour()
+    const labelUList& addressingSlice,
+    const scalarField& weights
 )
 :
-    sizeBeforeMapping_(mesh.nFaces()),
+    sizeBeforeMapping_(nTotalFaces),
     addressing_(addressingSlice.size()),
     weights_(addressingSlice.size())
 {
-    const scalarField& weights = mesh.weights().internalField();
-    const labelList& own = mesh.edgeOwner();
-    const labelList& neighb = mesh.edgeNeighbour();
-
     forAll(addressing_, i)
     {
         // Subtract one to align addressing.
         label ai = addressingSlice[i];
 //         label ai = mag(addressingSlice[i]) - 1;
 
-        if (ai < neighb.size())
+        if (ai < neigh.size())
         {
             // This is a regular edge. it has been an internal edge
             // of the original mesh and now it has become a edge
             // on the parallel boundary
-            addressing_[i].setSize(2);
-            weights_[i].setSize(2);
+            addressing_[i].resize(2);
+            weights_[i].resize(2);
 
-            addressing_[i][0] = own[ai];
-            addressing_[i][1] = neighb[ai];
+            addressing_[i][0] = owner[ai];
+            addressing_[i][1] = neigh[ai];
 
-            weights_[i][0] = weights[ai];
-            weights_[i][1] = 1.0 - weights[ai];
+            if (ai < weights.size())
+            {
+                // Edge weights exist/are usable
+                weights_[i][0] = weights[ai];
+                weights_[i][1] = 1.0 - weights[ai];
+            }
+            else
+            {
+                // No edge weights. use equal weighting
+                weights_[i][0] = 0.5;
+                weights_[i][1] = 0.5;
+            }
         }
         else
         {
@@ -92,11 +101,11 @@ processorAreaPatchFieldDecomposer
             // do the interpolation properly (I would need to look
             // up the different (edge) list of data), so I will
             // just grab the value from the owner face
-            //
-            addressing_[i].setSize(1);
-            weights_[i].setSize(1);
 
-            addressing_[i][0] = own[ai];
+            addressing_[i].resize(1);
+            weights_[i].resize(1);
+
+            addressing_[i][0] = owner[ai];
 
             weights_[i][0] = 1.0;
         }
@@ -104,6 +113,24 @@ processorAreaPatchFieldDecomposer
 }
 
 
+Foam::faFieldDecomposer::processorAreaPatchFieldDecomposer::
+processorAreaPatchFieldDecomposer
+(
+    const faMesh& mesh,
+    const labelUList& addressingSlice
+)
+:
+    processorAreaPatchFieldDecomposer
+    (
+        mesh.nFaces(),
+        mesh.edgeOwner(),
+        mesh.edgeNeighbour(),
+        addressingSlice,
+        mesh.weights().internalField()
+    )
+{}
+
+
 Foam::faFieldDecomposer::processorEdgePatchFieldDecomposer::
 processorEdgePatchFieldDecomposer
 (
@@ -117,8 +144,8 @@ processorEdgePatchFieldDecomposer
 {
     forAll(addressing_, i)
     {
-        addressing_[i].setSize(1);
-        weights_[i].setSize(1);
+        addressing_[i].resize(1);
+        weights_[i].resize(1);
 
         addressing_[i][0] = mag(addressingSlice[i]) - 1;
         weights_[i][0] = sign(addressingSlice[i]);
@@ -126,28 +153,167 @@ processorEdgePatchFieldDecomposer
 }
 
 
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
 Foam::faFieldDecomposer::faFieldDecomposer
 (
-    const faMesh& completeMesh,
+    const Foam::zero,
     const faMesh& procMesh,
     const labelList& edgeAddressing,
     const labelList& faceAddressing,
     const labelList& boundaryAddressing
 )
 :
-    completeMesh_(completeMesh),
     procMesh_(procMesh),
     edgeAddressing_(edgeAddressing),
     faceAddressing_(faceAddressing),
     boundaryAddressing_(boundaryAddressing),
+    // Mappers
+    patchFieldDecomposerPtrs_(),
+    processorAreaPatchFieldDecomposerPtrs_(),
+    processorEdgePatchFieldDecomposerPtrs_()
+{}
+
+
+Foam::faFieldDecomposer::faFieldDecomposer
+(
+    const faMesh& completeMesh,
+    const faMesh& procMesh,
+    const labelList& edgeAddressing,
+    const labelList& faceAddressing,
+    const labelList& boundaryAddressing
+)
+:
+    faFieldDecomposer
+    (
+        zero{},
+        procMesh,
+        edgeAddressing,
+        faceAddressing,
+        boundaryAddressing
+    )
+{
+    reset(completeMesh);
+}
+
+
+Foam::faFieldDecomposer::faFieldDecomposer
+(
+    const label nTotalFaces,
+    const List<labelRange>& boundaryRanges,
+    const labelUList& edgeOwner,
+    const labelUList& edgeNeigbour,
+
+    const faMesh& procMesh,
+    const labelList& edgeAddressing,
+    const labelList& faceAddressing,
+    const labelList& boundaryAddressing
+)
+:
+    faFieldDecomposer
+    (
+        zero{},
+        procMesh,
+        edgeAddressing,
+        faceAddressing,
+        boundaryAddressing
+    )
+{
+    reset(nTotalFaces, boundaryRanges, edgeOwner, edgeNeigbour);
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+bool Foam::faFieldDecomposer::empty() const
+{
+    return patchFieldDecomposerPtrs_.empty();
+}
 
-    patchFieldDecomposerPtrs_(procMesh_.boundary().size()),
-    processorAreaPatchFieldDecomposerPtrs_(procMesh_.boundary().size()),
-    processorEdgePatchFieldDecomposerPtrs_(procMesh_.boundary().size())
+
+void Foam::faFieldDecomposer::clear()
+{
+    patchFieldDecomposerPtrs_.clear();
+    processorAreaPatchFieldDecomposerPtrs_.clear();
+    processorEdgePatchFieldDecomposerPtrs_.clear();
+}
+
+
+void Foam::faFieldDecomposer::reset
+(
+    const label nTotalFaces,
+    const List<labelRange>& boundaryRanges,
+    const labelUList& edgeOwner,
+    const labelUList& edgeNeigbour
+)
+{
+    clear();
+    const label nMappers = procMesh_.boundary().size();
+
+    patchFieldDecomposerPtrs_.resize(nMappers);
+    processorAreaPatchFieldDecomposerPtrs_.resize(nMappers);
+    processorEdgePatchFieldDecomposerPtrs_.resize(nMappers);
+
+    forAll(boundaryAddressing_, patchi)
+    {
+        const label oldPatchi = boundaryAddressing_[patchi];
+        const faPatch& fap = procMesh_.boundary()[patchi];
+        const labelSubList localPatchSlice(fap.patchSlice(edgeAddressing_));
+
+        if (oldPatchi >= 0)
+        {
+            patchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new patchFieldDecomposer
+                (
+                    boundaryRanges[oldPatchi].size(),
+                    localPatchSlice,
+                    boundaryRanges[oldPatchi].start()
+                )
+            );
+        }
+        else
+        {
+            processorAreaPatchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new processorAreaPatchFieldDecomposer
+                (
+                    nTotalFaces,
+                    edgeOwner,
+                    edgeNeigbour,
+                    localPatchSlice
+                )
+            );
+
+            processorEdgePatchFieldDecomposerPtrs_.set
+            (
+                patchi,
+                new processorEdgePatchFieldDecomposer
+                (
+                    procMesh_.boundary()[patchi].size(),
+                    static_cast<const labelUList&>(localPatchSlice)
+                )
+            );
+        }
+    }
+}
+
+
+void Foam::faFieldDecomposer::reset(const faMesh& completeMesh)
 {
+    clear();
+    const label nMappers = procMesh_.boundary().size();
+    patchFieldDecomposerPtrs_.resize(nMappers);
+    processorAreaPatchFieldDecomposerPtrs_.resize(nMappers);
+    processorEdgePatchFieldDecomposerPtrs_.resize(nMappers);
+
     forAll(boundaryAddressing_, patchi)
     {
         const label oldPatchi = boundaryAddressing_[patchi];
+        const faPatch& fap = procMesh_.boundary()[patchi];
+        const labelSubList localPatchSlice(fap.patchSlice(edgeAddressing_));
 
         if (oldPatchi >= 0)
         {
@@ -156,9 +322,9 @@ Foam::faFieldDecomposer::faFieldDecomposer
                 patchi,
                 new patchFieldDecomposer
                 (
-                    completeMesh_.boundary()[oldPatchi].size(),
-                    procMesh_.boundary()[patchi].patchSlice(edgeAddressing_),
-                    completeMesh_.boundary()[oldPatchi].start()
+                    completeMesh.boundary()[oldPatchi].size(),
+                    localPatchSlice,
+                    completeMesh.boundary()[oldPatchi].start()
                 )
             );
         }
@@ -169,8 +335,8 @@ Foam::faFieldDecomposer::faFieldDecomposer
                 patchi,
                 new processorAreaPatchFieldDecomposer
                 (
-                    completeMesh_,
-                    procMesh_.boundary()[patchi].patchSlice(edgeAddressing_)
+                    completeMesh,
+                    localPatchSlice
                 )
             );
 
@@ -180,13 +346,7 @@ Foam::faFieldDecomposer::faFieldDecomposer
                 new processorEdgePatchFieldDecomposer
                 (
                     procMesh_.boundary()[patchi].size(),
-                    static_cast<const labelUList&>
-                    (
-                        procMesh_.boundary()[patchi].patchSlice
-                        (
-                            edgeAddressing_
-                        )
-                    )
+                    static_cast<const labelUList&>(localPatchSlice)
                 )
             );
         }
diff --git a/src/parallel/decompose/faDecompose/faFieldDecomposer.H b/src/parallel/decompose/faDecompose/faFieldDecomposer.H
index 18008a20773ff19c9ef198018c277facac409a1c..18e896801fc5c14804928057d7139285b0db4ac1 100644
--- a/src/parallel/decompose/faDecompose/faFieldDecomposer.H
+++ b/src/parallel/decompose/faDecompose/faFieldDecomposer.H
@@ -120,7 +120,7 @@ public:
         :
             public faPatchFieldMapper
         {
-            // Private data
+            // Private Data
 
                 label sizeBeforeMapping_;
                 labelListList addressing_;
@@ -128,7 +128,17 @@ public:
 
         public:
 
-            //- Construct given addressing
+            //- Construct addressing from details
+            processorAreaPatchFieldDecomposer
+            (
+                const label nTotalFaces,
+                const labelUList& edgeOwner,
+                const labelUList& edgeNeigbour,
+                const labelUList& addressingSlice,
+                const scalarField& edgeWeights = scalarField::null()
+            );
+
+            //- Construct given addressing from complete mesh
             processorAreaPatchFieldDecomposer
             (
                 const faMesh& mesh,
@@ -136,7 +146,7 @@ public:
             );
 
 
-            // Member functions
+            // Member Functions
 
                 label size() const
                 {
@@ -225,10 +235,10 @@ public:
 
 private:
 
-    // Private data
+    // Private Data
 
         //- Reference to complete mesh
-        const faMesh& completeMesh_;
+        //REMOVED: const faMesh& completeMesh_;
 
         //- Reference to processor mesh
         const faMesh& procMesh_;
@@ -265,7 +275,17 @@ public:
 
     // Constructors
 
-        //- Construct from components
+        //- Construct without mappers, added later with reset()
+        faFieldDecomposer
+        (
+            const Foam::zero,
+            const faMesh& procMesh,
+            const labelList& edgeAddressing,
+            const labelList& faceAddressing,
+            const labelList& boundaryAddressing
+        );
+
+        //- Construct from components using information from the complete mesh
         faFieldDecomposer
         (
             const faMesh& completeMesh,
@@ -275,13 +295,50 @@ public:
             const labelList& boundaryAddressing
         );
 
+        //- Construct from components without the complete mesh
+        faFieldDecomposer
+        (
+            // Information about the complete mesh
+            const label nTotalFaces,
+            const List<labelRange>& boundaryRanges,
+            const labelUList& edgeOwner,
+            const labelUList& edgeNeigbour,
+
+            // Addressing for processor mesh
+            const faMesh& procMesh,
+            const labelList& edgeAddressing,
+            const labelList& faceAddressing,
+            const labelList& boundaryAddressing
+        );
+
 
-    // Destructor
+    //- Destructor
     ~faFieldDecomposer() = default;
 
 
     // Member Functions
 
+        //- True if no mappers have been allocated
+        bool empty() const;
+
+        //- Remove all mappers
+        void clear();
+
+        //- Reset mappers using information from the complete mesh
+        void reset(const faMesh& completeMesh);
+
+        //- Reset mapper using information about the complete mesh
+        void reset
+        (
+            const label nTotalFaces,
+            const List<labelRange>& boundaryRanges,
+            const labelUList& edgeOwner,
+            const labelUList& edgeNeigbour
+        );
+
+
+    // Mapping
+
         //- Decompose area field
         template<class Type>
         tmp<GeometricField<Type, faPatchField, areaMesh>>