CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Accessing local cell index with global cell index in functionObject (https://www.cfd-online.com/Forums/openfoam-programming-development/236160-accessing-local-cell-index-global-cell-index-functionobject.html)

Shibi May 16, 2021 16:53

Accessing local cell index with global cell index in functionObject
 
Hello to all,

In a functionObject I am coding, I need to access the values of pressure of cellID {20, 70, 30, 50, 90}, in this order.


I using a 2D square domain with 10x10 cells for testing decomposed in 2 processors.


I have the following code.

Code:

  List<scalar> cellIds{20, 70, 30, 50, 90};
  List<scalar> pValues(cellIds.size() );

  const volScalarField& sField = lookupObject<volScalarField>("p");

    forAll(cellIds, cellI)
    {
          pValues[cellI] = sField [ cellIds [cellI] ];

    }

In serial, this will run without a problem. In parallel the domain is decomposed into 50 cells for each processor. So, when I try to access
sField[70], it will give me the following error:


Code:

[1]
[1]
[1] --> FOAM FATAL ERROR: (openfoam-2012)
[1] index 70 out of range [0,50]
[1]
[1]    From void Foam::UList<T>::checkIndex(Foam::label) const [with T = double; Foam::label = int]
[1]    in file /home/pc/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/lnInclude/UListI.H at line 138.
[1]
FOAM parallel run aborting
[1]
[0]
[0]
[0] --> FOAM FATAL ERROR: (openfoam-2012)
[0] index 70 out of range [0,50]
[0]
[0]    From void Foam::UList<T>::checkIndex(Foam::label) const [with T = double; Foam::label = int]
[0]    in file /home/pc/OpenFOAM/OpenFOAM-v2012/src/OpenFOAM/lnInclude/UListI.H at line 138.
[0]
FOAM parallel run aborting






Is it possible of access the local cellID on each processor based on the global cellID?


Any builtin function to do this?


Best Regards


olesen May 18, 2021 07:20

Quote:

Originally Posted by Shibi (Post 803965)
Hello to all,

In a functionObject I am coding, I need to access the values of pressure of cellID {20, 70, 30, 50, 90}, in this order.

I using a 2D square domain with 10x10 cells for testing decomposed in 2 processors.

I have the following code.

Code:

  List<scalar> cellIds{20, 70, 30, 50, 90};
  List<scalar> pValues(cellIds.size() );

  const volScalarField& sField = lookupObject<volScalarField>("p");

    forAll(cellIds, cellI)
    {
          pValues[cellI] = sField [ cellIds [cellI] ];

    }

In serial, this will run without a problem. In parallel the domain is decomposed into 50 cells for each processor. So, when I try to access
sField[70], it will give me the following error:
...[/CODE]

Is it possible of access the local cellID on each processor based on the global cellID?
Any builtin function to do this?

Best Regards

The usual method of coordinating things with global IDs uses the globalIndex class. But for how you have posed the problem there is simply no solution at all.
Let us give it a bit more consideration to what you are attempting.



You have some cellIDs known in serial based on a particular geometry. If you change your mesh resolution (coarser/fine mesh), or swap the corners of the origination blockMesh you will have completely different cellIDs (in serial!).


If you decompose onto multiple processors, which cells land where will depend on your decomposition method. To be really nasty about things, let us assume we are using the "random" decomposition method. This is my personal favourite. It is likely the worst possible decomposition you can imagine since each cell is randomly redistributed: horrible for calculation, great for debugging.


I hope by now you see where all of this is going. Working with some arbitrary cellIDs that you have specified in serial is never going to work.
Instead it would make sense to work directly with how you obtained these IDs in the first place. I would assume that you picked them out based on some x/y/z positions.


From these sample points (starting to look a lot like sampledSets) you can find the nearest location in mesh on each processor and reduce the result to find the best location. I guess you could also do things by hand, define an ijkMesh based on the global mesh bounding box and use that as a voxel type of selection. You'll have to see what fits best for you.



Shibi May 18, 2021 11:16

Hello Mr. Olesen,


Thanks for the reply.


I will give more context into what I am trying to do.


OpenFoam has the runTimeControl function object (https://www.openfoam.com/documentati...e-control.html) which I would like to make work for defining a steady state criteria based on the difference of properties between iterations i.e., at several locations x,y,z when the velocity and pressure difference between iterations is less than 1e-5 stop the simulation (steady criteria). The intent is to make this work with probes. But for now, I am asking the user to specify a number of random cells to keep track of some properties , e.g., pressure.

The random points are selected with:

Code:

  // Get numbers of cells in the domain
    const scalar nCells = returnReduce(this->mesh_.C().size(), sumOp<label>());

    // Function to generate integer random numbers based on the number of cells
    Random::uniformGeneratorOp<label> randVal(0,nCells-1);

    // Vector to store the cellID values. Resized to the user input and initialized with -1.
    nPointVector_.resize(nRandomPoints_, -1); 

    // Get n randomly selected cells
    // Create a vector from 0-nCells for random selection of cells
    List<label> cellIDList(nCells);
    forAll(cellIDList, i)
    {
        cellIDList[i]=i;
    }

    // Shuffles the vector to randomly select cells in the domain
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::default_random_engine e(seed);
    std::shuffle(cellIDList.begin(), cellIDList.end(), e);

    // Assigns the random cells to the nPointVector
    for(label i = 0 ; i < nRandomPoints_; i++)
    {
      nPointVector_[i] =  cellIDList[i];
    }

    // Vector to store the value of properties for 2 iterations. Resized to user input and initialized with -1

    twoIterationStorage_.resize(2, List<scalar> (nRandomPoints_, -1.0));


Afterwards in the execute() function of the funtionObject.

Code:

bool Foam::functionObjects::steadyStateCheck::execute()
{
    // Creates files to store data.

    createFiles();

    // Looks for the pressure field. fieldSet is a user input which for the time being is pressure
    const volScalarField& sField = lookupObject<volScalarField>(fieldSet_[0]);

  // Populates the storage vector with the values of the field from the randomly generated cells
    forAll(twoIterationStorage_[rowNumber_], cellI)
    {
        twoIterationStorage_[rowNumber_][cellI] = sField[ nPointVector_[cellI] ];
    }
   
    // Function to switch the rowNumber of the storage vector (wither 0 or 1)
    updateRowNumber();

    // Compute the maximum difference between all randomly selected cells
    const scalar maxDifference = gMax(mag(twoIterationStorage_[0]-twoIterationStorage_[1]));

// write information to file
  if(writeToFile() && Pstream::master() )
    {
        writeCurrentTime(coeffFilePtr_());
        coeffFilePtr_()
            << tab << maxDifference << tab
            << endl;
    }

// write randomly selected cellIDS to fill in case I want to check them in paraview
    if(writeCellIDs_ && Pstream::master() )
    {

        forAll(nPointVector_, cellI)
        {
            cellIDFilePtr_()
            << tab << label(nPointVector_[cellI]) << tab
            << endl; 
        }

        writeCellIDs_ = false;
 
    }

    firstIter_=false;

    // Write state/results information
    {
      setResult("Cd", maxDifference);
    }

    return true;
}


This procedure works in serial with:

Code:

runTimeControl1
 {
    type            runTimeControl;
    libs            ("libutilityFunctionObjects.so");
    conditions
    {
        condition1
        {
            type            average;
            functionObject mySteadyState;
            fields          (Cd);
            tolerance      1e-5;
            window 10;
            groupID        1;
        }

But apparently this is not so straightforward in parallel.


Do you know if OF 2012 has any feature that already performs this task?


Best regards.


All times are GMT -4. The time now is 04:05.