# Creating time/temp dependant variable

 Register Blogs Members List Search Today's Posts Mark Forums Read

 December 21, 2013, 15:59 Creating time/temp dependant variable #1 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 I am trying to create a time and temperature dependant variable within the solidDisplacementFoam solver, currently the value is defined as a constant volScalarField as shown: volScalarField mu("mu", E/(2.0*(1.0 + nu))); I need this to change in the following way: When reaching a certain temperature it should start increasing at a constant rate in time up till reaching a final value at which it stops increasing. I attempted to do this by adding the following code into the main .C file: Code: forAll(mu.internalField(), cellI) { if(T.internalField()[cellI]>330){ mu.internalField()[cellI] = 10e+06; } } mu.correctBoundaryConditions(); mu currently is set to a constant value upon reaching 330K temperature, how would I make this so that it increases at a constant rate in time and stops at a new larger value of mu when reaching the temperature? Any help at all with this problem would be greatly appreciated. Thank you. Last edited by sur4j; December 22, 2013 at 07:07.

 December 22, 2013, 07:20 #2 Senior Member   Join Date: Jan 2012 Posts: 160 Rep Power: 7 hi, I am not sure if it will work like this, but my idea would be something like this: Code: forAll(mu.internalField(), cellI) { if(T.internalField()[cellI]>330 && T.internalField()[cellI]< LIMITTEMPERATURE ) { mu.internalField()[cellI] = FUNCTION FOR mu DEPENDENT ON TEMPERATURE T; } else { mu("mu", E/(2.0*(1.0 + nu))); } } mu.correctBoundaryConditions(); Please note that this is not a 100% save solution since if the temperature rises over the LIMITTEMPERATURE the default value within else {} is used what should be wrong at this point, but you could solve this easily with a else if and afterwards a else . greetings maybee

 December 22, 2013, 08:11 #3 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 Thank you for the reply. For this simulations I need to make it time dependant, there is no upper limit for the temperature. What I am trying to do is find out how to make the "FUNCTION OF mu DEPENDANT ON TIME", so that when the point reaches the specified temperature in the IF statement the variable increases at a certain rate in time for example: IF "this point reaches 330K"{ "start increasing mu at this point at some rate for the next x seconds"} or you could even say something such as "start increasing mu at this point at some rate until reaching the value of mu=x at which point stop any further increase in mu" I attempted to program the temperature dependence in the IF statement I had wrote but don't know where to start with the time dependence.

 December 22, 2013, 08:51 #4 Senior Member   Join Date: Jan 2012 Posts: 160 Rep Power: 7 hi, ok I think I have understood you now. Since the time loop is the master loop of every solver, you will have to tell the compiler by your code that after "T => 330" is reached mu takes for the next X seconds the value Code: mu.OldTime() + specified value e.g. funciton So, for the value of mu you will have to store the mu field (if not done yet) and take the old field and add your specified value (function). The next problem will be the time you have to arrange. For example if you want to do this procedure shown in the above code for 5 seconds and the time step is 1 second you will have to tell the compiler something like Code: if the temperature 330 was reached do the above for the next 5 seconds (5 time steps) Obviously it will be not done easy like this, especially if you have a variable time step (what I don't know). My basic idea is to work with the GLOBAL variables "bool TempReached" and some kind of "count variable TempReachedTime" under which you save the time when T >= 330 was reached plus the time you want to increase mu (in the example 5 seconds). Afterwards you add some code like Code: if (TempReached) //TempReached is to be set true when T >= 330 is reached { //and after the time your increasing has to be finished to be //set false again if (actualTime <= (TempReachedTime + Time to increase mu) ) { forAll(mu.internalField(), cellI) { mu.internalField()[cellI] = mu of internalField of oldTime + specified value; } mu.correctBoundaryConditions(); } } else { forAll(mu.internalField(), cellI) { other value for mu } mu.correctBoundaryConditions(); } Note, this is just a basic idea plus it should only work for constant timesteps. When having variable time steps it gets more complicated. Hope this helps you a little.

 December 22, 2013, 14:27 #5 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 hi maybee, Thank you so much for your help. I am a beginner in programming so am still trying to get my head around how the code works and how to add it to the solver. Just to confirm, will this code do the following: wait until a point inside the body reaches 330K temperature then starts increasing mu at that point at a set rate for say 5 seconds and then stop increasing mu an further? You mentioned I would have to store the mu field, this has not already been done, does this mean that I will have to create an array to store all of the values? Will the following link cover most of what I need to know? http://www.cplusplus.com/doc/tutorial/ maybee likes this.

