diff --git a/src/OpenFOAM/fields/Fields/Field/FieldOps.C b/src/OpenFOAM/fields/Fields/Field/FieldOps.C
new file mode 100644
index 0000000000..0c9d997166
--- /dev/null
+++ b/src/OpenFOAM/fields/Fields/Field/FieldOps.C
@@ -0,0 +1,157 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2019 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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include
+
+// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
+
+template
+void Foam::FieldOps::assign
+(
+ Field& result,
+ const Field& a,
+ const UnaryOp& op
+)
+{
+ #ifdef FULLDEBUG
+ if (result.size() != a.size())
+ {
+ FatalErrorInFunction
+ << "Field sizes do not match: " << result.size() << " ("
+ << a.size() << ')' << nl
+ << abort(FatalError);
+ }
+ #endif
+
+ std::transform(a.cbegin(), a.cend(), result.begin(), op);
+}
+
+
+template
+void Foam::FieldOps::assign
+(
+ Field& result,
+ const Field& a,
+ const Field& b,
+ const BinaryOp& bop
+)
+{
+ #ifdef FULLDEBUG
+ if (result.size() != a.size() || result.size() != b.size())
+ {
+ FatalErrorInFunction
+ << "Field sizes do not match: " << result.size() << " ("
+ << a.size() << ' ' << b.size() << ')' << nl
+ << abort(FatalError);
+ }
+ #endif
+
+ std::transform(a.cbegin(), a.cend(), b.cbegin(), result.begin(), bop);
+}
+
+
+template
+void Foam::FieldOps::ternary
+(
+ Field& result,
+ const Field& a,
+ const Field& b,
+ const BinaryOp& bop
+)
+{
+ #ifdef FULLDEBUG
+ if (result.size() != a.size() || result.size() != b.size())
+ {
+ FatalErrorInFunction
+ << "Field sizes do not match: " << result.size() << " ("
+ << a.size() << ' ' << b.size() << ')' << nl
+ << abort(FatalError);
+ }
+ #endif
+
+ forAll(result, i)
+ {
+ result[i] = bop(a[i], b[i]) ? a[i] : b[i];
+ }
+}
+
+
+template
+void Foam::FieldOps::ternarySelect
+(
+ Field& result,
+ const BoolListType& cond,
+ const Field& a,
+ const Field& b,
+ const FlipOp& flip
+)
+{
+ #ifdef FULLDEBUG
+ if (result.size() != a.size() || result.size() != b.size())
+ {
+ FatalErrorInFunction
+ << "Field sizes do not match: " << result.size() << " ("
+ << a.size() << ' ' << b.size() << ')' << nl
+ << abort(FatalError);
+ }
+ #endif
+
+ forAll(result, i)
+ {
+ result[i] = flip(cond[i]) ? a[i] : b[i];
+ }
+}
+
+
+template
+void Foam::FieldOps::ternarySelect
+(
+ Field& result,
+ const bitSet& cond,
+ const Field& a,
+ const Field& b,
+ const FlipOp& flip
+)
+{
+ #ifdef FULLDEBUG
+ if (result.size() != a.size() || result.size() != b.size())
+ {
+ FatalErrorInFunction
+ << "Field sizes do not match: " << result.size() << " ("
+ << a.size() << ' ' << b.size() << ')' << nl
+ << abort(FatalError);
+ }
+ #endif
+
+ forAll(result, i)
+ {
+ result[i] = flip(cond[i]) ? a[i] : b[i];
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/fields/Fields/Field/FieldOps.H b/src/OpenFOAM/fields/Fields/Field/FieldOps.H
new file mode 100644
index 0000000000..47ebf2917f
--- /dev/null
+++ b/src/OpenFOAM/fields/Fields/Field/FieldOps.H
@@ -0,0 +1,208 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2019 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 .
+
+Namespace
+ Foam::FieldOps
+
+Description
+ Various utility functions to work on Fields
+
+SourceFiles
+ FieldOps.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef FieldOps_H
+#define FieldOps_H
+
+#include "flipOp.H"
+#include "ListOps.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace FieldOps
+{
+
+/*---------------------------------------------------------------------------*\
+ Namespace FieldOps Declarations
+\*---------------------------------------------------------------------------*/
+
+//- Populate a field as the result of a unary operation on an input.
+// It is permissible for inputs/outputs to refer to the same field(s),
+// but partially overlapping regions are ill-defined.
+//
+// Examples,
+// \code
+// boolField result(sfield1.size());
+//
+// FieldOps::assign(result, sfield1, lessOp1(0.5));
+// FieldOps::assign(result, lfield1, std::logical_not());
+// \endcode
+//
+// Example of using the Random::uniformGeneratorOp unary operator
+// to populate a random field,
+// \code
+// FieldOps::assign
+// (
+// sfield,
+// sfield,
+// Random::uniformGeneratorOp(-15, 25)
+// );
+// \endcode
+//
+// \note wraps std::transform
+template
+void assign
+(
+ Field& result,
+ const Field& a,
+ const UnaryOp& op
+);
+
+
+//- Populate a field as the result of a binary operation on two inputs.
+// It is permissible for inputs/outputs to refer to the same field(s),
+// but partially overlapping regions are ill-defined.
+//
+// Examples,
+// \code
+// FieldOps::assign(result, sfield1, sfield2, std::less());
+// FieldOps::assign(result, lfield1, lfield2, std::logical_or());
+// \endcode
+//
+// \note wraps std::transform
+template
+void assign
+(
+ Field& result,
+ const Field& a,
+ const Field& b,
+ const BinaryOp& bop
+);
+
+
+//- Emulate a ternary operation, selecting values from a or b
+//- depending on the binary predicate.
+//
+// Examples,
+// \code
+// FieldOps::ternary(result, sfield1, sfield2, std::less());
+// \endcode
+template
+void ternary
+(
+ Field& result,
+ const Field& a,
+ const Field& b,
+ const BinaryOp& bop
+);
+
+
+//- Emulate a ternary operation, selecting values from a or b
+//- depending on the conditional.
+//
+// The meaning of the conditional is adjusted by the flip operation,
+// which is typically Foam::noOp() or Foam::flipBoolOp()
+//
+// Similar parameter requirements as Foam::subset()
+//
+// Examples,
+// \code
+// FieldOps::ternarySelect(result, selector, sfield1, sfield2);
+// \endcode
+template
+void ternarySelect
+(
+ Field& result,
+ const BoolListType& cond,
+ const Field& a,
+ const Field& b,
+ const FlipOp& flip
+);
+
+
+//- Emulate a ternary operation, selecting values from a or b
+//- depending on the conditional.
+//
+// The meaning of the conditional is adjusted by the flip operation,
+// which is typically Foam::noOp() or Foam::flipBoolOp()
+template
+void ternarySelect
+(
+ Field& result,
+ const bitSet& cond,
+ const Field& a,
+ const Field& b,
+ const FlipOp& flip
+);
+
+
+//- Emulated ternary operation, without condition flipping
+template
+void ternarySelect
+(
+ Field& result,
+ const BoolListType& cond,
+ const Field& a,
+ const Field& b
+)
+{
+ ternarySelect(result, cond, a, b, noOp());
+}
+
+
+//- Emulated ternary operation, without condition flipping
+template
+void ternarySelect
+(
+ Field& result,
+ const bitSet& cond,
+ const Field& a,
+ const Field& b
+)
+{
+ ternarySelect(result, cond, a, b, noOp());
+}
+
+
+} // End namespace FieldOps
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+ #include "FieldOps.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldOps.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldOps.H
new file mode 100644
index 0000000000..a7fc88765f
--- /dev/null
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricFieldOps.H
@@ -0,0 +1,228 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2019 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 .
+
+InNamespace
+ Foam::FieldOps
+
+Description
+ Various utility functions to work on geometric fields
+
+SourceFiles
+ GeometricFieldOps.H
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef GeometricFieldOps_H
+#define GeometricFieldOps_H
+
+#include "FieldOps.H"
+#include "GeometricField.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace FieldOps
+{
+
+/*---------------------------------------------------------------------------*\
+ Namespace FieldOps Declarations
+\*---------------------------------------------------------------------------*/
+
+//- Populate a geometric field as the result of a unary operation on an input.
+// It is permissible for inputs/outputs to refer to the same field(s),
+// but partially overlapping regions are ill-defined.
+template
+<
+ class Tout, class T1, class UnaryOp,
+ template class PatchField, class GeoMesh
+>
+void assign
+(
+ GeometricField& result,
+ const GeometricField& a,
+ const UnaryOp& op
+)
+{
+ FieldOps::assign
+ (
+ result.primitiveFieldRef(),
+ a.primitiveField(),
+ op
+ );
+
+ auto& bfld = result.boundaryFieldRef();
+
+ const label len = bfld.size();
+
+ for (label i = 0; i < len; ++i)
+ {
+ FieldOps::assign
+ (
+ bfld[i],
+ a.boundaryField()[i],
+ op
+ );
+ }
+}
+
+
+//- Populate a geometric field from the binary operation on two inputs.
+// It is permissible for inputs/outputs to refer to the same field(s),
+// but partially overlapping regions are ill-defined.
+template
+<
+ class Tout, class T1, class T2, class BinaryOp,
+ template class PatchField, class GeoMesh
+>
+void assign
+(
+ GeometricField& result,
+ const GeometricField& a,
+ const GeometricField& b,
+ const BinaryOp& bop
+)
+{
+ FieldOps::assign
+ (
+ result.primitiveFieldRef(),
+ a.primitiveField(),
+ b.primitiveField(),
+ bop
+ );
+
+ auto& bfld = result.boundaryFieldRef();
+
+ const label len = bfld.size();
+
+ for (label i = 0; i < len; ++i)
+ {
+ FieldOps::assign
+ (
+ bfld[i],
+ a.boundaryField()[i],
+ b.boundaryField()[i],
+ bop
+ );
+ }
+}
+
+
+//- Emulate a ternary operation, selecting values from a or b
+//- depending on the binary predicate.
+template
+<
+ class T, class BinaryOp,
+ template class PatchField, class GeoMesh
+>
+void ternary
+(
+ GeometricField& result,
+ const GeometricField& a,
+ const GeometricField& b,
+ const BinaryOp& bop
+)
+{
+ FieldOps::ternary
+ (
+ result.primitiveFieldRef(),
+ a.primitiveField(),
+ b.primitiveField(),
+ bop
+ );
+
+ auto& bfld = result.boundaryFieldRef();
+
+ const label len = bfld.size();
+
+ for (label i = 0; i < len; ++i)
+ {
+ FieldOps::ternary
+ (
+ bfld[i],
+ a.boundaryField()[i],
+ b.boundaryField()[i],
+ bop
+ );
+ }
+}
+
+
+//- Emulate a ternary operation, selecting field values from a or b
+//- depending on the conditional.
+//
+// Since boolean fields are not normally used, a flip operation is
+// a general requirement.
+template
+<
+ class T, class BoolType, class FlipOp,
+ template class PatchField, class GeoMesh
+>
+void ternarySelect
+(
+ GeometricField& result,
+ const GeometricField& cond,
+ const GeometricField& a,
+ const GeometricField& b,
+ const FlipOp& flip
+)
+{
+ FieldOps::ternarySelect
+ (
+ result.primitiveFieldRef(),
+ cond.primitiveField(),
+ a.primitiveField(),
+ b.primitiveField(),
+ flip
+ );
+
+ auto& bfld = result.boundaryFieldRef();
+
+ const label len = bfld.size();
+
+ for (label i = 0; i < len; ++i)
+ {
+ FieldOps::ternarySelect
+ (
+ bfld[i],
+ cond.boundaryField()[i],
+ a.boundaryField()[i],
+ b.boundaryField()[i],
+ flip
+ );
+ }
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace FieldOps
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //