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/)
-   -   How to make a dictionary run-time modifiable? (https://www.cfd-online.com/Forums/openfoam-programming-development/142003-how-make-dictionary-run-time-modifiable.html)

kedarj14 April 8, 2011 07:46

How to make a dictionary run-time modifiable?
 
Hello All:

I have a bool type of variable which is read from the transport properties file. The true/false value gets read for the first time. However if I change that value in the transport properties file at runtime then the change is not communicated to the solver. The solver registers that the transport properties file has changed but it doesn't update the value of my variable. Controldict runtime modifiable is yes.

Is there something more I need to do to make the solver understand it has to read the updated value ?

Thanks,
Kedar

Gennaro September 21, 2014 13:10

How to make a dictionary run-time modifiable?
 
Hi all,

I created the following dictionary in createFields.H:
Code:

        IOdictionary equationConstants
        (
            IOobject
            (
                "equationConstants",
                runTime.constant(),
                fluidRegions[i],
                IOobject::MUST_READ,
                IOobject::NO_WRITE
            )
        );
   
        Info<< "    Reading Alambda\n" << endl;
        Alambdas.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("Alambda"))
        );
   
        Info<< "    Reading Slambda\n" << endl;
        Slambdas.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("Slambda"))
        );
   
        Info<< "    Reading Tlambda\n" << endl;
        Tlambdas.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("Tlambda"))
        );
   
        Info<< "    Reading SMALL\n" << endl;
        SMALLs.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("SMALL"))
        );

        Info<< "    Reading Sigma\n" << endl;
        Sigmas.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("Sigma"))
        );
       
        Info<< "    Reading Lref\n" << endl;
        Lrefs.set
        (
            i,
            new dimensionedScalar(equationConstants.lookup("Lref"))
        );

How can I make it run-time modifiable?

Thanks in advance

Gennaro

Gennaro September 25, 2014 09:35

any ideas? The problem is that not currently being run-time modifiable, if I change values in the dictionary file while a simulation is running, the new values are not read.

openfoammaofnepo October 12, 2014 12:56

Dear Gennaro,

I have the same concern, did you solve this problem now? Thank you very much.
OFFO


Quote:

Originally Posted by Gennaro (Post 511867)
any ideas? The problem is that not currently being run-time modifiable, if I change values in the dictionary file while a simulation is running, the new values are not read.


wyldckat October 12, 2014 15:17

Greetings to all!

I've moved the very first post from an old thread to this thread, since it's all in the same topic.

And I have to say that this is a bit of a tricky topic. First of all, the core magic happens if you use this option:
Code:

IOobject::MUST_READ_IF_MODIFIED
instead of:
Code:

IOobject::MUST_READ
But this only ensures that the dictionary variable is updated. In Gennaro's example, the variable "equationConstants" is automatically updated at the beginning of the "runTime"/"simpleControl"/"pimpleControl" loop.
Therefore, the variables "*lambdas" can only be updated if "equationConstants" is called once again.

Usually what's done is that this kind of auto-updatable code is placed inside a class that handles the data maintenance and storage. For example, if you look at the class "motionSolver": https://github.com/OpenFOAM/OpenFOAM...r/motionSolver - you'll see how this class derives from "IOdictionary", where the method "read()" is a virtual method that when reimplemented in "motionSolver", will automatically update the variables within "motionSolver" based on the data read from the assigned dictionary file. This method "read()" is called automatically by the mechanism "IOdictionary" inherits from other classes - for more information, read this wiki page and the ones referenced in it: http://openfoamwiki.net/index.php/Op...IOobject_class

