diff --git a/applications/test/momentOfInertia/Make/options b/applications/test/momentOfInertia/Make/options
index 54c035b8f55d183c1ad02bc372398feceaf31718..0b32f3355b3b4bf0fda452da0efb5e5c9e2201fa 100644
--- a/applications/test/momentOfInertia/Make/options
+++ b/applications/test/momentOfInertia/Make/options
@@ -1,5 +1,6 @@
 EXE_INC = \
-    -I$(LIB_SRC)/meshTools/lnInclude
+    -I$(LIB_SRC)/meshTools/lnInclude \
+    -I$(LIB_SRC)/triSurface/lnInclude
 
 EXE_LIBS = \
     -lmeshTools
diff --git a/applications/test/momentOfInertia/Test-momentOfInertia.C b/applications/test/momentOfInertia/Test-momentOfInertia.C
index 9a8ae40a5aaa31441ab819518df022157d246182..22327f1bddfa6b18092485d7f87d8fbd589c67af 100644
--- a/applications/test/momentOfInertia/Test-momentOfInertia.C
+++ b/applications/test/momentOfInertia/Test-momentOfInertia.C
@@ -26,180 +26,38 @@ Application
 
 Description
     Calculates the inertia tensor and principal axes and moments of a
-    test face and tetrahedron.
+    test face, tetrahedron and mesh.
 
 \*---------------------------------------------------------------------------*/
 
+#include "argList.H"
+#include "Time.H"
+#include "polyMesh.H"
 #include "ListOps.H"
 #include "face.H"
 #include "tetPointRef.H"
 #include "triFaceList.H"
 #include "OFstream.H"
 #include "meshTools.H"
+#include "momentOfInertia.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 using namespace Foam;
 
-void massPropertiesSolid
-(
-    const pointField& pts,
-    const triFaceList triFaces,
-    scalar density,
-    scalar& mass,
-    vector& cM,
-    tensor& J
-)
+int main(int argc, char *argv[])
 {
-    // Reimplemented from: Wm4PolyhedralMassProperties.cpp
-    // File Version: 4.10.0 (2009/11/18)
-
-    // Geometric Tools, LC
-    // Copyright (c) 1998-2010
-    // Distributed under the Boost Software License, Version 1.0.
-    // http://www.boost.org/LICENSE_1_0.txt
-    // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
-
-    // Boost Software License - Version 1.0 - August 17th, 2003
-
-    // Permission is hereby granted, free of charge, to any person or
-    // organization obtaining a copy of the software and accompanying
-    // documentation covered by this license (the "Software") to use,
-    // reproduce, display, distribute, execute, and transmit the
-    // Software, and to prepare derivative works of the Software, and
-    // to permit third-parties to whom the Software is furnished to do
-    // so, all subject to the following:
-
-    // The copyright notices in the Software and this entire
-    // statement, including the above license grant, this restriction
-    // and the following disclaimer, must be included in all copies of
-    // the Software, in whole or in part, and all derivative works of
-    // the Software, unless such copies or derivative works are solely
-    // in the form of machine-executable object code generated by a
-    // source language processor.
-
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-    // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
-    // NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-    // ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
-    // OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-    // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-    // USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    const scalar r6 = 1.0/6.0;
-    const scalar r24 = 1.0/24.0;
-    const scalar r60 = 1.0/60.0;
-    const scalar r120 = 1.0/120.0;
-
-    // order:  1, x, y, z, x^2, y^2, z^2, xy, yz, zx
-    scalarField integrals(10, 0.0);
-
-    forAll(triFaces, i)
-    {
-        const triFace& tri(triFaces[i]);
-
-        // vertices of triangle i
-        vector v0 = pts[tri[0]];
-        vector v1 = pts[tri[1]];
-        vector v2 = pts[tri[2]];
-
-        // cross product of edges
-        vector eA = v1 - v0;
-        vector eB = v2 - v0;
-        vector n = eA ^ eB;
-
-        // compute integral terms
-        scalar tmp0, tmp1, tmp2;
-
-        scalar f1x, f2x, f3x, g0x, g1x, g2x;
-
-        tmp0 = v0.x() + v1.x();
-        f1x = tmp0 + v2.x();
-        tmp1 = v0.x()*v0.x();
-        tmp2 = tmp1 + v1.x()*tmp0;
-        f2x = tmp2 + v2.x()*f1x;
-        f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
-        g0x = f2x + v0.x()*(f1x + v0.x());
-        g1x = f2x + v1.x()*(f1x + v1.x());
-        g2x = f2x + v2.x()*(f1x + v2.x());
-
-        scalar f1y, f2y, f3y, g0y, g1y, g2y;
-
-        tmp0 = v0.y() + v1.y();
-        f1y = tmp0 + v2.y();
-        tmp1 = v0.y()*v0.y();
-        tmp2 = tmp1 + v1.y()*tmp0;
-        f2y = tmp2 + v2.y()*f1y;
-        f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
-        g0y = f2y + v0.y()*(f1y + v0.y());
-        g1y = f2y + v1.y()*(f1y + v1.y());
-        g2y = f2y + v2.y()*(f1y + v2.y());
-
-        scalar f1z, f2z, f3z, g0z, g1z, g2z;
-
-        tmp0 = v0.z() + v1.z();
-        f1z = tmp0 + v2.z();
-        tmp1 = v0.z()*v0.z();
-        tmp2 = tmp1 + v1.z()*tmp0;
-        f2z = tmp2 + v2.z()*f1z;
-        f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
-        g0z = f2z + v0.z()*(f1z + v0.z());
-        g1z = f2z + v1.z()*(f1z + v1.z());
-        g2z = f2z + v2.z()*(f1z + v2.z());
-
-        // update integrals
-        integrals[0] += n.x()*f1x;
-        integrals[1] += n.x()*f2x;
-        integrals[2] += n.y()*f2y;
-        integrals[3] += n.z()*f2z;
-        integrals[4] += n.x()*f3x;
-        integrals[5] += n.y()*f3y;
-        integrals[6] += n.z()*f3z;
-        integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
-        integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
-        integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
-    }
-
-    integrals[0] *= r6;
-    integrals[1] *= r24;
-    integrals[2] *= r24;
-    integrals[3] *= r24;
-    integrals[4] *= r60;
-    integrals[5] *= r60;
-    integrals[6] *= r60;
-    integrals[7] *= r120;
-    integrals[8] *= r120;
-    integrals[9] *= r120;
-
-    // mass
-    mass = integrals[0];
-
-    // center of mass
-    cM = vector(integrals[1], integrals[2], integrals[3])/mass;
-
-    // inertia relative to origin
-    J.xx() = integrals[5] + integrals[6];
-    J.xy() = -integrals[7];
-    J.xz() = -integrals[9];
-    J.yx() = J.xy();
-    J.yy() = integrals[4] + integrals[6];
-    J.yz() = -integrals[8];
-    J.zx() = J.xz();
-    J.zy() = J.yz();
-    J.zz() = integrals[4] + integrals[5];
-
-    // inertia relative to center of mass
-    J -= mass*((cM & cM)*I - cM*cM);
-
-    // Apply density
-    mass *= density;
-    J *= density;
-}
+    argList::addOption
+    (
+        "cell",
+        "label",
+        "cell to use for inertia calculation, defaults to 0"
+    );
 
