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/)
-   -   Create registered object at runtime using a functionObject (https://www.cfd-online.com/Forums/openfoam-programming-development/99207-create-registered-object-runtime-using-functionobject.html)

CedricVH March 28, 2012 10:40

Create registered object at runtime using a functionObject
 
A functionObject can only perform calculations on fields that are calculated by the solver. If I want to calculate the fieldMinMax of the total pressure (ptot) at runtime, the createFields.H file of the solver has to be changed so that ptot is a known volScalarField.

However, it would be nice to generate this value without modifying the solver to preserve compatibility when upgrading OpenFOAM.

I can calculate ptot for an incompressible solver using this functionObject:

Code:

    compute_ptot
    {
        functionObjectLibs ( "libutilityFunctionObjects.so" );
        type coded;
        enabled true;
        redirectType ptot;
        outputControl  timeStep;
        outputInterval  1;
        code
        #{
            const volScalarField& p = mesh().lookupObject<volScalarField>("p");
            const volVectorField& U = mesh().lookupObject<volVectorField>("U");
            volScalarField ptot
            (
                IOobject
                (
                    "ptot",
                    mesh().time().timeName(),
                    p.mesh(),
                    IOobject::NO_READ,
                    IOobject::AUTO_WRITE
                ),
                p
            );
            ptot = p + 0.5*magSqr(U);
        #};
    }

However, if I then add this functionObject under the previous one:

Code:

    fieldMinMax
    {
        type fieldMinMax;
        functionObjectLibs ("libfieldFunctionObjects.so");
        log            true;
        valueOutput    false;
        outputControl  timeStep;
        outputInterval 1;
        mode magnitude;
        fields
        (
            ptot
        );
    }

Then it does not work as this functionObject does not know anything about ptot.

I can make a workaround by adding ptot.write() to the first functionObject and than reading it back in using readFields. However, this generates extra files and directories and is not a clean solution.

Is there a possibility to keep the calculated ptot in memory (as it does with p and U) in order to be able to use functionObjects on this value?

gschaider March 28, 2012 17:32

Quote:

Originally Posted by CedricVH (Post 351950)
A functionObject can only perform calculations on fields that are calculated by the solver. If I want to calculate the fieldMinMax of the total pressure (ptot) at runtime, the createFields.H file of the solver has to be changed so that ptot is a known volScalarField.

However, it would be nice to generate this value without modifying the solver to preserve compatibility when upgrading OpenFOAM.

I can calculate ptot for an incompressible solver using this functionObject:

Code:

    compute_ptot
    {
        functionObjectLibs ( "libutilityFunctionObjects.so" );
        type coded;
        enabled true;
        redirectType ptot;
        outputControl  timeStep;
        outputInterval  1;
        code
        #{
            const volScalarField& p = mesh().lookupObject<volScalarField>("p");
            const volVectorField& U = mesh().lookupObject<volVectorField>("U");
            volScalarField ptot
            (
                IOobject
                (
                    "ptot",
                    mesh().time().timeName(),
                    p.mesh(),
                    IOobject::NO_READ,
                    IOobject::AUTO_WRITE
                ),
                p
            );
            ptot = p + 0.5*magSqr(U);
        #};
    }

However, if I then add this functionObject under the previous one:

Code:

    fieldMinMax
    {
        type fieldMinMax;
        functionObjectLibs ("libfieldFunctionObjects.so");
        log            true;
        valueOutput    false;
        outputControl  timeStep;
        outputInterval 1;
        mode magnitude;
        fields
        (
            ptot
        );
    }

Then it does not work as this functionObject does not know anything about ptot.

I can make a workaround by adding ptot.write() to the first functionObject and than reading it back in using readFields. However, this generates extra files and directories and is not a clean solution.

Is there a possibility to keep the calculated ptot in memory (as it does with p and U) in order to be able to use functionObjects on this value?

The reason is that your field is created and destroyed every time your code snipplet is called. There is the possibility to check for existence of the field, if it is not there create it and pass ownership to the registry (this only happens once), then get a reference to the field itself, const_cast it ... then you can modify it .... and afterwards it is still in memory.

But what I usually do in that situation is write something like
Code:

          compute_ptot
            {
                type expressionField;
                outputControl timeStep;
                outputInterval 1;
                fieldName ptot;
                expression "p + 0.5*magSqr(U)";
                autowrite false;       
            }

and get the same effect. But of course that only works because every machine I touch gets infected by swak4Foam.
The coded-functionObject can be very useful and enables you to go to places that swak can't go, but I don't like to program C++ if it is not necessary (especially if the only thing that changed between applications is the one line of code that does the actual calculation)

PS: another way to solve this would be to write a subclass of codedFunctionObject that has a volScalarField as a member

CedricVH April 3, 2012 12:07

Thank you very much!

I did not manage in C++ but with swak4foam it works perfectly! However, swak4foam does not recognise the magSqr() function. If other people would have the same problem, the correct code is:

Code:

          compute_ptot
            {
                type expressionField;
                outputControl timeStep;
                outputInterval 1;
                fieldName ptot;
                expression "p + 0.5*sqrt(mag(U))";
                autowrite false;       
            }


gschaider April 3, 2012 14:48

Quote:

Originally Posted by CedricVH (Post 352956)
Thank you very much!

I did not manage in C++ but with swak4foam it works perfectly! However, swak4foam does not recognise the magSqr() function. If other people would have the same problem, the correct code is:

Code:

          compute_ptot
            {
                type expressionField;
                outputControl timeStep;
                outputInterval 1;
                fieldName ptot;
                expression "p + 0.5*sqrt(mag(U))";
                autowrite false;       
            }


OK. I was doing this off the top of my head without testing.

If a bug-report appears on the of-extend-Mantis the magSqr-function might appear in swak4Foam in the next release

eelcovv September 21, 2012 06:03

Hi Bernard,

I was reading your instruction to add an object to the registry from the code snipped. Actually, I would like to do something like this. For instance, I would like to calculated the averaged vorticity magnitude using the field average libs without modifying the code. For that I want to use the code snipped to calculate the mag voritcity. I tried your tip, it compiles but it does not work

The question is: how do I add the field to the object registry ? Do you have a hint for me ?

Here is what I have so far. I am trying to use checkin. Is that correct ?

Thanks!
Eelco

Code:

magUIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{

  const volVectorField& U = mesh().lookupObject<volVectorField>("U");

  if (!(IOobject("magVorticity", mesh().time().timeName(), U.mesh()).headerOk()))
  {
      Info << "creating magVorticity" << nl;
      volScalarField magVorticity
      (
          IOobject
          (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::NO_WRITE
          ),
        mag(fvc::curl(U))
      );

      Info << "Add it to the registry" << nl;
      magVorticity.checkIn();
  }

  Info << "now getting magVoritity" << nl;
  const volScalarField& magVorticity = mesh().lookupObject<volScalarField>("magVorticity");

  //magVorticity=mag(fvc::curl(U));

 #};
}


gschaider September 21, 2012 13:18

Quote:

Originally Posted by eelcovv (Post 382944)
Hi Bernard,

I was reading your instruction to add an object to the registry from the code snipped. Actually, I would like to do something like this. For instance, I would like to calculated the averaged vorticity magnitude using the field average libs without modifying the code. For that I want to use the code snipped to calculate the mag voritcity. I tried your tip, it compiles but it does not work

The question is: how do I add the field to the object registry ? Do you have a hint for me ?

Here is what I have so far. I am trying to use checkin. Is that correct ?

Thanks!
Eelco

The reason why you ask is that it didn't work, right?

I'm afraid the object is destroyed when it goes out of scope and the during that the destructor calls checkOut (its got no other choice as C++ will insist on giving back the memory). So I guess you'll have to create a volScalarField with new, check that in and forget about the pointer. But to see how to do that correctly without openig a HUGE memory leak and be sure that it is given back correctly at the end of the run I'd have to go through the sources. and frankly I don't care: If I want such a field I use an expressionField-function object with the expression "mag(curl(U))" give it a name and happily use it from then on (and I do that regularly). For me programming is solving a problem once, do it right and then forget how I did it. That's what swak is there for. Writing boilerplate-snipplets like the one below every time I need it (and I use that often) would be a good memory exercise (not my strong foot) but in the long run rather boring.

Don't get me wrong: if you want to learn how to program OpenFOAM then this is a nice exercise, but you'll learn more by reading the regIOobject and the objectRegistry-class and experimenting. If you just want to get your work done then take the 15 minutes it will take you to compile swak4Foam (most of the time will be spent drinking coffee) and use an expressionField. Or if you're lucky somebody will take this arrogant rant (hope it doesn't come across as that) as an incentive to show you (and me) how it can be done elegantly in C++

