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

Return cells cut by cuttingPlane

Register Blogs Community New Posts Updated Threads Search

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   December 14, 2018, 06:28
Default Return cells cut by cuttingPlane
  #1
New Member
 
Join Date: Nov 2016
Posts: 8
Rep Power: 9
jackdoubleyou is on a distinguished road
Hi,


I'm creating a new solver, based on pisoFoam, that requires me to perform spatial averaging on a series of x-z planes. I've successfully created the required planes, and created cuttingPlanes from all of them.



The mesh is created using blockMesh, and has 180 points in the x direction and 40 in the z direction, so each plane should intersect 7200 cells. When I use cuttingPlane.cutCells(), instead of returning the cells that have been cut by the plane, the first 7200 cells from the mesh are given. The relevant code is given below.

yLocs is a 1D std::vector containing all of the y values I want to average, and I've confirmed that these are correct. The plane normals and origins are also being correctly used. "cells" is a labelList as I don't want to average across my whole domain, only a part of it.



Code:
labelList cutPlanes[yLocs.size()];

int i = 0;

for (const auto &yValue: yLocs)
{
  point origin(-0.018,yValue,0.002);

  vector nVec(0,1,0);

  plane nplane(origin, nVec);

  cuttingPlane plane1(nplane, mesh, 0, cells);

  Info << plane1.refPoint() << endl;

  const labelList& cellsOnPlane = plane1.cutCells();

  /*forAll(cellsOnPlane, celli)
  {
    Info << celli << endl;
  }*/

  cutPlanes[i] = cellsOnPlane;

  i++;

 }
I've been through this thread (Write cells and data intersecting a plane cuttingPlane) and not been able to fix my problem. I'm using OpenFOAM v5.x.


Thanks in advance,
Jack
jackdoubleyou is offline   Reply With Quote

Old   December 21, 2018, 04:40
Default
  #2
Member
 
Join Date: Dec 2018
Location: Darmstadt, Germany
Posts: 87
Rep Power: 7
raumpolizei is on a distinguished road
Hey,
have you tried foamToVTK + viewing the cellids in paraview? You could then check at least what should be the output. That may help reason on your implementation.
Also, I'm not sure but shouldn't cutPlanes be some kind of container<labelList> ? I don't understand what this line is supposed to do:
Code:
labelList cutPlanes[yLocs.size()];
Seems like you are mixing access operator[] and initialization which may lead to undefined behaviour.
Code:
std::vector<labelList> cutPlanes(yLocs.size());
Is this what you originally wanted to express?
Best regards
RP
raumpolizei is offline   Reply With Quote

Old   December 21, 2018, 05:16
Default
  #3
New Member
 
Join Date: Nov 2016
Posts: 8
Rep Power: 9
jackdoubleyou is on a distinguished road
Hi,


I haven't tried that, will give it a go.


The std::vector line is what I originally tried, however it would not compile. I think it was because there is no implementation of std::vector that knows how to deal with labelLists.


labelList cutPlanes[yLocs.size()]


is supposed to initialise an empty array, of length yLocs.size(), of labelLists. It appears to have worked, although I agree it is not a great solution.


Thanks,
Jack
jackdoubleyou is offline   Reply With Quote

Old   December 21, 2018, 05:49
Default
  #4
Member
 
Join Date: Dec 2018
Location: Darmstadt, Germany
Posts: 87
Rep Power: 7
raumpolizei is on a distinguished road
That's strange, for me this works fine (v16.12)
Code:
#include "fvCFD.H"
#include<vector>
int main(int argc, char *argv[])
{
    std::vector<labelList> test(4);

    for( labelList& ilist: test)
    {
        ilist = labelList{1,2,3};
    }

    return 0;
}
Ah yeah, so much into C++ right now that I almost forgot about raw arrays . This should also be fine.
raumpolizei is offline   Reply With Quote

Old   December 21, 2018, 06:10
Default
  #5
New Member
 
Join Date: Nov 2016
Posts: 8
Rep Power: 9
jackdoubleyou is on a distinguished road
Yeah you're right, I can't reproduce the error I was previously having. It looks like either method works, but will go with std::vector, seems neater.


Still gives me the same problem though. I've loaded in the vtk, and the cell IDs that are being returned are not the correct ones. Someone in the lab has suggested that .cutCells() returns the cell IDs local to the plane, which will always be 0-7199, instead of the cell ID in the global mesh. I can't find anything online suggesting this should be the case however.


Jack
jackdoubleyou is offline   Reply With Quote

Old   December 21, 2018, 09:38
Default
  #6
New Member
 
Join Date: Nov 2016
Posts: 8
Rep Power: 9
jackdoubleyou is on a distinguished road
I've fixed the problem, it was to do with how I was referencing the cell list.


Instead of

Code:
forAll(cells, celli)
{
    code
}

it needed an additional line

Code:
forAll(cells, celli)
{
    const label cell = cells[celli]

    code
}
I was using the index of the labelList, instead of the cell ID contained within it.
jackdoubleyou is offline   Reply With Quote

Old   December 21, 2018, 11:31
Default
  #7
Member
 