+    #include "setRootCase.H"
+    #include "createTime.H"
+    #include "createPolyMesh.H"
 
-int main(int argc, char *argv[])
-{
     scalar density = 1.0;
 
     {
@@ -286,16 +144,7 @@ int main(int argc, char *argv[])
         vector cM = vector::zero;
         tensor J = tensor::zero;
 
-        massPropertiesSolid
-        (
-
-            pts,
-            tetFaces,
-            density,
-            m,
-            cM,
-            J
-        );
+        momentOfInertia::massPropertiesSolid(pts, tetFaces, density, m, cM, J);
 
         vector eVal = eigenValues(J);
 
@@ -344,7 +193,50 @@ int main(int argc, char *argv[])
         {
             str << "l " << nPts + 1 << ' ' << i + 1 << endl;
         }
+    }
+
+    {
+        const label cellI = args.optionLookupOrDefault("cell", 0);
+
+        tensorField mI = momentOfInertia::meshInertia(mesh);
+
+        tensor& J = mI[cellI];
+
+        vector eVal = eigenValues(J);
 
+        Info<< nl
+            << "Inertia tensor of cell " << cellI << " " << J << nl
+            << "eigenValues (principal moments) " << eVal << endl;
+
+        J /= cmptMax(eVal);
+
+        tensor eVec = eigenVectors(J);
+
+        Info<< "eigenVectors (principal axes, from normalised inertia) " << eVec
+            << endl;
+
+        OFstream str("cell_" + name(cellI) + "_inertia.obj");
+
+        Info<< nl << "Writing scaled principal axes of cell " << cellI << " to "
+            << str.name() << endl;
+
+        const point& cC = mesh.cellCentres()[cellI];
+
+        scalar scale = mag
+        (
+            (cC - mesh.faceCentres()[mesh.cells()[cellI][0]])
+           /eVal.component(findMin(eVal))
+        );
+
+        meshTools::writeOBJ(str, cC);
+        meshTools::writeOBJ(str, cC + scale*eVal.x()*eVec.x());
+        meshTools::writeOBJ(str, cC + scale*eVal.y()*eVec.y());
+        meshTools::writeOBJ(str, cC + scale*eVal.z()*eVec.z());
+
+        for (label i = 1; i < 4; i++)
+        {
+            str << "l " << 1 << ' ' << i + 1 << endl;
+        }
     }
 
     Info<< nl << "End" << nl << endl;
diff --git a/applications/utilities/surface/surfaceInertia/surfaceInertia.C b/applications/utilities/surface/surfaceInertia/surfaceInertia.C
index f72bcb6e5ebc2288038a6670e98a605ab554c401..2b8183295f77bdbe6811b612db7c8e7bc06e17cd 100644
--- a/applications/utilities/surface/surfaceInertia/surfaceInertia.C
+++ b/applications/utilities/surface/surfaceInertia/surfaceInertia.C
@@ -33,9 +33,6 @@ Description
 
 #include "argList.H"
 #include "ListOps.H"
-#include "face.H"
-#include "tetPointRef.H"
-#include "triFaceList.H"
 #include "triSurface.H"
 #include "OFstream.H"
 #include "meshTools.H"
@@ -43,242 +40,12 @@ Description
 #include "transform.H"
 #include "IOmanip.H"
 #include "Pair.H"
+#include "momentOfInertia.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 using namespace Foam;
 
-void massPropertiesSolid
-(
-    const pointField& pts,
-    const triFaceList& triFaces,
-    scalar density,
-    scalar& mass,
-    vector& cM,
-    tensor& J
-)
-{
-    // Reimplemented from: Wm4PolyhedralMassProperties.cpp
-    // File Version: 4.10.0 (2009/11/18)
-
-    // Geometric Tools, LC
-    // Copyright (c) 1998-2010
-    // Distributed under the Boost Software License, Version 1.0.
-    // http://www.boost.org/LICENSE_1_0.txt
-    // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
-
-    // Boost Software License - Version 1.0 - August 17th, 2003
-
-    // Permission is hereby granted, free of charge, to any person or
-    // organization obtaining a copy of the software and accompanying
-    // documentation covered by this license (the "Software") to use,
-    // reproduce, display, distribute, execute, and transmit the
-    // Software, and to prepare derivative works of the Software, and
-    // to permit third-parties to whom the Software is furnished to do
-    // so, all subject to the following:
-
-    // The copyright notices in the Software and this entire
-    // statement, including the above license grant, this restriction
-    // and the following disclaimer, must be included in all copies of
-    // the Software, in whole or in part, and all derivative works of
-    // the Software, unless such copies or derivative works are solely
-    // in the form of machine-executable object code generated by a
-    // source language processor.
-
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-    // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
-    // NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-    // ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
-    // OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
-    // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-    // USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-    const scalar r6 = 1.0/6.0;
-    const scalar r24 = 1.0/24.0;
-    const scalar r60 = 1.0/60.0;
-    const scalar r120 = 1.0/120.0;
-
-    // order:  1, x, y, z, x^2, y^2, z^2, xy, yz, zx
-    scalarField integrals(10, 0.0);
-
-    forAll(triFaces, i)
-    {
-        const triFace& tri(triFaces[i]);
-
-        // vertices of triangle i
-        vector v0 = pts[tri[0]];
-        vector v1 = pts[tri[1]];
-        vector v2 = pts[tri[2]];
-
-        // cross product of edges
-        vector eA = v1 - v0;
-        vector eB = v2 - v0;
-        vector n = eA ^ eB;
-
-        // compute integral terms
-        scalar tmp0, tmp1, tmp2;
-
-        scalar f1x, f2x, f3x, g0x, g1x, g2x;
-
-        tmp0 = v0.x() + v1.x();
-        f1x = tmp0 + v2.x();
-        tmp1 = v0.x()*v0.x();
-        tmp2 = tmp1 + v1.x()*tmp0;
-        f2x = tmp2 + v2.x()*f1x;
-        f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
-        g0x = f2x + v0.x()*(f1x + v0.x());
-        g1x = f2x + v1.x()*(f1x + v1.x());
-        g2x = f2x + v2.x()*(f1x + v2.x());
-
-        scalar f1y, f2y, f3y, g0y, g1y, g2y;
-
-        tmp0 = v0.y() + v1.y();
-        f1y = tmp0 + v2.y();
-        tmp1 = v0.y()*v0.y();
-        tmp2 = tmp1 + v1.y()*tmp0;
-        f2y = tmp2 + v2.y()*f1y;
-        f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
-        g0y = f2y + v0.y()*(f1y + v0.y());
-        g1y = f2y + v1.y()*(f1y + v1.y());
-        g2y = f2y + v2.y()*(f1y + v2.y());
-
-        scalar f1z, f2z, f3z, g0z, g1z, g2z;
-
-        tmp0 = v0.z() + v1.z();
-        f1z = tmp0 + v2.z();
-        tmp1 = v0.z()*v0.z();
-        tmp2 = tmp1 + v1.z()*tmp0;
-        f2z = tmp2 + v2.z()*f1z;
-        f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
-        g0z = f2z + v0.z()*(f1z + v0.z());
-        g1z = f2z + v1.z()*(f1z + v1.z());
-        g2z = f2z + v2.z()*(f1z + v2.z());
-
-        // update integrals
-        integrals[0] += n.x()*f1x;
-        integrals[1] += n.x()*f2x;
-        integrals[2] += n.y()*f2y;
-        integrals[3] += n.z()*f2z;
-        integrals[4] += n.x()*f3x;
-        integrals[5] += n.y()*f3y;
-        integrals[6] += n.z()*f3z;
-        integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
-        integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
-        integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
-    }
-
-    integrals[0] *= r6;
-    integrals[1] *= r24;
-    integrals[2] *= r24;
-    integrals[3] *= r24;
-    integrals[4] *= r60;
-    integrals[5] *= r60;
-    integrals[6] *= r60;
-    integrals[7] *= r120;
-    integrals[8] *= r120;
-    integrals[9] *= r120;
-
-    // mass
-    mass = integrals[0];
-
-    // center of mass
-    cM = vector(integrals[1], integrals[2], integrals[3])/mass;
-
-    // inertia relative to origin
-    J.xx() = integrals[5] + integrals[6];
-    J.xy() = -integrals[7];
-    J.xz() = -integrals[9];
-    J.yx() = J.xy();
-    J.yy() = integrals[4] + integrals[6];
-    J.yz() = -integrals[8];
-    J.zx() = J.xz();
-    J.zy() = J.yz();
-    J.zz() = integrals[4] + integrals[5];
-
-    // inertia relative to center of mass
-    J -= mass*((cM & cM)*I - cM*cM);
-
-    // Apply density
-    mass *= density;
-    J *= density;
-}
-
-
-void massPropertiesShell
-(
-    const pointField& pts,
-    const triFaceList& triFaces,
-    scalar density,
-    scalar& mass,
-    vector& cM,
-    tensor& J
-)
-{
-    // Reset properties for accumulation
-
-    mass = 0.0;
-    cM = vector::zero;
-    J = tensor::zero;
-
-    // Find centre of mass
-
-    forAll(triFaces, i)
-    {
-        const triFace& tri(triFaces[i]);
-
-        triPointRef t
-        (
-            pts[tri[0]],
-            pts[tri[1]],
-            pts[tri[2]]
-        );
-
-        scalar triMag = t.mag();
-
-        cM +=  triMag*t.centre();
-
-        mass += triMag;
-    }
-
-    cM /= mass;
-
-    mass *= density;
-
-    // Find inertia around centre of mass
-
-    forAll(triFaces, i)
-    {
-        const triFace& tri(triFaces[i]);
-
-        J += triPointRef
-        (
-            pts[tri[0]],
-            pts[tri[1]],
-            pts[tri[2]]
-        ).inertia(cM, density);
-    }
-}
-
-
-tensor applyParallelAxisTheorem
-(
-    scalar m,
-    const vector& cM,
-    const tensor& J,
-    const vector& refPt
-)
-{
-    // The displacement vector (refPt = cM) is the displacement of the
-    // new reference point from the centre of mass of the body that
-    // the inertia tensor applies to.
-
-    vector d = (refPt - cM);
-
-    return J + m*((d & d)*I - d*d);
-}
-
-
 int main(int argc, char *argv[])
 {
     argList::addNote
@@ -321,40 +88,17 @@ int main(int argc, char *argv[])
 
     triSurface surf(surfFileName);
 
-    triFaceList faces(surf.size());
-
-    forAll(surf, i)
-    {
-        faces[i] = triFace(surf[i]);
-    }
-
     scalar m = 0.0;
     vector cM = vector::zero;
     tensor J = tensor::zero;
 
     if (args.optionFound("shellProperties"))
     {
-        massPropertiesShell
-        (
-            surf.points(),
-            faces,
-            density,
-            m,
-            cM,
-            J
-        );
+        momentOfInertia::massPropertiesShell(surf, density, m, cM, J);
     }
     else
     {
-        massPropertiesSolid
-        (
-            surf.points(),
-            faces,
-            density,
-            m,
-            cM,
-            J
-        );
+        momentOfInertia::massPropertiesSolid(surf, density, m, cM, J);
     }
 
     if (m < 0)
@@ -583,7 +327,7 @@ int main(int argc, char *argv[])
         showTransform = false;
     }
 
-    Info<< nl << setprecision(10)
+    Info<< nl << setprecision(12)
         << "Density: " << density << nl
         << "Mass: " << m << nl
         << "Centre of mass: " << cM << nl
@@ -615,7 +359,7 @@ int main(int argc, char *argv[])
     if (calcAroundRefPt)
     {
         Info<< nl << "Inertia tensor relative to " << refPt << ": " << nl
-            << applyParallelAxisTheorem(m, cM, J, refPt)
+            << momentOfInertia::applyParallelAxisTheorem(m, cM, J, refPt)
             << endl;
     }
 
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H
index 3e5ee425d6ed9a527dbb067732d07e7b809a9174..3a7513770d756d4b7e9817ec1352d6945c3c7b82 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndices.H
@@ -41,6 +41,7 @@ SourceFiles
 #include "tetPointRef.H"
 #include "triPointRef.H"
 #include "polyMesh.H"
+#include "triFace.H"
 #include "face.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -146,6 +147,10 @@ public:
             //  mesh face for this tet from the supplied mesh
             inline triPointRef faceTri(const polyMesh& mesh) const;
 
+            //- Return the point indices corresponding to the tri on the mesh
+            //  face for this tet from the supplied mesh
+            inline triFace faceTriIs(const polyMesh& mesh) const;
+
             //- Return the geometry corresponding to the tri on the
             //  mesh face for this tet from the supplied mesh using
             //  the old position
diff --git a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H
index 6b8a7871a04c6fbadb9ee3d61bf47215e8b5764c..9a4287b5c4226e20f6f3e155dd4b2cbc306029f9 100644
--- a/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H
+++ b/src/OpenFOAM/meshes/polyMesh/polyMeshTetDecomposition/tetIndicesI.H
@@ -122,6 +122,21 @@ Foam::triPointRef Foam::tetIndices::faceTri(const polyMesh& mesh) const
 }
 
 