Quote:

Originally Posted by eelcovv (Post 382944)
Code:

magUIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{

  const volVectorField& U = mesh().lookupObject<volVectorField>("U");

  if (!(IOobject("magVorticity", mesh().time().timeName(), U.mesh()).headerOk()))
  {
      Info << "creating magVorticity" << nl;
      volScalarField magVorticity
      (
          IOobject
          (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::NO_WRITE
          ),
        mag(fvc::curl(U))
      );

      Info << "Add it to the registry" << nl;
      magVorticity.checkIn();
  }

  Info << "now getting magVoritity" << nl;
  const volScalarField& magVorticity = mesh().lookupObject<volScalarField>("magVorticity");

  //magVorticity=mag(fvc::curl(U));

 #};
}



eelcovv September 25, 2012 08:04

Hi Bernard,

Indeed my example didn't work for the reason you gave. Your remark about using swak4foam: yes, I totally agree, I use it at least quite a lot for funkySetFields and groovyBC, I didn't no this expression field yet.

But to be honest, the reason I wanted to do something complicated via C++ is that I want to keep an summation of the velocity of lagrangian particles (their values and their sum) per grid cell so I can calculate the mean conditional particle velocity over the field at the end of the run .This requires I think some C++ coding as I guessed swak4foam could not deal with lagrangian particles. I though if I got the simpler case wit mag(curl(U)) running I can do the particle averaging as well (without modifying the source code of the application)
So per grid cell I would like to keep durign the run
sumN=Sum_particlesincell(i)
sumU=Sumparticlesincell(U_i)
in order to get the <Upart>=sumU/sumN at the end of the run.

