CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > Software User Forums > OpenFOAM > OpenFOAM Post-Processing

Uprime2Mean and R (LES)

Register Blogs Community New Posts Updated Threads Search

Like Tree23Likes

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   February 13, 2020, 07:17
Default Uprime2Mean and R (LES)
  #1
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Hey everyone,

To repeat how 90% of posts here go, I'm relatively new to OpenFOAM, and I am having an issue processing the Reynolds Stress Tensor for my SA-based DES case.

My understanding is that 'Uprime2Mean' provides the Reynolds Stress Tensor of the resolved flow, while 'R' provides the sub-grid (modelled) tensor. With these two values it should be possible to produce a field that displays the percentage of resolved TKE as a method of mesh validation.

I'm seeking some guidance on how to either obtain an average of 'R' to use with 'Uprime2Mean' obtained through the fieldAverage function or an instantaneous value of 'Uprime2Mean' to use with 'R' obtained through the eponymous Post-Processing function.

I half expect that this is a horribly inefficient method of obtaining the desired data, and any other suggestions would be equally welcome!

Thanks,
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 13, 2020, 11:13
Default
  #2
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Quote:
Originally Posted by cjc96 View Post
Hey everyone,

To repeat how 90% of posts here go, I'm relatively new to OpenFOAM, and I am having an issue processing the Reynolds Stress Tensor for my SA-based DES case.

My understanding is that 'Uprime2Mean' provides the Reynolds Stress Tensor of the resolved flow, while 'R' provides the sub-grid (modelled) tensor. With these two values it should be possible to produce a field that displays the percentage of resolved TKE as a method of mesh validation.

I'm seeking some guidance on how to either obtain an average of 'R' to use with 'Uprime2Mean' obtained through the fieldAverage function or an instantaneous value of 'Uprime2Mean' to use with 'R' obtained through the eponymous post-processing function.

I half expect that this is a horribly inefficient method of obtaining the desired data, and any other suggestions would be equally welcome!

Thanks,
As an update, I have managed to produce time-averages of both 'Uprime2Mean' and 'R' by modifying the 'turbulenceFields' function to execute each time-step, thus allowing the 'fieldAverage' function to produce an average value for 'R'

I'm now hoping to produce the field:

Code:
(1/2*tr(Uprime2Mean))/(1/2*tr(R + Uprime2Mean))
as a post-processing step, but this is where my limited knowledge of C++ is starting to become a hindrance!

Any guidance would be appreciated,
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 13, 2020, 16:36
Default
  #3
HPE
Senior Member
 
HPE's Avatar
 
Herpes Free Engineer
Join Date: Sep 2019
Location: The Home Under The Ground with the Lost Boys
Posts: 932
Rep Power: 12
HPE is on a distinguished road
Might misunderstand you, but here we go: your understanding on these objects is correct.

You can obtain 'RMean' by the same FO 'fieldAverage', and use it with 'UPrime2Mean' at the end of a sim?
cjc96 likes this.
HPE is offline   Reply With Quote

Old   February 14, 2020, 04:59
Default
  #4
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Quote:
Originally Posted by HPE View Post
Might misunderstand you, but here we go: your understanding on these objects is correct.

You can obtain 'RMean' by the same FO 'fieldAverage', and use it with 'UPrime2Mean' at the end of a sim?
Hey HPE,
Thanks for your reply!

I actually made a bit of progress last night, but my post got caught by the new user moderator checks so didn't come through until after your response.

If you read that post you'll see I am now trying to form a new field, produced from:

Code:
(1/2*tr(Uprime2Mean))/(1/2*tr(RMean + Uprime2Mean))
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 14, 2020, 15:22
Default
  #5
HPE
Senior Member
 
HPE's Avatar
 
Herpes Free Engineer
Join Date: Sep 2019
Location: The Home Under The Ground with the Lost Boys
Posts: 932
Rep Power: 12
HPE is on a distinguished road
codedFunctionObjects can do it easily. Have a go for a review, and see by urself. I can provide an example after sitting in front of a PC unless you or other helpmates do earlier.
cjc96 likes this.
HPE is offline   Reply With Quote

