View Issue Details

IDProjectCategoryView StatusLast Update
0002722OpenFOAMFeaturepublic2017-11-29 11:16
Reporteratulkjoy Assigned Tohenry  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformCentos OSCentos 7.0OS VersionCentos 7.0
Product Versiondev 
Summary0002722: Wall Heat Flux function object
Description/OpenFOAM-dev/src/functionObjects/field/wallHeatFlux/wallHeatFlux.C
Total heat flux should be cumulative of convective heat flux and radiative heat flux at boundary. At wall boundary lower temperature then next adjacent cell due to gradient or snGrad convectibe heat flux will be negative.

wallHeatFluxBf[patchi] = heatFluxBf[patchi]; // ln 78 Col 45

This results in substracation not addition

wallHeatFluxBf[patchi] += radHeatFluxBf[patchi]; // Ln 90 col 61
Steps To ReproducewallHeatFluxBf[patchi] = -heatFluxBf[patchi]; //sign has been changed to make it +ve due to which or better make it +ve always if it is negative to see the effect
TagsfunctionObject

Activities

atulkjoy

2017-10-12 11:29

reporter  

wallHeatFlux.C (9,839 bytes)   
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
     \\/     M anipulation  | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "wallHeatFlux.H"
#include "surfaceInterpolate.H"
#include "fvcSnGrad.H"
#include "wallPolyPatch.H"
#include "turbulentFluidThermoModel.H"
#include "addToRunTimeSelectionTable.H"

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

namespace Foam
{
namespace functionObjects
{
    defineTypeNameAndDebug(wallHeatFlux, 0);
    addToRunTimeSelectionTable(functionObject, wallHeatFlux, dictionary);
}
/////////////////////////////////  START  ////////////////////////////////////////////////////////////
/////////////////////////////////// END //////////////////////////////////////////////////////////
}


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

void Foam::functionObjects::wallHeatFlux::writeFileHeader(Ostream& os) const
{
    // Add headers to output data
    writeHeader(os, "Wall heat-flux");
    writeCommented(os, "Time");
    writeTabbed(os, "patch");
    writeTabbed(os, "min");
    writeTabbed(os, "max");
    writeTabbed(os, "integral");
    os  << endl;
}
///////////////////////////////// START ///////////////////////////////////////////////////////////////
///////////////////////////////// END ////////////////////////////////////////////////////////////////

void Foam::functionObjects::wallHeatFlux::calcHeatFlux
(
    const volScalarField& alpha,
    const volScalarField& he,
    volScalarField& wallHeatFlux
)
{
    surfaceScalarField heatFlux(fvc::interpolate(alpha)*fvc::snGrad(he));

    volScalarField::Boundary& wallHeatFluxBf = wallHeatFlux.boundaryFieldRef();

    const surfaceScalarField::Boundary& heatFluxBf = heatFlux.boundaryField();

    forAll(wallHeatFluxBf, patchi)
    {
        wallHeatFluxBf[patchi] = -heatFluxBf[patchi];                                                                  ///Edited by atul from +ve to -ve 
//       Info<<" wallHeatFlux "<<heatFluxBf[patchi]<<" for "<<mesh_.boundaryMesh()[patchi].name()<<endl;
    }

    if (foundObject<volScalarField>("Qr"))
    {
        Info<<" Yes Radiation Qr found ::"<<endl;

        const volScalarField& Qr = lookupObject<volScalarField>("Qr");

        const volScalarField::Boundary& radHeatFluxBf = Qr.boundaryField();

        forAll(wallHeatFluxBf, patchi)
        {
            wallHeatFluxBf[patchi] += radHeatFluxBf[patchi];
//            Info<<" Radiation HeatFlux "<<radHeatFluxBf[patchi]<<" for "<<mesh_.boundaryMesh()[patchi].name()<<endl;
        }
    }
}

/////////////////////////////////////////////   START   ////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// END ////////////////////////////////////////////////////////////////////////////////////

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

Foam::functionObjects::wallHeatFlux::wallHeatFlux
(
    const word& name,
    const Time& runTime,
    const dictionary& dict
)
:
    fvMeshFunctionObject(name, runTime, dict),
    writeFile(obr_, name, typeName, dict),
    patchSet_()
{
    volScalarField* wallHeatFluxPtr
    (
        new volScalarField
        (
            IOobject
            (
                type(),
                mesh_.time().timeName(),
                mesh_,
                IOobject::NO_READ,
                IOobject::NO_WRITE
            ),
            mesh_,
            dimensionedScalar("0", dimMass/pow3(dimTime), 0)
        )
    );

    mesh_.objectRegistry::store(wallHeatFluxPtr);

    read(dict);

    writeFileHeader(file());
}


//////////////////////////////// START ////////////////////////////////////////////////////
////////////////////////////////////// END ///////////////////////////////////////////////////


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

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

///////////////////////////////  START  /////////////////////////////////////////////

/////////////////////////////////   END ///////////////////////////////////////////

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