I thought I need coded snipped for this, but if there is a way to do it with swak4foam: please let me know!

gschaider September 25, 2012 12:44

Quote:

Originally Posted by eelcovv (Post 383507)
Hi Bernard,

Indeed my example didn't work for the reason you gave. Your remark about using swak4foam: yes, I totally agree, I use it at least quite a lot for funkySetFields and groovyBC, I didn't no this expression field yet.

But to be honest, the reason I wanted to do something complicated via C++ is that I want to keep an summation of the velocity of lagrangian particles (their values and their sum) per grid cell so I can calculate the mean conditional particle velocity over the field at the end of the run .This requires I think some C++ coding as I guessed swak4foam could not deal with lagrangian particles.

You're right. It can not and I consider this to be the last "missing chapter" but due to the use of templating that is easier said than done (especially general expressions on particles using their properties)

Quote:

Originally Posted by eelcovv (Post 383507)
I though if I got the simpler case wit mag(curl(U)) running I can do the particle averaging as well (without modifying the source code of the application)
So per grid cell I would like to keep durign the run
sumN=Sum_particlesincell(i)
sumU=Sumparticlesincell(U_i)
in order to get the <Upart>=sumU/sumN at the end of the run.

I thought I need coded snipped for this, but if there is a way to do it with swak4foam: please let me know!

The current development version of swak (only the 2.x branch - see Wiki-page how to get that) has first attempts at incorporating lagrangian particles
- functionObjects that allow to add particle clouds to solvers that don't usually do particles
- function-plugins (a new feature of that development version) that query existing clouds (of the intermediate-variety) for information that they voluntarily give (volume/mass fraction of the particles, momentum and other sources ...) but the information you're interested in (particle properties mapped to the volume) it can not do. Writing such a function is not that hard ... for a specific cloud-type. The problem starts if it should be more general

So I'm afraid swak won't do this for you.

About your problem with the field being destroyed if the variable goes out of scope. The problem is basically that the coded-function object doesn't allow you to add member variables. But maybe this might help you:
Code:

static autoPtr<volScalarField> pField;
if(!pField.valid()) {
  pField.set(new volScalarField(....));
}
volScalarField &field=pField();
... do your thing

Have a look on the semantic of static local variables (and I can't promise that it will work here) to understand this sketch

What I'd do if I had that problem (but admittedly I'm a bit extreme here) would be to write a library with plugin-functions that encapsulate the querying of the particles in a special function that I can then call in swak-expressions (something like "cellVelocitySum(myCloudName)") if the library is loaded. That's what I did the functionPlugins for: adding application specific functionality to swak. But there is currently no docu for this, so this wouldn't be easy