Old   February 17, 2020, 05:03
Default
  #6
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Quote:
Originally Posted by HPE View Post
codedFunctionObjects can do it easily. Have a go for a review, and see by urself. I can provide an example after sitting in front of a PC unless you or other helpmates do earlier.
Hello again HPE,
Thanks once more for your help.

I've had a look into codedFunctionObjects. I was able to get a basic function to work (simply reading and printing out a field value) but I'm hitting some errors when I try to include the functionality to calculate the ratio I need. Unfortunately, my current lack of experience with C++ means most of the errors are beyond my understanding.

Code:
resolvedTKE
{
	type			coded;
	libs			("libutilityFunctionObjects.so");
	name			resolvedTKE;
	executeControl	timeStep
	executeInterval	1;
	writeControl	writeTime;
//	timeStart		0.5;
//	timeEnd			1;
	enabled			false;

	codeOptions
	#{
		-I$(LIB_SRC)/meshTools/lnInclude
	#};

	codeExecute
	#{
		const volSymmTensorField& RMean = mesh().lookupObject<volSymmTensorField>("RMean");
		const volSymmTensorField& UPrime2Mean = mesh().lookupObject<volSymmTensorField>("UPrime2Mean");

		Info << "Min RMean = " << min(RMean) << endl;
		Info << "Min UPrime2Mean = " << min(UPrime2Mean) << endl;

		// volScalarField resolvedTKE
		// (
		// 	IOobject
		// 	(
		// 		"resolvedTKE",
		// 		runTime.timeName(),
		// 		mesh,
		// 		IOobject::NO_READ,
		// 		IOobject::AUTO_WRITE
		// 	),
		// 	mesh,
		// 	dimensionedScalar(dimless, 0)
		// );
		//
		// resolvedTKE = ((1.0 / 2.0) * tr(UPrime2Mean)) / ((1.0 / 2.0) * tr(RMean + UPrime2Mean));
		// resolvedTKE.write();
	#};
}
If you view the above code, the function works as presented, but if I include the commented section it breaks.

I'd again appreciate any advice you can provide!
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 17, 2020, 08:38
Default
  #7
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
The following code appears to mostly work:

Code:
resolvedTKE
{
	type			coded;
	libs			("libutilityFunctionObjects.so");
	name			resolvedTKE;
	writeControl	runTime;
	writeInterval	0.005;
	// timeStart		0.5;
	// timeEnd			1;
	enabled			true;

	codeExecute
	#{
		const volSymmTensorField& RMean = mesh().lookupObject<volSymmTensorField>("RMean");
		const volSymmTensorField& UPrime2Mean = mesh().lookupObject<volSymmTensorField>("UPrime2Mean");

		volScalarField resolvedTKE
		(
			IOobject
			(
				"resolvedTKE",
				mesh().time().timeName(),
				mesh(),
				IOobject::NO_READ,
				IOobject::AUTO_WRITE
			),
			mesh(),
			dimensionedScalar(dimless, 0)
		);

		resolvedTKE = ((1.0 / 2.0) * tr(UPrime2Mean)) / ((1.0 / 2.0) * tr(RMean + UPrime2Mean));
		resolvedTKE.write();
	#};
}
However, the function ignores any writeControl or executeControl statements I include at the start, instead writing every time-step which is somewhat undesirable.

Due to this being a 'time' related problem, I'm assuming the issue is a result of one of (or a combination of) these lines:

Code:
mesh().time().timeName(),

IOobject::AUTO_WRITE

resolvedTKE.write();
But playing around with them seems to only result in no writes whatsoever.
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 17, 2020, 12:18
Default
  #8
HPE
Senior Member
 
HPE's Avatar
 
Herpes Free Engineer
Join Date: Sep 2019
Location: The Home Under The Ground with the Lost Boys
Posts: 932
Rep Power: 12
HPE is on a distinguished road
I haven't compiled it below, because I don't have a test-case, might need to add a `codeOptions`.