+Foam::triFace Foam::tetIndices::faceTriIs(const polyMesh& mesh) const
+{
+    const faceList& pFaces = mesh.faces();
+
+    const Foam::face& f = pFaces[faceI_];
+
+    return triFace
+    (
+        f[faceBasePtI_],
+        f[facePtAI_],
+        f[facePtBI_]
+    );
+}
+
+
 Foam::triPointRef Foam::tetIndices::oldFaceTri(const polyMesh& mesh) const
 {
     const pointField& oldPPts = mesh.oldPoints();
diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files
index 2c9f81195d082b75e3b08a62ede15f2a8ec37d85..47310b27e3ae0f4470c8c73848f2eb1ed47e1734 100644
--- a/src/meshTools/Make/files
+++ b/src/meshTools/Make/files
@@ -127,6 +127,7 @@ $(cellZoneSources)/setToCellZone/setToCellZone.C
 pointZoneSources = sets/pointZoneSources
 $(pointZoneSources)/setToPointZone/setToPointZone.C
 
+momentOfInertia/momentOfInertia.C
 
 surfaceSets/surfaceSets.C
 
diff --git a/src/meshTools/momentOfInertia/momentOfInertia.C b/src/meshTools/momentOfInertia/momentOfInertia.C
index af3265a5ecf9f95f53e3ac404fddea1a9602b3df..8dc1a53d61f4d0d26bcae4615686bc857327691e 100644
--- a/src/meshTools/momentOfInertia/momentOfInertia.C
+++ b/src/meshTools/momentOfInertia/momentOfInertia.C
@@ -21,382 +21,328 @@ License
     You should have received a copy of the GNU General Public License
     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
 
-Class
-    momentOfInertia
+\*---------------------------------------------------------------------------*/
 
-Description
-    Reimplementation of volInt.c by Brian Mirtich.
-        *  mirtich@cs.berkeley.edu                             *
-        *  http://www.cs.berkeley.edu/~mirtich                 *
+#include "momentOfInertia.H"
 
--------------------------------------------------------------------------------
-*/
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
-#include "momentOfInertia.H"
-//#include "pyramidPointFaceRef.H"
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-//Foam::tensor Foam::momentOfInertia
-//(
-//    const pointField& points,
-//    const faceList& faces,
-//    const cell& cFaces,
-//    const point& cc
-//)
-//{
-//    tensor t(tensor::zero);
-//
-//    forAll(cFaces, i)
-//    {
-//        const face& f = faces[cFaces[i]];
-//
-//        scalar pyrVol = pyramidPointFaceRef(f, cc).mag(points);
-//
-//        vector pyrCentre = pyramidPointFaceRef(f, cc).centre(points);
-//
-//        vector d = pyrCentre - cc;
-//
-//        t.xx() += pyrVol*(sqr(d.y()) + sqr(d.z()));
-//        t.yy() += pyrVol*(sqr(d.x()) + sqr(d.z()));
-//        t.zz() += pyrVol*(sqr(d.x()) + sqr(d.y()));
-//
-//        t.xy() -= pyrVol*d.x()*d.y();
-//        t.xz() -= pyrVol*d.x()*d.z();
-//        t.yz() -= pyrVol*d.y()*d.z();
-//    }
-//
-//    // Symmetric
-//    t.yx() = t.xy();
-//    t.zx() = t.xz();
-//    t.zy() = t.yz();
-//
-//    return t;
-//}
-
-
-#define sqr(x) ((x)*(x))
-#define pow3(x) ((x)*(x)*(x))
-
-// compute various integrations over projection of face
-void Foam::compProjectionIntegrals
+void Foam::momentOfInertia::massPropertiesSolid
 (
-    const pointField& points,
-    const face& f,
-    const direction A,
-    const direction B,
-
-    scalar& P1,
-    scalar& Pa,
-    scalar& Pb,
-    scalar& Paa,
-    scalar& Pab,
-    scalar& Pbb,
-    scalar& Paaa,
-    scalar& Paab,
-    scalar& Pabb,
-    scalar& Pbbb
+    const pointField& pts,
+    const triFaceList& triFaces,
+    scalar density,
+    scalar& mass,
+    vector& cM,
+    tensor& J
 )
 {
-    P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
-
-    forAll(f, i)
+    // Reimplemented from: Wm4PolyhedralMassProperties.cpp
+    // File Version: 4.10.0 (2009/11/18)
+
+    // Geometric Tools, LC
+    // Copyright (c) 1998-2010
+    // Distributed under the Boost Software License, Version 1.0.
+    // http://www.boost.org/LICENSE_1_0.txt
+    // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
+
+    // Boost Software License - Version 1.0 - August 17th, 2003
+
+    // Permission is hereby granted, free of charge, to any person or
+    // organization obtaining a copy of the software and accompanying
+    // documentation covered by this license (the "Software") to use,
+    // reproduce, display, distribute, execute, and transmit the
+    // Software, and to prepare derivative works of the Software, and
+    // to permit third-parties to whom the Software is furnished to do
+    // so, all subject to the following:
+
+    // The copyright notices in the Software and this entire
+    // statement, including the above license grant, this restriction
+    // and the following disclaimer, must be included in all copies of
+    // the Software, in whole or in part, and all derivative works of
+    // the Software, unless such copies or derivative works are solely
+    // in the form of machine-executable object code generated by a
+    // source language processor.
+
+    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
+    // NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+    // ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
+    // OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+    // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+    // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+    const scalar r6 = 1.0/6.0;
+    const scalar r24 = 1.0/24.0;
+    const scalar r60 = 1.0/60.0;
+    const scalar r120 = 1.0/120.0;
+
+    // order:  1, x, y, z, x^2, y^2, z^2, xy, yz, zx
+    scalarField integrals(10, 0.0);
+
+    forAll(triFaces, i)
     {
-        scalar a0 = points[f[i]][A];
-        scalar b0 = points[f[i]][B];
-        scalar a1 = points[f[(i+1) % f.size()]][A];
-        scalar b1 = points[f[(i+1) % f.size()]][B];
-        scalar da = a1 - a0;
-        scalar db = b1 - b0;
-
-        scalar a0_2 = a0 * a0;
-        scalar a0_3 = a0_2 * a0;
-        scalar a0_4 = a0_3 * a0;
-
-        scalar b0_2 = b0 * b0;
-        scalar b0_3 = b0_2 * b0;
-        scalar b0_4 = b0_3 * b0;
-
-        scalar a1_2 = a1 * a1;
-        scalar a1_3 = a1_2 * a1;
-
-        scalar b1_2 = b1 * b1;
-        scalar b1_3 = b1_2 * b1;
-
-        scalar C1 = a1 + a0;
-
-        scalar Ca = a1*C1 + a0_2;
-        scalar Caa = a1*Ca + a0_3;
-        scalar Caaa = a1*Caa + a0_4;
-
-        scalar Cb = b1*(b1 + b0) + b0_2;
-        scalar Cbb = b1*Cb + b0_3;
-        scalar Cbbb = b1*Cbb + b0_4;
-
-        scalar Cab = 3*a1_2 + 2*a1*a0 + a0_2;
-        scalar Kab = a1_2 + 2*a1*a0 + 3*a0_2;
-
-        scalar Caab = a0*Cab + 4*a1_3;
-        scalar Kaab = a1*Kab + 4*a0_3;
-
-        scalar Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
-        scalar Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
-
-        P1 += db*C1;
-        Pa += db*Ca;
-        Paa += db*Caa;
-        Paaa += db*Caaa;
-        Pb += da*Cb;
-        Pbb += da*Cbb;
-        Pbbb += da*Cbbb;
-        Pab += db*(b1*Cab + b0*Kab);
-        Paab += db*(b1*Caab + b0*Kaab);
-        Pabb += da*(a1*Cabb + a0*Kabb);
-  }
-
-  P1 /= 2.0;
-  Pa /= 6.0;
-  Paa /= 12.0;
-  Paaa /= 20.0;
-  Pb /= -6.0;
-  Pbb /= -12.0;
-  Pbbb /= -20.0;
-  Pab /= 24.0;
-  Paab /= 60.0;
-  Pabb /= -60.0;
+        const triFace& tri(triFaces[i]);
+
+        // vertices of triangle i
+        vector v0 = pts[tri[0]];
+        vector v1 = pts[tri[1]];
+        vector v2 = pts[tri[2]];
+
+        // cross product of edges
+        vector eA = v1 - v0;
+        vector eB = v2 - v0;
+        vector n = eA ^ eB;
+
+        // compute integral terms
+        scalar tmp0, tmp1, tmp2;
+
+        scalar f1x, f2x, f3x, g0x, g1x, g2x;
+
+        tmp0 = v0.x() + v1.x();
+        f1x = tmp0 + v2.x();
+        tmp1 = v0.x()*v0.x();
+        tmp2 = tmp1 + v1.x()*tmp0;
+        f2x = tmp2 + v2.x()*f1x;
+        f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
+        g0x = f2x + v0.x()*(f1x + v0.x());
+        g1x = f2x + v1.x()*(f1x + v1.x());
+        g2x = f2x + v2.x()*(f1x + v2.x());
+
+        scalar f1y, f2y, f3y, g0y, g1y, g2y;
+
+        tmp0 = v0.y() + v1.y();
+        f1y = tmp0 + v2.y();
+        tmp1 = v0.y()*v0.y();
+        tmp2 = tmp1 + v1.y()*tmp0;
+        f2y = tmp2 + v2.y()*f1y;
+        f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
+        g0y = f2y + v0.y()*(f1y + v0.y());
+        g1y = f2y + v1.y()*(f1y + v1.y());
+        g2y = f2y + v2.y()*(f1y + v2.y());
+
+        scalar f1z, f2z, f3z, g0z, g1z, g2z;
+
+        tmp0 = v0.z() + v1.z();
+        f1z = tmp0 + v2.z();
+        tmp1 = v0.z()*v0.z();
+        tmp2 = tmp1 + v1.z()*tmp0;
+        f2z = tmp2 + v2.z()*f1z;
+        f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
+        g0z = f2z + v0.z()*(f1z + v0.z());
+        g1z = f2z + v1.z()*(f1z + v1.z());
+        g2z = f2z + v2.z()*(f1z + v2.z());
+
+        // update integrals
+        integrals[0] += n.x()*f1x;
+        integrals[1] += n.x()*f2x;
+        integrals[2] += n.y()*f2y;
+        integrals[3] += n.z()*f2z;
+        integrals[4] += n.x()*f3x;
+        integrals[5] += n.y()*f3y;
+        integrals[6] += n.z()*f3z;
+        integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
+        integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
+        integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
+    }
+
+    integrals[0] *= r6;
+    integrals[1] *= r24;
+    integrals[2] *= r24;
+    integrals[3] *= r24;
+    integrals[4] *= r60;
+    integrals[5] *= r60;
+    integrals[6] *= r60;
+    integrals[7] *= r120;
+    integrals[8] *= r120;
+    integrals[9] *= r120;
+
+    // mass
+    mass = integrals[0];
+
+    // center of mass
+    cM = vector(integrals[1], integrals[2], integrals[3])/mass;
+
+    // inertia relative to origin
+    J.xx() = integrals[5] + integrals[6];
+    J.xy() = -integrals[7];
+    J.xz() = -integrals[9];
+    J.yx() = J.xy();
+    J.yy() = integrals[4] + integrals[6];
+    J.yz() = -integrals[8];
+    J.zx() = J.xz();
+    J.zy() = J.yz();
+    J.zz() = integrals[4] + integrals[5];
+
+    // inertia relative to center of mass
+    J -= mass*((cM & cM)*I - cM*cM);
+
+    // Apply density
+    mass *= density;
+    J *= density;
 }
 
 
