CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > Software User Forums > OpenFOAM > OpenFOAM Programming & Development

Accessing local cell index with global cell index in functionObject

Register Blogs Community New Posts Updated Threads Search

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   May 16, 2021, 16:53
Default Accessing local cell index with global cell index in functionObject
  #1
Member
 
Join Date: Feb 2020
Posts: 90
Rep Power: 6
Shibi is on a distinguished road
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

Shibi is offline   Reply With Quote

Old   May 18, 2021, 07:20
Default
  #2
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,689
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by Shibi View Post
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.


olesen is offline   Reply With Quote

Old   May 18, 2021, 11:16
Default
  #3
Member
 
Join Date: Feb 2020
Posts: 90
Rep Power: 6
Shibi is on a distinguished road
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.
Shibi is offline   Reply With Quote

Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
time step continuity problem in VAWT simulation lpz_michele OpenFOAM Running, Solving & CFD 5 February 22, 2018 19:50
pimpleDyMFoam computation randomly stops babapeti OpenFOAM Running, Solving & CFD 5 January 24, 2018 05:28
dynamic Mesh is faster than MRF???? sharonyue OpenFOAM Running, Solving & CFD 14 August 26, 2013 07:47
[blockMesh] BlockMeshmergePatchPairs hjasak OpenFOAM Meshing & Mesh Conversion 11 August 15, 2008 07:36
Convergence moving mesh lr103476 OpenFOAM Running, Solving & CFD 30 November 19, 2007 14:09


All times are GMT -4. The time now is 12:35.