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

[swak4Foam] delayed response - on the limit of groovyBC's capabilities?

Register Blogs Community New Posts Updated Threads Search

Like Tree2Likes
  • 1 Post By sylvester
  • 1 Post By sylvester

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   July 9, 2012, 05:00
Default delayed response - on the limit of groovyBC's capabilities?
  #1
Member
 
Roland
Join Date: Mar 2009
Location: Netherlands
Posts: 92
Rep Power: 17
sylvester is on a distinguished road
Is it possible to have a patch react to the value of another patch, but only after a certain delay?

For example see the geometry depicted in de picture attached.
From the bottom of a mixing tank, fluid with a certain amount of contamination is (continuously) taken. This fluid is then processed, such that the contamination level changes. After about 30 seconds the fluid is be fed back into the tank.

My first thought was to use groovyBC, as it was helpful so many times in the past. But after having a good look on the wiki and this forum I haven't been able to find a clue on how to do this. So maybe I have to build a custom boundary condition after all.

Any suggestion will be much appreciated!

Best regards,
Sylvester
Attached Images
File Type: png vat.png (12.0 KB, 16 views)
sylvester is offline   Reply With Quote

Old   July 9, 2012, 12:53
Default
  #2
Assistant Moderator
 
Bernhard Gschaider
Join Date: Mar 2009
Posts: 4,225
Rep Power: 51
gschaider will become famous soon enoughgschaider will become famous soon enough
Quote:
Originally Posted by sylvester View Post
Is it possible to have a patch react to the value of another patch, but only after a certain delay?

For example see the geometry depicted in de picture attached.
From the bottom of a mixing tank, fluid with a certain amount of contamination is (continuously) taken. This fluid is then processed, such that the contamination level changes. After about 30 seconds the fluid is be fed back into the tank.

My first thought was to use groovyBC, as it was helpful so many times in the past. But after having a good look on the wiki and this forum I haven't been able to find a clue on how to do this. So maybe I have to build a custom boundary condition after all.

Any suggestion will be much appreciated!