Let me know if it would be any help. I'm not sure since I'm bloody getting old. :]

Code:
resolvedTKE
{
    functionObjectLibs  (utilityFunctionObjects);
    type                coded;
    name              resolvedTKE;
    writeControl    writeTime;
    codeExecute
    #{
        static autoPtr<volScalarField> tkeRatio;
        if
        (
            mesh().time().timeIndex() == 1
            ||
            mesh().time().startTimeIndex() == mesh().time().timeIndex() - 1
        )
        {
            Info<< "    # First time-step or restart:" << nl;
            tkeRatio.set
            (
                new volScalarField
                (
                    IOobject
                    (
                        "tkeRatio",
                         mesh().time().timeName(),
                         mesh(),
                         IOobject::NO_READ,
                         IOobject::AUTO_WRITE
                     ),
                     mesh(),
                     dimless
                 )
             );
         }
         if (mesh().time().timeIndex() != 1)
         {
             const volSymmTensorField& RMean =
                mesh().lookupObjectRef<volSymmTensorField>("RMean");
             const volSymmTensorField& UPrime2Mean =
                mesh().lookupObjectRef<volSymmTensorField>("UPrime2Mean");
             volScalarField& tkeRatio = 
                mesh().lookupObjectRef<volScalarField>("tkeRatio");

            Info << "Min RMean = " << min(RMean) << endl;
            Info << "Min UPrime2Mean = " << min(UPrime2Mean) << endl;

            tkeRatio =
                (0.5*tr(UPrime2Mean))/(0.5*tr(RMean + UPrime2Mean) + SMALL);

            if (mesh().time().outputTime())
            {
                Info<< "    ### Writing out tkeRatio field" << nl << nl;
                tkeRatio.write();
            }
        }
    #};
}
FYI: I'm using v1912.

FYI: You need to have `RMean` and `UPrime2Mean` beforehand this FO, e.g. by using `fieldAverage`.
cjc96 and Agavi like this.
HPE is offline   Reply With Quote

Old   February 18, 2020, 09:03
Default
  #9
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Hello again HPE,
Thanks again for your help!

I've got the function mostly working now thanks to your input, and as a form of practice merged your code with my own as opposed to simply taking your code in its entirety.

Hopefully these will be my last questions for you and then you can go onto more important things!

Firstly, using:

Code:
if
(
	mesh().time().timeIndex() == 1
	||
	mesh().time().startTimeIndex() == mesh().time().timeIndex() - 1
)
is there a method to have the field initialise in the 0 directory, as opposed to during the first time step? In this case it doesn't actually matter, but could be useful in the future.

-------------------

Secondly, in your code:

Code:
tkeRatio = (0.5 * tr(UPrime2Mean)) / (0.5 * tr(RMean + UPrime2Mean) + SMALL);
I'm failing to see what the '+ SMALL' addition denotes, I'm guessing it is something left over from one of your own functions?

-------------------

Finally, I'd like the function to only write during a set time interval, such as can be done with the 'fieldAverage' function by denoting 'timeStart' and 'timeEnd'

My best guess thus far has been:

Code:
if
(
	mesh().time().writeTime()
	&&
	mesh().time().value() >= $timeStart
)
however, the compiler states that 'timeStart' hasn't been properly declared, leading me to presume it is included in another function somewhere (to be added using #include) but I am unsure which one.

-------------------

Thanks again for your time, I really am grateful
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU

Last edited by cjc96; February 18, 2020 at 10:07.
cjc96 is offline   Reply With Quote

Old   February 18, 2020, 13:27
Default
  #10
HPE
Senior Member
 
HPE's Avatar
 
Herpes Free Engineer
Join Date: Sep 2019
Location: The Home Under The Ground with the Lost Boys
Posts: 932
Rep Power: 12
HPE is on a distinguished road
>> is there a method to have the field initialise in the 0 directory, as opposed to during the first time step? In this case it doesn't actually matter, but could be useful in the future.

OpenFOAM learned `setExprFields`, link, which you can use it to initialise fields like by using swak4Foam.