December 22, 2013, 15:50
#6
Senior Member

Join Date: Jan 2012
Posts: 160
Rep Power: 7
hi again.

Quote:
 Just to confirm, will this code do the following: wait until a point inside the body reaches 330K temperature then starts increasing mu at that point at a set rate for say 5 seconds and then stop increasing mu an further?
I don't know what you mean by wait, but the simulation will proceed with the content of the else {} parenthesis until the temperature T is equal/higher than 330. But you brought up an important point: Since you have to differenciate between the several mesh-cells in your geometry my code does not fullfill this task. Therefore you would have to create a code more like this:

Code:
mu = mu.OldTime() + specified value e.g. funciton
Code:
If in a CELL the temperature 330 is reached do the above for this CELL the next 5 seconds (5 time steps)
Perhaps something like this could work (now it becomes funny ):

Code:
forAll(mu.internalField(), celli)
{
if (TempReached [celli])   //TempReached is to be set true when T >= 330 is reached
{                                 //and after the time your increasing has to be finished to be
//set false again
if (actualTime <= (TempReachedTime[celli] + Time to increase mu) )
{
if (Temp [cellI] >= 330)  //this assures that the temp is still equal/above 330
{
mu.internalField()[cellI] = mu of internalField of oldTime + specified value;
mu.correctBoundaryConditions();
}
}
else
{
mu.internalField()[celli] = other value
}
}
This means you have to implement several lists when using this solution:
-> for every cell you need a own bool TempReached, therefore a List of bools (or an arrat like you would say)
-> for every cell you need variable TempReachedTime, therefore a List of Times
-> I guess the List of temperatures for each cell already exists. [Should be a GeometricField]

Quote:
 You mentioned I would have to store the mu field, this has not already been done, does this mean that I will have to create an array to store all of the values? Will the following link cover most of what I need to know? http://www.cplusplus.com/doc/tutorial/
For the first part see: http://openfoamwiki.net/index.php/Ho...ure_to_icoFoam

The link covers the basics of c++ programming. It is absolutely necessary to understand the most of it. In the OpenFOAM code can be found much more, but this you should search for if needed for your project and after you know about the basics of programming.

Please note that the basic solution idea I have given is probably just one way and perhaps not even the best. I am not a computer scientist, nor I am an expert when it comes to the OpenFOAM code, but I think my idea or something similar to it could work.

 December 23, 2013, 15:01 #7 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 hi Maybee, Again, thank you for the very helpful detailed reply, I greatly appreciate the time you are spending with me on this. I think that I have gained a better understanding for the code now and have attempted to write the global variable arrays for TempReached and TimeTempReached: Code: int TempReached [size];//how to get the maximum value for cellI to get the "size" value? int TempReachedTime [size]; forAll(mu.internalField(), cellI) { if(T.internalField()[cellI]>330){ TempReached [cellI] = true; TempReachedTime [cellI] = currentTime;//how to get the current time? } } I then added the following into your code inside the loop to make the TempReached value false when reaching the required value for mu: Code: if ((actualTime - TempReachedTime[cellI]) => Time to increase mu){ TempReached [cellI] = false; } Firstly, will this code work? Also, I started thinking about what would happen when the time loop changed to the next time value, would the values in the for loop previously written for the global variables be overwritten? If so, would I be required to create multidimensional arrays for the global variables in which the time is taken into account? Thanks.

December 23, 2013, 15:59
#8
Senior Member

Join Date: Jan 2012
Posts: 160
Rep Power: 7
Quote:
 int TempReached [size];//how to get the maximum value for cellI to get the "size" value?
This should be a bool array not an int. You will have to look up in the object in which the cells are stored and search it for the number of cells. E.g. generally the class for this object should be fvMesh: http://foam.sourceforge.net/docs/cpp/a00741.html
If you are lucky a method for getting the number of cells is already existing within the class, if not you have to find a own code solution...

Quote:
 int TempReachedTime [size];
I just noticed this won t be this easy. I guess you will have to define a "twodimensional array" where the first array is for the cells and each cell has it own second array in which the times will be stored when Temp 330 is reached, since the Temp could be reached more than once. Furthermore you ll have to build up some mechanism that guarantees that always the right time is chosen out of the second array for the if condition...

Quote:
 I then added the following into your code inside the loop to make the TempReached value false when reaching the required value for mu: Code: if ((actualTime - TempReachedTime[cellI]) => Time to increase mu){ TempReached [cellI] = false; }
I see you learned some basics, actually it would perhaps be better just to add one else in my code:

Code:
forAll(mu.internalField(), celli)
{

if (Temp[celli] >= 330)
{
TempReached [celli] = true; // added mechanism to set cell bool of bool array true !
}

if (TempReached [celli])   //TempReached is to be set true when T >= 330 is reached
{                                 //and after the time your increasing has to be finished to be
//set false again
if (actualTime <= (TempReachedTime[celli] + Time to increase mu) )
{
if (Temp [cellI] >= 330)  //this assures that the temp is still equal/above 330
{
mu.internalField()[cellI] = mu of internalField of oldTime + specified value;
mu.correctBoundaryConditions();
}
else
{
TempReached [celli] = false;
mu.internalField()[celli] = other value
}
}
else
{
mu.internalField()[celli] = other value
}
}
Note, I also added a mechanism to set the cell booleans true if temp >=330

Quote:
 Firstly, will this code work?
No, the code will not work at the moment.
Aside from what I have posted you will surely have to check all the names I used in the basic IDEA, e.g. the object "actualTime" probably does not exist in this way -> you will have to search in the class Time object for it with something like "runTime.getTime" (in the solver I am working with the time object is called runTime -> look up your solver file).

Quote:
 Also, I started thinking about what would happen when the time loop changed to the next time value, would the values in the for loop previously written for the global variables be overwritten? If so, would I be required to create multidimensional arrays for the global variables in which the time is taken into account?
If the variables are declared/defined outside the time loop

Code:
//GLOBAL VARIABLES HERE DECLARED
while(runTime.loop)
{
.....
}
they will always store the last value they get within the loop. Note, I tested this with a while loop:

Code:
#include <iostream>

int main()
{
int i = 0;
int GLOBAL = 5;
while (i < 10)
{
GLOBAL ++;
i ++;
}
std::cout << GLOBAL << std::endl;
std::cout << i << std::endl;
return 0;
}
Just test it yourself if you like to .

About the array see what I have written above.

 December 23, 2013, 16:21 #9 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 Thanks for the fast and VERY helpful reply. Quick question, the simulations I plan on running with this solver are simple heat transfer simulations where a constant temperature BC is set at the walls therefore, I think that the temperature should only reach 330 once. For this simulation would the two dimensional array you mentioned above be necessary or could I continue using a simple 1D array?

December 23, 2013, 16:32
#10
Senior Member

Join Date: Jan 2012
Posts: 160
Rep Power: 7
Quote:
 Thanks for the fast and VERY helpful reply. Quick question, the simulations I plan on running with this solver are simple heat transfer simulations where a constant temperature BC is set at the walls therefore, I think that the temperature should only reach 330 once. For this simulation would the two dimensional array you mentioned above be necessary or could I continue using a simple 1D array?
In this case I guess a 1D array should be enough. Obviously this will limit your solver to a case where temp >=330 only one time is reached within the process.

Aside from this note, that you will have to define a mechanism that stores the time when temp >= 330 is reached, but exactly the time when it is reached the first time, since you want to use the "first occure time" for "TempReachedTime[celli]" within

Code:
if (actualTime <= (TempReachedTime[celli] + Time to increase mu)

 December 23, 2013, 18:03 #11 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 Is [cellI] an array? If so to find the size of the [cellI] could I not use the following simple code? (sizeof((celli))/sizeof((celli[0]))) Where the size of the entire array is found in bytes and then divided by the size of a single element of that array to get the total number of elements? and then maybe to stay safe I could add a bit to it to make sure that there is enough elements. Or if not could the following be used? int a;//this sits outside the time loop forAll(mu.internalField(), celli) {a++;} Then use the value for "a" to define the size?

December 24, 2013, 09:21
#12
Senior Member

Join Date: Jan 2012
Posts: 160
Rep Power: 7
Quote:
 Is [cellI] an array? If so to find the size of the [cellI] could I not use the following simple code? (sizeof((celli))/sizeof((celli[0]))) Where the size of the entire array is found in bytes and then divided by the size of a single element of that array to get the total number of elements? and then maybe to stay safe I could add a bit to it to make sure that there is enough elements.
Hmmm, no . An array is for example

Code:
int TempReachedTime [size];
where int defines the type of the array which means the elements of the array are of type int, where the array is "TempReachedTime" and where within [size] you define the size of the array which means how much elements are inside the array. If you leave it empty like [] the size will be chosen dynamically as needed, but generally it should be better to give the array the right size.
Furthermore the forAll loop shows how you can access the different elements of the array and therefore an iterator (with the name celli) is used which number is increased with every loop pass, e.g. in the first pass celli is 0 therefore the first element of the array "TempReachedTime" is accessed, in the second pass celli is 1 therefore the second element of the array "TempReachedTime" is accessed and so on.

But these all are c++ basics, if you can't understand it from tutorials use a c++ forum or a good book. See:

You can also switch between tutorials if one doesn 't explain a content good enough for you...

greetings
maybee

December 24, 2013, 11:24
#13
Member

Join Date: Aug 2013
Posts: 60
Rep Power: 6
Thank you for the reply. I did not realise that you could define a dynamic array by simply leaving the brackets empty, this will make things much simpler for me. I have started learning more about C++, I had read a lot about it in the past but never really understood it, I think this was because I never written the code and only looked at examples done by others therefore, I am going to write some code, to start off I wanted to see if an alternative method I had a while back to program this solver would work.

Quote:
 "start increasing mu at this point at some rate for the next x seconds"
or
Quote:
 "start increasing mu at this point at some rate until reaching the value of mu=x at which point stop any further increase in mu"
We had mainly concentrated on the first quote but I think it may be easier coding the second method, I have tried to write the code for this:
Code:
int deltaMu = the amount to increase mu each time step

forAll(mu.internalField(), cellI)
{
if(T.internalField()[cellI]>330){
if(mu.internalField()[cellI]<(mu+(deltaMu*5))){
mu.internalField()[cellI]+=deltaMu
mu.correctBoundaryConditions();
}
}
else{
mu.internalField()[cellI] = mu;//mu defined in previous code
mu.correctBoundaryConditions();
}
}
Would the above code work for this simulation?

EDIT: I added this code into the solver and it seems to work, do you notice anything that has been missed in this code? Would you suggest any improvements?

Thanks

Last edited by sur4j; December 24, 2013 at 12:55.

 December 24, 2013, 12:13 #14 Senior Member   Join Date: Jan 2012 Posts: 160 Rep Power: 7 Your code: Code: int deltaMu = the amount to increase mu each time step forAll(mu.internalField(), cellI) { if(T.internalField()[cellI]>330){ if(mu.internalField()[cellI]<(mu+(deltaMu*5))){ mu.internalField()[cellI]+=deltaMu mu.correctBoundaryConditions(); } } else{ mu.internalField()[cellI] = mu;//mu defined in previous code mu.correctBoundaryConditions(); } } Hi, this will work, but you have to think about the consequences... . You could define your own mu let us say muSTATIC = 2; (just as example). But let us go through the simulation to see what will happen: 1. Temp goes up to >=330 and mu.internalField() is increased like you want to for a specific time in every timestep. 2. Now the specific time is over -> what possibilities do we have: 2.1 The temperature is still >= 330 -> mu is increased again 2.2 The temperature is under 330 (e.g.325) -> mu instantly "jumps back" to another value -> from physical view strange My idea would be now : why not develop a mathematical function for mu in dependence of the temperature -> With this you could achieve a much more logical solution from a physical view (which is the important view here ). For example: Code: int muMAX = yourvalue; forAll(mu.internalField(), cellI) { if(mu.internalField()[cellI]< muMAX) //checks if final value for mu is reached { mu.internalField()[cellI]+= muBASIS + (mu per Kelvin) * Temperature // 1Grade Function mu.correctBoundaryConditions(); } } else //in this else: mu for the limittemperature must be defined { mu.internalField()[cellI] =muMAX // in other words "maximal mu" mu.correctBoundaryConditions(); } } Surely it has not to be a linear function 1 grade used for mu... Plus you won't need any any other variables like arrays ... sur4j likes this.

 December 24, 2013, 13:05 #15 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 Thanks for the improvements. Just out of interest, I had a problem when running the code I had previously written. When I use the following part of my code for example the solver compiles fine: if(mu.internalField()[cellI]<(9e+06+(deltaMu*3))) However, when I change the constant to the defined value mu as shown, I get an error: if(mu.internalField()[cellI]<(mu+(deltaMu*3))) This is strange because it is defined the same way in the equations inside of the same file, for example in the DEqun: fvm::laplacian(2*mu + lambda, D, "laplacian(DD,D)") mu itself is defined as shown in another header file as shown below. This header file is included at the start of the main code. volScalarField mu("mu", E/(2.0*(1.0 + nu))); If it helps, the error I am getting when using wmake on the solver is the following: Code: Making dependency list for source file cureFoam.C SOURCE=cureFoam.C ; g++ -m32 -Dlinux -DWM_DP -Wall -Wextra -Wno-unused-parameter -Wold-style-cast -O3 -DNoRepository -ftemplate-depth-100 -I/opt/openfoam222/src/finiteVolume/lnInclude -ItractionDisplacement/lnInclude -IlnInclude -I. -I/opt/openfoam222/src/OpenFOAM/lnInclude -I/opt/openfoam222/src/OSspecific/POSIX/lnInclude -fPIC -c \$SOURCE -o Make/linuxGccDPOpt/cureFoam.o cureFoam.C: In function ‘int main(int, char**)’: cureFoam.C:82:46: error: no match for ‘operator<’ in ‘(& mu.Foam::GeometricField::internalField [with Type = double, PatchField = Foam::fvPatchField, GeoMesh = Foam::volMesh, Foam::GeometricField::InternalField = Foam::Field]())->Foam::Field::.Foam::List::.Foam::UList::operator[] [with T = double, Foam::label = int](cellI) < Foam::operator+(const Foam::GeometricField&, const scalar&) [with PatchField = Foam::fvPatchField, GeoMesh = Foam::volMesh, Foam::scalar = double]((* &(Foam::scalar)(deltaMu * 3)))’ cureFoam.C:82:46: note: candidates are: /opt/openfoam222/src/OpenFOAM/lnInclude/dimensionedType.C:586:6: note: template bool Foam::operator<(const Foam::dimensioned&, const Foam::dimensioned&) /opt/openfoam222/src/OpenFOAM/lnInclude/VectorSpaceI.H:677:13: note: template bool Foam::operator<(const Foam::VectorSpace&, const Foam::VectorSpace&) readSolidDisplacementFoamControls.H:3:11: warning: unused variable ‘nCorr’ [-Wunused-variable] readSolidDisplacementFoamControls.H:5:8: warning: unused variable ‘convergenceTolerance’ [-Wunused-variable] make: *** [Make/linuxGccDPOpt/cureFoam.o] Error 1 As mentioned, this error does not appear when compiling with a value such as 9e+06 instead of mu so I think that things such as "error: no match for ‘operator<’" are not the real errors and are just created because of the way mu is defined. How would I define mu so that this error does not occur?

 December 24, 2013, 14:46 #16 Senior Member   Join Date: Jan 2012 Posts: 160 Rep Power: 7 hi, I am not sure, but when you look at Code: mu.internalField()[cellI] this should be some kinde of field (array) since you access the mu of the internal field of each cell. So I guess if you use the whole field for some calculation like probably here Code: fvm::laplacian(2*mu + lambda, D, "laplacian(DD,D)") it is okay to use the field, but not in this case Code: mu+(deltaMu*3) where you would add an int to a field and this operation perhaps is not defined. However, this is my guess .

 December 24, 2013, 15:01 #17 Member   Join Date: Aug 2013 Posts: 60 Rep Power: 6 Thanks for your help, I have a few more questions but will dedicate a new thread to them. Last edited by sur4j; December 26, 2013 at 08:39.

 Thread Tools Display Modes Linear Mode

 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 OffTrackbacks are On Pingbacks are On Refbacks are On Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post cfdonline2mohsen OpenFOAM 3 October 21, 2013 09:28 charlotte CFX 4 March 22, 2011 10:14 bhushas Main CFD Forum 1 May 30, 2008 04:35 gruber2 OpenFOAM Installation 5 December 30, 2005 05:27 lego CFX 3 November 5, 2002 21:09

All times are GMT -4. The time now is 09:56.