eelcovv October 1, 2012 03:06

Hi Bernard,

Well, thanks for the answer to my problem, your suggestion seems to work. For the record, here what I did:
Code:

magvorticityIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{

  const volVectorField& U = mesh().lookupObject<volVectorField>("U");
  static autoPtr<volScalarField> pField;

  if(!pField.valid())
  {
      Info << "Creating magVorticity" << nl;

      pField.set
      (
        new volScalarField
        (
            IOobject
            (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::AUTO_WRITE
            ),
            mag(fvc::curl(U))
        )
      );
  }

  volScalarField &magVorticity = pField();

  magVorticity.checkIn();

  magVorticity += mag(fvc::curl(U));
  Info << " max Vorticity " << max(magVorticity) << nl;
 #};
}
~

I take the summation of all the magnitudes of the vorticity, and indeed the scalar field is now kept into memory. Thanks for this, I think I can get now the particle statistics into this piece of code as well.

Well, one small issue, perhaps you have the solution for it as well.

Although this code works, the registration of the magVorticity field is done only at the end of the first iteration. In case you would like to use the fieldAverage functionobject, this is too late. Althought I make sure that the dynamic code is added before the fieldAverages, the magVorticity does not exist yet when the fieldaverage field are created and therefore fieldaverage complains if you add magVorticity to its list.
Do you have any trick to get away with this? For example to force to run the dynamic code directly at loading time? Or to postpone the allocation of the field average dict after the end of the iteration ?
Well, if it is not easy to solve, never mind. With this I at least get my particles statistics running. but if I could use fieldAverage for it it would be even better of coarse:-)

Thanks!


Regards
Eelco

gschaider October 1, 2012 08:41

Quote:

Originally Posted by eelcovv (Post 384295)
Hi Bernard,

Well, thanks for the answer to my problem, your suggestion seems to work. For the record, here what I did:
Code:

magvorticityIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{

  const volVectorField& U = mesh().lookupObject<volVectorField>("U");
  static autoPtr<volScalarField> pField;

  if(!pField.valid())
  {
      Info << "Creating magVorticity" << nl;

      pField.set
      (
        new volScalarField
        (
            IOobject
            (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::AUTO_WRITE
            ),
            mag(fvc::curl(U))
        )
      );
  }

  volScalarField &magVorticity = pField();

  magVorticity.checkIn();

  magVorticity += mag(fvc::curl(U));
  Info << " max Vorticity " << max(magVorticity) << nl;
 #};
}
~

I take the summation of all the magnitudes of the vorticity, and indeed the scalar field is now kept into memory. Thanks for this, I think I can get now the particle statistics into this piece of code as well.

Well, one small issue, perhaps you have the solution for it as well.

Although this code works, the registration of the magVorticity field is done only at the end of the first iteration. In case you would like to use the fieldAverage functionobject, this is too late. Althought I make sure that the dynamic code is added before the fieldAverages, the magVorticity does not exist yet when the fieldaverage field are created and therefore fieldaverage complains if you add magVorticity to its list.
Do you have any trick to get away with this? For example to force to run the dynamic code directly at loading time? Or to postpone the allocation of the field average dict after the end of the iteration ?

The problem probably is that the fields are specified during the construction of the function Object.

Well. I have a workaround. But don't be surprised: it involves swak. There is a functionObject executeIfSwakExpression (there is a number of similar FOs) that encapsulates a list of functionObjects and only executes them if a condition is true. Also there is an option readDuringConstruction. If set to false the construction of the FOs will be deferred until the expression (for instance "time>0.001") is true for the first time.

So what might work is this sequence
- your FO
- executeIfSwakExpression with
-- expression "true"
-- readDuringConstruction "false"
-- fieldAverage as the only FO in the sequence
might help you

But there is always the possibility to write a new FO by copy/pasting fieldAverage or inheriting and "rewiring" the execution

Quote:

Originally Posted by eelcovv (Post 384295)
Well, if it is not easy to solve, never mind. With this I at least get my particles statistics running. but if I could use fieldAverage for it it would be even better of coarse:-)

Thanks!


Regards
Eelco


eelcovv October 4, 2012 03:00

Bernard,

