CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Running, Solving & CFD (https://www.cfd-online.com/Forums/openfoam-solving/)
-   -   Relation between k and UPrime2Mean etc in LES (https://www.cfd-online.com/Forums/openfoam-solving/88355-relation-between-k-uprime2mean-etc-les.html)

Tarak May 15, 2011 02:51

Relation between k and UPrime2Mean etc in LES
 
Hii,

While doing LES using OF, I found that the value of k and the value of 0.5*(UPrime2Meanxx+UPrime2Meanyy+UPrime2Meanzz) are very different. Can someone please elaborate why is it so? They are supposed to be exactly the same, according to the definition of turbulent kinetic energy.

Thanks,
Tarak

longamon May 16, 2011 08:18

I think the difference is that the k calculated in LES refers to the sub-grid-scale kinetic energy, whereas the 0.5*(u'_ii) refers to the total turbulent kinetic energy

Tarak May 16, 2011 11:10

Hii,

Thanks for the reply. But while prescribing the boundary value in k, suppose say at inlet, we set the value of the TKE from k=1.5(I*U)^2. That's not sgs kinetic energy. So doesn't these 2 contradict each other?

Thanks,
Tarak

longamon May 16, 2011 12:39

I'm not sure of that boundary value for k, however, if you take a look at the source codes of the LES models you'll see how the k is calculated.

When using oneEqEddy models the sub-grid kinetic energy is calculated through a transport equation and then used to calculate the subgrid viscocity.

In smagorinsky models the sub-grid kinetic energy is calculated from the velocity gradient.

In LES modeling the SGS quantities are used to close the model. The value of k is an instantaneus value, different from the total turbulent kinetic energy calculated from the Reynolds stress tensor

Tarak May 16, 2011 12:42

Thanks a lot. Ya I'm sure that the k is indeed sgs k, but then it becomes difficult to prescribe the inlet condition, as the sgs ke is not known beforehand. So, is it wise to prescribe a relatively low value of k, that is lower than the total turb kinetic energy? I you have some personal experience with this, please do not hesitate to advice.

Thanks,
Tarak

longamon May 16, 2011 12:51

For the problem I'm solving now i'm using a turbulent inlet velocity profile, and for k i'm setting a low value, 2e-5. I'm getting accepable results with this. You should be worried for this condition if using oneEqEddy or kOmega type models, smagorinsky models do not depend on k as it is calculated from the velocity

Tarak May 16, 2011 12:54

Thanks a lot.

I am using dynamicOneeqEddy model, that's why I am so concerned about it. I am presently simulating the flow over a circular cylinder for Re=3900, but not managing to get an acceptable recirculation length. So, the way you prescribed now may help. If you had any luck with the flow over a circular cylider please do let me know.

Thanks,
Tarak

gregor May 17, 2011 03:43

k is indeed the turbulent sgs energy (see http://foam.sourceforge.net/doc/Doxy...OneEqEddy.html), but UPrime2Meanxx are the variances of the resolved and time averaged scales http://foam.sourceforge.net/doc/Doxy...0b4d6940d1b9e4.
So your 0.5*tr(UPrime2Mean) is more like kinetic energy of the resolved turbulent scales.

sam1364 January 20, 2012 20:08

Hi gregor

I am trying to find out how Uprime2Mean is calculated. I went to the source code of fieldaveraging, but still I could not figure out how this parameter is calculated. I am looking for a Reynolds stress definition as below

R=<u'iu'j>+<uiuj>-<ui><uj>

the first trem is unresolved Reynolds stress and the addition of the other two terms are the resolved Reynolds Stress. Is Uprime2Mean the same as above equation?

any comment on the Uprime2Mean calculation will be of great help to me.

Thanks

gregor January 24, 2012 08:16

Uprime2Mean is simply the variance of the resolved scales. Which is the quadratic value of the standard deviation sigma. Standard deviation gives you an idea on how much your values deviate around a mean value.

var = sigma^2 = 1/(N) sum^N(phi - <phi>)^2, where <.> is a time averaged value

So it is the averaged deviation around a mean value ;). The definition of Reynoldstresses has nothing to do with how the variances a calculated.

Gregor

sam1364 January 24, 2012 12:30

Thanks Gregor

Now, I have an idea on how Uprime2Mean is claculated.
I want to get the time average of Reynolds stress tensor during the run. In Kepsilon Model, R is calculated like this

tmp<volSymmTensorField> kEpsilon::R() const
{
return tmp<volSymmTensorField>
(
new volSymmTensorField
(
IOobject
(
"R",
runTime_.timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
((2.0/3.0)*I)*k_ - nut_*twoSymm(fvc::grad(U_)),
k_.boundaryField().types()
)
);
}

Do you have any idea how I can implement this in OpenFoam?

gregor January 24, 2012 12:43

Quote:

Originally Posted by sam1364 (Post 340914)
tmp<volSymmTensorField> kEpsilon::R() const
{
return tmp<volSymmTensorField>
(
new volSymmTensorField
(
IOobject
(
"R",
runTime_.timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
((2.0/3.0)*I)*k_ - nut_*twoSymm(fvc::grad(U_)),
k_.boundaryField().types()
)
);
}

Do you have any idea how I can implement this in OpenFoam?

Since you already have your modelled R field you could just add

Code:

functions
{
        fieldAverage1
        {
                type            fieldAverage;
                functionObjectLibs ( "libfieldFunctionObjects.so" );
                enabled        true;
                resetOnOutput  false;
                cleanRestart    true;
                outputControl  outputTime;

                fields
                (
                        R
                        {
                                mean        on;
                                prime2Mean  off;
                                base        time;
                        }

                );
        }
}

to your controlDict to average R over time.

sam1364 January 24, 2012 13:20

I have already done that. But it gives me the following error

Requested Field R Does not exist in the database

gregor January 25, 2012 03:18

Are you doing LES or RANS and what is your turbulence model ?

morard January 25, 2012 04:31

Hi,

I think that every field you want to average first has to be created here:

#include "createFields.H"

in your solver. So, go to solver you want to use, and add a new field in createField.H:
something like:

volSymmTensorField R_
...
...
Than, you'll have to add something like this into solver:

R_ = yourTurbulenceModel->R();

And than, field R_ can be averaged...
You'll have to play a little with solver, but this is not a big issue...

Regards,
Dejan

gregor January 25, 2012 04:43

Quote:

Originally Posted by morard (Post 341034)
Hi,

I think that every field you want to average first has to be created here:

Quote:

Originally Posted by morard (Post 341034)


#include "createFields.H"





It doesn't matter where you create it, as long as it is registred in the object registry.

Quote:

Originally Posted by morard (Post 341034)
R_ = yourTurbulenceModel->R();


Depending on if he is doing RANS or LES it could be

yourTurbulenceModel->B() (for LES)

aswell

Gregor

morard January 25, 2012 04:51

Ufff, sorry, my mistake. It's LES about (from the first post).
So, it's definitely:

yourTurbulenceModel->B() (for LES)

gregor January 25, 2012 04:56

Ok i just wondered, because its not the original guy asking anymore.

And if its LES then you have to create the field first (i.e. in #include createFields.H) and then assign it like B_ = yourLESturbMod->B().

I was just confused by his RANS example, where the R field gets created by default from the turbulence model.

sam1364 January 25, 2012 11:43

hi

I am using RANS and KEpsilon Model to solve my problem and the error still exists. I went through KEpsilon.C to find how R is calculated and saved. I see that in this file, k and epsilon are written in a file by using


k_
(
IOobject
(
"k",
runTime_.timeName(),
mesh_,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
autoCreateK("k", mesh_)

but for R, it is

tmp<volSymmTensorField> kEpsilon::R() const
{
return tmp<volSymmTensorField>
(
new volSymmTensorField
(
IOobject
(
"R",
runTime_.timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
((2.0/3.0)*I)*k_ - nut_*twoSymm(fvc::grad(U_)),
k_.boundaryField().types()
)
);
}

by Looking at the above file, I see that R is created but it is not written anywhere. I changed NO_WRITE to AUTO_WRITE, but nothing happened. Do you still believe that R is created and can be averaged?!

Thanks for your time. I do appreciate your help

gregor January 25, 2012 11:54

Ok i guess the reason is that you R field is only created as a tmp field if you are calling the R() function. So you should try what morad suggested and create a separate R field inside your createFields.H

as



Code:


volSymmTensorField R_
        (
            IOobject
            (
                "R",
                runTime_.timeName(),
                mesh_,
                IOobject::NO_READ,
                IOobject::NO_WRITE // you could use auto_write aswell
            ),       
          turbulence->R() // don't know if that works ?
          )



and make sure that you update it every time step by

R_ =
turbulence->R()

Gregor

sam1364 January 25, 2012 12:26

my Solver is pisoFoam. So, Should I add these new lines to the createFields.H inside the pisoFoam Directory?! Do I need to compile these codes when I add those terms?

in createFields.H inside pisoFoam Directory, I see that it reads U and P fields rather than writing them

Info<< "Reading field U\n" << endl;
volVectorField U
(
IOobject
(
"U",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);

are you sure this is the place to create R field?

gregor January 25, 2012 12:32

Quote:

Originally Posted by sam1364 (Post 341150)
my Solver is pisoFoam. So, Should I add these new lines to the createFields.H inside the pisoFoam Directory?! Do I need to compile these codes when I add those terms?

Yes you would have to recompile your code.


Quote:

Originally Posted by sam1364 (Post 341150)
in createFields.H inside pisoFoam Directory, I see that it reads U and P fields rather than writing them

It reads the fields and creates an entry in the object registry, which is needed for the sampling. So its nothing wrong with putting it in there, but you can place it anywhere else where it fits ;)

Gregor

morard January 25, 2012 12:36

...and don't forget to change the name of the solver :)

sam1364 January 25, 2012 13:05

Ok, thanks guys.

to compile a code, As far as I remember, I should use wmake libso. do I need to make a new library for my new solver let's say pisoFoam2?!
I do not want to change pisoFoam.C. I want to make a copy of that somewhere and then change it.

by the way, by the following command, do you mean that I should use this inside pisoFoam solver?! and what is turbulence?! do you mean RASModel ->R()?!

R_ = turbulence->R()

morard January 26, 2012 04:03

Hi,

first, just copy original pisoFoam and change name to, as you said, pisoFoam2 (but, my suggestion is to choose something other like pisoRFoam, because after some tome you will have pisoFoam2, pisoFoam3,... and you will definitely forget what did you change in each of those..). So, you have to change pisoFoam.C to pisoFoam2.C. Than, open Make folder and inside files, you also have to change:

pisoFoam2.C

EXE = $(FOAM_APPBIN)/pisoFoam2

Then navigate your terminal to pisoFoam2 folder and execute:

wclean
wmake

now you have your own solver pisoFoam2. Now do the changes mentioned by Gregor and me.

If you take a look into createFields.H, you will see how pointer is created. At the end of the file it is written:

autoPtr<incompressible::turbulenceModel> turbulence
(
incompressible::turbulenceModel::New(U, phi, laminarTransport)
);

so, you'll have to put inside pisoFoam2.C

R_ = turbulence->R();

Put this inside while loop. Between the lines: turbulence->correct(); and runTime.write(); might be a good position. So, at the end you'll have:

turbulence->correct();

R_ = turbulence->R();

runTime.write();

This should wor.

Check this page:
http://openfoamwiki.net/index.php/Ho...ure_to_icoFoam

There you can find a lot of useful things.

sam1364 January 26, 2012 10:53

Thanks Morad. So nice!
I will try it out!

sam1364 January 27, 2012 10:59

Hi

I compiled the new pisoFoam solver and I added the following line to the code:

createField.H


Info<< "Reading field R\n" << endl;
volSymmTensorField R
(
IOobject
(
"R",
runTime.timeName(),
mesh,
IOobject::MUST_READ,
IOobject::AUTO_WRITE
),
mesh
);

and to the pisoFoam2 solver,



volSymmTensorField R
(
IOobject
(
"R",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
turbulence->R()
);

R.write();


This way, the solver reads R field from time 0 and it writes and updates the R field every time step to a directory.

My problem is two things:

1- I want to have R field written in time directories specified in controlDict (specified write intervals). My new solver writes R in each time step and gives it as an output every time.

2- When I do field averaging, I do not receive the old error which was "the Requested R field does not exist". Now, R field is created. But, it seems that for field averaging, the algorithm gets the initial R field and average that during runtime which always gives the same thing for all times.


I would be happy if you can suggest a way to overcome any of the above issues.

Thanks,

gregor January 27, 2012 11:12

Quote:

Originally Posted by sam1364 (Post 341529)
and to the pisoFoam2 solver,



volSymmTensorField R
(
IOobject
(
"R",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
turbulence->R()
);

R.write();

there you made a mistake


In the pisoFoam2.C a simple

Code:

R=turbulence->R();
should be sufficient. You just want to get the R-field every timestep not create it every timestep. Furthermore you don't need a
Code:

R.write()
since you have told the objectRegistry to handle it by IOobject::AUTO_WRITE

Gregor

sam1364 January 27, 2012 11:18

I also tried adding this line instead of R.write(). But, I received an error when compiling the code. I will post the error in an hour or so.

Thanks

sam1364 January 30, 2012 12:00

hi,

Thanks to your comments, I could get field average of R over time.

sam1364 January 30, 2012 12:15

I also want to calculate U*U and get the average of this field over time. U is given by OpenFoam. I just need to add some lines to calculate U*U. if U=[1 2 3;4 5 6], by U*U, I mean the result is [1 4 9;16 25 36]. I do not know how openfoam writes U field so that I can write a "for loop" to calculate U*U. do you have any suggestions?

sam1364 January 30, 2012 13:17

Hi Gregor

I guess Uprime2Mean(0) is also equivalent to the following equation

<UU>-<U><U>, where <> is time averaged value.
since 1/n sum^N (U-<U>)^2= <UU>-2<U><U>+<U><U>=<UU>-<U><U>.
Am I right?






Quote:

Originally Posted by gregor (Post 340855)
Uprime2Mean is simply the variance of the resolved scales. Which is the quadratic value of the standard deviation sigma. Standard deviation gives you an idea on how much your values deviate around a mean value.

var = sigma^2 = 1/(N) sum^N(phi - <phi>)^2, where <.> is a time averaged value

So it is the averaged deviation around a mean value ;). The definition of Reynoldstresses has nothing to do with how the variances a calculated.

Gregor


gregor January 31, 2012 04:01

Quote:

Originally Posted by sam1364 (Post 341970)
Hi Gregor

I guess Uprime2Mean(0) is also equivalent to the following equation

<UU>-<U><U>, where <> is time averaged value.
since 1/n sum^N (U-<U>)^2= <UU>-2<U><U>+<U><U>=<UU>-<U><U>.
Am I right?

correct see http://en.wikipedia.org/wiki/Computa...r_the_variance

but i am a bit confussed by your vector definition in the above post ( U=[1 2 3; 4 5 6] ??)

Gregor

eugene February 1, 2012 05:48

You guys are making a mistake. Calling "R()" for an SGS model will not return the total Reynolds stress. It will just return the SGS stress. The only reason it is called "R()" is for compatibility with the RANS model nomenclature.

UPrime2Mean is calculated as:

UPrime2Mean_new = alpha*UPrime2Mean_old + (1-alpha) * sqr(U) - sqr(Umean);

with alpha = (Time - dTime) / Time

If you work it out, this is identical to the definition for Reynolds stress when averaged over a long time (<UU>-<U><U>).

To get the full stresses (resolved + SGS) you thus need UPrime2Mean + RMean. Unfortunately, you will still have to modify a solver to create RMean since the R field is not available by default as noted below.

gregor February 1, 2012 05:52

I know its confusing to discuss RANs matters in a LES thread but sam1364 is using kEpsilon (according to http://www.cfd-online.com/Forums/ope...tml#post340914).

Gregor

sam1364 February 1, 2012 09:26

Hi guys,

I have done UPrime2Mean + RMean to get the total Reynolds Stress for RANS simulation. I could get RMean thanks to Gregor suggestions. But I see a big problem when calculating R or Rmean and that is the values of R or RMean at the walls of cavity which are not zero (I am solving the lid driven cavity flow). I am using kqrwallfunction for R but I do not understand why I get non zero values of Reynolds stress at fixed walls. Am I using the right wall function, Should I set the values of R zero at the fixed wall?



Quote:

Originally Posted by eugene (Post 342243)
You guys are making a mistake. Calling "R()" for an SGS model will not return the total Reynolds stress. It will just return the SGS stress. The only reason it is called "R()" is for compatibility with the RANS model nomenclature.

UPrime2Mean is calculated as:

UPrime2Mean_new = alpha*UPrime2Mean_old + (1-alpha) * sqr(U) - sqr(Umean);

with alpha = (Time - dTime) / Time

If you work it out, this is identical to the definition for Reynolds stress when averaged over a long time (<UU>-<U><U>).

To get the full stresses (resolved + SGS) you thus need UPrime2Mean + RMean. Unfortunately, you will still have to modify a solver to create RMean since the R field is not available by default as noted below.


gregor February 1, 2012 10:19

I would assume that you are looking at R in the first cell next to the wall (which isnt zero). R exactly at the wall is zero since your k should be zero.

Gregor

sam1364 February 1, 2012 10:38

No, I am looking at wall and I am using this initial set up for R

dimensions [0 2 -2 0 0 0 0];

internalField uniform (0 0 0 0 0 0);

boundaryField
{
movingWall
{
type kqRWallFunction;
value uniform (0 0 0 0 0 0);
}
fixedWalls
{
type kqRWallFunction;
value uniform (0 0 0 0 0 0);
}
front
{
type symmetryPlane;
}
}

I guess based on the equation given in Kepsilon.C for R, the values at wall can be non zero.

buct11019 May 14, 2012 03:46

Quote:

Originally Posted by Tarak (Post 307835)
Thanks a lot.

I am using dynamicOneeqEddy model, that's why I am so concerned about it. I am presently simulating the flow over a circular cylinder for Re=3900, but not managing to get an acceptable recirculation length. So, the way you prescribed now may help. If you had any luck with the flow over a circular cylider please do let me know.

Thanks,
Tarak


Nice to meet you , Tarak.
Now I have the same question of you had last year. I am confusing about how to set the k. I had done some work in backward step simulation with oneeqEddy and dynamicOneeqEddy model at the same grid and the same condition. I set k as 1*10-5 in both simulaiton, but the dynamicOneeqEddy model diverge after about 15s, but can go on to compute.Would you please give me some suggestion on it?

rajeshkunwar April 30, 2013 10:20

Hi Gregor

In my URANS simulation k is not equal to 0.5*(Uprime2MeanXX+Uprime2MeanYY+Uprime2MeanZZ). This is probably because k and epsilon are calculated using evolution equation and R is computed using boussinesq approximation. whereas UPrime2Mean is computed using postprocessing of U field. So I doubt Reynolds stress is UPrime2Mean in URANS simulations.
I will appreciate your comment.


All times are GMT -4. The time now is 02:01.