Join Date: Dec 2018
Location: Darmstadt, Germany
Posts: 87
Rep Power: 7
raumpolizei is on a distinguished road
Riight, this forAll macro is so...unintuitive . I think this one is the only reason I, from time to time, have to lookup ranged based for loops. Glad you solved it.
raumpolizei is offline   Reply With Quote

Old   December 21, 2018, 12:13
Default
  #8
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,714
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by jackdoubleyou View Post
Hi,
I'm creating a new solver, based on pisoFoam, that requires me to perform spatial averaging on a series of x-z planes. I've successfully created the required planes, and created cuttingPlanes from all of them.
If you are going to do this cutting operation a lot (and it sounds like you are), you will probably want to reconsider what you are doing.

The cuttingPlane finds intersection cells *and* attempts to create a face loop for these intersections. From your description, it doesn't really sound like you need faces. You just want to have a list of intersected cells. In fact, you don't actually really want to have a list of the cells, instead you just want to know which cells are intersected to define that plane and be able to loop over them.

There is some similar code put into OpenFOAM-v1812 that you may want to take a look at and do something similar. I looked at this recently, and the cutting problem is much easier. (Reliably constructing faces from the intersections, handling degenerate cells etc, isn't so reliable). The other reason to avoid cuttingPlane is that older versions (ie, older than 1812) worked by calculating mesh edge cuts, which means mesh edges are created for the entire mesh - this can be an expensive operation.

I think that all you want to know is which cells are intersected by the plane. This is what is happening in src/sampling/surface/cutting/cuttingPlaneCuts.C


The comments there explain the stages

// Classify sides of plane (0=BACK, 1=ONPLANE, 2=FRONT) for each point

This is saved as 2-bits per mesh point (PackedList).

Loop over each mesh face (once):

// Check for face/plane intersection based on crossings
// Took (-1,0,+1) from plane::sign and packed as (0,1,2).
// Now use for left shift to obtain (1,2,4).
//
// Test accumulated value for an intersection with the plane.

If the face intersects the plane, you mark that cell as being 'cut'. If a cell has more than one face cut, the plane intersects the cell. You could be strict and insistent on three or more cuts, but there is no benefit and just more overhead.

For count the number of times a cell cut has happened, don't waste memory actually counting the number of cuts. Instead use two separate bitSets to count your state. The reason for the bitSet is that when this little algorithm is done we have a bitSet as its output.

I really like bitSet. For these types of things it is really good for memory (1-bit per location) and gives you fast checks for testing if any bits are set, population count to get how many etc. For your case, you'll want to use the iterator directly.
Eg
Code:
bitSet cellsCut(some_algorithm_like_above);

scalar avgVal = 0;


for (const label cellId : cellsCur){
      avgVal += someField[cellId];
}

const label nTotalCut = returnReduce(cellsCuts.count(), sumOp<label>());

if (nTotalCut)
{
     reduce(sumOp<scalar>());
     avgVal /= nTotalCut;
}

This should give you good performance, low overhead and provide the result that you need. Another benefit of this approach (see the cuttingPlane calcCellCuts method in 1812), is that you can also define an input bitSet to apply additional restrictions on the intersection. Eg, if you only want plane/mesh intersections that are also within some other geometrical region (eg, bounding box) or mesh region (eg zones).


If it makes sense, could also think about breaking this private method out.


I hope this gives you some new ideas.


Cheers,
/mark
olesen is offline   Reply With Quote

Old   December 21, 2018, 12:21
Default
  #9
Senior Member
 
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,714
Rep Power: 40
olesen has a spectacular aura aboutolesen has a spectacular aura about
Quote:
Originally Posted by jackdoubleyou View Post
it needed an additional line
Code:
forAll(cells, celli)
{
    const label cell = cells[celli]
}
I was using the index of the labelList, instead of the cell ID contained within it.

For standard containers, where you don't need the local indexing number you should prefer direct iteration. This avoids a method call 'size()' during every iteration and you don't need to use an indirection to get at your values. I don't say that this will speed up your code, but makes it easier to read (I think). Thus your code,

Code:
for (const label celli : cells)
{
    Info<< "using cell: " << celli << nl;
}

You can use exactly the same trick for HashSet too. But you will need to be careful trying this on a HashTable since those iterators are already what you normally need and the dereferenced '*iter' returns the value, whereas the stl versions return a key/value pair. In most of these cases, you should then be using the `forAllConstIters()` macro, which has two parameters.


/mark
olesen is offline   Reply With Quote

Reply

Tags
cutcells, cuttingplane


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
[snappyHexMesh] Error snappyhexmesh - Multiple outside loops avinashjagdale OpenFOAM Meshing & Mesh Conversion 53 March 8, 2019 10:42
[snappyHexMesh] sHM too many cells Knapsack OpenFOAM Meshing & Mesh Conversion 2 July 8, 2017 08:41
[ANSYS Meshing] Meshing with cut cells sunilpatil ANSYS Meshing & Geometry 2 February 24, 2016 02:48
[snappyHexMesh] No layers in a small gap bobburnquist OpenFOAM Meshing & Mesh Conversion 6 August 26, 2015 10:38
Coordinate cut c-grid and dummy cells zonexo Main CFD Forum 0 December 13, 2005 06:05


All times are GMT -4. The time now is 20:13.