View Issue Details

IDProjectCategoryView StatusLast Update
0002499OpenFOAMBugpublic2017-03-16 12:00
Reporterchrisk Assigned Tohenry  
PrioritynormalSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Summary0002499: FunctionObject dsmcFields has no acess to Mean-Fields
DescriptionHi,
I am using dsmcFoam and I am averaging the fields with the option restartOnOutput set to on. When this option is set the order in which the functionObject are called is crucial. If the fields are first averaged like in the tutorial wedge15Ma5 and then the dsmcFields functionObject is called the calulation "fails" (the non-averaged fields are used), because of the option restartOnOutput the Mean-Fields are reseted/cleared in memory the moment before the calculation.

Solution to that problem is change the order in which the functions are called in the controlDict, but doing this if I understand it right, the final timestep isn't used for the dsmcField-FunctionObject calculation, becauses it is not used in the averaging process, meaning the result is not what one would expect.

Also there is that problem that when you try to calculate the dsmcField in postProcess, that the Mean-Fields are not loaded into the ObjectRegistry for the dsmcFoam solver.

1) So trying something like this:
dsmcFoam -time 0.001 -postProcess

1) Results in:
--> FOAM FATAL ERROR:

    request for volScalarField rhoNMean from objectRegistry region0 failed
    available objects of type volScalarField are

2) Trying:
dsmcFoam -time 0.001 -postProcess -fields '(rhoNMean rhoMMean momentumMean linearKEMean internalEMean iDofMean fDMean)'

2) Results in the same error.

3) Trying:
postProcess -fields '(rhoNMean rhoMMean momentumMean linearKEMean internalEMean iDofMean fDMean)' -time 0.001 -func dsmcFields

3) Results in:
--> FOAM Warning :
    From function static bool Foam::functionObjectList::readFunctionObject(const Foam::string&, Foam::dictionary&, Foam::HashSet<>&, const Foam::word&)
    in file db/functionObjects/functionObjectList/functionObjectList.C at line 245
    Cannot find functionObject file dsmcFields
Time = 0.001

Reading fields:
    volScalarFields: iDofMean rhoMMean internalEMean rhoNMean linearKEMean
    volVectorFields: momentumMean fDMean



So fields are loaded, but after that nothing happens.

I hope my explenations are understandable and that it can be fixed.

Chears,
Christoph
Steps To Reproduce-Use the wedge15Ma5 tutorial
-Add the option restartOnOutput on; in the fieldAverage function
-Set the nEquivalentParticles to 5e11 in constant/dsmcProperties (Or else dsmcField can not be calculated, because some rhoNMean values are 0; See /src/functionObjects/lagrangian/dsmcFields/dsmcFields.C Line 146)
-Take a look in paraview and compare the UMean field, with one calculated in paraview (momentumMean/rhoMMean)
-Change the order of the function calls in the controlDict and compare again
TagsNo tags attached.

Activities

henry

2017-03-13 19:39

manager   ~0007924

Can you provide a patch to fix this problem?

chrisk

2017-03-13 21:51

reporter   ~0007926

Not really. Only a very very bad workaround, that doesn't fix the problem with the crucial order of functions and memory clearing when restartOnOutput is set to on.

With this "workaround" I am using the fieldAverage function during simulation and a motified dsmcField function (src/functionObjects/lagrangian/dsmcFields/dsmcFields.C), that loads the mean fields to the objectRegistry.

