diff --git a/etc/bashrc b/etc/bashrc
index e0e3039ae3..f4268e1ff7 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 6f21e8658d..918d4cfa13 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 bec9607668..26e22f9d93 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 79d8efe606..9ead10e19f 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 f3bee0ee80..a44eaa9671 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 098d885698..895513345d 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 bc6680fc53..8fee47ce9a 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 0000000000..80f7dbc464
--- /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 .
+
+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 ConstPrecisionAdaptor
+:
+ public tmp>
+{
+public:
+
+ // Constructors
+
+ //- Construct from InputType
+ ConstPrecisionAdaptor(const Field& input)
+ :
+ tmp>()
+ {
+ if (std::is_same::value)
+ {
+ // Set reference - cast for compiler to handle different types
+ this->cref(reinterpret_cast&>(input));
+ }
+ else
+ {
+ this->reset(new Field(input.size()));
+ std::copy(input.cbegin(), input.cend(), this->ref().begin());
+ }
+ }
+
+
+ // Member Functions
+
+ //- Return the field
+ static const Field& get
+ (
+ const Field& input,
+ Field& dst
+ )
+ {
+ if (std::is_same::value)
+ {
+ return reinterpret_cast&>(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 PrecisionAdaptor
+:
+ public tmp>
+{
+ // Private Data
+
+ //- Reference to underlying field
+ Field& ref_;
+
+
+public:
+
+ // Constructors
+
+ //- Construct from Field, copying on input as required
+ PrecisionAdaptor(Field& input)
+ :
+ tmp>(),
+ ref_(input)
+ {
+ if (std::is_same::value)
+ {
+ // Set reference - cast for compiler to handle different types
+ this->cref(reinterpret_cast&>(input));
+ }
+ else
+ {
+ this->reset(new Field(input.size()));
+ std::copy(input.cbegin(), input.cend(), this->ref().begin());
+ }
+ }
+
+
+ //- Destructor, copying on destroy
+ ~PrecisionAdaptor()
+ {
+ if (this->isTmp())
+ {
+ const Field& 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 db1f60d379..484aa120bd 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 |
+ \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2011 OpenFOAM Foundation
@@ -48,6 +48,7 @@ template class Field;
typedef Field