Thanks a lot, I just had a look at those swak function objects and I have the impression that this is going to help me. For now I actually solved it by writing a cloudfunction function object in the LPT library (copied VoidFraction Cloudfunctionobject and modified it to get the mean particle velocity field). This works and allows me to keep the statistical analyses separare from the solver as well.

I will have a look at the swak function objects as soon as I have some time. It seems to me that this replaces almost all the other functionobjects (averaging, sample lines and planes, volume averaging, monitoring points) with a greater flexibility, so it is worth to see if I can use it. Thanks for the hint!

Regards
Eelco

eelcovv October 19, 2012 04:12

averaging of field made with coded function objects
 
Hi Bernard,

Just had some time to play around with swak4foam to see if I got your suggestion running. And yes, swak4foam gives the solution again!

For those interested: In case you want to generate some field (like for instance the vorticity) on the fly (not in the solver) and also be able to average it with the functionobject, the following works

Put in your controlDict

Code:

libs
(
  "libsimpleSwakFunctionObjects.so"
  "libswakFunctionObjects.so"
);

functions
(
    #include "dynamicCodeVolumeAverageDict"
    #include "fieldAverageDict"
);

And than create the two files dynamicCodeVolumeAverageDict and fieldAverageDict in your system directory with the following contents

system/dynamicCodeVolumeAverageDict
Code:

magvorticityIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{
  const volVectorField& U = mesh().lookupObject<volVectorField>("U");
  static autoPtr<volScalarField> pField;

  if(!pField.valid())
  {
      Info << "Creating magVorticity" << nl;

      pField.set
      (
        new volScalarField
        (
            IOobject
            (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::AUTO_WRITE
            ),
            mag(fvc::curl(U))
        )
      );
  }

  volScalarField &magVorticity = pField();

  magVorticity.checkIn();

  magVorticity += mag(fvc::curl(U));
  Info << " max Vorticity " << max(magVorticity) << nl;
 #};
}

and

system/fieldAverageDict

Code:

fieldAverageEnc
{
  type            executeIfSwakExpression;
  logicalExpression "(time()>0.001)";
  logicalAccumulation "and";
  readDuringConstruction false;
  valueType      internalField;

  functions
  {
      fieldAverage
      {
        type            fieldAverage;
        functionObjectLibs ("libfieldFunctionObjects.so");
        enabled        true;
        timeStart      0;
        resetFields    1;
      // timeEnd        250;
        outputControl  outputTime;
        fields
        (
            U
            {
              mean        on;
              prime2Mean  on;
              base        time;
            }

            magVorticity
            {
              mean        on;
              prime2Mean  off;
              base        time;
            }
        );
      } // END fieldAverage
  }
}

That's it. At the start of the run, the magVorticity field is created and kept into memory by the dynamicCode part. Then after the first iteration the functionobject to average the fields is initialised, such that the field magVorticity is known and can be averaged too. Of coarse, this trick can be used on the cloudfunction objects as well, which allows you the average for instance the theta field generated with the VoidFraction cloudfunction object in case you do particle tracking simulations.

Bernard, thanks again for the very useful hints! (and for writing those swak4foam functionobjects in the first place of course).

Regards
Eelco

eelcovv October 19, 2012 04:14

Oops, the += in the code function object should be =, the former was of a testing phase.

gschaider October 19, 2012 05:58

Quote:

Originally Posted by eelcovv (Post 387459)
Hi Bernard,

Just had some time to play around with swak4foam to see if I got your suggestion running. And yes, swak4foam gives the solution again!

For those interested: In case you want to generate some field (like for instance the vorticity) on the fly (not in the solver) and also be able to average it with the functionobject, the following works

Put in your controlDict

Code:

libs
(
  "libsimpleSwakFunctionObjects.so"
  "libswakFunctionObjects.so"
);

functions
(
    #include "dynamicCodeVolumeAverageDict"
    #include "fieldAverageDict"
);

And than create the two files dynamicCodeVolumeAverageDict and fieldAverageDict in your system directory with the following contents

system/dynamicCodeVolumeAverageDict
Code:

