diff --git a/etc/bashrc b/etc/bashrc
index 8342d20098fe839161a02840efaeecd2e40c13fd..983208563a275bba1fefd50225012aeecbe682d7 100644
--- a/etc/bashrc
+++ b/etc/bashrc
@@ -81,7 +81,7 @@ export WM_COMPILER=Gcc
 export WM_ARCH_OPTION=64
 
 # [WM_PRECISION_OPTION] - Floating-point precision:
-# = DP | SP
+# = DP | SP | SPDP
 export WM_PRECISION_OPTION=DP
 
 # [WM_LABEL_SIZE] - Label size in bits:
diff --git a/etc/config.csh/aliases b/etc/config.csh/aliases
index 6f21e8658deddf1b7df422370015e7a3a56445a6..918d4cfa13f81322240fd89432d2897759584d71 100644
--- a/etc/config.csh/aliases
+++ b/etc/config.csh/aliases
@@ -25,8 +25,9 @@
 alias wmSet 'source $WM_PROJECT_DIR/etc/cshrc'
 alias wmInt32 'wmSet WM_LABEL_SIZE=32'
 alias wmInt64 'wmSet WM_LABEL_SIZE=64'
-alias wmSP 'wmSet WM_PRECISION_OPTION=SP'
 alias wmDP 'wmSet WM_PRECISION_OPTION=DP'
+alias wmSP 'wmSet WM_PRECISION_OPTION=SP'
+alias wmSPDP 'wmSet WM_PRECISION_OPTION=SPDP'
 
 # Clear env
 alias wmUnset 'source $WM_PROJECT_DIR/etc/config.csh/unset'
diff --git a/etc/config.csh/unset b/etc/config.csh/unset
index bec9607668acc26347324fd87575abd0bee589db..26e22f9d93a0aa78f8826e3ab01db3a6b6e9a409 100644
--- a/etc/config.csh/unset
+++ b/etc/config.csh/unset
@@ -162,8 +162,9 @@ endif
 unalias wmSet
 unalias wmInt32
 unalias wmInt64
-unalias wmSP
 unalias wmDP
+unalias wmSP
+unalias wmSPDP
 
 unalias wmUnset
 
diff --git a/etc/config.sh/aliases b/etc/config.sh/aliases
index 79d8efe606da47883f03165cae2eab56da6c9d5f..9ead10e19fdb33021966bc38aadf8019001b881e 100644
--- a/etc/config.sh/aliases
+++ b/etc/config.sh/aliases
@@ -25,8 +25,9 @@
 alias wmSet='. $WM_PROJECT_DIR/etc/bashrc'
 alias wmInt32='wmSet WM_LABEL_SIZE=32'
 alias wmInt64='wmSet WM_LABEL_SIZE=64'
-alias wmSP='wmSet WM_PRECISION_OPTION=SP'
 alias wmDP='wmSet WM_PRECISION_OPTION=DP'
+alias wmSP='wmSet WM_PRECISION_OPTION=SP'
+alias wmSPDP='wmSet WM_PRECISION_OPTION=SPDP'
 
 # Clear env
 alias wmUnset='. $WM_PROJECT_DIR/etc/config.sh/unset'
diff --git a/etc/config.sh/unset b/etc/config.sh/unset
index f3bee0ee80c744fcb611f65f641ceabab33124b1..a44eaa967159aec4f8bcf00c2f521580f793a41b 100644
--- a/etc/config.sh/unset
+++ b/etc/config.sh/unset
@@ -156,8 +156,9 @@ fi
 unalias wmSet       2>/dev/null
 unalias wmInt32     2>/dev/null
 unalias wmInt64     2>/dev/null
-unalias wmSP        2>/dev/null
 unalias wmDP        2>/dev/null
+unalias wmSP        2>/dev/null
+unalias wmSPDP      2>/dev/null
 
 unalias wmUnset     2>/dev/null
 
diff --git a/etc/cshrc b/etc/cshrc
index 875a66343c1287b8f7615b4665bdd718c152ff8e..88abc2cddadc814ee060fb7996195efce26b08ae 100644
--- a/etc/cshrc
+++ b/etc/cshrc
@@ -83,7 +83,7 @@ setenv WM_COMPILER Gcc
 setenv WM_ARCH_OPTION 64
 
 # [WM_PRECISION_OPTION] - Floating-point precision:
-# = DP | SP
+# = DP | SP | SPDP
 setenv WM_PRECISION_OPTION DP
 
 # [WM_LABEL_SIZE] - Label size in bits:
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index bc6680fc53b3d464f5aed8444b03a62b8d4bc446..8fee47ce9a7c63597b3529a95744aff48ac68d2c 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -79,7 +79,7 @@ primitives/Vector/complexVector/complexVector.C
 primitives/Vector/doubleVector/doubleVector.C
 primitives/Tensor/doubleTensor/doubleTensor.C
 #endif
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 primitives/Vector/floatVector/floatVector.C
 primitives/Tensor/floatTensor/floatTensor.C
 #endif
