ladybug-tools / butterfly

:butterfly: A light python API for creating and running OpenFoam cases for CFD simulation.
http://ladybug-tools.github.io/butterfly.html
GNU General Public License v3.0
249 stars 71 forks source link

Suggestions for useful OpenFOAM function objects #177

Open TheodoreGalanos opened 7 years ago

TheodoreGalanos commented 7 years ago

Hello,

There is a big number of function objects (FOs) avaialable. I will try to separate this in their respective categories. Not sure if I should open a new issue or just type here. I'll do it here for now and if needed I transfer everything in a new post.

First category is the fields category. These function objects capture, calculate, or access information about fields (e.g. U, p, k, e, etc.) on various parts of the mesh. The most important fields FOs from my experience so far, that is the ones I use the most, are:

Field MinMax function object

One of the simplest ones but probably my most used FO. I always enable this in my runs since I can very quickly and efficiently understand whethere my case is diverging and where exactly that happens. This FO reports the min and max values of the fields you provide and the location where these happen. The code is very simple (rsc here: https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/fieldMinMax/fieldMinMax.H):

fieldMinMax1
{
type fieldMinMax;
libs ("libfieldFunctionObjects.so");
writeToFile yes;
log yes;
location yes;
mode magnitude;
fields (U p);
}

This example captures U and p, but k and epsilon can and should be used. Inputs are the fiels to give values for.

I can imagine using this function object in Honeybee a lot since users can really understand if something is going wrong. It should be pretty straightforward to plot this as well as it is quite lite, only 2 values for each parameter per iteration. If possible, a real-time, multi-graph output plotting (mainly) max values would be nice.

Subtract

This one might be helpful for users that want to calculate a few things for their case. It does what it says subtracting a field off another field. Main inputs are the two fields, others should be default (see: https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/subtract/subtract.H).

Tdiff
{
type subtract;
libs ("libfieldFunctionObjects.so");
fields (T Tmean);
result Tdiff;
executeControl writeTime;
writeControl writeTime;
}

Average value

This FO calculates the average value of other fields calculated through function objects that give singular values. The code example below calculates the average force coefficients, which are calculated by another function object (see: https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/valueAverage/valueAverage.H):

valueAverage1
{
type valueAverage;
libs ("libfieldFunctionObjects.so");
writeToFile yes;
log yes;
functionObject forceCoeffs1;
fields (Cm Cd Cl);
window 0.5;
}

fluxSummary

This one is also very useful. It calculates the flux of u field across a selection of faces. The faces are selected through cellzones or even custom stl surfaces. Personally I use cellzones a lot for example when I want to monitor average velocities 1.1m above the floor or when I want to add porous zones in the mesh (i.e. trees). A very useful example implementation of this FO is to create a cellzone at the opening of your windows and then use the fluxSummary to get the (positive) flux of U passing through the cellzone or surface. The main inputs are the mode and the cellzone/surface to be used as the zone, and the direction depending on the mode.

I must admit I haven't used this yet, I was doing workarounds before this FO, but it looks promising. Output is the mass flow over surface A. I will test and let you know. Code snippet below (see:https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/fluxSummary/fluxSummary.H).

fluxSummary1
{
type fluxSummary;
libs ("libfieldFunctionObjects.so");
write yes;
log yes;
mode cellZoneAndDirection;
cellZoneAndDirection
(
(porosity (1 0 0))
);
scaleFactor 1.2;
}

wallShearStress

Some users have already been asking for this. Shear Stress is a measure of the force of friction from a fluid acting to a body (thing of air near the wall). It is given by the parallel forces on the wall. It is a simple FO with no real inputs (which calculates it for all walls in the model) or the specific wall boundary. Code snippet below (see: https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/wallShearStress/wallShearStress.H).

wallShearStress1
{
type wallShearStress;
libs ("libfieldFunctionObjects.so");
patches (".*Wall");
}

wallHeatFlux