-void Foam::compFaceIntegrals
+void Foam::momentOfInertia::massPropertiesShell
 (
-    const pointField& points,
-    const face& f,
-    const vector& n,
-    const scalar w,
-    const direction A,
-    const direction B,
-    const direction C,
-
-    scalar& Fa,
-    scalar& Fb,
-    scalar& Fc,
-    scalar& Faa,
-    scalar& Fbb,
-    scalar& Fcc,
-    scalar& Faaa,
-    scalar& Fbbb,
-    scalar& Fccc,
-    scalar& Faab,
-    scalar& Fbbc,
-    scalar& Fcca
+    const pointField& pts,
+    const triFaceList& triFaces,
+    scalar density,
+    scalar& mass,
+    vector& cM,
+    tensor& J
 )
 {
-    scalar P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
+    // Reset properties for accumulation
 
-    compProjectionIntegrals
-    (
-        points,
-        f,
-        A,
-        B,
-
-        P1,
-        Pa,
-        Pb,
-        Paa,
-        Pab,
-        Pbb,
-        Paaa,
-        Paab,
-        Pabb,
-        Pbbb
-    );
+    mass = 0.0;
+    cM = vector::zero;
+    J = tensor::zero;
 
-    scalar k1 = 1 / n[C];
-    scalar k2 = k1 * k1;
-    scalar k3 = k2 * k1;
-    scalar k4 = k3 * k1;
-
-    Fa = k1 * Pa;
-    Fb = k1 * Pb;
-    Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
-
-    Faa = k1 * Paa;
-    Fbb = k1 * Pbb;
-    Fcc = k3 * (sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb
-         + w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
-
-    Faaa = k1 * Paaa;
-    Fbbb = k1 * Pbbb;
-    Fccc = -k4 * (pow3(n[A])*Paaa + 3*sqr(n[A])*n[B]*Paab
-           + 3*n[A]*sqr(n[B])*Pabb + pow3(n[B])*Pbbb
-           + 3*w*(sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb)
-           + w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
-
-    Faab = k1 * Paab;
-    Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
-    Fcca = k3 * (sqr(n[A])*Paaa + 2*n[A]*n[B]*Paab + sqr(n[B])*Pabb
-         + w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
-}
+    // Find centre of mass
 
+    forAll(triFaces, i)
+    {
+        const triFace& tri(triFaces[i]);
 
-void Foam::compVolumeIntegrals
-(
-    const pointField& points,
-    const faceList& faces,
-    const cell& cFaces,
-    const vectorField& fNorm,
-    const scalarField& fW,
-
-    scalar& T0,
-    vector& T1,
-    vector& T2,
-    vector& TP
-)
-{
-    T0 = 0;
-    T1 = vector::zero;
-    T2 = vector::zero;
-    TP = vector::zero;
+        triPointRef t
+        (
+            pts[tri[0]],
+            pts[tri[1]],
+            pts[tri[2]]
+        );
 
-    forAll(cFaces, i)
-    {
-        const vector& n = fNorm[i];
+        scalar triMag = t.mag();
 
-        scalar nx = mag(n[0]);
-        scalar ny = mag(n[1]);
-        scalar nz = mag(n[2]);
+        cM +=  triMag*t.centre();
 
-        direction A, B, C;
+        mass += triMag;
+    }
 
-        if (nx > ny && nx > nz)
-        {
-            C = 0;
-        }
-        else
-        {
-            C = (ny > nz) ? 1 : 2;
-        }
+    cM /= mass;
 
-        A = (C + 1) % 3;
-        B = (A + 1) % 3;
+    mass *= density;
 
-        scalar Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
-        compFaceIntegrals
-        (
-            points,
-            faces[cFaces[i]],
-            n,
-            fW[i],
-            A,
-            B,
-            C,
-
-            Fa,
-            Fb,
-            Fc,
-            Faa,
-            Fbb,
-            Fcc,
-            Faaa,
-            Fbbb,
-            Fccc,
-            Faab,
-            Fbbc,
-            Fcca
-        );
+    // Find inertia around centre of mass
 
-        T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
+    forAll(triFaces, i)
+    {
+        const triFace& tri(triFaces[i]);
+
+        J += triPointRef
+        (
+            pts[tri[0]],
+            pts[tri[1]],
+            pts[tri[2]]
+        ).inertia(cM, density);
+    }
+}
 
-        T1[A] += n[A] * Faa;
-        T1[B] += n[B] * Fbb;
-        T1[C] += n[C] * Fcc;
 
-        T2[A] += n[A] * Faaa;
-        T2[B] += n[B] * Fbbb;
-        T2[C] += n[C] * Fccc;
+void Foam::momentOfInertia::massPropertiesSolid
+(
+    const triSurface& surf,
+    scalar density,
+    scalar& mass,
+    vector& cM,
+    tensor& J
+)
+{
+    triFaceList faces(surf.size());
 
-        TP[A] += n[A] * Faab;
-        TP[B] += n[B] * Fbbc;
-        TP[C] += n[C] * Fcca;
+    forAll(surf, i)
+    {
+        faces[i] = triFace(surf[i]);
     }
 
-    T1 /= 2;
-    T2 /= 3;
-    TP /= 2;
+    massPropertiesSolid(surf.points(), faces, density, mass, cM, J);
 }
 
 
-// Calculate
-// - r: centre of mass
-// - J: inertia around origin (point 0,0,0)
-void Foam::momentOfIntertia
+void Foam::momentOfInertia::massPropertiesShell
 (
-    const pointField& points,
-    const faceList& faces,
-    const cell& cFaces,
-    point& r,
+    const triSurface& surf,
+    scalar density,
+    scalar& mass,
+    vector& cM,
     tensor& J
 )
 {
-    // Face normals
-    vectorField fNorm(cFaces.size());
-    scalarField fW(cFaces.size());
+    triFaceList faces(surf.size());
 
-    forAll(cFaces, i)
+    forAll(surf, i)
     {
-        label faceI = cFaces[i];
+        faces[i] = triFace(surf[i]);
+    }
+
+    massPropertiesShell(surf.points(), faces, density, mass, cM, J);
+}
 
-        const face& f = faces[faceI];
 
-        fNorm[i] = f.normal(points);
-        fNorm[i] /= mag(fNorm[i]) + VSMALL;
+Foam::tensor Foam::momentOfInertia::applyParallelAxisTheorem
+(
+    scalar mass,
+    const vector& cM,
+    const tensor& J,
+    const vector& refPt
+)
+{
+    // The displacement vector (refPt = cM) is the displacement of the
+    // new reference point from the centre of mass of the body that
+    // the inertia tensor applies to.
+
+    vector d = (refPt - cM);
+
+    return J + mass*((d & d)*I - d*d);
+}
+
 
-        fW[i] = - (fNorm[i] & points[f[0]]);
+Foam::tmp<Foam::tensorField> Foam::momentOfInertia::meshInertia
+(
+    const polyMesh& mesh
+)
+{
+    tmp<tensorField> tTf = tmp<tensorField>(new tensorField(mesh.nCells()));
+
+    tensorField& tf = tTf();
+
+    forAll(tf, cI)
+    {
+        tf[cI] = meshInertia(mesh, cI);
     }
 
+    return tTf;
+}
 
-    scalar T0;
-    vector T1, T2, TP;
 
-    compVolumeIntegrals
+Foam::tensor Foam::momentOfInertia::meshInertia
+(
+    const polyMesh& mesh,
+    label cellI
+)
+{
+    List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices
     (
-        points,
-        faces,
-        cFaces,
-        fNorm,
-        fW,
-
-        T0,
-        T1,
-        T2,
-        TP
+        mesh,
+        cellI
     );
 
-    const scalar density = 1.0;  /* assume unit density */
+    triFaceList faces(cellTets.size());
 
-    scalar mass = density * T0;
+    forAll(cellTets, cTI)
+    {
+        faces[cTI] = cellTets[cTI].faceTriIs(mesh);
+    }
 
-    /* compute center of mass */
-    r = T1 / T0;
+    scalar m = 0.0;
+    vector cM = vector::zero;
+    tensor J = tensor::zero;
 
-    /* compute inertia tensor */
-    J.xx() = density * (T2[1] + T2[2]);
-    J.yy() = density * (T2[2] + T2[0]);
-    J.zz() = density * (T2[0] + T2[1]);
-    J.xy() = J.yx() = - density * TP[0];
-    J.yz() = J.zy() = - density * TP[1];
-    J.zx() = J.xz() = - density * TP[2];
+    massPropertiesSolid(mesh.points(), faces, 1.0, m, cM, J);
 
-    ///* translate inertia tensor to center of mass */
-    //J[XX] -= mass * (r[1]*r[1] + r[2]*r[2]);
-    //J[YY] -= mass * (r[2]*r[2] + r[0]*r[0]);
-    //J[ZZ] -= mass * (r[0]*r[0] + r[1]*r[1]);
-    //J[XY] = J[YX] += mass * r[0] * r[1];
-    //J[YZ] = J[ZY] += mass * r[1] * r[2];
-    //J[ZX] = J[XZ] += mass * r[2] * r[0];
+    return J;
 }
 
 
-
 // ************************************************************************* //
diff --git a/src/meshTools/momentOfInertia/momentOfInertia.H b/src/meshTools/momentOfInertia/momentOfInertia.H
index 8ff6209f0b18adc821b0657108b0c86717c6e675..bb5ffef6a8fb0968ae8ef954eba515a66bf57d4f 100644
--- a/src/meshTools/momentOfInertia/momentOfInertia.H
+++ b/src/meshTools/momentOfInertia/momentOfInertia.H
@@ -25,6 +25,9 @@ Class
     momentOfInertia
 
 Description
+    Calculates the inertia tensor and principal axes and moments of a
+    polyhedra/cells/triSurfaces.  Inertia can either be of the solid body or
+    of a thin shell.
 
 SourceFiles
     momentOfInertia.H
@@ -34,34 +37,86 @@ SourceFiles
 #ifndef momentOfInertia_H
 #define momentOfInertia_H
 
-#include "tensor.H"
-#include "primitiveMesh.H"
+#include "tetPointRef.H"
+#include "triFaceList.H"
+#include "triSurface.H"
+#include "polyMesh.H"
+#include "polyMeshTetDecomposition.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
 {
 
-////- Moment of inertia around cell centre for single cell.
-//tensor momentOfInertia
-//(
-//    const pointField&,
-//    const faceList&,
-//    const cell&,
-//    const point& cc
-//);
-
-// Calculate
-// - centre of mass
-// - inertia tensor around (0,0,0)
-void momentOfIntertia
-(
-    const pointField&,
-    const faceList&,
-    const cell&,
-    point& r,
-    tensor& Jorigin
-);
+/*---------------------------------------------------------------------------*\
+                     Class momentOfInertia Declaration
+\*---------------------------------------------------------------------------*/
+
+class momentOfInertia
+{
+
+public:
+
+    static void massPropertiesSolid
+    (
+        const pointField& pts,
+        const triFaceList& triFaces,
+        scalar density,
+        scalar& mass,
+        vector& cM,
+        tensor& J
+    );
+
+    static void massPropertiesShell
+    (
+        const pointField& pts,
+        const triFaceList& triFaces,
+        scalar density,
+        scalar& mass,
+        vector& cM,
+        tensor& J
+    );
+
+    static void massPropertiesSolid
+    (
+        const triSurface& surf,
+        scalar density,
+        scalar& mass,
+        vector& cM,
+        tensor& J
+    );
+
+    static void massPropertiesShell
+    (
+        const triSurface& surf,
+        scalar density,
+        scalar& mass,
+        vector& cM,
+        tensor& J
+    );
+
+    static tensor applyParallelAxisTheorem
+    (
+        scalar mass,
+        const vector& cM,
+        const tensor& J,
+        const vector& refPt
+    );
+
+    // Calculate the inertia tensor for all cells in the mesh
+    static tmp<tensorField> meshInertia
+    (
+        const polyMesh& mesh
+    );
+
+    // Calculate the inertia tensor the given cell
+    static tensor meshInertia
+    (
+        const polyMesh& mesh,
+        label cellI
+    );
+};
+
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //