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/)
-   -   Runtime modification of a volScalarField (https://www.cfd-online.com/Forums/openfoam-programming-development/122189-runtime-modification-volscalarfield.html)

Scofield August 14, 2013 06:59

Runtime modification of a volScalarField
 
Hey all,

I would like to modify a volScalarField called "modifyS" during runtime of a simulation. "modifyS" is a uniform field and located in the "constant" directory of my case.

In "createFields.H" I specify this field by using following IOobject definition:
----------------------
volScalarField modifyS
(
IOobject
(
"modifyS",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
),
mesh
);

----------------------

My problem:
If I modify "modifyS" during runtime, the modification is not read in. Even if I insert the lookup function at the beginning of the time loop, a modification is not read in:

----------------------
const volScalarField& modifyS = mesh.lookupObject<volScalarField>("modifyS");
-----------------------

Does anyone know how to modify a volScalarField during runtime?

Thanks in advance!
Regards,
Daniel

mkraposhin August 14, 2013 13:23

Quote:

Originally Posted by Scofield (Post 445645)
Hey all,

I would like to modify a volScalarField called "modifyS" during runtime of a simulation. "modifyS" is a uniform field and located in the "constant" directory of my case.

In "createFields.H" I specify this field by using following IOobject definition:
----------------------
volScalarField modifyS
(
IOobject
(
"modifyS",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
),
mesh
);

----------------------

My problem:
If I modify "modifyS" during runtime, the modification is not read in. Even if I insert the lookup function at the beginning of the time loop, a modification is not read in:

----------------------
const volScalarField& modifyS = mesh.lookupObject<volScalarField>("modifyS");
-----------------------

Does anyone know how to modify a volScalarField during runtime?

Thanks in advance!
Regards,
Daniel

First note.
when you are writing
----------------------
const volScalarField& modifyS = mesh.lookupObject<volScalarField>("modifyS");
-----------------------
you are not asking OpenFOAM to re-read field. This string means only: "find object of type volScalarField with the name modifyS and return constant reference to it to me"

Second note.
IOobject only defines flags for I/O, but method readIfModified() of the class regIOobject (which inherits from IOobject and inherited by volScalarField) do the task what you want.

So, you can try to insert line:
---
modifyS.readIfModified();
---

at the start of each time step:

while (runTime.run())
{
modifyS.readIfModified();
// do something else
}

Third note.
You can always check whether dictionary (field) was modified by the method modifyS.modified().
Than, you can run method modifyS.read()
See documentation here

Hope, this helped to you

Scofield August 20, 2013 10:49

Thanks a lot mkraposhin for your response. I really appreciate that.

Unfortunately the volScalarField "modifyS" ist still not updated when modified.
I have implemented it this way:

In createFields.H:
-------------------------------------
Info<< "Reading field modifyS\n" << endl;
volScalarField modifyS
(
IOobject
(
"modifyS",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
),
mesh
);

-----------------------------------

In shallowFoam.C:
----------------------------------------
...
while (runTime.run())
{
#include "readTimeControls.H"
#include "CourantNo.H"
#include "setDeltaT.H"

modifyS.readIfModified();
runTime++;
Info<< "modifyS = " << modifyS << nl << endl;
//... something else
}

-----------------------------------

I have deleted the lookup- function.
Do you or does someone else have an idea what else i can try?

I have another problem:
As soon as I define in createFields.H the IOobject "modifyS" as "MUST_READ_IF_MODIFIED", a modification of "modifyS" sometimes causes an abortion of the simulation with this error:
--------------------------------
regIOobject::readIfModified() :
Re-reading object modifyS from file "/home/BAUINFORMATIK/OpenFOAM/run/interactivity/PflegerTestModifyS/constant/modifyS"

--> FOAM FATAL IO ERROR:
cannot open file

file: /home/BAUINFORMATIK/OpenFOAM/run/interactivity/PflegerTestModifyS/constant/modifyS at line 0.

From function regIOobject::readStream()
in file db/regIOobject/regIOobjectRead.C at line 87.

FOAM exiting

----------------------------------------

Does someone know the reason for this error and why it occurs just sometimes?

Remarks:
- When I define the IOobject modifyS at the beginning of the time loop (with MUST_READ or MUST_READ_IF _MODIFIED), the modification actually works. But I also get sometimes this error that the corresponding file can't be opended. So if I can get rid of this error, I can at least use this unconventional solution.

- I have tested to modify the IOdictionary "transportProperties", and there a modification is always read in and the simulation is never stopped by an error. I don't know why it does not work for a volScalarField.

Thanks a lot in advance!

mkraposhin August 20, 2013 17:15

1 Attachment(s)
Hi, Scofield

By inspecting the OpenFOAM source code i found, that you cannot update volScalarField only by specifying MUST_READ_IF_MODIFIED at the construction.

The problem is that only IOdictionary class knows how to read data from file when it was modified.

More over, when object was modified, OpenFOAM object runTime reads it (by executing function ::read()) and sets the modified flag() to false.

You have three ways:

1) Use IOdictionary to store additional flags which will show that field modifyS was modified. If this flag was triggered, then, you need to re-init your field

2) Derive interface class from regIOobject and dictionary to read field when it was modified and then, substitute to volScalarField as a construction parameter

3) Derive you own field class from the GeometricField.

I will explain to you path #2

1) Create class IOfieldDictionary, which is derived from regIOobject and dictionary
Code:


class IOfieldDictionary
:
    public regIOobject,
    public dictionary
{
    const word type_;

public:

    // Redefine type name to be of the instantiated type
    virtual const word& type() const
    {
        return type_;
    }


    // Constructors

        //- Construct from ioobject and overloaded typename.
        explicit IOfieldDictionary(const IOobject& io, const word& type)
        :
            regIOobject(io),
            dictionary(readStream(type)),
            type_(type)
        {
            close();
        }



    // Member functions

        virtual bool readData(Istream& is)
        {
            is >> *this;
           
            return !is.bad();
        }

        virtual bool writeData(Ostream& os) const
        {
            dictionary::write(os, false);
            return os.good();
        }

        virtual bool write() const
        {
            return regIOobject::write();
        }
};

2) Create one object for this dictionary and second object for your field (pointer) in your createFields.H
Code:

    IOfieldDictionary modifySDict
    (
            IOobject
            (
                "modifyS",
                runTime.constant(),
                mesh,
                IOobject::MUST_READ_IF_MODIFIED,
                IOobject::NO_WRITE
            ),
            "volScalarField"
    );
   
    autoPtr<volScalarField> modifySPtr
    (
        new volScalarField
        (
            IOobject
            (
                "modifyS",
                runTime.constant(),
                mesh,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            ),
            mesh,
            modifySDict
        )
    );

3) Monitor for the additional flag ("modified") in your field at the start of each timestep:
Code:

    while (runTime.loop())
    {
        Info<< "Time = " << runTime.timeName() << nl << endl;
       
        {
            Switch modified (modifySDict.lookup("modified"));
           
            Info << "modified" << modified << endl;
           
            if (modified)
            {
                //create a new field
                autoPtr<volScalarField> modifySPtr
                (
                    new volScalarField
                    (
                        IOobject
                        (
                            "modifyS",
                            runTime.constant(),
                            mesh,
                            IOobject::NO_READ,
                            IOobject::NO_WRITE
                        ),
                        mesh,
                        modifySDict
                    )
                );

                modified = false;

                modifySDict.set<Switch>("modified", modified);
                IOfieldDictionary(modifySDict).write();

                Info << "field was modified" << endl << modifySPtr() << endl;
            }
        }
        volScalarField& modifyS = modifySPtr();

I attached the source code for the application and test case in tar.gz

when you finished with changing of the field in modifyS, you must set flag "modified" to true:
Code:

modified        true;

dimensions      [ 0 0 0 0 0 0 0 ];

internalField  uniform 2;

boundaryField
{
    movingWall
    {
        type            zeroGradient;
    }
    fixedWalls
    {
        type            zeroGradient;
    }
    frontAndBack
    {
        type            empty;
    }
}


Scofield October 1, 2013 09:31

Thanks a lot mkraposhin for your help. I have integrated it in my code and it works, your response was the solution for my problem. Great!

In another thread I have posted a similar problem:
http://www.cfd-online.com/Forums/ope...tml#post454451


All times are GMT -4. The time now is 10:09.