Also this problem only exists, because with OF 4.x it's possible to calculate the dsmcFields during the simulation. In previous versions this was done after the simulation with the executable dsmcFieldsCalc.
dsmcFields.C (11,382 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "dsmcFields.H"
#include "volFields.H"
#include "dictionary.H"
#include "dsmcCloud.H"
#include "constants.H"
#include "addToRunTimeSelectionTable.H"

using namespace Foam::constant;

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{
namespace functionObjects
{
    defineTypeNameAndDebug(dsmcFields, 0);

    addToRunTimeSelectionTable
    (
        functionObject,
        dsmcFields,
        dictionary
    );
}
}


// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::dsmcFields
(
    const word& name,
    const Time& runTime,
    const dictionary& dict
)
:
    functionObject(name),
    obr_
    (
        runTime.lookupObject<objectRegistry>
        (
            dict.lookupOrDefault("region", polyMesh::defaultRegion)
        )
    )
{
    if (!isA<fvMesh>(obr_))
    {
        FatalErrorInFunction
            << "objectRegistry is not an fvMesh" << exit(FatalError);
    }

    read(dict);
}


// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::~dsmcFields()
{}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

bool Foam::functionObjects::dsmcFields::read(const dictionary& dict)
{
    return true;
}


bool Foam::functionObjects::dsmcFields::execute()
{
    return true;
}


bool Foam::functionObjects::dsmcFields::write()
{
    word rhoNName = "rhoN";
    word rhoMName = "rhoM";
    word momentumName = "momentum";
    word linearKEName = "linearKE";
    word internalEName = "internalE";
    word iDofName = "iDof";
    word fDName = "fD";



    //obr_.lookupObject<volScalarField>()
    /*volScalarField rhoNMean
    (
        IOobject
        (
            rhoNMeanName,
            obr_.time().timeName(obr_.time().startTime().value()),
            obr_,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        1
    );*/


    const volScalarField& baseField1 = obr_.lookupObject<volScalarField>(rhoNName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoNName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField1
                )
            );

    const volScalarField& baseField2 = obr_.lookupObject<volScalarField>(rhoMName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoMName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField2
                )
            );

    const volVectorField& baseField3 = obr_.lookupObject<volVectorField>(momentumName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        momentumName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField3
                )
            );

    const volScalarField& baseField4 = obr_.lookupObject<volScalarField>(linearKEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        linearKEName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField4
                )
            );

    const volScalarField& baseField5 = obr_.lookupObject<volScalarField>(internalEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        internalEName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField5
                )
            );


    const volScalarField& baseField6 = obr_.lookupObject<volScalarField>(iDofName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        iDofName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField6
                )
            );


    const volVectorField& baseField7 = obr_.lookupObject<volVectorField>(fDName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        fDName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField7
                )
            );


    const volScalarField& rhoNMean = obr_.lookupObject<volScalarField>
    (
        rhoNName + "Mean"
    );

    const volScalarField& rhoMMean = obr_.lookupObject<volScalarField>
    (
        rhoMName + "Mean"
    );

    const volVectorField& momentumMean = obr_.lookupObject<volVectorField>
    (
        momentumName + "Mean"
    );

    const volScalarField& linearKEMean = obr_.lookupObject<volScalarField>
    (
        linearKEName + "Mean"
    );

    const volScalarField& internalEMean = obr_.lookupObject<volScalarField>
    (
        internalEName + "Mean"
    );

    const volScalarField& iDofMean = obr_.lookupObject<volScalarField>
    (
        iDofName + "Mean"
    );

    const volVectorField& fDMean = obr_.lookupObject<volVectorField>
    (
        fDName + "Mean"
    );

    if (min(mag(rhoNMean)).value() > VSMALL)
    {
        Info<< "Calculating dsmcFields." << endl;

        Info<< "    Calculating UMean field." << endl;
        volVectorField UMean
        (
            IOobject
            (
                "UMean",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            momentumMean/rhoMMean
        );

        Info<< "    Calculating translationalT field." << endl;
        volScalarField translationalT
        (
            IOobject
            (
                "translationalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),

            2.0/(3.0*physicoChemical::k.value()*rhoNMean)
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean))
        );

        Info<< "    Calculating internalT field." << endl;
        volScalarField internalT
        (
            IOobject
            (
                "internalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            (2.0/physicoChemical::k.value())*(internalEMean/iDofMean)
        );

        Info<< "    Calculating overallT field." << endl;
        volScalarField overallT
        (
            IOobject
            (
                "overallT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            2.0/(physicoChemical::k.value()*(3.0*rhoNMean + iDofMean))
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean) + internalEMean)
        );

        Info<< "    Calculating pressure field." << endl;
        volScalarField p
        (
            IOobject
            (
                "p",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            physicoChemical::k.value()*rhoNMean*translationalT
        );

        const fvMesh& mesh = fDMean.mesh();

        volScalarField::Boundary& pBf = p.boundaryFieldRef();

        forAll(mesh.boundaryMesh(), i)
        {
            const polyPatch& patch = mesh.boundaryMesh()[i];

            if (isA<wallPolyPatch>(patch))
            {
                pBf[i] =
                    fDMean.boundaryField()[i]
                  & (patch.faceAreas()/mag(patch.faceAreas()));
            }
        }

        Info<< "    mag(UMean) max/min : "
            << max(mag(UMean)).value() << " "
            << min(mag(UMean)).value() << endl;

        Info<< "    translationalT max/min : "
            << max(translationalT).value() << " "
            << min(translationalT).value() << endl;

        Info<< "    internalT max/min : "
            << max(internalT).value() << " "
            << min(internalT).value() << endl;

        Info<< "    overallT max/min : "
            << max(overallT).value() << " "
            << min(overallT).value() << endl;

        Info<< "    p max/min : "
            << max(p).value() << " "
            << min(p).value() << endl;

        UMean.write();

        translationalT.write();

        internalT.write();

        overallT.write();

        p.write();

        Info<< "dsmcFields written." << nl << endl;

        return true;
    }
    else
    {
        Info<< "Small value (" << min(mag(rhoNMean))
            << ") found in rhoNMean field. "
            << "Not calculating dsmcFields to avoid division by zero."
            << endl;

        return false;
    }
}