Similar to above calculates the heat flux through a wall boundary. No inputs, unless user wants to specify specific wall boundary. Code snippet below (see: https://develop.openfoam.com/Development/OpenFOAM-plus/blob/master/src/functionObjects/field/wallHeatFlux/wallHeatFlux.H).

wallHeatFlux1
{
type wallHeatFlux;
libs ("libfieldFunctionObjects.so");
patches (".*Wall");
}

I think that's all for the field FOs. Of course with a component similar to the one you posted on #150 we can give users the possibility to literally input any FO they want or simply experiment.

Kind regards, Theodore.

MikkiSeidenschnur commented 7 years ago

Hi @TheodoreGalanos

There are specifically two of the FO's that I find particularly interesting - that is the "fluxSummary" and the "wallHeatFlux1". As a HVAC designer those are the two best indicators for the designer that OF is actually calculating the same as the input that you have given to the program. I've actually listed this as one of the things I was missing with Butterfly to check my results properly - like in the case of monitoring what happens with the HeatTransfer recipe that seems to diverge in #146 .

Best regards Mikki Seidenschnur

TheodoreGalanos commented 7 years ago

Hi @MikkiSeidenschnur

It shouldn't be difficult to add wallHeatFlux, it is simply that code really. fluxSummary is a bit more difficult since it requires the user to set a cellZone but it isn't impossible to set up. I will try to get it going when I'm back on my work computer on Friday.

As for the heat transfer recipe, I was running some tests on our case with standard settings. We did find some bugs that we corrected in the settings and the case seems to run correctly, without diverging, when meshed properly. Heat transfer cases require, and are more sensitive to, higher quality meshes than the simple non buoyancy ones. I will try to work on the one in #146 as soon as I get the time.

Regards, Theodore.

mostaphaRoudsari commented 7 years ago

I did an initial implementation that let you add function objects to the case. We can use the same class to create new component for specific functions later.

image

TheodoreGalanos commented 7 years ago

Hi @mostaphaRoudsari

I realized that for some, maybe even all, function objects it is much simpler than that. OF seems to have the code saved in files in the installation and we can just call it in the controlDict. For example, if we want the solver to save the min and max values of our fields we simply add:

#includeFunc minMaxMagnitude;

in the functions block of our controlDict.

Should I make a separate issue to list objects that can be added like this? I feel it's easy to implement it this way.

Kind regards, Theodore.

akosior commented 7 years ago

Hi @TheodoreGalanos,

I have a case in which I want to stop the computations when the mean pressure value in some section stop changing, similar like in the force coefficients example that you gave. So I created a surfaceFieldValue function object that is doing an areaAverage operation on the selected surface. It is working fine. Now I would like to create a valueAverage type object like in your example but I have a problem with the fields entry. None of the names that I put there worked.

So my question is - does the valueAverage work with results from surfaceFieldValue type function object? If so what should be the name of the field in the valueAverage dict.

Thanks in advance, Andrzej

TheodoreGalanos commented 7 years ago

Hi Andrzej,

Could you paste the function object code that is breaking and/or the openfoam error report from the terminal? OF has very good error reporting procedures and usually points you to the exact line failing in the code. We can easily debug it from there. I have to say though, not sure you can use an output of a function object to an input of another, never tried it that is.

That said, are you sure you need to valueAverage the results of surfaceFieldValue? You are already requesting an areaAverage result from it so you should be getting exactly what you want. Additionally, I feel that averaging the results is just a math problem and you probably don't need a function object to do that, GH with native math component or a spreadsheet software would be faster.

Kind regards, Theodore.

akosior commented 7 years ago

Hi Theodore,

thank you for a fast answer. I am trying to do something similar to the case1 of the termination control described here. In this example result of one function object is used as the input of a different function object. Just instead of the drag coefficient I want to use an average pressure in a section. I am calculating the area average with:

areaAverage1
{
    type             surfaceFieldValue; 
    functionObjectLibs ("libfieldFunctionObjects.so");

    writeControl   timeStep; 
    writeFields    false;
    writeArea      true;
    log            true;

    valueOutput     false;

    regionType          sampledSurface;

    sampledSurfaceDict
    {
            type sampledTriSurfaceMesh;
            surface ref_areaAverage1.stl;
            source cells;
            interpolate true;
    }

    operation       areaAverage;
    fields (p);
    name aa1;    
}

As I understand it the valueAverage is doing averaging in time (or in this case in SIMPLE algorithm iterations) while areaAverage is doing averaging in space. So in the next step I am using function:

valueAverage1 
{ 
    type                valueAverage; 
    functionObjectLibs  ( "libfieldFunctionObjects.so" ); 
    writeControl       timeStep; 

    functionObject  areaAverage1; 
    fields              (areaAverage(p)); 
    window              10; 
}

And here is my problem. I do not know what is the proper field name to be used in this function. Whatever I put in the fields entry I get the error message that this field was not evaluated:

valueAverage: valueAverage1 averages: --> FOAM Warning : From function virtual bool Foam::functionObjects::valueAverage::execute() in file valueAverage/valueAverage.C at line 183 From function object: areaAverage1 Unprocessed fields: areaAverage(p)

Thanks, Andrzej

as919461 commented 2 years ago

Hello, I have created a custom FO to generate a file with some output scalar parameters and I want the simulation to have a convergence criteria when one of the parameters, say average flow stops changing (maxDiff = 1e-3 for maxIter = 10). I get the flow velocity at each time step inside my output file from the custom FO which has to be read. The problem is I cannot use the runTimeControl FO inside my custom FO as it required fields as input and I want a scalar variable as input. Let me know what could be a good approach to approach this problem. Thank you in advance.