bool Foam::foamyHexMeshChecks::closePoints
(
    Cell& c,
    const scalar tol
)
{
    for (label v = 0; v < 4; ++v)
    {
        for (label vA = v + 1; vA < 4; ++vA)
        {
            if
            (
                mag
                (
                    topoint(c->vertex(v)->point())
                  - topoint(c->vertex(vA)->point())
                )
              < tol
            )
            {
                return true;
            }
        }
    }

    return false;
}
void Foam::cellShapeControlMesh::barycentricCoords
(
    const Foam::point& pt,
    barycentric& bary,
    Cell_handle& ch
) const
{
    // Use the previous cell handle as a hint on where to start searching
    // Giving a hint causes strange errors...
    ch = locate(toPoint(pt));

    if (dimension() > 2 && !is_infinite(ch))
    {
        oldCellHandle_ = ch;

        tetPointRef tet
        (
            topoint(ch->vertex(0)->point()),
            topoint(ch->vertex(1)->point()),
            topoint(ch->vertex(2)->point()),
            topoint(ch->vertex(3)->point())
        );

        bary = tet.pointToBarycentric(pt);
    }
}
void Foam::cellShapeControlMesh::writeTriangulation()
{
    OFstream str
    (
        "refinementTriangulation_"
      + name(Pstream::myProcNo())
      + ".obj"
    );

    label count = 0;

    Info<< "Write refinementTriangulation" << endl;

    for
    (
        CellSizeDelaunay::Finite_edges_iterator e = finite_edges_begin();
        e != finite_edges_end();
        ++e
    )
    {
        Cell_handle c = e->first;
        Vertex_handle vA = c->vertex(e->second);
        Vertex_handle vB = c->vertex(e->third);

        // Don't write far edges
        if (vA->farPoint() || vB->farPoint())
        {
            continue;
        }

        // Don't write unowned edges
        if (vA->referred() && vB->referred())
        {
            continue;
        }

        pointFromPoint p1 = topoint(vA->point());
        pointFromPoint p2 = topoint(vB->point());

        meshTools::writeOBJ(str, p1, p2, count);
    }

    if (is_valid())
    {
        Info<< "    Triangulation is valid" << endl;
    }
    else
    {
        FatalErrorIn
        (
            "Foam::triangulatedMesh::writeRefinementTriangulation()"
        )   << "Triangulation is not valid"
            << abort(FatalError);
    }
}
void Foam::DelaunayMeshTools::writeFixedPoints
(
    const fileName& fName,
    const Triangulation& t
)
{
    OFstream str(fName);

    Pout<< nl
        << "Writing fixed points to " << str.name() << endl;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->fixed())
        {
            meshTools::writeOBJ(str, topoint(vit->point()));
        }
    }
}
void Foam::DelaunayMeshTools::drawDelaunayCell
(
    Ostream& os,
    const CellHandle& c,
    label offset
)
{
    // Supply offset as tet number
    offset *= 4;

    os  << "# cell index: " << label(c->cellIndex())
        << " INT_MIN = " << INT_MIN
        << endl;

    os  << "# circumradius "
        << mag(c->dual() - topoint(c->vertex(0)->point()))
        << endl;

    for (int i = 0; i < 4; i++)
    {
        os  << "# index / type / procIndex: "
            << label(c->vertex(i)->index()) << " "
            << label(c->vertex(i)->type()) << " "
            << label(c->vertex(i)->procIndex())
            <<
                (
                    CGAL::indexedVertexOps::uninitialised(c->vertex(i))
                  ? " # This vertex is uninitialised!"
                  : ""
                )
            << endl;

        meshTools::writeOBJ(os, topoint(c->vertex(i)->point()));
    }

    os  << "f " << 1 + offset << " " << 3 + offset << " " << 2 + offset << nl
        << "f " << 2 + offset << " " << 3 + offset << " " << 4 + offset << nl
        << "f " << 1 + offset << " " << 4 + offset << " " << 3 + offset << nl
        << "f " << 1 + offset << " " << 2 + offset << " " << 4 + offset << endl;

//    os  << "# cicumcentre " << endl;

//    meshTools::writeOBJ(os, c->dual());

//    os  << "l " << 1 + offset << " " << 5 + offset << endl;
}
Foam::scalar Foam::foamyHexMeshChecks::coplanarTet
(
    Cell& c,
    const scalar tol
)
{
    tetPointRef tet
    (
        topoint(c->vertex(0)->point()),
        topoint(c->vertex(1)->point()),
        topoint(c->vertex(2)->point()),
        topoint(c->vertex(3)->point())
    );

    const scalar quality = tet.quality();

    if (quality < tol)
    {
        return quality;
    }

    return 0;

//    plane triPlane
//    (
//        topoint(c->vertex(0)->point()),
//        topoint(c->vertex(1)->point()),
//        topoint(c->vertex(2)->point())
//    );
//
//    const scalar distance = triPlane.distance(topoint(c->vertex(3)->point()));
//
//    // Check if the four points are roughly coplanar. If they are then we
//    // cannot calculate the circumcentre. Better test might be the volume
//    // of the tet.
//    if (distance < tol)
//    {
//        return 0;
//    }
//
//    return distance;
}
Foam::labelList Foam::backgroundMeshDecomposition::processorPosition
(
    const List<PointType>& pts
) const
{
    DynamicList<label> toCandidateProc;
    DynamicList<point> testPoints;
    labelList ptBlockStart(pts.size(), -1);
    labelList ptBlockSize(pts.size(), -1);

    label nTotalCandidates = 0;

    forAll(pts, pI)
    {
        const pointFromPoint pt = topoint(pts[pI]);

        label nCandidates = 0;

        forAll(allBackgroundMeshBounds_, procI)
        {
            if (allBackgroundMeshBounds_[procI].contains(pt))
            {
                toCandidateProc.append(procI);
                testPoints.append(pt);

                nCandidates++;
            }
        }

        ptBlockStart[pI] = nTotalCandidates;
        ptBlockSize[pI] = nCandidates;

        nTotalCandidates += nCandidates;
    }

    // Needed for reverseDistribute
    label preDistributionToCandidateProcSize = toCandidateProc.size();

    autoPtr<mapDistribute> map(buildMap(toCandidateProc));

    map().distribute(testPoints);

    List<bool> pointOnCandidate(testPoints.size(), false);

    // Test candidate points on candidate processors
    forAll(testPoints, tPI)
    {
        pointOnCandidate[tPI] = positionOnThisProcessor(testPoints[tPI]);
    }
void Foam::DelaunayMeshTools::writeInternalDelaunayVertices
(
    const fileName& instance,
    const Triangulation& t
)
{
    pointField internalDelaunayVertices(t.number_of_vertices());

    label vertI = 0;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->internalPoint())
        {
            internalDelaunayVertices[vertI++] = topoint(vit->point());
        }
    }

    internalDelaunayVertices.setSize(vertI);

    pointIOField internalDVs
    (
        IOobject
        (
            "internalDelaunayVertices",
            instance,
            t.time(),
            IOobject::NO_READ,
            IOobject::AUTO_WRITE
        ),
        internalDelaunayVertices
    );

    Info<< nl
        << "Writing " << internalDVs.name()
        << " to " << internalDVs.instance()
        << endl;

    internalDVs.write();
}
void Foam::conformalVoronoiMesh::cellSizeMeshOverlapsBackground() const
{
    const cellShapeControlMesh& cellSizeMesh =
        cellShapeControl_.shapeControlMesh();

    DynamicList<Foam::point> pts(number_of_vertices());

    for
    (
        Delaunay::Finite_vertices_iterator vit = finite_vertices_begin();
        vit != finite_vertices_end();
        ++vit
    )
    {
        if (vit->internalOrBoundaryPoint() && !vit->referred())
        {
            pts.append(topoint(vit->point()));
        }
    }

    boundBox bb(pts);

    boundBox cellSizeMeshBb = cellSizeMesh.bounds();

    bool fullyContained = true;

    if (!cellSizeMeshBb.contains(bb))
    {
        Pout<< "Triangulation not fully contained in cell size mesh."
            << endl;

        Pout<< "Cell Size Mesh Bounds = " << cellSizeMesh.bounds() << endl;
        Pout<< "foamyHexMesh Bounds         = " << bb << endl;

        fullyContained = false;
    }

    reduce(fullyContained, andOp<unsigned int>());

    Info<< "Triangulation is "
        << (fullyContained ? "fully" : "not fully")
        << " contained in the cell size mesh"
        << endl;
}
void Foam::DelaunayMeshTools::writeOBJ
(
    const fileName& fName,
    const Triangulation& t,
    const indexedVertexEnum::vertexType startPointType,
    const indexedVertexEnum::vertexType endPointType
)
{
    OFstream str(fName);

    Pout<< nl
        << "Writing points of types:" << nl;

    forAllConstIter
    (
        HashTable<int>,
        indexedVertexEnum::vertexTypeNames_,
        iter
    )
    {
        if (iter() >= startPointType && iter() <= endPointType)
        {
            Pout<< "    " << iter.key() << nl;
        }
    }

    Pout<< "to " << str.name() << endl;

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->type() >= startPointType && vit->type() <= endPointType)
        {
            meshTools::writeOBJ(str, topoint(vit->point()));
        }
    }
}
Foam::boundBox Foam::cellShapeControlMesh::bounds() const
{
    DynamicList<Foam::point> pts(number_of_vertices());

    for
    (
        Finite_vertices_iterator vit = finite_vertices_begin();
        vit != finite_vertices_end();
        ++vit
    )
    {
        if (vit->real())
        {
            pts.append(topoint(vit->point()));
        }
    }

    boundBox bb(pts);

    return bb;
}
Foam::tmp<Foam::pointField> Foam::cellShapeControlMesh::cellCentres() const
{
    tmp<pointField> tcellCentres(new pointField(number_of_finite_cells()));
    pointField& cellCentres = tcellCentres.ref();

    label count = 0;
    for
    (
        CellSizeDelaunay::Finite_cells_iterator c = finite_cells_begin();
        c != finite_cells_end();
        ++c
    )
    {
        if (c->hasFarPoint())
        {
            continue;
        }

        scalarList bary;
        cellShapeControlMesh::Cell_handle ch;

        const Foam::point centre = topoint
        (
            CGAL::centroid<baseK>
            (
                c->vertex(0)->point(),
                c->vertex(1)->point(),
                c->vertex(2)->point(),
                c->vertex(3)->point()
            )
        );

        cellCentres[count++] = centre;
    }

    cellCentres.resize(count);

    return tcellCentres;
}
void Foam::conformalVoronoiMesh::insertInternalPoints
(
    List<Point>& points,
    bool distribute
)
{
    label nPoints = points.size();

    if (Pstream::parRun())
    {
        reduce(nPoints, sumOp<label>());
    }

    Info<< "    " << nPoints << " points to insert..." << endl;

    if (Pstream::parRun() && distribute)
    {
        List<Foam::point> transferPoints(points.size());

        forAll(points, pI)
        {
            transferPoints[pI] = topoint(points[pI]);
        }
Foam::tmp<Foam::pointField> Foam::DelaunayMeshTools::allPoints
(
    const Triangulation& t
)
{
    tmp<pointField> tpts(new pointField(t.vertexCount(), point::max));
    pointField& pts = tpts.ref();

    for
    (
        typename Triangulation::Finite_vertices_iterator vit =
            t.finite_vertices_begin();
        vit != t.finite_vertices_end();
        ++vit
    )
    {
        if (vit->internalOrBoundaryPoint() && !vit->referred())
        {
            pts[vit->index()] = topoint(vit->point());
        }
    }

    return tpts;
}
    forAll(pts, pI)
    {
        // Extract the sub list of results for this point

        SubList<bool> ptProcResults
        (
            pointOnCandidate,
            ptBlockSize[pI],
            ptBlockStart[pI]
        );

        forAll(ptProcResults, pPRI)
        {
            if (ptProcResults[pPRI])
            {
                ptProc[pI] = toCandidateProc[ptBlockStart[pI] + pPRI];

                break;
            }
        }

        if (ptProc[pI] < 0)
        {
            const pointFromPoint pt = topoint(pts[pI]);

            if (!globalBackgroundBounds_.contains(pt))
            {
                FatalErrorIn
                (
                    "Foam::labelList"
                    "Foam::backgroundMeshDecomposition::processorPosition"
                    "("
                        "const List<point>&"
                    ") const"
                )
                    << "The position " << pt
                    << " is not in any part of the background mesh "
                    << globalBackgroundBounds_ << endl
                    << "A background mesh with a wider margin around "
                    << "the geometry may help."
                    << exit(FatalError);
            }

            if (debug)
            {
                WarningIn
                (
                    "Foam::labelList"
                    "Foam::backgroundMeshDecomposition::processorPosition"
                    "("
                        "const List<point>&"
                    ") const"
                )   << "The position " << pt
                    << " was not found in the background mesh "
                    << globalBackgroundBounds_ << ", finding nearest."
                    << endl;
            }

            failedPointIndices.append(pI);
            failedPoints.append(pt);
        }
    }
void Foam::cellShapeControlMesh::distribute
(
    const backgroundMeshDecomposition& decomposition
)
{
    DynamicList<Foam::point> points(number_of_vertices());
    DynamicList<scalar> sizes(number_of_vertices());
    DynamicList<tensor> alignments(number_of_vertices());

    DynamicList<Vb> farPts(8);

    for
    (
        Finite_vertices_iterator vit = finite_vertices_begin();
        vit != finite_vertices_end();
        ++vit
    )
    {
        if (vit->real())
        {
            points.append(topoint(vit->point()));
            sizes.append(vit->targetCellSize());
            alignments.append(vit->alignment());
        }
        else if (vit->farPoint())
        {
            farPts.append
            (
                Vb
                (
                    vit->point(),
                    -1,
                    Vb::vtFar,
                    Pstream::myProcNo()
                )
            );

            farPts.last().targetCellSize() = vit->targetCellSize();
            farPts.last().alignment() = vit->alignment();
        }
    }

    autoPtr<mapDistribute> mapDist =
        DistributedDelaunayMesh<CellSizeDelaunay>::distribute
        (
            decomposition,
            points
        );

    mapDist().distribute(sizes);
    mapDist().distribute(alignments);

    // Reset the entire tessellation
    DelaunayMesh<CellSizeDelaunay>::reset();


    // Internal points have to be inserted first
    DynamicList<Vb> verticesToInsert(points.size());


    forAll(farPts, ptI)
    {
        verticesToInsert.append(farPts[ptI]);
    }
void Foam::controlMeshRefinement::initialMeshPopulation
(
    const autoPtr<backgroundMeshDecomposition>& decomposition
)
{
    if (shapeController_.shapeControlMesh().vertexCount() > 0)
    {
        // Mesh already populated.
        Info<< "Cell size and alignment mesh already populated." << endl;
        return;
    }

    autoPtr<boundBox> overallBoundBox;

    // Need to pass in the background mesh decomposition so that can test if
    // a point to insert is on the processor.
    if (Pstream::parRun())
    {
//        overallBoundBox.set(new boundBox(decomposition().procBounds()));
    }
    else
    {
//        overallBoundBox.set
//        (
//            new boundBox(geometryToConformTo_.geometry().bounds())
//        );
//
//        mesh_.insertBoundingPoints
//        (
//            overallBoundBox(),
//            sizeControls_
//        );
    }

    Map<label> priorityMap;

    const PtrList<cellSizeAndAlignmentControl>& controlFunctions =
        sizeControls_.controlFunctions();

    forAll(controlFunctions, fI)
    {
        const cellSizeAndAlignmentControl& controlFunction =
            controlFunctions[fI];

        const Switch& forceInsertion =
            controlFunction.forceInitialPointInsertion();

        Info<< "Inserting points from " << controlFunction.name()
            << " (" << controlFunction.type() << ")" << endl;
        Info<< "    Force insertion is " << forceInsertion.asText() << endl;

        pointField pts;
        scalarField sizes;
        triadField alignments;

        controlFunction.initialVertices(pts, sizes, alignments);

        Info<< "    Got initial vertices list of size " << pts.size() << endl;

        List<Vb> vertices(pts.size());

        // Clip the minimum size
        for (label vI = 0; vI < pts.size(); ++vI)
        {
            vertices[vI] = Vb(pts[vI], Vb::vtInternalNearBoundary);

            label maxPriority = -1;
            scalar size = sizeControls_.cellSize(pts[vI], maxPriority);

            if (maxPriority > controlFunction.maxPriority())
            {
                vertices[vI].targetCellSize() = max
                (
                    size,
                    shapeController_.minimumCellSize()
                );
            }
//            else if (maxPriority == controlFunction.maxPriority())
//            {
//                vertices[vI].targetCellSize() = max
//                (
//                    min(sizes[vI], size),
//                    shapeController_.minimumCellSize()
//                );
//            }
            else
            {
                vertices[vI].targetCellSize() = max
                (
                    sizes[vI],
                    shapeController_.minimumCellSize()
                );
            }

            vertices[vI].alignment() = alignments[vI];
        }

        Info<< "    Clipped minimum size" << endl;

        pts.clear();
        sizes.clear();
        alignments.clear();

        PackedBoolList keepVertex(vertices.size(), true);

        forAll(vertices, vI)
        {
            bool keep = true;

            pointFromPoint pt = topoint(vertices[vI].point());

            if (Pstream::parRun())
            {
                keep = decomposition().positionOnThisProcessor(pt);
            }

            if (keep && geometryToConformTo_.wellOutside(pt, SMALL))
            {
                keep = false;
            }

            if (!keep)
            {
                keepVertex[vI] = false;
            }
        }

        inplaceSubset(keepVertex, vertices);

        const label preInsertedSize = mesh_.number_of_vertices();

        Info<< "    Check sizes" << endl;

        forAll(vertices, vI)
        {
            bool insertPoint = false;

            pointFromPoint pt(topoint(vertices[vI].point()));

            if
            (
                mesh_.dimension() < 3
             || mesh_.is_infinite
                (
                    mesh_.locate(vertices[vI].point())
                )
            )
            {
                insertPoint = true;
            }

            const scalar interpolatedCellSize = shapeController_.cellSize(pt);
            const triad interpolatedAlignment =
                shapeController_.cellAlignment(pt);
            const scalar calculatedCellSize = vertices[vI].targetCellSize();
            const triad calculatedAlignment = vertices[vI].alignment();

            if (debug)
            {
                Info<< "Point = " << pt << nl
                    << "  Size(interp) = " << interpolatedCellSize << nl
                    << "    Size(calc) = " << calculatedCellSize << nl
                    << " Align(interp) = " << interpolatedAlignment << nl
                    << "   Align(calc) = " << calculatedAlignment << nl
                    << endl;
            }

            const scalar sizeDiff =
                mag(interpolatedCellSize - calculatedCellSize);
            const scalar alignmentDiff =
                diff(interpolatedAlignment, calculatedAlignment);

            if (debug)
            {
                Info<< "    size difference = " << sizeDiff << nl
                    << ", alignment difference = " << alignmentDiff << endl;
            }

            // @todo Also need to base it on the alignments
            if
            (
                sizeDiff/interpolatedCellSize > 0.1
             || alignmentDiff > 0.15
            )
            {
                insertPoint = true;
            }

            if (forceInsertion || insertPoint)
            {
                const label oldSize = mesh_.vertexCount();

                cellShapeControlMesh::Vertex_handle insertedVert = mesh_.insert
                (
                    pt,
                    calculatedCellSize,
                    vertices[vI].alignment(),
                    Vb::vtInternalNearBoundary
                );

                if (oldSize == mesh_.vertexCount() - 1)
                {
                    priorityMap.insert
                    (
                        insertedVert->index(),
                        controlFunction.maxPriority()
                    );
                }
            }
        }
bool Foam::conformalVoronoiMesh::distributeBackground(const Triangulation& mesh)
{
    if (!Pstream::parRun())
    {
        return false;
    }

    Info<< nl << "Redistributing points" << endl;

    timeCheck("Before distribute");

    label iteration = 0;

    scalar previousLoadUnbalance = 0;

    while (true)
    {
        scalar maxLoadUnbalance = mesh.calculateLoadUnbalance();

        if
        (
            maxLoadUnbalance <= foamyHexMeshControls().maxLoadUnbalance()
         || maxLoadUnbalance <= previousLoadUnbalance
        )
        {
            // If this is the first iteration, return false, if it was a
            // subsequent one, return true;
            return iteration != 0;
        }

        previousLoadUnbalance = maxLoadUnbalance;

        Info<< "    Total number of vertices before redistribution "
            << returnReduce(label(mesh.number_of_vertices()), sumOp<label>())
            << endl;

        const fvMesh& bMesh = decomposition_().mesh();

        volScalarField cellWeights
        (
            IOobject
            (
                "cellWeights",
                bMesh.time().timeName(),
                bMesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            ),
            bMesh,
            dimensionedScalar("weight", dimless, 1e-2),
            zeroGradientFvPatchScalarField::typeName
        );

        meshSearch cellSearch(bMesh, polyMesh::FACE_PLANES);

        labelList cellVertices(bMesh.nCells(), label(0));

        for
        (
            typename Triangulation::Finite_vertices_iterator vit
                = mesh.finite_vertices_begin();
            vit != mesh.finite_vertices_end();
            ++vit
        )
        {
            // Only store real vertices that are not feature vertices
            if (vit->real() && !vit->featurePoint())
            {
                pointFromPoint v = topoint(vit->point());

                label cellI = cellSearch.findCell(v);

                if (cellI == -1)
                {
//                     Pout<< "findCell conformalVoronoiMesh::distribute "
//                         << "findCell "
//                         << vit->type() << " "
//                         << vit->index() << " "
//                         << v << " "
//                         << cellI
//                         << " find nearest cellI ";

                    cellI = cellSearch.findNearestCell(v);
                }

                cellVertices[cellI]++;
            }
        }

        forAll(cellVertices, cI)
        {
            // Give a small but finite weight for empty cells.  Some
            // decomposition methods have difficulty with integer overflows in
            // the sum of the normalised weight field.
            cellWeights.internalField()[cI] = max
            (
                cellVertices[cI],
                1e-2
            );
        }

        autoPtr<mapDistributePolyMesh> mapDist = decomposition_().distribute
        (
            cellWeights
        );

        cellShapeControl_.shapeControlMesh().distribute(decomposition_);

        distribute();

        timeCheck("After distribute");

        iteration++;
    }