// ************************************************************************* //
dsmcFields.C (11,382 bytes)   

chrisk

2017-03-13 21:51

reporter  

dsmcFields-2.C (11,382 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "dsmcFields.H"
#include "volFields.H"
#include "dictionary.H"
#include "dsmcCloud.H"
#include "constants.H"
#include "addToRunTimeSelectionTable.H"

using namespace Foam::constant;

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{
namespace functionObjects
{
    defineTypeNameAndDebug(dsmcFields, 0);

    addToRunTimeSelectionTable
    (
        functionObject,
        dsmcFields,
        dictionary
    );
}
}


// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::dsmcFields
(
    const word& name,
    const Time& runTime,
    const dictionary& dict
)
:
    functionObject(name),
    obr_
    (
        runTime.lookupObject<objectRegistry>
        (
            dict.lookupOrDefault("region", polyMesh::defaultRegion)
        )
    )
{
    if (!isA<fvMesh>(obr_))
    {
        FatalErrorInFunction
            << "objectRegistry is not an fvMesh" << exit(FatalError);
    }

    read(dict);
}


// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::~dsmcFields()
{}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

bool Foam::functionObjects::dsmcFields::read(const dictionary& dict)
{
    return true;
}


bool Foam::functionObjects::dsmcFields::execute()
{
    return true;
}


bool Foam::functionObjects::dsmcFields::write()
{
    word rhoNName = "rhoN";
    word rhoMName = "rhoM";
    word momentumName = "momentum";
    word linearKEName = "linearKE";
    word internalEName = "internalE";
    word iDofName = "iDof";
    word fDName = "fD";



    //obr_.lookupObject<volScalarField>()
    /*volScalarField rhoNMean
    (
        IOobject
        (
            rhoNMeanName,
            obr_.time().timeName(obr_.time().startTime().value()),
            obr_,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        1
    );*/


    const volScalarField& baseField1 = obr_.lookupObject<volScalarField>(rhoNName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoNName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField1
                )
            );

    const volScalarField& baseField2 = obr_.lookupObject<volScalarField>(rhoMName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoMName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField2
                )
            );

    const volVectorField& baseField3 = obr_.lookupObject<volVectorField>(momentumName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        momentumName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField3
                )
            );

    const volScalarField& baseField4 = obr_.lookupObject<volScalarField>(linearKEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        linearKEName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField4
                )
            );

    const volScalarField& baseField5 = obr_.lookupObject<volScalarField>(internalEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        internalEName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField5
                )
            );


    const volScalarField& baseField6 = obr_.lookupObject<volScalarField>(iDofName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        iDofName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField6
                )
            );


    const volVectorField& baseField7 = obr_.lookupObject<volVectorField>(fDName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        fDName + "Mean",
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::MUST_READ,
                        IOobject::NO_WRITE
                    ),
                   1*baseField7
                )
            );


    const volScalarField& rhoNMean = obr_.lookupObject<volScalarField>
    (
        rhoNName + "Mean"
    );

    const volScalarField& rhoMMean = obr_.lookupObject<volScalarField>
    (
        rhoMName + "Mean"
    );

    const volVectorField& momentumMean = obr_.lookupObject<volVectorField>
    (
        momentumName + "Mean"
    );

    const volScalarField& linearKEMean = obr_.lookupObject<volScalarField>
    (
        linearKEName + "Mean"
    );

    const volScalarField& internalEMean = obr_.lookupObject<volScalarField>
    (
        internalEName + "Mean"
    );

    const volScalarField& iDofMean = obr_.lookupObject<volScalarField>
    (
        iDofName + "Mean"
    );

    const volVectorField& fDMean = obr_.lookupObject<volVectorField>
    (
        fDName + "Mean"
    );

    if (min(mag(rhoNMean)).value() > VSMALL)
    {
        Info<< "Calculating dsmcFields." << endl;

        Info<< "    Calculating UMean field." << endl;
        volVectorField UMean
        (
            IOobject
            (
                "UMean",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            momentumMean/rhoMMean
        );

        Info<< "    Calculating translationalT field." << endl;
        volScalarField translationalT
        (
            IOobject
            (
                "translationalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),

            2.0/(3.0*physicoChemical::k.value()*rhoNMean)
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean))
        );

        Info<< "    Calculating internalT field." << endl;
        volScalarField internalT
        (
            IOobject
            (
                "internalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            (2.0/physicoChemical::k.value())*(internalEMean/iDofMean)
        );

        Info<< "    Calculating overallT field." << endl;
        volScalarField overallT
        (
            IOobject
            (
                "overallT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            2.0/(physicoChemical::k.value()*(3.0*rhoNMean + iDofMean))
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean) + internalEMean)
        );

        Info<< "    Calculating pressure field." << endl;
        volScalarField p
        (
            IOobject
            (
                "p",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            physicoChemical::k.value()*rhoNMean*translationalT
        );

        const fvMesh& mesh = fDMean.mesh();

        volScalarField::Boundary& pBf = p.boundaryFieldRef();

        forAll(mesh.boundaryMesh(), i)
        {
            const polyPatch& patch = mesh.boundaryMesh()[i];

            if (isA<wallPolyPatch>(patch))
            {
                pBf[i] =
                    fDMean.boundaryField()[i]
                  & (patch.faceAreas()/mag(patch.faceAreas()));
            }
        }

        Info<< "    mag(UMean) max/min : "
            << max(mag(UMean)).value() << " "
            << min(mag(UMean)).value() << endl;

        Info<< "    translationalT max/min : "
            << max(translationalT).value() << " "
            << min(translationalT).value() << endl;

        Info<< "    internalT max/min : "
            << max(internalT).value() << " "
            << min(internalT).value() << endl;

        Info<< "    overallT max/min : "
            << max(overallT).value() << " "
            << min(overallT).value() << endl;

        Info<< "    p max/min : "
            << max(p).value() << " "
            << min(p).value() << endl;

        UMean.write();

        translationalT.write();

        internalT.write();

        overallT.write();

        p.write();

        Info<< "dsmcFields written." << nl << endl;

        return true;
    }
    else
    {
        Info<< "Small value (" << min(mag(rhoNMean))
            << ") found in rhoNMean field. "
            << "Not calculating dsmcFields to avoid division by zero."
            << endl;

        return false;
    }
}


// ************************************************************************* //
dsmcFields-2.C (11,382 bytes)   

chrisk

2017-03-13 21:57

reporter   ~0007927

* I use the motified dsmcField function after the simulation with:
dsmcFoam -postProcess

henry

2017-03-13 22:05

manager   ~0007928

When you have had time to complete a more consistent fix for the problem please submit it for inclusion on OpenFOAM.

chrisk

2017-03-14 12:55

reporter   ~0007929

Small fix to the workarond, MUST_READ prints a lot of warnings.

I can look into it more when I finish my master thesis, but for now I don't have much time on my hand.
dsmcFields-WorkAround.C (11,626 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

\*---------------------------------------------------------------------------*/

#include "dsmcFields.H"
#include "volFields.H"
#include "dictionary.H"
#include "dsmcCloud.H"
#include "constants.H"
#include "addToRunTimeSelectionTable.H"

using namespace Foam::constant;

// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{
namespace functionObjects
{
    defineTypeNameAndDebug(dsmcFields, 0);

    addToRunTimeSelectionTable
    (
        functionObject,
        dsmcFields,
        dictionary
    );
}
}


// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::dsmcFields
(
    const word& name,
    const Time& runTime,
    const dictionary& dict
)
:
    functionObject(name),
    obr_
    (
        runTime.lookupObject<objectRegistry>
        (
            dict.lookupOrDefault("region", polyMesh::defaultRegion)
        )
    )
{
    if (!isA<fvMesh>(obr_))
    {
        FatalErrorInFunction
            << "objectRegistry is not an fvMesh" << exit(FatalError);
    }

    read(dict);
}


// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::functionObjects::dsmcFields::~dsmcFields()
{}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

bool Foam::functionObjects::dsmcFields::read(const dictionary& dict)
{
    return true;
}


bool Foam::functionObjects::dsmcFields::execute()
{
    return true;
}


bool Foam::functionObjects::dsmcFields::write()
{
    word rhoNName = "rhoN";
    word rhoNMeanName = "rhoNMean";
    word rhoMName = "rhoM";
    word rhoMMeanName = "rhoMMean";
     word momentumName = "momentum";
    word momentumMeanName = "momentumMean";
    word linearKEName = "linearKE";
    word linearKEMeanName = "linearKEMean";
    word internalEName = "internalE";
    word internalEMeanName = "internalEMean";
    word iDofName = "iDof";
    word iDofMeanName = "iDofMean";
    word fDName = "fD";
    word fDMeanName = "fDMean";


    //obr_.lookupObject<volScalarField>()
    /*volScalarField rhoNMean
    (
        IOobject
        (
            rhoNMeanName,
            obr_.time().timeName(obr_.time().startTime().value()),
            obr_,
            IOobject::MUST_READ,
            IOobject::NO_WRITE
        ),
        1
    );*/
    const volScalarField& baseField1 = obr_.lookupObject<volScalarField>(rhoNName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoNMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField1
                )
            );

    const volScalarField& baseField2 = obr_.lookupObject<volScalarField>(rhoMName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        rhoMMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField2
                )
            );

    const volVectorField& baseField3 = obr_.lookupObject<volVectorField>(momentumName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        momentumMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField3
                )
            );

    const volScalarField& baseField4 = obr_.lookupObject<volScalarField>(linearKEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        linearKEMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField4
                )
            );

    const volScalarField& baseField5 = obr_.lookupObject<volScalarField>(internalEName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        internalEMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField5
                )
            );


    const volScalarField& baseField6 = obr_.lookupObject<volScalarField>(iDofName);
    obr_.store
            (
                new volScalarField
                (
                    IOobject
                    (
                        iDofMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField6
                )
            );


    const volVectorField& baseField7 = obr_.lookupObject<volVectorField>(fDName);
    obr_.store
            (
                new volVectorField
                (
                    IOobject
                    (
                        fDMeanName,
                        obr_.time().timeName(obr_.time().startTime().value()),
                        obr_,
                        IOobject::READ_IF_PRESENT,
                        IOobject::NO_WRITE
                    ),
                   1*baseField7
                )
            );


    const volScalarField& rhoNMean = obr_.lookupObject<volScalarField>
    (
        rhoNMeanName
    );

    const volScalarField& rhoMMean = obr_.lookupObject<volScalarField>
    (
        rhoMMeanName
    );

    const volVectorField& momentumMean = obr_.lookupObject<volVectorField>
    (
        momentumMeanName
    );

    const volScalarField& linearKEMean = obr_.lookupObject<volScalarField>
    (
        linearKEMeanName
    );

    const volScalarField& internalEMean = obr_.lookupObject<volScalarField>
    (
        internalEMeanName
    );

    const volScalarField& iDofMean = obr_.lookupObject<volScalarField>
    (
        iDofMeanName
    );

    const volVectorField& fDMean = obr_.lookupObject<volVectorField>
    (
        fDMeanName
    );

    if (min(mag(rhoNMean)).value() > VSMALL)
    {
        Info<< "Calculating dsmcFields." << endl;

        Info<< "    Calculating UMean field." << endl;
        volVectorField UMean
        (
            IOobject
            (
                "UMean",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            momentumMean/rhoMMean
        );

        Info<< "    Calculating translationalT field." << endl;
        volScalarField translationalT
        (
            IOobject
            (
                "translationalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),

            2.0/(3.0*physicoChemical::k.value()*rhoNMean)
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean))
        );

        Info<< "    Calculating internalT field." << endl;
        volScalarField internalT
        (
            IOobject
            (
                "internalT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            (2.0/physicoChemical::k.value())*(internalEMean/iDofMean)
        );

        Info<< "    Calculating overallT field." << endl;
        volScalarField overallT
        (
            IOobject
            (
                "overallT",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            2.0/(physicoChemical::k.value()*(3.0*rhoNMean + iDofMean))
           *(linearKEMean - 0.5*rhoMMean*(UMean & UMean) + internalEMean)
        );

        Info<< "    Calculating pressure field." << endl;
        volScalarField p
        (
            IOobject
            (
                "p",
                obr_.time().timeName(),
                obr_,
                IOobject::NO_READ
            ),
            physicoChemical::k.value()*rhoNMean*translationalT
        );

        const fvMesh& mesh = fDMean.mesh();

        volScalarField::Boundary& pBf = p.boundaryFieldRef();

        forAll(mesh.boundaryMesh(), i)
        {
            const polyPatch& patch = mesh.boundaryMesh()[i];

            if (isA<wallPolyPatch>(patch))
            {
                pBf[i] =
                    fDMean.boundaryField()[i]
                  & (patch.faceAreas()/mag(patch.faceAreas()));
            }
        }

        Info<< "    mag(UMean) max/min : "
            << max(mag(UMean)).value() << " "
            << min(mag(UMean)).value() << endl;

        Info<< "    translationalT max/min : "
            << max(translationalT).value() << " "
            << min(translationalT).value() << endl;

        Info<< "    internalT max/min : "
            << max(internalT).value() << " "
            << min(internalT).value() << endl;

        Info<< "    overallT max/min : "
            << max(overallT).value() << " "
            << min(overallT).value() << endl;

        Info<< "    p max/min : "
            << max(p).value() << " "
            << min(p).value() << endl;

        UMean.write();

        translationalT.write();

        internalT.write();

        overallT.write();

        p.write();

        Info<< "dsmcFields written." << nl << endl;

        return true;
    }
    else
    {
        Info<< "Small value (" << min(mag(rhoNMean))
            << ") found in rhoNMean field. "
            << "Not calculating dsmcFields to avoid division by zero."
            << endl;

        return false;
    }
}


// ************************************************************************* //
dsmcFields-WorkAround.C (11,626 bytes)   

henry

2017-03-14 15:35

manager   ~0007930

Rather than add a lot of mean field reading clutter to dsmcFields it is better that these are read by the postProcess utility in the same way as is done for the other post-processing functionObjects. This simply requires the creation of a postProcess configuration file in OpenFOAM-???/etc/caseDicts/postProcessing. I have added this file in OpenFOAM-dev and OpenFOAM-4.x so now

postProcess -time 0.001 -func dsmcFields

works on the wedge15Ma5 case.

chrisk

2017-03-16 11:54

reporter   ~0007932

Yeah that's a great solution, now you can at least use the functionObject in postProcess.

My workaround did not even work, it always read the same timestep.

Issue History

Date Modified Username Field Change
2017-03-13 19:07 chrisk New Issue
2017-03-13 19:39 henry Note Added: 0007924
2017-03-13 21:51 chrisk File Added: dsmcFields.C
2017-03-13 21:51 chrisk Note Added: 0007926
2017-03-13 21:51 chrisk File Added: dsmcFields-2.C
2017-03-13 21:57 chrisk Note Added: 0007927
2017-03-13 22:05 henry Note Added: 0007928
2017-03-14 12:55 chrisk File Added: dsmcFields-WorkAround.C
2017-03-14 12:55 chrisk Note Added: 0007929
2017-03-14 15:35 henry Note Added: 0007930
2017-03-16 11:54 chrisk Note Added: 0007932
2017-03-16 12:00 henry Assigned To => henry
2017-03-16 12:00 henry Status new => resolved
2017-03-16 12:00 henry Resolution open => fixed
2017-03-16 12:00 henry Fixed in Version => 4.x