CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Running, Solving & CFD (http://www.cfd-online.com/Forums/openfoam-solving/)
-   -   swak4foam : transient convergence criteria (http://www.cfd-online.com/Forums/openfoam-solving/119808-swak4foam-transient-convergence-criteria.html)

Hiroshiman June 25, 2013 09:25

swak4foam : transient convergence criteria
 
Hi,
I'm working on a periodic simulation and I'd like to set up a temporal convergence criteria. It would be something like
if variable(t+T)=variable(t) then stop simulation

In the swak4foam library there are tools to stop a simulation if a criteria is reached, something like (in controlDict) :

Code:

    stopHighVel
    {
        type panicDump ;
        fieldName Q ;
        minimum -1;
        maximum 0.001;
        verbose true;
    }

My question is,how to access the data on a specified patch at a specified time ?

Regards,

Florian

gschaider June 25, 2013 13:42

Quote:

Originally Posted by Hiroshiman (Post 435870)
Hi,
I'm working on a periodic simulation and I'd like to set up a temporal convergence criteria. It would be something like
if variable(t+T)=variable(t) then stop simulation

In the swak4foam library there are tools to stop a simulation if a criteria is reached, something like (in controlDict) :

Code:

    stopHighVel
    {
        type panicDump ;
        fieldName Q ;
        minimum -1;
        maximum 0.001;
        verbose true;
    }

My question is,how to access the data on a specified patch at a specified time ?

Regards,

Florian

Abusing that functionObject would be hardcore. But have a look at writeAndEndSwakExpression in the simpleSwakFunctionObjects-library. That might be EXACTLY what you're looking for (stops the run if a logical expression evaluates to "true" - either everywhere ("and") or somewhere ("or"))

Hiroshiman June 25, 2013 14:28

Thank you for writeAndEndSwakExpression, I didn't know this one. I'm still wondering how to access data at a specified time. oldTime only works for one timeStep in the past...
Any idea ?

Regards,

Florian

gschaider June 25, 2013 15:00

Quote:

Originally Posted by Hiroshiman (Post 435926)
Thank you for writeAndEndSwakExpression, I didn't know this one. I'm still wondering how to access data at a specified time. oldTime only works for one timeStep in the past...
Any idea ?

Regards,

Florian

Yep. Delayed variable

Hiroshiman June 28, 2013 11:14

Thank you very much, a mix of delayedVariables and writeAndEndSwakExpression works perfectly !
Regards,
Florian.

gschaider June 28, 2013 13:16

Quote:

Originally Posted by Hiroshiman (Post 436587)
Thank you very much, a mix of delayedVariables and writeAndEndSwakExpression works perfectly !

Thank YOU. Without you I wouldn't have thought that delayed variables can be used for convergence-checking

akidess June 29, 2013 07:14

Quote:

Originally Posted by Hiroshiman (Post 436587)
Thank you very much, a mix of delayedVariables and writeAndEndSwakExpression works perfectly !
Regards,
Florian.

Can you post the code? Might be useful for people in the future.

gschaider June 29, 2013 08:13

Quote:

Originally Posted by akidess (Post 436722)
Can you post the code? Might be useful for people in the future.

Even better: Adding it under http://openfoamwiki.net/index.php/Co...Usage_examples would make sure that people don't have to search threads for it

Hiroshiman July 2, 2013 10:41

Quote:

Originally Posted by gschaider (Post 436739)
Even better: Adding it under http://openfoamwiki.net/index.php/Co...Usage_examples would make sure that people don't have to search threads for it

I guess I can compete for the ugliest way of doing things but it does work (so far).
Test case : one intlet with a sinusoidal pressure, 2 free outlets.

Code:

    stopIfCrit {
            type writeAndEndSwakExpression;
            valueType internalField;
            logicalExpression "(maxU1 < threshold) && (maxU2 < threshold) && (tt >= 1.5) && (test > 0.5) ";
            /* In this case 2 outlets are considered and tested. The (very basic) criteria used is the maximum velocity at the outlet patches. The flow is periodic and supposed physically converged if the criteria values are the same at t and t+T.
            The two first tests are the velocities comparison.
            The third one is a delay because of the unphysical behaviour that can appear at the beginning of the simulation.
            The fourth is used to keep the simulation running for one period after the convergence is reached.*/
            logicalAccumulation and;
            variables (
                "UA1fter{patch'outlet1}=max(mag(U));" //delayed criteria on outlet1
                "Ub41{patch'outlet1}=max(mag(U));" // criteria on outlet1
                "UA2fter{patch'outlet2}=max(mag(U));"
                "Ub42{patch'outlet2}=max(mag(U));"
                "maxU1=100*mag(UA1fter-Ub41)/mag(UA1fter);"
                "maxU2=100*mag(UA2fter-Ub42)/mag(UA2fter);"
                "threshold=5;" // 5% of difference accepted
                "tt=time();"
                "test=((maxU1 < threshold) && (maxU2 < threshold) && (tt >= 1.5))?  1  : 0;" // test done with a delay of T.
            );
            delayedVariables (
                {
                    name UA1fter;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "100";
                }
                {
                    name UA2fter;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "100";
                }
                {
                    name test;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "0";
                }             
                );
            verbose true;
            outputControlMode timestep;
            outputInterval 1;
                }

What it looks like :
http://uppix.net/VXLVj8l.png
With : blue = p(inlet), pink = 5% threshold, red and green : convergence criteria on both outlets.

I was wondering : how can I add the period as a parameter ?


Florian

gschaider July 2, 2013 15:20

Quote:

Originally Posted by Hiroshiman (Post 437341)
I guess I can compete for the ugliest way of doing things but it does work (so far).
Test case : one intlet with a sinusoidal pressure, 2 free outlets.

Code:

    stopIfCrit {
            type writeAndEndSwakExpression;
            valueType internalField;
            logicalExpression "(maxU1 < threshold) && (maxU2 < threshold) && (tt >= 1.5) && (test > 0.5) ";
            /* In this case 2 outlets are considered and tested. The (very basic) criteria used is the maximum velocity at the outlet patches. The flow is periodic and supposed physically converged if the criteria values are the same at t and t+T.
            The two first tests are the velocities comparison.
            The third one is a delay because of the unphysical behaviour that can appear at the beginning of the simulation.
            The fourth is used to keep the simulation running for one period after the convergence is reached.*/
            logicalAccumulation and;
            variables (
                "UA1fter{patch'outlet1}=max(mag(U));" //delayed criteria on outlet1
                "Ub41{patch'outlet1}=max(mag(U));" // criteria on outlet1
                "UA2fter{patch'outlet2}=max(mag(U));"
                "Ub42{patch'outlet2}=max(mag(U));"
                "maxU1=100*mag(UA1fter-Ub41)/mag(UA1fter);"
                "maxU2=100*mag(UA2fter-Ub42)/mag(UA2fter);"
                "threshold=5;" // 5% of difference accepted
                "tt=time();"
                "test=((maxU1 < threshold) && (maxU2 < threshold) && (tt >= 1.5))?  1  : 0;" // test done with a delay of T.
            );
            delayedVariables (
                {
                    name UA1fter;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "100";
                }
                {
                    name UA2fter;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "100";
                }
                {
                    name test;
                    delay 0.7;
                    storeInterval 0.001;
                    startupValue "0";
                }             
                );
            verbose true;
            outputControlMode timestep;
            outputInterval 1;
                }


Nice. Just one problem: you're testing for the maximum. So if on outlet1 the same maximum is on a different location it still might be judged as "converged". One possibility would be to use as valueType patch on outlet1 and instead of max(mag(U)) use mag(U). instead wrap the max around the expression maxU1. That way you'd get convergence if the values on the outlet are really the same. But this only works for one patch at once (to treat the outlet2 similarly AT THE SAME TIME) is a little bit more tricky

Quote:

Originally Posted by Hiroshiman (Post 437341)
What it looks like :
http://uppix.net/VXLVj8l.png
With : blue = p(inlet), pink = 5% threshold, red and green : convergence criteria on both outlets.

I was wondering : how can I add the period as a parameter ?

With "period" you mean the delay of the delayedVariables? This value can currently only be a fixed value. But if you want to set the values consistently then you can set a dictionary entry
Code:

defaultDelay 0.7;
and make all delays use that
Code:

delay $defaultDelay;

Hiroshiman July 4, 2013 11:21

Quote:

Originally Posted by gschaider (Post 437399)
Nice. Just one problem: you're testing for the maximum. So if on outlet1 the same maximum is on a different location it still might be judged as "converged". One possibility would be to use as valueType patch on outlet1 and instead of max(mag(U)) use mag(U). instead wrap the max around the expression maxU1. That way you'd get convergence if the values on the outlet are really the same. But this only works for one patch at once (to treat the outlet2 similarly AT THE SAME TIME) is a little bit more tricky

Hi ! I'm aware of this this limitation and wand to create 2 functions like this, for each outlets :
Code:

    convcrit1
    {
        type swakExpression;
        valueType patch;
        patchName outlet1;
        variables (
            //"dummy=p-mag(U);"
            "UA1fter{patch'outlet1}=mag(U);"
            "Ub41{patch'outlet1}=mag(U);"
        );
        delayedVariables (
        {
            name UA1fter;
            delay 0.7;
            storeInterval 0.001;
            startupValue "100";
        });
        accumulations (
            max
        );
        expression "100*mag(UA1fter-Ub41)/mag(UA1fter)";
        verbose true;
        autoInterpolate true;
        warnAutoInterpolate false;
        outputControlMode timestep;
        outputInterval 1;
}

and then get the results to be evaluated in the function writeAndEndSwakExpression but I still have problems to exchange data from a function to another.

Quote:

Originally Posted by gschaider (Post 437399)
With "period" you mean the delay of the delayedVariables? This value can currently only be a fixed value. But if you want to set the values consistently then you can set a dictionary entry
Code:

defaultDelay 0.7;
and make all delays use that
Code:

delay $defaultDelay;

Thank you !

Florian

gschaider July 8, 2013 14:59

Quote:

Originally Posted by Hiroshiman (Post 437826)
Hi ! I'm aware of this this limitation and wand to create 2 functions like this, for each outlets :
Code:

    convcrit1
    {
        type swakExpression;
        valueType patch;
        patchName outlet1;
        variables (
            //"dummy=p-mag(U);"
            "UA1fter{patch'outlet1}=mag(U);"
            "Ub41{patch'outlet1}=mag(U);"
        );
        delayedVariables (
        {
            name UA1fter;
            delay 0.7;
            storeInterval 0.001;
            startupValue "100";
        });
        accumulations (
            max
        );
        expression "100*mag(UA1fter-Ub41)/mag(UA1fter)";
        verbose true;
        autoInterpolate true;
        warnAutoInterpolate false;
        outputControlMode timestep;
        outputInterval 1;
}

and then get the results to be evaluated in the function writeAndEndSwakExpression but I still have problems to exchange data from a function to another.

If you're on outlet1 you don't have to write UA1fter{patch'outlet1}. UA1fter is sufficient.

Many April 8, 2015 12:34

Hi everyone,

I am not understanding well the use of this wonderful tool.

I would like to stop my (steady) simulation when Residuals are below a given threshold (let's say 1e-4) and outlet velocity remains unchanged with iterations, so, I have included this in my controDict file:
velocity_outlet
{
type patchExpression;
accumulations (
average
);
patches (
out
);
expression "mag(U)";
verbose true;
outputControl timeStep;
outputInterval 1;
}

This computes averaged outlet velocity as I desired.

But now I am not sure how to compare old and present values. I would like to:

if
|uaveraged(iteration n)-uaveraged(iteration n-1)|<0.1
and
Residuals<1e-4
then
STOP

Based on the code I have seen here, I have tried something like this( forget about the Residuals in this first try)


stopIfCrit {
type writeAndEndSwakExpression;
valueType internalField;
logicalExpression "(tol < threshold)";

logicalAccumulation and;
variables (
"UA1fter=velocity_outlet;" //delayed criteria on outlet1
"Ub41=velocity_outlet;"

"tol=mag(UA1fter-Ub41);"

"threshold=0.5;"

"test=((tol < threshold) )? 1 : 0;"
);
delayedVariables (
{
name UA1fter;
delay 1;
storeInterval 1;
startupValue "1";
}

{
name test;
delay 1;
storeInterval 1;
startupValue "0";
}
);
verbose true;
outputControlMode timestep;
outputInterval 1;
}

But nothing happens. It seems that I am not telling OpenFOAM when it has to stop .This definition I have tried looks so weird:

"UA1fter=velocity_outlet;" //delayed criteria on outlet1
"Ub41=velocity_outlet;"

Does anybody know how I have to proceed to compare a computed value in the previous iteration with this value in the current iteration?


Thanks in advance!:)

Hiroshiman April 8, 2015 13:03

Quote:

Originally Posted by Many (Post 540601)
Hi everyone,

I am not understanding well the use of this wonderful tool.

I would like to stop my (steady) simulation when Residuals are below a given threshold (let's say 1e-4) and outlet velocity remains unchanged with iterations, so, I have included this in my controDict file:
velocity_outlet
{
type patchExpression;
accumulations (
average
);
patches (
out
);
expression "mag(U)";
verbose true;
outputControl timeStep;
outputInterval 1;
}

This computes averaged outlet velocity as I desired.

But now I am not sure how to compare old and present values. I would like to:

if
|uaveraged(iteration n)-uaveraged(iteration n-1)|<0.1
and
Residuals<1e-4
then
STOP

Based on the code I have seen here, I have tried something like this( forget about the Residuals in this first try)


stopIfCrit {
type writeAndEndSwakExpression;
valueType internalField;
logicalExpression "(tol < threshold)";

logicalAccumulation and;
variables (
"UA1fter=velocity_outlet;" //delayed criteria on outlet1
"Ub41=velocity_outlet;"

"tol=mag(UA1fter-Ub41);"

"threshold=0.5;"

"test=((tol < threshold) )? 1 : 0;"
);
delayedVariables (
{
name UA1fter;
delay 1;
storeInterval 1;
startupValue "1";
}

{
name test;
delay 1;
storeInterval 1;
startupValue "0";
}
);
verbose true;
outputControlMode timestep;
outputInterval 1;
}

But nothing happens. It seems that I am not telling OpenFOAM when it has to stop .This definition I have tried looks so weird:

"UA1fter=velocity_outlet;" //delayed criteria on outlet1
"Ub41=velocity_outlet;"

Does anybody know how I have to proceed to compare a computed value in the previous iteration with this value in the current iteration?


Thanks in advance!:)


Hi,
you can look at the variables values that are stored during the simulation to check if they are what you expect (in the swak4Foam folder at each timeStep).
You can use the [CODE ] [/CODE ] bracket to make the code readable.

Many April 8, 2015 13:45

Hi Hiroshiman,

The values of:

velocity_outlet
{
type patchExpression;
accumulations (
average
);
patches (
out
);
expression "mag(U)";
verbose true;
outputControl timeStep;
outputInterval 1;
}

are written in postProcessing folder (no swak4foam folder in my case)

The problem is I don't know how to use this values to stop my simulation when differences between consecutive iterations is small.

Some more help will be much aprecciated.


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