Exemple #1
0
Foam::Map<Foam::label> Foam::refinementIterator::setRefinement
(
    const List<refineCell>& refCells
)
{
    Map<label> addedCells(2*refCells.size());

    Time& runTime = const_cast<Time&>(mesh_.time());

    label nRefCells = refCells.size();

    label oldRefCells = -1;

    // Operate on copy.
    List<refineCell> currentRefCells(refCells);

    bool stop = false;

    do
    {
        if (writeMesh_)
        {
            // Need different times to write meshes.
            runTime++;
        }

        polyTopoChange meshMod(mesh_);

        if (debug)
        {
            Pout<< "refinementIterator : refining "
                << currentRefCells.size() << " cells." << endl;
        }

        // Determine cut pattern.
        cellCuts cuts(mesh_, cellWalker_, currentRefCells);

        label nCuts = cuts.nLoops();
        reduce(nCuts, sumOp<label>());

        if (nCuts == 0)
        {
            if (debug)
            {
                Pout<< "refinementIterator : exiting iteration since no valid"
                    << " loops found for " << currentRefCells.size() 
                    << " cells" << endl;


                fileName cutsFile("failedCuts_" + runTime.timeName() + ".obj");

                Pout<< "Writing cuts for time " <<  runTime.timeName()
                    << " to " << cutsFile << endl;

                OFstream cutsStream(cutsFile);


                labelList refCells(currentRefCells.size());
                forAll(currentRefCells, i)
                {
                    refCells[i] = currentRefCells[i].cellNo();
                }
                meshTools::writeOBJ
                (
                    cutsStream,
                    mesh().cells(),
                    mesh().faces(),
                    mesh().points(),
                    refCells
                );
            }

            break;
        }
            
        if (debug)
        {
            fileName cutsFile("cuts_" + runTime.timeName() + ".obj");

            Pout<< "Writing cuts for time " <<  runTime.timeName()
                << " to " << cutsFile << endl;

            OFstream cutsStream(cutsFile);
            cuts.writeOBJ(cutsStream);
        }


        // Insert mesh refinement into polyTopoChange.
        meshRefiner_.setRefinement(cuts, meshMod);


        //
        // Do all changes
        //

        autoPtr<mapPolyMesh> morphMap = meshMod.changeMesh
        (
            mesh_,
            false
        );

        // Move mesh (since morphing does not do this)
        if (morphMap().hasMotionPoints())
        {
            mesh_.movePoints(morphMap().preMotionPoints());
        }

        // Update stored refinement pattern
        meshRefiner_.updateMesh(morphMap());

        // Write resulting mesh
        if (writeMesh_)
        {
            if (debug)
            {
                Pout<< "Writing refined polyMesh to time "
                    << runTime.timeName() << endl;
            }

            mesh_.write();
        }

        // Update currentRefCells for new cell numbers. Use helper function
        // in meshCutter class.
        updateLabels
        (
            morphMap->reverseCellMap(),
            currentRefCells
        );

        // Update addedCells for new cell numbers
        updateLabels
        (
            morphMap->reverseCellMap(),
            addedCells
        );

        // Get all added cells from cellCutter (already in new numbering
        // from meshRefiner.updateMesh call) and add to global list of added
        const Map<label>& addedNow = meshRefiner_.addedCells();

        for
        (
            Map<label>::const_iterator iter = addedNow.begin();
            iter != addedNow.end();
            ++iter
        )
        {
            if (!addedCells.insert(iter.key(), iter()))
            {
                FatalErrorIn("refinementIterator")
                    << "Master cell " << iter.key()
                    << " already has been refined" << endl
                    << "Added cell:" << iter() << abort(FatalError);
            }
        }


        // Get failed refinement in new cell numbering and reconstruct input
        // to the meshRefiner. Is done by removing all refined cells from
        // current list of cells to refine.

        // Update refCells for new cell numbers.
        updateLabels
        (
            morphMap->reverseCellMap(),
            currentRefCells
        );

        // Pack refCells acc. to refined status
        nRefCells = 0;

        forAll(currentRefCells, refI)
        {
            const refineCell& refCell = currentRefCells[refI];

            if (!addedNow.found(refCell.cellNo()))
            {
                if (nRefCells != refI)
                {
                    currentRefCells[nRefCells++] =
                        refineCell
                        (
                            refCell.cellNo(),
                            refCell.direction()
                        );
                }
            }
        }

        oldRefCells = currentRefCells.size();

        currentRefCells.setSize(nRefCells);

        if (debug)
        {
            Pout<< endl;
        }

        // Stop only if all finished or all can't refine any further.
        stop = (nRefCells == 0) || (nRefCells == oldRefCells);
        reduce(stop, andOp<bool>());
    }
    while (!stop);


    if (nRefCells == oldRefCells)
    {
        WarningIn("refinementIterator")
            << "stopped refining."
            << "Did not manage to refine a single cell" << endl
            << "Wanted :" << oldRefCells << endl;
    }

    return addedCells;
}
// Coming from startEdgeI cross the edge to the other face
// across to the next cut edge.
bool Foam::cuttingPlane::walkCell
(
    const primitiveMesh& mesh,
    const UList<label>& edgePoint,
    const label cellI,
    const label startEdgeI,
    DynamicList<label>& faceVerts
)
{
    label faceI = -1;
    label edgeI = startEdgeI;

    label nIter = 0;

    faceVerts.clear();
    do
    {
        faceVerts.append(edgePoint[edgeI]);

        // Cross edge to other face
        faceI = meshTools::otherFace(mesh, cellI, faceI, edgeI);

        // Find next cut edge on face.
        const labelList& fEdges = mesh.faceEdges()[faceI];

        label nextEdgeI = -1;

        //Note: here is where we should check for whether there are more
        // than 2 intersections with the face (warped/non-convex face).
        // If so should e.g. decompose the cells on both faces and redo
        // the calculation.

        forAll(fEdges, i)
        {
            label edge2I = fEdges[i];

            if (edge2I != edgeI && edgePoint[edge2I] != -1)
            {
                nextEdgeI = edge2I;
                break;
            }
        }

        if (nextEdgeI == -1)
        {
            // Did not find another cut edge on faceI. Do what?
            WarningIn("Foam::cuttingPlane::walkCell")
                << "Did not find closed walk along surface of cell " << cellI
                << " starting from edge " << startEdgeI
                << " in " << nIter << " iterations." << nl
                << "Collected cutPoints so far:" << faceVerts
                << endl;

            return false;
        }

        edgeI = nextEdgeI;

        nIter++;

        if (nIter > 1000)
        {
            WarningIn("Foam::cuttingPlane::walkCell")
                << "Did not find closed walk along surface of cell " << cellI
                << " starting from edge " << startEdgeI
                << " in " << nIter << " iterations." << nl
                << "Collected cutPoints so far:" << faceVerts
                << endl;
            return false;
        }

    } while (edgeI != startEdgeI);
Foam::
dissolMotionPointPatchVectorField::
dissolMotionPointPatchVectorField
(
    const pointPatch& p,
    const DimensionedField<vector, pointMesh>& iF,
    const dictionary& dict
)
:
  fixedValuePointPatchField<vector>(p, iF)
{
  if(debug) {
    Info << "dissolMotionPointPatchVectorField constructor 2"<<endl;
  }
  
  if (dict.found("value"))
  {
    this->operator==
    (
      vectorField("value", dict, p.size())
    );
  }
  else
  {
    WarningIn(
        "dissolMotionPointPatchVectorField constructor 2"
        "("
        "const pointPatch& p,"
        "const DimensionedField<vector, pointMesh>& iF,"
        "const dictionary& dict"
        ")"
    ) << "No value defined for " << this->internalField().name()
        << " on " << this->patch().name()
        << endl;
  }
  
  
  if (!dict.readIfPresent<scalar>("rlxTol", rlxTol))
  {
    rlxTol = 1.0e-6;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for rlxTol"
      << " on " << this->patch().name() << " therefore using "
      << rlxTol
      << endl;
  }
  if (!dict.readIfPresent<int>("q_norm_recalc", q_norm_recalc))
  {
    q_norm_recalc = 1;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for q_norm_recalc"
      << " on " << this->patch().name() << " therefore using "
      << q_norm_recalc
      << endl;
  }
  if (!dict.readIfPresent<scalar>("k_1", k_1))
  {
    k_1 = 1.0;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for k_1"
      << " on " << this->patch().name() << " therefore using "
      << k_1
      << endl;
  }
  if (!dict.readIfPresent<scalar>("k_2", k_2))
  {
    k_2 = 1.0;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for k_2"
      << " on " << this->patch().name() << " therefore using "
      << k_2
      << endl;
  }
  if (!dict.readIfPresent<int>("q_2", q_2))
  {
    q_2 = 1;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for q_2"
      << " on " << this->patch().name() << " therefore using "
      << q_2
      << endl;
  }


  if (!dict.readIfPresent<int>("q_norm_recalc_edge", q_norm_recalc_edge))
  {
    q_norm_recalc_edge = 1;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for q_norm_recalc_edge"
      << " on " << this->patch().name() << " therefore using "
      << q_norm_recalc_edge
      << endl;
  }
  if (!dict.readIfPresent<scalar>("k_1edge", k_1edge))
  {
    k_1edge = 1.0;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for k_1edge"
      << " on " << this->patch().name() << " therefore using "
      << k_1edge
      << endl;
  }
  if (!dict.readIfPresent<scalar>("k_2edge", k_2edge))
  {
    k_2edge = 1.0;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for k_2edge"
      << " on " << this->patch().name() << " therefore using "
      << k_2edge
      << endl;
  }
  if (!dict.readIfPresent<int>("q_2edge", q_2edge))
  {
    q_2edge = 1;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<Type, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    )
      << "No value defined for q_2edge"
      << " on " << this->patch().name() << " therefore using "
      << q_2edge
      << endl;
  }
  
  if (!dict.readIfPresent<bool>("pinnedPoint", pinnedPoint))
  {
    pinnedPoint = false;
    WarningIn
    (
      "dissolMotionPointPatchVectorField constructor 2"
      "("
      "const fvPatch& p,"
      "const DimensionedField<scalar, volMesh>& iF,"
      "const dictionary& dict"
      ")"
    ) 
      << "No value defined for pinnedPoint"
      << " on " << this->patch().name() << " therefore using false"
      << endl;
  }

  
  
  if(debug) 
  {
    Info << "dissolMotionPointPatchVectorField constructor 2 "
            "calc_weights_surface"<<nl;
  }
  calc_weights_surface();
  
  if(debug) 
  {
    Info << "dissolMotionPointPatchVectorField constructor 2 "
            "make_lists_and_normals"<<nl;
  }
  make_lists_and_normals();
  
  /*
  for(int i=0; i<5; i++)
  {
    Info<<i<<" "<<surfWeights[i]<<"  "<<pinnedPointsNorm[i]<<nl;
  }
  std::exit(0);
  */
  
}
Exemple #4
0
// Remove a dirctory and its contents
bool Foam::rmDir(const fileName& directory)
{
    if (POSIX::debug)
    {
        Info<< "rmDir(const fileName&) : "
            << "removing directory " << directory << endl;
    }

    // Pointers to the directory entries
    DIR *source;
    struct dirent *list;

    // Attempt to open directory and set the structure pointer
    if ((source = ::opendir(directory.c_str())) == NULL)
    {
        WarningIn("rmDir(const fileName&)")
            << "cannot open directory " << directory << endl;

        return false;
    }
    else
    {
        // Read and parse all the entries in the directory
        while ((list = ::readdir(source)) != NULL)
        {
            fileName fName(list->d_name);

            if (fName != "." && fName != "..")
            {
                fileName path = directory/fName;

                if (path.type() == fileName::DIRECTORY)
                {
                    if (!rmDir(path))
                    {
                        WarningIn("rmDir(const fileName&)")
                            << "failed to remove directory " << fName
                            << " while removing directory " << directory
                            << endl;

                        ::closedir(source);

                        return false;
                    }
                }
                else
                {
                    if (!rm(path))
                    {
                        WarningIn("rmDir(const fileName&)")
                            << "failed to remove file " << fName
                            << " while removing directory " << directory
                            << endl;

                        ::closedir(source);

                        return false;
                    }
                }
            }

        }

        if (!rm(directory))
        {
            WarningIn("rmDir(const fileName&)")
                << "failed to remove directory " << directory << endl;

            ::closedir(source);

            return false;
        }

        ::closedir(source);

        return true;
    }
}
void Foam::inclinedFilmNusseltInletVelocityFvPatchVectorField::updateCoeffs()
{
    if (updated())
    {
        return;
    }

    const label patchI = patch().index();

    // retrieve the film region from the database

    const regionModels::regionModel& region =
        db().time().lookupObject<regionModels::regionModel>
        (
            "surfaceFilmProperties"
        );

    const regionModels::surfaceFilmModels::kinematicSingleLayer& film =
        dynamic_cast
        <
            const regionModels::surfaceFilmModels::kinematicSingleLayer&
        >(region);

    // calculate the vector tangential to the patch
    // note: normal pointing into the domain
    const vectorField n(-patch().nf());

    // TODO: currently re-evaluating the entire gTan field to return this patch
    const scalarField gTan(film.gTan()().boundaryField()[patchI] & n);

    if (patch().size() && (max(mag(gTan)) < SMALL))
    {
        WarningIn
        (
            "void Foam::inclinedFilmNusseltInletVelocityFvPatchVectorField::"
            "updateCoeffs()"
        )
            << "Tangential gravity component is zero.  This boundary condition "
            << "is designed to operate on patches inclined with respect to "
            << "gravity"
            << endl;
    }

    const volVectorField& nHat = film.nHat();

    const vectorField nHatp(nHat.boundaryField()[patchI].patchInternalField());

    vectorField nTan(nHatp ^ n);
    nTan /= mag(nTan) + ROOTVSMALL;

    // calculate distance in patch tangential direction

    const vectorField& Cf = patch().Cf();
    scalarField d(nTan & Cf);

    // calculate the wavy film height

    const scalar t = db().time().timeOutputValue();

    const scalar GMean = GammaMean_->value(t);
    const scalar a = a_->value(t);
    const scalar omega = omega_->value(t);

    const scalarField G(GMean + a*sin(omega*constant::mathematical::twoPi*d));

    const volScalarField& mu = film.mu();
    const scalarField mup(mu.boundaryField()[patchI].patchInternalField());

    const volScalarField& rho = film.rho();
    const scalarField rhop(rho.boundaryField()[patchI].patchInternalField());

    const scalarField Re(max(G, scalar(0.0))/mup);

    operator==(n*pow(gTan*mup/(3.0*rhop), 0.333)*pow(Re, 0.666));

    fixedValueFvPatchVectorField::updateCoeffs();
}
Exemple #6
0
bool Foam::polyMesh::checkFaceOrthogonality
(
    const vectorField& fAreas,
    const vectorField& cellCtrs,
    const bool report,
    const bool detailedReport,
    labelHashSet* setPtr
) const
{
    if (debug)
    {
        Info<< "bool polyMesh::checkFaceOrthogonality("
            << "const bool, labelHashSet*) const: "
            << "checking mesh non-orthogonality" << endl;
    }

    const labelList& own = faceOwner();
    const labelList& nei = faceNeighbour();

    // Calculate orthogonality for all internal and coupled boundary faces
    // (1 for uncoupled boundary faces)
    tmp<scalarField> tortho = polyMeshTools::faceOrthogonality
    (
        *this,
        fAreas,
        cellCtrs
    );
    const scalarField& ortho = tortho();

    // Severe nonorthogonality threshold
    const scalar severeNonorthogonalityThreshold =
        ::cos(degToRad(primitiveMesh::nonOrthThreshold_));


    scalar minDDotS = GREAT;
    scalar sumDDotS = 0.0;
    label nSummed = 0;
    label severeNonOrth = 0;
    label errorNonOrth = 0;


    // Statistics only for internal and masters of coupled faces
    PackedBoolList isMasterFace(syncTools::getInternalOrMasterFaces(*this));

    forAll(ortho, faceI)
    {
        if (ortho[faceI] < severeNonorthogonalityThreshold)
        {
            if (ortho[faceI] > SMALL)
            {
                if (setPtr)
                {
                    setPtr->insert(faceI);
                }

                severeNonOrth++;
            }
            else
            {
                // Error : non-ortho too large
                if (setPtr)
                {
                    setPtr->insert(faceI);
                }
                if (detailedReport && errorNonOrth == 0)
                {
                    // Non-orthogonality greater than 90 deg
                    WarningIn
                    (
                        "polyMesh::checkFaceOrthogonality"
                        "(const pointField&, const bool) const"
                    )   << "Severe non-orthogonality for face "
                        << faceI
                        << " between cells " << own[faceI]
                        << " and " << nei[faceI]
                        << ": Angle = "
                        << radToDeg(::acos(min(1.0, max(-1.0, ortho[faceI]))))
                        << " deg." << endl;
                }

                errorNonOrth++;
            }
        }

        if (isMasterFace[faceI])
        {
            minDDotS = min(minDDotS, ortho[faceI]);
            sumDDotS += ortho[faceI];
            nSummed++;
        }
    }

    reduce(minDDotS, minOp<scalar>());
    reduce(sumDDotS, sumOp<scalar>());
    reduce(nSummed, sumOp<label>());
    reduce(severeNonOrth, sumOp<label>());
    reduce(errorNonOrth, sumOp<label>());

    if (debug || report)
    {
        if (nSummed > 0)
        {
            if (debug || report)
            {
                Info<< "    Mesh non-orthogonality Max: "
                    << radToDeg(::acos(min(1.0, max(-1.0, minDDotS))))
                    << " average: "
                    << radToDeg(::acos(min(1.0, max(-1.0, sumDDotS/nSummed))))
                    << endl;
            }
        }

        if (severeNonOrth > 0)
        {
            Info<< "   *Number of severely non-orthogonal (> "
                << primitiveMesh::nonOrthThreshold_ << " degrees) faces: "
                << severeNonOrth << "." << endl;
        }
    }

    if (errorNonOrth > 0)
    {
        if (debug || report)
        {
            Info<< " ***Number of non-orthogonality errors: "
                << errorNonOrth << "." << endl;
        }

        return true;
    }
    else
    {
        if (debug || report)
        {
            Info<< "    Non-orthogonality check OK." << endl;
        }

        return false;
    }
}
Exemple #7
0
// Return components following the IOobject requirements
//
// behaviour
//    input               IOobject(instance, local, name)
//    -----               ------
//    "foo"               ("", "", "foo")
//    "foo/bar"           ("foo", "", "bar")
//    "/XXX/bar"          ("/XXX", "", "bar")
//    "foo/bar/"          ERROR - no name
//    "foo/xxx/bar"       ("foo", "xxx", "bar")
//    "foo/xxx/yyy/bar"   ("foo", "xxx/yyy", "bar")
bool Foam::IOobject::IOobject::fileNameComponents
(
    const fileName& path,
    fileName& instance,
    fileName& local,
    word& name
)
{
    instance.clear();
    local.clear();
    name.clear();

    // called with directory
    if (isDir(path))
    {
        WarningIn("IOobject::fileNameComponents(const fileName&, ...)")
            << " called with directory: " << path << "\n";
        return false;
    }

    string::size_type first = path.find('/');

    if (first == string::npos)
    {
        // no '/' found - no instance or local

        // check afterwards
        name.string::operator=(path);
    }
    else if (first == 0)
    {
        // Leading '/'. Absolute fileName
        string::size_type last = path.rfind('/');
        instance = path.substr(0, last);

        // check afterwards
        name.string::operator=(path.substr(last+1));
    }
    else
    {
        instance = path.substr(0, first);

        string::size_type last = path.rfind('/');
        if (last > first)
        {
            // with local
            local = path.substr(first+1, last-first-1);
        }

        // check afterwards
        name.string::operator=(path.substr(last+1));
    }


    // check for valid (and stripped) name, regardless of the debug level
    if (name.empty() || string::stripInvalid<word>(name))
    {
        WarningIn("IOobject::fileNameComponents(const fileName&, ...)")
            << "has invalid word for name: \"" << name
            << "\"\nwhile processing path: " << path << "\n";
        return false;
    }

    return true;
}
Foam::scalarVelocityProduct::scalarVelocityProduct
(
    const word& name,
    const objectRegistry& obr,
    const dictionary& dict,
    const bool loadFromFiles
)
    :
    name_(name),
    obr_(obr),
    active_(true),
    UName_("U"),
    scalarFields_(dict.lookup("scalarFields")),
    USNames_(scalarFields_.size()),
    writeFields_(false)
{
    // Check if the available mesh is an fvMesh, otherwise deactivate
    if (!isA<fvMesh>(obr_))
    {
        active_ = false;
        WarningIn
        (
            "scalarVelocityProduct::scalarVelocityProduct"
            "("
            "const word&, "
            "const objectRegistry&, "
            "const dictionary&, "
            "const bool"
            ")"
        )   << "No fvMesh available, deactivating " << name_ << nl
            << endl;
    }

    read(dict);

    if (active_)
    {
        const fvMesh& mesh = refCast<const fvMesh>(obr_);

        const volVectorField& U = mesh.lookupObject<volVectorField>(UName_);
        const dimensionSet& UDim = U.dimensions();

        forAll (scalarFields_, i)
        {
            const volScalarField& S =
                mesh.lookupObject<volScalarField>(scalarFields_[i]);
            const dimensionSet& SDim = S.dimensions();

            volVectorField* USproductPtr
            (
                new volVectorField
                (
                    IOobject
                    (
                        USNames_[i],
                        mesh.time().timeName(),
                        mesh,
                        IOobject::NO_READ,
                        IOobject::NO_WRITE
                    ),
                    mesh,
                    dimensionedVector
                    (
                        USNames_[i]+"Dim", UDim*SDim, vector::zero
                    )
                )
            );

            mesh.objectRegistry::store(USproductPtr);
        }
    }
}
Foam::polyMesh::polyMesh(const IOobject& io)
:
    objectRegistry(io),
    primitiveMesh(),
    allPoints_
    (
        IOobject
        (
            "points",
            time().findInstance(meshDir(), "points"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    // To be re-sliced later.  HJ, 19/oct/2008
    points_(allPoints_, allPoints_.size()),
    allFaces_
    (
        IOobject
        (
            "faces",
            time().findInstance(meshDir(), "faces"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    // To be re-sliced later.  HJ, 19/oct/2008
    faces_(allFaces_, allFaces_.size()),
    owner_
    (
        IOobject
        (
            "owner",
            time().findInstance(meshDir(), "faces"),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        )
    ),
    neighbour_
    (
        IOobject
        (
            "neighbour",
            time().findInstance(meshDir(), "faces"),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        )
    ),
    clearedPrimitives_(false),
    boundary_
    (
        IOobject
        (
            "boundary",
            time().findInstance(meshDir(), "boundary"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        *this
    ),
    bounds_(allPoints_),
    geometricD_(Vector<label>::zero),
    solutionD_(Vector<label>::zero),
    pointZones_
    (
        IOobject
        (
            "pointZones",
            time().findInstance
            (
                meshDir(),
                "pointZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    faceZones_
    (
        IOobject
        (
            "faceZones",
            time().findInstance
            (
                meshDir(),
                "faceZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    cellZones_
    (
        IOobject
        (
            "cellZones",
            time().findInstance
            (
                meshDir(),
                "cellZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    globalMeshDataPtr_(NULL),
    moving_(false),
    changing_(false),
    curMotionTimeIndex_(time().timeIndex()),
    oldAllPointsPtr_(NULL),
    oldPointsPtr_(NULL)
{
    if (exists(owner_.objectPath()))
    {
        initMesh();
    }
    else
    {
        cellIOList cLst
        (
            IOobject
            (
                "cells",
                // Find the cells file on the basis of the faces file
                // HJ, 8/Jul/2009
//                 time().findInstance(meshDir(), "cells"),
                time().findInstance(meshDir(), "faces"),
                meshSubDir,
                *this,
                IOobject::MUST_READ,
                IOobject::NO_WRITE
            )
        );


        // Set the primitive mesh
        initMesh(cLst);

        owner_.write();
        neighbour_.write();
    }

    // Calculate topology for the patches (processor-processor comms etc.)
    boundary_.updateMesh();

    // Calculate the geometry for the patches (transformation tensors etc.)
    boundary_.calcGeometry();

    // Warn if global empty mesh (constructs globalData!)
    if (globalData().nTotalPoints() == 0)
    {
        WarningIn("polyMesh(const IOobject&)")
            << "no points in mesh" << endl;
    }
    if (globalData().nTotalCells() == 0)
    {
        WarningIn("polyMesh(const IOobject&)")
            << "no cells in mesh" << endl;
    }
}
int main(int argc, char *argv[])
{

    argList::addOption("file","fileName","specify the input file");
    argList::addOption("fileIn","fileName","similar to file option");
    argList::addOption("field","fieldName","specify the output file");
    argList::addOption("fileOut","fileName","specify the output file");
    argList::addOption("folder","constant","specify the folder");
    argList::addOption("offset","0","add offset to interpolated value");

    Foam::argList args(argc,argv); 

    word matrixFile = "default";
    word nameField = "default";

    if (args.optionFound("file"))
    {
        matrixFile = args.option("file");
    }
    else if (args.optionFound("fileIn"))
    {
        WarningIn("setFieldsFromXY.C")
            << "option fileIn deprecated,  use option -file instead"
                << nl << endl;
        matrixFile = args.option("fileIn");
    }
    else
    {
        FatalErrorIn("setFieldsFromXY.C")
            << "no input file specified, use option -file"
            << exit(FatalError);
    }

    if (args.optionFound("field"))
    {
        nameField = args.option("field");
    }
    else if (args.optionFound("fileOut"))
    {
        WarningIn("setFieldsFromXY.C")
            << "option fileOut deprecated, use option -field instead"
                << nl << endl;
        nameField = args.option("fileOut");
    }
    else
    {
        FatalErrorIn("setFieldsFromXY.C")
            << "no field specified, use option -field"
            << exit(FatalError);
    }

    scalar offset = args.optionLookupOrDefault<scalar>("offset",0.);

    #include "createTime.H"
    #include "createMesh.H"
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

    //- read inputFile permeability matrix
    IFstream inputFileStream(matrixFile);
    RectangularMatrix<scalar> inputFile(inputFileStream());

    word fileDir = "constant";
    if (args.optionFound("folder"))
    {
        fileDir = args.option("folder"); 
    
    }

    volScalarField outputFile
        (
            IOobject
            (
                nameField,
                fileDir,
                mesh,
                IOobject::MUST_READ,
                IOobject::AUTO_WRITE
            ),
            mesh
        );

    forAll(outputFile,celli)
    {   
        label id1=-1;
        label id2=-1;
        label id3=-1;     
        scalar dist1 = VGREAT;
        scalar dist2 = VGREAT;
        scalar dist3 = VGREAT;

        for(label i=0;i<inputFile.m();i++)
        {
            scalar dist = Foam::sqrt(pow(inputFile[i][0]-mesh.C()[celli].x(),2)+pow(inputFile[i][1]-mesh.C()[celli].y(),2));
            if ( dist < dist1)
            {
                //Info <<  "1 *** " << dist << " " << dist1 <<  " " << dist2 <<  " " << dist3 << endl;
                id3 = id2;
                dist3 = dist2;
                id2 = id1;
                dist2 = dist1;
                id1 = i;
                dist1 = dist;
            }
            else if ( dist < dist2)
            {
                //         Info <<  "2 *** " << dist << " " << dist1 <<  " " << dist2 <<  " " << dist3 << endl;      
                id3 = id2;
                dist3 = dist2;
                id2 = i;
                dist2 = dist;                
            }
            else if ( dist < dist3)
            {
                //                Info <<  "3 *** " << dist << " " << dist1 <<  " " << dist2 <<  " " << dist3 << endl;
                id3 = i;
                dist3 = dist;                
            }
        }

        
        if ( (id1 == -1) || (id2 == -1) || (id3 == -1))
        {
            Info << nl << "Error : three point are not found for interpolation"
                << nl << id1 << " / " << id2 << " / " << id3 << endl;
        }
       
        outputFile[celli] = ( dist1*inputFile[id1][2] + dist2*inputFile[id2][2] + dist3*inputFile[id3][2] ) / (dist1+dist2+dist3) + offset;

    }
bool
#else
void
#endif
Foam::expressionField::write()
{
    Dbug << "write()" << endl;

    if(active_) {
        Info << "Creating expression field " << name_ << " ..." << flush;

        FieldValueExpressionDriver &driver=driver_();

        bool oldDimsetDebug=dimensionSet::debug;
        dimensionSet::debug=false;

        driver.clearVariables();

        driver.parse(expression_);

        dimensionSet::debug=oldDimsetDebug;

        Info << " type:" << driver.getResultType() << endl;

        if(driver.resultIsTyp<volVectorField>()) {
            storeField(
                driver.getResult<volVectorField>()
            );
        } else if(driver.resultIsTyp<volScalarField>()) {
            storeField(
                driver.getResult<volScalarField>()
            );
        } else if(driver.resultIsTyp<volTensorField>()) {
            storeField(
                driver.getResult<volTensorField>()
            );
        } else if(driver.resultIsTyp<volSymmTensorField>()) {
            storeField(
                driver.getResult<volSymmTensorField>()
            );
        } else if(driver.resultIsTyp<volSphericalTensorField>()) {
            storeField(
                driver.getResult<volSphericalTensorField>()
            );
        } else if(driver.resultIsTyp<surfaceVectorField>()) {
            storeField(
                driver.getResult<surfaceVectorField>()
            );
        } else if(driver.resultIsTyp<surfaceScalarField>()) {
            storeField(
                driver.getResult<surfaceScalarField>()
            );
        } else if(driver.resultIsTyp<surfaceTensorField>()) {
            storeField(
                driver.getResult<surfaceTensorField>()
            );
        } else if(driver.resultIsTyp<surfaceSymmTensorField>()) {
            storeField(
                driver.getResult<surfaceSymmTensorField>()
            );
        } else if(driver.resultIsTyp<surfaceSphericalTensorField>()) {
            storeField(
                driver.getResult<surfaceSphericalTensorField>()
            );
        } else if(driver.resultIsTyp<pointVectorField>()) {
            storeField(
                driver.getResult<pointVectorField>()
            );
        } else if(driver.resultIsTyp<pointScalarField>()) {
            storeField(
                driver.getResult<pointScalarField>()
            );
        } else if(driver.resultIsTyp<pointTensorField>()) {
            storeField(
                driver.getResult<pointTensorField>()
            );
        } else if(driver.resultIsTyp<pointSymmTensorField>()) {
            storeField(
                driver.getResult<pointSymmTensorField>()
            );
        } else if(driver.resultIsTyp<pointSphericalTensorField>()) {
            storeField(
                driver.getResult<pointSphericalTensorField>()
            );
        } else {
            WarningIn("Foam::expressionField::execute()")
                << "Expression '" << expression_
                    << "' evaluated to an unsupported type "
                    << driver.typ()
                    << endl;
        }
    }

    driver_->tryWrite();
    Dbug << "write() - end" << endl;
#ifdef FOAM_IOFILTER_WRITE_NEEDS_BOOL
    return true;
#endif
}
Exemple #12
0
Foam::polyMesh::polyMesh(const IOobject& io)
:
    objectRegistry(io),
    primitiveMesh(),
    points_
    (
        IOobject
        (
            "points",
            time().findInstance(meshDir(), "points"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    faces_
    (
        IOobject
        (
            "faces",
            time().findInstance(meshDir(), "faces"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        )
    ),
    owner_
    (
        IOobject
        (
            "owner",
            faces_.instance(),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        )
    ),
    neighbour_
    (
        IOobject
        (
            "neighbour",
            faces_.instance(),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        )
    ),
    clearedPrimitives_(false),
    boundary_
    (
        IOobject
        (
            "boundary",
            time().findInstance(meshDir(), "boundary"),
            meshSubDir,
            *this,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        *this
    ),
    bounds_(points_),
    comm_(UPstream::worldComm),
    geometricD_(Vector<label>::zero),
    solutionD_(Vector<label>::zero),
    tetBasePtIsPtr_(NULL),
    cellTreePtr_(NULL),
    pointZones_
    (
        IOobject
        (
            "pointZones",
            time().findInstance
            (
                meshDir(),
                "pointZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    faceZones_
    (
        IOobject
        (
            "faceZones",
            time().findInstance
            (
                meshDir(),
                "faceZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    cellZones_
    (
        IOobject
        (
            "cellZones",
            time().findInstance
            (
                meshDir(),
                "cellZones",
                IOobject::READ_IF_PRESENT
            ),
            meshSubDir,
            *this,
            IOobject::READ_IF_PRESENT,
            IOobject::NO_WRITE
        ),
        *this
    ),
    globalMeshDataPtr_(NULL),
    moving_(false),
    topoChanging_(false),
    curMotionTimeIndex_(time().timeIndex()),
    oldPointsPtr_(NULL)
{
    if (exists(owner_.objectPath()))
    {
        initMesh();
    }
    else
    {
        cellCompactIOList cLst
        (
            IOobject
            (
                "cells",
                time().findInstance(meshDir(), "cells"),
                meshSubDir,
                *this,
                IOobject::MUST_READ,
                IOobject::NO_WRITE
            )
        );

        // Set the primitive mesh
        initMesh(cLst);

        owner_.write();
        neighbour_.write();
    }

    // Calculate topology for the patches (processor-processor comms etc.)
    boundary_.updateMesh();

    // Calculate the geometry for the patches (transformation tensors etc.)
    boundary_.calcGeometry();

    // Warn if global empty mesh
    if (returnReduce(nPoints(), sumOp<label>()) == 0)
    {
        WarningIn("polyMesh(const IOobject&)")
            << "no points in mesh" << endl;
    }
    if (returnReduce(nCells(), sumOp<label>()) == 0)
    {
        WarningIn("polyMesh(const IOobject&)")
            << "no cells in mesh" << endl;
    }

    // Initialise demand-driven data
    calcDirections();
}
void Foam::SmootherBoundary::analyseDict(dictionary &snapDict)
{
    _featureAngle = readScalar(snapDict.lookup("featureAngle"));
    _minEdgeForFeature = readLabel(snapDict.lookup("minEdgeForFeature"));
    _minFeatureEdgeLength = readScalar(snapDict.lookup("minFeatureEdgeLength"));
    _writeFeatures = readBool(snapDict.lookup("writeFeatures"));

    Info<< "  snapControls:"  << nl
        << "    - Feature angle              : " << _featureAngle  << nl
        << "    - Min edges for features     : " << _minEdgeForFeature << nl
        << "    - Min feature edge length    : " << _minFeatureEdgeLength << nl;

    const polyBoundaryMesh& bM = _polyMesh->boundaryMesh();
    const label NbPolyPatchs = bM.size();
    _triSurfList.resize(NbPolyPatchs, 0);
    _triSurfSearchList.resize(NbPolyPatchs, 0);
    _surfFeatList.resize(NbPolyPatchs, 0);
    _extEdgMeshList.resize(NbPolyPatchs, 0);
    _bndUseIntEdges.resize(NbPolyPatchs, true);
    _bndIsSnaped.resize(NbPolyPatchs, true);
    _bndLayers.resize(NbPolyPatchs);

    if (snapDict.found("boundaries"))
    {
        Info<< "    - Boundary specifications    : " << nl;

        const dictionary& bndDict = snapDict.subDict("boundaries");
        wordList bndDefined = bndDict.toc();

        forAll(bndDefined, patchI)
        {
            Info<< "    - " << bndDefined[patchI] << nl;

            const dictionary& patchDic = bndDict.subDict(bndDefined[patchI]);

            if (patchDic.found("triSurface"))
            {
                word file = patchDic.lookup("triSurface");

                bool exist = false;
                for(label patchJ = 0; patchJ < NbPolyPatchs && !exist; ++patchJ)
                {
                    exist = bM[patchJ].name() == bndDefined[patchI];

                    if (exist)
                    {
                        Info<< "        - Snaping surface    : " << file << nl;

                        _bndIsSnaped[patchJ] = false;

                        IOobject surfFile
                        (
                            file,
                            _polyMesh->time().constant(),
                            "triSurface",
                            _polyMesh->time(),
                            IOobject::MUST_READ,
                            IOobject::NO_WRITE
                        );

                        triSurface* bnd = new triSurface(surfFile.filePath());
                        addTriFace(patchJ, bnd);

                        if (patchDic.found("internalFeatureEdges"))
                        {
                            _bndUseIntEdges[patchJ] = readBool
                            (
                                patchDic.lookup("internalFeatureEdges")
                            );

                            Info<< "        - Use internal edges : "
                                << _bndUseIntEdges[patchJ] << nl;
                        }
                        else
                        {
                            _bndUseIntEdges[patchJ] = false;
                        }

                        if (patchDic.found("boundaryLayer"))
                        {
                            _bndLayers[patchJ] = SmootherBoundaryLayer
                            (
                                patchDic.subDict("boundaryLayer")
                            );
                        }
                    }
                }

                if (!exist)
                {
                    WarningIn("Foam::MeshSmoother::analyseDict()")
                        << "Patch " << bndDefined[patchI]
                        << " definied in smootherDict is not existing in "
                        << "polyMesh, existing patch in polyMesh ares: "
                        << bM.names() << nl;
                }
            }
        }
Exemple #14
0
// Call scotch with options from dictionary.
Foam::label Foam::ptscotchDecomp::decompose
(
    const fileName& meshPath,
    const List<int>& adjncy,
    const List<int>& xadj,
    const scalarField& cWeights,

    List<int>& finalDecomp
) const
{
    if (debug)
    {
        Pout<< "ptscotchDecomp : entering with xadj:" << xadj.size() << endl;
    }

    // Dump graph
    if (decompositionDict_.found("ptscotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("ptscotchCoeffs");

        if (scotchCoeffs.lookupOrDefault("writeGraph", false))
        {
            OFstream str
            (
                meshPath + "_" + Foam::name(Pstream::myProcNo()) + ".dgr"
            );

            Pout<< "Dumping Scotch graph file to " << str.name() << endl
                << "Use this in combination with dgpart." << endl;

            globalIndex globalCells(xadj.size()-1);

            // Distributed graph file (.grf)
            label version = 2;
            str << version << nl;
            // Number of files (procglbnbr)
            str << Pstream::nProcs();
            // My file number (procloc)
            str << ' ' << Pstream::myProcNo() << nl;

            // Total number of vertices (vertglbnbr)
            str << globalCells.size();
            // Total number of connections (edgeglbnbr)
            str << ' ' << returnReduce(xadj[xadj.size()-1], sumOp<label>())
                << nl;
            // Local number of vertices (vertlocnbr)
            str << xadj.size()-1;
            // Local number of connections (edgelocnbr)
            str << ' ' << xadj[xadj.size()-1] << nl;
            // Numbering starts from 0
            label baseval = 0;
            // 100*hasVertlabels+10*hasEdgeWeights+1*hasVertWeighs
            str << baseval << ' ' << "000" << nl;
            for (label cellI = 0; cellI < xadj.size()-1; cellI++)
            {
                label start = xadj[cellI];
                label end = xadj[cellI+1];
                str << end-start;

                for (label i = start; i < end; i++)
                {
                    str << ' ' << adjncy[i];
                }
                str << nl;
            }
        }
    }

    // Strategy
    // ~~~~~~~~

    // Default.
    SCOTCH_Strat stradat;
    check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit");

    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");


        string strategy;
        if (scotchCoeffs.readIfPresent("strategy", strategy))
        {
            if (debug)
            {
                Info<< "ptscotchDecomp : Using strategy " << strategy << endl;
            }
            SCOTCH_stratDgraphMap(&stradat, strategy.c_str());
            //fprintf(stdout, "S\tStrat=");
            //SCOTCH_stratSave(&stradat, stdout);
            //fprintf(stdout, "\n");
        }
    }


    // Graph
    // ~~~~~

    List<int> velotab;


    // Check for externally provided cellweights and if so initialise weights

    scalar minWeights = gMin(cWeights);

    if (!cWeights.empty())
    {
        if (minWeights <= 0)
        {
            WarningIn
            (
                "ptscotchDecomp::decompose(..)"
            )   << "Illegal minimum weight " << minWeights
                << endl;
        }

        if (cWeights.size() != xadj.size()-1)
        {
            FatalErrorIn
            (
                "ptscotchDecomp::decompose(..)"
            )   << "Number of cell weights " << cWeights.size()
                << " does not equal number of cells " << xadj.size()-1
                << exit(FatalError);
        }
    }

    scalar velotabSum = gSum(cWeights)/minWeights;

    scalar rangeScale(1.0);

    if (Pstream::master())
    {
        if (velotabSum > scalar(INT_MAX - 1))
        {
            // 0.9 factor of safety to avoid floating point round-off in
            // rangeScale tipping the subsequent sum over the integer limit.
            rangeScale = 0.9*scalar(INT_MAX - 1)/velotabSum;

            WarningIn
            (
                "ptscotchDecomp::decompose(...)"
            )   << "Sum of weights has overflowed integer: " << velotabSum
                << ", compressing weight scale by a factor of " << rangeScale
                << endl;
        }
    }

    Pstream::scatter(rangeScale);

    if (!cWeights.empty())
    {
        // Convert to integers.
        velotab.setSize(cWeights.size());

        forAll(velotab, i)
        {
            velotab[i] = int((cWeights[i]/minWeights - 1)*rangeScale) + 1;
        }
Exemple #15
0
int main(int argc, char *argv[])
{

    Foam::timeSelector::addOptions(false);
    Foam::argList::validArgs.append("expressionDict");
#   include "addRegionOption.H"
    argList::validOptions.insert("noDimensionChecking","");
    argList::validOptions.insert("foreignMeshesThatFollowTime",
                                  "<list of mesh names>");

#   include "setRootCase.H"

    printSwakVersion();

    IFstream theFile(args.args()[1]);
    dictionary theExpressions(theFile);
    wordList foreignMeshesThatFollowTime(0);

    if (!args.options().found("time") && !args.options().found("latestTime")) {
        FatalErrorIn("main()")
            << args.executable()
                << ": time/latestTime option is required" << endl
            << exit(FatalError);
    }

    if(args.options().found("noDimensionChecking")) {
        dimensionSet::debug=0;
    }
    if(args.options().found("foreignMeshesThatFollowTime")) {
        string followMeshes(
            args.options()["foreignMeshesThatFollowTime"]
        );
        IStringStream followStream("("+followMeshes+")");
        foreignMeshesThatFollowTime=wordList(followStream);
    }

#   include "createTime.H"
    Foam::instantList timeDirs = Foam::timeSelector::select0(runTime, args);

#   include "createNamedMesh.H"

    forAllConstIter(IDLList<entry>, theExpressions, iter)
    {
        const dictionary &dict=iter().dict();

        CommonValueExpressionDriver::readForeignMeshInfo(dict);
    }

    forAll(timeDirs, timeI)
    {
        runTime.setTime(timeDirs[timeI], timeI);

        Foam::Info << "\nTime = " << runTime.timeName() << Foam::endl;

        mesh.readUpdate();

        forAll(foreignMeshesThatFollowTime,i) {
            const word &name=foreignMeshesThatFollowTime[i];
            if(MeshesRepository::getRepository().hasMesh(name)) {
                Info << "Setting mesh " << name << " to current Time"
                    << endl;

                MeshesRepository::getRepository().setTime(
                    name,
                    runTime.value()
                );
            } else {
                FatalErrorIn(args.executable())
                    << "No mesh with name " << name << " declared. " << nl
                        << "Can't follow current time"
                        << endl
                        << exit(FatalError);

            }
        }

        forAllConstIter(IDLList<entry>, theExpressions, iter)
        {
            Info << iter().keyword() << " : " << flush;

            const dictionary &dict=iter().dict();

            autoPtr<CommonValueExpressionDriver> driver=
                CommonValueExpressionDriver::New(dict,mesh);
            wordList accumulations(dict.lookup("accumulations"));

            driver->setSearchBehaviour(
                true,
                true,
                true         // search on disc
            );

            driver->clearVariables();
            driver->parse(string(dict.lookup("expression")));
            word rType=driver->CommonValueExpressionDriver::getResultType();

            if(rType==pTraits<scalar>::typeName) {
                writeData<scalar>(driver(),accumulations);
            } else if(rType==pTraits<vector>::typeName) {
                writeData<vector>(driver(),accumulations);
            } else if(rType==pTraits<tensor>::typeName) {
                writeData<tensor>(driver(),accumulations);
            } else if(rType==pTraits<symmTensor>::typeName) {
                writeData<symmTensor>(driver(),accumulations);
            } else if(rType==pTraits<sphericalTensor>::typeName) {
                writeData<sphericalTensor>(driver(),accumulations);
            } else {
                WarningIn(args.executable())
                    << "Don't know how to handle type " << rType
                        << endl;
            }

            Info << endl;
        }
Exemple #16
0
bool triSurface::readAC(const fileName& ACfileName)
{
    IFstream ACfile(ACfileName);

    if (!ACfile.good())
    {
        FatalErrorIn("triSurface::readAC(const fileName&)")
            << "Cannot read file " << ACfileName
            << exit(FatalError);
    }

    string line;
    ACfile.getLine(line);

    string version = line.substr(4);

    if (version != "b")
    {
        WarningIn("bool triSurface::readAC(const fileName& ACfileName)")
            << "When reading AC3D file " << ACfileName
            << " read header " << line << " with version " << version
            << endl << "Only tested reading with version 'b'."
            << " This might give problems" << endl;
    }

    string cmd;

    string args;

    if (!readUpto("OBJECT", ACfile, args) || (args != "world"))
    {
        FatalErrorIn("bool triSurface::readAC(const fileName& ACfileName)")
            << "Cannot find \"OBJECT world\" in file " << ACfileName
            << exit(FatalError);
    }

    // Number of kids = patches

    readUpto("kids", ACfile, args, "");

    label nPatches = parseInt(args);

    // Storage for patches and unmerged points and faces

    DynamicList<point> points;
    DynamicList<labelledTri> faces;
    geometricSurfacePatchList patches(nPatches);


    // Start of vertices for object/patch
    label patchStartVert = 0;

    for (label patchI = 0; patchI < nPatches; patchI++)
    {
        readUpto("OBJECT", ACfile, args, " while reading patch " + patchI);

        // Object global values
        string patchName = string("patch") + name(patchI);
        label nVerts = 0;
        tensor rot(I);
        vector loc(0, 0, 0);

        // Read all info for current patch
        while (ACfile.good())
        {
            // Read line and get first word. If end of file break since
            // patch should always end with 'kids' command ?not sure.
            if (!readCmd(ACfile, cmd, args))
            {
                FatalErrorIn("triSurface::readAC(const fileName&)")
                    << "Did not read up to \"kids 0\" while reading patch "
                    << patchI << " from file " << ACfileName
                    << exit(FatalError);
            }

            if (cmd == "name")
            {
                IStringStream nameStream(args);

                nameStream >> patchName;
            }
            else if (cmd == "rot")
            {
                // rot %f %f %f  %f %f %f  %f %f %f
                IStringStream lineStream(args);

                lineStream
                    >> rot.xx() >> rot.xy() >> rot.xz()
                    >> rot.yx() >> rot.yy() >> rot.yz()
                    >> rot.zx() >> rot.zy() >> rot.zz();

                WarningIn("triSurface::readAC(const fileName&)")
                    << "rot (rotation tensor) command not implemented"
                    << "Line:" << cmd << ' ' << args << endl
                    << "while reading patch " << patchI << endl;
            }
Exemple #17
0
bool Foam::polyMesh::checkFaceSkewness
(
    const pointField& points,
    const vectorField& fCtrs,
    const vectorField& fAreas,
    const vectorField& cellCtrs,
    const bool report,
    const bool detailedReport,
    labelHashSet* setPtr
) const
{
    if (debug)
    {
        Info<< "bool polyMesh::checkFaceSkewnesss("
            << "const bool, labelHashSet*) const: "
            << "checking face skewness" << endl;
    }

    const labelList& own = faceOwner();
    const labelList& nei = faceNeighbour();

    // Warn if the skew correction vector is more than skewWarning times
    // larger than the face area vector

    tmp<scalarField> tskew = polyMeshTools::faceSkewness
    (
        *this,
        points,
        fCtrs,
        fAreas,
        cellCtrs
    );
    const scalarField& skew = tskew();

    scalar maxSkew = max(skew);
    label nWarnSkew = 0;

    // Statistics only for all faces except slave coupled faces
    PackedBoolList isMasterFace(syncTools::getMasterFaces(*this));

    forAll(skew, faceI)
    {
        // Check if the skewness vector is greater than the PN vector.
        // This does not cause trouble but is a good indication of a poor mesh.
        if (skew[faceI] > skewThreshold_)
        {
            if (setPtr)
            {
                setPtr->insert(faceI);
            }
            if (detailedReport && nWarnSkew == 0)
            {
                // Non-orthogonality greater than 90 deg
                if (isInternalFace(faceI))
                {
                    WarningIn
                    (
                        "polyMesh::checkFaceSkewnesss"
                        "(const pointField&, const bool) const"
                    )   << "Severe skewness " << skew[faceI]
                        << " for face " << faceI
                        << " between cells " << own[faceI]
                        << " and " << nei[faceI];
                }
                else
                {
                    WarningIn
                    (
                        "polyMesh::checkFaceSkewnesss"
                        "(const pointField&, const bool) const"
                    )   << "Severe skewness " << skew[faceI]
                        << " for boundary face " << faceI
                        << " on cell " << own[faceI];
                }
            }

            if (isMasterFace[faceI])
            {
                nWarnSkew++;
            }
        }
    }

    reduce(maxSkew, maxOp<scalar>());
    reduce(nWarnSkew, sumOp<label>());

    if (nWarnSkew > 0)
    {
        if (debug || report)
        {
            Info<< " ***Max skewness = " << maxSkew
                << ", " << nWarnSkew << " highly skew faces detected"
                   " which may impair the quality of the results"
                << endl;
        }

        return true;
    }
    else
    {
        if (debug || report)
        {
            Info<< "    Max skewness = " << maxSkew << " OK." << endl;
        }

        return false;
    }
}
const Foam::Tuple2<Foam::scalar, Type>&
Foam::interpolationTable<Type>::operator[](const label i) const
{
    label ii = i;
    label n  = this->size();

    if (n <= 1)
    {
        ii = 0;
    }
    else if (ii < 0)
    {
        switch (boundsHandling_)
        {
            case interpolationTable::ERROR:
            {
                FatalErrorIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "index (" << ii << ") underflow" << nl
                    << exit(FatalError);
                break;
            }
            case interpolationTable::WARN:
            {
                WarningIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "index (" << ii << ") underflow" << nl
                    << "    Continuing with the first entry"
                    << endl;
                // fall-through to 'CLAMP'
            }
            case interpolationTable::CLAMP:
            {
                ii = 0;
                break;
            }
            case interpolationTable::REPEAT:
            {
                while (ii < 0)
                {
                    ii += n;
                }
                break;
            }
        }
    }
    else if (ii >= n)
    {
        switch (boundsHandling_)
        {
            case interpolationTable::ERROR:
            {
                FatalErrorIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "index (" << ii << ") overflow" << nl
                    << exit(FatalError);
                break;
            }
            case interpolationTable::WARN:
            {
                WarningIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "index (" << ii << ") overflow" << nl
                    << "    Continuing with the last entry"
                    << endl;
                // fall-through to 'CLAMP'
            }
            case interpolationTable::CLAMP:
            {
                ii = n - 1;
                break;
            }
            case interpolationTable::REPEAT:
            {
                while (ii >= n)
                {
                    ii -= n;
                }
                break;
            }
        }
    }

    return List<Tuple2<scalar, Type> >::operator[](ii);
}
Exemple #19
0
void Foam::setsToFaceZone::applyToSet
(
    const topoSetSource::setAction action,
    topoSet& set
) const
{
    if (!isA<faceZoneSet>(set))
    {
        WarningIn
        (
            "setsToFaceZone::applyToSet(const topoSetSource::setAction"
            ", topoSet"
        )   << "Operation only allowed on a faceZoneSet." << endl;
    }
    else
    {
        faceZoneSet& fzSet = refCast<faceZoneSet>(set);

        if ((action == topoSetSource::NEW) || (action == topoSetSource::ADD))
        {
            Info<< "    Adding all faces from faceSet " << faceSetName_
                << " ..." << endl;

            // Load the sets
            faceSet fSet(mesh_, faceSetName_);
            cellSet cSet(mesh_, cellSetName_);

            // Start off from copy
            DynamicList<label> newAddressing(fzSet.addressing());
            DynamicList<bool> newFlipMap(fzSet.flipMap());

            forAllConstIter(faceSet, fSet, iter)
            {
                label faceI = iter.key();

                if (!fzSet.found(faceI))
                {
                    bool flip = false;

                    label own = mesh_.faceOwner()[faceI];
                    bool ownFound = cSet.found(own);

                    if (mesh_.isInternalFace(faceI))
                    {
                        label nei = mesh_.faceNeighbour()[faceI];
                        bool neiFound = cSet.found(nei);

                        if (ownFound && !neiFound)
                        {
                            flip = false;
                        }
                        else if (!ownFound && neiFound)
                        {
                            flip = true;
                        }
                        else
                        {
                            WarningIn
                            (
                                "setsToFaceZone::applyToSet"
                                "(const topoSetSource::setAction, topoSet)"
                            )   << "One of owner or neighbour of internal face "
                                << faceI << " should be in cellSet "
                                << cSet.name()
                                << " to be able to determine orientation."
                                << endl
                                << "Face:" << faceI << " own:" << own
                                << " OwnInCellSet:" << ownFound
                                << " nei:" << nei
                                << " NeiInCellSet:" << neiFound
                                << endl;
                        }
                    }
                    else
                    {
                        flip = !ownFound;
                    }

                    newAddressing.append(faceI);
                    newFlipMap.append(flip);
                }
            }

            fzSet.addressing().transfer(newAddressing);
            fzSet.flipMap().transfer(newFlipMap);
            fzSet.updateSet();
        }
Type Foam::interpolationTable<Type>::operator()(const scalar value) const
{
    label n = this->size();

    if (n <= 1)
    {
        return List<Tuple2<scalar, Type> >::operator[](0).second();
    }

    scalar minLimit = List<Tuple2<scalar, Type> >::operator[](0).first();
    scalar maxLimit = List<Tuple2<scalar, Type> >::operator[](n-1).first();
    scalar lookupValue = value;

    if (lookupValue < minLimit)
    {
        switch (boundsHandling_)
        {
            case interpolationTable::ERROR:
            {
                FatalErrorIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const scalar) const"
                )   << "value (" << lookupValue << ") underflow" << nl
                    << exit(FatalError);
                break;
            }
            case interpolationTable::WARN:
            {
                WarningIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const scalar) const"
                )   << "value (" << lookupValue << ") underflow" << nl
                    << "    Continuing with the first entry"
                    << endl;
                // fall-through to 'CLAMP'
            }
            case interpolationTable::CLAMP:
            {
                return List<Tuple2<scalar, Type> >::operator[](0).second();
                break;
            }
            case interpolationTable::REPEAT:
            {
                // adjust lookupValue to >= minLimit
                scalar span = maxLimit-minLimit;
                lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
                break;
            }
        }
    }
    else if (lookupValue >= maxLimit)
    {
        switch (boundsHandling_)
        {
            case interpolationTable::ERROR:
            {
                FatalErrorIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "value (" << lookupValue << ") overflow" << nl
                    << exit(FatalError);
                break;
            }
            case interpolationTable::WARN:
            {
                WarningIn
                (
                    "Foam::interpolationTable<Type>::operator[]"
                    "(const label) const"
                )   << "value (" << lookupValue << ") overflow" << nl
                    << "    Continuing with the last entry"
                    << endl;
                // fall-through to 'CLAMP'
            }
            case interpolationTable::CLAMP:
            {
                return List<Tuple2<scalar, Type> >::operator[](n-1).second();
                break;
            }
            case interpolationTable::REPEAT:
            {
                // adjust lookupValue <= maxLimit
                scalar span = maxLimit-minLimit;
                lookupValue = fmod(lookupValue-minLimit, span) + minLimit;
                break;
            }
        }
    }

    label lo = 0;
    label hi = 0;

    // look for the correct range
    for (label i = 0; i < n; ++i)
    {
        if (lookupValue >= List<Tuple2<scalar, Type> >::operator[](i).first())
        {
            lo = hi = i;
        }
        else
        {
            hi = i;
            break;
        }
    }

    if (lo == hi)
    {
        // we are at the end of the table - or there is only a single entry
        return List<Tuple2<scalar, Type> >::operator[](hi).second();
    }
    else if (hi == 0)
    {
        // this treatment should should only occur under these conditions:
        //  -> the 'REPEAT' treatment
        //  -> (0 <= value <= minLimit)
        //  -> minLimit > 0
        // Use the value at maxLimit as the value for value=0
        lo = n - 1;

        return
        (
            List<Tuple2<scalar, Type> >::operator[](lo).second()
          + (
                List<Tuple2<scalar, Type> >::operator[](hi).second()
              - List<Tuple2<scalar, Type> >::operator[](lo).second()
            )
           *(lookupValue / minLimit)
        );
    }
    else
    {
        // normal interpolation
        return
        (
            List<Tuple2<scalar, Type> >::operator[](lo).second()
          + (
                List<Tuple2<scalar, Type> >::operator[](hi).second()
              - List<Tuple2<scalar, Type> >::operator[](lo).second()
            )
           *(
                lookupValue
              - List<Tuple2<scalar, Type> >::operator[](lo).first()
            )
           /(
                List<Tuple2<scalar, Type> >::operator[](hi).first()
              - List<Tuple2<scalar, Type> >::operator[](lo).first()
            )
        );
    }
}
Foam::danckwertsFvPatchScalarField::
danckwertsFvPatchScalarField
(
    const fvPatch& p,
    const DimensionedField<scalar, volMesh>& iF,
    const dictionary& dict
)
:
  mixedFvPatchScalarField(p, iF)
{
  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2" << endl;
  }
  
  
  if (dict.found("value"))
  {
    fvPatchScalarField::operator=
    (
      scalarField("value", dict, p.size())
    );
  }
  else
  {
    fvPatchScalarField::operator=(this->refValue());
    WarningIn(
        "!!!nonLinearFvPatchField<Type>::nonLinearFvPatchField"
        "("
        "const fvPatch& p,"
        "const DimensionedField<Type, volMesh>& iF,"
        "const dictionary& dict"
        ")"
    ) << "No value defined for " << this->internalField().name()
        << " on " << this->patch().name() << " therefore using "
        << this->refValue()
        << endl;
  }

  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2  "
              "value set" << endl;
  }

  if (dict.found("refValue"))
    this->refValue() = scalarField("refValue", dict, p.size());
  else
  {
    if (dict.found("value")) {
      // make sure that refValue has a sensible value for the "update" below
      this->refValue() = scalarField(this->patchInternalField());
    }
    else{
      this->refValue() = pTraits<scalar>::zero;
    }
  }

  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2  "
              "refValue set" << endl;
  }

  if (dict.found("refGradient")) {
      this->refGrad() = scalarField("refGradient", dict, p.size());
  } else {
      this->refGrad() = pTraits<scalar>::zero;
  }

  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2  "
              "refGrad set" << endl;
  }

  if (dict.found("valueFraction")) {
      this->valueFraction() = Field<scalar>("valueFraction", dict, p.size());
  } else {
      this->valueFraction() = 1;
  }

  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2  "
              "valueFraction set" << endl;
  }

  if (!this->updated())
  {
    this->mixedFvPatchScalarField::updateCoeffs();
  }
  /* 
  scalarField::operator=
      (
        this->valueFraction()*this->refValue()
        +
        (1.0 - this->valueFraction())*
        (
            this->patchInternalField()
            + this->refGrad()/this->patch().deltaCoeffs()
        )
      );
  */

  if(debug) {
      Info << "danckwertsFvPatchField<Type>::danckwertsFvPatchField 2  "
              "operator" << endl;
  }
  
  fvPatchScalarField::evaluate();
}
// Call scotch with options from dictionary.
Foam::label Foam::ptscotchDecomp::decompose
(
    const fileName& meshPath,
    const List<int>& adjncy,
    const List<int>& xadj,
    const scalarField& cWeights,

    List<int>& finalDecomp
) const
{
    if (debug)
    {
        Pout<< "ptscotchDecomp : entering with xadj:" << xadj.size() << endl;
    }

    // Dump graph
    if (decompositionDict_.found("ptscotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("ptscotchCoeffs");

        if (scotchCoeffs.lookupOrDefault("writeGraph", false))
        {
            OFstream str
            (
               meshPath + "_" + Foam::name(Pstream::myProcNo()) + ".dgr"
            );

            Pout<< "Dumping Scotch graph file to " << str.name() << endl
                << "Use this in combination with dgpart." << endl;

            globalIndex globalCells(xadj.size()-1);

            // Distributed graph file (.grf)
            label version = 2;
            str << version << nl;
            // Number of files (procglbnbr)
            str << Pstream::nProcs();
            // My file number (procloc)
            str << ' ' << Pstream::myProcNo() << nl;

            // Total number of vertices (vertglbnbr)
            str << globalCells.size();
            // Total number of connections (edgeglbnbr)
            str << ' ' << returnReduce(xadj[xadj.size()-1], sumOp<label>())
                << nl;
            // Local number of vertices (vertlocnbr)
            str << xadj.size()-1;
            // Local number of connections (edgelocnbr)
            str << ' ' << xadj[xadj.size()-1] << nl;
            // Numbering starts from 0
            label baseval = 0;
            // 100*hasVertlabels+10*hasEdgeWeights+1*hasVertWeighs
            str << baseval << ' ' << "000" << nl;
            for (label cellI = 0; cellI < xadj.size()-1; cellI++)
            {
                label start = xadj[cellI];
                label end = xadj[cellI+1];
                str << end-start;

                for (label i = start; i < end; i++)
                {
                    str << ' ' << adjncy[i];
                }
                str << nl;
            }
        }
    }

    // Strategy
    // ~~~~~~~~

    // Default.
    SCOTCH_Strat stradat;
    check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit");

    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");


        string strategy;
        if (scotchCoeffs.readIfPresent("strategy", strategy))
        {
            if (debug)
            {
                Info<< "ptscotchDecomp : Using strategy " << strategy << endl;
            }
            SCOTCH_stratDgraphMap(&stradat, strategy.c_str());
            //fprintf(stdout, "S\tStrat=");
            //SCOTCH_stratSave(&stradat, stdout);
            //fprintf(stdout, "\n");
        }
    }


    // Graph
    // ~~~~~

    List<int> velotab;


    // Check for externally provided cellweights and if so initialise weights
    scalar minWeights = gMin(cWeights);
    if (cWeights.size() > 0)
    {
        if (minWeights <= 0)
        {
            WarningIn
            (
                "ptscotchDecomp::decompose(..)"
            )   << "Illegal minimum weight " << minWeights
                << endl;
        }

        if (cWeights.size() != xadj.size()-1)
        {
            FatalErrorIn
            (
                "ptscotchDecomp::decompose(..)"
            )   << "Number of cell weights " << cWeights.size()
                << " does not equal number of cells " << xadj.size()-1
                << exit(FatalError);
        }

        // Convert to integers.
        velotab.setSize(cWeights.size());
        forAll(velotab, i)
        {
            velotab[i] = int(cWeights[i]/minWeights);
        }
    }



    if (debug)
    {
        Pout<< "SCOTCH_dgraphInit" << endl;
    }
    SCOTCH_Dgraph grafdat;
    check(SCOTCH_dgraphInit(&grafdat, MPI_COMM_WORLD), "SCOTCH_dgraphInit");


    if (debug)
    {
        Pout<< "SCOTCH_dgraphBuild with:" << nl
            << "xadj.size()-1   : " << xadj.size()-1 << nl
            << "xadj            : " << long(xadj.begin()) << nl
            << "velotab         : " << long(velotab.begin()) << nl
            << "adjncy.size()   : " << adjncy.size() << nl
            << "adjncy          : " << long(adjncy.begin()) << nl
            << endl;
    }

    check
    (
        SCOTCH_dgraphBuild
        (
            &grafdat,               // grafdat
            0,                      // baseval, c-style numbering
            xadj.size()-1,          // vertlocnbr, nCells
            xadj.size()-1,          // vertlocmax
            const_cast<SCOTCH_Num*>(xadj.begin()),
                                    // vertloctab, start index per cell into
                                    // adjncy
            const_cast<SCOTCH_Num*>(&xadj[1]),// vendloctab, end index  ,,

            const_cast<SCOTCH_Num*>(velotab.begin()),// veloloctab, vtx weights
            NULL,                   // vlblloctab

            adjncy.size(),          // edgelocnbr, number of arcs
            adjncy.size(),          // edgelocsiz
            const_cast<SCOTCH_Num*>(adjncy.begin()),         // edgeloctab
            NULL,                   // edgegsttab
            NULL                    // edlotab, edge weights
        ),
        "SCOTCH_dgraphBuild"
    );


    if (debug)
    {
        Pout<< "SCOTCH_dgraphCheck" << endl;
    }
    check(SCOTCH_dgraphCheck(&grafdat), "SCOTCH_dgraphCheck");


    // Architecture
    // ~~~~~~~~~~~~
    // (fully connected network topology since using switch)

    if (debug)
    {
        Pout<< "SCOTCH_archInit" << endl;
    }
    SCOTCH_Arch archdat;
    check(SCOTCH_archInit(&archdat), "SCOTCH_archInit");

    List<label> processorWeights;
    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");

        scotchCoeffs.readIfPresent("processorWeights", processorWeights);
    }
    if (processorWeights.size())
    {
        if (debug)
        {
            Info<< "ptscotchDecomp : Using procesor weights "
                << processorWeights
                << endl;
        }
        check
        (
            SCOTCH_archCmpltw(&archdat, nProcessors_, processorWeights.begin()),
            "SCOTCH_archCmpltw"
        );
    }
    else
    {
        if (debug)
        {
            Pout<< "SCOTCH_archCmplt" << endl;
        }
        check
        (
            SCOTCH_archCmplt(&archdat, nProcessors_),
            "SCOTCH_archCmplt"
        );
    }


    //SCOTCH_Mapping mapdat;
    //SCOTCH_dgraphMapInit(&grafdat, &mapdat, &archdat, NULL);
    //SCOTCH_dgraphMapCompute(&grafdat, &mapdat, &stradat); /*Perform mapping*/
    //SCOTCHdgraphMapExit(&grafdat, &mapdat);


    // Hack:switch off fpu error trapping
#   ifdef LINUX_GNUC
    int oldExcepts = fedisableexcept
    (
        FE_DIVBYZERO
      | FE_INVALID
      | FE_OVERFLOW
    );
#   endif

    if (debug)
    {
        Pout<< "SCOTCH_dgraphMap" << endl;
    }
    finalDecomp.setSize(xadj.size()-1);
    finalDecomp = 0;
    check
    (
        SCOTCH_dgraphMap
        (
            &grafdat,
            &archdat,
            &stradat,           // const SCOTCH_Strat *
            finalDecomp.begin() // parttab
        ),
        "SCOTCH_graphMap"
    );

#   ifdef LINUX_GNUC
    feenableexcept(oldExcepts);
#   endif



    //finalDecomp.setSize(xadj.size()-1);
    //check
    //(
    //    SCOTCH_dgraphPart
    //    (
    //        &grafdat,
    //        nProcessors_,       // partnbr
    //        &stradat,           // const SCOTCH_Strat *
    //        finalDecomp.begin() // parttab
    //    ),
    //    "SCOTCH_graphPart"
    //);

    if (debug)
    {
        Pout<< "SCOTCH_dgraphExit" << endl;
    }
    // Release storage for graph
    SCOTCH_dgraphExit(&grafdat);
    // Release storage for strategy
    SCOTCH_stratExit(&stradat);
    // Release storage for network topology
    SCOTCH_archExit(&archdat);

    return 0;
}
// Call scotch with options from dictionary.
Foam::label Foam::scotchDecomp::decompose
(
    const List<int>& adjncy,
    const List<int>& xadj,
    const scalarField& cWeights,

    List<int>& finalDecomp
)
{
    // Dump graph
    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");

        if (scotchCoeffs.found("writeGraph"))
        {
            Switch writeGraph(scotchCoeffs.lookup("writeGraph"));

            if (writeGraph)
            {
                OFstream str(mesh_.time().path() / mesh_.name() + ".grf");

                Info<< "Dumping Scotch graph file to " << str.name() << endl
                    << "Use this in combination with gpart." << endl;

                label version = 0;
                str << version << nl;
                // Numer of vertices
                str << xadj.size()-1 << ' ' << adjncy.size() << nl;
                // Numbering starts from 0
                label baseval = 0;
                // Has weights?
                label hasEdgeWeights = 0;
                label hasVertexWeights = 0;
                label numericflag = 10*hasEdgeWeights+hasVertexWeights;
                str << baseval << ' ' << numericflag << nl;
                for (label cellI = 0; cellI < xadj.size()-1; cellI++)
                {
                    label start = xadj[cellI];
                    label end = xadj[cellI+1];
                    str << end-start;

                    for (label i = start; i < end; i++)
                    {
                        str << ' ' << adjncy[i];
                    }
                    str << nl;
                }
            }
        }
    }


    // Strategy
    // ~~~~~~~~

    // Default.
    SCOTCH_Strat stradat;
    check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit");

    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");


        string strategy;
        if (scotchCoeffs.readIfPresent("strategy", strategy))
        {
            if (debug)
            {
                Info<< "scotchDecomp : Using strategy " << strategy << endl;
            }
            SCOTCH_stratGraphMap(&stradat, strategy.c_str());
            //fprintf(stdout, "S\tStrat=");
            //SCOTCH_stratSave(&stradat, stdout);
            //fprintf(stdout, "\n");
        }
    }


    // Graph
    // ~~~~~

    List<int> velotab;


    // Check for externally provided cellweights and if so initialise weights
    scalar minWeights = gMin(cWeights);
    if (cWeights.size() > 0)
    {
        if (minWeights <= 0)
        {
            WarningIn
            (
                "scotchDecomp::decompose"
                "(const pointField&, const scalarField&)"
            )   << "Illegal minimum weight " << minWeights
                << endl;
        }

        if (cWeights.size() != xadj.size()-1)
        {
            FatalErrorIn
            (
                "scotchDecomp::decompose"
                "(const pointField&, const scalarField&)"
            )   << "Number of cell weights " << cWeights.size()
                << " does not equal number of cells " << xadj.size()-1
                << exit(FatalError);
        }

        // Convert to integers.
        velotab.setSize(cWeights.size());
        forAll(velotab, i)
        {
            velotab[i] = int(cWeights[i]/minWeights);
        }
    }



    SCOTCH_Graph grafdat;
    check(SCOTCH_graphInit(&grafdat), "SCOTCH_graphInit");
    check
    (
        SCOTCH_graphBuild
        (
            &grafdat,
            0,                      // baseval, c-style numbering
            xadj.size()-1,          // vertnbr, nCells
            xadj.begin(),           // verttab, start index per cell into adjncy
            &xadj[1],               // vendtab, end index  ,,
            velotab.begin(),        // velotab, vertex weights
            NULL,                   // vlbltab
            adjncy.size(),          // edgenbr, number of arcs
            adjncy.begin(),         // edgetab
            NULL                    // edlotab, edge weights
        ),
        "SCOTCH_graphBuild"
    );
    check(SCOTCH_graphCheck(&grafdat), "SCOTCH_graphCheck");


    // Architecture
    // ~~~~~~~~~~~~
    // (fully connected network topology since using switch)

    SCOTCH_Arch archdat;
    check(SCOTCH_archInit(&archdat), "SCOTCH_archInit");

    List<label> processorWeights;
    if (decompositionDict_.found("scotchCoeffs"))
    {
        const dictionary& scotchCoeffs =
            decompositionDict_.subDict("scotchCoeffs");

        scotchCoeffs.readIfPresent("processorWeights", processorWeights);
    }
    if (processorWeights.size())
    {
        if (debug)
        {
            Info<< "scotchDecomp : Using procesor weights " << processorWeights
                << endl;
        }
        check
        (
            SCOTCH_archCmpltw(&archdat, nProcessors_, processorWeights.begin()),
            "SCOTCH_archCmpltw"
        );
    }
    else
    {
        check
        (
            SCOTCH_archCmplt(&archdat, nProcessors_),
            "SCOTCH_archCmplt"
        );
    }


    //SCOTCH_Mapping mapdat;
    //SCOTCH_graphMapInit(&grafdat, &mapdat, &archdat, NULL);
    //SCOTCH_graphMapCompute(&grafdat, &mapdat, &stradat); /* Perform mapping */
    //SCOTCH_graphMapExit(&grafdat, &mapdat);


    // Hack:switch off fpu error trapping
#   ifdef LINUX_GNUC
    int oldExcepts = fedisableexcept
    (
        FE_DIVBYZERO
      | FE_INVALID
      | FE_OVERFLOW
    );
#   endif

    finalDecomp.setSize(xadj.size()-1);
    finalDecomp = 0;
    check
    (
        SCOTCH_graphMap
        (
            &grafdat,
            &archdat,
            &stradat,           // const SCOTCH_Strat *
            finalDecomp.begin() // parttab
        ),
        "SCOTCH_graphMap"
    );

#   ifdef LINUX_GNUC
    feenableexcept(oldExcepts);
#   endif



    //finalDecomp.setSize(xadj.size()-1);
    //check
    //(
    //    SCOTCH_graphPart
    //    (
    //        &grafdat,
    //        nProcessors_,       // partnbr
    //        &stradat,           // const SCOTCH_Strat *
    //        finalDecomp.begin() // parttab
    //    ),
    //    "SCOTCH_graphPart"
    //);

    // Release storage for graph
    SCOTCH_graphExit(&grafdat);
    // Release storage for strategy
    SCOTCH_stratExit(&stradat);
    // Release storage for network topology
    SCOTCH_archExit(&archdat);

    return 0;
}
Foam::polyBoundaryMesh::polyBoundaryMesh
(
    const IOobject& io,
    const polyMesh& mesh
)
:
    polyPatchList(),
    regIOobject(io),
    mesh_(mesh)
{
    if
    (
        readOpt() == IOobject::MUST_READ
     || readOpt() == IOobject::MUST_READ_IF_MODIFIED
    )
    {
        if (readOpt() == IOobject::MUST_READ_IF_MODIFIED)
        {
            WarningIn
            (
                "polyBoundaryMesh::polyBoundaryMesh\n"
                "(\n"
                "    const IOobject&,\n"
                "    const polyMesh&\n"
                ")"
            )   << "Specified IOobject::MUST_READ_IF_MODIFIED but class"
                << " does not support automatic rereading."
                << endl;
        }


        polyPatchList& patches = *this;

        // Read polyPatchList
        Istream& is = readStream(typeName);

        PtrList<entry> patchEntries(is);
        patches.setSize(patchEntries.size());

        forAll(patches, patchI)
        {
            patches.set
            (
                patchI,
                polyPatch::New
                (
                    patchEntries[patchI].keyword(),
                    patchEntries[patchI].dict(),
                    patchI,
                    *this
                )
            );
        }

        // Check state of IOstream
        is.check
        (
            "polyBoundaryMesh::polyBoundaryMesh"
            "(const IOobject&, const polyMesh&)"
        );

        close();
    }
Exemple #25
0
Foam::polyMesh::readUpdateState Foam::polyMesh::readUpdate()
{
    if (debug)
    {
        Info<< "polyMesh::readUpdateState polyMesh::readUpdate() : "
            << "Updating mesh based on saved data." << endl;
    }

    // Find the point and cell instance
    fileName pointsInst(time().findInstance(meshDir(), "points"));
    fileName facesInst(time().findInstance(meshDir(), "faces"));

    if (debug)
    {
        Info<< "Faces instance: old = " << facesInstance()
            << " new = " << facesInst << nl
            << "Points instance: old = " << pointsInstance()
            << " new = " << pointsInst << endl;
    }

    if (facesInst != facesInstance())
    {
        // Topological change
        if (debug)
        {
            Info<< "Topological change" << endl;
        }

        clearOut();

        // Set instance to new instance. Note that points instance can differ
        // from from faces instance.
        setInstance(facesInst);
        points_.instance() = pointsInst;

        points_ = pointIOField
        (
            IOobject
            (
                "points",
                pointsInst,
                meshSubDir,
                *this,
                IOobject::MUST_READ,
                IOobject::NO_WRITE,
                false
            )
        );

        faces_ = faceCompactIOList
        (
            IOobject
            (
                "faces",
                facesInst,
                meshSubDir,
                *this,
                IOobject::MUST_READ,
                IOobject::NO_WRITE,
                false
            )
        );

        owner_ = labelIOList
        (
            IOobject
            (
                "owner",
                facesInst,
                meshSubDir,
                *this,
                IOobject::READ_IF_PRESENT,
                IOobject::NO_WRITE,
                false
            )
        );

        neighbour_ = labelIOList
        (
            IOobject
            (
                "neighbour",
                facesInst,
                meshSubDir,
                *this,
                IOobject::READ_IF_PRESENT,
                IOobject::NO_WRITE,
                false
            )
        );

        // Reset the boundary patches
        polyBoundaryMesh newBoundary
        (
            IOobject
            (
                "boundary",
                facesInst,
                meshSubDir,
                *this,
                IOobject::MUST_READ,
                IOobject::NO_WRITE,
                false
            ),
            *this
        );

        // Check that patch types and names are unchanged
        bool boundaryChanged = false;

        if (newBoundary.size() != boundary_.size())
        {
            boundaryChanged = true;
        }
        else
        {
            wordList newTypes = newBoundary.types();
            wordList newNames = newBoundary.names();

            wordList oldTypes = boundary_.types();
            wordList oldNames = boundary_.names();

            forAll(oldTypes, patchI)
            {
                if
                (
                    oldTypes[patchI] != newTypes[patchI]
                 || oldNames[patchI] != newNames[patchI]
                )
                {
                    boundaryChanged = true;
                    break;
                }
            }
        }

        if (boundaryChanged)
        {
            WarningIn("polyMesh::readUpdateState polyMesh::readUpdate()")
                << "Number of patches has changed.  This may have "
                << "unexpected consequences.  Proceed with care." << endl;

            boundary_.clear();
            boundary_.setSize(newBoundary.size());

            forAll(newBoundary, patchI)
            {
                boundary_.set(patchI, newBoundary[patchI].clone(boundary_));
            }
        }
        else
        {
scalar
GGIInterpolation<MasterPatch, SlavePatch>::polygonIntersection
(
    const List<point2D>& poly1,
    const List<point2D>& poly2
) const
{
    // Using pointers because clipping and subject may be swapped
    // by the algorithm.  HJ, 24/Oct/2008

    // The first polygon will be the clipping polygon
    const List<point2D>* clippingPolygon = &poly1;

    // Yhe second polygon will be the subject polygon; the one that
    // is going to be clipped
    const List<point2D>* subjectPolygon = &poly2;

    // Empty list so we can detect weird cases later
    List<point2D> clippedPolygon;
    scalar intersectionArea = 0.0;

    // First, let's get rid of the obvious:
    //  1: Neither polygons intersect one another
    //     --> intersection area == 0.0 : that should not happen
    //  2: If both polygons completely overlap one another
    //     ---> subjectPolygon is the intersection polygon
    //  3: If clippingPolygon totally enclosed subjectPolygon
    //     ---> subjectPolygon is the intersecting polygon
    //  4: If subjectPolygon totally enclosed clippingPolygon
    //     --> clippingPolygon is the intersecting polygon
    //  5: Otherwise, we have partial or full intersection
    //
    //  For this, we first detect if the vertices of the subject polygon
    //  are inside or outside of the clipping polygon
    //  This is a quick intersection test...

    // Keep track of who is inside or outside
    List<bool> subjectVertexInside(subjectPolygon->size());

    insideOutside statusInOut =
        isVertexInsidePolygon
        (
            *clippingPolygon,
            *subjectPolygon,
            subjectVertexInside
        );

    // We check right away if statusInOut == ALL_OUTSIDE
    // Sometimes, it is just that the clipping polygon is inside the
    // subject polygon instead So let's explore this situation, just
    // in case
    if (statusInOut == ALL_OUTSIDE)
    {
        // We need to check if subject is not completely or partially
        // enclosing clipping instead

        clippingPolygon = &poly2;
        subjectPolygon  = &poly1;

        subjectVertexInside.setSize(subjectPolygon->size());
        statusInOut =
            isVertexInsidePolygon
            (
                *clippingPolygon,
                *subjectPolygon,
                subjectVertexInside
            );

    }

    switch(statusInOut)
    {
    case ALL_INSIDE:
    {
        clippedPolygon = *subjectPolygon;
        break;
    }
    case ALL_OUTSIDE:
    case PARTIALLY_OVERLAPPING:
    default:
    {
        // Compute the intersection

        // If by any chance, we have reached a situation where the
        // intersection is really zero, it is because the quick
        // reject tests have missed something. The intersection
        // area will be 0.0, and the calling function should at
        // least check for this, and report loudly...
        clippedPolygon =
            clipPolygon2DSutherlandHodgman
            (
                *clippingPolygon,
                *subjectPolygon
            );// For convex polygons

#if 0
        // This is the next candidate to code if the Sutherland
        // Hodgman algorithm encounters concave polygons...
        clippedPolygon =
            clipPolygon2DGreinerHormann
            (
                *clippingPolygon,
                *subjectPolygon,
                subjectVertexInside
            );   // For arbitrary polygons
#endif
        break;
    }
    }

    // Compute the area of clippedPolygon if we indeed do have a
    // clipped polygon; otherwise, the computed area stays at 0.0;
    if (clippedPolygon.size() > 2)
    {
        // We are only interested in the absolute value
        intersectionArea = mag(area2D(clippedPolygon));
    }

    if (debug)
    {
        // Check against tolerances
        scalar clippingArea  = area2D(*clippingPolygon);
        scalar subjectArea   = area2D(*subjectPolygon);

        if
        (
            mag(intersectionArea/clippingArea) < areaErrorTol_
            || mag(intersectionArea/subjectArea)  < areaErrorTol_
        )
        {
            WarningIn
            (
                "GGIInterpolation<MasterPatch, SlavePatch>::"
                "polygonIntersection"
            )   << "Intersection might be wrong wrong: clipping side "
                << intersectionArea/clippingArea << " subject: "
                << intersectionArea/subjectArea << endl;
        }
    }

    return intersectionArea;
}
// Remove a dirctory and it's contents
bool rmDir(const fileName& directory)
{
    if (MSwindows::debug)
    {
        Info<< "rmdir(const fileName&) : "
            << "removing directory " << directory << endl;
    }

    bool success = true;

    // Need to destroy DirectorIterator prior to
    // removing directory otherwise fails on Windows XP
    {
        MSwindows::DirectoryIterator dirIt(directory);

        while (success && dirIt.hasNext())
        {
            const fileName & fName = dirIt.next();

            if (fName != "." && fName != "..")
            {
                fileName path = directory/fName;

                if (path.type() == fileName::DIRECTORY)
                {
                    success = rmDir(path);

                    if (!success)
                    {
                        WarningIn("rmdir(const fileName&)")
                                << "failed to remove directory " << fName
                                << " while removing directory " << directory
                                << endl;
                    }
                }
                else
                {
                    success = rm(path);

                    if (!success)
                    {
                        WarningIn("rmdir(const fileName&)")
                                << "failed to remove file " << fName
                                << " while removing directory " << directory
                                << endl;
                    }
                }
            }
        }
    }

    if (success)
    {
        success = ::RemoveDirectory(directory.c_str());

        if (!success)
        {
            WarningIn("rmdir(const fileName&)")
                    << "failed to remove directory " << directory << endl;
        }
    }

    return success;
}
Exemple #28
0
void Foam::FitData<FitDataType, ExtendedStencil, Polynomial>::calcFit
(
    scalarList& coeffsi,
    const List<point>& C,
    const scalar wLin,
    const label facei
)
{
    vector idir(1,0,0);
    vector jdir(0,1,0);
    vector kdir(0,0,1);
    findFaceDirs(idir, jdir, kdir, facei);

    // Setup the point weights
    scalarList wts(C.size(), scalar(1));
    wts[0] = centralWeight_;
    if (linearCorrection_)
    {
        wts[1] = centralWeight_;
    }

    // Reference point
    point p0 = this->mesh().faceCentres()[facei];

    // Info << "Face " << facei << " at " << p0 << " stencil points at:\n"
    //     << C - p0 << endl;

    // p0 -> p vector in the face-local coordinate system
    vector d;

    // Local coordinate scaling
    scalar scale = 1;

    // Matrix of the polynomial components
    scalarRectangularMatrix B(C.size(), minSize_, scalar(0));

    for(label ip = 0; ip < C.size(); ip++)
    {
        const point& p = C[ip];

        d.x() = (p - p0)&idir;
        d.y() = (p - p0)&jdir;
#       ifndef SPHERICAL_GEOMETRY
        d.z() = (p - p0)&kdir;
#       else
        d.z() = mag(p) - mag(p0);
#       endif

        if (ip == 0)
        {
            scale = cmptMax(cmptMag((d)));
        }

        // Scale the radius vector
        d /= scale;

        Polynomial::addCoeffs
        (
            B[ip],
            d,
            wts[ip],
            dim_
        );
    }

    // Additional weighting for constant and linear terms
    for(label i = 0; i < B.n(); i++)
    {
        B[i][0] *= wts[0];
        B[i][1] *= wts[0];
    }

    // Set the fit
    label stencilSize = C.size();
    coeffsi.setSize(stencilSize);

    bool goodFit = false;
    for(int iIt = 0; iIt < 8 && !goodFit; iIt++)
    {
        SVD svd(B, SMALL);

        scalar maxCoeff = 0;
        label maxCoeffi = 0;

        for(label i=0; i<stencilSize; i++)
        {
            coeffsi[i] = wts[0]*wts[i]*svd.VSinvUt()[0][i];
            if (mag(coeffsi[i]) > maxCoeff)
            {
                maxCoeff = mag(coeffsi[i]);
                maxCoeffi = i;
            }
        }

        if (linearCorrection_)
        {
            goodFit =
                (mag(coeffsi[0] - wLin) < linearLimitFactor_*wLin)
             && (mag(coeffsi[1] - (1 - wLin)) < linearLimitFactor_*(1 - wLin))
             && maxCoeffi <= 1;
        }
        else
        {
            // Upwind: weight on face is 1.
            goodFit =
                (mag(coeffsi[0] - 1.0) < linearLimitFactor_*1.0)
             && maxCoeffi <= 1;
        }

        // if (goodFit && iIt > 0)
        // {
            // Info << "FitData<Polynomial>::calcFit"
            //     << "(const List<point>& C, const label facei" << nl
            //     << "Can now fit face " << facei << " iteration " << iIt
            //     << " with sum of weights " << sum(coeffsi) << nl
            //     << "    Weights " << coeffsi << nl
            //     << "    Linear weights " << wLin << " " << 1 - wLin << nl
            //     << "    sing vals " << svd.S() << endl;
        // }

        if (!goodFit) // (not good fit so increase weight in the centre and weight
                      //  for constant and linear terms)
        {
            // if (iIt == 7)
            // {
            //     WarningIn
            //     (
            //         "FitData<Polynomial>::calcFit"
            //         "(const List<point>& C, const label facei"
            //     )   << "Cannot fit face " << facei << " iteration " << iIt
            //         << " with sum of weights " << sum(coeffsi) << nl
            //         << "    Weights " << coeffsi << nl
            //         << "    Linear weights " << wLin << " " << 1 - wLin << nl
            //         << "    sing vals " << svd.S() << endl;
            // }

            wts[0] *= 10;
            if (linearCorrection_)
            {
                wts[1] *= 10;
            }

            for(label j = 0; j < B.m(); j++)
            {
                B[0][j] *= 10;
                B[1][j] *= 10;
            }

            for(label i = 0; i < B.n(); i++)
            {
                B[i][0] *= 10;
                B[i][1] *= 10;
            }
        }
    }

    if (goodFit)
    {
        if (linearCorrection_)
        {
            // Remove the uncorrected linear coefficients
            coeffsi[0] -= wLin;
            coeffsi[1] -= 1 - wLin;
        }
        else
        {
            // Remove the uncorrected upwind coefficients
            coeffsi[0] -= 1.0;
        }
    }
    else
    {
        // if (debug)
        // {
            WarningIn
            (
                "FitData<Polynomial>::calcFit(..)"
            )   << "Could not fit face " << facei
                << "    Weights = " << coeffsi
                << ", reverting to linear." << nl
                << "    Linear weights " << wLin << " " << 1 - wLin << endl;
        // }

        coeffsi = 0;
    }
}
void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology)
{
    Info<< "Mesh stats" << nl
        << "    points:           "
        << returnReduce(mesh.points().size(), sumOp<label>()) << nl;

    label nInternalPoints = returnReduce
    (
        mesh.nInternalPoints(),
        sumOp<label>()
    );

    if (nInternalPoints != -Pstream::nProcs())
    {
        Info<< "    internal points:  " << nInternalPoints << nl;

        if (returnReduce(mesh.nInternalPoints(), minOp<label>()) == -1)
        {
            WarningIn("Foam::printMeshStats(const polyMesh&, const bool)")
                << "Some processors have their points sorted into internal"
                << " and external and some do not." << endl
                << "This can cause problems later on." << endl;
        }
    }

    if (allTopology && nInternalPoints != -Pstream::nProcs())
    {
        label nEdges = returnReduce(mesh.nEdges(), sumOp<label>());
        label nInternalEdges = returnReduce
        (
            mesh.nInternalEdges(),
            sumOp<label>()
        );
        label nInternal1Edges = returnReduce
        (
            mesh.nInternal1Edges(),
            sumOp<label>()
        );
        label nInternal0Edges = returnReduce
        (
            mesh.nInternal0Edges(),
            sumOp<label>()
        );

        Info<< "    edges:            " << nEdges << nl
            << "    internal edges:   " << nInternalEdges << nl
            << "    internal edges using one boundary point:   "
            << nInternal1Edges-nInternal0Edges << nl
            << "    internal edges using two boundary points:  "
            << nInternalEdges-nInternal1Edges << nl;
    }

    label nFaces = returnReduce(mesh.faces().size(), sumOp<label>());
    label nIntFaces = returnReduce(mesh.faceNeighbour().size(), sumOp<label>());
    label nCells = returnReduce(mesh.cells().size(), sumOp<label>());

    Info<< "    faces:            " << nFaces << nl
        << "    internal faces:   " << nIntFaces << nl
        << "    cells:            " << nCells << nl
        << "    faces per cell:   "
        << scalar(nFaces + nIntFaces)/max(1, nCells) << nl
        << "    boundary patches: " << mesh.boundaryMesh().size() << nl
        << "    point zones:      " << mesh.pointZones().size() << nl
        << "    face zones:       " << mesh.faceZones().size() << nl
        << "    cell zones:       " << mesh.cellZones().size() << nl
        << endl;

    // Construct shape recognizers
    hexMatcher hex;
    prismMatcher prism;
    wedgeMatcher wedge;
    pyrMatcher pyr;
    tetWedgeMatcher tetWedge;
    tetMatcher tet;

    // Counters for different cell types
    label nHex = 0;
    label nWedge = 0;
    label nPrism = 0;
    label nPyr = 0;
    label nTet = 0;
    label nTetWedge = 0;
    label nUnknown = 0;

    Map<label> polyhedralFaces;

    for (label cellI = 0; cellI < mesh.nCells(); cellI++)
    {
        if (hex.isA(mesh, cellI))
        {
            nHex++;
        }
        else if (tet.isA(mesh, cellI))
        {
            nTet++;
        }
        else if (pyr.isA(mesh, cellI))
        {
            nPyr++;
        }
        else if (prism.isA(mesh, cellI))
        {
            nPrism++;
        }
        else if (wedge.isA(mesh, cellI))
        {
            nWedge++;
        }
        else if (tetWedge.isA(mesh, cellI))
        {
            nTetWedge++;
        }
        else
        {
            nUnknown++;
            polyhedralFaces(mesh.cells()[cellI].size())++;
        }
    }

    reduce(nHex,sumOp<label>());
    reduce(nPrism,sumOp<label>());
    reduce(nWedge,sumOp<label>());
    reduce(nPyr,sumOp<label>());
    reduce(nTetWedge,sumOp<label>());
    reduce(nTet,sumOp<label>());
    reduce(nUnknown,sumOp<label>());

    Info<< "Overall number of cells of each type:" << nl
        << "    hexahedra:     " << nHex << nl
        << "    prisms:        " << nPrism << nl
        << "    wedges:        " << nWedge << nl
        << "    pyramids:      " << nPyr << nl
        << "    tet wedges:    " << nTetWedge << nl
        << "    tetrahedra:    " << nTet << nl
        << "    polyhedra:     " << nUnknown
        << endl;

    if (nUnknown > 0)
    {
        Pstream::mapCombineGather(polyhedralFaces, plusEqOp<label>());

        Info<< "    Breakdown of polyhedra by number of faces:" << nl
            << "        faces" << "   number of cells" << endl;

        const labelList sortedKeys = polyhedralFaces.sortedToc();

        forAll(sortedKeys, keyI)
        {
            const label nFaces = sortedKeys[keyI];

            Info<< setf(std::ios::right) << setw(13)
                << nFaces << "   " << polyhedralFaces[nFaces] << nl;
        }
    }
Foam::SVD::SVD(const scalarRectangularMatrix& A, const scalar minCondition)
:
    U_(A),
    V_(A.m(), A.m()),
    S_(A.m()),
    VSinvUt_(A.m(), A.n()),
    nZeros_(0)
{
    // SVDcomp to find U_, V_ and S_ - the singular values

    const label Um = U_.m();
    const label Un = U_.n();

    scalarList rv1(Um);
    scalar g = 0;
    scalar scale = 0;
    scalar s = 0;
    scalar anorm = 0;
    label l = 0;

    for (label i = 0; i < Um; i++)
    {
        l = i+2;
        rv1[i] = scale*g;
        g = s = scale = 0;

        if (i < Un)
        {
            for (label k = i; k < Un; k++)
            {
                scale += mag(U_[k][i]);
            }

            if (scale != 0)
            {
                for (label k = i; k < Un; k++)
                {
                    U_[k][i] /= scale;
                    s += U_[k][i]*U_[k][i];
                }

                scalar f = U_[i][i];
                g = -sign(Foam::sqrt(s), f);
                scalar h = f*g - s;
                U_[i][i] = f - g;

                for (label j = l-1; j < Um; j++)
                {
                    s = 0;
                    for (label k = i; k < Un; k++)
                    {
                        s += U_[k][i]*U_[k][j];
                    }

                    f = s/h;
                    for (label k = i; k < A.n(); k++)
                    {
                        U_[k][j] += f*U_[k][i];
                    }
                }

                for (label k = i; k < Un; k++)
                {
                    U_[k][i] *= scale;
                }
            }
        }

        S_[i] = scale*g;

        g = s = scale = 0;

        if (i+1 <= Un && i != Um)
        {
            for (label k = l-1; k < Um; k++)
            {
                scale += mag(U_[i][k]);
            }

            if (scale != 0)
            {
                for (label k=l-1; k < Um; k++)
                {
                    U_[i][k] /= scale;
                    s += U_[i][k]*U_[i][k];
                }

                scalar f = U_[i][l-1];
                g = -sign(Foam::sqrt(s),f);
                scalar h = f*g - s;
                U_[i][l-1] = f - g;

                for (label k = l-1; k < Um; k++)
                {
                    rv1[k] = U_[i][k]/h;
                }

                for (label j = l-1; j < Un; j++)
                {
                    s = 0;
                    for (label k = l-1; k < Um; k++)
                    {
                        s += U_[j][k]*U_[i][k];
                    }

                    for (label k = l-1; k < Um; k++)
                    {
                        U_[j][k] += s*rv1[k];
                    }
                }
                for (label k = l-1; k < Um; k++)
                {
                    U_[i][k] *= scale;
                }
            }
        }

        anorm = max(anorm, mag(S_[i]) + mag(rv1[i]));
    }

    for (label i = Um-1; i >= 0; i--)
    {
        if (i < Um-1)
        {
            if (g != 0)
            {
                for (label j = l; j < Um; j++)
                {
                    V_[j][i] = (U_[i][j]/U_[i][l])/g;
                }

                for (label j=l; j < Um; j++)
                {
                    s = 0;
                    for (label k = l; k < Um; k++)
                    {
                        s += U_[i][k]*V_[k][j];
                    }

                    for (label k = l; k < Um; k++)
                    {
                        V_[k][j] += s*V_[k][i];
                    }
                }
            }

            for (label j = l; j < Um;j++)
            {
                V_[i][j] = V_[j][i] = 0.0;
            }
        }

        V_[i][i] = 1;
        g = rv1[i];
        l = i;
    }

    for (label i = min(Um, Un) - 1; i >= 0; i--)
    {
        l = i+1;
        g = S_[i];

        for (label j = l; j < Um; j++)
        {
            U_[i][j] = 0.0;
        }

        if (g != 0)
        {
            g = 1.0/g;

            for (label j = l; j < Um; j++)
            {
                s = 0;
                for (label k = l; k < Un; k++)
                {
                    s += U_[k][i]*U_[k][j];
                }

                scalar f = (s/U_[i][i])*g;

                for (label k = i; k < Un; k++)
                {
                    U_[k][j] += f*U_[k][i];
                }
            }

            for (label j = i; j < Un; j++)
            {
                U_[j][i] *= g;
            }
        }
        else
        {
            for (label j = i; j < Un; j++)
            {
                U_[j][i] = 0.0;
            }
        }

        ++U_[i][i];
    }

    for (label k = Um-1; k >= 0; k--)
    {
        for (label its = 0; its < 35; its++)
        {
            bool flag = true;

            label nm;
            for (l = k; l >= 0; l--)
            {
                nm = l-1;
                if (mag(rv1[l]) + anorm == anorm)
                {
                    flag = false;
                    break;
                }
                if (mag(S_[nm]) + anorm == anorm) break;
            }

            if (flag)
            {
                scalar c = 0.0;
                s = 1.0;
                for (label i = l-1; i < k+1; i++)
                {
                    scalar f = s*rv1[i];
                    rv1[i] = c*rv1[i];

                    if (mag(f) + anorm == anorm) break;

                    g = S_[i];
                    scalar h = sqrtSumSqr(f, g);
                    S_[i] = h;
                    h = 1.0/h;
                    c = g*h;
                    s = -f*h;

                    for (label j = 0; j < Un; j++)
                    {
                        scalar y = U_[j][nm];
                        scalar z = U_[j][i];
                        U_[j][nm] = y*c + z*s;
                        U_[j][i] = z*c - y*s;
                    }
                }
            }

            scalar z = S_[k];

            if (l == k)
            {
                if (z < 0.0)
                {
                    S_[k] = -z;

                    for (label j = 0; j < Um; j++) V_[j][k] = -V_[j][k];
                }
                break;
            }
            if (its == 34)
            {
                WarningIn
                (
                    "SVD::SVD"
                    "(scalarRectangularMatrix& A, const scalar minCondition)"
                )   << "no convergence in 35 SVD iterations"
                    << endl;
            }

            scalar x = S_[l];
            nm = k-1;
            scalar y = S_[nm];
            g = rv1[nm];
            scalar h = rv1[k];
            scalar f = ((y - z)*(y + z) + (g - h)*(g + h))/(2.0*h*y);
            g = sqrtSumSqr(f, scalar(1));
            f = ((x - z)*(x + z) + h*((y/(f + sign(g, f))) - h))/x;
            scalar c = 1.0;
            s = 1.0;

            for (label j = l; j <= nm; j++)
            {
                label i = j + 1;
                g = rv1[i];
                y = S_[i];
                h = s*g;
                g = c*g;
                scalar z = sqrtSumSqr(f, h);
                rv1[j] = z;
                c = f/z;
                s = h/z;
                f = x*c + g*s;
                g = g*c - x*s;
                h = y*s;
                y *= c;

                for (label jj = 0; jj < Um; jj++)
                {
                    x = V_[jj][j];
                    z = V_[jj][i];
                    V_[jj][j] = x*c + z*s;
                    V_[jj][i] = z*c - x*s;
                }

                z = sqrtSumSqr(f, h);
                S_[j] = z;
                if (z)
                {
                    z = 1.0/z;
                    c = f*z;
                    s = h*z;
                }
                f = c*g + s*y;
                x = c*y - s*g;

                for (label jj=0; jj < Un; jj++)
                {
                    y = U_[jj][j];
                    z = U_[jj][i];
                    U_[jj][j] = y*c + z*s;
                    U_[jj][i] = z*c - y*s;
                }
            }
            rv1[l] = 0.0;
            rv1[k] = f;
            S_[k] = x;
        }
    }

    // zero singular values that are less than minCondition*maxS
    const scalar minS = minCondition*S_[findMax(S_)];
    for (label i = 0; i < S_.size(); i++)
    {
        if (S_[i] <= minS)
        {
            //Info << "Removing " << S_[i] << " < " << minS << endl;
            S_[i] = 0;
            nZeros_++;
        }
    }

    // now multiply out to find the pseudo inverse of A, VSinvUt_
    multiply(VSinvUt_, V_, inv(S_), U_.T());

    // test SVD
    /*scalarRectangularMatrix SVDA(A.n(), A.m());
    multiply(SVDA, U_, S_, transpose(V_));
    scalar maxDiff = 0;
    scalar diff = 0;
    for(label i = 0; i < A.n(); i++)
    {
        for(label j = 0; j < A.m(); j++)
        {
            diff = mag(A[i][j] - SVDA[i][j]);
            if (diff > maxDiff) maxDiff = diff;
        }
    }
    Info << "Maximum discrepancy between A and svd(A) = " << maxDiff << endl;

    if (maxDiff > 4)
    {
        Info << "singular values " << S_ << endl;
    }
    */
}