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/)
-   -   Access to Ubar_ in fvOption (Urgent Help) (https://www.cfd-online.com/Forums/openfoam-programming-development/231479-access-ubar_-fvoption-urgent-help.html)

mostanad November 7, 2020 03:48

Access to protected Ubar_ in fvOption (Urgent Help)
 
Hi all,
I have a question about fvOption. I am using meanVelocityForce as the type of momentum source in my fvOption file. However, by looking the source file of this momentum type at OpenFOAM-5.x/src/fvOptions/sources/derived/meanVelocityForce, something seems hard to me.

https://github.com/OpenFOAM/OpenFOAM...ityForce.C#L89
We have a Ubar_ vector as a protected value which is read from fvOption file. Due to its protected type, it cannot be used at the outside of its class. So can anybody help me to just print its value (Info) at each timestep of my solver.
I think a solution is defining a public function at the class to print its value, and use this function at each time step in our solver coding (fvOptions.functionforUbar). But it has lots of c++ details.

ztnuaa November 7, 2020 04:08

Dear mostanad,

As you said, the Ubar_ defined at class "meanVelocityForce" is read from "fvOptions" file. And it's just a user-defined fixed vector value which is not changed during the calculation.

So if you want to use it in your solver, i think an easy way is to
(1) define the same "Ubar" in your solver's dict file and read it in your code
or
(2) read 'fvOptions' in your solver's code to get the user-defined "Ubar" value.

Timo

mostanad November 7, 2020 04:23

Quote:

Originally Posted by ztnuaa (Post 787034)
Dear mostanad,

As you said, the Ubar_ defined at class "meanVelocityForce" is read from "fvOptions" file. And it's just a user-defined fixed vector value which is not changed during the calculation.

So if you want to use it in your solver, i think an easy way is to
(1) define the same "Ubar" in your solver's dict file and read it in your code
or
(2) read 'fvOptions' in your solver's code to get the user-defined "Ubar" value.

Timo


Thank you Dear Timo for your quick reply. The problem cannot be solved by these two methods. Yes, the Ubar_ is a user defined vector and by #include "createFvOptions.H" in my solver, the solver reads just once the fvOption file and gives the Ubar value to this vector. So it cannot be changed in different timestep.

However, if I can define a function in meanVelocityForce.C (like constrain or correct functions), I report this value in every timestep or as my final goal, I can change its value(because I want to change Ubar_ based on some results in each timestep). So do you have any solution for that?

Thanks, Mohammad

mostanad November 7, 2020 04:36

Quote:

Originally Posted by mostanad (Post 787037)
Thank you Dear Timo for your quick reply. The problem cannot be solved by these two methods. Yes, the Ubar_ is a user defined vector and by #include "createFvOptions.H" in my solver, the solver reads just once the fvOption file and gives the Ubar value to this vector. So it cannot be changed in different timestep.

However, if I can define a function in meanVelocityForce.C (like constrain or correct functions), I report this value in every timestep or as my final goal, I can change its value(because I want to change Ubar_ based on some results in each timestep). So do you have any solution for that?

Thanks, Mohammad


I have found something similar to my problem, but with no details!!! So still help me!

https://www.cfd-online.com/Forums/op...-variable.html

ztnuaa November 7, 2020 04:45

Dear Mohammad,

Okay, I get your point.
I think it's possible to change the Ubar_ value on the fly. The idea is to pass a parameter to meanVelocityForce::correct(volVectorField& U) or meanVelocityForce::constrain. Say, (1)change the following function:
Code:

void Foam::fv::meanVelocityForce::correct(volVectorField& U)
{
...
}

to
Code:

void Foam::fv::meanVelocityForce::correct(volVectorField& U, vector& Ubar_New)
{
...
Ubar_ = Ubar_New;
...
}

Or you can change *constrain* function, say change this :
Code:


void Foam::fv::meanVelocityForce::constrain
(
    fvMatrix<vector>& eqn,
    const label
)
{
...
}

To:
Code:


void Foam::fv::meanVelocityForce::constrain
(
    fvMatrix<vector>& eqn,
    const label,
    vector& Ubar_new
)
{
...
Uba_ = Ubar_New;
}

Ubar_New is computed by your solver and pass it to fvOptions meanVelocityForce and modify the protected *Ubar_* inside it. This is allowed in the code.

This *correct* and *constrain* function is called in the UEqn.H. You can check pimpleFoam solver for more information and choose one by your own situation.

Timo

mostanad November 7, 2020 05:25

Quote:

Originally Posted by ztnuaa (Post 787042)
Dear Mohammad,

Okay, I get your point.
I think it's possible to change the Ubar_ value on the fly. The idea is to pass a parameter to meanVelocityForce::correct(volVectorField& U) or meanVelocityForce::constrain. Say, (1)change the following function:
Code:

void Foam::fv::meanVelocityForce::correct(volVectorField& U)
{
...
}

to
Code:

void Foam::fv::meanVelocityForce::correct(volVectorField& U, vector& Ubar_New)
{
...
Ubar_ = Ubar_New;
...
}

Or you can change *constrain* function, say change this :
Code:


void Foam::fv::meanVelocityForce::constrain
(
    fvMatrix<vector>& eqn,
    const label
)
{
...
}

To:
Code:


void Foam::fv::meanVelocityForce::constrain
(
    fvMatrix<vector>& eqn,
    const label,
    vector& Ubar_new
)
{
...
Uba_ = Ubar_New;
}

Ubar_New is computed by your solver and pass it to fvOptions meanVelocityForce and modify the protected *Ubar_* inside it. This is allowed in the code.

This *correct* and *constrain* function is called in the UEqn.H. You can check pimpleFoam solver for more information and choose one by your own situation.

Timo

What an amazing suggestion Timo. However working with constrain or correct functions is a bit hard because of having multiple classes working with these functions for different source terms types in fvOption. I should work on that to reach a result. BTW, how do you think about defining a separate function than constrain or correct.

ztnuaa November 7, 2020 05:37

Dear Mohammad,
Yes, this solution will introduce some inconvenience. It's much better to define a separate function to just set your desired Ubar value. I'll have a look at it when I finish my dinner.
By the way, both solution need to define virtual functions in the *fvOptions* so that you can access it in your solver.
Timo

ztnuaa November 7, 2020 06:55

Quote:

Originally Posted by ztnuaa (Post 787049)
Dear Mohammad,
Yes, this solution will introduce some inconvenience. It's much better to define a separate function to just set your desired Ubar value. I'll have a look at it when I finish my dinner.
By the way, both solution need to define virtual functions in the *fvOptions* so that you can access it in your solver.
Timo

Okay, after some debug, I think we now have achieved your goals. Here is an example, (My code is under OpenFOAM-2.3.1 and I think you can figure it out under OpenFOAM-5.x)
1. create virtual functions in fvOption.[CH]:
fvOptions/fvOptions/fvOption.H
Code:

virtual void setUbar(vector& UbarTarget);
fvOptions/fvOptions/fvOption.C
Code:

void Foam::fv::option::setUbar(vector& UbarTarget)
{
    // do nothing
}

2. create virtual funciton in fvOptions/fvOptions/fvOpitonList.[CH]:
fvOptions/fvOptions/fvOpitonList.H
Code:

       
void setUbar(vector& UbarTarget);

fvOptions/fvOptions/fvOpitonList.C
Code:

void Foam::fv::optionList::setUbar(vector& UbarTarget)
{
    forAll(*this, i)
    {
        this->operator[](i).setUbar(UbarTarget);
    }
}

3. create function in meanVelocityForce:
meanVelocityForce.H
Code:

            //- Set target ubar
            virtual void setUbar(vector& UbarTarget);

meanVelocityForce.C
Code:

void Foam::fv::meanVelocityForce::setUbar
(
    vector& UbarTarget
)
{
    //Info<< "UbarTarget:"<<UbarTarget<<"    "<<Ubar_<<endl;
    // Set Ubar by UbarTarget
    Ubar_ = UbarTarget;
}

4. Acess this function in your solver by fvOptions.setUar(UbarTarget). e.g.:
Code:

vector UbarTarget(5.0,0.0,0.0);
fvOptions.setUbar(UbarTarget);

Make sure you write Ubar_ to some file and read Ubar_ from that file when you restart your simulation (like it handles gradP). Therefore, it won't use the Ubar defined at fvOptions when your restart your simulation.

Timo

mostanad November 7, 2020 06:59

Quote:

Originally Posted by ztnuaa (Post 787049)
Dear Mohammad,
Yes, this solution will introduce some inconvenience. It's much better to define a separate function to just set your desired Ubar value. I'll have a look at it when I finish my dinner.
By the way, both solution need to define virtual functions in the *fvOptions* so that you can access it in your solver.
Timo

Thank you Timo, I think the best possible solution for me is to separate this function from others because of having another complicated function in this class with name addSup. Changing Ubar in every iteration should be started from this function not constrain or correct. So I wanna give some hints about separating function. I made some progress on that. Please follow these points and if you find any unclear point, just inform me. First of all, I have inserted a function in my solver which is:
Code:

fvOptions.Uvalue();
It is just like fvOptions.constrain(UEqn), and is inserted before the U equation loop. By defining this function, lets go to the source codes. We should now go to meanVelocityForce.H and put this on that:
Code:

virtual void Uvalue();
and in meanVelocityForce.C
Code:

void Foam::fv::meanVelocityForce::Uvalue()//insert by Mo
{
    Info << " Ubar " << Ubar_ << endl;//insert by Mo
}

Then, this class has inherited from fvOptions.C (options class), fvOptionList.C (optionList class), and fvOption.C (option class). They are so complicated but I put some commands based on constrain and correct function on that. Again on fvoption.H and fvOption.C I put
Code:

virtual void Uvalue();
and

Code:

void Foam::fv::option::Uvalue(){}
Then this functions should be referenced in options class as well. So in fvOptionList.H,I put
Code:

void Uvalue()//insert by Mo
            {
                forAll(*this, i)
                {
                    option& source = this->operator[](i);
                    source.Uvalue();
                  }
 }

Its completely such the thing that has been done for constrain and correct functions in fvOptionListTemplates.C, which source the Uvalue function defined in fvOption.C file. I found this solution after trying so many different ways, but the sourcing in fvOptionList.H is still a bit weird for me. This codes are compiling without any error, but after running my test case, none of addSup, constrain, correct, and Uvalue functions don't work. It seems that the fvOption is not working with my modification. So what is wrong with that? I think you can solve the puzzle.
Thank you,
Mohammad

mostanad November 7, 2020 07:02

Quote:

Originally Posted by ztnuaa (Post 787054)
Okay, after some debug, I think we now have achieved your goals. Here is an example, (My code is under OpenFOAM-2.3.1 and I think you can figure it out under OpenFOAM-5.x)
1. create virtual functions in fvOption.[CH]:
fvOptions/fvOptions/fvOption.H
Code:

virtual void setUbar(vector& UbarTarget);
fvOptions/fvOptions/fvOption.C
Code:

void Foam::fv::option::setUbar(vector& UbarTarget)
{
    // do nothing
}

2. create virtual funciton in fvOptions/fvOptions/fvOpitonList.[CH]:
fvOptions/fvOptions/fvOpitonList.H
Code:

       
void setUbar(vector& UbarTarget);

fvOptions/fvOptions/fvOpitonList.C
Code:

void Foam::fv::optionList::setUbar(vector& UbarTarget)
{
    forAll(*this, i)
    {
        this->operator[](i).setUbar(UbarTarget);
    }
}

3. create function in meanVelocityForce:
meanVelocityForce.H
Code:

            //- Set target ubar
            virtual void setUbar(vector& UbarTarget);

meanVelocityForce.C
Code:

void Foam::fv::meanVelocityForce::setUbar
(
    vector& UbarTarget
)
{
    //Info<< "UbarTarget:"<<UbarTarget<<"    "<<Ubar_<<endl;
    // Set Ubar by UbarTarget
    Ubar_ = UbarTarget;
}

4. Acess this function in your solver by fvOptions.setUar(UbarTarget). e.g.:
Code:

vector UbarTarget(5.0,0.0,0.0);
fvOptions.setUbar(UbarTarget);

Make sure you write Ubar_ to some file and read Ubar_ from that file when you restart your simulation (like it handles gradP). Therefore, it won't use the Ubar defined at fvOptions when your restart your simulation.

Timo

Woooooooooow. Timo, I did almost the same thing. You are awesome man. Awesome. Your post surprised me since it was so close to my efforts. Now I wanna go for that. I will tell you the result ASAP.

ztnuaa November 7, 2020 07:10

Haha, yes, we did the same thing at the same time.

I think you should pass a parameter in your Uvalue() function and modify Ubar_ in it, such that the Ubar_ will be changed every time you call fvOptions.Uvalue.

Here is my test result using the code in my last post:
Code:

Time = 0.200001

smoothSolver:  Solving for Ux, Initial residual = 0.00115195, Final residual = 2.02236e-07, No Iterations 2
smoothSolver:  Solving for Uy, Initial residual = 0.00936929, Final residual = 1.63209e-06, No Iterations 2
smoothSolver:  Solving for Uz, Initial residual = 0.00943482, Final residual = 1.54585e-06, No Iterations 2
Pressure gradient source: uncorrected Ubar = 36, pressure gradient = 2284.67
UbarTarget:(5 0 0)    (36 0 0)
GAMG:  Solving for p, Initial residual = 0.0710281, Final residual = 0.0024497, No Iterations 2
time step continuity errors : sum local = 4.06092e-08, global = -3.4513e-18, cumulative = -3.4513e-18
Pressure gradient source: uncorrected Ubar = 36, pressure gradient = -5.98508e+07
GAMG:  Solving for p, Initial residual = 0.448843, Final residual = 8.42978e-07, No Iterations 28
time step continuity errors : sum local = 1.94414e-11, global = 6.0499e-18, cumulative = 2.5986e-18
Pressure gradient source: uncorrected Ubar = 35.6024, pressure gradient = -5.90832e+07
ExecutionTime = 0.78 s  ClockTime = 1 s

fieldAverage fieldAverage1:
    Reading/initialising field UMean
    Reading/initialising field UPrime2Mean

fieldAverage fieldAverage1 output:
    Calculating averages

Courant Number mean: 0.0414973 max: 0.0803248
Time = 0.200002

smoothSolver:  Solving for Ux, Initial residual = 0.919327, Final residual = 7.03513e-06, No Iterations 5
smoothSolver:  Solving for Uy, Initial residual = 0.0113043, Final residual = 7.20097e-06, No Iterations 3
smoothSolver:  Solving for Uz, Initial residual = 0.0112912, Final residual = 6.50256e-06, No Iterations 3
Pressure gradient source: uncorrected Ubar = -53.3497, pressure gradient = 5.40978e+07
UbarTarget:(5 0 0)    (5 0 0)
GAMG:  Solving for p, Initial residual = 0.97442, Final residual = 0.051851, No Iterations 3
time step continuity errors : sum local = 2.22175e-05, global = -9.29353e-16, cumulative = -9.26754e-16
Pressure gradient source: uncorrected Ubar = -52.7138, pressure gradient = 5.28642e+07
GAMG:  Solving for p, Initial residual = 0.0645526, Final residual = 9.08584e-07, No Iterations 16
time step continuity errors : sum local = 7.7011e-10, global = 4.40136e-15, cumulative = 3.47461e-15
Pressure gradient source: uncorrected Ubar = -52.6635, pressure gradient = 5.27667e+07
ExecutionTime = 1.24 s  ClockTime = 2 s

First step, Ubar_ = 36 is read from fvOptions:
UbarTarget:(5 0 0) (36 0 0)

Second step, Ubar is changed to 5 which is modified by setUbar(UbarTarget):
UbarTarget:(5 0 0) (5 0 0)


Timo

mostanad November 7, 2020 07:56

Quote:

Originally Posted by ztnuaa (Post 787057)
Haha, yes, we did the same thing at the same time.

I think you should pass a parameter in your Uvalue() function and modify Ubar_ in it, such that the Ubar_ will be changed every time you call fvOptions.Uvalue.

Here is my test result using the code in my last post:
Code:

Time = 0.200001

smoothSolver:  Solving for Ux, Initial residual = 0.00115195, Final residual = 2.02236e-07, No Iterations 2
smoothSolver:  Solving for Uy, Initial residual = 0.00936929, Final residual = 1.63209e-06, No Iterations 2
smoothSolver:  Solving for Uz, Initial residual = 0.00943482, Final residual = 1.54585e-06, No Iterations 2
Pressure gradient source: uncorrected Ubar = 36, pressure gradient = 2284.67
UbarTarget:(5 0 0)    (36 0 0)
GAMG:  Solving for p, Initial residual = 0.0710281, Final residual = 0.0024497, No Iterations 2
time step continuity errors : sum local = 4.06092e-08, global = -3.4513e-18, cumulative = -3.4513e-18
Pressure gradient source: uncorrected Ubar = 36, pressure gradient = -5.98508e+07
GAMG:  Solving for p, Initial residual = 0.448843, Final residual = 8.42978e-07, No Iterations 28
time step continuity errors : sum local = 1.94414e-11, global = 6.0499e-18, cumulative = 2.5986e-18
Pressure gradient source: uncorrected Ubar = 35.6024, pressure gradient = -5.90832e+07
ExecutionTime = 0.78 s  ClockTime = 1 s

fieldAverage fieldAverage1:
    Reading/initialising field UMean
    Reading/initialising field UPrime2Mean

fieldAverage fieldAverage1 output:
    Calculating averages

Courant Number mean: 0.0414973 max: 0.0803248
Time = 0.200002

smoothSolver:  Solving for Ux, Initial residual = 0.919327, Final residual = 7.03513e-06, No Iterations 5
smoothSolver:  Solving for Uy, Initial residual = 0.0113043, Final residual = 7.20097e-06, No Iterations 3
smoothSolver:  Solving for Uz, Initial residual = 0.0112912, Final residual = 6.50256e-06, No Iterations 3
Pressure gradient source: uncorrected Ubar = -53.3497, pressure gradient = 5.40978e+07
UbarTarget:(5 0 0)    (5 0 0)
GAMG:  Solving for p, Initial residual = 0.97442, Final residual = 0.051851, No Iterations 3
time step continuity errors : sum local = 2.22175e-05, global = -9.29353e-16, cumulative = -9.26754e-16
Pressure gradient source: uncorrected Ubar = -52.7138, pressure gradient = 5.28642e+07
GAMG:  Solving for p, Initial residual = 0.0645526, Final residual = 9.08584e-07, No Iterations 16
time step continuity errors : sum local = 7.7011e-10, global = 4.40136e-15, cumulative = 3.47461e-15
Pressure gradient source: uncorrected Ubar = -52.6635, pressure gradient = 5.27667e+07
ExecutionTime = 1.24 s  ClockTime = 2 s

First step, Ubar_ = 36 is read from fvOptions:
UbarTarget:(5 0 0) (36 0 0)

Second step, Ubar is changed to 5 which is modified by setUbar(UbarTarget):
UbarTarget:(5 0 0) (5 0 0)


Timo


Dear Time,
I followed all the steps you posted, but it is getting the following error in solver compilation:
Code:

periodiccfdemSolverIB.C:(.text.startup+0x28a4): undefined reference to `Foam::fv::optionList::setUbar(Foam::Vector<double>&)'
collect2: error: ld returned 1 exit status


ztnuaa November 7, 2020 08:34

1 Attachment(s)
Quote:

Originally Posted by mostanad (Post 787063)
Dear Time,
I followed all the steps you posted, but it is getting the following error in solver compilation:
Code:

periodiccfdemSolverIB.C:(.text.startup+0x28a4): undefined reference to `Foam::fv::optionList::setUbar(Foam::Vector<double>&)'
collect2: error: ld returned 1 exit status



Well, this is weird. I don't have OpenFOAM-5.x compiled on my computer, so I can't reproduce this error. I tested it under OpenFOAM-2.3./2.3x and it's okay.

So I recommend you to check the code again because i don't know what's the difference between 2.3.x and 5.x. See the attachment of my case for more info.

Timo

mostanad November 7, 2020 08:41

I think this is because of this part:
Code:

this->operator[](i).setUbar(UbarTarget);
and this one:
Code:

option& source = this->operator[](i);;
source.setUbar(UbarTarget);

Also, the modification in fvOptionList.H, the function should be declared as virtual or not?
Thank you again.

ztnuaa November 7, 2020 08:52

Quote:

Originally Posted by mostanad (Post 787067)
I think this is because of this part:
Code:

this->operator[](i).setUbar(UbarTarget);
and this one:
Code:

option& source = this->operator[](i);;
source.setUbar(UbarTarget);

Also, the modification in fvOptionList.H, the function should be declared as virtual or not?
Thank you again.

I think both methods are okay. You can give it a try to declare the setUbar function with virtual void. In my case just void is okay. I'm not sure where the bug is from.

Timo

mostanad November 7, 2020 10:44

Quote:

Originally Posted by ztnuaa (Post 787069)
I think both methods are okay. You can give it a try to declare the setUbar function with virtual void. In my case just void is okay. I'm not sure where the bug is from.

Timo

Sorry Timo for my multiple requests. Can you send me your solver codes as well? I wanna see the header files in your solver.
Thanks
Mohammad

ztnuaa November 7, 2020 10:53

I'm not in my office so I can't sent you the code right now.
But it's very simple. My test solver is just the original pimpleFoam solver of OpenFOAM-2.3.1.I only add that two lines in the end of UEqn.H file.

Timo

mostanad November 7, 2020 22:53

Quote:

Originally Posted by mostanad (Post 787063)
Dear Time,
I followed all the steps you posted, but it is getting the following error in solver compilation:
Code:

periodiccfdemSolverIB.C:(.text.startup+0x28a4): undefined reference to `Foam::fv::optionList::setUbar(Foam::Vector<double>&)'
collect2: error: ld returned 1 exit status


Does anybody have any suggestion for this error in OF 5.x? What has been changed from version 2.3 to 5.x?

mostanad November 9, 2020 02:59

Finally, the modification suggested by Timo worked for me. I just recompiled all the src library again.


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