bool Foam::functionObjects::wallHeatFlux::read(const dictionary& dict)
{
    fvMeshFunctionObject::read(dict);
    writeFile::read(dict);

    const polyBoundaryMesh& pbm = mesh_.boundaryMesh();

    patchSet_ =
        mesh_.boundaryMesh().patchSet
        (
            wordReList(dict.lookupOrDefault("patches", wordReList()))
        );

    Info<< type() << " " << name() << ":" << nl;

    if (patchSet_.empty())
    {
        forAll(pbm, patchi)
        {
            if (isA<wallPolyPatch>(pbm[patchi]))
            {
                patchSet_.insert(patchi);
            }
        }

        Info<< "    processing all wall patches" << nl << endl;
    }
    else
    {
        Info<< "    processing wall patches: " << nl;
        labelHashSet filteredPatchSet;
        forAllConstIter(labelHashSet, patchSet_, iter)
        {
            label patchi = iter.key();
            if (isA<wallPolyPatch>(pbm[patchi]))
            {
                filteredPatchSet.insert(patchi);
                Info<< "        " << pbm[patchi].name() << endl;
            }
            else
            {
                WarningInFunction
                    << "Requested wall heat-flux on non-wall boundary "
                    << "type patch: " << pbm[patchi].name() << endl;
            }
        }

        Info<< endl;

        patchSet_ = filteredPatchSet;
    }

    return true;
}


////////////////////////////////////////// START  //////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// END ////////////////////////////////////////////////////////////////

bool Foam::functionObjects::wallHeatFlux::execute()
{
    volScalarField& wallHeatFlux = const_cast<volScalarField&>
    (
        lookupObject<volScalarField>(type())
    );

    if
    (
        foundObject<compressible::turbulenceModel>
        (
            turbulenceModel::propertiesName
        )
    )
    {
        const compressible::turbulenceModel& turbModel =
            lookupObject<compressible::turbulenceModel>
            (
                turbulenceModel::propertiesName
            );

        calcHeatFlux
        (
            turbModel.alphaEff()(),
            turbModel.transport().he(),
            wallHeatFlux
        );
    }
    else if (foundObject<fluidThermo>(fluidThermo::dictName))
    {
        const fluidThermo& thermo =
            lookupObject<fluidThermo>(fluidThermo::dictName);

        calcHeatFlux
        (
            thermo.alpha(),
            thermo.he(),
            wallHeatFlux
        );
    }
    else
    {
        FatalErrorInFunction
            << "Unable to find compressible turbulence model in the "
            << "database" << exit(FatalError);
    }

    return true;
}
////////////////////////////////////////  START  //////////////////////////////////////////////////////////////////////
/////////////////////////////////////////  END ////////////////////////////////////////////////////////////////////////

bool Foam::functionObjects::wallHeatFlux::write()
{
    const volScalarField& wallHeatFlux = lookupObject<volScalarField>(type());

    Log << type() << " " << name() << " write:" << nl
        << "    writing field " << wallHeatFlux.name() << endl;

    wallHeatFlux.write();

    const fvPatchList& patches = mesh_.boundary();

    const surfaceScalarField::Boundary& magSf =
        mesh_.magSf().boundaryField();

    forAllConstIter(labelHashSet, patchSet_, iter)
    {
        label patchi = iter.key();
        const fvPatch& pp = patches[patchi];

        const scalarField& hfp = wallHeatFlux.boundaryField()[patchi];

        const scalar minHfp = gMin(hfp);
        const scalar maxHfp = gMax(hfp);
        const scalar integralHfp = gSum(magSf[patchi]*hfp);

        if (Pstream::master())
        {
            writeTime(file());

            file()
                << token::TAB << pp.name()
                << token::TAB << minHfp
                << token::TAB << maxHfp
                << token::TAB << integralHfp
                << endl;
        }

        Log << "    min/max(" << pp.name() << ") = "
            << minHfp << ", " << maxHfp << ", " << integralHfp << endl;
    }

    return true;
}

/////////////////////////////////////////////// START ///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

// ************************************************************************* //
wallHeatFlux.C (9,839 bytes)   

henry

2017-10-12 15:45

manager   ~0008863

Can you provide a simple case or is there a tutorial case which demonstrates the need for this change?

StephanG

2017-10-13 09:21

reporter   ~0008864

I don't quite understand what you are getting at. The heat flux can be negative. This is not an error. The sign tells you if the heat is flowing into the domain or if it is leaving it. For CHT one side is always negative and the other positive.

wyldckat

2017-10-15 10:22

updater   ~0008874

@atulkjoy: Please provide more details for this bug report, as requested on the rules page: https://bugs.openfoam.org/rules.php

I know that you asked about this on this thread: https://www.cfd-online.com/Forums/openfoam-post-processing/192658-wall-heat-flux-utulity.html

But in this report here, please also provide the evidences of what you initially discovered and how you reached the conclusion regarding what should be the correct sign. I know that you provided the plots and results on that thread, but it's not accessible to the public unless people log in there, so please post the images here as well.

----

