void Foam::quadraticFitSnGradData::findFaceDirs
(
    vector& idir,        // value changed in return
    vector& jdir,        // value changed in return
    vector& kdir,        // value changed in return
    const fvMesh& mesh,
    const label faci
)
{
    idir = mesh.Sf()[faci];
    idir /= mag(idir);

    #ifndef SPHERICAL_GEOMETRY
        if (mesh.nGeometricD() <= 2) // find the normal direcion
        {
            if (mesh.geometricD()[0] == -1)
            {
                kdir = vector(1, 0, 0);
            }
            else if (mesh.geometricD()[1] == -1)
            {
                kdir = vector(0, 1, 0);
            }
            else
            {
                kdir = vector(0, 0, 1);
            }
        }
        else // 3D so find a direction in the plane of the face
        {
            const face& f = mesh.faces()[faci];
            kdir = mesh.points()[f[0]] - mesh.points()[f[1]];
        }
    #else
        // Spherical geometry so kdir is the radial direction
        kdir = mesh.Cf()[faci];
    #endif

    if (mesh.nGeometricD() == 3)
    {
        // Remove the idir component from kdir and normalise
        kdir -= (idir & kdir)*idir;

        scalar magk = mag(kdir);

        if (magk < SMALL)
        {
            FatalErrorIn("findFaceDirs") << " calculated kdir = zero"
                << exit(FatalError);
        }
        else
        {
            kdir /= magk;
        }
    }

    jdir = kdir ^ idir;
}
void Foam::vtkFoam::addInternalMesh
(
    const fvMesh& mesh,
    vtkUnstructuredGrid* vtkMesh
)
{
    SetName(vtkMesh, "Internal Mesh");

    // Number of additional points needed by the decomposition of polyhedra
    label nAddPoints = 0;

    // Number of additional cells generated by the decomposition of polyhedra
    label nAddCells = 0;

    const cellModel& tet = *(cellModeller::lookup("tet"));
    const cellModel& pyr = *(cellModeller::lookup("pyr"));
    const cellModel& prism = *(cellModeller::lookup("prism"));
    const cellModel& wedge = *(cellModeller::lookup("wedge"));
    const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
    const cellModel& hex = *(cellModeller::lookup("hex"));

    // Scan for cells which need to be decomposed and count additional points
    // and cells
    if (debug)
    {
        Info<< "building cell-shapes" << endl;
    }
    const cellShapeList& cellShapes = mesh.cellShapes();

    if (debug)
    {
        Info<< "scanning" << endl;
    }

    forAll(cellShapes, cellI)
    {
        const cellModel& model = cellShapes[cellI].model();

        if
        (
            model != hex
         && model != wedge
         && model != prism
         && model != pyr
         && model != tet
         && model != tetWedge
        )
        {
            const cell& cFaces = mesh.cells()[cellI];

            forAll(cFaces, cFaceI)
            {
                const face& f = mesh.faces()[cFaces[cFaceI]];

                label nFacePoints = f.size();

                label nQuads = (nFacePoints - 2)/2;
                label nTris = (nFacePoints - 2)%2;
                nAddCells += nQuads + nTris;
            }

            nAddCells--;
            nAddPoints++;
        }
    }

    // Set size of additional point addressing array
    // (from added point to original cell)
    addPointCellLabels_.setSize(nAddPoints);

    // Set size of additional cells mapping array
    // (from added cell to original cell)
    superCells_.setSize(mesh.nCells() + nAddCells);

    if (debug)
    {
        Info<< "converting points" << endl;
    }

    // Convert Foam mesh vertices to VTK
    vtkPoints *vtkpoints = vtkPoints::New();
    vtkpoints->Allocate(mesh.nPoints() + nAddPoints);

    const Foam::pointField& points = mesh.points();

    forAll(points, i)
    {
        vtkFoamInsertNextPoint(vtkpoints, points[i]);
    }