Best regards,
Sylvester
How does the outgoing fluid determine the properties of the incoming fluid? A simple switching condition can be implemented with storedVariables (provided the state doesn't change afterwards). If you're going for something like C_in(t)=C_out(t-30): that is currently not possible. I have been thinking about delayedVariables (and they shouldn't be too hard to implement with the usual restriction "only uniform") but no concrete plans yet (A feature-request/bug-report would show that there is some demand for that and COULD speed things up)

Another possibility would be to use the pythonIntegration-functionObject and implement the delaying yourself (one possibility would be to use rrdtool to do the storage. It is specialized for that kind of thing)

I don't think that the coded-functionObject that comes with OF gives you the possibility to store date between calls to the FO and therefor won't work with this. But I could be wrong
gschaider is offline   Reply With Quote

Old   July 10, 2012, 03:18
Default
  #3
Member
 
Roland
Join Date: Mar 2009
Location: Netherlands
Posts: 92
Rep Power: 17
sylvester is on a distinguished road
Hi Bernhard,

Thanks for your help.

Quote:
Originally Posted by gschaider View Post
How does the outgoing fluid determine the properties of the incoming fluid? A simple switching condition can be implemented with storedVariables (provided the state doesn't change afterwards). If you're going for something like C_in(t)=C_out(t-30): that is currently not possible. I have been thinking about delayedVariables (and they shouldn't be too hard to implement with the usual restriction "only uniform") but no concrete plans yet (A feature-request/bug-report would show that there is some demand for that and COULD speed things up)
Yes, it would be something like C_in(t)=f(C_out(t-30)). I'll place a request for the storedVariables feature.

Quote:
Originally Posted by gschaider View Post
Another possibility would be to use the pythonIntegration-functionObject and implement the delaying yourself (one possibility would be to use rrdtool to do the storage. It is specialized for that kind of thing)
I have never used the pythonIntegration-functionObject, but I'll look into it. Combining it with rrdtool may well be beyond my capabilities though. Nevertheless I'll give it a try.

Quote:
Originally Posted by gschaider View Post
I don't think that the coded-functionObject that comes with OF gives you the possibility to store date between calls to the FO and therefor won't work with this. But I could be wrong
To me the coded BC never appeared more powerful, or as easy to use as groovyBC. So I did not considered before. I'll have look at it though.

If I get something working, I'll report back here.

Regards,
Sylvester
sylvester is offline   Reply With Quote

Old   July 10, 2012, 03:35
Default
  #4
Assistant Moderator
 
Bernhard Gschaider
Join Date: Mar 2009
Posts: 4,225
Rep Power: 51
gschaider will become famous soon enoughgschaider will become famous soon enough
Quote:
Originally Posted by sylvester View Post
Hi Bernhard,

Thanks for your help.



Yes, it would be something like C_in(t)=f(C_out(t-30)). I'll place a request for the storedVariables feature.



I have never used the pythonIntegration-functionObject, but I'll look into it. Combining it with rrdtool may well be beyond my capabilities though. Nevertheless I'll give it a try.
I've had a quick look at the API of rrdtool: I'm afraid it is not a good choice. It doesn't keep the database in memory but on disc and access is .... weird. I thought mostly that the RoundRobin-capability would make it a good candidate

Quote:
Originally Posted by sylvester View Post
To me the coded BC never appeared more powerful, or as easy to use as groovyBC. So I did not considered before. I'll have look at it though.
As I said: I'm afraid it won't help you for your problem as it "forgets" everything between calls.

BTW: swak has a subclass (swakCoded) of it that allows to read and write swak-Variables in global namespaces. But this isn't sufficient for our purposes too I'm afraid

Quote:
Originally Posted by sylvester View Post
If I get something working, I'll report back here.
OK
gschaider is offline   Reply With Quote

Old   July 11, 2012, 05:55
Default
  #5
Member
 
Roland
Join Date: Mar 2009
Location: Netherlands
Posts: 92
Rep Power: 17
sylvester is on a distinguished road
Hi Bernhard,

I've got it working now.

The input concentration is calculated in a swakCoded/swakFunctionObjects. Using globalScopes this concentration is available to a standard groovyBC for the inlet patch.

The time history of the concentration is stored within the swakCoded/swakFunctionObjects using a global (fixed length) scalar. The availability of a labelList for this part would have resulted in prettier code, but this is also working.

The examples I used for this construct were 'cylinderWithSwak' for the 'swakCoded/swakFunctionObjects' part and the file 'Examples/tests/pythonIntegration/0/rand' for the 'globalScopes/groovyBC' part.

Thanks again for your help!

regards,
Sylvester
Ohbuchi likes this.
sylvester is offline   Reply With Quote

Old   July 11, 2012, 08:29
Default
  #6
Assistant Moderator
 
Bernhard Gschaider
Join Date: Mar 2009
Posts: 4,225
Rep Power: 51
gschaider will become famous soon enoughgschaider will become famous soon enough
Quote:
Originally Posted by sylvester View Post
Hi Bernhard,

I've got it working now.
Great. Congratulations. Its always nice when people abuse swak for stuff that I didn't think is possible.

Quote:
Originally Posted by sylvester View Post
The input concentration is calculated in a swakCoded/swakFunctionObjects. Using globalScopes this concentration is available to a standard groovyBC for the inlet patch.

The time history of the concentration is stored within the swakCoded/swakFunctionObjects using a global (fixed length) scalar. The availability of a labelList for this part would have resulted in prettier code, but this is also working.
Just some questions:
- you mean "fixedLength scalarList", right?
- why was labelList not possible? Not "known"? Are you aware of codeInclude (see http://www.openfoam.org/docs/user/ba...8-1050004.2.11) or does this not work with the swak-FO?
- how did you get the persistence between calls? Is it possible to add member variables to the FO or did you use a static variable in the function?
- does your solution assume a fixed time-step?

Quote:
Originally Posted by sylvester View Post
The examples I used for this construct were 'cylinderWithSwak' for the 'swakCoded/swakFunctionObjects' part and the file 'Examples/tests/pythonIntegration/0/rand' for the 'globalScopes/groovyBC' part.
Anyhow. I'll go ahead with the delayed thing once I have time.

Would you like to contribute your example?

Bernhard
gschaider is offline   Reply With Quote

Old   July 11, 2012, 09:07
Default
  #7
Member
 
Roland
Join Date: Mar 2009
Location: Netherlands
Posts: 92
Rep Power: 17
sylvester is on a distinguished road
Quote:
Originally Posted by gschaider View Post
- you mean "fixedLength scalarList", right?
Never heard of them. For my (ugly) solution see the timeList and concentrationList definition in the code below.

Quote:
Originally Posted by gschaider View Post
- why was labelList not possible? Not "known"? Are you aware of codeInclude (see http://www.openfoam.org/docs/user/ba...8-1050004.2.11) or does this not work with the swak-FO?
TimeList and concentrationList only accepted type scalar (or vector), see code below.
I was not aware of codeInclude.

Quote:
Originally Posted by gschaider View Post
- how did you get the persistence between calls? Is it possible to add member variables to the FO or did you use a static variable in the function?
"persistance between calls": I don't even know what that means.

Quote:
Originally Posted by gschaider View Post
- does your solution assume a fixed time-step?
As you'll see in the code, this part is not finished yet. I'm already storing the (average) concentration every time data is written to disk. And I have verified I can access this data at a later iteration. Next I will add a mechanism that will use linear interpolation between stored concentration value, plus some additional processing function.


Quote:
Originally Posted by gschaider View Post
Anyhow. I'll go ahead with the delayed thing once I have time.
For me the urgency level has dropped quite a few levels now. Let me know if you need somebody to test it, though.

Regards,
Sylvester

from controlDict:
Code:
libs (
    "libswakFunctionObjects.so"
    "libsimpleSwakFunctionObjects.so"
    "libgroovyStandardBCs.so"
);

functions
{
    addTimeList {
        type addGlobalVariable;
        globalName timeList;
        globalScope concentrationResults;
        valueType scalar;
        value 999999{0};
        isSingleValue false;
    }
    addTimeListLength {
        type addGlobalVariable;
        globalName timeListLength;
        globalScope concentrationResults;
        valueType scalar;
        value 0;
        isSingleValue true;
    }
    addConcentrationList {
        type addGlobalVariable;
        globalName concentrationList;
        globalScope concentrationResults;
        valueType scalar;
        value 999999{0};
        isSingleValue false;
    }
    addInConcentration {
        type addGlobalVariable;
        globalName inConcentration;
        globalScope concentrationResults;
        valueType scalar;
        value 0;
        isSingleValue true;
    }

    concentrationFunction
    {
        // Load the library containing the 'coded' functionObject
        functionObjectLibs ("libswakFunctionObjects.so");
        type swakCoded;
        codedToSwakNamespace concentrationResults;
        codedToSwakVariables
        (
            timeList
            timeListLength
            concentrationList
            inConcentration
        );
        swakToCodedNamespaces (concentrationResults);
        code
        #{
            const volScalarField& T = mesh().lookupObject<volScalarField>("T");

            label outPatch = mesh().boundaryMesh().findPatchID("outlet");
            label inPatch = mesh().boundaryMesh().findPatchID("inlet");

            scalar delay=30.;

            dimensionedScalar Concentration
            (
                "Concentration",
                dimensionSet(0, 0, 0, 1, 0),
                gSum
                (
                    T.boundaryField()[outPatch] * mesh().magSf().boundaryField()[outPatch]
                )
                /
                gSum
                (
                    mesh().magSf().boundaryField()[outPatch]
                )
            );

            if (mesh().time().outputTime())
            {
                timeList[++timeListLength] = mesh().time().value();
                concentrationList[timeListLength] = Concentration.value();
                scalar procesTime = timeList[timeListLength] - delay;

                if (procesTime < timeList[0])
                {
//                     Info << "No data yet" << endl;
                    inConcentration = 1.0;
                }
                else
                {
//                     Info << "Woohoo data!" << endl;
                    inConcentration = 1.0 + max(concentrationList[timeListLength],0);
                }
            }
        #};
    }
}
from 0/T:
Code:
    inlet
    {
        type            groovyBC;
        value           uniform 1;
        globalScopes ( concentrationResults );
        valueExpression "inConcentration";
    }
tomf likes this.
sylvester is offline   Reply With Quote

Old   July 11, 2012, 13:43
Default
  #8
Assistant Moderator
 
Bernhard Gschaider
Join Date: Mar 2009
Posts: 4,225
Rep Power: 51
gschaider will become famous soon enoughgschaider will become famous soon enough
Quote:
Originally Posted by sylvester View Post
from controlDict:
Code:
libs (
    "libswakFunctionObjects.so"
    "libsimpleSwakFunctionObjects.so"
    "libgroovyStandardBCs.so"
);

functions
{
    addTimeList {
        type addGlobalVariable;
        globalName timeList;
        globalScope concentrationResults;
        valueType scalar;
        value 999999{0};
        isSingleValue false;
    }
    addTimeListLength {
        type addGlobalVariable;
        globalName timeListLength;
        globalScope concentrationResults;
        valueType scalar;
        value 0;
        isSingleValue true;
    }
    addConcentrationList {
        type addGlobalVariable;
        globalName concentrationList;
        globalScope concentrationResults;
        valueType scalar;
        value 999999{0};
        isSingleValue false;
    }
    addInConcentration {
        type addGlobalVariable;
        globalName inConcentration;
        globalScope concentrationResults;
        valueType scalar;
        value 0;
        isSingleValue true;
    }

    concentrationFunction
    {
        // Load the library containing the 'coded' functionObject
        functionObjectLibs ("libswakFunctionObjects.so");
        type swakCoded;
        codedToSwakNamespace concentrationResults;
        codedToSwakVariables
        (
            timeList
            timeListLength
            concentrationList
            inConcentration
        );
        swakToCodedNamespaces (concentrationResults);
        code
        #{
            const volScalarField& T = mesh().lookupObject<volScalarField>("T");

            label outPatch = mesh().boundaryMesh().findPatchID("outlet");
            label inPatch = mesh().boundaryMesh().findPatchID("inlet");

            scalar delay=30.;

            dimensionedScalar Concentration
            (
                "Concentration",
                dimensionSet(0, 0, 0, 1, 0),
                gSum
                (
                    T.boundaryField()[outPatch] * mesh().magSf().boundaryField()[outPatch]
                )
                /
                gSum
                (
                    mesh().magSf().boundaryField()[outPatch]
                )
            );

            if (mesh().time().outputTime())
            {
                timeList[++timeListLength] = mesh().time().value();
                concentrationList[timeListLength] = Concentration.value();
                scalar procesTime = timeList[timeListLength] - delay;

                if (procesTime < timeList[0])
                {
//                     Info << "No data yet" << endl;
                    inConcentration = 1.0;
                }
                else
                {
//                     Info << "Woohoo data!" << endl;
                    inConcentration = 1.0 + max(concentrationList[timeListLength],0);
                }
            }
        #};
    }
}
from 0/T:
Code:
    inlet
    {
        type            groovyBC;
        value           uniform 1;
        globalScopes ( concentrationResults );
        valueExpression "inConcentration";
    }
Now THAT is a wickedly cool solution. Didn't think of using a global variable for storing the data. Honestly: wasn't even aware that I allowed non-uniform specification. But as I think of it: of course. That is needed for restarting

Quote:
Originally Posted by sylvester View Post
Never heard of them. For my (ugly) solution see the timeList and concentrationList definition in the code below.


TimeList and concentrationList only accepted type scalar (or vector), see code below.
I was not aware of codeInclude.
That was all under the assumption that you stored the data in the functionObject. So codeInclude won't help you here.

label as a list type is not supported by swak because there is no such thing as a volLabelField

Quote:
Originally Posted by sylvester View Post
"persistance between calls": I don't even know what that means.
That means that the functionObject stores data between two consecutive function calls

Quote:
Originally Posted by sylvester View Post
As you'll see in the code, this part is not finished yet. I'm already storing the (average) concentration every time data is written to disk. And I have verified I can access this data at a later iteration. Next I will add a mechanism that will use linear interpolation between stored concentration value, plus some additional processing function.
OK. One possibility for "finer" granularity would be to define yourself a deltaT and a value "lastWritten" and new data is only added when time>lastWritten+deltaT. But I'm confident you'll find a way yourself

Quote:
Originally Posted by sylvester View Post
For me the urgency level has dropped quite a few levels now. Let me know if you need somebody to test it, though.
Don't be offended but your urgency is of little relevance to me if you're not a client
gschaider is offline   Reply With Quote

Reply

Tags
boundary condition, delayed response, groovybc, mixing tank


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



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