@Henry and @StephanG: Just in case atulkjoy doesn't answer in the meantime, here is a partial quote of what I wrote regarding this topic on that thread:

   In OpenFOAM 4.x and older, the calculation is done as:

       convective_term - radiative_term

   While in OpenFOAM 5.x and newer, the calculation is done as:

       convective_term + radiative_term

   I haven't managed to figure out which one is correct, because I haven't managed to figure out what is the sign convention for Qr and for the convective heat flux.
   At a first glance, it seemed like Qr was always positive ("q = Boltzman * T^4 * Area"), which doesn't make much sense in this context, since it should be a subtraction of the two or more temperature[/radiation] sources, imposed on the wall.

wyldckat

2017-11-28 23:06

updater   ~0009093

I have some more details on this topic, but I haven't had the time to sort through them yet and confirm what is correct. But here goes the information I've gathered so far:

 1. The change in the sign for this calculation has already occurred in the past. Start reading from the following Juho's comment here: https://bugs.openfoam.org/view.php?id=1856#c5713 - in report #1856.

    - In a nutshell, see the bug fix in this commit: https://github.com/OpenFOAM/OpenFOAM-dev/commit/5749c95ed68e40c11ea586549fb667553d218f1f


 2. A recent optimization that was implemented into this 'wallHeatFlux' function object - see Issue #2725: https://bugs.openfoam.org/view.php?id=2725 - has lead to not allowing the calculation of said wall heat flux on coupled patches, which is the test that was indications by Juho in the aforementioned issue #1856, and I quote:

> Steps to reproduce:
> 1. Run the chtMultiRegionSimpleFoam multiRegionHeaterRadiation tutorial to convergence
> 2. Check the heat balance between the regions with the wallHeatFlux utility


Therefore, once it's possible to run the function object with the tutorial case "chtMultiRegionSimpleFoam/multiRegionHeaterRadiation", it's possible to assess if the radiation term is meant to be added or subtracted.

henry

2017-11-28 23:38

manager   ~0009095

@wyldckat It is not clear to me how the changes for #2725 affect this, could you clarify?

wyldckat

2017-11-29 08:54

updater   ~0009098

@Henry: I don't have an updated build of OpenFOAM-dev at hand right now, but when the tutorial case "chtMultiRegionSimpleFoam/multiRegionHeaterRadiation" is run with the function object 'wallHeatFlux', I get an error message about 'snGrad' not being implemented for coupled patches.

Therefore, I was not able to do the same test that Juho did for the last fix in #1856, i.e. to verify which sign should be used when accounting the radiation term into the 'wallHeatFlux'.

My apologies for not opening another report for the 'snGrad' issue sooner, but I was planning on opening it only when I had all of the pieces and patch... but a couple of weeks passed by since then, so it seemed best to at least provide what I already knew about this current report and associated information.

henry

2017-11-29 09:09

manager   ~0009100

@wyldckat: Thanks for the clarification, I will investigate.

tniemi

2017-11-29 10:37

reporter   ~0009101

Just to comment, the sign convention of qr is such that it is the net amount of radiation absorbed by the wall -> positive qr indicates that energy is flowing into the wall and out of the domain. This means that qr behaves opposite to wallHeatFluxBf which is negative if the flux is out of the domain. This was the reason why the sign was changed previously. Easiest fix would be changing += to -= in line 91 in wallHeatFlux.C.

henry

2017-11-29 10:42

manager   ~0009102

@wyldckat: I am not able to reproduce the problem, I have added

functions
{
    #includeFunc wallHeatFlux(region=heater)
}

to the controlDict and the case runs fine and generates heat flux data for the patch. Could you provide more details for how to reproduce the problem?

wyldckat

2017-11-29 10:58

updater   ~0009103

@Henry: If it's working fine for you, then please move onward. I will open a new bug report if I'm able to reproduce the issue I had with snGrad+coupled boundaries.

In the meantime, tniemi's answer seems to clarify the need for the original bug report.

henry

2017-11-29 11:16

manager   ~0009104

Thanks Timo

Resolved in OpenFOAM-5.x by commit a268af97208e55ed1d4f1ebff4d95a9faf64ef9c

Resolved in OpenFOAM-dev by commit 396259f105b2542912c35b29c4d8b96df5d3a77c

Issue History

Date Modified Username Field Change
2017-10-12 11:29 atulkjoy New Issue
2017-10-12 11:29 atulkjoy File Added: wallHeatFlux.C
2017-10-12 11:29 atulkjoy Tag Attached: functionObject
2017-10-12 15:45 henry Note Added: 0008863
2017-10-13 09:21 StephanG Note Added: 0008864
2017-10-15 10:22 wyldckat Note Added: 0008874
2017-11-28 23:06 wyldckat Note Added: 0009093
2017-11-28 23:38 henry Note Added: 0009095
2017-11-29 08:54 wyldckat Note Added: 0009098
2017-11-29 09:09 henry Note Added: 0009100
2017-11-29 10:37 tniemi Note Added: 0009101
2017-11-29 10:42 henry Note Added: 0009102
2017-11-29 10:58 wyldckat Note Added: 0009103
2017-11-29 11:16 henry Assigned To => henry
2017-11-29 11:16 henry Status new => resolved
2017-11-29 11:16 henry Resolution open => fixed
2017-11-29 11:16 henry Fixed in Version => 5.x
2017-11-29 11:16 henry Note Added: 0009104