magvorticityIntegral
{
 functionObjectLibs ("libutilityFunctionObjects.so");
 type coded;
 redirectType integral;
 outputControl timeStep;
 code
 #{
  const volVectorField& U = mesh().lookupObject<volVectorField>("U");
  static autoPtr<volScalarField> pField;

  if(!pField.valid())
  {
      Info << "Creating magVorticity" << nl;

      pField.set
      (
        new volScalarField
        (
            IOobject
            (
              "magVorticity",
              mesh().time().timeName(),
              U.mesh(),
              IOobject::NO_READ,
              IOobject::AUTO_WRITE
            ),
            mag(fvc::curl(U))
        )
      );
  }

  volScalarField &magVorticity = pField();

  magVorticity.checkIn();

  magVorticity += mag(fvc::curl(U));
  Info << " max Vorticity " << max(magVorticity) << nl;
 #};
}

<snip>

That's it. At the start of the run, the magVorticity field is created and kept into memory by the dynamicCode part. Then after the first iteration the functionobject to average the fields is initialised, such that the field magVorticity is known and can be averaged too. Of coarse, this trick can be used on the cloudfunction objects as well, which allows you the average for instance the theta field generated with the VoidFraction cloudfunction object in case you do particle tracking simulations.

Bernard, thanks again for the very useful hints! (and for writing those swak4foam functionobjects in the first place of course).

Regards
Eelco

Nice. But as you bit the bullet anyway and installed swak you might as well have said

Code:

magvorticityIntegral
            {
                type expressionField;
                outputControl timeStep;
                outputInterval 1;
                fieldName magVorticity;
                expression "mag(curl(U))";
                autowrite false;       
            }

But that way you learned something about static variables

eelcovv October 19, 2012 09:08

It's always nice to know that there are several ways to Rome :-)

eelcovv November 26, 2012 09:15

startTime reference
 
Dear Bernhard,

I took the trick you showed me with the executeIfSwakExpression in my standard repetoir. One little question
I now use the expression:
{
type executeIfSwakExpression;
logicalExpression "(time()>0.001)";
logicalAccumulation "and";
readDuringConstruction false;
valueType internalField;
functions
{
}
}

However, if I make a restart I have to change the 0.001 into something with 10.0001 orso. Is there a way to refer to the startTime of the current run, something like
logicalExpression "(time()>startTime()+0.001)";

I tried a few options, but none did work. Otherwise: is there a way just to check if a field excists ? and the execute the function only if it is true ? That would help too.

Well, thanks for any hints.

Regards
Eelco

gschaider November 26, 2012 15:01

Quote:

Originally Posted by eelcovv (Post 394214)
Dear Bernhard,

I took the trick you showed me with the executeIfSwakExpression in my standard repetoir. One little question
I now use the expression:
{
type executeIfSwakExpression;
logicalExpression "(time()>0.001)";
logicalAccumulation "and";
readDuringConstruction false;
valueType internalField;
functions
{
}
}

However, if I make a restart I have to change the 0.001 into something with 10.0001 orso. Is there a way to refer to the startTime of the current run, something like
logicalExpression "(time()>startTime()+0.001)";

