CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Creating time/temp dependant variable (https://www.cfd-online.com/Forums/openfoam-programming-development/127813-creating-time-temp-dependant-variable.html)

sur4j December 21, 2013 15:59

Creating time/temp dependant variable
 
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.

maybee December 22, 2013 07:20

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

sur4j December 22, 2013 08:11

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.

maybee December 22, 2013 08:51

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.

sur4j December 22, 2013 14:27

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 December 22, 2013 15:50

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 :D):

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

For you link:
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.

sur4j December 23, 2013 15:01

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.

maybee December 23, 2013 15:59

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.

sur4j December 23, 2013 16:21

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?

maybee December 23, 2013 16:32

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)

sur4j December 23, 2013 18:03

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?

maybee December 24, 2013 09:21

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:

https://www.google.com.tr/search?q=c...glish&safe=off

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

greetings
maybee

sur4j December 24, 2013 11:24

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.

In my third post on this thread I had said:
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

maybee December 24, 2013 12:13

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 :D : 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 December 24, 2013 13:05

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<Type, PatchField, GeoMesh>::internalField [with Type = double, PatchField = Foam::fvPatchField, GeoMesh = Foam::volMesh, Foam::GeometricField<Type, PatchField, GeoMesh>::InternalField = Foam::Field<double>]())->Foam::Field<double>::<anonymous>.Foam::List<double>::<anonymous>.Foam::UList<T>::operator[] [with T = double, Foam::label = int](cellI) < Foam::operator+(const Foam::GeometricField<double, PatchField, GeoMesh>&, 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<class Type> bool Foam::operator<(const Foam::dimensioned<Type>&, const Foam::dimensioned<Type>&)
/opt/openfoam222/src/OpenFOAM/lnInclude/VectorSpaceI.H:677:13: note: template<class Form, class Cmpt, int nCmpt> bool Foam::operator<(const Foam::VectorSpace<Form, Cmpt, nCmpt>&, const Foam::VectorSpace<Form, Cmpt, nCmpt>&)
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?

maybee December 24, 2013 14:46

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 :).

sur4j December 24, 2013 15:01

Thanks for your help, I have a few more questions but will dedicate a new thread to them.


All times are GMT -4. The time now is 06:04.