Therefore, the solution should be to do the following steps, in Gennaro's example:
  1. Create a new class that derives from "IOdictionary" and place inside it the code that handles the population of the variables "*lambda". I'll call it "LambdaManager" for example.
  2. In the "createFields.H" file, replace all of your presented code with something like this:
    Code:

    //definition for replacing all of the lists you've got with just one
    PtrList<LambdaManager> equationConstants(numRegions);

    //... then use this instead

            equationConstants.set
            (
              i,
              new LambdaManager(
                IOobject(
                (
                    "equationConstants",
                    runTime.constant(),
                    fluidRegions[i],
                    IOobject::MUST_READ_IF_MODIFIED,
                    IOobject::NO_WRITE
                )
              )
            );

  3. Now, the final step for this trick (assuming you can create the new class on your own), is to replace the calls to the variables from this:
    Code:

    Alambdas(i)()
    To this:
    Code:

    equationConstants(i)().Alambda()


A simplified version of this big example would be something like this:
  1. Have a look at the solver "laplacianFoam": https://github.com/OpenFOAM/OpenFOAM.../laplacianFoam
  2. Move this piece of code from "createFields.H":
    Code:

        Info<< "Reading diffusivity DT\n" << endl;

        dimensionedScalar DT
        (
            transportProperties.lookup("DT")
        );

    to "laplacianFoam.C", after this part of the code:
    Code:

        while (simple.loop())
        {
            Info<< "Time = " << runTime.timeName() << nl << endl;

  3. In other words, it becomes something like this:
    Code:

        while (simple.loop())
        {
            Info<< "Time = " << runTime.timeName() << nl << endl;

            Info<< "Updating diffusivity DT\n" << endl;

            dimensionedScalar DT
            (
                transportProperties.lookup("DT")
            );

  4. It's not the prettiest solution, but I'm not in the mood to test this myself and to improve this solution :rolleyes:
    I'm not 100% certain, but I think that this might work:
    Code:

        while (simple.loop())
        {
            Info<< "Time = " << runTime.timeName() << nl << endl;

            if(transportProperties.modified())
            {
                Info<< "Updating diffusivity DT\n" << endl;

                DT = dimensionedScalar(transportProperties.lookup("DT"));
            }

    Of course this implies that in this case, you should not make any changes to the file "createFields.H"
    • edit 1 year later: After OFFO asked the question below, I tested things myself and the "modified()" method is useless in this scenario. Simply do:
      Code:

          while (simple.loop())
          {
              Info<< "Time = " << runTime.timeName() << nl << endl;

              DT = dimensionedScalar(transportProperties.lookup("DT"));

Best regards,
Bruno

openfoammaofnepo November 3, 2015 12:02

Dear Bruno,

This is an old problem, but it seems I have not solved it yet.

I add the following in the createField.H to build a dictionary:
Code:

    IOdictionary additionalControlsDict
    (
        IOobject
        (
            "additionalControls",
            runTime.constant(),
            mesh,
            IOobject::MUST_READ_IF_MODIFIED,
            IOobject::NO_WRITE
        )
    );

Then in the main code for a solver:

Code:

            dimensionedScalar relax(additionalControlsDict.lookup("relax"));
            Info<<"relax="<< relax <<endl;

When I change relax in that dictionary, the information printed by the solver is the new value of "relax". However, the strange thing is: this new value is not used by the solver (I checked my results and this can be confirmed). So that means the solver is still using the old one for running. Do you know what causes this problem? I think this implementation is similar to what you mentioned in the last thread.

Also, in the last thread, you mentioned that:

Code:

Therefore, the variables "*lambdas" can only be updated if "equationConstants" is called once again.
It is not clear for me about the how to call "equationConstants" (in my case it is "additionalControlsDict") again?

Thank you.

wyldckat November 29, 2015 11:27

Hi OFFO,

Many thanks for asking about this, because as I had mentioned in the previous post, I wasn't certain if it would work, since I didn't test it myself.

Nonetheless, I've tested this now with icoFoam and apparently the "modified()" method can only be used by the auto-reading mechanism. What we should simply do is the same that the file "readPISOControls.H" does (see in folder "src/finiteVolume/cfdTools/general/include/" in OpenFOAM 2.1.1):
Code:

    const dictionary& pisoDict = mesh.solutionDict().subDict("PISO");

    const int nOuterCorr =
        pisoDict.lookupOrDefault<int>("nOuterCorrectors", 1);

    const int nCorr =
        pisoDict.lookupOrDefault<int>("nCorrectors", 1);

    const int nNonOrthCorr =
        pisoDict.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0);

    const bool momentumPredictor =
        pisoDict.lookupOrDefault("momentumPredictor", true);

    const bool transonic =
        pisoDict.lookupOrDefault("transonic", false);

In other words, I've already updated my previous post with an addendum, but the idea is that you can change the following in "icoFoam.C":
Code:

    while (runTime.loop())
    {
        Info<< "Time = " << runTime.timeName() << nl << endl;

        #include "readPISOControls.H"
        #include "CourantNo.H"

        fvVectorMatrix UEqn
        (
            fvm::ddt(U)
          + fvm::div(phi, U)
          - fvm::laplacian(nu, U)
        );

To this:
Code:

    while (runTime.loop())
    {
        Info<< "Time = " << runTime.timeName() << nl << endl;

        #include "readPISOControls.H"
        #include "CourantNo.H"
       
        nu = transportProperties.lookup("nu");

        fvVectorMatrix UEqn
        (
            fvm::ddt(U)
          + fvm::div(phi, U)
          - fvm::laplacian(nu, U)
        );

Best regards,
Bruno


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