void Foam::GAMGAgglomeration::agglomerateLduAddressing
(
    const label fineLevelIndex
)
{
    const lduMesh& fineMesh = meshLevel(fineLevelIndex);
    const lduAddressing& fineMeshAddr = fineMesh.lduAddr();

    const labelUList& upperAddr = fineMeshAddr.upperAddr();
    const labelUList& lowerAddr = fineMeshAddr.lowerAddr();

    label nFineFaces = upperAddr.size();

    // Get restriction map for current level
    const labelField& restrictMap = restrictAddressing(fineLevelIndex);

    if (min(restrictMap) == -1)
    {
        FatalErrorInFunction
            << "min(restrictMap) == -1" << exit(FatalError);
    }

    if (restrictMap.size() != fineMeshAddr.size())
    {
        FatalErrorInFunction
            << "restrict map does not correspond to fine level. " << endl
            << " Sizes: restrictMap: " << restrictMap.size()
            << " nEqns: " << fineMeshAddr.size()
            << abort(FatalError);
    }


    // Get the number of coarse cells
    const label nCoarseCells = nCells_[fineLevelIndex];

    // Storage for coarse cell neighbours and coefficients

    // Guess initial maximum number of neighbours in coarse cell
    label maxNnbrs = 10;

    // Number of faces for each coarse-cell
    labelList cCellnFaces(nCoarseCells, 0);

    // Setup initial packed storage for coarse-cell faces
    labelList cCellFaces(maxNnbrs*nCoarseCells);

    // Create face-restriction addressing
    faceRestrictAddressing_.set(fineLevelIndex, new labelList(nFineFaces));
    labelList& faceRestrictAddr = faceRestrictAddressing_[fineLevelIndex];

    // Initial neighbour array (not in upper-triangle order)
    labelList initCoarseNeighb(nFineFaces);

    // Counter for coarse faces
    label& nCoarseFaces = nFaces_[fineLevelIndex];
    nCoarseFaces = 0;

    // Loop through all fine faces
    forAll(upperAddr, fineFacei)
    {
        label rmUpperAddr = restrictMap[upperAddr[fineFacei]];
        label rmLowerAddr = restrictMap[lowerAddr[fineFacei]];

        if (rmUpperAddr == rmLowerAddr)
        {
            // For each fine face inside of a coarse cell keep the address
            // of the cell corresponding to the face in the faceRestrictAddr
            // as a negative index
            faceRestrictAddr[fineFacei] = -(rmUpperAddr + 1);
        }
        else
        {
            // this face is a part of a coarse face

            label cOwn = rmUpperAddr;
            label cNei = rmLowerAddr;

            // get coarse owner and neighbour
            if (rmUpperAddr > rmLowerAddr)
            {
                cOwn = rmLowerAddr;
                cNei = rmUpperAddr;
            }

            // check the neighbour to see if this face has already been found
            label* ccFaces = &cCellFaces[maxNnbrs*cOwn];

            bool nbrFound = false;
            label& ccnFaces = cCellnFaces[cOwn];

            for (int i=0; i<ccnFaces; i++)
            {
                if (initCoarseNeighb[ccFaces[i]] == cNei)
                {
                    nbrFound = true;
                    faceRestrictAddr[fineFacei] = ccFaces[i];
                    break;
                }
            }

            if (!nbrFound)
            {
                if (ccnFaces >= maxNnbrs)
                {
                    label oldMaxNnbrs = maxNnbrs;
                    maxNnbrs *= 2;

                    cCellFaces.setSize(maxNnbrs*nCoarseCells);

                    forAllReverse(cCellnFaces, i)
                    {
                        label* oldCcNbrs = &cCellFaces[oldMaxNnbrs*i];
                        label* newCcNbrs = &cCellFaces[maxNnbrs*i];

                        for (int j=0; j<cCellnFaces[i]; j++)
                        {
                            newCcNbrs[j] = oldCcNbrs[j];
                        }
                    }

                    ccFaces = &cCellFaces[maxNnbrs*cOwn];
                }

                ccFaces[ccnFaces] = nCoarseFaces;
                initCoarseNeighb[nCoarseFaces] = cNei;
                faceRestrictAddr[fineFacei] = nCoarseFaces;
                ccnFaces++;

                // new coarse face created
                nCoarseFaces++;
            }
Foam::MGridGenGAMGAgglomeration::MGridGenGAMGAgglomeration
(
    const lduMesh& mesh,
    const dictionary& dict
)
:
    GAMGAgglomeration(mesh, dict),
    fvMesh_(refCast<const fvMesh>(mesh))
{
    // Min, max size of agglomerated cells
    label minSize(readLabel(dict.lookup("minSize")));
    label maxSize(readLabel(dict.lookup("maxSize")));


    // Get the finest-level interfaces from the mesh
    interfaceLevels_.set
    (
        0,
        new lduInterfacePtrsList(fvMesh_.boundary().interfaces())
    );

    // Start geometric agglomeration from the cell volumes and areas of the mesh
    scalarField* VPtr = const_cast<scalarField*>(&fvMesh_.cellVolumes());
    vectorField* SfPtr = const_cast<vectorField*>(&fvMesh_.faceAreas());

    // Create the boundary area cell field
    scalarField* SbPtr(new scalarField(fvMesh_.nCells(), 0));

    {
        scalarField& Sb = *SbPtr;

        const labelList& own = fvMesh_.faceOwner();
        const vectorField& Sf = fvMesh_.faceAreas();

        forAll(Sf, facei)
        {
            if (!fvMesh_.isInternalFace(facei))
            {
                Sb[own[facei]] += mag(Sf[facei]);
            }
        }
    }


    // Agglomerate until the required number of cells in the coarsest level
    // is reached

    label nCreatedLevels = 0;

    while (nCreatedLevels < maxLevels_ - 1)
    {
        label nCoarseCells = -1;

        tmp<labelField> finalAgglomPtr = agglomerate
        (
            nCoarseCells,
            minSize,
            maxSize,
            meshLevel(nCreatedLevels).lduAddr(),
            *VPtr,
            *SfPtr,
            *SbPtr
        );

        if (continueAgglomerating(nCoarseCells))
        {
            nCells_[nCreatedLevels] = nCoarseCells;
            restrictAddressing_.set(nCreatedLevels, finalAgglomPtr);
        }
        else
        {
            break;
        }

        agglomerateLduAddressing(nCreatedLevels);

        // Agglomerate the cell volumes field for the next level
        {
            scalarField* aggVPtr
            (
                new scalarField(meshLevels_[nCreatedLevels].size())
            );

            restrictField(*aggVPtr, *VPtr, nCreatedLevels);

            if (nCreatedLevels)
            {
                delete VPtr;
            }

            VPtr = aggVPtr;
        }

        // Agglomerate the face areas field for the next level
        {
            vectorField* aggSfPtr
            (
                new vectorField
                (
                    meshLevels_[nCreatedLevels].upperAddr().size(),
                    vector::zero
                )
            );

            restrictFaceField(*aggSfPtr, *SfPtr, nCreatedLevels);

            if (nCreatedLevels)
            {
                delete SfPtr;
            }

            SfPtr = aggSfPtr;
        }

        // Agglomerate the cell boundary areas field for the next level
        {
            scalarField* aggSbPtr
            (
                new scalarField(meshLevels_[nCreatedLevels].size())
            );

            restrictField(*aggSbPtr, *SbPtr, nCreatedLevels);

            delete SbPtr;
            SbPtr = aggSbPtr;
        }

        nCreatedLevels++;
    }

    // Shrink the storage of the levels to those created
    compactLevels(nCreatedLevels);

    // Delete temporary geometry storage
    if (nCreatedLevels)
    {
        delete VPtr;
        delete SfPtr;
    }
    delete SbPtr;
}
Exemplo n.º 3
0
void Foam::GAMGAgglomeration::compactLevels(const label nCreatedLevels)
{
    nCells_.setSize(nCreatedLevels);
    restrictAddressing_.setSize(nCreatedLevels);
    nFaces_.setSize(nCreatedLevels);
    faceRestrictAddressing_.setSize(nCreatedLevels);
    faceFlipMap_.setSize(nCreatedLevels);
    nPatchFaces_.setSize(nCreatedLevels);
    patchFaceRestrictAddressing_.setSize(nCreatedLevels);
    meshLevels_.setSize(nCreatedLevels);

    // Have procCommunicator_ always, even if not procAgglomerating
    procCommunicator_.setSize(nCreatedLevels + 1);
    if (processorAgglomerate())
    {
        procAgglomMap_.setSize(nCreatedLevels);
        agglomProcIDs_.setSize(nCreatedLevels);
        procCellOffsets_.setSize(nCreatedLevels);
        procFaceMap_.setSize(nCreatedLevels);
        procBoundaryMap_.setSize(nCreatedLevels);
        procBoundaryFaceMap_.setSize(nCreatedLevels);

        procAgglomeratorPtr_().agglomerate();


    }

    // Print a bit
    if (processorAgglomerate() && debug)
    {
        Info<< "GAMGAgglomeration:" << nl
            << "    local agglomerator     : " << type() << nl;
        if (processorAgglomerate())
        {
            Info<< "    processor agglomerator : "
                << procAgglomeratorPtr_().type() << nl
                << nl;
        }

        Info<< setw(36) << "nCells"
            << setw(20) << "nFaces/nCells"
            << setw(20) << "nInterfaces"
            << setw(20) << "nIntFaces/nCells"
            << setw(12) << "profile"
            << nl
            << setw(8) << "Level"
            << setw(8) << "nProcs"
            << "    "
            << setw(8) << "avg"
            << setw(8) << "max"
            << "    "
            << setw(8) << "avg"
            << setw(8) << "max"
            << "    "
            << setw(8) << "avg"
            << setw(8) << "max"
            << "    "
            << setw(8) << "avg"
            << setw(8) << "max"
            //<< "    "
            << setw(12) << "avg"
            << nl
            << setw(8) << "-----"
            << setw(8) << "------"
            << "    "
            << setw(8) << "---"
            << setw(8) << "---"
            << "    "
            << setw(8) << "---"
            << setw(8) << "---"
            << "    "
            << setw(8) << "---"
            << setw(8) << "---"
            << "    "
            << setw(8) << "---"
            << setw(8) << "---"
            //<< "    "
            << setw(12) << "---"
            //<< "    "
            << nl;

        for (label levelI = 0; levelI <= size(); levelI++)
        {
            label nProcs = 0;
            label nCells = 0;
            scalar faceCellRatio = 0;
            label nInterfaces = 0;
            label nIntFaces = 0;
            scalar ratio = 0.0;
            scalar profile = 0.0;

            if (hasMeshLevel(levelI))
            {
                nProcs = 1;

                const lduMesh& fineMesh = meshLevel(levelI);
                nCells = fineMesh.lduAddr().size();
                faceCellRatio =
                    scalar(fineMesh.lduAddr().lowerAddr().size())/nCells;

                const lduInterfacePtrsList interfaces =
                    fineMesh.interfaces();
                forAll(interfaces, i)
                {
                    if (interfaces.set(i))
                    {
                        nInterfaces++;
                        nIntFaces += interfaces[i].faceCells().size();
                    }
                }
                ratio = scalar(nIntFaces)/nCells;

                profile = fineMesh.lduAddr().band().second();
            }

            label totNprocs = returnReduce(nProcs, sumOp<label>());

            label maxNCells = returnReduce(nCells, maxOp<label>());
            label totNCells = returnReduce(nCells, sumOp<label>());

            scalar maxFaceCellRatio =
                returnReduce(faceCellRatio, maxOp<scalar>());
            scalar totFaceCellRatio =
                returnReduce(faceCellRatio, sumOp<scalar>());

            label maxNInt = returnReduce(nInterfaces, maxOp<label>());
            label totNInt = returnReduce(nInterfaces, sumOp<label>());

            scalar maxRatio = returnReduce(ratio, maxOp<scalar>());
            scalar totRatio = returnReduce(ratio, sumOp<scalar>());

            scalar totProfile = returnReduce(profile, sumOp<scalar>());

            int oldPrecision = Info().precision(4);

            Info<< setw(8) << levelI
                << setw(8) << totNprocs
                << "    "
                << setw(8) << totNCells/totNprocs
                << setw(8) << maxNCells
                << "    "
                << setw(8) << totFaceCellRatio/totNprocs
                << setw(8) << maxFaceCellRatio
                << "    "
                << setw(8) << scalar(totNInt)/totNprocs
                << setw(8) << maxNInt
                << "    "
                << setw(8) << totRatio/totNprocs
                << setw(8) << maxRatio
                << setw(12) << totProfile/totNprocs
                << nl;

            Info().precision(oldPrecision);
        }
        Info<< endl;
    }