Snip calculating mass flow

From OpenFOAMWiki

1 Description

This describes how to set up the solver in order to calculate the mass fluxes on the boundary. It works in serial and parallel.

It was taken from the thread Calculation of integral boundary values.

2 Preparing the solver

Firstly, you need to #include "SortableList.H" as one of the top level includes in a solver application.

Then #include "buildGlobalBoundaryList.H" once "createMesh.H" and other initialisations have been run in the main function. (This only needs to be run once.)

The result of this is a wordList variable called "globalPatchNames" that is available on each processor, and contains a sorted list of all real patches in the model.

To compute mass fluxes after each timestep, #include "computeMassFlux.H"

3 The files

3.1 buildGlobalBoundaryList.H

 
#include "SortableList.H"
 
wordList buildGlobalBoundaryList(polyMesh &mesh)
{
    int i;
    label numPatches;
    SortableList<word> sortablePatchNames(0);
    List<wordList> gatheredPatchNames(Pstream::nProcs());
 
    Info<< "Building global boundary list" << endl;
 
    // collect all real patches into a wordList
    wordList realPatches(0);
    forAll (mesh.boundaryMesh(), patchIndex)
    {
        const polyPatch& patch = mesh.boundaryMesh()[patchIndex];
        if (typeid(patch) != typeid(processorPolyPatch))
        {
            realPatches.setSize(realPatches.size()+1);
            realPatches[realPatches.size()-1] = patch.name();
        }
    }
 
    // gather real patches from each processor
    gatheredPatchNames[Pstream::myProcNo()] = realPatches;
    Pstream::gatherList(gatheredPatchNames);
 
    if (Pstream::master())
    {
        // store unique patches (using a HashSet)
        HashSet<word> hashSetPatchNames(0);
        forAll (gatheredPatchNames, patchListProc)
        {
            forAll (gatheredPatchNames[patchListProc], patchNameItr)
            {
                hashSetPatchNames.insert(
                    gatheredPatchNames[patchListProc][patchNameItr]
                    );
            }
        }
 
        // store patch names into a SortableList
        sortablePatchNames.setSize(hashSetPatchNames.size());
        i=0;
        for
        (
            HashSet<word>::const_iterator iter = hashSetPatchNames.begin();
            iter != hashSetPatchNames.end();
            ++iter
        )
        {
            sortablePatchNames[i++] = iter.key();
        }
 
        // *** SORT CAUSES SEG-FAULT **********
	// sortablePatchNames.sort();
        // ************************************
 
        // save the number of patches
        numPatches = sortablePatchNames.size();
    }
 
    // scatter the number of patches to each processor
    Pstream::scatter(numPatches);
 
    // reset the list size on all other processors
    if (!Pstream::master())
    {
        sortablePatchNames.setSize(numPatches);
    }
 
    // scatter individual patch names to each processor
    // and rebuild the patch list
    word tmpPatchName;
    for (i=0; i<numPatches; i++)
    {
        if(Pstream::master())
        {
            tmpPatchName = sortablePatchNames[i];
        }
        Pstream::scatter(tmpPatchName);
        if(!Pstream::master())
        {
            sortablePatchNames[i] = tmpPatchName;
        }
    }
 
    // return the global patch names
    return sortablePatchNames;
}

3.2 calculateMassFlux.H

 
{
    scalar netFlux = 0;
    forAll (globalBoundaryList, patchI)
    {
        scalar flux = 0;
        label patchIndex = mesh.boundaryMesh().findPatchID(globalBoundaryList[patchI]);
        if (patchIndex >= 0)
        {
            flux = sum(phi.boundaryField()[patchIndex]);
        }
        reduce(flux, sumOp<scalar>());
        Info<< "Mass flux at " << globalBoundaryList[patchI]
            << " = " << flux << endl;
        netFlux += flux;
    }
    Info<< "Net mass flux = " << netFlux << endl << endl;
}