|
[Sponsors] |
April 30, 2021, 07:37 |
Accessing dimensions (x, y, z) of cells
|
#1 |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
Hello everybody,
for a new hybrid turbulence model I want to implement I need the dimensions of each cell to calculate a new delta. I found a way of calculating the dimensions in each direction (x, y, z) in meter. See code attached: Code:
const faceList & ff = this->mesh().faces(); const pointField & pp = this->mesh().points(); volScalarField deltax = this->y_; volScalarField deltay = this->y_; volScalarField deltaz = this->y_; forAll(this->mesh().C(), celli) { const cell & cc = this->mesh().cells()[celli]; labelList pLabels(cc.labels(ff)); pointField pLocal(pLabels.size(), vector::zero); forAll(pLabels, pointi) { pLocal[pointi] = pp[pLabels[pointi]]; } dimensionedScalar Convert ("Convert", dimensionSet(0, 1, 0, 0, 0, 0, 0), scalar(1)); deltax = (Foam::max(pLocal & vector(1,0,0)) - Foam::min(pLocal & vector(1,0,0))) * Convert; deltay = (Foam::max(pLocal & vector(0,1,0)) - Foam::min(pLocal & vector(0,1,0))) * Convert; deltaz = (Foam::max(pLocal & vector(0,0,1)) - Foam::min(pLocal & vector(0,0,1))) * Convert; } But my question is: Is there a more effective way of computing the cell dimensions in x, y and z than using a forAll loop? I have the impression that this is rather time-consuming when using a large mesh. Many thanks for your help! Daniel |
|
May 3, 2021, 02:35 |
|
#2 |
Senior Member
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,689
Rep Power: 40 |
boundBox for the cell points?
BTW in your code example it appears that you are overwriting the entire fields each cell - probably not what you want. For efficiency, it would make sense to store/access the values as a DimensionedField of vectors and dump all of it into a class as a MeshObject. This would make it demand-driven and you could handle mesh changes seamlessly. |
|
May 3, 2021, 03:12 |
|
#3 | |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
Maybe I show the whole code so it becomes a bit more clear. I should also mention that I am a beginner with OpenFOAM coding and found this code in a other forum post and it seemed that this the thing I need: Cell size (x,y,z)
My whole code for calculating the variable I need with the cell dimensions looks like this. For a non-moving mesh, the dimensions of each cell should only calculated at the beginning since they are not changing in time, but I am not sure yet how to solve this issue. Maybe write another file like the cubeRootVolDelta or the maxDelta. But what changes with each iteration is the vorticity, this should therefore be calculated at each time step. Code:
template<class BasicTurbulenceModel> tmp<volScalarField> SAEDES<BasicTurbulenceModel>::deltaOmega ( ) const { volVectorField vorticity = fvc::curl(this->U()); volScalarField magVorticity = mag(vorticity); volVectorField vorticityUnit = vorticity / magVorticity; const faceList & ff = this->mesh().faces(); const pointField & pp = this->mesh().points(); volScalarField deltax = this->y_; volScalarField deltay = this->y_; volScalarField deltaz = this->y_; forAll(this->mesh().C(), celli) { const cell & cc = this->mesh().cells()[celli]; labelList pLabels(cc.labels(ff)); pointField pLocal(pLabels.size(), vector::zero); forAll(pLabels, pointi) { pLocal[pointi] = pp[pLabels[pointi]]; } dimensionedScalar Convert ("Convert", dimensionSet(0, 1, 0, 0, 0, 0, 0), scalar(1)); deltax = (Foam::max(pLocal & vector(1,0,0)) - Foam::min(pLocal & vector(1,0,0))) * Convert; deltay = (Foam::max(pLocal & vector(0,1,0)) - Foam::min(pLocal & vector(0,1,0))) * Convert; deltaz = (Foam::max(pLocal & vector(0,0,1)) - Foam::min(pLocal & vector(0,0,1))) * Convert; //Info <<deltax<< endl; //Info <<deltay<< endl; //Info <<deltaz<< endl; } return sqrt( sqr(vorticityUnit.component(0)) * deltay * deltaz + sqr(vorticityUnit.component(1)) * deltaz * deltax + sqr(vorticityUnit.component(2)) * deltax * deltay ); } Quote:
Many thanks for your help! Best regards, Daniel |
||
May 3, 2021, 05:32 |
|
#4 | |
Senior Member
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,689
Rep Power: 40 |
Quote:
If you examine the closing statements in your loop: Code:
forAll(this->mesh().C(), celli) { ... // !!! HERE ! !!! deltax = (Foam::max(pLocal & vector(1,0,0)) - Foam::min(pLocal & vector(1,0,0))) * Convert; deltay = (Foam::max(pLocal & vector(0,1,0)) - Foam::min(pLocal & vector(0,1,0))) * Convert; deltaz = (Foam::max(pLocal & vector(0,0,1)) - Foam::min(pLocal & vector(0,0,1))) * Convert; } After exiting the loop, the entire field will simply have the value of the last cell, which you will not notice if the mesh is uniform. |
||
May 3, 2021, 05:48 |
|
#5 |
Senior Member
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,689
Rep Power: 40 |
You would need to verify, but my first idea was something like this (NOTE: quality not checked!!).
Code:
volScalarField deltax = this->y_; volScalarField deltay = this->y_; volScalarField deltaz = this->y_; ... starting here const polyMesh& pMesh = this->mesh(); const label nCells = pMesh.nCells(); boundBox cellBb; for (label celli = 0; celli < nCells; ++celli) { const labelList& cPoints = pMesh.cellPoints(celli); cellBb.clear(); cellBb.add(pMesh.points(), cPoints); deltax[celli] = (cellBb.max().x() - cellBb.min().x()); deltay[celli] = (cellBb.max().y() - cellBb.min().y()); deltaz[celli] = (cellBb.max().z() - cellBb.min().z()); } |
|
May 3, 2021, 07:52 |
|
#6 |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
Many thanks for your help, now I understand! You are completely right. I just tested your piece of code and it seems to work also it seems much faster, I just have to check if the dimensions are right. I think for this the easiest way is to create IOobjects, what do you think?
But if I now want to calculate the deltaOmega for each cell, I don't have to use a forAll loop, right? I can just calculate like this: Code:
sqrt( sqr(vorticityUnit.component(0)) * deltay * deltaz + sqr(vorticityUnit.component(1)) * deltaz * deltax + sqr(vorticityUnit.component(2)) * deltax * deltay ); |
|
May 3, 2021, 11:09 |
|
#7 |
Senior Member
Mark Olesen
Join Date: Mar 2009
Location: https://olesenm.github.io/
Posts: 1,689
Rep Power: 40 |
It's fine enough the way you now have it.
Since you have complete volfields after the loop, the rest should be OK. You will Probably want to store deltaxy, deltayz, deltazx instead. Cheap to calculate within the loop, and saves extra multiplications later. After that can revise how you create your fields. Probably want them with the class scope. For that, autoPtr is the usual container. |
|
May 20, 2022, 07:53 |
|
#8 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
Hi Daniel,
what does this->Y in your code mean?? Thanks in advance |
|
May 20, 2022, 09:45 |
|
#9 |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
||
May 20, 2022, 10:05 |
|
#10 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
I had written a loop similar to yours for finding deltaX and wrote return statement after the loop. But when I use deltaX in return statement it is throwing an error message that deltaX is undefined
|
|
May 23, 2022, 02:08 |
|
#11 |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
||
May 23, 2022, 02:12 |
|
#12 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
Hi Daniel,
I didn't define it before loop. Because I don't know what I should assign to deltaX as u assigned this->Y. my cose looks like this Foam::tmp<Foam::volScalarField> Foam:haseChangeTwoPhaseMixtures::myPhaseChange:: kappaGradT() const { const volScalarField limalpha1(min(max((alpha1()), scalar(0)), scalar(1))); const volVectorField& U = db().lookupObject<volVectorField>("U"); const fvMesh & mesh = U.mesh(); const unallocLabelList& neighbour = mesh.neighbour(); const unallocLabelList& owner = mesh.owner(); const volVectorField& C = mesh.C(); const volScalarField& T = alpha1().db().lookupObject<volScalarField>("T"); forAll(owner, facei) { vector delta = C[neighbour[facei]] - C[owner[facei]]; volScalarField gradAlpha = fvc::grad(limalpha1) & mesh.C(); volScalarField alphaPrim = mag(gradAlpha); const dimensionedScalar len("len",dimLength,mag(delta)); const dimensionedScalar small("small",dimensionSet(0, 0, 0, 0, 0, 0, 0),1e-5); } return ( (limalpha1*lambda1_+ (1-limalpha1)*lambda2_) * ((T-Tsat_)/(len))*(gradAlpha/max(alphaPrim,small)) ); } |
|
May 23, 2022, 02:24 |
|
#13 | |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
Quote:
you could try to define a vector before the loop like: Code:
vector delta(0,0,0); |
||
May 23, 2022, 02:32 |
|
#14 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
Hi Daniel,
Thanks for your suggestion,I implemented it like this now I have no eroors or warnings,is it correct way?? Foam::tmp<Foam::volScalarField> Foam:haseChangeTwoPhaseMixtures::myPhaseChange:: kappaGradT() const { const volScalarField limalpha1(min(max((alpha1()), scalar(0)), scalar(1))); const volVectorField& U = db().lookupObject<volVectorField>("U"); const fvMesh & mesh = U.mesh(); const unallocLabelList& neighbour = mesh.neighbour(); const unallocLabelList& owner = mesh.owner(); const volVectorField& C = mesh.C(); const volScalarField& T = alpha1().db().lookupObject<volScalarField>("T"); vector delta(0,0,0); const dimensionedScalar len("len",dimLength,0); forAll(owner, facei) { vector delta = C[neighbour[facei]] - C[owner[facei]]; volScalarField gradAlpha = fvc::grad(limalpha1) & mesh.C(); volScalarField alphaPrim = mag(gradAlpha); const dimensionedScalar len("len",dimLength,mag(delta)); const dimensionedScalar small("small",dimensionSet(0, 0, 0, 0, 0, 0, 0),1e-5); } return ( (limalpha1*lambda1_+ (1-limalpha1)*lambda2_) * ((T-Tsat_)/(len))*(gradAlpha/max(alphaPrim,small)) ); } is delta in loop getting used? Why I am doubting this is, I have set both delta and len to 0 before the loop ,will the get updated |
|
May 23, 2022, 02:54 |
|
#15 | |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
Quote:
Yes, that should be working. You are just defining delta and len beforehand so that it will be recognized for the loop. During the loop it will then get updated. You could print len or delta during your simulation so you can see if the results are meaningful. I am not sure how to print anymore but there are some posts related to this topic, just google for it. |
||
May 23, 2022, 03:33 |
|
#16 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
Hi daniel,
Thanks for helping me, And I am able to print them and I am getting correct results |
|
May 23, 2022, 05:11 |
|
#17 |
Member
Daniel
Join Date: May 2018
Posts: 43
Rep Power: 8 |
||
May 23, 2022, 05:44 |
|
#18 |
Member
hari charan
Join Date: Sep 2021
Location: India,hyderabad
Posts: 96
Rep Power: 4 |
Hi Daniel,
Can you look this post and suggest me what's wrong in it. Multiplication of source term with div(T) is causing error Thanks in advance |
|
November 21, 2023, 10:26 |
|
#19 |
New Member
Join Date: Aug 2017
Posts: 16
Rep Power: 8 |
Hi Olesen,
If I want to write it as a post-processing program, is that possible? Regards. |
|
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
[ICEM] Problem with prism cells | sidharath | ANSYS Meshing & Geometry | 0 | September 1, 2015 07:09 |
Accessing neighboring cells' cell number | Daniel Lattin | Siemens | 4 | October 20, 2006 16:19 |
physical boundary error!! | kris | Siemens | 2 | August 3, 2005 00:32 |
Accessing neighbouring cells in UDF | Hiranya Nath | FLUENT | 5 | March 22, 2002 23:29 |
Accessing neighboring cells in UDF | Christian | FLUENT | 1 | January 18, 2002 22:06 |