diff --git a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H
new file mode 100644
index 0000000000000000000000000000000000000000..80f7dbc464f4f2768c7a7a3522f081406b5cce68
--- /dev/null
+++ b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H
@@ -0,0 +1,154 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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::PrecisionAdaptor
+
+Description
+    Conversion adaptor for Field that either wraps as a tmp reference
+    or creates the necessary tmp and copies the values on construction
+    and destruction.
+    This provides automatic conversion between (scalar) types for use
+    with linear solvers able to run mixed precision.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef PrecisionAdaptor_H
+#define PrecisionAdaptor_H
+
+#include "Field.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+//- A const Field wrapper with possible data conversion
+template<class Type, class InputType>
+class ConstPrecisionAdaptor
+:
+    public tmp<Field<Type>>
+{
+public:
+
+    // Constructors
+
+        //- Construct from InputType
+        ConstPrecisionAdaptor(const Field<InputType>& input)
+        :
+            tmp<Field<Type>>()
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                // Set reference - cast for compiler to handle different types
+                this->cref(reinterpret_cast<const Field<Type>&>(input));
+            }
+            else
+            {
+                this->reset(new Field<Type>(input.size()));
+                std::copy(input.cbegin(), input.cend(), this->ref().begin());
+            }
+        }
+
+
+    // Member Functions
+
+        //- Return the field
+        static const Field<Type>& get
+        (
+            const Field<InputType>& input,
+            Field<Type>& dst
+        )
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                return reinterpret_cast<const Field<Type>&>(input);
+            }
+            else
+            {
+                dst.resize(input.size());
+                std::copy(input.cbegin(), input.cend(), dst.begin());
+                return dst;
+            }
+        }
+};
+
+
+//- A Field wrapper with possible data conversion
+template<class Type, class InputType>
+class PrecisionAdaptor
+:
+    public tmp<Field<Type>>
+{
+    // Private Data
+
+        //- Reference to underlying field
+        Field<InputType>& ref_;
+
+
+public:
+
+    // Constructors
+
+        //- Construct from Field<InputType>, copying on input as required
+        PrecisionAdaptor(Field<InputType>& input)
+        :
+            tmp<Field<Type>>(),
+            ref_(input)
+        {
+            if (std::is_same<Type, InputType>::value)
+            {
+                // Set reference - cast for compiler to handle different types
+                this->cref(reinterpret_cast<const Field<Type>&>(input));
+            }
+            else
+            {
+                this->reset(new Field<Type>(input.size()));
+                std::copy(input.cbegin(), input.cend(), this->ref().begin());
+            }
+        }
+
+
+    //- Destructor, copying on destroy
+    ~PrecisionAdaptor()
+    {
+        if (this->isTmp())
+        {
+            const Field<Type>& store = this->cref();
+            ref_.resize(store.size());
+            std::copy(store.cbegin(), store.cend(), ref_.begin());
+        }
+    }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H b/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H
index a45fafd1ebec1ff171f4e786fde0a0ba95c47775..1a36283d8868b25acb53d27e08e3f68e2e43a639 100644
--- a/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H
+++ b/src/OpenFOAM/fields/Fields/primitiveFieldsFwd.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2004-2010 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2004-2010, 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011 OpenFOAM Foundation
@@ -48,6 +48,7 @@ template<class Type> class Field;
 
 typedef Field<label> labelField;
 typedef Field<scalar> scalarField;
+typedef Field<solveScalar> solveScalarField;
 typedef Field<vector> vectorField;
 typedef Field<sphericalTensor> sphericalTensorField;
 typedef Field<symmTensor> symmTensorField;
diff --git a/src/OpenFOAM/global/global.Cver b/src/OpenFOAM/global/global.Cver
index 9b471f038185862f4f70f2991edd93839e208f30..0eb7101ee539705002e38c74101698b58f8b4aba 100644
--- a/src/OpenFOAM/global/global.Cver
+++ b/src/OpenFOAM/global/global.Cver
@@ -98,6 +98,7 @@ const std::string Foam::foamVersion::buildArch
 #endif
     ";label="  + std::to_string(8*sizeof(Foam::label))
   + ";scalar=" + std::to_string(8*sizeof(Foam::scalar))
+  + ";solve=" + std::to_string(8*sizeof(Foam::solveScalar))
 );
 
 
diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.C b/src/OpenFOAM/primitives/Scalar/Scalar.C
index dbd3e079fd81a7609054272bdd56ac33eddd45a7..6895c9f981a36c7a2fa9dfeb04bd710a7eee7494 100644
--- a/src/OpenFOAM/primitives/Scalar/Scalar.C
+++ b/src/OpenFOAM/primitives/Scalar/Scalar.C
@@ -39,6 +39,7 @@ const Scalar pTraits<Scalar>::min = -ScalarVGREAT;
 const Scalar pTraits<Scalar>::max = ScalarVGREAT;
 const Scalar pTraits<Scalar>::rootMin = -ScalarROOTVGREAT;
 const Scalar pTraits<Scalar>::rootMax = ScalarROOTVGREAT;
+const Scalar pTraits<Scalar>::vsmall = ScalarVSMALL;
 
 const char* const pTraits<Scalar>::componentNames[] = { "" };
 