Not sure. There is no such function. My first impulse would have been to use a storedVariable that initializes to "time()" and is never reset. Problem is (not 100% sure, you might want to experiment) that stored variables are too clever for this application: the value gets stored at write time and is restored during a restart (usually that is what one wants so I don't apologize). But you can always remove the file where the value is stored and it gets initialized again ... to the current startTime.

Adding a global variable with the addGlobalVariable-functionObject has the same problem ... I think (I could look at the source but I'm too busy).

Then there is the possibility to use the pythonIntegration-functionObject: define a code snipplet for the initialization time that sets some variable to the current time (which is the initialization time). Don't modify it in the other snipplets and export the variable to a global namespace from which the functionObject in question can import it.

If you bit the bullet and used the pythonIntegration then you might be able to do it with the executeIfPython-function object and the python code:
Code:

if not "startTime" in dir():
    startTime=runTime
return runTime>(startTime+0.001)

If I read the source correctly the Python-environment is preserved between timesteps so the if will only be evaluated at the first timestep (If that works I'd consider it to be the most elegant solution)

Quote:

Originally Posted by eelcovv (Post 394214)
I tried a few options, but none did work. Otherwise: is there a way just to check if a field excists ? and the execute the function only if it is true ? That would help too.

I'd suggest you create a new functionObject with a type that doesn't exist (for instance "type captainBeefheart;") and be inspired by the list of functionObjects that OF spits out. Maybe the one called executeIfObjectPresent will interest you.

For examples on the usage of this something like "grep -r executeIfPython Examples/*" will help you

eelcovv November 27, 2012 02:38

Thanks for the hints Bernhard!
I will give the python option a try. If I find I solution I will report it back to you.
Eelco (alias Captain beefheard;)

eelcovv November 27, 2012 03:04

executeIfObjectExists
 
For those interested. Using the captain braveheard trick I found the executeIfObjectExists function object. I need this because first I use a swakExpression to calculate the magnitude of the vorticity:

Code:

magVorticity
{
  type expressionField;
  outputControl timeStep;
  outputInterval 1;
  fieldName magVorticity;
  expression "mag(curl(U))";
  autowrite true;
}

Then I want to plot this magVorticity using planes libsampling.so, however, at the first time step the magVorticity does not exist yet and therefore the code will crash at start up. You have to encapsulate surface sampling function object with another function object that checks if magVorticity exists.

You can do the following

Code:

PlanesVTKEnc
{
  type executeIfObjectExists;
  readDuringConstruction false;
  objectName magVorticity;
  checkType true;
  objectType volScalarField;
  objectShouldExist true;
  valueType      internalField;
  functions
  { 
      PlanesVTK
      {     
        enabled        true;
        type surfaces;
        setFormat raw;
        surfaceFormat vtk;
        writeFormat binary;
        timePrecision 0;
        interpolationScheme cellPointFace;
        functionObjectLibs ("libsampling.so");
        outputControl  timeStep;
        outputInterval  1;
        fields
        (
            U
            nuSgs
            magVorticity
        );
        surfaces
        (
            pxy_z0p0
            {
              type            plane;    // always triangulated
              // make plane relative to the coordinateSystem (Cartesian)
              coordinateSystem
              {
                  origin      (0.0 0.0 0.0);
              }
              basePoint      (0 0 0);
              normalVector    (0 0 1);
              interpolate    true;
            }
        );
      } 
  }
}

This is more elegant than checking on time: it just checks if the field already exists, if true, sample the planes. Voila!

Bernhard, thanks again for the useful hints. swak4foam is truly fantastic!

gschaider November 27, 2012 10:11

Quote:

Originally Posted by eelcovv (Post 394330)
For those interested. Using the captain braveheard trick I found the executeIfObjectExists function object. I need this because first I use a swakExpression to calculate the magnitude of the vorticity:

Code:

magVorticity
{
  type expressionField;
  outputControl timeStep;
  outputInterval 1;
  fieldName magVorticity;
  expression "mag(curl(U))";
  autowrite true;
}

Then I want to plot this magVorticity using planes libsampling.so, however, at the first time step the magVorticity does not exist yet and therefore the code will crash at start up. You have to encapsulate surface sampling function object with another function object that checks if magVorticity exists.

You can do the following

Code:

PlanesVTKEnc
{
  type executeIfObjectExists;
  readDuringConstruction false;
  objectName magVorticity;
  checkType true;
  objectType volScalarField;
  objectShouldExist true;
  valueType      internalField;
  functions
  { 
      PlanesVTK
      {     
        enabled        true;
        type surfaces;
        setFormat raw;
        surfaceFormat vtk;
        writeFormat binary;
        timePrecision 0;
        interpolationScheme cellPointFace;
        functionObjectLibs ("libsampling.so");
        outputControl  timeStep;
        outputInterval  1;
        fields
        (
            U
            nuSgs
            magVorticity
        );
        surfaces
        (
            pxy_z0p0
            {
              type            plane;    // always triangulated
              // make plane relative to the coordinateSystem (Cartesian)
              coordinateSystem
              {
                  origin      (0.0 0.0 0.0);
              }
              basePoint      (0 0 0);
              normalVector    (0 0 1);
              interpolate    true;
            }
        );
      } 
  }
}


Thank you for posting the solution here for future generations. Could I ask you to maybe add it to this new section of the swak4Foam-page on the Wiki: http://openfoamwiki.net/index.php/Co...Usage_examples (just a quick copy paste)
Quote:

Originally Posted by eelcovv (Post 394330)
This is more elegant than checking on time: it just checks if the field already exists, if true, sample the planes. Voila!

Bernhard, thanks again for the useful hints. swak4foam is truly fantastic!

Damn. I thought I had tricked you to come to the dark side of the force (=Python)


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