CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Community Contributions (https://www.cfd-online.com/Forums/openfoam-community-contributions/)
-   -   [swak4Foam] groovyBC and probe measurement (https://www.cfd-online.com/Forums/openfoam-community-contributions/137607-groovybc-probe-measurement.html)

odellar June 19, 2014 07:54

groovyBC and probe measurement
 
Hi,

I'm trying to use groovyBC to implement closed-loop control in a simulation. I have a probe (in the controlDict) set to record a pressure measurement at a particular position in the geometry, and wish to use this value in conjunction with groovyBC to perform some maths operation on the value of pressure at the probe at each timestep, and use this value to update the value of a particular boundary condition for the next timestep.

So far my thinking takes me thus far:
Code:

actuatorBoundary   
{   
type                    groovyBC;   
valueExpression        "0.5*(probeReading)"; // Some function of the probe recording    variables                "probeReading *** NOT SURE HOW TO DO THIS? ***   
value                    uniform (0 0 0);   
}

Can anyone help me with the code to implement this? I can't find an example which does this sort of thing exactly.

Thanks a lot,
Olie

gschaider June 19, 2014 08:15

Quote:

Originally Posted by odellar (Post 497774)
Hi,

I'm trying to use groovyBC to implement closed-loop control in a simulation. I have a probe (in the controlDict) set to record a pressure measurement at a particular position in the geometry, and wish to use this value in conjunction with groovyBC to perform some maths operation on the value of pressure at the probe at each timestep, and use this value to update the value of a particular boundary condition for the next timestep.

So far my thinking takes me thus far:
Code:

actuatorBoundary   
{   
type                    groovyBC;   
valueExpression        "0.5*(probeReading)"; // Some function of the probe recording    variables                "probeReading *** NOT SURE HOW TO DO THIS? ***   
value                    uniform (0 0 0);   
}

Can anyone help me with the code to implement this? I can't find an example which does this sort of thing exactly.

Thanks a lot,
Olie

What confuses people here mostly is that you don't use a probe but a sampled-set. swak can't access probes for technical reasons (basically: probes don't want to be accessed). But a sampled set of type cloud is equivalent. Examples that do that in the swak-Examples are groovcBC/fillingTheDam and FromPresentations/cleaningTank. Also in the swak-presentation at PennState (see the swak-page) a similar thing is explained

odellar June 20, 2014 06:49

Quote:

Originally Posted by gschaider (Post 497779)
What confuses people here mostly is that you don't use a probe but a sampled-set. swak can't access probes for technical reasons (basically: probes don't want to be accessed). But a sampled set of type cloud is equivalent. Examples that do that in the swak-Examples are groovcBC/fillingTheDam and FromPresentations/cleaningTank. Also in the swak-presentation at PennState (see the swak-page) a similar thing is explained

Oh okay - didn't realise that. I've not used a cloud type sampled set before - does this just go in the controlDict as the probe would? (Do you know where I can find some documentation on cloud's use?).

Okay so after some more reading and re-reading I think, after I've got a cloud sample correct, the groovyBC boundary in the 0/U file should look something like this:

Code:

actuator
{
  type                    groovyBC;
  variables              "pMeasurement@cloudSampler=p;"
  valueExpression  "10*p";            // Or *SOME* mathematical expression
  value                  uniform (1 0 0); // Or *SOME* initial conditions
}

Is this the right idea? (Note here I've assumed the same usage with a cloud sampled set as that when using a patch.

Thanks again,
Olie

****EDIT****
Oh no - found some documentation on using cloud and it appears you can only use this in sampleDict - so now I'm confused.. How do I use this during runtime so it samples (like a probe) at each time step such that groovyBC can then use the value?

gschaider June 20, 2014 11:50

Quote:

Originally Posted by odellar (Post 497936)
Oh okay - didn't realise that. I've not used a cloud type sampled set before - does this just go in the controlDict as the probe would? (Do you know where I can find some documentation on cloud's use?).

Okay so after some more reading and re-reading I think, after I've got a cloud sample correct, the groovyBC boundary in the 0/U file should look something like this:

Code:

actuator
{
  type                    groovyBC;
  variables              "pMeasurement@cloudSampler=p;"
  valueExpression  "10*p";            // Or *SOME* mathematical expression
  value                  uniform (1 0 0); // Or *SOME* initial conditions
}

Is this the right idea? (Note here I've assumed the same usage with a cloud sampled set as that when using a patch.

Thanks again,
Olie

****EDIT****
Oh no - found some documentation on using cloud and it appears you can only use this in sampleDict - so now I'm confused.. How do I use this during runtime so it samples (like a probe) at each time step such that groovyBC can then use the value?

Have a look at the cleaningTank-example. It uses a cloud-set to control the run (control is probably a BIT more complicated than what you intend to do)

odellar June 23, 2014 10:35

Quote:

Originally Posted by gschaider (Post 498013)
Have a look at the cleaningTank-example. It uses a cloud-set to control the run (control is probably a BIT more complicated than what you intend to do)

Okay thank you. I've tried to base my approach on this, and so far now have the addition of the following in my controlDict:

Code:

functions
{
    readpField {
        type readAndUpdateFields;
        fields ( p );
    }

    createMeasurement
    {
    type createSampledSet;
    outputControl outputTime;
    outputInterval 1;
    setName sensor1;
    set {
        type cloud;
        axis x;
        points (
            (0 -0.5 0.5)
        );
    }
}
}

in an attempt to 'sample' the value of p at the coordinates (0 -0.5 0.5) at each written timestep, and the following in a funkySetFieldsDict located in system:
Code:

expressions (
    buildP
    {
        field p;
        create true;
    }
);

When I run the solver however, it fails and says --> FOAM FATAL ERROR:
Field p does not exist


From function Foam::readAndUpdateFields::read(const dictionary& dict)
in file misc/readAndUpdateFields/readAndUpdateFields.C at line 128.

FOAM exiting

What am I doing wrong?
Thanks again, Olie

odellar June 27, 2014 14:22

:( ? Anyone?

odellar July 1, 2014 12:26

Working (I think) but strange results.
 
I believe I've got it working now - I put this in the functions section of the controlDict:

Code:

createMeasurement
        {
        type createSampledSet;
        outputControl outputTime;
        outputInterval 1;
        setName sensor1;
        set {
                type cloud;
                axis xyz;
                points (
                        (0 -0.5 0.5)
                );
        } }

and made this the entry in the 0/U directory for the boundary I want to be controlled based on the measurement from sensor1:

Code:

actuator
    {
        type groovyBC;
        value        uniform (0 0 0);
        variables (
                "pressureMeasurement{set'sensor1}=p;"
                );
        valueExpression "0.01*vector(0,pressureMeasurement,0)";
    }

So sensor1 is meant to measure the pressure at (0,-0.5,0.5), then multiply this value by 0.01 to give the velocity - this velocity value is to be used as a uniform velocity boundary condition for actuator.

I think it's *close* to working, but not quite. The attached image (hope the attaching works) shows the sampled pressure from sensor1, p_wall, the velocity on the actuator boundary v_act, and the ratio of p_wall to v_wall, which *should* be 100, given groovyBC is set to give v_act=0.01*p_wall, but it's more like 200.

Am I doing something wrong? Thanks!

http://oi57.tinypic.com/2nbve3a.jpg

gschaider July 2, 2014 17:45

Quote:

Originally Posted by odellar (Post 499531)
I believe I've got it working now - I put this in the functions section of the controlDict:

Code:

createMeasurement
        {
        type createSampledSet;
        outputControl outputTime;
        outputInterval 1;
        setName sensor1;
        set {
                type cloud;
                axis xyz;
                points (
                        (0 -0.5 0.5)
                );
        } }

and made this the entry in the 0/U directory for the boundary I want to be controlled based on the measurement from sensor1:

Code:

actuator
    {
        type groovyBC;
        value        uniform (0 0 0);
        variables (
                "pressureMeasurement{set'sensor1}=p;"
                );
        valueExpression "0.01*vector(0,pressureMeasurement,0)";
    }

So sensor1 is meant to measure the pressure at (0,-0.5,0.5), then multiply this value by 0.01 to give the velocity - this velocity value is to be used as a uniform velocity boundary condition for actuator.

I think it's *close* to working, but not quite. The attached image (hope the attaching works) shows the sampled pressure from sensor1, p_wall, the velocity on the actuator boundary v_act, and the ratio of p_wall to v_wall, which *should* be 100, given groovyBC is set to give v_act=0.01*p_wall, but it's more like 200.

Am I doing something wrong? Thanks!

http://oi57.tinypic.com/2nbve3a.jpg

That looks strange. Should work. How do you measure the velocity on the boundary?

BTW: just to be sure make it "pressureMeasurement{set'sensor1}=average( p );" (I think otherwise it might break in parallel)

odellar July 3, 2014 04:48

Quote:

Originally Posted by gschaider (Post 499725)
That looks strange. Should work. How do you measure the velocity on the boundary?

BTW: just to be sure make it "pressureMeasurement{set'sensor1}=average( p );" (I think otherwise it might break in parallel)

I sample velocity afterwards using the following in the sampleDict under sets:
Code:

actuator_velocity
    {
    type        uniform;
    axis        z;

    start      (-0.015 0 0);
        end        (-0.015 0 1);
        nPoints    3;
    }

I know these seems a daft way to sample a point but I've never worked out how else to do it! So given my case is a 2D geometry, so is length 1 in the z-direction (but with just one mesh cell in that direction), I sample a line in the z-direction with 3 points located at z=0, z=0.5 and z=1 and look at the middle one - any help on the proper way of sampling at a point would be greatly appreciated!

Oh thank you I'll put in average().

Also, can you use matrices in groovyBC expressions? Similar to how you can use vectors somehow? If so how do you do this?

Thanks a lot.

odellar July 3, 2014 08:16

Also...
 
Also, I'm using some storedVariables for a boundary condition, which update themselves each timestep, something like storedVariable1 = 0.5*storedVariable1 (there's more to it, but that's the general idea). However my thinking is that it updates the value of the variable every computational timestep which is a variable time step - I only want it to update at every write interval - so how do I specify that it's only to update at, for example, every 0.5 seconds? NOT ever actual computational time step?

Thanks a lot again, Olie

gschaider July 3, 2014 15:22

Quote:

Originally Posted by odellar (Post 499807)
I sample velocity afterwards using the following in the sampleDict under sets:
Code:

actuator_velocity
    {
    type        uniform;
    axis        z;

    start      (-0.015 0 0);
        end        (-0.015 0 1);
        nPoints    3;
    }

I know these seems a daft way to sample a point but I've never worked out how else to do it! So given my case is a 2D geometry, so is length 1 in the z-direction (but with just one mesh cell in that direction), I sample a line in the z-direction with 3 points located at z=0, z=0.5 and z=1 and look at the middle one - any help on the proper way of sampling at a point would be greatly appreciated!

Oh thank you I'll put in average().

Also, can you use matrices in groovyBC expressions? Similar to how you can use vectors somehow? If so how do you do this?

Thanks a lot.

Sampling the point with a cloud like you did above is the way to do it. Without the average only the processor that has the point would have a value. That's why it is needed

matrixes are called tensors (3x3). swak supports all the operations on them OF supports (see the programmers-guide)

gschaider July 3, 2014 15:30

Quote:

Originally Posted by odellar (Post 499846)
Also, I'm using some storedVariables for a boundary condition, which update themselves each timestep, something like storedVariable1 = 0.5*storedVariable1 (there's more to it, but that's the general idea). However my thinking is that it updates the value of the variable every computational timestep which is a variable time step - I only want it to update at every write interval - so how do I specify that it's only to update at, for example, every 0.5 seconds? NOT ever actual computational time step?

Thanks a lot again, Olie

I don't think that mixing the physical (your BC) with the discretization (output-times) is a good idea. Solution would depend on how often you write something out.

You want your storedVariable1 to "decay" exponentially, right? A bit of fiddling around with deltaT() and exp() will give you a decay with the same rate (it is year 1 mathematics. So don't ask me for formulas. I don't want to embarrass myself)

odellar July 4, 2014 06:32

Quote:

Originally Posted by gschaider (Post 499945)
I don't think that mixing the physical (your BC) with the discretization (output-times) is a good idea. Solution would depend on how often you write something out.

You want your storedVariable1 to "decay" exponentially, right? A bit of fiddling around with deltaT() and exp() will give you a decay with the same rate (it is year 1 mathematics. So don't ask me for formulas. I don't want to embarrass myself)

Thanks I'll look into tensors.

No that was just an example of the manner in which I'm wanting to use storedVariables - what I'm trying to do with them is actually more complicated, using them as state values for a discrete time state-space controller. But this shouldn't matter - the point is I need it to only update storedVariables at certain times: the times when data is written.

Correct the solution will depend on how often it's written - this is CORRECT in my particular situation (don't ask why, unless you're really interested!). So is this possible?

Thank you for all your help so far! I dare say I'm at the final hurdle!

gschaider July 5, 2014 06:52

Quote:

Originally Posted by odellar (Post 500073)
Thanks I'll look into tensors.

No that was just an example of the manner in which I'm wanting to use storedVariables - what I'm trying to do with them is actually more complicated, using them as state values for a discrete time state-space controller. But this shouldn't matter - the point is I need it to only update storedVariables at certain times: the times when data is written.

Correct the solution will depend on how often it's written - this is CORRECT in my particular situation (don't ask why, unless you're really interested!). So is this possible?

Thank you for all your help so far! I dare say I'm at the final hurdle!

An example for discrete states would be in Examples/FromPresentations the cleaning-tank examples

General swak-Expressions have no function "outputTime()" that is true for times when OF does output (for the reasons above). What DOES have such a variable is the Python-integration

odellar July 7, 2014 04:51

Quote:

Originally Posted by gschaider (Post 500191)
An example for discrete states would be in Examples/FromPresentations the cleaning-tank examples

General swak-Expressions have no function "outputTime()" that is true for times when OF does output (for the reasons above). What DOES have such a variable is the Python-integration

Okay thank you - where abouts is the code relating to these situated? Is it anything to do with the commonVariables file?

Thanks, Olie

gschaider July 9, 2014 14:05

Quote:

Originally Posted by odellar (Post 500371)
Okay thank you - where abouts is the code relating to these situated? Is it anything to do with the commonVariables file?

Thanks, Olie

No. That is for common expressions between BCs (mostly for "smoothing" what goes out on one side to be used as input on the other side). Variables for the state are declared in system/controlDict in the defineState functionObject.

odellar July 14, 2014 07:46

Quote:

Originally Posted by gschaider (Post 500815)
No. That is for common expressions between BCs (mostly for "smoothing" what goes out on one side to be used as input on the other side). Variables for the state are declared in system/controlDict in the defineState functionObject.

Thank you, this certainly helps, but I'm still not sure - just by reading the code in the example - how to actually use it.

My guess is to put something like this in controlDict:
Code:

defineState {
type addGlobalVariable;
outputControl runtime;
outputInterval 0.5; // to output every 0.5 seconds?
globalScope stateInformation;
globalVariables {
state1 {
valueType scalar;
value 0; // What does this mean?
}
state2 {
valueType scalar;
value 0; // What does this mean?
}
}
}

then I don't know where to go from there?

If it helps, the attached image shows what I'm trying to implement - note that state values x do not refer to some physical state (such as pressure, velocity etc), they're just values that are updated at each write interval according to x_k+1 = Ax_k + Bs_k, and in the image when I refer to 'timestep' I also mean write interval, i.e. some fixed interval (in my case 0.5 seconds).

Thanks

http://i.imgur.com/G6zEvin.png

gschaider July 22, 2014 16:43

Quote:

Originally Posted by odellar (Post 501411)
Thank you, this certainly helps, but I'm still not sure - just by reading the code in the example - how to actually use it.

My guess is to put something like this in controlDict:
Code:

defineState {
type addGlobalVariable;
outputControl runtime;
outputInterval 0.5; // to output every 0.5 seconds?
globalScope stateInformation;
globalVariables {
state1 {
valueType scalar;
value 0; // What does this mean?
}
state2 {
valueType scalar;
value 0; // What does this mean?
}
}
}

then I don't know where to go from there?

If it helps, the attached image shows what I'm trying to implement - note that state values x do not refer to some physical state (such as pressure, velocity etc), they're just values that are updated at each write interval according to x_k+1 = Ax_k + Bs_k, and in the image when I refer to 'timestep' I also mean write interval, i.e. some fixed interval (in my case 0.5 seconds).

Thanks

http://i.imgur.com/G6zEvin.png

That is a huge picture.

Anyway: For the meaning of value etc see http://openfoamwiki.net/images/c/c0/...rogrammers.pdf starting at page 30. A few pages later calculateGlobalVariables is explained (which would be how you get the sensor values). The groovyBC then will only have to get the global variables (that is also explained there)


All times are GMT -4. The time now is 08:21.