diff --git a/src/functionObjects/field/Make/files b/src/functionObjects/field/Make/files
index 6e433e7e91..603111a869 100644
--- a/src/functionObjects/field/Make/files
+++ b/src/functionObjects/field/Make/files
@@ -76,4 +76,6 @@ age/age.C
comfort/comfort.C
+cylindrical/cylindricalFunctionObject.C
+
LIB = $(FOAM_LIBBIN)/libfieldFunctionObjects
diff --git a/src/functionObjects/field/cylindrical/cylindricalFunctionObject.C b/src/functionObjects/field/cylindrical/cylindricalFunctionObject.C
new file mode 100644
index 0000000000..54829d7e69
--- /dev/null
+++ b/src/functionObjects/field/cylindrical/cylindricalFunctionObject.C
@@ -0,0 +1,149 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2020 OpenFOAM Foundation
+ \\/ 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 .
+
+\*---------------------------------------------------------------------------*/
+
+#include "cylindricalFunctionObject.H"
+#include "volFields.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+ defineTypeNameAndDebug(cylindrical, 0);
+
+ addToRunTimeSelectionTable
+ (
+ functionObject,
+ cylindrical,
+ dictionary
+ );
+}
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+Foam::tensor Foam::functionObjects::cylindrical::R(const vector& p) const
+{
+ vector dir = p - origin_;
+ dir /= mag(dir) + vSmall;
+
+ const vector axis = axis_/mag(axis_);
+ const vector r = dir - (dir & axis)*axis;
+
+ return tensor(r, axis^r, axis);
+}
+
+
+void Foam::functionObjects::cylindrical::transform
+(
+ vectorField& vf,
+ const vectorField& points
+) const
+{
+ if (toCartesian_)
+ {
+ forAll(points, i)
+ {
+ vf[i] = this->R(points[i]).T() & vf[i];
+ }
+ }
+ else
+ {
+ forAll(points, i)
+ {
+ vf[i] = this->R(points[i]) & vf[i];
+ }
+ }
+}
+
+
+bool Foam::functionObjects::cylindrical::calc()
+{
+ if (foundObject(fieldName_))
+ {
+ const volVectorField& vf = lookupObject(fieldName_);
+ const volVectorField& C = mesh_.C();
+
+ tmp tcvf(volVectorField::New(resultName_, vf));
+
+ volVectorField& cvf = tcvf.ref();
+ transform(cvf.primitiveFieldRef(), C);
+
+ forAll(vf.boundaryField(), patchi)
+ {
+ transform
+ (
+ cvf.boundaryFieldRef()[patchi],
+ C.boundaryField()[patchi]
+ );
+ }
+
+ return store(resultName_, tcvf);
+ }
+ else
+ {
+ cannotFindObject(fieldName_);
+
+ return false;
+ }
+
+ return true;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::functionObjects::cylindrical::cylindrical
+(
+ const word& name,
+ const Time& runTime,
+ const dictionary& dict
+)
+:
+ fieldExpression
+ (
+ name,
+ runTime,
+ dict,
+ dict.lookupOrDefault("toCartesian", false)
+ ? "cartesian"
+ : typeName
+ ),
+ origin_(dict.lookup("origin")),
+ axis_(dict.lookup("axis")),
+ toCartesian_(dict.lookupOrDefault("toCartesian", false))
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::functionObjects::cylindrical::~cylindrical()
+{}
+
+
+// ************************************************************************* //
diff --git a/src/functionObjects/field/cylindrical/cylindricalFunctionObject.H b/src/functionObjects/field/cylindrical/cylindricalFunctionObject.H
new file mode 100644
index 0000000000..aa99132e9d
--- /dev/null
+++ b/src/functionObjects/field/cylindrical/cylindricalFunctionObject.H
@@ -0,0 +1,150 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2020 OpenFOAM Foundation
+ \\/ 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::functionObjects::cylindrical
+
+Description
+ Transforms the specified velocity field into a
+ cylindrical polar coordinate system or back to Cartesian.
+
+ Example of function object specification to convert the velocity field U
+ into cylindrical polar coordinates before averaging and returning the
+ average to Cartesian coordinates:
+ \verbatim
+ cartesianToCylindrical
+ {
+ type cylindrical;
+ libs ("libfieldFunctionObjects.so");
+
+ origin (0 0 0);
+ axis (0 0 1);
+
+ field U;
+
+ writeControl outputTime;
+ writeInterval 1;
+ }
+
+ #includeFunc fieldAverage(cylindrical(U))
+
+ cylindricalToCartesian
+ {
+ type cylindrical;
+ libs ("libfieldFunctionObjects.so");
+
+ origin (0 0 0);
+ axis (0 0 1);
+
+ field cylindrical(U)Mean;
+ toCartesian true;
+ result UMean;
+
+ writeControl outputTime;
+ writeInterval 1;
+ }
+ \endverbatim
+ This is particularly useful for cases with rotating regions, e.g. mixer
+ vessels with AMI.
+
+See also
+ Foam::functionObjects::fieldExpression
+ Foam::functionObjects::fvMeshFunctionObject
+
+SourceFiles
+ cylindrical.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef cylindricalFunctionObject_H
+#define cylindricalFunctionObject_H
+
+#include "fieldExpression.H"
+#include "primitiveFieldsFwd.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace functionObjects
+{
+
+/*---------------------------------------------------------------------------*\
+ Class cylindrical Declaration
+\*---------------------------------------------------------------------------*/
+
+class cylindrical
+:
+ public fieldExpression
+{
+ // Private Data
+
+ vector origin_;
+
+ vector axis_;
+
+
+ // Private Member Functions
+
+ tensor R(const vector& p) const;
+
+ void transform(vectorField& vf, const vectorField& points) const;
+
+ bool toCartesian_;
+
+ //- Calculate the cylindrical field and return true if successful
+ virtual bool calc();
+
+
+public:
+
+ //- Runtime type information
+ TypeName("cylindrical");
+
+
+ // Constructors
+
+ //- Construct from Time and dictionary
+ cylindrical
+ (
+ const word& name,
+ const Time& runTime,
+ const dictionary& dict
+ );
+
+
+ //- Destructor
+ virtual ~cylindrical();
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace functionObjects
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/tutorials/incompressible/pimpleFoam/laminar/mixerVesselAMI2D/system/controlDict b/tutorials/incompressible/pimpleFoam/laminar/mixerVesselAMI2D/system/controlDict
index ea4c2b7732..03c17a33b9 100644
--- a/tutorials/incompressible/pimpleFoam/laminar/mixerVesselAMI2D/system/controlDict
+++ b/tutorials/incompressible/pimpleFoam/laminar/mixerVesselAMI2D/system/controlDict
@@ -29,7 +29,7 @@ deltaT 1e-3;
writeControl adjustableRunTime;
-writeInterval 0.1;
+writeInterval 0.05;
purgeWrite 0;
@@ -49,4 +49,40 @@ adjustTimeStep yes;
maxCo 0.5;
+functions
+{
+ cartesianToCylindrical
+ {
+ type cylindrical;
+ libs ("libfieldFunctionObjects.so");
+
+ origin (0 0 0);
+ axis (0 0 1);
+
+ field U;
+
+ writeControl outputTime;
+ writeInterval 1;
+ }
+
+ #includeFunc fieldAverage(cylindrical(U))
+
+ cylindricalToCartesian
+ {
+ type cylindrical;
+ libs ("libfieldFunctionObjects.so");
+
+ origin (0 0 0);
+ axis (0 0 1);
+
+ field cylindrical(U)Mean;
+ toCartesian true;
+ result UMean;
+
+ writeControl outputTime;
+ writeInterval 1;
+ }
+}
+
+
// ************************************************************************* //