>> I'm failing to see what the '+ SMALL' addition denotes, I'm guessing it is something left over from one of your own functions?

Not sure throws error when compiled (because I haven't compiled it), but `SMALL` is an OpenFOAM object which is equal to the smallest floating-point, for my double-precision compilation SMALL=1e-15. SMALL is there in the denominator to avoid zero-division error, which might be annoying if you are not familiar with.

>> Finally, I'd like the function to only write during a set time interval, such as can be done with the 'fieldAverage' function by denoting 'timeStart' and 'timeEnd'

You can use these keywords in codedFOs as well. But they are not for writing, but execution. Outside of their interval, the FO will not be executed.

>> however, the compiler states that 'timeStart' hasn't been properly declared, leading me to presume it is included in another function somewhere (to be added using #include) but I am unsure which one.

`timeStart` is not known locally. If you want it, you need to construct it like

`const scalar timeStart = 10;`

Or you need to turn-on the generic `timeStart` keyword up there somewhere. Otherwise, compiler will not recognise it since C++ statically defined language (your object type must be known there).

Hope it helps.
cjc96 likes this.
HPE is offline   Reply With Quote

Old   February 20, 2020, 05:11
Default
  #11
Senior Member
 
Andrea
Join Date: Feb 2012
Location: Leeds, UK
Posts: 179
Rep Power: 16
Andrea1984 is on a distinguished road
Hi Conor,

an alternative method could be to hardcode resolved TKE, epsilon and all the other variables you need in a modified version of the solver. I gave it a go here: pimpleTKEBudgetFoam, which also includes a LESResolutionIndex = k_res/(k_modelled + k_res)

Andrea
acgnipper, HPE, cjc96 and 1 others like this.
Andrea1984 is offline   Reply With Quote

Old   February 26, 2020, 06:08
Default
  #12
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Quote:
Originally Posted by Andrea1984 View Post
Hi Conor,

an alternative method could be to hardcode resolved TKE, epsilon and all the other variables you need in a modified version of the solver. I gave it a go here: pimpleTKEBudgetFoam, which also includes a LESResolutionIndex = k_res/(k_modelled + k_res)

Andrea
Hey Andrea,
Thanks for replying!

Had a look through your repository and while I think I'll stick with the function for the time being, as I think it offers a bit more flexibility in what I am trying to do at the moment, it was very useful and I did pinch a few aspects of your code!

One thing I did disagree with however, and this may in actuality just be poor understanding on my part, is your calculation of 'kRes'

Code:
volVectorField UPrime = (U - db.lookupObject<volVectorField>("UMean"));

volScalarField kRes = 0.5*(UPrime & UPrime);
I understand that you have avoided needing to actually build the Reynolds Stress Tensor, seeing as we are only interested in the leading diagonal. However, am I not right in saying that:

R_{ij} \equiv \overline{u'_{i}u'_{j}}

And that you are in fact calculating:

Andrea_{ij} \equiv {u'_{i}u'_{j}}

Again, forgive me if I have totally misinterpreted either your code, or the underlying maths but I am eager to learn either way!
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 26, 2020, 06:14
Default
  #13
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Also,
I just thought I'd include the function I settled on (for now) for reference, in case someone is working on a similar problem in the future:

Code:
LESIndex
{
	type			coded;
	libs			("libutilityFunctionObjects.so");
	name			LESIndex;
	executeControl	writeTime;
	writeControl	writeTime;
	// timeStart		0;
	// timeEnd		0;
	enabled			true;

/*---------------------------------------------------------------------------*\

	LES Quality Evaluation
		** Requires fieldAverage Function to Obtain UPrime2Mean**
			** Resolved Reynolds Stress Tensor
		** Requires turbulenceFields Function to Obtain R**
			** Subgrid Reynolds Stress Tensor

\*---------------------------------------------------------------------------*/

	codeExecute
	#{
		static autoPtr<volScalarField> LESIndex;

		if
		(
			mesh().foundObject<volSymmTensorField>("UPrime2Mean")
			&&
			mesh().foundObject<volSymmTensorField>("R")
			&&
			mesh().foundObject<volScalarField>("LESIndex") == 0
		)
		{
			Info << "LES Quality Index:" << endl;
			Info << "	Initialising" << endl;
			Info << "	Calculating" << nl << endl;

			LESIndex.set
			(
				new volScalarField
				(
					IOobject
					(
						"LESIndex",
						mesh().time().timeName(),
						mesh(),
						IOobject::NO_READ,
						IOobject::AUTO_WRITE
					),
					mesh(),
					dimensionedScalar
					(
						"LESIndex",
						dimless,
						0
					)
				)
			);

			const volSymmTensorField& R = mesh().lookupObjectRef<volSymmTensorField>("R");
			const volSymmTensorField& UPrime2Mean = mesh().lookupObjectRef<volSymmTensorField>("UPrime2Mean");

			volScalarField& LESIndex = mesh().lookupObjectRef<volScalarField>("LESIndex");
			LESIndex = (0.5 * tr(UPrime2Mean)) / (0.5 * tr(R + UPrime2Mean));
			LESIndex.write();
		}

		else if
		(
			mesh().foundObject<volSymmTensorField>("UPrime2Mean")
			&&
			mesh().foundObject<volSymmTensorField>("R")
			&&
			mesh().foundObject<volScalarField>("LESIndex")
		)
		{
			Info << "LES Quality Index:" << endl;
			Info << "	Calculating" << nl << endl;

			const volSymmTensorField& R = mesh().lookupObjectRef<volSymmTensorField>("R");
			const volSymmTensorField& UPrime2Mean = mesh().lookupObjectRef<volSymmTensorField>("UPrime2Mean");

			volScalarField& LESIndex = mesh().lookupObjectRef<volScalarField>("LESIndex");
			LESIndex = (0.5 * tr(UPrime2Mean)) / (0.5 * tr(R + UPrime2Mean));
			LESIndex.write();
		}

		else
		{
			Info << "LES Quality Index:" << endl;
			Warning << endl
					<< "	Unable to Calculate LES Quality Index" << endl
					<< "	UPrime2Mean and/or R Unavailable" << endl
					<< "	Enable fieldAverage and turbulenceFields Functions" << nl << endl;
		}
	#};
}
The final function takes elements from my original attempt, HPE's function and Andrea's solver
shock77 likes this.
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 26, 2020, 06:21
Default
  #14
Senior Member
 
Andrea
Join Date: Feb 2012
Location: Leeds, UK
Posts: 179
Rep Power: 16
Andrea1984 is on a distinguished road
Hi Conor,

in a previous version of the code (see first commit) I had something like:

Code:
RRes = symm((UPrime*UPrime)); //Instantaneous resolved Reynolds stress tensor
kRes = 0.5*tr(RRes);
Than I realised that I was not interested in the non-diagonal components of R, so I though I would avoid the calculation of R altogether and just use

Code:
volScalarField kRes = 0.5*(UPrime & UPrime);
which, if I am not mistaken, is essentially the same, i.e.:

k=\frac{1}{2}\overline{u_i u_i}=\frac{1}{2} \left (\overline{u_1^2}+\overline{u_2^2}+\overline{u_3^2} \right)

Hope this clarifies it

Andrea
cjc96 likes this.
Andrea1984 is offline   Reply With Quote

Old   February 26, 2020, 07:57
Default
  #15
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Hey Andrea,

Yes, I totally agree that we aren't interested in the entire Reynolds Stress Tensor so may as well simplify the calculation.

However, unless I am misinterpreting your code, which as I said at the start of this thread, is entirely possible (I am very much new to this) you are calculating:

k = \frac{1}{2} (u'u') = \frac{1}{2} (u'^{2}_{i}+u'^{2}_{j}+u'^{2}_{k})

as opposed to:

k = \frac{1}{2} (\overline{u'u'}) = \frac{1}{2} (\overline{u'^{2}_{i}}+\overline{u'^{2}_{j}}+\overline{u'^{2}_{k}})

Again, I do apologise if I am just being a massive idiot =D
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   February 26, 2020, 08:08
Default
  #16
Senior Member
 
Andrea
Join Date: Feb 2012
Location: Leeds, UK
Posts: 179
Rep Power: 16
Andrea1984 is on a distinguished road
Lol no need to apologies, I am not 100% sure as well. Actually I believe I was wrong in my previous post to include the overbar in my definition of kRes.

It is true I am calculating the "instantaneous" value of kRes - I figured that I can then obtain the time-averaged kRes by just adding kRes (instantaneous) to the fieldAverage utility, which would output kResMean, i.e. including the overbar.

I am not entirely sure if this is mathematically correct, it was leading to reasonable results in a test I did in a simple channel flow though. See snapshot below:

https://imgur.com/yM6fNQx
cjc96 likes this.
Andrea1984 is offline   Reply With Quote

Old   February 27, 2020, 10:03
Default
  #17
New Member
 
Josh
Join Date: Jun 2013
Posts: 19
Rep Power: 12
joshm is on a distinguished road
Quote:
Originally Posted by Andrea1984 View Post
Lol no need to apologies, I am not 100% sure as well. Actually I believe I was wrong in my previous post to include the overbar in my definition of kRes.

It is true I am calculating the "instantaneous" value of kRes - I figured that I can then obtain the time-averaged kRes by just adding kRes (instantaneous) to the fieldAverage utility, which would output kResMean, i.e. including the overbar.

I am not entirely sure if this is mathematically correct, it was leading to reasonable results in a test I did in a simple channel flow though. See snapshot below:

https://imgur.com/yM6fNQx

If you forget to do this at runtime, as long as you do have the mean U and nut fields, you can just change the name of UMean to U and nutMean to nut and run the R utility.
Andrea1984 likes this.
joshm is offline   Reply With Quote

Old   April 17, 2020, 12:10
Default
  #18
Senior Member
 
Arijit Saha
Join Date: Feb 2019
Location: Singapore
Posts: 132
Rep Power: 7
ari003 is on a distinguished road
Quote:
Originally Posted by cjc96 View Post
As an update, I have managed to produce time-averages of both 'Uprime2Mean' and 'R' by modifying the 'turbulenceFields' function to execute each time-step, thus allowing the 'fieldAverage' function to produce an average value for 'R'

I'm now hoping to produce the field:

Code:
(1/2*tr(Uprime2Mean))/(1/2*tr(R + Uprime2Mean))
as a post-processing step, but this is where my limited knowledge of C++ is starting to become a hindrance!

Any guidance would be appreciated,
I can use that equation to find the value of resolved KE in spreadsheet. But I m not getting what does that tr denotes. Please can anyone say that?
ari003 is offline   Reply With Quote

Old   April 17, 2020, 12:13
Default
  #19
Member
 
Conor Crickmore
Join Date: Jan 2020
Location: Leicestershire, United Kingdom
Posts: 36
Rep Power: 6
cjc96 is on a distinguished road
Quote:
Originally Posted by ari003 View Post
I can use that equation to find the value of resolved KE in spreadsheet. But I m not getting what does that tr denotes. Please can anyone say that?
Hey bud,

The symbol 'tr' denotes the trace of a matrix

Hope that helps!
ari003 likes this.
__________________
Conor Crickmore
PhD Researcher in Automotive Aerodynamics
Aeronautical and Automotive Engineering
Loughborough University
LE11 3TU
cjc96 is offline   Reply With Quote

Old   August 25, 2020, 04:50
Default
  #20
New Member
 
Ran Yi
Join Date: May 2019
Posts: 9
Rep Power: 6
lizzy is on a distinguished road
Hello Conor,
Thanks for your share. I'm wandering if the "R" in your final coded function denotes the averaged value of R? Or just an instaneous tensor value?

Quote:
Originally Posted by cjc96 View Post
Also,
I just thought I'd include the function I settled on (for now) for reference, in case someone is working on a similar problem in the future:

Code:
LESIndex
{
	type			coded;
	libs			("libutilityFunctionObjects.so");
	name			LESIndex;
	executeControl	writeTime;
	writeControl	writeTime;
	// timeStart		0;
	// timeEnd		0;
	enabled			true;

/*---------------------------------------------------------------------------*\

	LES Quality Evaluation
		** Requires fieldAverage Function to Obtain UPrime2Mean**
			** Resolved Reynolds Stress Tensor
		** Requires turbulenceFields Function to Obtain R**
			** Subgrid Reynolds Stress Tensor

\*---------------------------------------------------------------------------*/

	codeExecute
	#{
		static autoPtr<volScalarField> LESIndex;

		if
		(
			mesh().foundObject<volSymmTensorField>("UPrime2Mean")
			&&
			mesh().foundObject<volSymmTensorField>("R")
			&&
			mesh().foundObject<volScalarField>("LESIndex") == 0
		)
		{
			Info << "LES Quality Index:" << endl;
			Info << "	Initialising" << endl;
			Info << "	Calculating" << nl << endl;

			LESIndex.set
			(
				new volScalarField
				(
					IOobject
					(
						"LESIndex",
						mesh().time().timeName(),
						mesh(),
						IOobject::NO_READ,
						IOobject::AUTO_WRITE
					),
					mesh(),
					dimensionedScalar
					(
						"LESIndex",
						dimless,
						0
					)
				)
			);

			const volSymmTensorField& R = mesh().lookupObjectRef<volSymmTensorField>("R");
			const volSymmTensorField& UPrime2Mean = mesh().lookupObjectRef<volSymmTensorField>("UPrime2Mean");

			volScalarField& LESIndex = mesh().lookupObjectRef<volScalarField>("LESIndex");
			LESIndex = (0.5 * tr(UPrime2Mean)) / (0.5 * tr(R + UPrime2Mean));
			LESIndex.write();
		}

		else if
		(
			mesh().foundObject<volSymmTensorField>("UPrime2Mean")
			&&
			mesh().foundObject<volSymmTensorField>("R")
			&&
			mesh().foundObject<volScalarField>("LESIndex")
		)
		{
			Info << "LES Quality Index:" << endl;
			Info << "	Calculating" << nl << endl;

			const volSymmTensorField& R = mesh().lookupObjectRef<volSymmTensorField>("R");
			const volSymmTensorField& UPrime2Mean = mesh().lookupObjectRef<volSymmTensorField>("UPrime2Mean");

			volScalarField& LESIndex = mesh().lookupObjectRef<volScalarField>("LESIndex");
			LESIndex = (0.5 * tr(UPrime2Mean)) / (0.5 * tr(R + UPrime2Mean));
			LESIndex.write();
		}

		else
		{
			Info << "LES Quality Index:" << endl;
			Warning << endl
					<< "	Unable to Calculate LES Quality Index" << endl
					<< "	UPrime2Mean and/or R Unavailable" << endl
					<< "	Enable fieldAverage and turbulenceFields Functions" << nl << endl;
		}
	#};
}
The final function takes elements from my original attempt, HPE's function and Andrea's solver
lizzy is offline   Reply With Quote

Reply

Tags
des les, les, reynolds stress tensor, turbulent kinetic energy


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
LES best practice: resolved and modelled turbulence kinetic energy em17 OpenFOAM Running, Solving & CFD 22 April 17, 2020 13:01
Relation between k and UPrime2Mean etc in LES Tarak OpenFOAM Running, Solving & CFD 49 August 10, 2018 13:10
Worse accuracy in LES models than in RANS models dferrando OpenFOAM Running, Solving & CFD 0 August 30, 2017 04:56
Resolved KE versus SGS KE - LES smog OpenFOAM 0 February 11, 2016 18:01
Bug in Dynamic 1Eq Eddy Viscosity LES Model Incompressible flow harishg OpenFOAM Bugs 5 December 2, 2008 18:18


All times are GMT -4. The time now is 16:57.