diff --git a/src/OpenFOAM/primitives/Scalar/Scalar.H b/src/OpenFOAM/primitives/Scalar/Scalar.H
index 8c0472d0ae77225fd4a73004c9cd1b7e789a3998..9714074a9989f9428a85caa645dd431ec9d6bc2e 100644
--- a/src/OpenFOAM/primitives/Scalar/Scalar.H
+++ b/src/OpenFOAM/primitives/Scalar/Scalar.H
@@ -78,6 +78,7 @@ public:
         static const Scalar min;
         static const Scalar rootMax;
         static const Scalar rootMin;
+        static const Scalar vsmall;
 
 
     // Constructors
diff --git a/src/OpenFOAM/primitives/Scalar/scalar/scalar.H b/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
index 47aefb774de188549d62d8d1a0becb764f8a1d54..911f83623ed18b1787162a5ec809b7c77a121e39 100644
--- a/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
+++ b/src/OpenFOAM/primitives/Scalar/scalar/scalar.H
@@ -28,7 +28,7 @@ Typedef
 
 Description
     A floating-point number identical to float or double depending on
-    whether WM_SP or WM_DP is defined.
+    whether WM_SP, WM_SPDP or WM_DP is defined.
 
 SourceFiles
     scalar.C
@@ -43,13 +43,18 @@ SourceFiles
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
 
 // Define scalar as a float
 
 namespace Foam
 {
     typedef floatScalar scalar;
+    #if defined(WM_SPDP)
+    typedef doubleScalar solveScalar;
+    #else
+    typedef floatScalar solveScalar;
+    #endif
 
     constexpr scalar GREAT = floatScalarGREAT;
     constexpr scalar VGREAT = floatScalarVGREAT;
@@ -89,6 +94,7 @@ namespace Foam
 namespace Foam
 {
     typedef doubleScalar scalar;
+    typedef doubleScalar solveScalar;
 
     constexpr scalar GREAT = doubleScalarGREAT;
     constexpr scalar VGREAT = doubleScalarVGREAT;
diff --git a/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H b/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H
index 986b56b24c17e011b5d37cd48029ebffac1b3a94..5240625536ffab1f18ba28395b5eae6a46d8fa41 100644
--- a/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H
+++ b/src/OpenFOAM/primitives/Tensor/floatTensor/floatTensor.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2016 OpenFOAM Foundation
@@ -50,7 +50,7 @@ namespace Foam
 typedef Tensor<float> floatTensor;
 
 //- Data associated with floatTensor type are contiguous
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 template<>
 inline bool contiguous<floatTensor>() {return true;}
 #endif
diff --git a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
index 1337e8232574b80b0ed4ec452e5125ac062e090e..5c702f6d65d14bbc3e37377681c0be2aa4af9b16 100644
--- a/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
+++ b/src/OpenFOAM/primitives/Vector/floatVector/floatVector.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           |
+    \\  /    A nd           | Copyright (C) 2019 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
                             | Copyright (C) 2011 OpenFOAM Foundation
@@ -50,7 +50,7 @@ namespace Foam
 typedef Vector<float> floatVector;
 
 //- Data associated with floatVector type are contiguous
-#if !defined(WM_SP)
+#if !defined(WM_SP) && !defined(WM_SPDP)
 template<>
 inline bool contiguous<floatVector>() {return true;}
 #endif
diff --git a/src/Pstream/mpi/UPstream.C b/src/Pstream/mpi/UPstream.C
index c37f0255fcb27f006d55679c638ed7476e6c5d04..1128a215d5e78797c497657471267aeee4b70f01 100644
--- a/src/Pstream/mpi/UPstream.C
+++ b/src/Pstream/mpi/UPstream.C
@@ -39,7 +39,7 @@ License
 #include <cstdlib>
 #include <csignal>
 
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
     #define MPI_SCALAR MPI_FLOAT
 #elif defined(WM_DP)
     #define MPI_SCALAR MPI_DOUBLE
diff --git a/src/dummyThirdParty/metisDecomp/metis.h b/src/dummyThirdParty/metisDecomp/metis.h
index b594fc09b1d322c48448d78c4d93eb1feeb1b711..fe0c086e14ace1b75db0c74639b94c17324fdd39 100644
--- a/src/dummyThirdParty/metisDecomp/metis.h
+++ b/src/dummyThirdParty/metisDecomp/metis.h
@@ -27,14 +27,14 @@
 
 
 // Float type: OpenFOAM uses WM_SP, WM_DP, metis.h uses REALTYPEWIDTH
-#if defined(WM_SP)
+#if defined(WM_SP) || defined(WM_SPDP)
   typedef float real_t;
   #define REALTYPEWIDTH 32
 #elif defined(WM_DP)
   typedef double real_t;
   #define REALTYPEWIDTH 64
 #else
-  #error "Incorrect user-supplied value for WM_SP / WM_DP  (metis REALTYPEWIDTH)"
+  #error "Incorrect user-supplied value for WM_SP (WM_SPDP) / WM_DP  (metis REALTYPEWIDTH)"
 #endif